File: //snap/google-cloud-cli/current/lib/surface/compute/backend_buckets/update.py
# -*- coding: utf-8 -*- #
# Copyright 2015 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.
"""Commands for updating backend buckets."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import encoding
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute import cdn_flags_utils as cdn_flags
from googlecloudsdk.command_lib.compute import exceptions
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute import scope as compute_scope
from googlecloudsdk.command_lib.compute import signed_url_flags
from googlecloudsdk.command_lib.compute.backend_buckets import backend_buckets_utils
from googlecloudsdk.command_lib.compute.backend_buckets import flags as backend_buckets_flags
from googlecloudsdk.command_lib.compute.security_policies import (
flags as security_policy_flags)
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.UniverseCompatible
class Update(base.UpdateCommand):
"""Update a backend bucket.
*{command}* is used to update backend buckets.
"""
BACKEND_BUCKET_ARG = None
EDGE_SECURITY_POLICY_ARG = None
support_regional_global_flags = False
@classmethod
def Args(cls, parser):
"""Set up arguments for this command."""
backend_buckets_flags.AddUpdatableArgs(
cls, parser, 'update', cls.support_regional_global_flags
)
backend_buckets_flags.GCS_BUCKET_ARG.AddArgument(parser)
signed_url_flags.AddSignedUrlCacheMaxAge(
parser, required=False, unspecified_help='')
cdn_flags.AddCdnPolicyArgs(parser, 'backend bucket', update_command=True)
cls.EDGE_SECURITY_POLICY_ARG = (
security_policy_flags.EdgeSecurityPolicyArgumentForTargetResource(
resource='backend bucket'))
cls.EDGE_SECURITY_POLICY_ARG.AddArgument(parser)
backend_buckets_flags.AddCacheKeyExtendedCachingArgs(parser)
backend_buckets_flags.AddCompressionMode(parser)
def AnyArgsSpecified(self, args):
"""Returns true if any args for updating backend bucket were specified."""
return (args.IsSpecified('description') or
args.IsSpecified('gcs_bucket_name') or
args.IsSpecified('enable_cdn') or
args.IsSpecified('edge_security_policy') or
args.IsSpecified('cache_key_include_http_header') or
args.IsSpecified('cache_key_query_string_whitelist') or
args.IsSpecified('compression_mode'))
def AnyFlexibleCacheArgsSpecified(self, args):
"""Returns true if any Flexible Cache args for updating backend bucket were specified."""
return any(
(args.IsSpecified('cache_mode'), args.IsSpecified('client_ttl'),
args.IsSpecified('no_client_ttl'), args.IsSpecified('default_ttl'),
args.IsSpecified('no_default_ttl'), args.IsSpecified('max_ttl'),
args.IsSpecified('no_max_ttl'),
args.IsSpecified('custom_response_header'),
args.IsSpecified('no_custom_response_headers'),
args.IsSpecified('negative_caching'),
args.IsSpecified('negative_caching_policy'),
args.IsSpecified('no_negative_caching_policies'),
args.IsSpecified('serve_while_stale'),
args.IsSpecified('no_serve_while_stale'),
args.IsSpecified('bypass_cache_on_request_headers'),
args.IsSpecified('no_bypass_cache_on_request_headers')))
def GetGetRequest(self, client, backend_bucket_ref):
"""Returns a request to retrieve the backend bucket."""
if backend_bucket_ref.Collection() == 'compute.regionBackendBuckets':
return (
client.apitools_client.regionBackendBuckets,
'Get',
client.messages.ComputeRegionBackendBucketsGetRequest(
project=backend_bucket_ref.project,
region=backend_bucket_ref.region,
backendBucket=backend_bucket_ref.Name(),
),
)
return (client.apitools_client.backendBuckets, 'Get',
client.messages.ComputeBackendBucketsGetRequest(
project=backend_bucket_ref.project,
backendBucket=backend_bucket_ref.Name()))
def GetSetRequest(self, client, backend_bucket_ref, replacement):
"""Returns a request to update the backend bucket."""
if backend_bucket_ref.Collection() == 'compute.regionBackendBuckets':
return (
client.apitools_client.regionBackendBuckets,
'Patch',
client.messages.ComputeRegionBackendBucketsPatchRequest(
project=backend_bucket_ref.project,
region=backend_bucket_ref.region,
backendBucket=backend_bucket_ref.Name(),
backendBucketResource=replacement,
),
)
return (client.apitools_client.backendBuckets, 'Patch',
client.messages.ComputeBackendBucketsPatchRequest(
project=backend_bucket_ref.project,
backendBucket=backend_bucket_ref.Name(),
backendBucketResource=replacement))
def GetSetEdgeSecurityPolicyRequest(self, client, backend_bucket_ref,
security_policy_ref):
"""Returns a request to set the edge policy for the backend bucket."""
if backend_bucket_ref.Collection() == 'compute.regionBackendBuckets':
raise exceptions.ArgumentError(
'Regional backend buckets do not support edge security policies.')
return (client.apitools_client.backendBuckets, 'SetEdgeSecurityPolicy',
client.messages.ComputeBackendBucketsSetEdgeSecurityPolicyRequest(
project=backend_bucket_ref.project,
backendBucket=backend_bucket_ref.Name(),
securityPolicyReference=client.messages.SecurityPolicyReference(
securityPolicy=security_policy_ref)))
def Modify(self, args, existing):
"""Modifies and returns the updated backend bucket."""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
replacement = encoding.CopyProtoMessage(existing)
cleared_fields = []
if args.IsSpecified('description'):
replacement.description = args.description
if args.gcs_bucket_name:
replacement.bucketName = args.gcs_bucket_name
if args.enable_cdn is not None:
replacement.enableCdn = args.enable_cdn
backend_buckets_utils.ApplyCdnPolicyArgs(
client,
args,
replacement,
is_update=True,
cleared_fields=cleared_fields)
if args.custom_response_header is not None:
replacement.customResponseHeaders = args.custom_response_header
if args.no_custom_response_headers:
replacement.customResponseHeaders = []
if not replacement.customResponseHeaders:
cleared_fields.append('customResponseHeaders')
if (replacement.cdnPolicy is not None and
replacement.cdnPolicy.cacheMode and args.enable_cdn is not False): # pylint: disable=g-bool-id-comparison
replacement.enableCdn = True
if args.compression_mode is not None:
replacement.compressionMode = (
client.messages.BackendBucket.CompressionModeValueValuesEnum(
args.compression_mode))
if not replacement.description:
cleared_fields.append('description')
return replacement, cleared_fields
def MakeRequests(self, args):
"""Makes the requests for updating the backend bucket."""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
if self.support_regional_global_flags:
backend_bucket_ref = backend_buckets_flags.GLOBAL_REGIONAL_BACKEND_BUCKET_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client),
default_scope=compute_scope.ScopeEnum.GLOBAL,
)
else:
backend_bucket_ref = self.BACKEND_BUCKET_ARG.ResolveAsResource(
args, holder.resources
)
get_request = self.GetGetRequest(client, backend_bucket_ref)
objects = client.MakeRequests([get_request])
new_object, cleared_fields = self.Modify(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:
# Only skip update if edge_security_policy is not set.
if getattr(args, 'edge_security_policy', None) is None:
log.status.Print(
'No change requested; skipping update for [{0}].'.format(
objects[0].name))
return objects
backend_bucket_result = []
else:
with client.apitools_client.IncludeFields(cleared_fields):
backend_bucket_result = client.MakeRequests(
[self.GetSetRequest(client, backend_bucket_ref, new_object)])
# Empty string is a valid value.
if getattr(args, 'edge_security_policy', None) is not None:
if backend_bucket_ref.Collection() == 'compute.regionBackendBuckets':
raise exceptions.ArgumentError(
'argument --edge-security-policy: Regional backend buckets do not'
' support edge security policies.'
)
if getattr(args, 'edge_security_policy', None):
security_policy_ref = self.EDGE_SECURITY_POLICY_ARG.ResolveAsResource(
args, holder.resources).SelfLink()
# If security policy is an empty string we should clear the current policy
else:
security_policy_ref = None
edge_security_policy_request = self.GetSetEdgeSecurityPolicyRequest(
client, backend_bucket_ref, security_policy_ref)
edge_security_policy_result = client.MakeRequests(
[edge_security_policy_request])
else:
edge_security_policy_result = []
return backend_bucket_result + edge_security_policy_result
def Run(self, args):
"""Issues the request necessary for updating a backend bucket."""
if (not self.AnyArgsSpecified(args) and
not args.IsSpecified('signed_url_cache_max_age') and
not args.IsSpecified('request_coalescing') and
not self.AnyFlexibleCacheArgsSpecified(args)):
raise exceptions.UpdatePropertyError(
'At least one property must be modified.')
return self.MakeRequests(args)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
@base.UniverseCompatible
class UpdateBeta(Update):
"""Update a backend bucket.
*{command}* is used to update backend buckets.
To delete a global backend bucket, run either of the following:
$ {command} my-backend-bucket
--no-enable-cdn
--global
$ {command} my-backend-bucket
--no-enable-cdn
To delete a regional backend bucket, run the following:
$ {command} my-backend-bucket --region=us-central1
--no-enable-cdn
"""
support_regional_global_flags = True
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.UniverseCompatible
class UpdateAlpha(UpdateBeta):
"""Update a backend bucket.
*{command}* is used to update backend buckets.
To delete a global backend bucket, run either of the following:
$ {command} my-backend-bucket
--no-enable-cdn
--global
$ {command} my-backend-bucket
--no-enable-cdn
To delete a regional backend bucket, run the following:
$ {command} my-backend-bucket --region=us-central1
--no-enable-cdn
"""
support_regional_global_flags = True