237 lines
9.1 KiB
Python
237 lines
9.1 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2014 Google LLC. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""Command for updating HTTPS health checks."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
from googlecloudsdk.api_lib.compute import base_classes
|
|
from googlecloudsdk.calliope import arg_parsers
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.command_lib.compute.health_checks import exceptions
|
|
from googlecloudsdk.command_lib.compute.https_health_checks import flags
|
|
from googlecloudsdk.core import log
|
|
|
|
THRESHOLD_UPPER_BOUND = 10
|
|
THRESHOLD_LOWER_BOUND = 1
|
|
TIMEOUT_UPPER_BOUND_SEC = 300
|
|
TIMEOUT_LOWER_BOUND_SEC = 1
|
|
CHECK_INTERVAL_UPPER_BOUND_SEC = 300
|
|
CHECK_INTERVAL_LOWER_BOUND_SEC = 1
|
|
|
|
|
|
class Update(base.UpdateCommand):
|
|
"""Update a legacy HTTPS health check.
|
|
|
|
*{command}* is used to update an existing legacy HTTPS health check. Only
|
|
arguments passed in will be updated on the health check. Other
|
|
attributes will remain unaffected.
|
|
"""
|
|
|
|
HTTPS_HEALTH_CHECKS_ARG = None
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
cls.HTTPS_HEALTH_CHECKS_ARG = flags.HttpsHealthCheckArgument()
|
|
cls.HTTPS_HEALTH_CHECKS_ARG.AddArgument(parser, operation_type='update')
|
|
|
|
parser.add_argument(
|
|
'--host',
|
|
help="""\
|
|
The value of the host header used in this HTTPS health check request.
|
|
By default, this is empty and Compute Engine automatically sets
|
|
the host header in health requests to the same external IP address as
|
|
the forwarding rule associated with the target pool. Setting this to
|
|
an empty string will clear any existing host value.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--port',
|
|
type=int,
|
|
help="""\
|
|
The TCP port number that this health check monitors.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--request-path',
|
|
help="""\
|
|
The request path that this health check monitors. For example,
|
|
``/healthcheck''.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--check-interval',
|
|
type=arg_parsers.Duration(),
|
|
help="""\
|
|
How often to perform a health check for an instance. For example,
|
|
specifying ``10s'' will run the check every 10 seconds.
|
|
See $ gcloud topic datetimes for information on duration formats.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--timeout',
|
|
type=arg_parsers.Duration(),
|
|
help="""\
|
|
If Compute Engine doesn't receive an HTTPS 200 response from the
|
|
instance by the time specified by the value of this flag, the health
|
|
check request is considered a failure. For example, specifying ``10s''
|
|
will cause the check to wait for 10 seconds before considering the
|
|
request a failure.
|
|
See $ gcloud topic datetimes for information on duration formats.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--unhealthy-threshold',
|
|
type=int,
|
|
help="""\
|
|
The number of consecutive health check failures before a healthy
|
|
instance is marked as unhealthy.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--healthy-threshold',
|
|
type=int,
|
|
help="""\
|
|
The number of consecutive successful health checks before an
|
|
unhealthy instance is marked as healthy.
|
|
""")
|
|
|
|
parser.add_argument(
|
|
'--description',
|
|
help=('A textual description for the HTTPS health check. Pass in an '
|
|
'empty string to unset.'))
|
|
|
|
def GetGetRequest(self, client, https_health_check_ref):
|
|
"""Returns a request for fetching the existing HTTPS health check."""
|
|
return (client.apitools_client.httpsHealthChecks,
|
|
'Get',
|
|
client.messages.ComputeHttpsHealthChecksGetRequest(
|
|
httpsHealthCheck=https_health_check_ref.Name(),
|
|
project=https_health_check_ref.project))
|
|
|
|
def GetSetRequest(self, client, https_health_check_ref, replacement):
|
|
"""Returns a request for updated the HTTPS health check."""
|
|
return (client.apitools_client.httpsHealthChecks,
|
|
'Update',
|
|
client.messages.ComputeHttpsHealthChecksUpdateRequest(
|
|
httpsHealthCheck=https_health_check_ref.Name(),
|
|
httpsHealthCheckResource=replacement,
|
|
project=https_health_check_ref.project))
|
|
|
|
def Modify(self, client, args, existing_check):
|
|
"""Returns a modified HttpsHealthCheck message."""
|
|
# Description and Host are the only attributes that can be cleared by
|
|
# passing in an empty string (but we don't want to set it to an empty
|
|
# string).
|
|
if args.description:
|
|
description = args.description
|
|
elif args.description is None:
|
|
description = existing_check.description
|
|
else:
|
|
description = None
|
|
|
|
if args.host:
|
|
host = args.host
|
|
elif args.host is None:
|
|
host = existing_check.host
|
|
else:
|
|
host = None
|
|
|
|
new_health_check = client.messages.HttpsHealthCheck(
|
|
name=existing_check.name,
|
|
host=host,
|
|
port=args.port or existing_check.port,
|
|
description=description,
|
|
requestPath=args.request_path or existing_check.requestPath,
|
|
checkIntervalSec=(args.check_interval or
|
|
existing_check.checkIntervalSec),
|
|
timeoutSec=args.timeout or existing_check.timeoutSec,
|
|
healthyThreshold=(args.healthy_threshold or
|
|
existing_check.healthyThreshold),
|
|
unhealthyThreshold=(args.unhealthy_threshold or
|
|
existing_check.unhealthyThreshold),
|
|
)
|
|
return new_health_check
|
|
|
|
def Run(self, args):
|
|
"""Issues requests necessary to update the HTTPS Health Checks."""
|
|
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
|
|
client = holder.client
|
|
|
|
if (args.check_interval is not None
|
|
and (args.check_interval < CHECK_INTERVAL_LOWER_BOUND_SEC
|
|
or args.check_interval > CHECK_INTERVAL_UPPER_BOUND_SEC)):
|
|
raise exceptions.ArgumentError(
|
|
'[--check-interval] must not be less than {0} second or greater '
|
|
'than {1} seconds; received [{2}] seconds.'.format(
|
|
CHECK_INTERVAL_LOWER_BOUND_SEC, CHECK_INTERVAL_UPPER_BOUND_SEC,
|
|
args.check_interval))
|
|
|
|
if (args.timeout is not None
|
|
and (args.timeout < TIMEOUT_LOWER_BOUND_SEC
|
|
or args.timeout > TIMEOUT_UPPER_BOUND_SEC)):
|
|
raise exceptions.ArgumentError(
|
|
'[--timeout] must not be less than {0} second or greater than {1} '
|
|
'seconds; received: [{2}] seconds.'.format(
|
|
TIMEOUT_LOWER_BOUND_SEC, TIMEOUT_UPPER_BOUND_SEC, args.timeout))
|
|
|
|
if (args.healthy_threshold is not None
|
|
and (args.healthy_threshold < THRESHOLD_LOWER_BOUND
|
|
or args.healthy_threshold > THRESHOLD_UPPER_BOUND)):
|
|
raise exceptions.ArgumentError(
|
|
'[--healthy-threshold] must be an integer between {0} and {1}, '
|
|
'inclusive; received: [{2}].'.format(THRESHOLD_LOWER_BOUND,
|
|
THRESHOLD_UPPER_BOUND,
|
|
args.healthy_threshold))
|
|
|
|
if (args.unhealthy_threshold is not None
|
|
and (args.unhealthy_threshold < THRESHOLD_LOWER_BOUND
|
|
or args.unhealthy_threshold > THRESHOLD_UPPER_BOUND)):
|
|
raise exceptions.ArgumentError(
|
|
'[--unhealthy-threshold] must be an integer between {0} and {1}, '
|
|
'inclusive; received [{2}].'.format(THRESHOLD_LOWER_BOUND,
|
|
THRESHOLD_UPPER_BOUND,
|
|
args.unhealthy_threshold))
|
|
|
|
args_unset = not (args.port
|
|
or args.request_path
|
|
or args.check_interval
|
|
or args.timeout
|
|
or args.healthy_threshold
|
|
or args.unhealthy_threshold)
|
|
if args.description is None and args.host is None and args_unset:
|
|
raise exceptions.ArgumentError('At least one property must be modified.')
|
|
|
|
https_health_check_ref = self.HTTPS_HEALTH_CHECKS_ARG.ResolveAsResource(
|
|
args, holder.resources)
|
|
get_request = self.GetGetRequest(client, https_health_check_ref)
|
|
|
|
objects = client.MakeRequests([get_request])
|
|
|
|
new_object = self.Modify(client, args, objects[0])
|
|
|
|
# If existing object is equal to the proposed object or if
|
|
# Modify() returns None, then there is no work to be done, so we
|
|
# print the resource and return.
|
|
if objects[0] == new_object:
|
|
log.status.Print(
|
|
'No change requested; skipping update for [{0}].'.format(
|
|
objects[0].name))
|
|
return objects
|
|
|
|
return client.MakeRequests(
|
|
[self.GetSetRequest(client, https_health_check_ref, new_object)])
|