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,42 @@
# -*- 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 addresses."""
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 Addresses(base.Group):
"""Read and manipulate Compute Engine addresses."""
Addresses.category = base.NETWORKING_CATEGORY
Addresses.detailed_help = {
'DESCRIPTION': """
Read and manipulate Compute Engine addresses.
For more information about addresses, see the
[addresses documentation](https://cloud.google.com/compute/docs/ip-addresses/).
See also: [Addresses API](https://cloud.google.com/compute/docs/reference/rest/v1/addresses).
""",
}

View File

@@ -0,0 +1,26 @@
# -*- 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 Compute Engine address 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 Compute Engine address configurations."""

View File

@@ -0,0 +1,38 @@
release_tracks: [ALPHA]
command_type: CONFIG_EXPORT
help_text:
brief: Export the configuration for a Compute Engine address.
description: |
*{command}* exports the configuration for a Compute Engine address.
Address configurations can be exported in
Kubernetes Resource Model (krm) or Terraform HCL formats. The
default format is `krm`.
Specifying `--all` allows you to export the configurations for all
addresses within the project.
Specifying `--path` allows you to export the configuration(s) to
a local directory.
examples: |
To export the configuration for an address, run:
$ {command} my-address
To export the configuration for an address to a file, run:
$ {command} my-address --path=/path/to/dir/
To export the configuration for an address in Terraform
HCL format, run:
$ {command} my-address --resource-format=terraform
To export the configurations for all addresses within a
project, run:
$ {command} --all
arguments:
resource:
help_text: Address to export the configuration for.
spec: !REF googlecloudsdk.command_lib.compute.resources:address

View File

