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,40 @@
# -*- coding: utf-8 -*- #
# Copyright 2018 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 Compute Engine reservations."""
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 Reservations(base.Group):
"""Manage Compute Engine reservations."""
category = base.COMPUTE_CATEGORY
Reservations.detailed_help = {
'DESCRIPTION': """
Manage Compute Engine reservations.
For more information about reservations, see the
[reservations documentation](https://cloud.google.com/compute/docs/instances/reserving-zonal-resources).
See also: [Reservations API](https://cloud.google.com/compute/docs/reference/rest/v1/reservations).
""",
}

View File

@@ -0,0 +1,43 @@
release_tracks: [ALPHA, BETA, GA]
help_text:
brief: Add IAM policy binding to a Compute Engine reservation.
description: |
Add an IAM policy binding to the IAM policy of a Compute Engine reservation. One binding consists of a member,
a role, and an optional condition.
examples: |
To add an IAM policy binding for the role of 'roles/compute.securityAdmin' for the user 'test-user@gmail.com'
with reservation 'my-reservation' and zone 'ZONE', run:
$ {command} my-reservation --zone=ZONE --member='user:test-user@gmail.com' --role='roles/compute.securityAdmin'
To add an IAM policy binding which expires at the end of the year 2018 for the role of
'roles/compute.securityAdmin' and the user 'test-user@gmail.com' with reservation 'my-reservation' and zone 'ZONE', run:
$ {command} my-reservation --zone=ZONE --member='user:test-user@gmail.com' --role='roles/compute.securityAdmin' --condition='expression=request.time < timestamp("2019-01-01T00:00:00Z"),title=expires_end_of_2018,description=Expires at midnight on 2018-12-31'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
request:
collection: compute.reservations
use_relative_name: false
api_version: v1
BETA:
api_version: beta
ALPHA:
api_version: alpha
arguments:
resource:
help_text: The reservation for which to add IAM policy binding to.
spec: !REF googlecloudsdk.command_lib.compute.resources:reservation
iam:
set_iam_policy_request_path: zoneSetPolicyRequest
message_type_overrides:
policy: Policy
set_iam_policy_request: ComputeReservationsSetIamPolicyRequest
enable_condition: true
policy_version: 3
get_iam_policy_version_path: optionsRequestedPolicyVersion

View File

@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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 Compute Engine reservation blocks."""
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 ReservationBlocks(base.Group):
"""Manage Compute Engine reservation blocks."""
category = base.COMPUTE_CATEGORY
detailed_help = {
'DESCRIPTION': """
Manage Compute Engine reservation blocks.
""",
}

View File

@@ -0,0 +1,89 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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 reservation blocks."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations.blocks import flags
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe a Compute Engine reservation block."""
@staticmethod
def Args(parser):
Describe.ReservationArg = (
resource_args.GetReservationResourceArg()
)
Describe.ReservationArg.AddArgument(parser, operation_type='describe')
flags.AddDescribeFlags(parser)
flags.AddFullViewFlag(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
reservation_ref = Describe.ReservationArg.ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client))
view_enum = self.GetViewEnum(client, args)
request = client.messages.ComputeReservationBlocksGetRequest(
reservation=reservation_ref.reservation,
zone=reservation_ref.zone,
project=reservation_ref.project,
reservationBlock=args.block_name,
view=view_enum,
)
return client.MakeRequests([(client.apitools_client.reservationBlocks,
'Get', request)])[0]
def GetViewEnum(self, client, args):
view_enum = None
if args.IsSpecified('full_view'):
if args.full_view == 'BLOCK_VIEW_FULL':
view_enum = (
client.messages.ComputeReservationBlocksGetRequest.ViewValueValuesEnum.FULL
)
if args.full_view == 'BLOCK_VIEW_BASIC':
view_enum = (
client.messages.ComputeReservationBlocksGetRequest.ViewValueValuesEnum.BASIC
)
return view_enum
Describe.detailed_help = {
'EXAMPLES':
"""\
To describe a reservation block in reservation my-reservation in my-zone
with block name my-reservation-block-0001, run:
$ {command} my-reservation --zone=my-zone --block-name=my-reservation-block-0001
""",
}

View File

@@ -0,0 +1,102 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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 reservation blocks."""
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 request_helper
from googlecloudsdk.api_lib.compute import utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute import flags
from googlecloudsdk.command_lib.compute import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import resource_args
DETAILED_HELP = {
'DESCRIPTION':
"""\
{command} displays all Compute Engine reservation blocks in a densely
deployed reservation.
""",
'EXAMPLES':
"""\
To list all reservation blocks in a densely deployed reservation in
table form, run:
$ {command} my-reservation --zone=us-central1-a --project=my-project
To list the URIs of all reservation blocks in a densely deployed
reservation, run:
$ {command} my-reservation --zone=us-central1-a --project=my-project --uri
"""
}
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List Compute Engine reservation blocks."""
detailed_help = DETAILED_HELP
@classmethod
def Args(cls, parser):
List.ReservationArg = resource_args.GetReservationResourceArg()
List.ReservationArg.AddArgument(parser)
def _Run(self, args, holder):
client = holder.client
reservation_ref = (List.ReservationArg.
ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=flags.GetDefaultScopeLister(client)))
service = client.apitools_client.reservationBlocks
request = (client.messages.
ComputeReservationBlocksListRequest(
reservation=reservation_ref.reservation,
zone=reservation_ref.zone,
project=reservation_ref.project))
errors = []
results = list(request_helper.MakeRequests(
requests=[(service, 'List', request)],
http=client.apitools_client.http,
batch_url=client.batch_url,
errors=errors))
if errors:
utils.RaiseToolException(errors)
return results
def Run(self, args):
"""Creates and issues a reservationBlocks.list request.
Args:
args: the argparse arguments that this command was invoked with.
Returns:
List of reservation blocks.
"""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return self._Run(args, holder)

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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 performing maintenance on a reservation block."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations import util
from googlecloudsdk.command_lib.compute.reservations.blocks import flags
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class PerformMaintenance(base.UpdateCommand):
"""Perform maintenance on a reservation block within a reservation."""
@staticmethod
def Args(parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='perform-maintenance')
flags.AddDescribeFlags(parser)
flags.AddScopeFlags(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
reservation_ref = resource_args.GetReservationResourceArg(
).ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client))
request = (
client.messages.ComputeReservationBlocksPerformMaintenanceRequest(
reservation=reservation_ref.reservation,
zone=reservation_ref.zone,
project=reservation_ref.project,
reservationBlock=args.block_name,
reservationsBlocksPerformMaintenanceRequest=
client.messages.ReservationsBlocksPerformMaintenanceRequest(
maintenanceScope=util.MakeReservationBlocksMaintenanceScope(
client.messages, args.scope))
)
)
return client.MakeRequests([(client.apitools_client.reservationBlocks,
'PerformMaintenance', request)])
PerformMaintenance.detailed_help = {
'EXAMPLES':
"""\
To perform maintenance on a reservation block in reservation my-reservation
in my-zone with block name my-reservation-block-0001 with scope all, run:
$ {command} my-reservation --zone=my-zone --block-name=my-reservation-block-0001 --scope=all
""",
}

