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,31 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 ha-controllers."""
from googlecloudsdk.calliope import base
@base.Hidden
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class HaControllers(base.Group):
"""Manage HA Controllers.
Manage High Availability (HA) Controllers. An HA Controller is a regional
resource that provides high availability for a virtual machine (VM) instance
in case of a zonal outage by offering a failover path to a VM in another zone.
"""
category = base.COMPUTE_CATEGORY

View File

@@ -0,0 +1,242 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 create an HA Controller."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import textwrap
from googlecloudsdk.api_lib.compute import base_classes
from googlecloudsdk.api_lib.compute.ha_controllers import utils as api_utils
from googlecloudsdk.api_lib.compute.operations import poller
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute.ha_controllers import utils
from googlecloudsdk.command_lib.util.apis import arg_utils
from googlecloudsdk.core import exceptions as core_exceptions
from googlecloudsdk.core import log
_NODE_AFFINITY_FILE_HELP_TEXT = textwrap.dedent("""\
The JSON/YAML file containing the configuration of desired nodes onto
which instance in this zone could be scheduled. These rules filter the nodes
according to their node affinity labels. A node's affinity labels come
from the node template of the group the node is in.
The file should contain a list of a JSON/YAML objects. For an example,
see https://cloud.google.com/compute/docs/nodes/provisioning-sole-tenant-vms#configure_node_affinity_labels.
The following list describes the fields:
*key*::: Corresponds to the node affinity label keys of
the Node resource.
*operator*::: Specifies the node selection type. Must be one of:
`IN`: Requires Compute Engine to seek for matched nodes.
`NOT_IN`: Requires Compute Engine to avoid certain nodes.
*values*::: Optional. A list of values which correspond to the node
affinity label values of the Node resource.
""")
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Create(base.CreateCommand):
"""Create an HA Controller.
Create an High Availability (HA) Controller, which helps
ensure that a virtual machine (VM) instance remains operational by
automatically managing failover across two zones.
"""
@staticmethod
def Args(parser):
base.ASYNC_FLAG.AddToParser(parser)
utils.AddHaControllerNameArgToParser(
parser, base.ReleaseTrack.ALPHA.name.lower()
)
messages = utils.GetMessagesModule('alpha')
parser.add_argument(
'--description',
help=(
'An optional, user-provided description for the HA Controller to'
' help identify its purpose.'
),
)
parser.add_argument(
'--instance-name',
help=(
'The name of the existing VM that the HA Controller manages. This'
' VM must already exist in one of the zones specified in'
' --zone-configuration.'
),
)
parser.add_argument(
'--failover-initiation',
required=True,
type=lambda x: arg_utils.ChoiceToEnum(
x,
messages.HaController.FailoverInitiationValueValuesEnum,
),
help=(
'Specifies how a failover is triggered. Set to MANUAL_ONLY if you'
' want to trigger failovers yourself. Must be one of:'
f' {utils.EnumTypeToChoices(messages.HaController.FailoverInitiationValueValuesEnum)}'
),
)
parser.add_argument(
'--secondary-zone-capacity',
required=True,
type=lambda x: arg_utils.ChoiceToEnum(
x,
messages.HaController.SecondaryZoneCapacityValueValuesEnum,
),
help=(
'Determines the capacity guarantee in the secondary zone. Use'
' BEST_EFFORT to create a VM based on capacity availability at the'
' time of failover, suitable for workloads that can tolerate longer'
' recovery times. Must be one of:'
f' {utils.EnumTypeToChoices(messages.HaController.SecondaryZoneCapacityValueValuesEnum)}'
),
)
parser.add_argument(
'--zone-configuration',
required=True,
type=arg_parsers.ArgObject(
enable_file_upload=False,
spec={
'reservation': arg_parsers.ArgObject(
value_type=str,
help_text=(
'Specifies the reservation name. The reservation must'
' exist within the HA Controller region.'
),
),
'reservation-affinity': arg_parsers.ArgObject(
value_type=lambda x: arg_utils.ChoiceToEnum(
x,
messages.HaControllerZoneConfigurationReservationAffinity.ConsumeReservationTypeValueValuesEnum,
),
help_text=(
'Specifies the reservation-affinity value.'
' Must be one of:'
f' {utils.EnumTypeToChoices(messages.HaControllerZoneConfigurationReservationAffinity.ConsumeReservationTypeValueValuesEnum)}'
),
),
'node': arg_parsers.ArgObject(
value_type=str,
help_text=(
'Specifies the node name. The node must exist within'
' the HA Controller region.'
),
),
'node-group': arg_parsers.ArgObject(
value_type=str,
help_text=(
'Specifies the node-group name. The node-group must'
' exist within the HA Controller region. Must be one'
' of:'
f' {utils.EnumTypeToChoices(messages.HaControllerZoneConfigurationNodeAffinity.OperatorValueValuesEnum)}'
),
),
'node-affinity-file': arg_parsers.ArgObject(
value_type=arg_parsers.FileContents(),
enable_file_upload=False,
help_text=_NODE_AFFINITY_FILE_HELP_TEXT,
),
'node-project': arg_parsers.ArgObject(
value_type=str,
help_text=(
'Specifies the name of the project with shared sole'
' tenant node groups to create an instance in.'
),
),
'zone': arg_parsers.ArgObject(
value_type=str,
help_text=(
'Specifies the zone. The zone must be within the HA'
' Controller region.'
),
),
},
),
action=arg_parsers.FlattenAction(),
help=(
'Configures the two zones for the HA Controller and specifies how'
' VM capacity is reserved in each zone. You must provide two zone'
' configurations. You can also specify an existing reservation or'
' node-group to guarantee capacity.'
),
)
parser.add_argument(
'--network-auto-configuration',
required=False,
type=arg_parsers.ArgObject(
spec={
'stack-type': arg_parsers.ArgObject(
value_type=lambda x: arg_utils.ChoiceToEnum(
x,
messages.HaControllerNetworkingAutoConfigurationInternal.StackTypeValueValuesEnum),
help_text=(
'Specifies the stack type for the network'
' configuration. Must match the stack type of the'
' instance. Must be one of:'
f' {utils.EnumTypeToChoices(messages.HaControllerNetworkingAutoConfigurationInternal.StackTypeValueValuesEnum)}'
),
),
'address': arg_parsers.ArgObject(
value_type=str,
help_text=(
'Specifies an optional IPv4 address to assign to'
' the instance. If not specified, an ephemeral IP will'
' be generated.'
),
),
'internal-ipv6-address': arg_parsers.ArgObject(
value_type=str,
help_text=(
'Specifies an optional IPv6 address to assign to'
' the instance. If not specified, an ephemeral IP will'
' be generated.'
),
),
},
),
action=arg_parsers.FlattenAction(),
help=(
'Adds a network interface to the instance.'
),
)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
ha_controller_ref = args.CONCEPTS.ha_controller.Parse()
ha_controller = client.messages.HaController(
name=ha_controller_ref.Name(),
region=ha_controller_ref.region,
description=args.description,
instanceName=args.instance_name,
failoverInitiation=args.failover_initiation,
secondaryZoneCapacity=args.secondary_zone_capacity,
zoneConfigurations=utils.MakeZoneConfiguration(args.zone_configuration),
networkingAutoConfiguration=utils.MakeNetworkConfiguration(
args.network_auto_configuration
),
)
return api_utils.Insert(
holder, ha_controller, ha_controller_ref, args.async_
)

View File

@@ -0,0 +1,27 @@
- release_tracks: [ALPHA]
help_text:
brief: Permanently delete a specified HA Controller.
description: Delete an High Availability (HA) Controller to permanently remove the high availability and failover capabilities from the associated virtual machine (VM) instance.
examples: |
To delete an HA Controller named `my-ha-controller` in the `us-central1` region, run the following command:
$ {command} my-ha-controller \
--region=us-central1
request:
api_version: alpha
collection: compute.haControllers
method: delete
async:
collection: compute.regionOperations
response_name_field: selfLink
state:
field: status
success_values: ['DONE']
arguments:
resource:
help_text: The HA Controller that you want to delete.
spec: !REF googlecloudsdk.command_lib.compute.ha_controllers.resources:ha_controller
is_positional: true

View File

@@ -0,0 +1,20 @@
- release_tracks: [ALPHA]
help_text:
brief: View the details and configuration of a specified HA Controller.
description: Describe an High Availability (HA) Controller to view its details and configurations.
examples: |
To view the details of an HA Controller named `my-ha-controller` in the `us-central1` region, run the following command:
$ {command} my-ha-controller \
--region=us-central1
request:
api_version: alpha
collection: compute.haControllers
method: get
arguments:
resource:
help_text: The HA Controller that you want to describe.
spec: !REF googlecloudsdk.command_lib.compute.ha_controllers.resources:ha_controller
is_positional: true

View File

@@ -0,0 +1,108 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 export an HA Controller to a YAML file."""
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.ha_controllers import utils as api_utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute.ha_controllers import utils
from googlecloudsdk.command_lib.export import util as export_util
from googlecloudsdk.core import log
from googlecloudsdk.core import yaml
from googlecloudsdk.core.util import files
def _DetailedHelp():
return {
'brief':
'Export an HA Controller.',
'DESCRIPTION':
"""\
Exports an High Availability (HA) Controller's configuration to a
file. This configuration can be imported at a later time.
""",
'EXAMPLES':
"""\
An HA Controller can be exported by running:
$ {command} my-ha-controller --destination=<path-to-file>
"""
}
def _GetApiVersion(release_track):
"""Returns the API version for the HA Controller."""
if release_track == base.ReleaseTrack.ALPHA:
return 'alpha'
def _GetSchemaPath(release_track, for_help=False):
"""Returns the schema path for the HA Controller."""
return export_util.GetSchemaPath(
'compute',
_GetApiVersion(release_track),
'HaController',
for_help=for_help,
)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Export(base.ExportCommand):
"""Export an HA Controller.
Export an High Availability (HA) Controller, which helps
ensure that a virtual machine (VM) instance remains operational by
automatically managing failover across two zones.
"""
detailed_help = _DetailedHelp()
@staticmethod
def Args(parser):
utils.AddHaControllerNameArgToParser(
parser, base.ReleaseTrack.ALPHA.name.lower()
)
export_util.AddExportFlags(
parser, _GetSchemaPath(base.ReleaseTrack.ALPHA, for_help=True))
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
ha_controller_ref = args.CONCEPTS.ha_controller.Parse()
ha_controller = api_utils.Get(client, ha_controller_ref)
yaml_data = yaml.load(export_util.Export(
message=ha_controller, schema_path=_GetSchemaPath(self.ReleaseTrack())
))
yaml_data = utils.FixExportStructure(yaml_data)
if args.destination:
with files.FileWriter(args.destination) as stream:
yaml.dump(yaml_data, stream=stream)
return log.status.Print(
'Exported [{}] to \'{}\'.'.format(
ha_controller.name, args.destination
)
)
else:
yaml.dump(yaml_data, stream=sys.stdout)