@@ -0,0 +1,458 @@
# -*- 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 reserving IP addresses."""
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 constants
from googlecloudsdk.api_lib.compute import name_generator
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.addresses import flags
import ipaddr
from six.moves import zip # pylint: disable=redefined-builtin
def _Args(cls, parser, support_psc_google_apis):
"""Argument parsing."""
cls.ADDRESSES_ARG = flags.AddressArgument(required=False)
cls.ADDRESSES_ARG.AddArgument(parser, operation_type='create')
flags.AddDescription(parser)
parser.display_info.AddCacheUpdater(flags.AddressesCompleter)
flags.AddAddressesAndIPVersions(parser, required=False)
flags.AddNetworkTier(parser)
flags.AddPrefixLength(parser)
flags.AddPurpose(parser, support_psc_google_apis)
flags.AddIPv6EndPointType(parser)
cls.SUBNETWORK_ARG = flags.SubnetworkArgument()
cls.SUBNETWORK_ARG.AddArgument(parser)
cls.NETWORK_ARG = flags.NetworkArgument()
cls.NETWORK_ARG.AddArgument(parser)
flags.IpCollectionArgument().AddArgument(parser)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
r"""Reserve IP addresses.
*{command}* is used to reserve one or more IP addresses. Once an IP address
is reserved, it will be associated with the project until it is released
using 'gcloud compute addresses delete'. Ephemeral IP addresses that are in
use by resources in the project can be reserved using the '--addresses' flag.
## EXAMPLES
To reserve three IP addresses in the 'us-central1' region, run:
$ {command} address-1 address-2 address-3 --region=us-central1
To reserve ephemeral IP addresses '162.222.181.198' and '23.251.146.189' which
are being used by virtual machine instances in the 'us-central1' region, run:
$ {command} --addresses=162.222.181.198,23.251.146.189 --region=us-central1
In the above invocation, the two addresses will be assigned random names.
To reserve an IP address named subnet-address-1 from the subnet 'default' in
the 'us-central1' region, run:
$ {command} subnet-address-1 \
--region=us-central1 \
--subnet=default
To reserve an IP range '10.110.0.0/16' from the network 'default' for
'VPC_PEERING', run:
$ {command} ip-range-1 --global --addresses=10.110.0.0 --prefix-length=16 \
--purpose=VPC_PEERING --network=default
To reserve any IP range with prefix length '16' from the network 'default' for
'VPC_PEERING', run:
$ {command} ip-range-1 --global --prefix-length=16 --purpose=VPC_PEERING \
--network=default
To reserve an address from network 'default' for PRIVATE_SERVICE_CONNECT, run:
$ {command} psc-address-1 --global --addresses=10.110.0.10 \
--purpose=PRIVATE_SERVICE_CONNECT --network=default
"""
ADDRESSES_ARG = None
SUBNETWORK_ARG = None
NETWORK_ARG = None
_support_psc_google_apis = True
@classmethod
def Args(cls, parser):
_Args(
cls,
parser,
support_psc_google_apis=cls._support_psc_google_apis)
def ConstructNetworkTier(self, messages, args):
if args.network_tier:
network_tier = args.network_tier.upper()
if network_tier in constants.NETWORK_TIER_CHOICES_FOR_INSTANCE:
return messages.Address.NetworkTierValueValuesEnum(args.network_tier)
else:
raise exceptions.InvalidArgumentException(
'--network-tier',
'Invalid network tier [{tier}]'.format(tier=network_tier))
else:
return None
def Run(self, args):
"""Issues requests necessary to create Addresses."""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
names, addresses = self._GetNamesAndAddresses(args)
if not args.name:
args.name = names
address_refs = self.ADDRESSES_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client))
requests = []
for address, address_ref in zip(addresses, address_refs):
address_msg = self.GetAddress(client.messages, args, address, address_ref,
holder.resources)
if address_ref.Collection() == 'compute.globalAddresses':
requests.append((client.apitools_client.globalAddresses, 'Insert',
client.messages.ComputeGlobalAddressesInsertRequest(
address=address_msg, project=address_ref.project)))
elif address_ref.Collection() == 'compute.addresses':
requests.append((client.apitools_client.addresses, 'Insert',
client.messages.ComputeAddressesInsertRequest(
address=address_msg,
region=address_ref.region,
project=address_ref.project)))
return client.MakeRequests(requests)
def _GetNamesAndAddresses(self, args):
"""Returns names and addresses provided in args."""
if not args.addresses and not args.name:
raise exceptions.MinimumArgumentException(
['NAME', '--address'],
'At least one name or address must be provided.')
if args.name:
names = args.name
else:
# If we dont have any names then we must some addresses.
names = [name_generator.GenerateRandomName() for _ in args.addresses]
if args.addresses:
addresses = args.addresses
else:
# If we dont have any addresses then we must some names.
addresses = [None] * len(args.name)
if len(addresses) != len(names):
raise exceptions.BadArgumentException(
'--addresses',
'If providing both, you must specify the same number of names as '
'addresses.')
return names, addresses
def CheckPurposeInSubnetwork(self, messages, purpose):
if (purpose != messages.Address.PurposeValueValuesEnum.GCE_ENDPOINT and
purpose !=
messages.Address.PurposeValueValuesEnum.SHARED_LOADBALANCER_VIP):
raise exceptions.InvalidArgumentException(
'--purpose',
'must be GCE_ENDPOINT or SHARED_LOADBALANCER_VIP for regional '
'internal addresses.')
# TODO(b/266237285): Need to remove exceptions and break down function.
def GetAddress(self, messages, args, address, address_ref, resource_parser):
"""Get and validate address setting.
Retrieve address resource from input arguments and validate the address
configuration for both external/internal IP address reservation/promotion.
Args:
messages: The client message proto includes all required GCE API fields.
args: argparse.Namespace, An object that contains the values for the
arguments specified in the .Args() method.
address: Address object.
address_ref: Reference of the address.
resource_parser: A resource parser used to parse resource name into url.
Returns:
An address resource proto message.
Raises:
ConflictingArgumentsException: If both network and subnetwork fields are
set.
MinimumArgumentException: Missing network or subnetwork with purpose
field.
InvalidArgumentException: The input argument is not set correctly or
unable to be parsed.
RequiredArgumentException: The required argument is missing from user
input.
"""
network_tier = self.ConstructNetworkTier(messages, args)
if args.ip_version or (address is None and address_ref.Collection()
== 'compute.globalAddresses'):
ip_version = messages.Address.IpVersionValueValuesEnum(args.ip_version or
'IPV4')
else:
# IP version is only specified in global and regional external Ipv6
# requests if an address is not specified to determine whether an ipv4 or
# ipv6 address should be allocated.
ip_version = None
if args.subnet and args.network:
raise exceptions.ConflictingArgumentsException('--network', '--subnet')
purpose = None
if args.purpose and not args.network and not args.subnet:
raise exceptions.MinimumArgumentException(['--network', '--subnet'],
' if --purpose is specified')
# TODO(b/36862747): get rid of args.subnet check
if args.subnet:
if address_ref.Collection() == 'compute.globalAddresses':
raise exceptions.BadArgumentException(
'--subnet', '[--subnet] may not be specified for global addresses.')
if not args.subnet_region:
args.subnet_region = address_ref.region
subnetwork_url = flags.SubnetworkArgument().ResolveAsResource(
args, resource_parser).SelfLink()
if not args.endpoint_type:
# External IPv6 reservation does not need purpose field.
purpose = messages.Address.PurposeValueValuesEnum(args.purpose or
'GCE_ENDPOINT')
self.CheckPurposeInSubnetwork(messages, purpose)
else:
subnetwork_url = None
network_url = None
if args.network:
purpose = messages.Address.PurposeValueValuesEnum(args.purpose or
'VPC_PEERING')
network_url = flags.NetworkArgument().ResolveAsResource(
args, resource_parser).SelfLink()
if purpose != messages.Address.PurposeValueValuesEnum.IPSEC_INTERCONNECT:
if address_ref.Collection() == 'compute.addresses':
raise exceptions.InvalidArgumentException(
'--network',
'network may not be specified for regional addresses.')
supported_purposes = {
'VPC_PEERING': messages.Address.PurposeValueValuesEnum.VPC_PEERING
}
if self._support_psc_google_apis:
supported_purposes['PRIVATE_SERVICE_CONNECT'] = (
messages.Address.PurposeValueValuesEnum.PRIVATE_SERVICE_CONNECT
)
if purpose not in supported_purposes.values():
raise exceptions.InvalidArgumentException(
'--purpose', 'must be {} for '
'global internal addresses.'.format(' or '.join(
supported_purposes.keys())))
ipv6_endpoint_type = None
if args.endpoint_type:
ipv6_endpoint_type = messages.Address.Ipv6EndpointTypeValueValuesEnum(
args.endpoint_type)
address_type = None
if args.endpoint_type:
address_type = messages.Address.AddressTypeValueValuesEnum.EXTERNAL
elif subnetwork_url or network_url:
address_type = messages.Address.AddressTypeValueValuesEnum.INTERNAL
if address is not None:
try:
ip_address = ipaddr.IPAddress(address)
except ValueError:
raise exceptions.InvalidArgumentException(
'--addresses', 'Invalid IP address {e}'.format(e=address)
)
if args.prefix_length:
if address and not address_type:
# This is address promotion.
address_type = messages.Address.AddressTypeValueValuesEnum.EXTERNAL
elif (
(address is None or ip_address.version != 6)
and purpose != messages.Address.PurposeValueValuesEnum.VPC_PEERING
and purpose
!= messages.Address.PurposeValueValuesEnum.IPSEC_INTERCONNECT
):
raise exceptions.InvalidArgumentException(
'--prefix-length',
'can only be used with [--purpose VPC_PEERING/IPSEC_INTERCONNECT]'
' or Internal/External IPv6 reservation. Found {e}'.format(
e=purpose
),
)
if not args.prefix_length:
if purpose == messages.Address.PurposeValueValuesEnum.VPC_PEERING:
raise exceptions.RequiredArgumentException(
'--prefix-length',
'prefix length is needed for reserving VPC peering IP ranges.')
if purpose == messages.Address.PurposeValueValuesEnum.IPSEC_INTERCONNECT:
raise exceptions.RequiredArgumentException(
'--prefix-length', 'prefix length is needed for reserving IP ranges'
' for HA VPN over Cloud Interconnect.')
address_msg = messages.Address(
address=address,
prefixLength=args.prefix_length,
description=args.description,
networkTier=network_tier,
ipVersion=ip_version,
name=address_ref.Name(),
addressType=address_type,
purpose=purpose,
subnetwork=subnetwork_url,
network=network_url,
ipv6EndpointType=ipv6_endpoint_type)
if args.ip_collection:
address_msg.ipCollection = flags.IpCollectionArgument().ResolveAsResource(
args, resource_parser).SelfLink()
return address_msg
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class CreateBeta(Create):
# pylint: disable=line-too-long
r"""Reserve IP addresses.
*{command}* is used to reserve one or more IP addresses. Once an IP address
is reserved, it will be associated with the project until it is released
using 'gcloud compute addresses delete'. Ephemeral IP addresses that are in
use by resources in the project can be reserved using the '--addresses' flag.
## EXAMPLES
To reserve three IP addresses in the 'us-central1' region, run:
$ {command} address-1 address-2 address-3 --region=us-central1
To reserve ephemeral IP addresses '162.222.181.198' and '23.251.146.189' which
are being used by virtual machine instances in the 'us-central1' region, run:
$ {command} --addresses=162.222.181.198,23.251.146.189 --region=us-central1
In the above invocation, the two addresses will be assigned random names.
To reserve an IP address named subnet-address-1 from the subnet 'default' in
the 'us-central1' region, run:
$ {command} subnet-address-1 --region=us-central1 --subnet=default
To reserve an IP address that can be used by multiple internal load balancers
from the subnet 'default' in the 'us-central1' region, run:
$ {command} shared-address-1 --region=us-central1 --subnet=default \
--purpose=SHARED_LOADBALANCER_VIP
To reserve an IP range '10.110.0.0/16' from the network 'default' for
'VPC_PEERING', run:
$ {command} ip-range-1 --global --addresses=10.110.0.0 --prefix-length=16 \
--purpose=VPC_PEERING --network=default
To reserve any IP range with prefix length '16' from the network 'default' for
'VPC_PEERING', run:
$ {command} ip-range-1 --global --prefix-length=16 --purpose=VPC_PEERING \
--network=default
To reserve an address from network 'default' for PRIVATE_SERVICE_CONNECT, run:
$ {command} psc-address-1 --global --addresses=10.110.0.10 \
--purpose=PRIVATE_SERVICE_CONNECT --network=default
"""
_support_psc_google_apis = True
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(CreateBeta):
# pylint: disable=line-too-long
r"""Reserve IP addresses.
*{command}* is used to reserve one or more IP addresses. Once an IP address
is reserved, it will be associated with the project until it is released
using 'gcloud compute addresses delete'. Ephemeral IP addresses that are in
use by resources in the project can be reserved using the '--addresses' flag.
## EXAMPLES
To reserve three IP addresses in the 'us-central1' region, run:
$ {command} address-1 address-2 address-3 --region=us-central1
To reserve ephemeral IP addresses '162.222.181.198' and '23.251.146.189' which
are being used by virtual machine instances in the 'us-central1' region, run:
$ {command} --addresses=162.222.181.198,23.251.146.189 --region=us-central1
In the above invocation, the two addresses will be assigned random names.
To reserve an IP address named subnet-address-1 from the subnet 'default' in
the 'us-central1' region, run:
$ {command} subnet-address-1 --region=us-central1 --subnet=default
To reserve an IP address that can be used by multiple internal load balancers
from the subnet 'default' in the 'us-central1' region, run:
$ {command} shared-address-1 --region=us-central1 --subnet=default \
--purpose=SHARED_LOADBALANCER_VIP
To reserve an IP range '10.110.0.0/16' from the network 'default' for
'VPC_PEERING', run:
$ {command} ip-range-1 --global --addresses=10.110.0.0 --prefix-length=16 \
--purpose=VPC_PEERING --network=default
To reserve any IP range with prefix length '16' from the network 'default' for
'VPC_PEERING', run:
$ {command} ip-range-1 --global --prefix-length=16 --purpose=VPC_PEERING \
--network=default
To reserve an address from network 'default' for PRIVATE_SERVICE_CONNECT, run:
$ {command} psc-address-1 --global --addresses=10.110.0.10 \
--purpose=PRIVATE_SERVICE_CONNECT --network=default
"""
_support_psc_google_apis = True