View File

@@ -0,0 +1,143 @@
# -*- 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.
"""Command for compute reservations create."""
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.reservations import flags
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations import util
def _MakeCreateRequest(args, messages, project, reservation_ref, resources):
"""Common routine for creating reservation request."""
reservation = util.MakeReservationMessageFromArgs(messages, args,
reservation_ref, resources)
reservation.description = args.description
return messages.ComputeReservationsInsertRequest(
reservation=reservation, project=project, zone=reservation_ref.zone)
def _RunCreate(compute_api, args):
"""Common routine for creating reservation."""
resources = compute_api.resources
reservation_ref = resource_args.GetReservationResourceArg().ResolveAsResource(
args,
resources,
scope_lister=compute_flags.GetDefaultScopeLister(compute_api.client))
messages = compute_api.client.messages
project = reservation_ref.project
create_request = _MakeCreateRequest(args, messages, project, reservation_ref,
resources)
service = compute_api.client.apitools_client.reservations
return compute_api.client.MakeRequests([(service, 'Insert', create_request)])
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.UniverseCompatible
class Create(base.CreateCommand):
"""Create a Compute Engine reservation."""
_support_auto_delete = False
_support_folder_share_setting = False
_support_reservation_sharing_policy = True
_support_ssd_count = True
@classmethod
def Args(cls, parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='create')
flags.AddCreateFlags(
parser,
support_folder_share_setting=cls._support_folder_share_setting,
support_reservation_sharing_policy=cls._support_reservation_sharing_policy,
support_ssd_count=cls._support_ssd_count,
)
def Run(self, args):
return _RunCreate(base_classes.ComputeApiHolder(base.ReleaseTrack.GA), args)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class CreateBeta(Create):
"""Create a Compute Engine reservation."""
_support_ssd_count = True
_support_auto_delete = True
_support_folder_share_setting = False
_support_reservation_sharing_policy = True
@classmethod
def Args(cls, parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='create')
flags.AddCreateFlags(
parser,
support_folder_share_setting=cls._support_folder_share_setting,
support_auto_delete=cls._support_auto_delete,
support_reservation_sharing_policy=cls._support_reservation_sharing_policy,
support_ssd_count=cls._support_ssd_count,
)
def Run(self, args):
return _RunCreate(
base_classes.ComputeApiHolder(base.ReleaseTrack.BETA), args)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(CreateBeta):
"""Create a Compute Engine reservation."""
_support_ssd_count = True
_support_auto_delete = True
_support_folder_share_setting = True
_support_reservation_sharing_policy = True
@classmethod
def Args(cls, parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='create')
flags.AddCreateFlags(
parser,
support_fleet=True,
support_folder_share_setting=cls._support_folder_share_setting,
support_ssd_count=cls._support_ssd_count,
support_auto_delete=cls._support_auto_delete,
support_reservation_sharing_policy=cls._support_reservation_sharing_policy,
)
def Run(self, args):
return _RunCreate(
base_classes.ComputeApiHolder(base.ReleaseTrack.ALPHA), args)
Create.detailed_help = {
'brief': (
'Create a Compute Engine reservation.'
),
'EXAMPLES': """
To create a Compute Engine reservation by specifying VM properties using an instance template, run:
$ {command} my-reservation --vm-count=1 --source-instance-template=example-instance-template --zone=fake-zone
To create a Compute Engine reservation by directly specifying VM properties, run:
$ {command} my-reservation --vm-count=1 --machine-type=custom-8-10240 --min-cpu-platform="Intel Haswell" --accelerator=count=2,type=nvidia-tesla-v100 --local-ssd=size=375,interface=scsi --zone=fake-zone
"""
}

View File

@@ -0,0 +1,35 @@
- release_tracks: [ALPHA, BETA, GA]
help_text:
brief: Delete a Compute Engine reservation.
description: Delete a Compute Engine reservation.
examples: |
To delete a given Compute Engine reservation, run:
$ {command} my-reservation --zone=ZONE
arguments:
resource:
spec: !REF googlecloudsdk.command_lib.compute.resources:reservation
help_text: The name of the reservation to delete.
request:
collection: compute.reservations
api_version: v1
BETA:
api_version: beta
ALPHA:
api_version: alpha
async:
api_version: v1
BETA:
api_version: beta
ALPHA:
api_version: alpha
method: wait
collection: compute.zoneOperations
response_name_field: selfLink
state:
field: status
success_values: ['DONE']

View File

@@ -0,0 +1,21 @@
- release_tracks: [ALPHA, BETA, GA]
help_text:
brief: Show details about a Compute Engine reservation.
description: Show details about a Compute Engine reservation.
examples: |
To describe a given Compute Engine reservation, run:
$ {command} my-reservation --zone=ZONE
arguments:
resource:
spec: !REF googlecloudsdk.command_lib.compute.resources:reservation
help_text: The name of the reservation to describe.
request:
collection: compute.reservations
api_version: v1
BETA:
api_version: beta
ALPHA:
api_version: alpha

View File

