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,38 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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.
"""The super-group for the Cloud Resource Manager CLI."""
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 ResourceManager(base.Group):
"""Manage Cloud Resources.
Commands to query and update your Cloud Organizations, Folders, and Projects.
"""
category = base.IDENTITY_AND_SECURITY_CATEGORY
def Filter(self, context, args):
# TODO(b/190539161): Determine if command group works with project number
base.RequireProjectID(args)
del context, args
base.DisableUserProjectQuota()

View File

@@ -0,0 +1,33 @@
# -*- 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.
"""The group for the Cloud Folders Capabilities CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import capabilities
from googlecloudsdk.calliope import base
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA
)
@base.DefaultUniverseOnly
class Capabilities(base.Group):
"""Manage Cloud Folder Capabilities.
Commands to query and update your Cloud Folder's Capabilities.
"""

View File

@@ -0,0 +1,53 @@
# -*- 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 show metadata for a specified capability."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import capabilities
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA
)
@base.DefaultUniverseOnly
class Describe(base.DescribeCommand):
"""Show whether a Capability is enabled.
Command to show whether a Capability is enabled.
This command can fail for the following reasons:
* The capability specified does not exist.
* The active account does not have permission to access the given
folder/capability.
## EXAMPLES
The following command prints metadata for a capability with the ID
`folders/123/capabilities/app-management`:
$ {command} "folders/123/capabilities/app-management"
"""
@staticmethod
def Args(parser):
flags.CapabilityIdArg('you want to describe.').AddToParser(parser)
def Run(self, args):
return capabilities.GetCapability(args.id)

View File

@@ -0,0 +1,78 @@
# -*- 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 update a folder capability."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import capabilities
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA
)
@base.DefaultUniverseOnly
class Update(base.Command):
"""Update a folder capability.
Command to Update/Set the `value` field of the Folder capability. This
can be done by using the `--enable` flag to set the value to True, and
the `--no-enable` flag to set the value to False.
This command can fail for the following reasons:
* There is no folder parenting the given capability name.
* The active account does not have permission to update the given
folder/capability.
## EXAMPLES
The following command updates a capability with the ID
`folders/123/capabilities/app-management` to have
the value True:
$ {command} "folders/123/capabilities/app-management" --enable
In order to set the value to False, the following command can be used:
$ {command} "folders/123/capabilities/app-management" --no-enable
"""
@staticmethod
def Args(parser):
flags.CapabilityIdArg('you want to update.').AddToParser(parser)
parser.add_argument(
'--enable',
action=arg_parsers.StoreTrueFalseAction,
dest='value',
required=True,
help='Enable the Capability',
)
parser.add_argument(
'--update-mask',
help=(
'Update Mask. This is an optional field, and the only valid value'
' this can be set to currently is "value".'
),
)
def Run(self, args):
capability_name = args.id
return capabilities.UpdateCapability(
capability_name, args.value, args.update_mask
)

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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.
"""The group for the Cloud Folders CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
# @base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
class Folders(base.Group):
"""Manage Cloud Folders.
Commands to query and update your Cloud Folders.
"""
@staticmethod
def Args(parser):
parser.display_info.AddUriFunc(folders.GetUri)

View File

@@ -0,0 +1,33 @@
release_tracks: [GA, BETA, ALPHA]
help_text:
brief: Add IAM policy binding for a folder.
description: |
Adds a policy binding to the IAM policy of a folder, given a folder ID and the binding. One
binding consists of a member, a role, and an optional condition.
examples: |
To add an IAM policy binding for the role of 'roles/editor' for the user 'test-user@gmail.com'
on the folder 'folder-id', run:
$ {command} folder-id --member='user:test-user@gmail.com' --role='roles/editor'
To add an IAM policy binding which expires at the end of the year 2018 for the role of
'roles/storage.objectAdmin' and the user 'test-user@gmail.com' on the folder 'folder-id', run:
$ {command} folder-id --member='user:test-user@gmail.com' --role='roles/storage.objectAdmin' --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: cloudresourcemanager.folders
api_version: v2
arguments:
resource:
help_text: The ID of the folder to add the IAM binding.
spec: !REF googlecloudsdk.command_lib.resource_manager.resources:folder
iam:
enable_condition: true
policy_version: 3
get_iam_policy_version_path: getIamPolicyRequest.options.requestedPolicyVersion

View File

@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*- #
# Copyright 2015 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to create a new folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.api_lib.resource_manager import operations
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create a new folder.
Creates a new folder in the given parent folder or organization.
## EXAMPLES
The following command creates a folder with the name `abc` into a
folder with the ID `2345`:
$ {command} --display-name=abc --folder=2345
The following command creates a folder with the name `abc` into an
organization with ID `1234`:
$ {command} --display-name=abc --organization=1234
"""
@staticmethod
def Args(parser):
flags.AddParentFlagsToParser(parser)
flags.OperationAsyncFlag().AddToParser(parser)
base.Argument(
'--display-name',
required=True,
help='Friendly display name to use for the new folder.',
).AddToParser(parser)
flags.TagsFlag().AddToParser(parser)
def Run(self, args):
flags.CheckParentFlags(args)
messages = folders.FoldersMessages()
tags = flags.GetTagsFromFlags(args, messages.Folder.TagsValue)
operation = folders.FoldersService().Create(
messages.CloudresourcemanagerFoldersCreateRequest(
parent=flags.GetParentFromFlags(args),
folder=messages.Folder(displayName=args.display_name, tags=tags),
)
)
if args.async_:
return operation
else:
finished_operation = operations.WaitForOperation(operation)
result = operations.ExtractOperationResponse(finished_operation,
messages.Folder)
log.CreatedResource(result)
return result

View File

@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 delete a folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Delete a folder.
Delete a folder, given a valid folder ID.
This command can fail for the following reasons:
* There is no folder with the given ID.
* The active account does not have permission to delete the given folder.
* The folder to be deleted is not empty.
## EXAMPLES
The following command deletes a folder with the ID `123456789`:
$ {command} 123456789
"""
@staticmethod
def Args(parser):
flags.FolderIdArg('you want to delete.').AddToParser(parser)
def Run(self, args):
service = folders.FoldersService()
messages = folders.FoldersMessages()
result = service.Delete(
messages.CloudresourcemanagerFoldersDeleteRequest(foldersId=args.id))
log.DeletedResource(result)

View File

@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 show metadata for a specified folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Show metadata for a folder.
Shows metadata for a folder, given a valid folder ID.
This command can fail for the following reasons:
* The folder specified does not exist.
* The active account does not have permission to access the given
folder.
## EXAMPLES
The following command prints metadata for a folder with the ID `3589215982`:
$ {command} 3589215982
"""
@staticmethod
def Args(parser):
flags.FolderIdArg('you want to describe.').AddToParser(parser)
def Run(self, args):
return folders.GetFolder(args.id)

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 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 get IAM policy for a folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import policies_flags
from googlecloudsdk.command_lib.resource_manager import flags
class GetIamPolicy(base.ListCommand):
"""Get IAM policies for a folder and its ancestors.
Get IAM policies for a folder and its ancestors, given a folder ID.
## EXAMPLES
To get IAM policies for folder ``3589215982'' and its ancestors, run:
$ {command} 3589215982
"""
@staticmethod
def Args(parser):
flags.GetFolderResourceArg('get IAM policy for.').AddToParser(parser)
base.URI_FLAG.RemoveFromParser(parser)
policies_flags.AddIncludeDenyFlag(parser)
def Run(self, args):
return folders.GetAncestorsIamPolicy(args.folder_id, args.include_deny,
self.ReleaseTrack())

View File

@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to get IAM policy for a folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.GA)
class GetIamPolicy(base.ListCommand):
"""Get IAM policy for a folder.
Gets the IAM policy for a folder, given a folder ID.
## EXAMPLES
The following command prints the IAM policy for a folder with the ID
`3589215982`:
$ {command} 3589215982
"""
@staticmethod
def Args(parser):
flags.FolderIdArg('whose policy you want to get.').AddToParser(parser)
base.URI_FLAG.RemoveFromParser(parser)
def Run(self, args):
return folders.GetIamPolicy(args.id)

View File

@@ -0,0 +1,28 @@
- release_tracks: [ALPHA]
help_text:
brief: Get the IAM policy for a folder.
description: |
*{command}* displays the IAM policy associated with a folder.
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 folder, run:
$ {command} my-folder
request:
collection: cloudresourcemanager.folders
api_version: v2
arguments:
resource:
help_text: The ID of the folder for which to display the IAM policy.
spec: !REF googlecloudsdk.command_lib.resource_manager.resources:folder
iam:
policy_version: 3
get_iam_policy_version_path: getIamPolicyRequest.options.requestedPolicyVersion

View File

@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 list all folder IDs associated with the active user."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
class ListBeta(base.ListCommand):
r"""List folders accessible by the active account.
List all folders to which the user has access under the specified
parent (either an Organization or a Folder). Exactly one of --folder
or --organization must be provided.
## EXAMPLES
The following command lists folders under org with ID `123456789`:
$ {command} --organization=123456789
The following command lists folders under folder with ID `123456789`:
$ {command} --folder=123456789
The following command lists all the folders including the delete requested
ones under the folder with ID `123456789`:
$ {command} --folder=123456789 --show-deleted
The following command lists only the deleted folders under folder with
ID `123456789`:
$ {command} --folder=123456789 --show-deleted \
--filter='lifecycleState:DELETE_REQUESTED':
"""
@staticmethod
def Args(parser):
flags.FolderIdFlag('to list folders under').AddToParser(parser)
flags.OrganizationIdFlag('to list folders under').AddToParser(parser)
parser.add_argument(
'--show-deleted',
action='store_true',
help="""\
Put --show-deleted flag to include folders
for which delete is requested.
""")
parser.display_info.AddFormat("""
table(
displayName:label=DISPLAY_NAME,
parent:label=PARENT_NAME,
name.segment():label=ID:align=right:sort=1,
lifecycleState
)
""")
def Run(self, args):
"""Run the list command."""
flags.CheckParentFlags(args)
return list_pager.YieldFromList(
folders.FoldersService(),
folders.FoldersMessages().CloudresourcemanagerFoldersListRequest(
parent=flags.GetParentFromFlags(args),
showDeleted=args.show_deleted),
limit=args.limit,
batch_size_attribute='pageSize',
batch_size=args.page_size,
field='folders')
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List folders accessible by the active account.
List all folders to which the user has access under the specified
parent (either an Organization or a Folder). Exactly one of --folder
or --organization must be provided.
## EXAMPLES
The following command lists folders under org with ID `123456789`:
$ {command} --organization=123456789
The following command lists folders under folder with ID `123456789`:
$ {command} --folder=123456789
"""
@staticmethod
def Args(parser):
flags.FolderIdFlag('to list folders under').AddToParser(parser)
flags.OrganizationIdFlag('to list folders under').AddToParser(parser)
parser.display_info.AddFormat("""
table(
displayName:label=DISPLAY_NAME,
parent:label=PARENT_NAME,
name.segment():label=ID:align=right:sort=1
)
""")
def Run(self, args):
"""Run the list command."""
flags.CheckParentFlags(args)
return list_pager.YieldFromList(
folders.FoldersService(),
folders.FoldersMessages().CloudresourcemanagerFoldersListRequest(
parent=flags.GetParentFromFlags(args)),
limit=args.limit,
batch_size_attribute='pageSize',
batch_size=args.page_size,
field='folders')

View File