View File

@@ -0,0 +1,83 @@
# -*- 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 addresses."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.addresses import flags
@base.UniverseCompatible
class Delete(base.DeleteCommand):
r"""Release reserved IP addresses.
*{command}* releases one or more Compute Engine IP addresses.
## EXAMPLES
To release an address with the name 'address-name', run:
$ {command} address-name
To release two addresses with the names 'address-name1' and 'address-name2',
run:
$ {command} address-name1 address-name2
"""
ADDRESSES_ARG = None
@classmethod
def Args(cls, parser):
cls.ADDRESSES_ARG = flags.AddressArgument(required=True)
cls.ADDRESSES_ARG.AddArgument(parser, operation_type='delete')
parser.display_info.AddCacheUpdater(flags.AddressesCompleter)
def Run(self, args):
"""Issues requests necessary to delete Addresses."""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
address_refs = self.ADDRESSES_ARG.ResolveAsResource(
args, holder.resources,
default_scope=compute_scope.ScopeEnum.REGION,
scope_lister=compute_flags.GetDefaultScopeLister(client))
utils.PromptForDeletion(address_refs)
requests = []
for address_ref in address_refs:
if address_ref.Collection() == 'compute.globalAddresses':
request = client.messages.ComputeGlobalAddressesDeleteRequest(
address=address_ref.Name(),
project=address_ref.project,
)
requests.append((client.apitools_client.globalAddresses, 'Delete',
request))
elif address_ref.Collection() == 'compute.addresses':
request = client.messages.ComputeAddressesDeleteRequest(
address=address_ref.Name(),
project=address_ref.project,
region=address_ref.region,
)
requests.append((client.apitools_client.addresses, 'Delete', request))
return client.MakeRequests(requests)