View File

@@ -0,0 +1,35 @@
- release_tracks: [ALPHA]
help_text:
brief: Initiate the failover of the virtual machine (VM) instance to a designated failover zone.
description: Initiate the failover of the VM to a designated zone by using a High Availability (HA) Controller. Regional disks attached to the other preconfigured zone are included in this failover.
examples: |
To trigger the failover of HA Controller `my-ha-controller` to zone `us-central1-a`, run the following command:
$ {command} my-ha-controller \
--region=us-central1 \
--failover-to-zone=us-central1-a
request:
api_version: alpha
collection: compute.haControllers
method: failover
async:
collection: compute.regionOperations
response_name_field: selfLink
state:
field: status
success_values: ['DONE']
arguments:
resource:
help_text: The HA Controller that you want to failover.
spec: !REF googlecloudsdk.command_lib.compute.ha_controllers.resources:ha_controller
is_positional: true
params:
- arg_name: failover-to-zone
api_field: haControllersFailoverRequest.failoverToZone
required: true
help_text: |
The destination zone for the failover. This must be the pre-configured secondary zone for the HA Controller.

View File

@@ -0,0 +1,156 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 import an HA Controller to a YAML file."""
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.ha_controllers import utils as api_utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute.ha_controllers import utils
from googlecloudsdk.command_lib.export import util as export_util
from googlecloudsdk.core import log
from googlecloudsdk.core import yaml
from googlecloudsdk.core.console import console_io
def _DetailedHelp():
return {
'brief':
'Import an HA Controller.',
'DESCRIPTION':
"""\
Imports an High Availability (HA) Controller's configuration from a
file.
""",
'EXAMPLES':
"""\
An HA Controller can be imported by running:
$ {command} my-ha-controller --source=<path-to-file>
"""
}
def _GetApiVersion(release_track):
"""Returns the API version for the HA Controller."""
if release_track == base.ReleaseTrack.ALPHA:
return 'alpha'
def _GetSchemaPath(release_track, for_help=False):
"""Returns the schema path for the HA Controller."""
return export_util.GetSchemaPath(
'compute',
_GetApiVersion(release_track),
'HaController',
for_help=for_help,
)
def _CompareHaControllers(old_ha_controller, new_ha_controller):
"""Compares existing HA Controller with the imported one to see if a patch is needed."""
for field_name, new_value in new_ha_controller.items():
old_value = old_ha_controller.get(field_name)
if new_value != old_value:
return True
return False
def _ReadResourceFromYaml(yaml_data, release_track):
"""Reads, validates and fixes structure of the YAML data."""
data = console_io.ReadFromFileOrStdin(yaml_data, binary=False)
yaml_data = yaml.load(data)
export_util.ValidateYAML(
yaml_data, _GetSchemaPath(release_track)
)
yaml_data = utils.FixImportStructure(yaml_data)
return yaml_data
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Import(base.ImportCommand):
"""Import an HA Controller.
Import an High Availability (HA) Controller, which helps
ensure that a virtual machine (VM) instance remains operational by
automatically managing failover across two zones.
"""
@staticmethod
def Args(parser):
base.ASYNC_FLAG.AddToParser(parser)
utils.AddHaControllerNameArgToParser(
parser, base.ReleaseTrack.ALPHA.name.lower()
)
export_util.AddImportFlags(
parser, _GetSchemaPath(base.ReleaseTrack.ALPHA, for_help=True))
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
ha_controller_ref = args.CONCEPTS.ha_controller.Parse()
# Import HA Controller from YAML file.
yaml_data = _ReadResourceFromYaml(args.source or '-', self.ReleaseTrack())
ha_controller = export_util.Import(
message_type=client.messages.HaController,
stream=yaml.dump(yaml_data),
)
ha_controller.name = ha_controller_ref.Name()
ha_controller.region = ha_controller_ref.region
# Try to get the existing HA Controller.
try:
old_ha_controller = api_utils.Get(client, ha_controller_ref)
old_ha_controller = yaml.load(
export_util.Export(
message=old_ha_controller,
schema_path=_GetSchemaPath(self.ReleaseTrack()),
)
)
except apitools_exceptions.HttpError as error:
if error.status_code != 404:
raise error
# HA Controller does not exist, create a new one.
return api_utils.Insert(
holder, ha_controller, ha_controller_ref, args.async_
)
has_diff = _CompareHaControllers(old_ha_controller, yaml_data)
if not has_diff:
# No change in the fields provided in the import file, do not send
# requests to server.
log.status.Print(
'No changes detected in the HA Controller [{0}]. Skipping update.'
.format(ha_controller_ref.Name())
)
return
console_io.PromptContinue(
message=('HA Controller [{0}] will be overwritten.').format(
ha_controller_ref.Name()
),
cancel_on_no=True,
)
return api_utils.Patch(
holder, ha_controller, ha_controller_ref, args.async_
)

View File

@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""List Compute Engine HA Controllers."""
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.api_lib.compute import utils
from googlecloudsdk.calliope import base
RESOURCE_TYPE = 'HA Controllers'
DETAILED_HELP = {
'brief':
'List Compute Engine ' + RESOURCE_TYPE,
'DESCRIPTION':
"""\
*{{command}}* displays all Compute Engine {0} in a project.
""".format(RESOURCE_TYPE)
}
EXAMPLE_FORMAT = """\
To list all {0} in a project in table form, run:
$ {{command}}
To list {0} in specific regions only in table form, run:
$ {{command}} --regions=REGION1,REGION2...
To list the URIs of all {0} in a project, run:
$ {{command}} --uri
"""
def _TransformSecondaryZone(resource):
"""Returns the secondary zone for the HA Controller."""
if (
not resource
or not resource.get('status')
or not resource['status'].get('zoneStatus')
):
return ''
for zone, config in resource['status']['zoneStatus'].items():
if not config['isPrimary']:
return zone
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class List(base.ListCommand):
"""List Compute Engine HA Controllers."""
@staticmethod
def Args(parser):
parser.display_info.AddFormat("""\
table(
name,
region.basename(),
status.primaryZone,
secondaryZone(),
instanceName,
status.ongoingFailover,
failoverInitiation,
secondaryZoneCapacity
)""")
parser.display_info.AddUriFunc(utils.MakeGetUriFunc())
parser.display_info.AddTransforms({
'secondaryZone': _TransformSecondaryZone,
})
lister.AddRegionsArg(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
request_data = lister.ParseRegionalFlags(args, holder.resources)
list_implementation = lister.RegionalLister(
client, client.apitools_client.haControllers
)
return lister.Invoke(request_data, list_implementation)
List.detailed_help = DETAILED_HELP.copy()
List.detailed_help['EXAMPLES'] = EXAMPLE_FORMAT.format(RESOURCE_TYPE)

View File

@@ -0,0 +1,48 @@
- release_tracks: [ALPHA]
help_text:
brief: Update the settings of an existing HA Controller.
description: Update an High Availability (HA) Controller to, for example, change the existing HA Controller failover initiation configuration from automatic to manual, or vice-versa.
examples: |
To update the description of an HA Controller named `my-ha-controller` in the `us-central1` region, run the following command:
$ {command} my-ha-controller \
--description="new description" \
--region=us-central1
request:
api_version: alpha
collection: compute.haControllers
method: patch
modify_request_hooks:
- googlecloudsdk.command_lib.compute.ha_controllers.utils:SetResourceName
async:
collection: compute.regionOperations
response_name_field: selfLink
state:
field: status
success_values: ['DONE']
arguments:
resource:
help_text: The HA Controller that you want to update.
spec: !REF googlecloudsdk.command_lib.compute.ha_controllers.resources:ha_controller
is_positional: true
params:
- group:
required: true
mutex: false
params:
- arg_name: description
api_field: haControllerResource.description
help_text: |
Updates the text description of the HA controller.
- arg_name: failover-initiation
api_field: haControllerResource.failoverInitiation
help_text: |
Changes the failover trigger between AUTOMATIC and MANUAL_ONLY.
- arg_name: secondary-zone-capacity
api_field: haControllerResource.secondaryZoneCapacity
help_text: |
Changes the capacity guarantee in the secondary zone between GUARANTEED_STOPPED and BEST_EFFORT.