@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 move a folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.api_lib.resource_manager import operations
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Move(base.UpdateCommand):
"""Move a folder to a new position within the same organization.
Move the given folder under a new parent folder or under the organization.
Exactly one of --folder or --organization must be provided.
This command can fail for the following reasons:
* There is no folder with the given ID.
* There is no parent with the given type and ID.
* The new parent is not in the same organization of the given folder.
* Permission missing for performing this move.
## EXAMPLES
The following command moves a folder with the ID `123456789` into a
folder with the ID `2345`:
$ {command} 123456789 --folder=2345
The following command moves a folder with the ID `123456789` into an
organization with ID `1234`:
$ {command} 123456789 --organization=1234
"""
@staticmethod
def Args(parser):
flags.FolderIdArg('you want to move.').AddToParser(parser)
flags.OperationAsyncFlag().AddToParser(parser)
flags.AddParentFlagsToParser(parser)
def Run(self, args):
flags.CheckParentFlags(args)
messages = folders.FoldersMessages()
move_request = messages.CloudresourcemanagerFoldersMoveRequest(
foldersId=args.id,
moveFolderRequest=messages.MoveFolderRequest(
destinationParent=flags.GetParentFromFlags(args)))
operation = folders.FoldersService().Move(move_request)
if args.async_:
return operation
else:
if operation.done and not operation.name:
log.status.Print('No changes necessary.')
return
finished_op = operations.WaitForOperation(operation)
result = operations.ExtractOperationResponse(finished_op, messages.Folder)
log.UpdatedResource(result)

View File

@@ -0,0 +1,40 @@
release_tracks: [GA, BETA, ALPHA]
help_text:
brief: Remove IAM policy binding for a folder
description: |
Removes a policy binding to the IAM policy of a folder, given a folder ID and the binding. One
binding consists of a member, a role, and an optional condition.
examples: |
To remove an IAM policy binding for the role of 'roles/editor' for the user
'test-user@gmail.com' on the folder 'folder-id', run:
$ {command} folder-id --member='user:test-user@gmail.com' --role='roles/editor'
To remove an IAM policy binding with a condition of
expression='request.time < timestamp("2019-01-01T00:00:00Z")', title='expires_end_of_2018',
and description='Expires at midnight on 2018-12-31' for the role of 'roles/storage.objectAdmin'
for the user 'test-user@gmail.com' on the folder 'folder-id', run:
$ {command} folder-id --member='user:test-user@gmail.com' --role='roles/storage.objectAdmin' --condition='expression=request.time < timestamp("2019-01-01T00:00:00Z"),title=expires_end_of_2018,description=Expires at midnight on 2018-12-31'
To remove all IAM policy bindings regardless of the condition for the role of
'roles/storage.objectAdmin' and for the user 'test-user@gmail.com' on the folder 'folder-id', run:
$ {command} folder-id --member='user:test-user@gmail.com' --role='roles/storage.objectAdmin' --all
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
request:
collection: cloudresourcemanager.folders
api_version: v2
arguments:
resource:
help_text: The ID of the folder to remove the IAM binding.
spec: !REF googlecloudsdk.command_lib.resource_manager.resources:folder
iam:
enable_condition: true
policy_version: 3
get_iam_policy_version_path: getIamPolicyRequest.options.requestedPolicyVersion

View File

@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*- #
# Copyright 2022 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to search folders associated with the active user."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import sys
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Search(base.Command):
"""Search folders matching the specified query.
You can specify the maximum number of folders to return in the result
using the `--limit`flag.
## EXAMPLES
The following command lists the folders that have been marked for deletion:
$ {command} --query='state:DELETE_REQUESTED'
Folders with their displayNames starting with sun like sunflower-folder,
sunburn-folder etc. can be listed using the below command
$ {command} --query='displayName:sun*'
"""
FOLDERS_API_VERSION = 'v3'
@staticmethod
def Args(parser):
parser.display_info.AddFormat("""
table(
displayName,
name,
parent,
state
)
""")
base.LIMIT_FLAG.AddToParser(parser)
base.SORT_BY_FLAG.AddToParser(parser)
parser.add_argument(
'--query',
help="""\
A boolean expression for the search criteria used to select the folders to return.
If no search criteria is specified then all accessible projects will be returned.
Query expressions can be used to restrict results based upon displayName, state
and parent, where the operators `=` (`:`) `NOT`, `AND` and `OR` can be used along
with the suffix wildcard symbol `*`. The `displayName` field in a query expression should
use escaped quotes for values that include whitespace to prevent unexpected behavior.
For more details and fields supported by the query expression please refer
query parameters section `[here]
(https://cloud.google.com/resource-manager/reference/rest/v3/folders/search#query-parameters)`
""")
parser.add_argument(
'--page-size',
type=arg_parsers.BoundedInt(1, sys.maxsize, unlimited=True),
require_coverage_in_tests=False,
category=base.LIST_COMMAND_FLAGS,
help="""\
This flag specifies the maximum number of folders per page.
""")
def Run(self, args):
"""Run the search command."""
return list_pager.YieldFromList(
folders.FoldersService(self.FOLDERS_API_VERSION),
folders.FoldersMessages(
self.FOLDERS_API_VERSION).CloudresourcemanagerFoldersSearchRequest(
query=args.query),
method='Search',
limit=args.limit,
batch_size_attribute='pageSize',
batch_size=args.page_size,
field='folders')

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to set IAM policy for a folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.resource_manager import flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class SetIamPolicy(base.Command):
"""Set IAM policy for a folder.
Sets the IAM policy for a folder, given a folder ID and a file encoded in
JSON or YAML that contains the IAM policy.
## EXAMPLES
The following command reads an IAM policy defined in a JSON file `policy.json`
and sets it for a folder with the ID `3589215982`:
$ {command} 3589215982 policy.json
"""
@staticmethod
def Args(parser):
flags.FolderIdArg('whose policy you want to set.').AddToParser(parser)
parser.add_argument(
'policy_file', help='JSON or YAML file with the IAM policy.')
def Run(self, args):
messages = folders.FoldersMessages()
policy, update_mask = iam_util.ParsePolicyFileWithUpdateMask(
args.policy_file, messages.Policy)
policy.version = iam_util.MAX_LIBRARY_IAM_SUPPORTED_VERSION
# To preserve the existing set-iam-policy behavior of always overwriting
# bindings and etag, add bindings and etag to update_mask.
if 'bindings' not in update_mask:
update_mask += ',bindings'
if 'etag' not in update_mask:
update_mask += ',etag'
result = folders.SetIamPolicy(args.id, policy, update_mask)
iam_util.LogSetIamPolicy(args.id, 'folder')
return result

View File

@@ -0,0 +1,58 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 undelete a folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Undelete(base.CreateCommand):
"""Undelete a folder.
Undeletes the folder with the given folder ID.
This command can fail for the following reasons:
* There is no folder with the given ID.
* The active account does not have Owner or Editor permissions for the
given folder.
* When the folder to be undeleted has the same display name as an active
folder under this folder's parent.
## EXAMPLES
The following command undeletes the folder with the ID `3589215982`:
$ {command} 3589215982
"""
@staticmethod
def Args(parser):
flags.FolderIdArg('you want to undelete.').AddToParser(parser)
def Run(self, args):
service = folders.FoldersService()
messages = folders.FoldersMessages()
restored = service.Undelete(
messages.CloudresourcemanagerFoldersUndeleteRequest(
foldersId=args.id))
log.RestoredResource(restored)

View File

@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to update a folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import folders
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Update(base.UpdateCommand):
"""Update the display name of a folder.
Updates the given folder with new folder name.
This command can fail for the following reasons:
* There is no folder with the given ID.
* The active account does not have permission to update the given
folder.
* The new display name is taken by another folder under this folder's
parent.
## EXAMPLES
The following command updates a folder with the ID `123456789` to have
the name "Foo Bar and Grill":
$ {command} 123456789 --display-name="Foo Bar and Grill"
"""
@staticmethod
def Args(parser):
flags.FolderIdArg('you want to update.').AddToParser(parser)
parser.add_argument(
'--display-name',
required=True,
help='New display name for the folder (unique under the same parent).')
def Run(self, args):
folder = folders.GetFolder(args.id)
folder.displayName = args.display_name
request = folders.FoldersMessages().CloudresourcemanagerFoldersPatchRequest(
folder=folder, foldersId=args.id, updateMask='display_name')
log.UpdatedResource(folders.FoldersService().Patch(request))

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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.
"""The group for the Cloud Resource Manager Liens CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import liens
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Liens(base.Group):
"""Manage Cloud Resource Manager Liens.
Commands to manage your Cloud Resource Liens.
"""
@staticmethod
def Args(parser):
parser.display_info.AddUriFunc(liens.GetUri)

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command group for managing Cloud Resource Manager lien configurations."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Config(base.Group):
"""Manage Cloud Resource Manager lien configurations."""

View File

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

View File

@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*- #
# Copyright 2015 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to create a new Lien."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import error
from googlecloudsdk.api_lib.resource_manager import liens
from googlecloudsdk.calliope import base
from googlecloudsdk.core import properties
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Create(base.CreateCommand):
"""Create a new lien.
Creates a new lien to be applied to a project.
"""
@staticmethod
def Args(parser):
base.Argument(
'--restrictions',
required=True,
help='Comma separated list of IAM permissions to curtail.').AddToParser(
parser)
base.Argument(
'--reason',
required=True,
help='Human-readable description of why this lien is being applied.'
).AddToParser(parser)
base.Argument(
'--origin',
required=False,
help='Origin of this lien. Defaults to user identity.'
).AddToParser(parser)
@error.EmitErrorDetails
def Run(self, args):
parent = 'projects/' + properties.VALUES.core.project.Get(required=True)
# Origin is a required field which will default to the account property if
# not specified.
origin = args.origin
if not origin:
origin = properties.VALUES.core.account.Get(required=True)
messages = liens.LiensMessages()
return liens.LiensService().Create(
messages.Lien(
parent=parent,
restrictions=args.restrictions.split(','),
origin=origin,
reason=args.reason))

View File

@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 delete a lien."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import error
from googlecloudsdk.api_lib.resource_manager import liens
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Delete(base.DeleteCommand):
"""Delete a lien.
Delete a lien, given a valid lien ID.
This command can fail for the following reasons:
* There is no lien with the given ID.
* The active account does not have permission to delete the given lien.
## EXAMPLES
The following command deletes a lien with the ID `p8765-kjasdkkhsd`:
$ {command} p8765-kjasdkkhsd
"""
@staticmethod
def Args(parser):
flags.LienIdArg('you want to delete.').AddToParser(parser)
@error.EmitErrorDetails
def Run(self, args):
service = liens.LiensService()
messages = liens.LiensMessages()
service.Delete(
messages.CloudresourcemanagerLiensDeleteRequest(liensId=args.id))
log.DeletedResource(liens.LienIdToName(args.id))

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 list all lien IDs associated for the specified project."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.resource_manager import error
from googlecloudsdk.api_lib.resource_manager import liens
from googlecloudsdk.calliope import base
from googlecloudsdk.core import properties
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class List(base.ListCommand):
"""List liens associated with the specified project.
List all liens which are associated with the specified project.
"""
@staticmethod
def Args(parser):
parser.display_info.AddFormat("""
table(
name.segment(),
origin,
reason
)
""")
@error.YieldErrorDetails
def Run(self, args):
"""Run the list command."""
parent = 'projects/' + properties.VALUES.core.project.Get(required=True)
return list_pager.YieldFromList(
liens.LiensService(),
liens.LiensMessages().CloudresourcemanagerLiensListRequest(
parent=parent),
limit=args.limit,
batch_size_attribute='pageSize',
batch_size=args.page_size,
field='liens')

View File

@@ -0,0 +1,34 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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.
"""The group for the Cloud Resource Manager Operations CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import operations
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Operations(base.Group):
"""Query Cloud Resource Manager long-running operations.
Commands to query long-running operations created in Cloud Resource Manager.
"""
@staticmethod
def Args(parser):
parser.display_info.AddUriFunc(operations.GetUri)

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*- #
# Copyright 2016 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 show metadata for a specified folder."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import operations
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils
from googlecloudsdk.command_lib.resource_manager import flags
from googlecloudsdk.command_lib.resource_manager import tag_arguments
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Describe(base.DescribeCommand):
"""Show metadata for an operation.
Show metadata for an operation, given a valid operation ID.
This command can fail for the following reasons:
* The operation specified does not exist.
* You do not have permission to view the operation.
## EXAMPLES
The following command prints metadata for an operation with the
ID `fc.3589215982`:
$ {command} fc.3589215982
"""
@staticmethod
def Args(parser):
flags.OperationIdArg('you want to describe.').AddToParser(parser)
tag_arguments.AddLocationArgToParser(parser, (
'Region or zone of the Operation to get. This field is not required if '
'the Operation is on a global resource such as a Project or TagKey.'))
def Run(self, args):
location = args.location if args.IsSpecified('location') else None
with endpoint_utils.CrmEndpointOverrides(location):
return operations.GetOperationV3(args.id)

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The group for the Org Policies CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.DefaultUniverseOnly
class OrgPolicies(base.Group):
"""Manage Org Policies.
Commands to query and to update your Org Policies.
"""