View File

@@ -0,0 +1,69 @@
# -*- 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 addresses."""
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.addresses import flags
class Describe(base.DescribeCommand):
r"""Display detailed information about a reserved static address.
*{command}* displays all data associated with a reserved static address in a
project.
## EXAMPLES
To get details about a global address, run:
$ {command} my-address-name --global
To get details about a regional address, run:
$ {command} my-address-name --region=us-central1
"""
ADDRESS_ARG = None
@staticmethod
def Args(parser):
Describe.ADDRESS_ARG = flags.AddressArgument(plural=False)
Describe.ADDRESS_ARG.AddArgument(parser, operation_type='describe')
def Run(self, args):
"""Issues request necessary to describe the Addresses."""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
address_ref = Describe.ADDRESS_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(client))
if address_ref.Collection() == 'compute.addresses':
service = client.apitools_client.addresses
request = client.messages.ComputeAddressesGetRequest(
**address_ref.AsDict())
elif address_ref.Collection() == 'compute.globalAddresses':
service = client.apitools_client.globalAddresses
request = client.messages.ComputeGlobalAddressesGetRequest(
**address_ref.AsDict())
return client.MakeRequests([(service, 'Get', request)])[0]

View File

@@ -0,0 +1,104 @@
# -*- 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 addresses."""
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.addresses import flags
import six
def _TransformAddressRange(resource):
prefix_length = resource.get('prefixLength')
address = resource.get('address')
if prefix_length:
return address + '/' + six.text_type(prefix_length)
return address
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.GA,
base.ReleaseTrack.ALPHA)
class List(base.ListCommand):
"""List addresses."""
@staticmethod
def Args(parser):
parser.display_info.AddFormat("""\
table(
name,
address_range():label=ADDRESS/RANGE,
address_type:label=TYPE,
purpose,
network.basename(),
region.basename(),
subnetwork.basename():label=SUBNET,
status
)""")
lister.AddMultiScopeListerFlags(parser, regional=True, global_=True)
parser.display_info.AddCacheUpdater(flags.AddressesCompleter)
parser.display_info.AddTransforms({'address_range': _TransformAddressRange})
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
request_data = lister.ParseMultiScopeFlags(args, holder.resources)
list_implementation = lister.MultiScopeLister(
client,
regional_service=client.apitools_client.addresses,
global_service=client.apitools_client.globalAddresses,
aggregation_service=client.apitools_client.addresses)
return lister.Invoke(request_data, list_implementation)
List.detailed_help = {
'brief':
'List addresses',
'DESCRIPTION':
"""
*{command}* lists summary information of addresses in a project. The
*--uri* option can be used to display URIs instead. Users who want to
see more data should use `gcloud compute addresses describe`.
By default, global addresses and addresses from all regions are listed.
The results can be narrowed down by providing the *--regions* or
*--global* flag.
""",
'EXAMPLES':
"""
To list all addresses in a project in table form, run:
$ {command}
To list the URIs of all addresses in a project, run:
$ {command} --uri
To list all of the global addresses in a project, run:
$ {command} --global
To list all of the addresses from the ``us-central1'' region, run:
$ {command} --filter=region:us-central1
""",
}

