feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
# -*- 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.
"""Commands for reading and manipulating forwarding rules."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.UniverseCompatible
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA)
class ForwardingRules(base.Group):
"""Read and manipulate traffic forwarding rules to network load balancers."""
ForwardingRules.category = base.LOAD_BALANCING_CATEGORY
ForwardingRules.detailed_help = {
'DESCRIPTION': """
Read and manipulate traffic forwarding rules for load balancers,
protocol forwarding, or Classic Cloud VPN.
For more information about forwarding rules, see the
[forwarding rules documentation](https://cloud.google.com/load-balancing/docs/forwarding-rule-concepts).
See also: [Region forwarding rules API](https://cloud.google.com/compute/docs/reference/rest/v1/forwardingRules)
and [Global forwarding rules API](https://cloud.google.com/compute/docs/reference/rest/v1/globalForwardingRules).
""",
}

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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 group for managing instance configurations."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Config(base.Group):
"""Manage traffic forwarding rule configurations."""
Config.detailed_help = {
'DESCRIPTION': """
Manage traffic forwarding rule configurations.
""",
}

View File

@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Export backend service command."""
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 base
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
from googlecloudsdk.command_lib.util.declarative import python_command_util as declarative_python_util
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Export(base.Command):
"""Export the configuration for a firewall rule."""
detailed_help = declarative_python_util.BuildHelpText(
singular='forwarding rule', service='Compute Engine')
@classmethod
def Args(cls, parser):
cls.FORWARDING_RULE_ARG = flags.ForwardingRuleArgument(required=False)
declarative_python_util.RegisterArgs(
parser, cls.FORWARDING_RULE_ARG.AddArgument, operation_type='export')
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
resource_ref = str(
self.FORWARDING_RULE_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(holder.client)))
return declarative_python_util.RunExport(
args=args,
collection='compute.forwardingRules',
resource_ref=resource_ref)

View File

@@ -0,0 +1,673 @@
# -*- 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 creating forwarding rules."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import ipaddress
import re
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute import constants
from googlecloudsdk.api_lib.compute import forwarding_rules_utils as utils
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import exceptions as fw_exceptions
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
from googlecloudsdk.core import log
import six
from six.moves import range # pylint: disable=redefined-builtin
def _Args(parser, support_all_protocol):
"""Add the flags to create a forwarding rule."""
flags.AddCreateArgs(
parser,
include_psc_google_apis=True,
include_target_service_attachment=True,
)
flags.AddIPProtocols(parser, support_all_protocol)
flags.AddDescription(parser)
flags.AddPortsAndPortRange(parser)
flags.AddNetworkTier(parser, for_update=False)
flags.AddAllowGlobalAccess(parser)
flags.AddAllowPscGlobalAccess(parser)
flags.AddSourceIpRanges(parser)
flags.AddDisableAutomateDnsZone(parser)
flags.AddIsMirroringCollector(parser)
flags.AddServiceDirectoryRegistration(parser)
parser.add_argument(
'--service-label',
help='(Only for Internal Load Balancing): '
'https://cloud.google.com/load-balancing/docs/dns-names/\n'
'The DNS label to use as the prefix of the fully qualified domain '
'name for this forwarding rule. The full name will be internally '
'generated and output as dnsName. If this field is not specified, '
'no DNS record will be generated and no DNS name will be output. '
'You cannot use the `--service-label` flag if the forwarding rule '
'references an internal IP address that has the '
'`--purpose=SHARED_LOADBALANCER_VIP` flag set.')
flags.AddAddressesAndIPVersions(parser)
forwarding_rule_arg = flags.ForwardingRuleArgument()
forwarding_rule_arg.AddArgument(parser, operation_type='create')
parser.display_info.AddCacheUpdater(flags.ForwardingRulesCompleter)
return forwarding_rule_arg
class CreateHelper(object):
"""Helper class to create a forwarding rule."""
FORWARDING_RULE_ARG = None
def __init__(
self,
holder,
support_all_protocol,
support_sd_registration_for_regional,
):
self._holder = holder
self._support_all_protocol = support_all_protocol
self._support_sd_registration_for_regional = (
support_sd_registration_for_regional
)
@classmethod
def Args(cls, parser, support_all_protocol):
"""Inits the class args for supported features."""
cls.FORWARDING_RULE_ARG = _Args(parser, support_all_protocol)
def ConstructProtocol(self, messages, args):
if args.ip_protocol:
return messages.ForwardingRule.IPProtocolValueValuesEnum(args.ip_protocol)
else:
return
def Run(self, args):
"""Issues requests necessary to create Forwarding Rules."""
client = self._holder.client
forwarding_rule_ref = self.FORWARDING_RULE_ARG.ResolveAsResource(
args,
self._holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client))
if forwarding_rule_ref.Collection() == 'compute.globalForwardingRules':
requests = self._CreateGlobalRequests(client, self._holder.resources,
args, forwarding_rule_ref)
elif forwarding_rule_ref.Collection() == 'compute.forwardingRules':
requests = self._CreateRegionalRequests(client, self._holder.resources,
args, forwarding_rule_ref)
return client.MakeRequests(requests)
def _CreateGlobalRequests(self, client, resources, args, forwarding_rule_ref):
"""Create a globally scoped request."""
is_psc_google_apis = (
hasattr(args, 'target_google_apis_bundle')
and args.target_google_apis_bundle
)
sd_registration = None
if hasattr(args, 'service_directory_registration'
) and args.service_directory_registration:
if not is_psc_google_apis:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
'Can only be specified for regional forwarding rules or Private Service Connect forwarding rules targeting a Google APIs bundle.'
)
# Parse projects/../locations/..
match = re.match(
r'^projects/([^/]+)/locations/([^/]+)(?:/namespaces/([^/]+))?$',
args.service_directory_registration)
if not match:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
'Must be of the form projects/PROJECT/locations/REGION or projects/PROJECT/locations/REGION/namespaces/NAMESPACE'
)
project = match.group(1)
region = match.group(2)
namespace = match.group(3)
if project != forwarding_rule_ref.project:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
'Must be in the same project as the forwarding rule.')
sd_registration = client.messages.ForwardingRuleServiceDirectoryRegistration(
serviceDirectoryRegion=region, namespace=namespace)
ports_all_specified, range_list = _ExtractPortsAndAll(args.ports)
port_range = _MakeSingleUnifiedPortRange(args.port_range, range_list)
# All global forwarding rules must use EXTERNAL or INTERNAL_SELF_MANAGED
# schemes presently.
load_balancing_scheme = _GetLoadBalancingScheme(args, client.messages,
is_psc_google_apis)
if (load_balancing_scheme == client.messages.ForwardingRule
.LoadBalancingSchemeValueValuesEnum.INTERNAL):
raise fw_exceptions.ArgumentError(
'You cannot specify internal [--load-balancing-scheme] for a global '
'forwarding rule.')
if (load_balancing_scheme == client.messages.ForwardingRule
.LoadBalancingSchemeValueValuesEnum.INTERNAL_SELF_MANAGED):
if (not args.target_http_proxy and not args.target_https_proxy and
not args.target_grpc_proxy and not args.target_tcp_proxy):
target_error_message_with_tcp = (
'You must specify either [--target-http-proxy], '
'[--target-https-proxy], [--target-grpc-proxy] '
'or [--target-tcp-proxy] for an '
'INTERNAL_SELF_MANAGED [--load-balancing-scheme].')
raise fw_exceptions.ArgumentError(target_error_message_with_tcp)
if args.subnet:
raise fw_exceptions.ArgumentError(
'You cannot specify [--subnet] for an INTERNAL_SELF_MANAGED '
'[--load-balancing-scheme].')
if not args.address:
raise fw_exceptions.ArgumentError(
'You must specify [--address] for an INTERNAL_SELF_MANAGED '
'[--load-balancing-scheme]')
if is_psc_google_apis:
rule_name = forwarding_rule_ref.Name()
if len(rule_name) > 20 or rule_name[0].isdigit(
) or not rule_name.isalnum():
raise fw_exceptions.ArgumentError(
'A forwarding rule to Google APIs must have a name that is between '
' 1-20 characters long, alphanumeric, starting with a letter.')
if port_range:
raise exceptions.InvalidArgumentException(
'--ports',
'[--ports] is not allowed for PSC-GoogleApis forwarding rules.')
if load_balancing_scheme:
raise exceptions.InvalidArgumentException(
'--load-balancing-scheme',
'The --load-balancing-scheme flag is not allowed for PSC-GoogleApis'
' forwarding rules.')
if args.target_google_apis_bundle in flags.PSC_GOOGLE_APIS_BUNDLES:
target_as_str = args.target_google_apis_bundle
else:
bundles_list = ', '.join(flags.PSC_GOOGLE_APIS_BUNDLES)
raise exceptions.InvalidArgumentException(
'--target-google-apis-bundle',
'The valid values for target-google-apis-bundle are: ' +
bundles_list)
else:
# L7XLB in Premium Tier.
target_ref = utils.GetGlobalTarget(resources, args)
target_as_str = target_ref.SelfLink()
if ports_all_specified:
raise exceptions.InvalidArgumentException(
'--ports',
'[--ports] cannot be set to ALL for global forwarding rules.')
if not port_range:
raise exceptions.InvalidArgumentException(
'--ports', '[--ports] is required for global forwarding rules.')
protocol = self.ConstructProtocol(client.messages, args)
address = self._ResolveAddress(resources, args,
compute_flags.compute_scope.ScopeEnum.GLOBAL,
forwarding_rule_ref)
forwarding_rule = client.messages.ForwardingRule(
description=args.description,
name=forwarding_rule_ref.Name(),
IPAddress=address,
IPProtocol=protocol,
portRange=port_range,
target=target_as_str,
networkTier=_ConstructNetworkTier(client.messages, args),
loadBalancingScheme=load_balancing_scheme)
self._ProcessCommonArgs(client, resources, args, forwarding_rule_ref,
forwarding_rule)
if sd_registration:
forwarding_rule.serviceDirectoryRegistrations.append(sd_registration)
if args.IsSpecified('allow_global_access'):
forwarding_rule.allowGlobalAccess = args.allow_global_access
request = client.messages.ComputeGlobalForwardingRulesInsertRequest(
forwardingRule=forwarding_rule, project=forwarding_rule_ref.project)
return [(client.apitools_client.globalForwardingRules, 'Insert', request)]
def _CreateRegionalRequests(self, client, resources, args,
forwarding_rule_ref):
"""Create a regionally scoped request."""
is_psc_ilb = (
hasattr(args, 'target_service_attachment')
and args.target_service_attachment
)
target_ref, region_ref = utils.GetRegionalTarget(
client, resources, args, forwarding_rule_ref
)
if not args.region and region_ref:
args.region = region_ref
protocol = self.ConstructProtocol(client.messages, args)
address = self._ResolveAddress(resources, args,
compute_flags.compute_scope.ScopeEnum.REGION,
forwarding_rule_ref)
load_balancing_scheme = _GetLoadBalancingScheme(args, client.messages,
is_psc_ilb)
if is_psc_ilb and load_balancing_scheme:
raise exceptions.InvalidArgumentException(
'--load-balancing-scheme',
'The --load-balancing-scheme flag is not allowed for PSC-ILB '
'forwarding rules.')
if (load_balancing_scheme == client.messages.ForwardingRule
.LoadBalancingSchemeValueValuesEnum.INTERNAL):
if args.port_range:
raise fw_exceptions.ArgumentError(
'You cannot specify [--port-range] for a forwarding rule '
'whose [--load-balancing-scheme] is internal, '
'please use [--ports] flag instead.')
if (load_balancing_scheme == client.messages.ForwardingRule
.LoadBalancingSchemeValueValuesEnum.INTERNAL_SELF_MANAGED):
raise fw_exceptions.ArgumentError(
'You cannot specify an INTERNAL_SELF_MANAGED '
'[--load-balancing-scheme] for a regional forwarding rule.')
forwarding_rule = client.messages.ForwardingRule(
description=args.description,
name=forwarding_rule_ref.Name(),
IPAddress=address,
IPProtocol=protocol,
networkTier=_ConstructNetworkTier(client.messages, args),
loadBalancingScheme=load_balancing_scheme)
if args.source_ip_ranges:
forwarding_rule.sourceIpRanges = args.source_ip_ranges
self._ProcessCommonArgs(client, resources, args, forwarding_rule_ref,
forwarding_rule)
ports_all_specified, range_list = _ExtractPortsAndAll(args.ports)
if target_ref.Collection() == 'compute.regionBackendServices':
# A FR pointing to a BES has no target attribute.
forwarding_rule.backendService = target_ref.SelfLink()
forwarding_rule.target = None
else:
# A FR pointing to anything not a BES has a target attribute.
forwarding_rule.backendService = None
forwarding_rule.target = target_ref.SelfLink()
if ((target_ref.Collection() == 'compute.regionBackendServices' or
target_ref.Collection() == 'compute.targetInstances') and
args.load_balancing_scheme == 'INTERNAL'):
# This is for L4ILB and internal protocol forwarding.
# API fields allPorts, ports, and portRange are mutually exclusive.
# API field portRange is not valid for this case.
# Use of L3_DEFAULT implies all ports even if allPorts is unset.
if ports_all_specified:
forwarding_rule.allPorts = True
elif range_list:
forwarding_rule.ports = [
six.text_type(p) for p in _GetPortList(range_list)
]
elif ((target_ref.Collection() == 'compute.regionTargetHttpProxies' or
target_ref.Collection() == 'compute.regionTargetHttpsProxies') and
args.load_balancing_scheme == 'INTERNAL'):
# This is a legacy configuration for L7ILB.
forwarding_rule.ports = [
six.text_type(p) for p in _GetPortList(range_list)
]
elif args.load_balancing_scheme == 'INTERNAL':
# There are currently no other valid combinations of targets with scheme
# internal. With scheme internal, targets must presently be a regional
# backend service (L4ILB) or a target instance (protocol forwarding).
raise exceptions.InvalidArgumentException(
'--load-balancing-scheme',
'Only target instances and backend services should be specified as '
'a target for internal load balancing.')
elif args.load_balancing_scheme == 'INTERNAL_MANAGED':
# This is L7ILB.
forwarding_rule.portRange = _MakeSingleUnifiedPortRange(
args.port_range, range_list)
elif args.load_balancing_scheme == 'EXTERNAL_MANAGED':
# This is regional L7XLB.
forwarding_rule.portRange = _MakeSingleUnifiedPortRange(
args.port_range, range_list)
elif ((target_ref.Collection() == 'compute.regionBackendServices') and
((args.load_balancing_scheme == 'EXTERNAL') or
(not args.load_balancing_scheme))):
# This is NetLB using a backend service. Scheme is either explicitly
# EXTERNAL or not supplied (EXTERNAL is the default scheme).
# API fields allPorts, ports, and portRange are mutually exclusive.
# All three API fields are valid for this case.
# Use of L3_DEFAULT implies all ports even if allPorts is unset.
if ports_all_specified:
forwarding_rule.allPorts = True
elif range_list:
if len(range_list) > 1:
# More than one port, potentially discontiguous, from --ports= flag.
forwarding_rule.ports = [
six.text_type(p) for p in _GetPortList(range_list)
]
else:
# Exactly one value from --ports= flag. Might be a single port (80);
# might be a range (80-90). Since it might be a range, the portRange
# API attribute is more appropriate.
forwarding_rule.portRange = six.text_type(range_list[0])
elif args.port_range:
forwarding_rule.portRange = _MakeSingleUnifiedPortRange(
args.port_range, range_list)
elif ((target_ref.Collection() == 'compute.targetPool' or
target_ref.Collection() == 'compute.targetInstances') and
((args.load_balancing_scheme == 'EXTERNAL') or
(not args.load_balancing_scheme))):
# This is NetLB using a target pool or external protocol forwarding.
# Scheme is either explicitly EXTERNAL or not supplied (EXTERNAL is the
# default scheme).
# API fields allPorts, ports, and portRange are mutually exclusive.
# API field ports is not valid for this case.
# Use of L3_DEFAULT implies all ports by definition.
if ports_all_specified:
forwarding_rule.allPorts = True
else:
forwarding_rule.portRange = _MakeSingleUnifiedPortRange(
args.port_range, range_list)
else:
# All other regional forwarding rules with load balancing scheme EXTERNAL.
forwarding_rule.portRange = _MakeSingleUnifiedPortRange(
args.port_range, range_list)
if hasattr(args, 'service_label'):
forwarding_rule.serviceLabel = args.service_label
if args.IsSpecified('allow_global_access'):
forwarding_rule.allowGlobalAccess = args.allow_global_access
if args.IsSpecified('allow_psc_global_access'):
forwarding_rule.allowPscGlobalAccess = args.allow_psc_global_access
if args.IsSpecified('ip_collection'):
forwarding_rule.ipCollection = flags.IP_COLLECTION_ARG.ResolveAsResource(
args, resources).SelfLink()
if args.IsSpecified('disable_automate_dns_zone'):
forwarding_rule.noAutomateDnsZone = args.disable_automate_dns_zone
if hasattr(args, 'is_mirroring_collector'):
forwarding_rule.isMirroringCollector = args.is_mirroring_collector
if hasattr(args, 'service_directory_registration'
) and args.service_directory_registration:
if is_psc_ilb:
# Parse projects/../locations/../namespaces/..
match = re.match(
r'^projects/([^/]+)/locations/([^/]+)/namespaces/([^/]+)$',
args.service_directory_registration)
if not match:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
'If set, must be of the form projects/PROJECT/locations/REGION/namespaces/NAMESPACE'
)
project = match.group(1)
region = match.group(2)
if project != forwarding_rule_ref.project or region != forwarding_rule_ref.region:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
'Service Directory registration must be in the same project and region as the forwarding rule.'
)
sd_registration = client.messages.ForwardingRuleServiceDirectoryRegistration(
namespace=match.group(3))
forwarding_rule.serviceDirectoryRegistrations.append(sd_registration)
else:
if not self._support_sd_registration_for_regional:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
"""flag is available in one or more alternate release tracks. Try:
gcloud alpha compute forwarding-rules create --service-directory-registration
gcloud beta compute forwarding-rules create --service-directory-registration"""
)
# Parse projects/../locations/../namespaces/../services/..
match = re.match(
r'^projects/([^/]+)/locations/([^/]+)/namespaces/([^/]+)/services/([^/]+)$',
args.service_directory_registration)
if not match:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
'Must be of the form projects/PROJECT/locations/REGION/namespaces/NAMESPACE/services/SERVICE'
)
project = match.group(1)
region = match.group(2)
if project != forwarding_rule_ref.project or region != forwarding_rule_ref.region:
raise exceptions.InvalidArgumentException(
'--service-directory-registration',
'Service Directory registration must be in the same project and region as the forwarding rule.'
)
sd_registration = client.messages.ForwardingRuleServiceDirectoryRegistration(
namespace=match.group(3), service=match.group(4))
forwarding_rule.serviceDirectoryRegistrations.append(sd_registration)
request = client.messages.ComputeForwardingRulesInsertRequest(
forwardingRule=forwarding_rule,
project=forwarding_rule_ref.project,
region=forwarding_rule_ref.region)
return [(client.apitools_client.forwardingRules, 'Insert', request)]
def _ResolveAddress(self, resources, args, scope, forwarding_rule_ref):
"""Resolve address resource."""
# Address takes either an ip address or an address resource. If parsing as
# an IP address fails, then we resolve as a resource.
address = args.address
if address is not None:
try:
# ipaddress only allows unicode input
ipaddress.ip_network(six.text_type(args.address))
except ValueError:
# TODO(b/37086838): Make sure global/region settings are inherited by
# address resource.
if scope == compute_flags.compute_scope.ScopeEnum.REGION:
if not args.global_address and not args.address_region:
if forwarding_rule_ref.Collection() == 'compute.forwardingRules':
args.address_region = forwarding_rule_ref.region
address_ref = flags.AddressArg().ResolveAsResource(
args, resources, default_scope=scope)
address = address_ref.SelfLink()
return address
def _ProcessCommonArgs(self, client, resources, args, forwarding_rule_ref,
forwarding_rule):
"""Processes common arguments for global and regional commands.
Args:
client: The client used by gcloud.
resources: The resource parser.
args: The arguments passed to the gcloud command.
forwarding_rule_ref: The forwarding rule reference.
forwarding_rule: The forwarding rule to set properties on.
"""
if args.ip_version:
forwarding_rule.ipVersion = (
client.messages.ForwardingRule.IpVersionValueValuesEnum(
args.ip_version))
if args.network:
forwarding_rule.network = flags.NetworkArg().ResolveAsResource(
args, resources).SelfLink()
if args.subnet:
if (not args.subnet_region and
forwarding_rule_ref.Collection() == 'compute.forwardingRules'):
args.subnet_region = forwarding_rule_ref.region
forwarding_rule.subnetwork = flags.SUBNET_ARG.ResolveAsResource(
args, resources).SelfLink()
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.UniverseCompatible
class Create(base.CreateCommand):
"""Create a forwarding rule to direct network traffic to a load balancer."""
_support_all_protocol = False
_support_sd_registration_for_regional = False
@classmethod
def Args(cls, parser):
CreateHelper.Args(parser, cls._support_all_protocol)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return CreateHelper(
holder,
self._support_all_protocol,
self._support_sd_registration_for_regional,
).Run(args)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class CreateBeta(Create):
"""Create a forwarding rule to direct network traffic to a load balancer."""
_support_all_protocol = False
_support_sd_registration_for_regional = True
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(CreateBeta):
"""Create a forwarding rule to direct network traffic to a load balancer."""
_support_all_protocol = True
_support_sd_registration_for_regional = True
Create.detailed_help = {
'DESCRIPTION': ("""
*{{command}}* is used to create a forwarding rule. {overview}
When creating a forwarding rule, exactly one of ``--target-instance'',
``--target-pool'', ``--target-http-proxy'', ``--target-https-proxy'',
``--target-grpc-proxy'', ``--target-ssl-proxy'', ``--target-tcp-proxy'',
``--target-vpn-gateway'', ``--backend-service'' or ``--target-google-apis-bundle''
must be specified.""".format(overview=flags.FORWARDING_RULES_OVERVIEW)),
'EXAMPLES':
"""
To create a global forwarding rule that will forward all traffic on port
8080 for IP address ADDRESS to a target http proxy PROXY, run:
$ {command} RULE_NAME --global --target-http-proxy=PROXY --ports=8080 --address=ADDRESS
To create a regional forwarding rule for the subnet SUBNET_NAME on the
default network that will forward all traffic on ports 80-82 to a
backend service SERVICE_NAME, run:
$ {command} RULE_NAME --load-balancing-scheme=INTERNAL --backend-service=SERVICE_NAME --subnet=SUBNET_NAME --network=default --region=REGION --ports=80-82
"""
}
CreateBeta.detailed_help = Create.detailed_help
CreateAlpha.detailed_help = CreateBeta.detailed_help
def _UnifyPortRangeFromListOfRanges(ports_range_list):
"""Return a single port range by combining a list of port ranges."""
if not ports_range_list:
return None, None
ports = sorted(ports_range_list)
combined_port_range = ports.pop(0)
for port_range in ports_range_list:
try:
combined_port_range = combined_port_range.Combine(port_range)
except arg_parsers.Error:
raise exceptions.InvalidArgumentException(
'--ports', 'Must specify consecutive ports at this time.')
return combined_port_range
def _ExtractPortsAndAll(ports_with_all):
if ports_with_all:
return ports_with_all.all_specified, ports_with_all.ranges
else:
return False, []
def _MakeSingleUnifiedPortRange(arg_port_range, range_list_from_arg_ports):
"""Reconciles the deprecated --port-range arg with ranges from --ports arg."""
if arg_port_range:
log.warning(
'The --port-range flag is deprecated. Use equivalent --ports=%s'
' flag.', arg_port_range)
return six.text_type(arg_port_range)
elif range_list_from_arg_ports:
range_list = _UnifyPortRangeFromListOfRanges(range_list_from_arg_ports)
return six.text_type(range_list) if range_list else None
def _GetPortList(range_list):
"""Creates list of singleton port numbers from list of ports and ranges."""
ports = []
for port_range in range_list:
ports.extend(list(range(port_range.start, port_range.end + 1)))
return sorted(ports)
def _GetLoadBalancingScheme(args, messages, is_psc):
"""Get load balancing scheme."""
if not args.load_balancing_scheme:
# The default is EXTERNAL for non-PSC forwarding rules.
return None if is_psc else messages.ForwardingRule.LoadBalancingSchemeValueValuesEnum.EXTERNAL
if args.load_balancing_scheme == 'INTERNAL':
return messages.ForwardingRule.LoadBalancingSchemeValueValuesEnum.INTERNAL
elif args.load_balancing_scheme == 'EXTERNAL':
return messages.ForwardingRule.LoadBalancingSchemeValueValuesEnum.EXTERNAL
elif args.load_balancing_scheme == 'EXTERNAL_MANAGED':
return messages.ForwardingRule.LoadBalancingSchemeValueValuesEnum.EXTERNAL_MANAGED
elif args.load_balancing_scheme == 'INTERNAL_SELF_MANAGED':
return (messages.ForwardingRule.LoadBalancingSchemeValueValuesEnum
.INTERNAL_SELF_MANAGED)
elif args.load_balancing_scheme == 'INTERNAL_MANAGED':
return (messages.ForwardingRule.LoadBalancingSchemeValueValuesEnum
.INTERNAL_MANAGED)
return None
def _ConstructNetworkTier(messages, args):
"""Get network tier."""
if args.network_tier:
network_tier = args.network_tier.upper()
if network_tier in constants.NETWORK_TIER_CHOICES_FOR_INSTANCE:
return messages.ForwardingRule.NetworkTierValueValuesEnum(
args.network_tier)
else:
raise exceptions.InvalidArgumentException(
'--network-tier',
'Invalid network tier [{tier}]'.format(tier=network_tier))
else:
return