View File

@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to add allowed values to an Organization Policy list policy."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import exceptions
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
import six
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Allow(base.Command):
"""Add values to an Organization Policy allowed_values list policy.
Adds one or more values to the specified Organization Policy allowed_values
list policy associated with the specified resource.
## EXAMPLES
The following command adds `devEnv` and `prodEnv` to an Organization Policy
allowed_values list policy for constraint `serviceuser.services`
on project `foo-project`:
$ {command} serviceuser.services --project=foo-project devEnv prodEnv
"""
@staticmethod
def Args(parser):
flags.AddIdArgToParser(parser)
flags.AddParentResourceFlagsToParser(parser)
base.Argument(
'allowed_value',
metavar='ALLOWED_VALUE',
nargs='+',
help='The values to add to the allowed_values list policy.',
).AddToParser(parser)
# TODO(b/73831954):consider refactoring
def Run(self, args):
messages = org_policies.OrgPoliciesMessages()
service = org_policies_base.OrgPoliciesService(args)
policy = service.GetOrgPolicy(org_policies_base.GetOrgPolicyRequest(args))
if policy.booleanPolicy or (policy.listPolicy and
policy.listPolicy.deniedValues):
raise exceptions.ResourceManagerError(
'Cannot add values to a non-allowed_values list policy.')
if policy.listPolicy and policy.listPolicy.allValues:
raise exceptions.ResourceManagerError(
'Cannot add values if all_values is already specified.')
if policy.listPolicy and policy.listPolicy.allowedValues:
for value in args.allowed_value:
policy.listPolicy.allowedValues.append(six.text_type(value))
else:
policy.listPolicy = messages.ListPolicy(allowedValues=args.allowed_value)
if policy.restoreDefault:
policy.restoreDefault = None
return service.SetOrgPolicy(
org_policies_base.SetOrgPolicyRequest(args, policy))

View File

@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to delete an Organization Policy."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class DeletePolicy(base.DeleteCommand):
"""Delete an Organization Policy.
Deletes an Organization Policy associated with the specified resource.
## EXAMPLES
The following command clears an Organization Policy for constraint
`serviceuser.services` on project `foo-project`:
$ {command} serviceuser.services --project=foo-project
"""
@staticmethod
def Args(parser):
flags.AddIdArgToParser(parser)
flags.AddParentResourceFlagsToParser(parser)
def Run(self, args):
service = org_policies_base.OrgPoliciesService(args)
result = service.ClearOrgPolicy(self.ClearOrgPolicyRequest(args))
log.DeletedResource(result)
@staticmethod
def ClearOrgPolicyRequest(args):
messages = org_policies.OrgPoliciesMessages()
resource_id = org_policies_base.GetResource(args)
request = messages.ClearOrgPolicyRequest(
constraint=org_policies.FormatConstraint(args.id))
if args.project:
return messages.CloudresourcemanagerProjectsClearOrgPolicyRequest(
projectsId=resource_id, clearOrgPolicyRequest=request)
elif args.organization:
return messages.CloudresourcemanagerOrganizationsClearOrgPolicyRequest(
organizationsId=resource_id, clearOrgPolicyRequest=request)
elif args.folder:
return messages.CloudresourcemanagerFoldersClearOrgPolicyRequest(
foldersId=resource_id, clearOrgPolicyRequest=request)
return None

View File

@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to add denied values to an Organization Policy list policy."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import exceptions
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
import six
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Deny(base.Command):
r"""Add values to an Organization Policy denied_values list policy.
Adds one or more values to the specified Organization Policy denied_values
list policy associated with the specified resource.
## EXAMPLES
The following command adds `devEnv` and `prodEnv` to an Organization Policy
denied_values list policy for constraint `serviceuser.services`
on project `foo-project`:
$ {command} serviceuser.services --project=foo-project devEnv prodEnv
"""
@staticmethod
def Args(parser):
flags.AddIdArgToParser(parser)
flags.AddParentResourceFlagsToParser(parser)
base.Argument(
'denied_value',
metavar='DENIED_VALUE',
nargs='+',
help='The values to add to the denied_values list policy.',
).AddToParser(parser)
# TODO(b/73831954):consider refactoring
def Run(self, args):
messages = org_policies.OrgPoliciesMessages()
service = org_policies_base.OrgPoliciesService(args)
policy = service.GetOrgPolicy(org_policies_base.GetOrgPolicyRequest(args))
if policy.booleanPolicy or (policy.listPolicy and
policy.listPolicy.allowedValues):
raise exceptions.ResourceManagerError(
'Cannot add values to a non-denied_values list policy.')
if policy.listPolicy and policy.listPolicy.allValues:
raise exceptions.ResourceManagerError(
'Cannot add values if all_values is already specified.')
if policy.listPolicy and policy.listPolicy.deniedValues:
for value in args.denied_value:
policy.listPolicy.deniedValues.append(six.text_type(value))
else:
policy.listPolicy = messages.ListPolicy(deniedValues=args.denied_value)
if policy.restoreDefault:
policy.restoreDefault = None
return service.SetOrgPolicy(
org_policies_base.SetOrgPolicyRequest(args, policy))

View File

@@ -0,0 +1,92 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to describe an Organization Policy."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import exceptions
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an Organization Policy.
Describes an Organization Policy associated with the specified resource.
## EXAMPLES
The following command retrieves an Organization Policy
for constraint `serviceuser.services` on project `foo-project`:
$ {command} serviceuser.services --project=foo-project
The following command retrieves the effective Organization Policy
for constraint `serviceuser.services` on project `foo-project`:
$ {command} serviceuser.services --project=foo-project --effective
"""
POLICY_V2_WARNING = ('This policy has been set with Tags through Organization'
' Policy V2 API, please use `gcloud org-policies` '
'commands instead.')
@staticmethod
def Args(parser):
flags.AddIdArgToParser(parser)
flags.AddParentResourceFlagsToParser(parser)
base.Argument(
'--effective',
action='store_true',
required=False,
default=False,
help='Show the effective policy.').AddToParser(parser)
def Run(self, args):
service = org_policies_base.OrgPoliciesService(args)
if not args.effective:
response = service.GetOrgPolicy(
org_policies_base.GetOrgPolicyRequest(args))
if response.version is not None and response.version == 2:
raise exceptions.ResourceManagerError(self.POLICY_V2_WARNING)
else:
response = service.GetEffectiveOrgPolicy(
self.GetEffectiveOrgPolicyRequest(args))
return response
@staticmethod
def GetEffectiveOrgPolicyRequest(args):
m = org_policies.OrgPoliciesMessages()
resource_id = org_policies_base.GetResource(args)
request = m.GetEffectiveOrgPolicyRequest(
constraint=org_policies.FormatConstraint(args.id))
if args.project:
return m.CloudresourcemanagerProjectsGetEffectiveOrgPolicyRequest(
projectsId=resource_id, getEffectiveOrgPolicyRequest=request)
elif args.organization:
return m.CloudresourcemanagerOrganizationsGetEffectiveOrgPolicyRequest(
organizationsId=resource_id, getEffectiveOrgPolicyRequest=request)
elif args.folder:
return m.CloudresourcemanagerFoldersGetEffectiveOrgPolicyRequest(
foldersId=resource_id, getEffectiveOrgPolicyRequest=request)
return None

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to turn off enforcement of a boolean constraint."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class DisableEnforce(base.Command):
"""Turns off enforcement of boolean Organization Policy constraint.
Turns off enforcement of a boolean Organization Policy constraint at
the specified resource.
## EXAMPLES
The following command disables enforcement of the Organization Policy boolean
constraint `compute.disableSerialPortAccess` on project `foo-project`:
$ {command} compute.disableSerialPortAccess --project=foo-project
"""
@staticmethod
def Args(parser):
flags.AddIdArgToParser(parser)
flags.AddParentResourceFlagsToParser(parser)
def Run(self, args):
service = org_policies_base.OrgPoliciesService(args)
messages = org_policies.OrgPoliciesMessages()
return service.SetOrgPolicy(
org_policies_base.SetOrgPolicyRequest(
args,
messages.OrgPolicy(
constraint=org_policies.FormatConstraint(args.id),
booleanPolicy=messages.BooleanPolicy(enforced=False))))

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to turn on enforcement of a boolean constraint."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class EnableEnforce(base.Command):
"""Turns on enforcement of boolean Organization Policy constraint.
Turns on enforcement of a boolean Organization Policy constraint at
the specified resource.
## EXAMPLES
The following command enables enforcement of the Organization Policy boolean
constraint `compute.disableSerialPortAccess` on project `foo-project`:
$ {command} compute.disableSerialPortAccess --project=foo-project
"""
@staticmethod
def Args(parser):
flags.AddIdArgToParser(parser)
flags.AddParentResourceFlagsToParser(parser)
def Run(self, args):
service = org_policies_base.OrgPoliciesService(args)
messages = org_policies.OrgPoliciesMessages()
return service.SetOrgPolicy(
org_policies_base.SetOrgPolicyRequest(
args,
messages.OrgPolicy(
constraint=org_policies.FormatConstraint(args.id),
booleanPolicy=messages.BooleanPolicy(enforced=True))))

View File

@@ -0,0 +1,121 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# pylint: disable=line-too-long
"""Command to list Organization Policies associated with the specified resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List Organization Policies associated with the specified resource.
## EXAMPLES
The following command lists all set Organization Policies associated with
project `foo-project`:
$ {command} --project=foo-project
The following command lists all available constraints in addition to set
Organization Policies associated with project `foo-project`:
$ {command} --project=foo-project --show-unset
"""
@staticmethod
def Args(parser):
flags.AddParentResourceFlagsToParser(parser)
base.Argument(
'--show-unset',
action='store_true',
required=False,
default=False,
help="""
Show available constraints. For more information about constraints, see
https://cloud.google.com/resource-manager/docs/organization-policy/understanding-constraints
""").AddToParser(parser)
parser.display_info.AddFormat("""
table(
constraint,
listPolicy.yesno(no="-", yes="SET"),
booleanPolicy.yesno(no="-", yes="SET"),
etag
)
""")
def Run(self, args):
service = org_policies_base.OrgPoliciesService(args)
response = service.ListOrgPolicies(self.ListOrgPoliciesRequest(args))
if args.show_unset:
constraints = service.ListAvailableOrgPolicyConstraints(
self.ListAvailableOrgPolicyConstraintsRequest(args))
existing_policies = [policy.constraint for policy in response.policies]
messages = org_policies.OrgPoliciesMessages()
for constraint in constraints.constraints:
if constraint.name not in existing_policies:
response.policies.append(
messages.OrgPolicy(constraint=constraint.name))
return response.policies
@staticmethod
def ListOrgPoliciesRequest(args):
messages = org_policies.OrgPoliciesMessages()
resource_id = org_policies_base.GetResource(args)
request = messages.ListOrgPoliciesRequest()
if args.project:
return messages.CloudresourcemanagerProjectsListOrgPoliciesRequest(
projectsId=resource_id, listOrgPoliciesRequest=request)
elif args.organization:
return messages.CloudresourcemanagerOrganizationsListOrgPoliciesRequest(
organizationsId=resource_id, listOrgPoliciesRequest=request)
elif args.folder:
return messages.CloudresourcemanagerFoldersListOrgPoliciesRequest(
foldersId=resource_id, listOrgPoliciesRequest=request)
return None
@staticmethod
def ListAvailableOrgPolicyConstraintsRequest(args):
messages = org_policies.OrgPoliciesMessages()
resource_id = org_policies_base.GetResource(args)
request = messages.ListAvailableOrgPolicyConstraintsRequest()
if args.project:
# pylint: disable=line-too-long
return messages.CloudresourcemanagerProjectsListAvailableOrgPolicyConstraintsRequest(
projectsId=resource_id,
listAvailableOrgPolicyConstraintsRequest=request)
elif args.organization:
# pylint: disable=line-too-long
return messages.CloudresourcemanagerOrganizationsListAvailableOrgPolicyConstraintsRequest(
organizationsId=resource_id,
listAvailableOrgPolicyConstraintsRequest=request)
elif args.folder:
# pylint: disable=line-too-long
return messages.CloudresourcemanagerFoldersListAvailableOrgPolicyConstraintsRequest(
foldersId=resource_id,
listAvailableOrgPolicyConstraintsRequest=request)
return None

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*- #
# Copyright 2017 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to set an Organization Policy."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import org_policies
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import org_policies_base
from googlecloudsdk.command_lib.resource_manager import org_policies_flags as flags
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class SetPolicy(base.DescribeCommand):
"""Set Organization Policy.
Sets an Organization Policy associated with the specified resource from
a file that contains the JSON or YAML encoded Organization Policy.
## EXAMPLES
Organization policy list constraint YAML file example:
constraint: constraints/CONSTRAINT_NAME
listPolicy:
deniedValues:
- VALUE_A
Organization policy list constraint JSON file example:
{
"constraint": "constraints/CONSTRAINT_NAME",
"listPolicy": {
"deniedValues": ["VALUE_A"]
}
}
The following command sets an Organization Policy for a constraint
on project `foo-project` from file `/tmp/policy.yaml`:
$ {command} --project=foo-project /tmp/policy.yaml
"""
@staticmethod
def Args(parser):
flags.AddParentResourceFlagsToParser(parser)
base.Argument(
'policy_file',
help='JSON or YAML file with the Organization Policy.').AddToParser(
parser)
def Run(self, args):
service = org_policies_base.OrgPoliciesService(args)
messages = org_policies.OrgPoliciesMessages()
return service.SetOrgPolicy(
org_policies_base.SetOrgPolicyRequest(args,
org_policies.GetFileAsMessage(
args.policy_file,
messages.OrgPolicy)))

View File

@@ -0,0 +1,39 @@
# -*- 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.
"""The command group for the Resource Settings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.Hidden
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ResourceSettings(base.Group):
"""Create and manage Resource Settings.
The gcloud Resource Settings command group lets you create and manipulate
Resource Settings.
The Resource Settings Service is a hierarchy-aware service with a
public-facing API for end-users to store settings that modify the behavior of
their Google Cloud Platform resources (e.g., VM, firewall, Project, etc.).
The settings are attached at the project level and above and can influence CRM
resources as well as sub-project resources that are descendants of the setting
attachment point.
"""