@@ -0,0 +1,31 @@
release_tracks: [ALPHA, BETA, GA]
help_text:
brief: Get the IAM policy for a Compute Engine reservation.
description: |
*{command}* displays the IAM policy associated with a
Compute Engine reservation in a project. If formatted as JSON,
the output can be edited and used as a policy file for
set-iam-policy. The output includes an "etag" field
identifying the version emitted and allowing detection of
concurrent policy updates; see
$ {parent} set-iam-policy for additional details.
examples: |
To print the IAM policy for a given reservation, run:
$ {command} my-reservation --zone=my-zone
request:
collection: compute.reservations
use_relative_name: false
modify_request_hooks:
- googlecloudsdk.command_lib.iam.hooks:UseMaxRequestedPolicyVersion:api_field=optionsRequestedPolicyVersion
api_version: v1
BETA:
api_version: beta
ALPHA:
api_version: alpha
arguments:
resource:
help_text: The reservation to display the IAM policy for.
spec: !REF googlecloudsdk.command_lib.compute.resources:reservation

View File

@@ -0,0 +1,61 @@
# -*- 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.
"""List Compute Engine reservations."""
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
class List(base.ListCommand):
"""List Compute Engine reservations."""
@staticmethod
def Args(parser):
parser.display_info.AddFormat("""\
table(name,
specificReservation.inUseCount,
specificReservation.count,
zone.basename(),
shareSettings.shareType)
""")
parser.display_info.AddUriFunc(utils.MakeGetUriFunc())
lister.AddZonalListerArgs(parser, hidden=True)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
request_data = lister.ParseZonalFlags(args, holder.resources)
list_implementation = lister.ZonalLister(
client, client.apitools_client.reservations)
return lister.Invoke(request_data, list_implementation)
List.detailed_help = {
'brief': 'List Compute Engine reservations.',
'EXAMPLES': '''
To list all Compute Engine reservations, run:
$ {command}
'''
}

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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 performing maintenance on a reservation."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import flags
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class PerformMaintenance(base.UpdateCommand):
"""Perform maintenance on a reservation, only applicable to reservations with reservation blocks."""
@staticmethod
def Args(parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='perform-maintenance')
flags.AddScopeFlags(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
reservation_ref = resource_args.GetReservationResourceArg(
).ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client))
request = (
client.messages.ComputeReservationsPerformMaintenanceRequest(
reservation=reservation_ref.reservation,
zone=reservation_ref.zone,
project=reservation_ref.project,
reservationsPerformMaintenanceRequest=
client.messages.ReservationsPerformMaintenanceRequest(
maintenanceScope=util.MakeReservationsMaintenanceScope(client.messages, args.scope))
)
)
service = client.apitools_client.reservations
return client.MakeRequests([(service, 'PerformMaintenance', request)])
PerformMaintenance.detailed_help = {
'EXAMPLES':
"""\
To perform maintenance on reservation my-reservation in my-zone with scope all, run:
$ {command} my-reservation --zone=my-zone --scope=all
""",
}

View File

@@ -0,0 +1,43 @@
release_tracks: [ALPHA, BETA, GA]
help_text:
brief: Remove IAM policy binding from a Compute Engine reservation.
description: |
Remove an IAM policy binding from the IAM policy of a Compute Engine reservation. One binding consists of a member,
a role, and an optional condition.
examples: |
To remove an IAM policy binding for the role of 'roles/compute.securityAdmin' for the user 'test-user@gmail.com'
with reservation 'my-reservation' and zone 'ZONE', run:
$ {command} my-reservation --zone=ZONE --member='user:test-user@gmail.com' --role='roles/compute.securityAdmin'
To remove an IAM policy binding which expires at the end of the year 2018 for the role of
'roles/compute.securityAdmin' and the user 'test-user@gmail.com' with reservation 'my-reservation' and zone 'ZONE', run:
$ {command} my-reservation --zone=ZONE --member='user:test-user@gmail.com' --role='roles/compute.securityAdmin' --condition='expression=request.time < timestamp("2019-01-01T00:00:00Z"),title=expires_end_of_2018,description=Expires at midnight on 2018-12-31'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
request:
collection: compute.reservations
use_relative_name: false
api_version: v1
BETA:
api_version: beta
ALPHA:
api_version: alpha
arguments:
resource:
help_text: The reservation for which to remove IAM policy binding from.
spec: !REF googlecloudsdk.command_lib.compute.resources:reservation
iam:
set_iam_policy_request_path: zoneSetPolicyRequest
message_type_overrides:
policy: Policy
set_iam_policy_request: ComputeReservationsSetIamPolicyRequest
enable_condition: true
policy_version: 3
get_iam_policy_version_path: optionsRequestedPolicyVersion

View File

@@ -0,0 +1,36 @@
release_tracks: [ALPHA, BETA, GA]
help_text:
brief: Set the IAM policy for a Compute Engine reservation.
description: |
Set the IAM policy for the given reservation as defined in a JSON or YAML file.
examples: |
The following command will read am IAM policy defined in a JSON file
'policy.json' and set it for the reservation `my-reservation`:
$ {command} my-reservation --zone=ZONE policy.json
See https://cloud.google.com/iam/docs/managing-policies for details of the
policy file format and contents.
request:
collection: compute.reservations
use_relative_name: false
modify_request_hooks:
- googlecloudsdk.command_lib.iam.hooks:UseMaxRequestedPolicyVersion:api_field=zoneSetPolicyRequest.policy.version
api_version: v1
BETA:
api_version: beta
ALPHA:
api_version: alpha
arguments:
resource:
help_text: The reservation to set the IAM policy for.
spec: !REF googlecloudsdk.command_lib.compute.resources:reservation
iam:
set_iam_policy_request_path: zoneSetPolicyRequest
message_type_overrides:
policy: Policy
set_iam_policy_request: ComputeReservationsSetIamPolicyRequest

View File

@@ -0,0 +1,34 @@
# -*- 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 Compute Engine reservation slots."""
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)
class ReservationSubBlocks(base.Group):
"""Manage Compute Engine reservation slots."""
category = base.COMPUTE_CATEGORY
detailed_help = {
'DESCRIPTION': """
Manage Compute Engine reservation slots.
""",
}