View File

@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 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 moving addresses."""
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.addresses import flags
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA
)
class Move(base.SilentCommand):
"""Move an address to another project.
## EXAMPLES
The following command moves address `external-ip1` in region `us-central1` to
project `test-playground` with new address name `test-ip1`:
$ {command} external-ip1 --new-name=test-ip1
--target-project=test-playground --region=us-central1
"""
ADDRESS_ARG = None
@classmethod
def Args(cls, parser):
cls.ADDRESS_ARG = flags.AddressArgument(plural=False)
cls.ADDRESS_ARG.AddArgument(parser)
flags.AddMoveArguments(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
address_ref = self.ADDRESS_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(holder.client))
new_name = args.new_name if args.new_name is not None else address_ref.Name(
)
messages = holder.client.messages
if address_ref.Collection() == 'compute.globalAddresses':
address_url = 'projects/{}/global/addresses/{}'.format(
args.target_project, new_name)
request_msg = messages.ComputeGlobalAddressesMoveRequest(
address=address_ref.Name(),
project=address_ref.project,
globalAddressesMoveRequest=messages.GlobalAddressesMoveRequest(
description=args.description,
destinationAddress=address_url,
),
)
request = (holder.client.apitools_client.globalAddresses, 'Move',
request_msg)
else:
address_url = 'projects/{}/regions/{}/addresses/{}'.format(
args.target_project, address_ref.region, new_name)
request_msg = messages.ComputeAddressesMoveRequest(
region=address_ref.region,
address=address_ref.Name(),
project=address_ref.project,
regionAddressesMoveRequest=messages.RegionAddressesMoveRequest(
description=args.description,
destinationAddress=address_url,
),
)
request = (holder.client.apitools_client.addresses, 'Move', request_msg)
return holder.client.MakeRequests([request],
project_override=args.target_project)

View File

@@ -0,0 +1,124 @@
# -*- 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 labels for addresses."""
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.operations import poller
from googlecloudsdk.api_lib.util import waiter
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.addresses import flags
from googlecloudsdk.command_lib.util.args import labels_util
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
class Update(base.UpdateCommand):
r"""Update a Compute Engine address.
*{command}* updates labels for a Compute Engine
address.
## EXAMPLES
To add/update labels 'k0' and 'k1' and remove labels with key 'k3' for address
'example-address', run:
$ {command} example-address --region=us-central1 \
--update-labels=k0=value1,k1=value2 --remove-labels=k3
Labels can be used to identify the address and to filter them as in:
$ {parent_command} list --filter='labels.k1:value2'
To list existing labels for address 'example-address', run:
$ {parent_command} describe example-address --format="default(labels)"
"""
ADDRESS_ARG = None
@classmethod
def Args(cls, parser):
cls.ADDRESS_ARG = flags.AddressArgument(plural=False)
cls.ADDRESS_ARG.AddArgument(parser)
labels_util.AddUpdateLabelsFlags(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client.apitools_client
messages = holder.client.messages
address_ref = self.ADDRESS_ARG.ResolveAsResource(
args,
holder.resources,
scope_lister=compute_flags.GetDefaultScopeLister(holder.client))
labels_diff = labels_util.Diff.FromUpdateArgs(args)
if not labels_diff.MayHaveUpdates():
raise calliope_exceptions.RequiredArgumentException(
'LABELS', 'At least one of --update-labels or '
'--remove-labels must be specified.')
if address_ref.Collection() == 'compute.globalAddresses':
address = client.globalAddresses.Get(
messages.ComputeGlobalAddressesGetRequest(**address_ref.AsDict()))
labels_value = messages.GlobalSetLabelsRequest.LabelsValue
else:
address = client.addresses.Get(
messages.ComputeAddressesGetRequest(**address_ref.AsDict()))
labels_value = messages.RegionSetLabelsRequest.LabelsValue
labels_update = labels_diff.Apply(labels_value, address.labels)
if not labels_update.needs_update:
return address
if address_ref.Collection() == 'compute.globalAddresses':
request = messages.ComputeGlobalAddressesSetLabelsRequest(
project=address_ref.project,
resource=address_ref.Name(),
globalSetLabelsRequest=messages.GlobalSetLabelsRequest(
labelFingerprint=address.labelFingerprint,
labels=labels_update.labels))
operation = client.globalAddresses.SetLabels(request)
operation_ref = holder.resources.Parse(
operation.selfLink, collection='compute.globalOperations')
operation_poller = poller.Poller(client.globalAddresses)
else:
request = messages.ComputeAddressesSetLabelsRequest(
project=address_ref.project,
resource=address_ref.Name(),
region=address_ref.region,
regionSetLabelsRequest=messages.RegionSetLabelsRequest(
labelFingerprint=address.labelFingerprint,
labels=labels_update.labels))
operation = client.addresses.SetLabels(request)
operation_ref = holder.resources.Parse(
operation.selfLink, collection='compute.regionOperations')
operation_poller = poller.Poller(client.addresses)
return waiter.WaitFor(
operation_poller, operation_ref,
'Updating labels of address [{0}]'.format(address_ref.Name()))