View File

@@ -0,0 +1,73 @@
# -*- 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.
"""Unset-value command for the Resource Settings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager.settings import utils as api_utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager.settings import arguments
from googlecloudsdk.command_lib.resource_manager.settings import utils
from googlecloudsdk.core.console import console_io
@base.Hidden
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Clear(base.DescribeCommand):
r"""Remove the value of a resource setting.
Remove the value of a resource setting. This reverts the resource to
inheriting the resource settings from above it in the resource hierarchy,
if any is set on a resource above it.
## EXAMPLES
To unset the resource settings ``net-preferredDnsServers'' with the
project ``foo-project'', run:
$ {command} net-preferredDnsServers --project=foo-project
"""
@staticmethod
def Args(parser):
arguments.AddSettingsNameArgToParser(parser)
arguments.AddResourceFlagsToParser(parser)
def Run(self, args):
"""Unset the resource settings.
Args:
args: argparse.Namespace, An object that contains the values for the
arguments specified in the Args method.
Returns:
The deleted settings.
"""
settings_service = api_utils.GetServiceFromArgs(args)
setting_name = utils.GetSettingsPathFromArgs(args)
if not console_io.PromptContinue(
message=('Your setting will be cleared.'),
):
return None
get_request = api_utils.GetDeleteValueRequestFromArgs(args, setting_name)
setting_value = settings_service.Clear(get_request)
return setting_value

View File

@@ -0,0 +1,87 @@
# -*- 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.
"""Describe command for the Resource Settings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager.settings import utils as api_utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager.settings import arguments
from googlecloudsdk.command_lib.resource_manager.settings import utils
@base.Hidden
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Describe(base.DescribeCommand):
r"""Get a resource setting.
Get a resource setting
## EXAMPLES
To describe the resource settings ``iam-projectCreatorRoles'' with the
Project ``foo-project'', run:
$ {command} iam-projectCreatorRoles --project=foo-project
"""
@staticmethod
def Args(parser):
arguments.AddSettingsNameArgToParser(parser)
arguments.AddResourceFlagsToParser(parser)
parser.add_argument(
'--effective',
action='store_true',
help='Describe the effective setting.',
)
def Run(self, args):
"""Get the (effective) resource settings.
If --effective is not specified, it is a regular resource setting.
If --effective is specified, it is an effective setting.
Args:
args: argparse.Namespace, An object that contains the values for the
arguments specified in the Args method.
Returns:
The retrieved settings.
"""
if args.effective:
settings_service = api_utils.GetEffectiveServiceFromArgs(args)
setting_name = utils.GetEffectiveSettingsPathFromArgs(args)
get_request = api_utils.GetDescribeRequestFromArgs(
args, setting_name, True
)
setting_value = settings_service.Get(get_request)
return setting_value
else:
settings_service = api_utils.GetServiceFromArgs(args)
setting_name = utils.GetSettingsPathFromArgs(args)
get_request = api_utils.GetDescribeRequestFromArgs(
args, setting_name, False
)
setting_value = settings_service.Get(get_request)
return setting_value

View File

@@ -0,0 +1,56 @@
# -*- 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.
"""List command for the Resource Settings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager.settings import utils as api_utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager.settings import arguments
from googlecloudsdk.command_lib.resource_manager.settings import utils
@base.Hidden
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class List(base.ListCommand):
r"""List all available resource settings.
List all available resource settings. ## EXAMPLES To list all available
resource settings with the project ``foo-project'', run:
$ {command} --project=foo-project
"""
@staticmethod
def Args(parser):
arguments.AddResourceFlagsToParser(parser)
def Run(self, args):
"""Get the resource settings.
Args:
args: argparse.Namespace, An object that contains the values for the
arguments specified in the Args method.
Returns:
The retrieved settings.
"""
settings_service = api_utils.GetServiceFromArgs(args)
parent_resource = utils.GetParentResourceFromArgs(args)
get_request = api_utils.GetListRequestFromArgs(args, parent_resource)
setting_value = settings_service.List(get_request)
return setting_value

View File

@@ -0,0 +1,88 @@
# -*- 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.
"""Set-policy command for the Resource Settings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from argcomplete import completers
from googlecloudsdk.api_lib.resource_manager.settings import service
from googlecloudsdk.api_lib.resource_manager.settings import utils as api_utils
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager.settings import exceptions
from googlecloudsdk.command_lib.resource_manager.settings import utils
@base.Hidden
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class Update(base.Command):
r"""Update the value of a resource setting.
Update the value of a resource setting.
## EXAMPLES
To set the resource setting from the file with the path ``./sample_path'',
run:
$ {command} --setting-from-file="./test_input.json"
"""
@staticmethod
def Args(parser):
parser.add_argument(
'--setting-from-file',
metavar='setting-from-file',
completer=completers.FilesCompleter,
required=True,
help='Path to JSON or YAML file that contains the resource setting.')
def Run(self, args):
"""Creates or updates a setting from a JSON or YAML file.
Args:
args: argparse.Namespace, An object that contains the values for the
arguments specified in the Args method.
Returns:
The created or updated setting.
"""
settings_message = service.ResourceSettingsMessages()
# TODO(b/379282601): Instead of taking all input from file , if we can use flags
input_setting = utils.GetMessageFromFile(
args.setting_from_file, settings_message.Setting)
if not input_setting.name:
raise exceptions.InvalidInputError(
'Name field not present in the resource setting.')
if not utils.ValidateSettingPath(input_setting.name):
raise exceptions.InvalidInputError('Name field has invalid syntax')
resource_type = utils.GetResourceTypeFromString(input_setting.name)
settings_service = api_utils.GetServiceFromResourceType(resource_type)
# Syntax: [organizations|folders|projects]/{resource_id}/
# settings/{setting_name}
setting_path = input_setting.name
etag = input_setting.etag if hasattr(input_setting, 'etag') else None
update_request = api_utils.GetPatchRequestFromResourceType(
resource_type, setting_path, input_setting.value, etag)
update_response = settings_service.Patch(update_request)
return update_response

View File

@@ -0,0 +1,34 @@
# -*- 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.
"""The command group for the Resource Manager CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Tags(base.Group):
"""Create and manipulate tag keys, values and bindings.
The Tags Service gives you centralized and programmatic
control over your organization's tags. As the tag
administrator, you will be able to create and configure restrictions across
the tags in your organization or projects. As the tag user, you will be able
to attach tags values to different resources.
"""

View File

@@ -0,0 +1,35 @@
# -*- 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.
"""The command group for the Resource Manager CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class TagBindings(base.Group):
"""Create and manipulate TagBindings.
The Resource Manager Service gives you centralized and programmatic
control over your organization or project's Tags. As the tag
administrator, you will be able to create and configure restrictions across
the tags in your organization or projects. As the tag user, you will be able
to attach TagValues to different resources as a TagBinding.
"""

View File

