1# -*- coding: utf-8 -*- # 2# Copyright 2015 Google LLC. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15"""Command for updating health checks.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import unicode_literals 20 21from googlecloudsdk.api_lib.compute import base_classes 22from googlecloudsdk.api_lib.compute import health_checks_utils 23from googlecloudsdk.calliope import base 24from googlecloudsdk.calliope import exceptions 25from googlecloudsdk.command_lib.compute import scope as compute_scope 26from googlecloudsdk.command_lib.compute.health_checks import flags 27from googlecloudsdk.core import exceptions as core_exceptions 28from googlecloudsdk.core import log 29 30 31def _DetailedHelp(): 32 return { 33 'brief': 34 'Update a HTTP2 health check.', 35 'DESCRIPTION': 36 """\ 37 *{command}* is used to update an existing HTTP2 health check. Only 38 arguments passed in will be updated on the health check. Other 39 attributes will remain unaffected. 40 """, 41 'EXAMPLES': 42 """\ 43 To update health check interval to 10s, run: 44 45 $ {command} my-health-check-name --check-interval=10s 46 """, 47 } 48 49 50def _Args(parser, include_l7_internal_load_balancing, include_log_config): 51 health_check_arg = flags.HealthCheckArgument( 52 'HTTP2', 53 include_l7_internal_load_balancing=include_l7_internal_load_balancing) 54 health_check_arg.AddArgument(parser, operation_type='update') 55 health_checks_utils.AddHttpRelatedUpdateArgs(parser) 56 health_checks_utils.AddHttpRelatedResponseArg(parser) 57 health_checks_utils.AddProtocolAgnosticUpdateArgs(parser, 'HTTP2') 58 if include_log_config: 59 health_checks_utils.AddHealthCheckLoggingRelatedArgs(parser) 60 61 62def _GetGetRequest(client, health_check_ref): 63 """Returns a request for fetching the existing health check.""" 64 return (client.apitools_client.healthChecks, 'Get', 65 client.messages.ComputeHealthChecksGetRequest( 66 healthCheck=health_check_ref.Name(), 67 project=health_check_ref.project)) 68 69 70def _GetSetRequest(client, health_check_ref, replacement): 71 """Returns a request for updating the health check.""" 72 return (client.apitools_client.healthChecks, 'Update', 73 client.messages.ComputeHealthChecksUpdateRequest( 74 healthCheck=health_check_ref.Name(), 75 healthCheckResource=replacement, 76 project=health_check_ref.project)) 77 78 79def _GetRegionalGetRequest(client, health_check_ref): 80 """Returns a request for fetching the existing health check.""" 81 return (client.apitools_client.regionHealthChecks, 'Get', 82 client.messages.ComputeRegionHealthChecksGetRequest( 83 healthCheck=health_check_ref.Name(), 84 project=health_check_ref.project, 85 region=health_check_ref.region)) 86 87 88def _GetRegionalSetRequest(client, health_check_ref, replacement): 89 """Returns a request for updating the health check.""" 90 return (client.apitools_client.regionHealthChecks, 'Update', 91 client.messages.ComputeRegionHealthChecksUpdateRequest( 92 healthCheck=health_check_ref.Name(), 93 healthCheckResource=replacement, 94 project=health_check_ref.project, 95 region=health_check_ref.region)) 96 97 98def _Modify(client, args, existing_check, include_log_config): 99 """Returns a modified HealthCheck message.""" 100 # We do not support using 'update http2' with a health check of a 101 # different protocol. 102 if (existing_check.type != 103 client.messages.HealthCheck.TypeValueValuesEnum.HTTP2): 104 raise core_exceptions.Error( 105 'update http2 subcommand applied to health check with protocol ' + 106 existing_check.type.name) 107 108 # Description, PortName, Response and Host are the only attributes that can 109 # be cleared by passing in an empty string (but we don't want to set it to 110 # an empty string). 111 if args.description: 112 description = args.description 113 elif args.description is None: 114 description = existing_check.description 115 else: 116 description = None 117 118 if args.host: 119 host = args.host 120 elif args.host is None: 121 host = existing_check.http2HealthCheck.host 122 else: 123 host = None 124 125 if args.response: 126 response = args.response 127 elif args.response is None: 128 response = existing_check.http2HealthCheck.response 129 else: 130 response = None 131 132 port, port_name, port_specification = health_checks_utils.\ 133 HandlePortRelatedFlagsForUpdate(args, existing_check.http2HealthCheck) 134 135 proxy_header = existing_check.http2HealthCheck.proxyHeader 136 if args.proxy_header is not None: 137 proxy_header = ( 138 client.messages.HTTP2HealthCheck.ProxyHeaderValueValuesEnum( 139 args.proxy_header)) 140 new_health_check = client.messages.HealthCheck( 141 name=existing_check.name, 142 description=description, 143 type=client.messages.HealthCheck.TypeValueValuesEnum.HTTP2, 144 http2HealthCheck=client.messages.HTTP2HealthCheck( 145 host=host, 146 port=port, 147 portName=port_name, 148 portSpecification=port_specification, 149 requestPath=(args.request_path or 150 existing_check.http2HealthCheck.requestPath), 151 proxyHeader=proxy_header, 152 response=response), 153 checkIntervalSec=(args.check_interval or existing_check.checkIntervalSec), 154 timeoutSec=args.timeout or existing_check.timeoutSec, 155 healthyThreshold=(args.healthy_threshold or 156 existing_check.healthyThreshold), 157 unhealthyThreshold=(args.unhealthy_threshold or 158 existing_check.unhealthyThreshold), 159 ) 160 161 if include_log_config: 162 new_health_check.logConfig = health_checks_utils.ModifyLogConfig( 163 client, args, existing_check.logConfig) 164 return new_health_check 165 166 167def _ValidateArgs(args, include_log_config): 168 """Validates given args and raises exception if any args are invalid.""" 169 health_checks_utils.CheckProtocolAgnosticArgs(args) 170 171 args_unset = not (args.port or args.request_path or args.check_interval or 172 args.timeout or args.healthy_threshold or 173 args.unhealthy_threshold or args.proxy_header or 174 args.use_serving_port) 175 176 if include_log_config: 177 args_unset = (args.enable_logging is None and args_unset) 178 179 if (args.description is None and args.host is None and 180 args.response is None and args.port_name is None and args_unset): 181 raise exceptions.ToolException('At least one property must be modified.') 182 183 184def _Run(args, holder, include_l7_internal_load_balancing, include_log_config): 185 """Issues requests necessary to update the HTTP2 Health Checks.""" 186 client = holder.client 187 188 _ValidateArgs(args, include_log_config) 189 190 health_check_arg = flags.HealthCheckArgument( 191 'HTTP2', 192 include_l7_internal_load_balancing=include_l7_internal_load_balancing) 193 health_check_ref = health_check_arg.ResolveAsResource( 194 args, holder.resources, default_scope=compute_scope.ScopeEnum.GLOBAL) 195 if health_checks_utils.IsRegionalHealthCheckRef(health_check_ref): 196 get_request = _GetRegionalGetRequest(client, health_check_ref) 197 else: 198 get_request = _GetGetRequest(client, health_check_ref) 199 200 objects = client.MakeRequests([get_request]) 201 202 new_object = _Modify(client, args, objects[0], include_log_config) 203 204 # If existing object is equal to the proposed object or if 205 # _Modify() returns None, then there is no work to be done, so we 206 # print the resource and return. 207 if objects[0] == new_object: 208 log.status.Print('No change requested; skipping update for [{0}].'.format( 209 objects[0].name)) 210 return objects 211 212 if health_checks_utils.IsRegionalHealthCheckRef(health_check_ref): 213 set_request = _GetRegionalSetRequest(client, health_check_ref, new_object) 214 else: 215 set_request = _GetSetRequest(client, health_check_ref, new_object) 216 217 return client.MakeRequests([set_request]) 218 219 220@base.ReleaseTracks(base.ReleaseTrack.GA) 221class Update(base.UpdateCommand): 222 """Update a HTTP2 health check.""" 223 224 _include_l7_internal_load_balancing = True 225 _include_log_config = True 226 detailed_help = _DetailedHelp() 227 228 @classmethod 229 def Args(cls, parser): 230 _Args(parser, cls._include_l7_internal_load_balancing, 231 cls._include_log_config) 232 233 def Run(self, args): 234 holder = base_classes.ComputeApiHolder(self.ReleaseTrack()) 235 return _Run(args, holder, self._include_l7_internal_load_balancing, 236 self._include_log_config) 237 238 239@base.ReleaseTracks(base.ReleaseTrack.BETA) 240class UpdateBeta(Update): 241 242 pass 243 244 245@base.ReleaseTracks(base.ReleaseTrack.ALPHA) 246class UpdateAlpha(UpdateBeta): 247 248 pass 249