View File

@@ -0,0 +1,76 @@
# -*- 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 for describing reservation slots."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations.slots import flags
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Describe(base.DescribeCommand):
"""Describe a Compute Engine reservation slot."""
@staticmethod
def Args(parser):
Describe.ReservationArg = (
resource_args.GetReservationResourceArg()
)
Describe.ReservationArg.AddArgument(parser, operation_type='describe')
flags.AddDescribeFlags(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
reservation_ref = Describe.ReservationArg.ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client))
parent_name = f'reservations/{reservation_ref.reservation}/reservationBlocks/{args.block_name}/reservationSubBlocks/{args.sub_block_name}'
request = (
client.messages.ComputeReservationSlotsGetRequest(
parentName=parent_name,
zone=reservation_ref.zone,
project=reservation_ref.project,
reservationSlot=args.slot_name,
)
)
return client.MakeRequests([(client.apitools_client.reservationSlots,
'Get', request)])[0]
Describe.detailed_help = {
'EXAMPLES':
"""\
To describe a reservation slot in reservation exr1 in my-zone with block
name my-block, sub-block name my-sub-block, and slot name my-slot, run:
$ {command} exr1 --zone=my-zone --block-name=my-block \
--sub-block-name=my-sub-block --slot-name=my-slot
""",
}

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.
"""Command for listing reservation slots."""
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 request_helper
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.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations.slots import flags
DETAILED_HELP = {
'DESCRIPTION':
"""\
{command} displays all Compute Engine reservation slots in an extended reservation's sub-block.
""",
'EXAMPLES':
"""\
To list all reservation slots in an extended reservation's block my-block and sub-block my-sub-block in table form,
run:
$ {command} extended-reservation --block-name=my-block --sub-block-name=my-sub-block --zone=us-central1-a --project=my-project
To list the URIs of all reservation slots in an extended reservation, run:
$ {command} extended-reservation --block-name=my-block --sub-block-name=my-sub-block --zone=us-central1-a --project=my-project --uri
"""
}
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class List(base.ListCommand):
"""List Compute Engine reservation slots."""
detailed_help = DETAILED_HELP
@classmethod
def Args(cls, parser):
List.ReservationArg = resource_args.GetReservationResourceArg()
List.ReservationArg.AddArgument(parser, operation_type='list')
flags.AddListFlags(parser)
def _Run(self, args, holder):
client = holder.client
reservation_ref = (
List.ReservationArg.ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client)))
parent_name = f'reservations/{reservation_ref.reservation}/reservationBlocks/{args.block_name}/reservationSubBlocks/{args.sub_block_name}'
service = client.apitools_client.reservationSlots
request = (client.messages.
ComputeReservationSlotsListRequest(
parentName=parent_name,
zone=reservation_ref.zone,
project=reservation_ref.project))
errors = []
results = list(request_helper.MakeRequests(
requests=[(service, 'List', request)],
http=client.apitools_client.http,
batch_url=client.batch_url,
errors=errors))
if errors:
utils.RaiseToolException(errors)
return results
def Run(self, args):
"""Creates and issues a reservationSlots.list request.
Args:
args: the argparse arguments that this command was invoked with.
Returns:
List of reservation slots.
"""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return self._Run(args, holder)

View File

@@ -0,0 +1,35 @@
# -*- 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 Compute Engine reservation sub blocks."""
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 ReservationSubBlocks(base.Group):
"""Manage Compute Engine reservation sub blocks."""
category = base.COMPUTE_CATEGORY
detailed_help = {
'DESCRIPTION': """
Manage Compute Engine reservation sub blocks.
""",
}

View File