@@ -0,0 +1,108 @@
# -*- 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.
"""Create command for the Resource Manager - Tag Bindings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils as endpoints
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Create(base.Command):
"""Creates a TagBinding resource.
Creates a TagBinding given the TagValue and the parent cloud resource the
TagValue will be attached to. The TagValue can be represented with its
numeric id or its namespaced name of
{parent_namespace}/{tag_key_short_name}/{tag_value_short_name}. The parent
resource should be represented with its full resource name. See:
https://cloud.google.com/apis/design/resource_names#full_resource_name.
"""
detailed_help = {
"EXAMPLES":
"""
To create a TagBinding between tagValues/123 and Project with name
``//cloudresourcemanager.googleapis.com/projects/1234'' run:
$ {command} --tag-value=tagValues/123 --parent=//cloudresourcemanager.googleapis.com/projects/1234
To create a TagBinding between TagValue ``test'' under TagKey ``env'' and
Project with name ``//cloudresourcemanager.googleapis.com/projects/1234'' run:
$ {command} --tag-value=789/env/test --parent=//cloudresourcemanager.googleapis.com/projects/1234
"""
}
@staticmethod
def Args(parser):
arguments.AddTagValueArgToParser(parser)
arguments.AddParentArgToParser(
parser,
message="Full resource name of the resource to attach to the tagValue.")
arguments.AddAsyncArgToParser(parser)
arguments.AddLocationArgToParser(
parser,
("Region or zone of the resource to bind to the TagValue. This "
"field is not required if the resource is a global resource like "
"projects, folders and organizations."))
def Run(self, args):
messages = tags.TagMessages()
tag_value = None
tag_value_namespaced_name = None
if args.tag_value.find("tagValues/") == 0:
tag_value = args.tag_value
else:
tag_value_namespaced_name = args.tag_value
location = args.location if args.IsSpecified("location") else None
resource_name = tag_utils.GetCanonicalResourceName(
args.parent, location, base.ReleaseTrack.GA)
if tag_value is not None:
tag_binding = messages.TagBinding(
parent=resource_name,
tagValue=tag_value,
)
else:
tag_binding = messages.TagBinding(
parent=resource_name,
tagValueNamespacedName=tag_value_namespaced_name,
)
create_req = messages.CloudresourcemanagerTagBindingsCreateRequest(
tagBinding=tag_binding)
with endpoints.CrmEndpointOverrides(location):
service = tags.TagBindingsService()
op = service.Create(create_req)
if args.async_ or op.done:
return op
else:
return operations.WaitForReturnOperation(
op,
"Waiting for TagBinding for parent [{}] and tag value [{}] to be "
"created with [{}]".format(resource_name, tag_value, op.name))

View File

@@ -0,0 +1,129 @@
# -*- 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.
"""Delete command for the Tag Manager - Tag Bindings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py.exceptions import HttpBadRequestError
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils as endpoints
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
from six.moves.urllib.parse import quote
PROJECTS_PREFIX = "//cloudresourcemanager.googleapis.com/projects/"
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Delete(base.Command):
"""Deletes a TagBinding.
Deletes a TagBinding given the TagValue and the parent resource that the
TagValue is attached to. The parent must be given as the full resource name.
See: https://cloud.google.com/apis/design/resource_names#full_resource_name.
The TagValue can be represented with its numeric id or
its namespaced name of
{parent_namespace}/{tag_key_short_name}/{tag_value_short_name}.
"""
detailed_help = {
"EXAMPLES":
"""
To delete a TagBinding between tagValue/111 and Project with
name ``//cloudresourcemanager.googleapis.com/projects/1234'' run:
$ {command} --tag-value=tagValue/123 --parent=//cloudresourcemanager.googleapis.com/projects/1234
To delete a binding between TagValue test under TagKey ``env'' that
lives under ``organizations/789'' and Project with name ``//cloudresourcemanager.googleapis.com/projects/1234'' run:
$ {command} --tag-value=789/env/test --parent=//cloudresourcemanager.googleapis.com/projects/1234
"""
}
@staticmethod
def Args(parser):
arguments.AddTagValueArgToParser(parser)
arguments.AddParentArgToParser(
parser,
message="Full resource name of the resource attached to the tagValue.")
arguments.AddAsyncArgToParser(parser)
arguments.AddLocationArgToParser(
parser,
("Region or zone of the resource to unbind from the TagValue. This "
"field is not required if the resource is a global resource like "
"projects, folders and organizations."))
def Run(self, args):
location = args.location if args.IsSpecified("location") else None
resource_name = tag_utils.GetCanonicalResourceName(args.parent, location,
base.ReleaseTrack.GA)
if args.tag_value.find("tagValues/") == 0:
tag_value = args.tag_value
else:
tag_value = tag_utils.GetNamespacedResource(
args.tag_value, tag_utils.TAG_VALUES
).name
messages = tags.TagMessages()
binding_name = "/".join(
["tagBindings", quote(resource_name, safe=""), tag_value])
del_req = messages.CloudresourcemanagerTagBindingsDeleteRequest(
name=binding_name)
try:
with endpoints.CrmEndpointOverrides(location):
service = tags.TagBindingsService()
op = service.Delete(del_req)
if args.async_ or op.done:
return op
else:
return operations.WaitForReturnOperation(
op,
"Waiting for TagBinding for resource [{}] and tag value [{}] to "
"be deleted with [{}]".format(
args.parent, args.tag_value, op.name
),
)
except HttpBadRequestError:
if args.parent.find(PROJECTS_PREFIX) != 0:
raise
# Attempt to fetch and delete the binding for the given project id.
binding_name = tag_utils.ProjectNameToBinding(resource_name, tag_value,
location)
del_req = messages.CloudresourcemanagerTagBindingsDeleteRequest(
name=binding_name)
with endpoints.CrmEndpointOverrides(location):
service = tags.TagBindingsService()
op = service.Delete(del_req)
if args.async_ or op.done:
return op
else:
return operations.WaitForReturnOperation(
op,
"Waiting for TagBinding for resource [{}] and tag value [{}] to be "
"deleted with [{}]".format(args.parent, tag_value, op.name))

View File

@@ -0,0 +1,144 @@
# -*- 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 command for the Tag Manager - Tag Bindings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import urllib.parse
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils as endpoints
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
EFFECTIVE_TAG_BINDING_COLLECTION = "effectiveTagBindingCollections/"
TAG_BINDING_COLLECTION = "tagBindingCollections/"
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class List(base.ListCommand):
"""Lists TagBindings bound to the specified resource.
When specifying a parent resource, the full name of the parent resource must
be used. See:
https://cloud.google.com/apis/design/resource_names#full_resource_name.
"""
detailed_help = {
"EXAMPLES":
"""
To list TagBindings for '//cloudresourcemanager.googleapis.com/projects/123' run:
$ {command} --parent=//cloudresourcemanager.googleapis.com/projects/123
"""
}
@staticmethod
def Args(parser):
arguments.AddParentArgToParser(
parser, message="Full resource name attached to the binding")
arguments.AddLocationArgToParser(
parser, ("Region or zone of the resource for listing TagBindings. This "
"field should not be set if the resource is a global resource "
"like projects, folders and organizations."))
arguments.AddEffectiveArgToParser(
parser,
("Show all effective TagBindings on the resource. TagBindings applied "
"at a higher level will be inherited to all descendants."))
def Run(self, args):
show_effective = args.IsSpecified("effective")
if self.ReleaseTrack() == base.ReleaseTrack.ALPHA:
freeform_enabled = True
location = args.location if args.IsSpecified("location") else "global"
if(show_effective):
collection_resource_name = (
f"locations/{location}/{EFFECTIVE_TAG_BINDING_COLLECTION}{args.parent}"
)
else:
collection_resource_name = (
f"locations/{location}/{TAG_BINDING_COLLECTION}{args.parent}"
)
resource_name = tag_utils.GetCanonicalResourceName(
collection_resource_name, location, base.ReleaseTrack.ALPHA)
else:
freeform_enabled = False
location = args.location if args.IsSpecified("location") else None
resource_name = tag_utils.GetCanonicalResourceName(args.parent, location,
base.ReleaseTrack.GA)
with endpoints.CrmEndpointOverrides(location):
messages = tags.TagMessages()
if freeform_enabled:
if show_effective:
service = tags.EffectiveTagsCollectionService()
location, _, tag_binding_collection_name = resource_name.partition(
EFFECTIVE_TAG_BINDING_COLLECTION
)
encoded_resource_name = (
f"{location}{EFFECTIVE_TAG_BINDING_COLLECTION}{urllib.parse.quote(tag_binding_collection_name, safe='')}"
)
list_effective_req = (
messages.CloudresourcemanagerLocationsEffectiveTagBindingCollectionsGetRequest(
name=encoded_resource_name
)
)
return service.Get(list_effective_req)
else:
service = tags.TagBindingsCollectionService()
location, _, tag_binding_collection_name = resource_name.partition(
TAG_BINDING_COLLECTION
)
encoded_resource_name = (
f"{location}{TAG_BINDING_COLLECTION}{urllib.parse.quote(tag_binding_collection_name, safe='')}"
)
list_req = messages.CloudresourcemanagerLocationsTagBindingCollectionsGetRequest(
name=encoded_resource_name
)
return service.Get(list_req)
else:
if show_effective:
service = tags.EffectiveTagsService()
list_effective_req = (
messages.CloudresourcemanagerEffectiveTagsListRequest(
parent=resource_name
)
)
return list_pager.YieldFromList(
service,
list_effective_req,
batch_size_attribute="pageSize",
batch_size=0,
field="effectiveTags",
)
else:
service = tags.TagBindingsService()
list_req = messages.CloudresourcemanagerTagBindingsListRequest(
parent=resource_name
)
return list_pager.YieldFromList(
service,
list_req,
batch_size_attribute="pageSize",
batch_size=args.page_size,
field="tagBindings",
)

View File

@@ -0,0 +1,119 @@
# -*- 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.
"""Update Command for the Resource Manager - Tags Bindings CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import urllib.parse
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils as endpoints
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
@base.DefaultUniverseOnly
class Update(base.Command):
"""Updates TagBindings bound to the specified resource."""
@staticmethod
def Args(parser):
arguments.AddUpdateResourceNameArgToParser(
parser,
message="Full resource name of the resource to attach to the tagValue.",
)
arguments.AddLocationArgToParser(
parser,
(
"Region or zone of the resource to bind to the TagValue. This "
"field is not required if the resource is a global resource like "
"projects, folders and organizations."
),
)
arguments.UpdateTagGroup(parser)
def Run(self, args):
messages = tags.TagMessages()
location = args.location if args.IsSpecified("location") else None
resource_name = tag_utils.GetCanonicalResourceName(
args.resource_name, location, base.ReleaseTrack.ALPHA
)
if location is None:
tag_binding_collection_name = (
"locations/global"
+ "/tagBindingCollections/"
+ urllib.parse.quote(resource_name, safe="")
)
else:
tag_binding_collection_name = (
"locations/"
+ location
+ "/tagBindingCollections/"
+ urllib.parse.quote(resource_name, safe="")
)
list_req = (
messages.CloudresourcemanagerLocationsTagBindingCollectionsGetRequest(
name=tag_binding_collection_name
)
)
with endpoints.CrmEndpointOverrides(location):
list_service = tags.TagBindingsCollectionService()
original = list_service.Get(list_req)
# Initialize update mask to "*" to make a put request. We can update it
# further to support patch requests.
update_mask = "*"
tags_map_to_update = tag_utils.ParseTagGroup(args, original)
tag_bindings = messages.TagBindingCollection.TagsValue()
for tag_key, tag_value in tags_map_to_update.items():
additional_property = (
messages.TagBindingCollection.TagsValue.AdditionalProperty(
key=tag_key, value=tag_value
)
)
tag_bindings.additionalProperties.append(additional_property)
# additional_property is a
# TagBindingCollection.TagsValue.AdditionalProperty
tag_binding_collection = messages.TagBindingCollection(
etag=original.etag,
name=tag_binding_collection_name,
fullResourceName=resource_name,
tags=tag_bindings,
)
update_req = (
messages.CloudresourcemanagerLocationsTagBindingCollectionsPatchRequest(
name=tag_binding_collection_name,
tagBindingCollection=tag_binding_collection,
updateMask=update_mask,
)
)
with endpoints.CrmEndpointOverrides(location):
service = tags.TagBindingsCollectionService()
op = service.Patch(update_req)
return op

View File

@@ -0,0 +1,35 @@
# -*- 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.
"""The command group for the Resource Manager CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class TagHolds(base.Group):
"""Create and manipulate TagHolds.
The Resource Manager Service gives you centralized and programmatic
control over your organization's Tags. As the tag
administrator, you will be able to create and configure restrictions across
the tags in your organization or projects, and you will be able to indicate
the use of a TagValue as a TagHold.
"""