View File

@@ -0,0 +1,82 @@
# -*- 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 deleting forwarding rules."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute import utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
def _Args(parser):
"""Add the flags to delete a forwarding rule."""
forwarding_rules_arg = flags.ForwardingRuleArgumentPlural()
forwarding_rules_arg.AddArgument(parser, operation_type='delete')
parser.display_info.AddCacheUpdater(flags.ForwardingRulesCompleter)
return forwarding_rules_arg
def _Run(args, holder, forwarding_rules_arg):
"""Issues requests necessary to delete Forwarding Rules."""
client = holder.client
forwarding_rule_refs = forwarding_rules_arg.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client))
utils.PromptForDeletion(forwarding_rule_refs)
requests = []
for forwarding_rule_ref in forwarding_rule_refs:
if forwarding_rule_ref.Collection() == 'compute.globalForwardingRules':
request = client.messages.ComputeGlobalForwardingRulesDeleteRequest(
forwardingRule=forwarding_rule_ref.Name(),
project=forwarding_rule_ref.project)
requests.append(
(client.apitools_client.globalForwardingRules, 'Delete', request))
else:
request = client.messages.ComputeForwardingRulesDeleteRequest(
forwardingRule=forwarding_rule_ref.Name(),
project=forwarding_rule_ref.project,
region=forwarding_rule_ref.region)
requests.append(
(client.apitools_client.forwardingRules, 'Delete', request))
return client.MakeRequests(requests)
class Delete(base.DeleteCommand):
"""Delete forwarding rules.
*{command}* deletes one or more Compute Engine forwarding rules.
"""
FORWARDING_RULES_ARG = None
@classmethod
def Args(cls, parser):
cls.FORWARDING_RULES_ARG = _Args(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return _Run(args, holder, self.FORWARDING_RULES_ARG)

View File

@@ -0,0 +1,78 @@
# -*- 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 describing forwarding rules."""
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 base
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
def _Args(parser):
forwarding_rules_arg = flags.ForwardingRuleArgument()
forwarding_rules_arg.AddArgument(parser, operation_type='describe')
return forwarding_rules_arg
def _Run(args, holder, forwarding_rules_arg):
"""Issues request necessary to describe the Forwarding Rule."""
client = holder.client
forwarding_rule_ref = forwarding_rules_arg.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client))
if forwarding_rule_ref.Collection() == 'compute.forwardingRules':
service = client.apitools_client.forwardingRules
request = client.messages.ComputeForwardingRulesGetRequest(
**forwarding_rule_ref.AsDict())
elif forwarding_rule_ref.Collection() == 'compute.globalForwardingRules':
service = client.apitools_client.globalForwardingRules
request = client.messages.ComputeGlobalForwardingRulesGetRequest(
**forwarding_rule_ref.AsDict())
return client.MakeRequests([(service, 'Get', request)])[0]
class Describe(base.DescribeCommand):
"""Display detailed information about a forwarding rule.
*{command}* displays all data associated with a forwarding rule
in a project.
## EXAMPLES
To get details about a global forwarding rule, run:
$ {command} FORWARDING-RULE --global
To get details about a regional forwarding rule, run:
$ {command} FORWARDING-RULE --region=us-central1
"""
FORWARDING_RULE_ARG = None
@staticmethod
def Args(parser):
Describe.FORWARDING_RULE_ARG = _Args(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return _Run(args, holder, self.FORWARDING_RULE_ARG)

View File

@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 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.
"""Export forwarding rules command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import sys
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute import forwarding_rules_utils as utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
from googlecloudsdk.command_lib.export import util as export_util
from googlecloudsdk.core.util import files
DETAILED_HELP = {
'DESCRIPTION':
"""\
Exports a forwarding rule's configuration to a file.
""",
'EXAMPLES':
"""\
A forwarding rule can be exported by running:
$ {command} NAME --destination=<path-to-file>
"""
}
@base.ReleaseTracks(base.ReleaseTrack.GA, base.ReleaseTrack.BETA,
base.ReleaseTrack.ALPHA)
class Export(base.Command):
"""Export a forwarding rule.
Exports a forwarding rule's configuration to a file.
This configuration can be imported at a later time.
"""
FORWARDING_RULE_ARG = None
detailed_help = DETAILED_HELP
@classmethod
def GetApiVersion(cls):
"""Returns the API version based on the release track."""
if cls.ReleaseTrack() == base.ReleaseTrack.ALPHA:
return 'alpha'
elif cls.ReleaseTrack() == base.ReleaseTrack.BETA:
return 'beta'
return 'v1'
@classmethod
def GetSchemaPath(cls, for_help=False):
"""Returns the resource schema path."""
return export_util.GetSchemaPath(
'compute', cls.GetApiVersion(), 'ForwardingRule', for_help=for_help)
@classmethod
def Args(cls, parser):
cls.FORWARDING_RULE_ARG = flags.ForwardingRuleArgument()
cls.FORWARDING_RULE_ARG.AddArgument(parser, operation_type='export')
export_util.AddExportFlags(parser, cls.GetSchemaPath(for_help=True))
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
forwarding_rule_ref = self.FORWARDING_RULE_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client))
forwarding_rule = utils.SendGetRequest(client, forwarding_rule_ref)
if args.destination:
with files.FileWriter(args.destination) as stream:
export_util.Export(message=forwarding_rule,
stream=stream,
schema_path=self.GetSchemaPath())
else:
export_util.Export(message=forwarding_rule,
stream=sys.stdout,
schema_path=self.GetSchemaPath())

View File

@@ -0,0 +1,181 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 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.
"""Import forwarding rules command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute import forwarding_rules_utils as utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import exceptions
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
from googlecloudsdk.command_lib.export import util as export_util
from googlecloudsdk.core import yaml_validator
from googlecloudsdk.core.console import console_io
DETAILED_HELP = {
'DESCRIPTION':
"""\
Imports a forwarding rule's configuration from a file.
""",
'EXAMPLES':
"""\
Import a forwarding rule by running:
$ {command} NAME --source=<path-to-file>
"""
}
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Import(base.UpdateCommand):
"""Import a forwarding rule."""
FORWARDING_RULE_ARG = None
detailed_help = DETAILED_HELP
_support_source_ip_range = False
@classmethod
def GetApiVersion(cls):
"""Returns the API version based on the release track."""
if cls.ReleaseTrack() == base.ReleaseTrack.ALPHA:
return 'alpha'
elif cls.ReleaseTrack() == base.ReleaseTrack.BETA:
return 'beta'
return 'v1'
@classmethod
def GetSchemaPath(cls, for_help=False):
"""Returns the resource schema path."""
return export_util.GetSchemaPath(
'compute', cls.GetApiVersion(), 'ForwardingRule', for_help=for_help)
@classmethod
def Args(cls, parser):
cls.FORWARDING_RULE_ARG = flags.ForwardingRuleArgument()
cls.FORWARDING_RULE_ARG.AddArgument(parser, operation_type='import')
export_util.AddImportFlags(parser, cls.GetSchemaPath(for_help=True))
def SendPatchRequest(self, client, forwarding_rule_ref, replacement):
"""Create forwarding rule patch request."""
console_message = (
'Forwarding Rule [{0}] cannot be updated in version v1'.format(
forwarding_rule_ref.Name()))
raise NotImplementedError(console_message)
def SendInsertRequest(self, client, forwarding_rule_ref, forwarding_rule):
"""Send forwarding rule insert request."""
if forwarding_rule_ref.Collection() == 'compute.forwardingRules':
return client.apitools_client.forwardingRules.Insert(
client.messages.ComputeForwardingRulesInsertRequest(
forwardingRule=forwarding_rule,
project=forwarding_rule_ref.project,
region=forwarding_rule_ref.region))
return client.apitools_client.globalForwardingRules.Insert(
client.messages.ComputeGlobalForwardingRulesInsertRequest(
forwardingRule=forwarding_rule,
project=forwarding_rule_ref.project))
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
forwarding_rule_ref = self.FORWARDING_RULE_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(holder.client))
data = console_io.ReadFromFileOrStdin(args.source or '-', binary=False)
try:
forwarding_rule = export_util.Import(
message_type=client.messages.ForwardingRule,
stream=data,
schema_path=self.GetSchemaPath())
except yaml_validator.ValidationError as e:
raise exceptions.ValidationError(str(e))
# Get existing forwarding rule.
try:
forwarding_rule_old = utils.SendGetRequest(client, forwarding_rule_ref)
except apitools_exceptions.HttpError as error:
if error.status_code != 404:
raise error
# Forwarding rule does not exist, create a new one.
return self.SendInsertRequest(client, forwarding_rule_ref,
forwarding_rule)
# No change, do not send requests to server.
if forwarding_rule_old == forwarding_rule:
return
console_io.PromptContinue(
message=('Forwarding Rule [{0}] will be overwritten.').format(
forwarding_rule_ref.Name()),
cancel_on_no=True)
# Populate id and fingerprint fields. These two fields are manually
# removed from the schema files.
forwarding_rule.id = forwarding_rule_old.id
forwarding_rule.fingerprint = forwarding_rule_old.fingerprint
# Unspecified fields are assumed to be cleared.
cleared_fields = []
if not forwarding_rule.networkTier:
cleared_fields.append('networkTier')
if not forwarding_rule.allowGlobalAccess:
cleared_fields.append('allowGlobalAccess')
if self._support_source_ip_range and not forwarding_rule.sourceIpRanges:
cleared_fields.append('sourceIpRanges')
if not forwarding_rule.metadataFilters:
cleared_fields.append('metadataFilters')
with client.apitools_client.IncludeFields(cleared_fields):
return self.SendPatchRequest(client, forwarding_rule_ref, forwarding_rule)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class ImportBeta(Import):
"""Import a forwarding rule."""
def SendPatchRequest(self, client, forwarding_rule_ref, replacement):
"""Create forwarding rule patch request."""
if forwarding_rule_ref.Collection() == 'compute.forwardingRules':
return client.apitools_client.forwardingRules.Patch(
client.messages.ComputeForwardingRulesPatchRequest(
project=forwarding_rule_ref.project,
region=forwarding_rule_ref.region,
forwardingRule=forwarding_rule_ref.Name(),
forwardingRuleResource=replacement))
return client.apitools_client.globalForwardingRules.Patch(
client.messages.ComputeGlobalForwardingRulesPatchRequest(
project=forwarding_rule_ref.project,
forwardingRule=forwarding_rule_ref.Name(),
forwardingRuleResource=replacement))
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ImportAlpha(ImportBeta):
"""Import a forwarding rule."""
_support_source_ip_range = True
pass