@@ -0,0 +1,83 @@
# -*- 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 for describing reservation sub-blocks."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations.sub_blocks import flags
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe a Compute Engine reservation sub-block."""
@staticmethod
def Args(parser):
Describe.ReservationArg = (
resource_args.GetReservationResourceArg()
)
Describe.ReservationArg.AddArgument(parser, operation_type='describe')
flags.AddDescribeFlags(parser)
flags.AddFullViewFlag(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
reservation_ref = Describe.ReservationArg.ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client))
parent_name = f'reservations/{reservation_ref.reservation}/reservationBlocks/{args.block_name}'
view_enum = None
if args.IsSpecified('full_view'):
view_enum_type = (
client.messages.ComputeReservationSubBlocksGetRequest.ViewValueValuesEnum
)
view_enum = view_enum_type(args.full_view)
request = (
client.messages.ComputeReservationSubBlocksGetRequest(
parentName=parent_name,
zone=reservation_ref.zone,
project=reservation_ref.project,
reservationSubBlock=args.sub_block_name,
view=view_enum,)
)
return client.MakeRequests([(client.apitools_client.reservationSubBlocks,
'Get', request)])[0]
Describe.detailed_help = {
'EXAMPLES':
"""\
To describe a reservation sub-block in reservation exr1 in my-zone
with block name my-block and sub-block name my-sub-block, run:
$ {command} exr1 --zone=my-zone --block-name=my-block --sub-block-name=my-sub-block
""",
}

View File

@@ -0,0 +1,104 @@
# -*- 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 for listing reservation sub-blocks."""
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 request_helper
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.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations.sub_blocks import flags
DETAILED_HELP = {
'DESCRIPTION':
"""\
{command} displays all Compute Engine reservation sub-blocks in an extended reservation's block.
""",
'EXAMPLES':
"""\
To list all reservation sub-blocks in an extended reservation's block my-block in table form,
run:
$ {command} extended-reservation --block-name=my-block --zone=us-central1-a --project=my-project
To list the URIs of all reservation blocks in an extended reservation, run:
$ {command} extended-reservation --block-name=my-block --zone=us-central1-a --project=my-project --uri
"""
}
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List Compute Engine reservation sub-blocks."""
detailed_help = DETAILED_HELP
@classmethod
def Args(cls, parser):
List.ReservationArg = resource_args.GetReservationResourceArg()
List.ReservationArg.AddArgument(parser, operation_type='list')
flags.AddListFlags(parser)
def _Run(self, args, holder):
client = holder.client
reservation_ref = (
List.ReservationArg.ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client)))
parent_name = f'reservations/{reservation_ref.reservation}/reservationBlocks/{args.block_name}'
service = client.apitools_client.reservationSubBlocks
request = (client.messages.
ComputeReservationSubBlocksListRequest(
parentName=parent_name,
zone=reservation_ref.zone,
project=reservation_ref.project))
errors = []
results = list(request_helper.MakeRequests(
requests=[(service, 'List', request)],
http=client.apitools_client.http,
batch_url=client.batch_url,
errors=errors))
if errors:
utils.RaiseToolException(errors)
return results
def Run(self, args):
"""Creates and issues a reservationSubBlocks.list request.
Args:
args: the argparse arguments that this command was invoked with.
Returns:
List of reservation sub-blocks.
"""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
return self._Run(args, holder)

View File

@@ -0,0 +1,75 @@
# -*- 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 for performing maintenance on a reservation sub-block."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations.sub_blocks import flags
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class PerformMaintenance(base.UpdateCommand):
"""Perform maintenance on a reservation sub-block."""
@staticmethod
def Args(parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='perform-maintenance')
flags.AddDescribeFlags(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
reservation_ref = resource_args.GetReservationResourceArg(
).ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client))
parent_name = f'reservations/{reservation_ref.reservation}/reservationBlocks/{args.block_name}'
request = (
client.messages.ComputeReservationSubBlocksPerformMaintenanceRequest(
parentName=parent_name,
zone=reservation_ref.zone,
project=reservation_ref.project,
reservationSubBlock=args.sub_block_name
)
)
return client.MakeRequests([(client.apitools_client.reservationSubBlocks,
'PerformMaintenance', request)])
PerformMaintenance.detailed_help = {
'EXAMPLES':
"""\
To perform maintenance on a reservation sub-block in reservation exr-1
in ZONE with block name block-1 and sub-block name sub-block-1, run:
$ {command} exr-1 --zone=ZONE --block-name=block-1
--sub-block-name=sub-block-1
""",
}

View File

@@ -0,0 +1,129 @@
# -*- 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 for reporting a faulty reservation sub-block."""
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 import scope as compute_scope
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations.sub_blocks import flags
from googlecloudsdk.command_lib.compute.reservations.sub_blocks import util
from googlecloudsdk.core.console import console_io
def _GetReportFaultyRequest(args, reservation_ref, holder):
"""Create Update Request for report faulty."""
client = holder.client
parent_name = f'reservations/{reservation_ref.reservation}/reservationBlocks/{args.block_name}'
fault_reasons = []
if args.fault_reasons:
for reason in args.fault_reasons:
fault_reasons.append(
client.messages.ReservationSubBlocksReportFaultyRequestFaultReason(
behavior=util.MakeFaultBehavior(
client.messages, reason.get('behavior')
),
description=reason.get('description'),
)
)
disruption_schedule = util.MakeDisruptionSchedule(
client.messages, args.disruption_schedule
)
failure_component = util.MakeFailureComponent(
client.messages, args.failure_component
)
report_faulty_body = client.messages.ReservationSubBlocksReportFaultyRequest(
disruptionSchedule=disruption_schedule,
faultReasons=fault_reasons,
failureComponent=failure_component,
)
request = client.messages.ComputeReservationSubBlocksReportFaultyRequest(
parentName=parent_name,
zone=reservation_ref.zone,
project=reservation_ref.project,
reservationSubBlock=args.sub_block_name,
reservationSubBlocksReportFaultyRequest=report_faulty_body,
)
return request
@base.UniverseCompatible
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA
)
class ReportFaulty(base.UpdateCommand):
"""Report a sub-block within a reservation as faulty."""
@staticmethod
def Args(parser):
resource_args.GetReservationResourceArg(
help_text=(
'The name of the reservation containing the sub-block to report as'
' faulty'
)
).AddArgument(parser, operation_type='report-subblock-as-faulty')
flags.AddDescribeFlags(parser)
flags.GetDisruptionScheduleFlag().AddToParser(parser)
flags.GetFaultReasonsFlag().AddToParser(parser)
flags.GetFailureComponentFlag().AddToParser(parser)
def Run(self, args):
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
client = holder.client
reservation_ref = resource_args.GetReservationResourceArg(
).ResolveAsResource(
args,
holder.resources,
default_scope=compute_scope.ScopeEnum.ZONE,
scope_lister=compute_flags.GetDefaultScopeLister(client))
prompt_message = (
'WARNING: This action is highly disruptive and will immediately '
'terminate all running VMs within this sub-block.'
)
console_io.PromptContinue(
message=prompt_message,
prompt_string='Do you want to continue?',
throw_if_unattended=True,
cancel_on_no=True,
)
request = _GetReportFaultyRequest(args, reservation_ref, holder)
return client.MakeRequests([(client.apitools_client.reservationSubBlocks,
'ReportFaulty', request)])
ReportFaulty.detailed_help = {
'EXAMPLES':
"""\
To report reservation exr-1 in ZONE with block name block-1 and
sub block name sub-block-1 as faulty, run:
$ {command} exr-1 --zone=ZONE --block-name=block-1 \
--sub-block-name=sub-block-1 \
--disruption-schedule=IMMEDIATE \
--fault-reasons=behavior=PERFORMANCE,description="performance issues" \
--failure-component=NVLINK_SWITCH
""",
}

View File