View File

@@ -0,0 +1,119 @@
# -*- 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.
"""Create command for the Resource Manager - Tag Holds CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils as endpoints
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Create(base.Command):
"""Create a TagHold resource.
Create a TagHold under a TagValue, indicating that the TagValue is being
used by a holder (cloud resource) from an (optional) origin. The TagValue
can be represented with its numeric id or its namespaced name of
{parent_namespace}/{tag_key_short_name}/{tag_value_short_name}.
"""
detailed_help = {
"EXAMPLES":
"""
To create a TagHold on tagValues/123, with holder cloud-resource-holder,
origin creator-origin, in region us-central1-a, with help link
www.example.help.link.com, run:
$ {command} tagValues/123 --holder=cloud-resource-holder --origin=creator-origin --help-link=www.example.help.link.com --location=us-central1-a
To create a TagHold under TagValue test under TagKey env in organization id
789, with holder cloud-resource-holder, run:
$ {command} 789/env/test --holder=cloud-resource-holder
"""
}
@staticmethod
def Args(parser):
parser.add_argument(
"parent", metavar="PARENT", help="Tag value name or namespaced name.")
arguments.AddLocationArgToParser(
parser,
message=("Region or zone where the TagHold will be stored. If not "
"provided, the TagHold will be stored in a \"global\" "
"region."))
parser.add_argument(
"--holder",
metavar="HOLDER",
required=True,
help=(
"The name of the resource where the TagValue is being used. Must be"
" less than 200 characters."))
parser.add_argument(
"--origin",
metavar="ORIGIN",
required=False,
help=(
"An optional string representing the origin of this request. This "
"field should include human-understandable information to "
"distinguish origins from each other. Must be less than 200 "
"characters."))
parser.add_argument(
"--help-link",
required=False,
metavar="HELP_LINK",
help=(
"A URL where an end user can learn more about removing this hold."))
def Run(self, args):
messages = tags.TagMessages()
if args.parent.find("tagValues/") == 0:
parent = args.parent
else:
parent = tag_utils.GetNamespacedResource(
args.parent, tag_utils.TAG_VALUES
).name
holder = args.holder
origin = args.origin if args.IsSpecified("origin") else None
location = args.location if args.IsSpecified("location") else None
help_link = args.help_link if args.IsSpecified("help_link") else None
tag_hold = messages.TagHold(
holder=holder, origin=origin, helpLink=help_link)
create_req = messages.CloudresourcemanagerTagValuesTagHoldsCreateRequest(
parent=parent, tagHold=tag_hold)
with endpoints.CrmEndpointOverrides(location):
service = tags.TagHoldsService()
op = service.Create(create_req)
if op.done:
return op
else:
return operations.WaitForReturnOperation(
op, "Waiting for TagHold for parent tag value[{}] to be "
"created with [{}]".format(parent, op.name))

View File

@@ -0,0 +1,78 @@
# -*- 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.
"""Delete command for the Tag Manager - Tag Holds CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils as endpoints
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Delete(base.Command):
"""Delete a TagHold.
Delete a TagHold given its full name, specified as
tagValues/{tag_value_id}/tagHolds/{tag_hold_id}.
"""
detailed_help = {
"EXAMPLES":
"""
To delete a TagHold under tagValue/111 with id abc-123-def in region
us-central1-a, run:
$ {command} tagValue/111/tagHolds/abc-123-def --location=us-central1-a
"""
}
@staticmethod
def Args(parser):
# Positional Argument
parser.add_argument(
"tag_hold_name",
metavar="TAG_HOLD_NAME",
help=("TagHold given its full name, specified as "
"tagValues/{tag_value_id}/tagHolds/{tag_hold_id}"))
arguments.AddLocationArgToParser(
parser,
("Region where the TagHold is stored. If not provided, the API will "
"attempt to find and delete the specified TagHold from the \"global\" "
"region."))
def Run(self, args):
location = args.location if args.IsSpecified("location") else None
messages = tags.TagMessages()
del_req = messages.CloudresourcemanagerTagValuesTagHoldsDeleteRequest(
name=args.tag_hold_name)
with endpoints.CrmEndpointOverrides(location):
service = tags.TagHoldsService()
op = service.Delete(del_req)
if op.done:
return op
else:
return operations.WaitForReturnOperation(
op, "Waiting for TagHold [{}] to be deleted with [{}]".format(
args.tag_hold_name, op.name))

View File

@@ -0,0 +1,115 @@
# -*- 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.
"""List command for the Tag Manager - Tag Holds CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import endpoint_utils as endpoints
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List TagHolds under the specified TagValue.
List TagHolds under a TagValue. The TagValue can be represented with its
numeric id or its namespaced name of
{parent_namespace}/{tag_key_short_name}/{tag_value_short_name}. Limited to
TagHolds stored in a single --location: if none is provided, the API will
assume the "global" location. Optional filters are --holder and --origin: if
provided, returned TagHolds' holder and origin fields must match the exact
flag value.
"""
detailed_help = {
"EXAMPLES":
"""
To list TagHolds for tagValues/456 in us-central1-a, run:
$ {command} tagValues/456 --location=us-central1-a
To list TagHolds for tagValues/456, with holder cloud-holder-resource and
origin creator-origin, run:
$ {command} tagValues/456 --holder=cloud-holder-resource --origin=creator-origin
"""
}
@staticmethod
def Args(parser):
# Positional Argument
parser.add_argument(
"parent",
metavar="PARENT",
help=("TagValue resource name or namespaced name to list TagHolds for. "
"This field should be in the form tagValues/<id> or "
"<parent_namespace>/<tagkey_short_name>/<short_name>."))
arguments.AddLocationArgToParser(
parser, ("Region where the matching TagHolds are stored. If not "
"provided, the API will attempt to retrieve matching TagHolds "
"from the \"global\" region."))
parser.add_argument(
"--holder",
metavar="HOLDER",
required=False,
help=(
"The holder field of the TagHold to match exactly. If not provided,"
" the API will return all matching TagHolds disregarding the holder"
" field."))
parser.add_argument(
"--origin",
metavar="ORIGIN",
required=False,
help=(
"The origin field of the TagHold to match exactly. If not provided,"
" the API will return all matching TagHolds disregarding the origin"
" field."))
def Run(self, args):
location = args.location if args.IsSpecified("location") else None
holder_filter = "holder = {}".format(
args.holder) if args.IsSpecified("holder") else None
origin_filter = "origin = {}".format(
args.origin) if args.IsSpecified("origin") else None
holder_origin_filter = " AND ".join(
[x for x in [holder_filter, origin_filter] if x is not None])
if args.parent.find("tagValues/") == 0:
parent = args.parent
else:
parent = tag_utils.GetNamespacedResource(
args.parent, tag_utils.TAG_VALUES
).name
with endpoints.CrmEndpointOverrides(location):
service = tags.TagHoldsService()
messages = tags.TagMessages()
list_req = messages.CloudresourcemanagerTagValuesTagHoldsListRequest(
parent=parent, filter=holder_origin_filter)
return list_pager.YieldFromList(
service,
list_req,
batch_size_attribute="pageSize",
batch_size=args.page_size,
field="tagHolds")

View File

@@ -0,0 +1,35 @@
# -*- 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.
"""The command group for the Resource Manager CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class TagKeys(base.Group):
"""Create and manipulate TagKeys.
The Resource Manager Service gives you centralized and programmatic
control over your organization's Tags. As the tag
administrator, you will be able to create and configure restrictions across
the tags in your organization or projects. As the tag user, you will be able
to attach TagValues to different resources.
"""

View File

@@ -0,0 +1,94 @@
# -*- 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.
"""AddIamPolicyBinding command for the Resource Manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.api_lib.util import http_retry
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
import six.moves.http_client
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class AddIamPolicyBinding(base.Command):
"""Adds a policy binding to the IAM policy of a TagKey.
Adds the IAM policy binding for a TagKey resource given the binding
and an identifier for the TagKey. The identifier can be the TagKey's
parent/short name or the TagKey's ID in the form:
tagKeys/{numeric_id}.
"""
detailed_help = {
'EXAMPLES':
"""
To add an IAM policy binding for the role of 'roles/editor' for the
user 'test-user@gmail.com' on the Tag Key 'tagKeys/123', run:
$ {command} tagKeys/123 --member='user:test-user@gmail.com' --role='roles/editor'
To add an IAM policy binding for a Tag Key with the name 'env' under
'organization/456' for the role of 'roles/resourcemanager.tagUser' for
the user 'test-user@gmail.com', run:
$ {command} 456/env --member='user:test-user@gmail.com' --role='roles/resourcemanager.tagUser'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
iam_util.AddArgsForAddIamPolicyBinding(parser, add_condition=True)
# Allow for retries due to etag-based optimistic concurrency control
@http_retry.RetryOnHttpStatus(six.moves.http_client.CONFLICT)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagKeys/') == 0:
tag_key = args.RESOURCE_NAME
else:
tag_key = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS
).name
get_iam_policy_req = (
messages.CloudresourcemanagerTagKeysGetIamPolicyRequest(
resource=tag_key))
policy = service.GetIamPolicy(get_iam_policy_req)
condition = iam_util.ValidateAndExtractConditionMutexRole(args)
iam_util.AddBindingToIamPolicyWithCondition(messages.Binding, messages.Expr,
policy, args.member, args.role,
condition)
set_iam_policy_request = messages.SetIamPolicyRequest(policy=policy)
request = messages.CloudresourcemanagerTagKeysSetIamPolicyRequest(
resource=tag_key, setIamPolicyRequest=set_iam_policy_request)
result = service.SetIamPolicy(request)
iam_util.LogSetIamPolicy(tag_key, 'TagKey')
return result

View File

@@ -0,0 +1,108 @@
# -*- 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.
"""Create command for the Resource Manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Create(base.Command):
r"""Creates a TagKey resource under the specified tag parent.
## EXAMPLES
To create a TagKey with the name env under 'organizations/123' with
description 'description', run:
$ {command} env --parent=organizations/123
--description=description
"""
@classmethod
def Args(cls, parser):
group = parser.add_argument_group("TagKey.", required=True)
arguments.AddShortNameArgToParser(group)
arguments.AddParentArgToParser(
group,
message="Parent of the TagKey in the form of organizations/{org_id}.")
arguments.AddDescriptionArgToParser(parser)
arguments.AddPurposeArgToParser(parser)
arguments.AddPurposeDataArgToParser(parser)
if cls.ReleaseTrack() in [base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA]:
arguments.AddAllowedValuesRegexArgToParser(parser)
arguments.AddAsyncArgToParser(parser)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
short_name = args.short_name
tag_parent = args.parent
description = args.description
allowed_values_regex = None
if "allowed_values_regex" in args and args.IsSpecified(
"allowed_values_regex"
):
allowed_values_regex = args.allowed_values_regex
purpose = None
purpose_data = None
if args.IsSpecified("purpose"):
purpose = messages.TagKey.PurposeValueValuesEnum(args.purpose)
if args.IsSpecified("purpose_data"):
if not purpose:
raise tag_utils.InvalidInputError("Purpose parameter not set")
additional_properties = [
messages.TagKey.PurposeDataValue.AdditionalProperty(
key=key, value=value) for key, value in args.purpose_data.items()
]
purpose_data = messages.TagKey.PurposeDataValue(
additionalProperties=additional_properties)
tag_key_params = {
"shortName": short_name,
"parent": tag_parent,
"description": description,
"purpose": purpose,
"purposeData": purpose_data,
}
if self.ReleaseTrack() in [base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA]:
tag_key_params["allowedValuesRegex"] = allowed_values_regex
tag_key = messages.TagKey(**tag_key_params)
create_req = messages.CloudresourcemanagerTagKeysCreateRequest(
tagKey=tag_key)
op = service.Create(create_req)
if args.async_:
return op
return operations.WaitForOperation(
op,
"Waiting for TagKey [{}] to be created".format(short_name),
service=service)

View File

@@ -0,0 +1,76 @@
# -*- 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.
"""Delete command for the resource manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Delete(base.Command):
"""Deletes the specified TagKey resource.
Deletes the TagKey resource given the TagKey's parent and short name
or the TagKey's numeric id.
"""
detailed_help = {
'EXAMPLES':
"""
To delete a TagKey with id ``123'', run:
$ {command} tagKeys/123
To delete a TagKey named ``env'' under organization ``456'',
run:
$ {command} 456/env
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
arguments.AddAsyncArgToParser(parser)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagKeys/') == 0:
tag_key = args.RESOURCE_NAME
else:
tag_key = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS
).name
delete_request = messages.CloudresourcemanagerTagKeysDeleteRequest(
name=tag_key)
op = service.Delete(delete_request)
if args.async_:
return op
return operations.WaitForReturnOperation(
op, 'Waiting for TagKey [{}] to be deleted'.format(tag_key))