View File

@@ -0,0 +1,75 @@
# -*- 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 listing forwarding rules."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute import lister
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
def _Args(parser):
"""Add flags to list forwarding rules to the parser."""
parser.display_info.AddFormat("""\
table(
name,
region.basename(),
IPAddress,
IPProtocol,
firstof(
target,
backendService).scope():label=TARGET
)
""")
lister.AddMultiScopeListerFlags(parser, regional=True, global_=True)
parser.display_info.AddCacheUpdater(flags.ForwardingRulesCompleter)
def _Run(args, holder):
"""Issues request necessary to list forwarding rules."""
client = holder.client
request_data = lister.ParseMultiScopeFlags(args, holder.resources)
list_implementation = lister.MultiScopeLister(
client,
regional_service=client.apitools_client.forwardingRules,
global_service=client.apitools_client.globalForwardingRules,
aggregation_service=client.apitools_client.forwardingRules)
return lister.Invoke(request_data, list_implementation)
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.GA,
base.ReleaseTrack.ALPHA)
class List(base.ListCommand):
"""List forwarding rules."""
@staticmethod
def Args(parser):
_Args(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return _Run(args, holder)
List.detailed_help = (
base_classes.GetGlobalRegionalListerHelp('forwarding rules'))

View File

@@ -0,0 +1,133 @@
# -*- 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 modifying the target of forwarding rules."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute import forwarding_rules_utils as utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
class SetTargetHelper(object):
"""Helper that sets a forwarding rule's target."""
FORWARDING_RULE_ARG = None
def __init__(self, holder):
self._holder = holder
@classmethod
def Args(cls, parser):
"""Adds flags to set the target of a forwarding rule."""
cls.FORWARDING_RULE_ARG = flags.ForwardingRuleArgument()
flags.AddSetTargetArgs(parser)
cls.FORWARDING_RULE_ARG.AddArgument(parser)
def Run(self, args):
"""Issues requests necessary to set target on Forwarding Rule."""
client = self._holder.client
forwarding_rule_ref = self.FORWARDING_RULE_ARG.ResolveAsResource(
args,
self._holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client))
if forwarding_rule_ref.Collection() == 'compute.globalForwardingRules':
requests = self.CreateGlobalRequests(client, self._holder.resources,
forwarding_rule_ref, args)
elif forwarding_rule_ref.Collection() == 'compute.forwardingRules':
requests = self.CreateRegionalRequests(client, self._holder.resources,
forwarding_rule_ref, args)
return client.MakeRequests(requests)
def CreateGlobalRequests(self, client, resources, forwarding_rule_ref, args):
"""Create a globally scoped request."""
target_ref = utils.GetGlobalTarget(resources, args)
request = client.messages.ComputeGlobalForwardingRulesSetTargetRequest(
forwardingRule=forwarding_rule_ref.Name(),
project=forwarding_rule_ref.project,
targetReference=client.messages.TargetReference(
target=target_ref.SelfLink(),),
)
return [(client.apitools_client.globalForwardingRules, 'SetTarget', request)
]
def CreateRegionalRequests(self, client, resources, forwarding_rule_ref,
args):
"""Create a regionally scoped request."""
target_ref, _ = utils.GetRegionalTarget(
client, resources, args, forwarding_rule_ref=forwarding_rule_ref
)
request = client.messages.ComputeForwardingRulesSetTargetRequest(
forwardingRule=forwarding_rule_ref.Name(),
project=forwarding_rule_ref.project,
region=forwarding_rule_ref.region,
targetReference=client.messages.TargetReference(
target=target_ref.SelfLink(),),
)
return [(client.apitools_client.forwardingRules, 'SetTarget', request)]
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Set(base.UpdateCommand):
"""Modify a forwarding rule to direct network traffic to a new target."""
FORWARDING_RULE_ARG = None
detailed_help = {
'DESCRIPTION': ("""
*{{command}}* is used to set a new target for a forwarding
rule. {overview}
When creating a forwarding rule, exactly one of ``--target-instance'',
``--target-pool'', ``--target-http-proxy'', ``--target-https-proxy'',
``--target-grpc-proxy'', ``--target-ssl-proxy'',
``--target-tcp-proxy'' or ``--target-vpn-gateway''
must be specified.""".format(overview=flags.FORWARDING_RULES_OVERVIEW)
),
}
@classmethod
def Args(cls, parser):
SetTargetHelper.Args(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return SetTargetHelper(holder).Run(args)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class SetBeta(Set):
"""Modify a forwarding rule to direct network traffic to a new target."""
pass
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class SetAlpha(SetBeta):
"""Modify a forwarding rule to direct network traffic to a new target."""
pass

View File

@@ -0,0 +1,372 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 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 to update forwarding-rules."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.protorpclite import messages as message_proto
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute import constants
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions as calliope_exceptions
from googlecloudsdk.command_lib.compute import flags as compute_flags
from googlecloudsdk.command_lib.compute.forwarding_rules import exceptions as fw_exceptions
from googlecloudsdk.command_lib.compute.forwarding_rules import flags
from googlecloudsdk.command_lib.util.args import labels_util
def _Args(
cls,
parser,
support_network_tier,
):
"""Add the flags to create a forwarding rule."""
cls.FORWARDING_RULE_ARG = flags.ForwardingRuleArgument()
cls.FORWARDING_RULE_ARG.AddArgument(parser)
labels_util.AddUpdateLabelsFlags(parser)
if support_network_tier:
flags.AddNetworkTier(parser, for_update=True)
flags.AddSourceIpRanges(parser)
flags.AddAllowGlobalAccess(parser)
flags.AddAllowPscGlobalAccess(parser)
flags.AddExternalMigration(parser)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class UpdateGA(base.UpdateCommand):
"""Update a Compute Engine forwarding rule."""
FORWARDING_RULE_ARG = None
_support_network_tier = False
@classmethod
def Args(cls, parser):
_Args(
cls,
parser,
support_network_tier=cls._support_network_tier,
)
def _CreateGlobalSetLabelsRequest(self, messages, forwarding_rule_ref,
forwarding_rule, replacement):
return messages.ComputeGlobalForwardingRulesSetLabelsRequest(
project=forwarding_rule_ref.project,
resource=forwarding_rule_ref.Name(),
globalSetLabelsRequest=messages.GlobalSetLabelsRequest(
labelFingerprint=forwarding_rule.labelFingerprint,
labels=replacement))
def _CreateRegionalSetLabelsRequest(self, messages, forwarding_rule_ref,
forwarding_rule, replacement):
return messages.ComputeForwardingRulesSetLabelsRequest(
project=forwarding_rule_ref.project,
resource=forwarding_rule_ref.Name(),
region=forwarding_rule_ref.region,
regionSetLabelsRequest=messages.RegionSetLabelsRequest(
labelFingerprint=forwarding_rule.labelFingerprint,
labels=replacement))
def ConstructNetworkTier(self, messages, network_tier):
if network_tier:
network_tier = network_tier.upper()
if network_tier in constants.NETWORK_TIER_CHOICES_FOR_INSTANCE:
return messages.ForwardingRule.NetworkTierValueValuesEnum(network_tier)
else:
raise calliope_exceptions.InvalidArgumentException(
'--network-tier',
'Invalid network tier [{tier}]'.format(tier=network_tier))
else:
return
def _HasNextTierChange(self, args):
return self._support_network_tier and args.network_tier is not None
def _HasSourceIpRangeChange(self, args):
return args.IsSpecified('source_ip_ranges')
def _HasGlobalAccessChange(self, args):
return args.IsSpecified('allow_global_access')
def _HasPscGlobalAccessChange(self, args):
return args.IsSpecified('allow_psc_global_access')
def _HasExternalMigrationChange(self, args):
return (
args.IsSpecified(
'external_managed_backend_bucket_migration_testing_percentage'
)
or args.IsSpecified('external_managed_backend_bucket_migration_state')
or args.IsSpecified(
'clear_external_managed_backend_bucket_migration_state'
)
or args.IsSpecified('load_balancing_scheme')
)
def Modify(
self, messages: message_proto, args, existing, cleared_fields
) -> message_proto.Message:
"""Returns a modified forwarding rule message and included fields."""
has_change = False
forwarding_rule = messages.ForwardingRule(name=existing.name)
if self._HasNextTierChange(args):
forwarding_rule.networkTier = self.ConstructNetworkTier(
messages, args.network_tier)
has_change = True
if self._HasSourceIpRangeChange(args):
forwarding_rule.sourceIpRanges = args.source_ip_ranges
has_change = True
if self._HasGlobalAccessChange(args):
forwarding_rule.allowGlobalAccess = args.allow_global_access
has_change = True
if self._HasPscGlobalAccessChange(args):
forwarding_rule.allowPscGlobalAccess = args.allow_psc_global_access
forwarding_rule.fingerprint = existing.fingerprint
has_change = True
if args.IsSpecified('external_managed_backend_bucket_migration_state'):
forwarding_rule.externalManagedBackendBucketMigrationState = messages.ForwardingRule.ExternalManagedBackendBucketMigrationStateValueValuesEnum(
args.external_managed_backend_bucket_migration_state
)
has_change = True
if args.IsSpecified(
'external_managed_backend_bucket_migration_testing_percentage'
):
forwarding_rule.externalManagedBackendBucketMigrationTestingPercentage = (
args.external_managed_backend_bucket_migration_testing_percentage
)
has_change = True
if args.IsSpecified('load_balancing_scheme'):
forwarding_rule.loadBalancingScheme = (
messages.ForwardingRule.LoadBalancingSchemeValueValuesEnum(
args.load_balancing_scheme
)
)
has_change = True
if args.IsSpecified(
'clear_external_managed_backend_bucket_migration_state'
):
cleared_fields.append('externalManagedBackendBucketMigrationState')
cleared_fields.append(
'externalManagedBackendBucketMigrationTestingPercentage'
)
has_change = True
if not has_change:
return None
return forwarding_rule
def Run(self, args):
"""Returns a list of requests necessary for updating forwarding rules."""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client.apitools_client
messages = holder.client.messages
forwarding_rule_ref = self.FORWARDING_RULE_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(holder.client))
labels_diff = labels_util.Diff.FromUpdateArgs(args)
has_labels_updates = labels_diff.MayHaveUpdates()
has_change = any([
has_labels_updates,
self._HasNextTierChange(args),
self._HasGlobalAccessChange(args),
self._HasPscGlobalAccessChange(args),
self._HasSourceIpRangeChange(args),
self._HasExternalMigrationChange(args),
])
if not has_change:
raise fw_exceptions.ArgumentError(
'At least one property must be specified.')
# Get replacement.
if forwarding_rule_ref.Collection() == 'compute.globalForwardingRules':
get_request = (client.globalForwardingRules, 'Get',
messages.ComputeGlobalForwardingRulesGetRequest(
forwardingRule=forwarding_rule_ref.Name(),
project=forwarding_rule_ref.project))
labels_value = messages.GlobalSetLabelsRequest.LabelsValue
else:
get_request = (client.forwardingRules, 'Get',
messages.ComputeForwardingRulesGetRequest(
forwardingRule=forwarding_rule_ref.Name(),
project=forwarding_rule_ref.project,
region=forwarding_rule_ref.region))
labels_value = messages.RegionSetLabelsRequest.LabelsValue
objects = holder.client.MakeRequests([get_request])
forwarding_rule = objects[0]
cleared_fields = []
forwarding_rule_replacement = self.Modify(
messages, args, forwarding_rule, cleared_fields
)
label_update = labels_diff.Apply(labels_value, forwarding_rule.labels)
# Create requests.
requests = []
if forwarding_rule_ref.Collection() == 'compute.globalForwardingRules':
if forwarding_rule_replacement:
request = messages.ComputeGlobalForwardingRulesPatchRequest(
forwardingRule=forwarding_rule_ref.Name(),
forwardingRuleResource=forwarding_rule_replacement,
project=forwarding_rule_ref.project)
requests.append((client.globalForwardingRules, 'Patch', request))
if label_update.needs_update:
request = self._CreateGlobalSetLabelsRequest(messages,
forwarding_rule_ref,
forwarding_rule,
label_update.labels)
requests.append((client.globalForwardingRules, 'SetLabels', request))
else:
if forwarding_rule_replacement:
request = messages.ComputeForwardingRulesPatchRequest(
forwardingRule=forwarding_rule_ref.Name(),
forwardingRuleResource=forwarding_rule_replacement,
project=forwarding_rule_ref.project,
region=forwarding_rule_ref.region)
requests.append((client.forwardingRules, 'Patch', request))
if label_update.needs_update:
request = self._CreateRegionalSetLabelsRequest(messages,
forwarding_rule_ref,
forwarding_rule,
label_update.labels)
requests.append((client.forwardingRules, 'SetLabels', request))
with client.IncludeFields(cleared_fields):
return holder.client.MakeRequests(requests)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class UpdateBeta(UpdateGA):
"""Update a Compute Engine forwarding rule."""
_support_network_tier = False
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(UpdateBeta):
"""Update a Compute Engine forwarding rule."""
_support_network_tier = True
UpdateGA.detailed_help = {
'brief':
'Update a Compute Engine forwarding rule.',
'DESCRIPTION':
"""\
*{command}* updates global access for a Compute Engine forwarding rule.
""",
'EXAMPLES':
"""\
To update the forwarding rule to allow global access, run:
$ {command} example-fr --allow-global-access --region=us-central1
To add/update labels ``k0'' and ``k1'' and remove labels with key ``k3'',
run:
$ {command} example-fr --region=us-central1 \
--update-labels=k0=value1,k1=value2 --remove-labels=k3
Labels can be used to identify the forwarding rule and to filter them as
in
$ {parent_command} list --filter='labels.k1:value2'
To list existing labels, run:
$ {parent_command} describe example-fr --format="default(labels)"
"""
}
UpdateBeta.detailed_help = {
'brief':
'Update a Compute Engine forwarding rule.',
'DESCRIPTION':
"""\
*{command}* updates labels and global access for a Compute
Engine forwarding rule.
""",
'EXAMPLES':
"""\
To update the forwarding rule to allow global access, run:
$ {command} example-fr --allow-global-access --region=us-central1
To add/update labels ``k0'' and ``k1'' and remove labels with key ``k3'',
run:
$ {command} example-fr --region=us-central1 \
--update-labels=k0=value1,k1=value2 --remove-labels=k3
Labels can be used to identify the forwarding rule and to filter them as
in
$ {parent_command} list --filter='labels.k1:value2'
To list existing labels, run:
$ {parent_command} describe example-fr --format="default(labels)"
"""
}
UpdateAlpha.detailed_help = {
'brief':
'Update a Compute Engine forwarding rule.',
'DESCRIPTION':
"""\
*{command}* updates labels, global access and network tier for a Compute
Engine forwarding rule.
""",
'EXAMPLES':
"""\
To update the forwarding rule to allow global access, run:
$ {command} example-fr --allow-global-access --region=us-central1
To add/update labels ``k0'' and ``k1'' and remove labels with key ``k3''
, run:
$ {command} example-fr --region=us-central1 \
--update-labels=k0=value1,k1=value2 --remove-labels=k3
Labels can be used to identify the forwarding rule and to filter them as
in
$ {parent_command} list --filter='labels.k1:value2'
To list existing labels, run:
$ {parent_command} describe example-fr --format="default(labels)"
"""
}