@@ -0,0 +1,676 @@
# -*- 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 for compute reservations update."""
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 request_helper
from googlecloudsdk.api_lib.compute import utils
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.reservations import flags as r_flags
from googlecloudsdk.command_lib.compute.reservations import resource_args
from googlecloudsdk.command_lib.compute.reservations import util
def _ValidateArgs(
args,
support_share_with_flag,
support_auto_delete=False,
support_reservation_sharing_policy=False,
support_emergent_maintenance=False,
support_share_type=False,
support_scheduling_type=False,
):
"""Validates that both share settings arguments are mentioned.
Args:
args: The arguments given to the update command.
support_share_with_flag: Check if share_with is supported.
support_auto_delete: Check if auto-delete settings are supported.
support_reservation_sharing_policy: Check if reservation sharing policy is
supported.
support_emergent_maintenance: Check if emergent maintenance is supported.
support_share_type: Check if share setting is supported.
support_scheduling_type: Check if scheduling type is supported.
"""
# Check the version and share-with option.
share_with = False
parameter_names = [
'--share-with',
'--vm-count',
]
one_option_exception_message = (
'Please provide one of these options: 1- Specify share-with or'
' add-share-with or remove-share-with to update the project list. 2-'
' Specify reservation vm-count to resize. '
)
if support_auto_delete:
parameter_names.extend([
'--delete-at-time',
'--delete-after-duration',
'--disable-auto-delete',
])
one_option_exception_message += (
'3- Modify auto-delete'
' properties with specifing auto-delete-at-time or'
' auto-delete-after-duration or disable-auto-delete flags.'
)
if support_reservation_sharing_policy:
parameter_names.extend([
'--reservation-sharing-policy',
])
one_option_exception_message += (
'4- Modify reservation sharing policy with specifying'
' reservation-sharing-policy flag.'
)
if support_emergent_maintenance:
parameter_names.extend([
'--enable-emergent-maintenance',
'--no-enable-emergent-maintenance'
])
one_option_exception_message += (
'5- Modify emergent maintenance with specifying'
' enable-emergent-maintenance flag.'
)
if support_share_type:
parameter_names.extend([
'--share-setting',
])
one_option_exception_message += (
'6- Modify share setting with specifying share-setting flag.'
)
if support_scheduling_type:
parameter_names.extend([
'--scheduling-type',
])
one_option_exception_message += (
'7- Modify scheduling type with specifying scheduling-type flag.'
)
has_share_with = False
if support_share_with_flag:
has_share_with = args.IsSpecified('share_with')
has_add_share_with = args.IsSpecified('add_share_with')
has_remove_share_with = args.IsSpecified('remove_share_with')
if has_share_with or has_add_share_with or has_remove_share_with:
share_with = True
if (
(has_share_with and has_add_share_with)
or (has_share_with and has_remove_share_with)
or (has_add_share_with and has_remove_share_with)
):
raise exceptions.ConflictingArgumentsException(
'--share-with', '--add-share-with', '--remove-share-with'
)
if has_remove_share_with:
for project in getattr(args, 'remove_share_with', []):
if not project.isnumeric():
raise exceptions.InvalidArgumentException(
'--remove-share-with',
'Please specify project number (not project id/name).',
)
minimum_argument_specified = not share_with and not args.IsSpecified(
'vm_count'
)
if support_auto_delete:
auto_delete_settings_updated = args.IsSpecified('delete_at_time') or (
args.IsSpecified('delete_after_duration')
or args.IsSpecified('disable_auto_delete')
)
minimum_argument_specified = (
minimum_argument_specified and not auto_delete_settings_updated
)
if support_reservation_sharing_policy:
minimum_argument_specified = (
minimum_argument_specified
and not args.IsSpecified('reservation_sharing_policy')
)
if support_emergent_maintenance:
minimum_argument_specified = (
minimum_argument_specified
and not args.IsSpecified('enable_emergent_maintenance')
)
if support_scheduling_type:
minimum_argument_specified = (
minimum_argument_specified and not args.IsSpecified('scheduling_type')
)
# Check parameters (add_share_with and remove_share_with are on GA).
if minimum_argument_specified:
raise exceptions.MinimumArgumentException(parameter_names,
one_option_exception_message)
def _GetShareSettingUpdateRequest(
args, reservation_ref, holder, support_share_with_flag,
support_share_type):
"""Create Update Request for share-with.
Returns:
update request.
Args:
args: The arguments given to the update command.
reservation_ref: reservation refrence.
holder: base_classes.ComputeApiHolder.
support_share_with_flag: Check if share_with is supported.
support_share_type: Check if share_type is supported.
"""
messages = holder.client.messages
# Set updated properties and build update mask.
share_settings = None
update_mask = []
setting_configs = None
if support_share_type and args.IsSpecified('share_setting'):
setting_configs = getattr(args, 'share_setting', None)
update_mask.append('shareSettings.shareType')
if support_share_with_flag:
if not setting_configs and (args.IsSpecified('share_with') or
args.IsSpecified('add_share_with') or
args.IsSpecified('remove_share_with')):
setting_configs = 'projects'
if args.IsSpecified('share_with'):
share_settings = util.MakeShareSettingsWithArgs(
messages, args, setting_configs, share_with='share_with')
update_mask.extend([
'shareSettings.projectMap.' + project
for project in getattr(args, 'share_with', [])
])
else:
setting_configs = 'projects'
if args.IsSpecified('add_share_with'):
share_settings = util.MakeShareSettingsWithArgs(
messages, args, setting_configs, share_with='add_share_with')
update_mask.extend([
'shareSettings.projectMap.' + project
for project in getattr(args, 'add_share_with', [])
])
elif args.IsSpecified('remove_share_with'):
share_settings = util.MakeShareSettingsWithArgs(
messages, args, setting_configs, share_with='remove_share_with')
update_mask.extend([
'shareSettings.projectMap.' + project
for project in getattr(args, 'remove_share_with', [])
])
# Build reservation object using new share-settings.
r_resource = util.MakeReservationMessage(messages, reservation_ref.Name(),
share_settings, None, None, None,
reservation_ref.zone)
# Build update request.
r_update_request = messages.ComputeReservationsUpdateRequest(
reservation=reservation_ref.Name(),
reservationResource=r_resource,
paths=update_mask,
project=reservation_ref.project,
zone=reservation_ref.zone)
return r_update_request
def _GetReservationSharingPolicyUpdateRequest(args, reservation_ref, holder):
"""Create Update Request for the reservation sharing policy.
Returns:
UpdateRequest
Args:
args: The arguments given to the update command.
reservation_ref: reservation refrence.
holder: base_classes.ComputeApiHolder.
"""
messages = holder.client.messages
r_resource = util.MakeReservationMessage(
messages,
reservation_ref.Name(),
None,
None,
None,
None,
reservation_ref.zone,
reservation_sharing_policy=getattr(
args, 'reservation_sharing_policy', None
),
)
# Build update request.
return messages.ComputeReservationsUpdateRequest(
reservation=reservation_ref.Name(),
reservationResource=r_resource,
paths=['reservationSharingPolicy.serviceShareType'],
project=reservation_ref.project,
zone=reservation_ref.zone,
)
def _GetResizeRequest(args, reservation_ref, holder):
"""Create Update Request for vm_count.
Returns:
resize request.
Args:
args: The arguments given to the update command.
reservation_ref: reservation refrence.
holder: base_classes.ComputeApiHolder.
"""
messages = holder.client.messages
vm_count = None
if args.IsSpecified('vm_count'):
vm_count = args.vm_count
# Build resize request.
r_resize_request = messages.ComputeReservationsResizeRequest(
reservation=reservation_ref.Name(),
reservationsResizeRequest=messages.ReservationsResizeRequest(
specificSkuCount=vm_count),
project=reservation_ref.project,
zone=reservation_ref.zone)
return r_resize_request
def _AutoDeleteUpdateRequest(args, reservation_ref, holder):
"""Create Update Request for modifying auto-delete properties."""
messages = holder.client.messages
update_mask = []
if args.IsSpecified('delete_at_time'):
update_mask.append('deleteAtTime')
delete_at_time = args.delete_at_time
else:
delete_at_time = None
if args.IsSpecified('delete_after_duration'):
update_mask.append('deleteAfterDuration')
delete_after_duration = args.delete_after_duration
else:
delete_after_duration = None
if args.IsSpecified('disable_auto_delete'):
update_mask.append('deleteAtTime')
r_resource = util.MakeReservationMessage(
messages,
reservation_ref.Name(),
None,
None,
None,
None,
reservation_ref.zone,
delete_at_time,
delete_after_duration,
)
# Build update request.
return messages.ComputeReservationsUpdateRequest(
reservation=reservation_ref.Name(),
reservationResource=r_resource,
paths=update_mask,
project=reservation_ref.project,
zone=reservation_ref.zone,
)
def _EnableEmergentMaintenanceUpdateRequest(args, reservation_ref, holder):
"""Create Update Request for enabling emergent maintenance."""
messages = holder.client.messages
update_mask = []
if args.IsSpecified('enable_emergent_maintenance'):
update_mask.append('enableEmergentMaintenance')
enable_emergent_maintenance = args.enable_emergent_maintenance
else:
enable_emergent_maintenance = None
r_resource = util.MakeReservationMessage(
messages,
reservation_ref.Name(),
None,
None,
None,
None,
reservation_ref.zone,
enable_emergent_maintenance=enable_emergent_maintenance,
)
# Build Update Request.
return messages.ComputeReservationsUpdateRequest(
reservation=reservation_ref.Name(),
reservationResource=r_resource,
paths=update_mask,
project=reservation_ref.project,
zone=reservation_ref.zone,
)
def _SchedulingTypeUpdateRequest(args, reservation_ref, holder):
"""Create Update Request for scheduling type."""
messages = holder.client.messages
update_mask = []
if args.IsSpecified('scheduling_type'):
update_mask.append('schedulingType')
scheduling_type = args.scheduling_type
else:
scheduling_type = None
r_resource = util.MakeReservationMessage(
messages,
reservation_ref.Name(),
None,
None,
None,
None,
reservation_ref.zone,
scheduling_type=scheduling_type,
)
# Build Update Request.
return messages.ComputeReservationsUpdateRequest(
reservation=reservation_ref.Name(),
reservationResource=r_resource,
paths=update_mask,
project=reservation_ref.project,
zone=reservation_ref.zone,
)
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.UniverseCompatible
class Update(base.UpdateCommand):
"""Update Compute Engine reservations."""
_support_share_with_flag = False
_support_auto_delete = False
_support_reservation_sharing_policy = True
_support_emergent_maintenance = True
_support_share_type = False
_support_scheduling_type = True
@classmethod
def Args(cls, parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='update')
r_flags.GetAddShareWithFlag().AddToParser(parser)
r_flags.GetRemoveShareWithFlag().AddToParser(parser)
r_flags.GetVmCountFlag(False).AddToParser(parser)
r_flags.GetReservationSharingPolicyFlag().AddToParser(parser)
r_flags.GetEnableEmergentMaintenanceFlag().AddToParser(parser)
r_flags.GetSchedulingTypeFlag().AddToParser(parser)
def Run(self, args):
"""Common routine for updating reservation."""
holder = base_classes.ComputeApiHolder(self.ReleaseTrack())
resources = holder.resources
service = holder.client.apitools_client.reservations
# Validate the command.
_ValidateArgs(
args,
self._support_share_with_flag,
self._support_auto_delete,
self._support_reservation_sharing_policy,
self._support_emergent_maintenance,
self._support_share_type,
self._support_scheduling_type,
)
reservation_ref = resource_args.GetReservationResourceArg(
).ResolveAsResource(
args,
resources,
scope_lister=compute_flags.GetDefaultScopeLister(holder.client))
result = list()
errors = []
share_with = False
if args.IsSpecified('add_share_with') or args.IsSpecified(
'remove_share_with'):
share_with = True
if self._support_share_with_flag:
if args.IsSpecified('share_with'):
share_with = True
if share_with:
r_update_request = _GetShareSettingUpdateRequest(
args, reservation_ref, holder, self._support_share_with_flag,
self._support_share_type)
# Invoke Reservation.update API.
result.append(
list(
request_helper.MakeRequests(
requests=[(service, 'Update', r_update_request)],
http=holder.client.apitools_client.http,
batch_url=holder.client.batch_url,
errors=errors)))
if errors:
utils.RaiseToolException(errors)
if self._support_reservation_sharing_policy:
if args.IsSpecified('reservation_sharing_policy'):
r_sharing_policy_request = _GetReservationSharingPolicyUpdateRequest(
args, reservation_ref, holder
)
result.append(
list(
request_helper.MakeRequests(
requests=[(service, 'Update', r_sharing_policy_request)],
http=holder.client.apitools_client.http,
batch_url=holder.client.batch_url,
errors=errors,
)
)
)
if args.IsSpecified('vm_count'):
r_resize_request = _GetResizeRequest(args, reservation_ref, holder)
# Invoke Reservation.resize API.
result.append(
holder.client.MakeRequests(([(service, 'Resize', r_resize_request)])))
if self._support_auto_delete:
if args.IsSpecified('delete_at_time') or (
args.IsSpecified('delete_after_duration')
or args.IsSpecified('disable_auto_delete')
):
r_update_request = _AutoDeleteUpdateRequest(
args, reservation_ref, holder
)
result.append(
list(
request_helper.MakeRequests(
requests=[(service, 'Update', r_update_request)],
http=holder.client.apitools_client.http,
batch_url=holder.client.batch_url,
errors=errors,
)
)
)
if errors:
utils.RaiseToolException(errors)
if self._support_emergent_maintenance:
if args.IsSpecified('enable_emergent_maintenance'):
r_update_request = _EnableEmergentMaintenanceUpdateRequest(
args, reservation_ref, holder
)
result.append(
list(
request_helper.MakeRequests(
requests=[(service, 'Update', r_update_request)],
http=holder.client.apitools_client.http,
batch_url=holder.client.batch_url,
errors=errors,
)))
if errors:
utils.RaiseToolException(errors)
if self._support_scheduling_type:
if args.IsSpecified('scheduling_type'):
r_update_request = _SchedulingTypeUpdateRequest(
args, reservation_ref, holder
)
result.append(
list(
request_helper.MakeRequests(
requests=[(service, 'Update', r_update_request)],
http=holder.client.apitools_client.http,
batch_url=holder.client.batch_url,
errors=errors,
)
)
)
if errors:
utils.RaiseToolException(errors)
return result
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class UpdateBeta(Update):
"""Update Compute Engine reservations."""
_support_share_with_flag = True
_support_auto_delete = True
_support_reservation_sharing_policy = True
_support_emergent_maintenance = True
_support_share_type = True
_support_scheduling_type = True
@classmethod
def Args(cls, parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='update')
r_flags.GetShareWithFlag().AddToParser(parser)
r_flags.GetAddShareWithFlag().AddToParser(parser)
r_flags.GetRemoveShareWithFlag().AddToParser(parser)
r_flags.GetVmCountFlag(False).AddToParser(parser)
r_flags.GetReservationSharingPolicyFlag().AddToParser(parser)
r_flags.GetEnableEmergentMaintenanceFlag().AddToParser(parser)
r_flags.GetSharedSettingFlag(
support_folder_share_setting=False).AddToParser(parser)
r_flags.GetSchedulingTypeFlag().AddToParser(parser)
auto_delete_group = base.ArgumentGroup(
'Manage auto-delete properties for reservations.',
required=False,
mutex=True,
)
auto_delete_group.AddArgument(r_flags.GetDeleteAtTimeFlag())
auto_delete_group.AddArgument(r_flags.GetDeleteAfterDurationFlag())
auto_delete_group.AddArgument(r_flags.GetDisableAutoDelete())
auto_delete_group.AddToParser(parser)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(Update):
"""Update Compute Engine reservations."""
_support_share_with_flag = True
_support_auto_delete = True
_support_reservation_sharing_policy = True
_support_emergent_maintenance = True
_support_share_type = True
_support_scheduling_type = True
@classmethod
def Args(cls, parser):
resource_args.GetReservationResourceArg().AddArgument(
parser, operation_type='update'
)
r_flags.GetShareWithFlag().AddToParser(parser)
r_flags.GetAddShareWithFlag().AddToParser(parser)
r_flags.GetRemoveShareWithFlag().AddToParser(parser)
r_flags.GetVmCountFlag(False).AddToParser(parser)
r_flags.GetReservationSharingPolicyFlag().AddToParser(parser)
r_flags.GetEnableEmergentMaintenanceFlag().AddToParser(parser)
r_flags.GetSharedSettingFlag(
support_folder_share_setting=False).AddToParser(parser)
r_flags.GetSchedulingTypeFlag().AddToParser(parser)
auto_delete_group = base.ArgumentGroup(
'Manage auto-delete properties for reservations.',
required=False,
mutex=True,
)
auto_delete_group.AddArgument(r_flags.GetDeleteAtTimeFlag())
auto_delete_group.AddArgument(r_flags.GetDeleteAfterDurationFlag())
auto_delete_group.AddArgument(r_flags.GetDisableAutoDelete())
auto_delete_group.AddToParser(parser)
Update.detailed_help = {
'EXAMPLES':
"""
To add `project-1,project-2,project-3` to the list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --add-share-with=project-1,project-2,project-3 --zone=us-central1-a
To remove `project-1,project-2,project-3` from the list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --remove-share-with=project-1,project-2,project-3 --zone=us-central1-a
To update the number of reserved VM instances to 500 for a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --zone=us-central1-a --vm-count=500
"""
}
UpdateBeta.detailed_help = {
'EXAMPLES':
"""
To add `project-1,project-2,project-3` to the list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --add-share-with=project-1,project-2,project-3 --zone=us-central1-a
To remove `project-1,project-2,project-3` from the list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --remove-share-with=project-1,project-2,project-3 --zone=us-central1-a
To update the entire list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --share-with=project-1,project-2,project-3 --zone=us-central1-a
To update the number of reserved VM instances to 500 for a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --zone=us-central1-a --vm-count=500
"""
}
UpdateAlpha.detailed_help = {
'EXAMPLES':
"""
To add `project-1,project-2,project-3` to the list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --add-share-with=project-1,project-2,project-3 --zone=us-central1-a
To remove `project-1,project-2,project-3` from the list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --remove-share-with=project-1,project-2,project-3 --zone=us-central1-a
To update the entire list of projects that are shared with a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --share-with=project-1,project-2,project-3 --zone=us-central1-a
To update the number of reserved VM instances to 500 for a Compute Engine reservation, `my-reservation` in zone: `us-central1-a`, run:
$ {command} my-reservation --zone=us-central1-a --vm-count=500
"""
}