View File

@@ -0,0 +1,67 @@
# -*- 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.
"""Describe command for the Resource Manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Describe(base.Command):
"""Describes a TagKey resource.
Gets metadata for a TagKey resource given the TagKey's resource name or
namespaced name.
"""
detailed_help = {
'EXAMPLES':
"""
To describe a TagKey with id '123', run:
$ {command} tagkeys/123
To describe a TagKey with the name 'env' under organizations '456',
run:
$ {command} 456/env
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagKeys/') == 0:
tag_key = args.RESOURCE_NAME
else:
tag_key = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS
).name
get_request = messages.CloudresourcemanagerTagKeysGetRequest(
name=tag_key)
return service.Get(get_request)

View File

@@ -0,0 +1,67 @@
# -*- 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.
"""GetIamPolicy command for the Resource Manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class GetIamPolicy(base.Command):
"""Gets the IAM policy for a TagKey resource.
Returns the IAM policy for a TagKey resource given the TagKey's display
name and parent or the TagKey's numeric id.
"""
detailed_help = {
'EXAMPLES':
"""
To get the IAM policy for a TagKey with id '123', run:
$ {command} tagKeys/123
To get the IAM policy for a TagKey with the name 'env' under
'organizations/456', run:
$ {command} 456/env
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagKeys/') == 0:
tag_key = args.RESOURCE_NAME
else:
tag_key = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS
).name
request = messages.CloudresourcemanagerTagKeysGetIamPolicyRequest(
resource=tag_key)
return service.GetIamPolicy(request)

View File

@@ -0,0 +1,59 @@
# -*- 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 command for the Resource Manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class List(base.ListCommand):
r"""Lists TagKeys under the specified parent resource.
## EXAMPLES
To list all the TagKeys under 'organizations/123', run:
$ {command} --parent='organizations/123'
"""
@staticmethod
def Args(parser):
arguments.AddParentArgToParser(
parser,
message="Parent of the TagKey in the form of organizations/{org_id}.")
parser.display_info.AddFormat("table(name:sort=1, short_name, description)")
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
tag_parent = args.parent
list_request = messages.CloudresourcemanagerTagKeysListRequest(
parent=tag_parent, pageSize=args.page_size)
return list_pager.YieldFromList(
service,
list_request,
batch_size_attribute="pageSize",
batch_size=args.page_size,
field="tagKeys")

View File

@@ -0,0 +1,95 @@
# -*- 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.
"""RemoveIamPolicyBinding command for the Resource Manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.api_lib.util import http_retry
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
import six.moves.http_client
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class RemoveIamPolicyBinding(base.Command):
"""Removes a policy binding from the IAM policy of a TagKey.
Removes an IAM policy binding for a TagKey resource given the binding
and an identifier for the TagKey. The identifier can be the TagKey's
parent/short name or the TagKey's ID in the form:
tagKeys/{numeric_id}.
"""
detailed_help = {
'EXAMPLES':
"""
To remove an IAM policy binding for the role of 'roles/editor' for the
user 'test-user@gmail.com' on the tagKey 'tagKeys/123', run:
$ {command} tagKeys/123 --member='user:test-user@gmail.com' --role='roles/editor'
To remove an IAM policy binding for a TagKey with the name 'env'
under 'organization/456' for the role of
'roles/resourcemanager.tagUser' for the user 'test-user@gmail.com',
run:
$ {command} 456/env --member='user:test-user@gmail.com' --role='roles/resourcemanager.tagUser'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
iam_util.AddArgsForRemoveIamPolicyBinding(parser, add_condition=True)
# Allow for retries due to etag-based optimistic concurrency control
@http_retry.RetryOnHttpStatus(six.moves.http_client.CONFLICT)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagKeys/') == 0:
tag_key = args.RESOURCE_NAME
else:
tag_key = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS
).name
get_iam_policy_req = (
messages.CloudresourcemanagerTagKeysGetIamPolicyRequest(
resource=tag_key))
policy = service.GetIamPolicy(get_iam_policy_req)
condition = iam_util.ValidateAndExtractConditionMutexRole(args)
iam_util.RemoveBindingFromIamPolicyWithCondition(policy, args.member,
args.role, condition,
args.all)
set_iam_policy_request = messages.SetIamPolicyRequest(policy=policy)
request = messages.CloudresourcemanagerTagKeysSetIamPolicyRequest(
resource=tag_key, setIamPolicyRequest=set_iam_policy_request)
result = service.SetIamPolicy(request)
iam_util.LogSetIamPolicy(tag_key, 'TagKey')
return result

View File

@@ -0,0 +1,79 @@
# -*- 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.
"""SetIamPolicy command for the Resource Manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class SetIamPolicy(base.Command):
"""Sets IAM policy for a TagKey resource.
Sets the IAM policy for a TagKey resource given the TagKey's display
name and parent or the TagKey's numeric id and a file encoded in
JSON or YAML that contains the IAM policy.
"""
detailed_help = {
'EXAMPLES':
"""
To set the IAM policy for a TagKey with id '123' and IAM policy
defined in a YAML file '/path/to/my_policy.yaml', run:
$ {command} tagKeys/123 /path/to/my_policy.yaml
To set the IAM policy for a tagKey with the short_name 'env' under
'organization/456' and IAM policy defined in a JSON file
'/path/to/my_policy.json', run:
$ {command} 456/env /path/to/my_policy.json
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
arguments.AddPolicyFileArgToParser(parser)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagKeys/') == 0:
tag_key = args.RESOURCE_NAME
else:
tag_key = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS
).name
policy = iam_util.ParsePolicyFile(args.POLICY_FILE, messages.Policy)
policy.version = iam_util.MAX_LIBRARY_IAM_SUPPORTED_VERSION
set_iam_policy_request = messages.SetIamPolicyRequest(policy=policy)
request = messages.CloudresourcemanagerTagKeysSetIamPolicyRequest(
resource=tag_key, setIamPolicyRequest=set_iam_policy_request)
result = service.SetIamPolicy(request)
iam_util.LogSetIamPolicy(tag_key, 'TagKey')
return result

View File

@@ -0,0 +1,93 @@
# -*- 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.
"""Update command for the resource manager - Tag Keys CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Update(base.Command):
"""Updates the specified TagKey resource's description.
Updates the TagKey's description given the TagKey's parent and short name
or the TagKey's numeric id.
"""
detailed_help = {
'EXAMPLES':
"""
To update a TagKey with id ``123'', run:
$ {command} tagKeys/123 --description=foobar --allowed-values-regex=.*
To update a TagKey named ``env'' under organization ``456'',
run:
$ {command} 456/env --description=foobar --allowed-values-regex=.*
"""
}
@classmethod
def Args(cls, parser):
arguments.AddResourceNameArgToParser(parser)
arguments.AddAsyncArgToParser(parser)
arguments.AddDescriptionArgToParser(parser)
if cls.ReleaseTrack() in [base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA]:
arguments.AddAllowedValuesRegexArgToParser(parser)
def Run(self, args):
service = tags.TagKeysService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagKeys/') == 0:
tag_key = tag_utils.GetResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS)
else:
tag_key = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_KEYS
)
update_masks = []
if 'allowed_values_regex' in args and args.IsSpecified(
'allowed_values_regex'
):
tag_key.allowedValuesRegex = args.allowed_values_regex
update_masks.append('allowed_values_regex')
if args.IsSpecified('description'):
tag_key.description = args.description
update_masks.append('description')
update_request = messages.CloudresourcemanagerTagKeysPatchRequest(
name=tag_key.name, tagKey=tag_key, updateMask=','.join(update_masks))
op = service.Patch(update_request)
if args.async_:
return op
return operations.WaitForOperation(
op,
'Waiting for TagKey [{}] to be updated'.format(tag_key.name),
service=service)

View File

@@ -0,0 +1,35 @@
# -*- 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.
"""The command group for the Resource Manager CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class TagValues(base.Group):
"""Create and manipulate TagValues.
The Resource Manager Service gives you centralized and programmatic
control over your organization's Tags. As the tag
administrator, you will be able to create and configure restrictions across
the tags in your organization or projects. As the tag user, you will be able
to attach TagValues to different resources.
"""

View File

@@ -0,0 +1,95 @@
# -*- 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.
"""AddIamPolicyBinding command for the Resource Manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.api_lib.util import http_retry
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
import six.moves.http_client
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class AddIamPolicyBinding(base.Command):
"""Adds a policy binding to the IAM policy of a TagValue.
Adds the IAM policy binding for a TagValue resource given the binding
and an identifier for the TagValue. The identifier can be the TagValue's
namespaced name in the form
<parent_namespace>/<tagkey_short_name>/<tagvalue_short_name> or the
TagValue's ID in the form: tagValues/{numeric_id}.
"""
detailed_help = {
'EXAMPLES':
"""
To add an IAM policy binding for the role of 'roles/editor' for the
user 'test-user@gmail.com' on the Tag Value 'tagValues/111', run:
$ {command} tagValues/111 --member='user:test-user@gmail.com' --role='roles/editor'
To add an IAM policy binding for a Tag Value with the name 'dev' under
'organization/456/env' for the role of 'roles/resourcemanager.tagUser' for
the user 'test-user@gmail.com', run:
$ {command} 456/env/dev --member='user:test-user@gmail.com' --role='roles/resourcemanager.tagUser'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
iam_util.AddArgsForAddIamPolicyBinding(parser, add_condition=True)
# Allow for retries due to etag-based optimistic concurrency control
@http_retry.RetryOnHttpStatus(six.moves.http_client.CONFLICT)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagValues/') == 0:
tag_value = args.RESOURCE_NAME
else:
tag_value = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES
).name
get_iam_policy_req = (
messages.CloudresourcemanagerTagValuesGetIamPolicyRequest(
resource=tag_value))
policy = service.GetIamPolicy(get_iam_policy_req)
condition = iam_util.ValidateAndExtractConditionMutexRole(args)
iam_util.AddBindingToIamPolicyWithCondition(messages.Binding, messages.Expr,
policy, args.member, args.role,
condition)
set_iam_policy_request = messages.SetIamPolicyRequest(policy=policy)
request = messages.CloudresourcemanagerTagValuesSetIamPolicyRequest(
resource=tag_value, setIamPolicyRequest=set_iam_policy_request)
result = service.SetIamPolicy(request)
iam_util.LogSetIamPolicy(tag_value, 'TagValue')
return result

View File

@@ -0,0 +1,98 @@
# -*- 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.
"""Create command for the Resource Manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA
)
@base.DefaultUniverseOnly
class Create(base.Command):
"""Creates a TagValue resource.
Creates a TagValue resource given the short_name and description (optional)
as well as the parent, the of the TagValue. The parent of the
TagValue can be a TagKey or TagValue. The parent can be specified by
its numeric ID or its namespaced name.
"""
detailed_help = {"EXAMPLES": """
To create a TagValue with the short name `test` and the
description `descriptio` under a TagKey with a short name `env`
under `organizations/123`, run:
$ {command} test --parent=123/env
--description=description
To create a TagValue with the short name `test` under TagKey
with id `456`, run:
$ {command} test --parent=tagKeys/456
--description=description
"""}
@staticmethod
def Args(parser):
group = parser.add_argument_group("TagValue.", required=True)
arguments.AddShortNameArgToParser(group)
arguments.AddParentArgToParser(
group,
message=(
"Parent of the TagValue in either in the form of "
"tagKeys/{id} or {org_id}/{tagkey_short_name}"
),
)
arguments.AddDescriptionArgToParser(parser)
arguments.AddAsyncArgToParser(parser)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
short_name = args.short_name
description = args.description
tag_value_parent = tag_utils.GetTagValueParent(args.parent)
tag_value = messages.TagValue(
shortName=short_name,
description=description,
parent=tag_value_parent,
)
create_req = messages.CloudresourcemanagerTagValuesCreateRequest(
tagValue=tag_value
)
op = service.Create(create_req)
if args.async_:
return op
return operations.WaitForOperation(
op,
"Waiting for TagValue [{}] to be created".format(short_name),
service=service,
)

View File

@@ -0,0 +1,77 @@
# -*- 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.
"""Delete command for the resource manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Delete(base.Command):
"""Deletes the specified TagValue resource.
Deletes the TagValue resource given the TagValue's parent and short name
or the TagValue's numeric id.
"""
detailed_help = {
'EXAMPLES':
"""
To delete a TagValue with id ``123'', run:
$ {command} tagValues/123
To delete a TagValue named ``dev'' with tagKey ``env'' under
organization ``456'',
run:
$ {command} 456/env/dev
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
arguments.AddAsyncArgToParser(parser)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagValues/') == 0:
tag_value = args.RESOURCE_NAME
else:
tag_value = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES
).name
delete_request = messages.CloudresourcemanagerTagValuesDeleteRequest(
name=tag_value)
op = service.Delete(delete_request)
if args.async_:
return op
return operations.WaitForReturnOperation(
op, 'Waiting for TagValue [{}] to be deleted'.format(tag_value))

View File

@@ -0,0 +1,68 @@
# -*- 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.
"""Describe command for the Resource Manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Describe(base.Command):
"""Describes a TagValue resource.
Gets metadata for a TagValue resource given the TagValue's resource name or
namespaced name.
"""
detailed_help = {
'EXAMPLES':
"""
To describe a TagValue with id ``123'', run:
$ {command} tagValues/123
To describe a TagValue with name ``dev'' with the tagKey ``env'' under
organizations ``456'',
run:
$ {command} 456/env/dev
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagValues/') == 0:
tag_value = args.RESOURCE_NAME
else:
tag_value = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES
).name
get_request = messages.CloudresourcemanagerTagValuesGetRequest(
name=tag_value)
return service.Get(get_request)

View File

@@ -0,0 +1,67 @@
# -*- 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.
"""GetIamPolicy command for the Resource Manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class GetIamPolicy(base.Command):
"""Gets the IAM policy for a TagValue resource.
Returns the IAM policy for a TagValue resource given the TagValue's short
name and parent or the TagValue's numeric id.
"""
detailed_help = {
'EXAMPLES':
"""
To get the IAM policy for a TagValue with id '123', run:
$ {command} tagValues/123
To get the IAM policy for a TagValue with the name 'dev' under
'organizations/456' and tagKey parent 'env', run:
$ {command} 456/env/dev
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagValues/') == 0:
tag_value = args.RESOURCE_NAME
else:
tag_value = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES
).name
request = messages.CloudresourcemanagerTagValuesGetIamPolicyRequest(
resource=tag_value)
return service.GetIamPolicy(request)

View File

@@ -0,0 +1,70 @@
# -*- 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 command for the Resource Manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(
base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA, base.ReleaseTrack.GA
)
@base.DefaultUniverseOnly
class List(base.ListCommand):
r"""Lists TagValues under the specified parent resource.
## EXAMPLES
To list all the TagValues under ``organizations/123/env'', run:
$ {command} --parent=123/env
"""
@staticmethod
def Args(parser):
arguments.AddParentArgToParser(
parser,
message=(
"Parent of the TagValue in either in the form of "
"tagKeys/{id} or {org_id}/{tagkey_short_name}"
),
)
parser.display_info.AddFormat("table(name:sort=1, short_name, description)")
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
tag_value_parent = tag_utils.GetTagValueParent(args.parent)
list_request = messages.CloudresourcemanagerTagValuesListRequest(
parent=tag_value_parent,
pageSize=args.page_size,
)
return list_pager.YieldFromList(
service,
list_request,
batch_size_attribute="pageSize",
batch_size=args.page_size,
field="tagValues",
)

View File

@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*- #
# Copyright 2019 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""RemoveIamPolicyBinding command for the Resource Manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.api_lib.util import http_retry
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
import six.moves.http_client
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class RemoveIamPolicyBinding(base.Command):
"""Removes a policy binding from the IAM policy of a TagValue.
Removes an IAM policy binding for a TagValue resource given the binding
and an identifier for the TagValue. The identifier can be the TagValue's
namespaced name in the form
<parent_namespace>/<tagkey_short_name>/<tagvalue_short_name> or the
TagValue's ID in the form: tagValues/{numeric_id}.
"""
detailed_help = {
'EXAMPLES':
"""
To remove an IAM policy binding for the role of 'roles/editor' for the
user 'test-user@gmail.com' on the tagValue 'tagValues/111', run:
$ {command} tagValues/111 --member='user:test-user@gmail.com' --role='roles/editor'
To remove an IAM policy binding for a TagValue with the name 'dev'
under 'organization/456/env' for the role of
'roles/resourcemanager.tagUser' for the user 'test-user@gmail.com',
run:
$ {command} 456/env/dev --member='user:test-user@gmail.com' --role='roles/resourcemanager.tagUser'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
iam_util.AddArgsForRemoveIamPolicyBinding(parser, add_condition=True)
# Allow for retries due to etag-based optimistic concurrency control
@http_retry.RetryOnHttpStatus(six.moves.http_client.CONFLICT)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagValues/') == 0:
tag_value = args.RESOURCE_NAME
else:
tag_value = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES
).name
get_iam_policy_req = (
messages.CloudresourcemanagerTagValuesGetIamPolicyRequest(
resource=tag_value))
policy = service.GetIamPolicy(get_iam_policy_req)
condition = iam_util.ValidateAndExtractConditionMutexRole(args)
iam_util.RemoveBindingFromIamPolicyWithCondition(policy, args.member,
args.role, condition,
args.all)
set_iam_policy_request = messages.SetIamPolicyRequest(policy=policy)
request = messages.CloudresourcemanagerTagValuesSetIamPolicyRequest(
resource=tag_value, setIamPolicyRequest=set_iam_policy_request)
result = service.SetIamPolicy(request)
iam_util.LogSetIamPolicy(tag_value, 'TagValue')
return result

View File

@@ -0,0 +1,79 @@
# -*- 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.
"""SetIamPolicy command for the Resource Manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class SetIamPolicy(base.Command):
"""Sets IAM policy for a TagValue resource.
Sets the IAM policy for a TagValue resource given the TagValue's short name
name and parent or the TagValue's numeric id and a file encoded in
JSON or YAML that contains the IAM policy.
"""
detailed_help = {
'EXAMPLES':
"""
To set the IAM policy for a TagValue with id '111' and IAM policy
defined in a YAML file '/path/to/my_policy.yaml', run:
$ {command} tagValues/111 /path/to/my_policy.yaml
To set the IAM policy for a tagValue with the short_name 'dev' under
'organization/456' and tag key short name 'env' and IAM policy
defined in a JSON file '/path/to/my_policy.json', run:
$ {command} 456/env/dev /path/to/my_policy.json
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
arguments.AddPolicyFileArgToParser(parser)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagValues/') == 0:
tag_value = args.RESOURCE_NAME
else:
tag_value = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES
).name
policy = iam_util.ParsePolicyFile(args.POLICY_FILE, messages.Policy)
policy.version = iam_util.MAX_LIBRARY_IAM_SUPPORTED_VERSION
set_iam_policy_request = messages.SetIamPolicyRequest(policy=policy)
request = messages.CloudresourcemanagerTagValuesSetIamPolicyRequest(
resource=tag_value, setIamPolicyRequest=set_iam_policy_request)
result = service.SetIamPolicy(request)
iam_util.LogSetIamPolicy(tag_value, 'TagValue')
return result

View File

@@ -0,0 +1,83 @@
# -*- 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.
"""Update command for the resource manager - Tag Values CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.resource_manager import tags
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.resource_manager import operations
from googlecloudsdk.command_lib.resource_manager import tag_arguments as arguments
from googlecloudsdk.command_lib.resource_manager import tag_utils
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA,
base.ReleaseTrack.GA)
class Update(base.Command):
"""Updates the specified TagValue resource's description.
Updates the TagValue's description given the TagValue's
namespaced name <parent_namespace>/<tagkey_short_name>/<short_name>
or the TagValue's numeric id tagValues/<id>
"""
detailed_help = {
'EXAMPLES':
"""
To update a TagValue with id ``123'', run:
$ {command} tagValues/123 --description="foobar"
To update a TagValue named ``dev'' with the tagKey ``env''
under organization ``456'',
run:
$ {command} 465/env/dev --description="foobar"
"""
}
@staticmethod
def Args(parser):
arguments.AddResourceNameArgToParser(parser)
arguments.AddAsyncArgToParser(parser)
arguments.AddDescriptionArgToParser(parser)
def Run(self, args):
service = tags.TagValuesService()
messages = tags.TagMessages()
if args.RESOURCE_NAME.find('tagValues/') == 0:
tag_value = tag_utils.GetResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES)
else:
tag_value = tag_utils.GetNamespacedResource(
args.RESOURCE_NAME, tag_utils.TAG_VALUES
)
tag_value.description = args.description
update_request = messages.CloudresourcemanagerTagValuesPatchRequest(
name=tag_value.name, tagValue=tag_value, updateMask='description')
op = service.Patch(update_request)
if args.async_:
return op
return operations.WaitForOperation(
op,
'Waiting for TagValue [{}] to be updated'.format(tag_value.name),
service=service)