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,20 @@
# -*- 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.
"""Package marker file."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,253 @@
# -*- 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.
"""Utilities for calling the Composer UserWorkloads ConfigMaps API."""
import typing
from typing import Mapping, Tuple
from googlecloudsdk.api_lib.composer import util as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.composer import util as command_util
from googlecloudsdk.core import yaml
if typing.TYPE_CHECKING:
from googlecloudsdk.core.resources import Resource
from googlecloudsdk.generated_clients.apis.composer.v1alpha2 import composer_v1alpha2_messages
from googlecloudsdk.generated_clients.apis.composer.v1beta1 import composer_v1beta1_messages
from googlecloudsdk.generated_clients.apis.composer.v1 import composer_v1_messages
def GetService(release_track=base.ReleaseTrack.GA):
return api_util.GetClientInstance(
release_track
).projects_locations_environments_userWorkloadsConfigMaps
def CreateUserWorkloadsConfigMap(
environment_ref: 'Resource',
config_map_file_path: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
'composer_v1alpha2_messages.UserWorkloadsConfigMap',
'composer_v1beta1_messages.UserWorkloadsConfigMap',
'composer_v1_messages.UserWorkloadsConfigMap',
]:
"""Calls the Composer Environments.CreateUserWorkloadsConfigMap method.
Args:
environment_ref: Resource, the Composer environment resource to create a
user workloads ConfigMap for.
config_map_file_path: string, path to a local file with a Kubernetes
ConfigMap in yaml format.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
UserWorkloadsConfigMap: the created user workloads ConfigMap.
Raises:
command_util.InvalidUserInputError: if metadata.name was absent from the
file.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
config_map_name, config_map_data = _ReadConfigMapFromFile(
config_map_file_path
)
user_workloads_config_map_name = f'{environment_ref.RelativeName()}/userWorkloadsConfigMaps/{config_map_name}'
user_workloads_config_map_data = api_util.DictToMessage(
config_map_data,
message_module.UserWorkloadsConfigMap.DataValue,
)
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsConfigMapsCreateRequest(
parent=environment_ref.RelativeName(),
userWorkloadsConfigMap=message_module.UserWorkloadsConfigMap(
name=user_workloads_config_map_name,
data=user_workloads_config_map_data,
),
)
return GetService(release_track=release_track).Create(request_message)
def GetUserWorkloadsConfigMap(
environment_ref: 'Resource',
config_map_name: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
'composer_v1alpha2_messages.UserWorkloadsConfigMap',
'composer_v1beta1_messages.UserWorkloadsConfigMap',
'composer_v1_messages.UserWorkloadsConfigMap',
]:
"""Calls the Composer Environments.GetUserWorkloadsConfigMap method.
Args:
environment_ref: Resource, the Composer environment resource to get a user
workloads ConfigMap for.
config_map_name: string, name of the Kubernetes ConfigMap.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
UserWorkloadsConfigMap: user workloads ConfigMap.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
user_workloads_config_map_name = f'{environment_ref.RelativeName()}/userWorkloadsConfigMaps/{config_map_name}'
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsConfigMapsGetRequest(
name=user_workloads_config_map_name,
)
return GetService(release_track=release_track).Get(request_message)
def ListUserWorkloadsConfigMaps(
environment_ref: 'Resource',
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
typing.List['composer_v1alpha2_messages.UserWorkloadsConfigMap'],
typing.List['composer_v1beta1_messages.UserWorkloadsConfigMap'],
typing.List['composer_v1_messages.UserWorkloadsConfigMap'],
]:
"""Calls the Composer Environments.ListUserWorkloadsConfigMaps method.
Args:
environment_ref: Resource, the Composer environment resource to list user
workloads ConfigMaps for.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
list of user workloads ConfigMaps.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
page_token = ''
user_workloads_config_maps = []
while True:
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsConfigMapsListRequest(
pageToken=page_token,
parent=environment_ref.RelativeName(),
)
response = GetService(release_track=release_track).List(request_message)
user_workloads_config_maps.extend(response.userWorkloadsConfigMaps)
if not response.nextPageToken:
break
# Set page_token for the next request.
page_token = response.nextPageToken
return user_workloads_config_maps
def UpdateUserWorkloadsConfigMap(
environment_ref: 'Resource',
config_map_file_path: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
'composer_v1alpha2_messages.UserWorkloadsConfigMap',
'composer_v1beta1_messages.UserWorkloadsConfigMap',
'composer_v1_messages.UserWorkloadsConfigMap',
]:
"""Calls the Composer Environments.UpdateUserWorkloadsConfigMap method.
Args:
environment_ref: Resource, the Composer environment resource to update a
user workloads ConfigMap for.
config_map_file_path: string, path to a local file with a Kubernetes
ConfigMap in yaml format.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
UserWorkloadsConfigMap: the updated user workloads ConfigMap.
Raises:
command_util.InvalidUserInputError: if metadata.name was absent from the
file.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
config_map_name, config_map_data = _ReadConfigMapFromFile(
config_map_file_path
)
user_workloads_config_map_name = f'{environment_ref.RelativeName()}/userWorkloadsConfigMaps/{config_map_name}'
user_workloads_config_map_data = api_util.DictToMessage(
config_map_data,
message_module.UserWorkloadsConfigMap.DataValue,
)
request_message = message_module.UserWorkloadsConfigMap(
name=user_workloads_config_map_name,
data=user_workloads_config_map_data,
)
return GetService(release_track=release_track).Update(request_message)
def DeleteUserWorkloadsConfigMap(
environment_ref: 'Resource',
config_map_name: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
):
"""Calls the Composer Environments.DeleteUserWorkloadsConfigMap method.
Args:
environment_ref: Resource, the Composer environment resource to delete a
user workloads ConfigMap for.
config_map_name: string, name of the Kubernetes ConfigMap.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
user_workloads_config_map_name = f'{environment_ref.RelativeName()}/userWorkloadsConfigMaps/{config_map_name}'
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsConfigMapsDeleteRequest(
name=user_workloads_config_map_name,
)
GetService(release_track=release_track).Delete(request_message)
def _ReadConfigMapFromFile(
config_map_file_path: str,
) -> Tuple[str, Mapping[str, str]]:
"""Reads ConfigMap object from yaml file.
Args:
config_map_file_path: path to the file.
Returns:
tuple with name and data of the ConfigMap.
Raises:
command_util.InvalidUserInputError: if the content of the file is invalid.
"""
config_map_file_content = yaml.load_path(config_map_file_path)
if not isinstance(config_map_file_content, dict):
raise command_util.InvalidUserInputError(
f'Invalid content of the {config_map_file_path}'
)
kind = config_map_file_content.get('kind')
metadata_name = config_map_file_content.get('metadata', {}).get('name', '')
data = config_map_file_content.get('data', {})
if kind != 'ConfigMap':
raise command_util.InvalidUserInputError(
f'Incorrect "kind" attribute value. Found: {kind}, should be: ConfigMap'
)
if not metadata_name:
raise command_util.InvalidUserInputError(
f'Empty metadata.name in {config_map_file_path}'
)
return metadata_name, data

View File

@@ -0,0 +1,255 @@
# -*- 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.
"""Utilities for calling the Composer UserWorkloads Secrets API."""
import typing
from typing import Mapping, Tuple
from googlecloudsdk.api_lib.composer import util as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.composer import util as command_util
from googlecloudsdk.core import yaml
if typing.TYPE_CHECKING:
from googlecloudsdk.core.resources import Resource
from googlecloudsdk.generated_clients.apis.composer.v1alpha2 import composer_v1alpha2_messages
from googlecloudsdk.generated_clients.apis.composer.v1beta1 import composer_v1beta1_messages
from googlecloudsdk.generated_clients.apis.composer.v1 import composer_v1_messages
def GetService(release_track=base.ReleaseTrack.GA):
return api_util.GetClientInstance(
release_track
).projects_locations_environments_userWorkloadsSecrets
def CreateUserWorkloadsSecret(
environment_ref: 'Resource',
secret_file_path: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
'composer_v1alpha2_messages.UserWorkloadsSecret',
'composer_v1beta1_messages.UserWorkloadsSecret',
'composer_v1_messages.UserWorkloadsSecret',
]:
"""Calls the Composer Environments.CreateUserWorkloadsSecret method.
Args:
environment_ref: Resource, the Composer environment resource to create a
user workloads Secret for.
secret_file_path: string, path to a local file with a Kubernetes Secret in
yaml format.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
UserWorkloadsSecret: the created user workloads Secret.
Raises:
command_util.InvalidUserInputError: if metadata.name was absent from the
file.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
secret_name, secret_data = _ReadSecretFromFile(secret_file_path)
user_workloads_secret_name = (
f'{environment_ref.RelativeName()}/userWorkloadsSecrets/{secret_name}'
)
user_workloads_secret_data = api_util.DictToMessage(
secret_data,
message_module.UserWorkloadsSecret.DataValue,
)
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsSecretsCreateRequest(
parent=environment_ref.RelativeName(),
userWorkloadsSecret=message_module.UserWorkloadsSecret(
name=user_workloads_secret_name,
data=user_workloads_secret_data,
),
)
return GetService(release_track=release_track).Create(request_message)
def GetUserWorkloadsSecret(
environment_ref: 'Resource',
secret_name: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
'composer_v1alpha2_messages.UserWorkloadsSecret',
'composer_v1beta1_messages.UserWorkloadsSecret',
'composer_v1_messages.UserWorkloadsSecret',
]:
"""Calls the Composer Environments.GetUserWorkloadsSecret method.
Args:
environment_ref: Resource, the Composer environment resource to get a user
workloads Secret for.
secret_name: string, name of the Kubernetes Secret.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
UserWorkloadsSecret: user workloads Secret.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
user_workloads_secret_name = (
f'{environment_ref.RelativeName()}/userWorkloadsSecrets/{secret_name}'
)
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsSecretsGetRequest(
name=user_workloads_secret_name,
)
return GetService(release_track=release_track).Get(request_message)
def ListUserWorkloadsSecrets(
environment_ref: 'Resource',
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
typing.List['composer_v1alpha2_messages.UserWorkloadsSecret'],
typing.List['composer_v1beta1_messages.UserWorkloadsSecret'],
typing.List['composer_v1_messages.UserWorkloadsSecret'],
]:
"""Calls the Composer Environments.ListUserWorkloadsSecrets method.
Args:
environment_ref: Resource, the Composer environment resource to list user
workloads Secrets for.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
list of user workloads Secrets.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
page_token = ''
user_workloads_secrets = []
while True:
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsSecretsListRequest(
pageToken=page_token,
parent=environment_ref.RelativeName(),
)
response = GetService(release_track=release_track).List(request_message)
user_workloads_secrets.extend(response.userWorkloadsSecrets)
if not response.nextPageToken:
break
# Set page_token for the next request.
page_token = response.nextPageToken
return user_workloads_secrets
def UpdateUserWorkloadsSecret(
environment_ref: 'Resource',
secret_file_path: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
) -> typing.Union[
'composer_v1alpha2_messages.UserWorkloadsSecret',
'composer_v1beta1_messages.UserWorkloadsSecret',
'composer_v1_messages.UserWorkloadsSecret',
]:
"""Calls the Composer Environments.UpdateUserWorkloadsSecret method.
Args:
environment_ref: Resource, the Composer environment resource to update a
user workloads Secret for.
secret_file_path: string, path to a local file with a Kubernetes Secret in
yaml format.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
Returns:
UserWorkloadsSecret: the updated user workloads Secret.
Raises:
command_util.InvalidUserInputError: if metadata.name was absent from the
file.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
secret_name, secret_data = _ReadSecretFromFile(secret_file_path)
user_workloads_secret_name = (
f'{environment_ref.RelativeName()}/userWorkloadsSecrets/{secret_name}'
)
user_workloads_secret_data = api_util.DictToMessage(
secret_data,
message_module.UserWorkloadsSecret.DataValue,
)
request_message = message_module.UserWorkloadsSecret(
name=user_workloads_secret_name,
data=user_workloads_secret_data,
)
return GetService(release_track=release_track).Update(request_message)
def DeleteUserWorkloadsSecret(
environment_ref: 'Resource',
secret_name: str,
release_track: base.ReleaseTrack = base.ReleaseTrack.ALPHA,
):
"""Calls the Composer Environments.DeleteUserWorkloadsSecret method.
Args:
environment_ref: Resource, the Composer environment resource to delete a
user workloads Secret for.
secret_name: string, name of the Kubernetes Secret.
release_track: base.ReleaseTrack, the release track of the command. Will
dictate which Composer client library will be used.
"""
message_module = api_util.GetMessagesModule(release_track=release_track)
user_workloads_secret_name = (
f'{environment_ref.RelativeName()}/userWorkloadsSecrets/{secret_name}'
)
request_message = message_module.ComposerProjectsLocationsEnvironmentsUserWorkloadsSecretsDeleteRequest(
name=user_workloads_secret_name,
)
GetService(release_track=release_track).Delete(request_message)
def _ReadSecretFromFile(secret_file_path: str) -> Tuple[str, Mapping[str, str]]:
"""Reads Secret object from yaml file.
Args:
secret_file_path: path to the file.
Returns:
tuple with name and data of the Secret.
Raises:
command_util.InvalidUserInputError: if the content of the file is invalid.
"""
secret_file_content = yaml.load_path(secret_file_path)
if not isinstance(secret_file_content, dict):
raise command_util.InvalidUserInputError(
f'Invalid content of the {secret_file_path}'
)
kind = secret_file_content.get('kind')
metadata_name = secret_file_content.get('metadata', {}).get('name', '')
data = secret_file_content.get('data', {})
if kind != 'Secret':
raise command_util.InvalidUserInputError(
f'Incorrect "kind" attribute value. Found: {kind}, should be: Secret'
)
if not metadata_name:
raise command_util.InvalidUserInputError(
f'Empty metadata.name in {secret_file_path}'
)
return metadata_name, data

View File

@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Utilities for calling the Composer ListWorkloads API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.composer import util as api_util
from googlecloudsdk.calliope import base
LIST_FIELD_NAME = 'workloads'
PAGE_SIZE = 1000
def GetService(release_track=base.ReleaseTrack.GA):
return api_util.GetClientInstance(
release_track).projects_locations_environments
class EnvironmentsWorkloadsService(object):
"""Provides workloads from Composer ListWorkloads API."""
def __init__(self, release_track=base.ReleaseTrack.GA):
self.client = None
self.release_track = release_track
self.messages = api_util.GetMessagesModule(release_track=self.release_track)
def GetClient(self):
if self.client is None:
self.client = api_util.GetClientInstance(
self.release_track).projects_locations_environments_workloads
return self.client
def List(self, project_location_ref):
"""Retrieves list of Composer workloads from Composer ListWorkloads API."""
request = (
self.messages.ComposerProjectsLocationsEnvironmentsWorkloadsListRequest
)
locations = [project_location_ref]
return list(
api_util.AggregateListResults(
request, self.GetClient(), locations, LIST_FIELD_NAME, PAGE_SIZE
)
)

View File

@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*- #
# Copyright 2018 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Utilities for calling the Composer ImageVersions API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.composer import util as api_util
from googlecloudsdk.calliope import base
LIST_FIELD_NAME = 'imageVersions'
PAGE_SIZE = 1000
class ImageVersionService(object):
"""Provides supported images version from the Image Version API."""
def __init__(self, release_track=base.ReleaseTrack.GA):
self.client = None
self.release_track = release_track
self.messages = api_util.GetMessagesModule(release_track=self.release_track)
def GetClient(self):
if self.client is None:
self.client = api_util.GetClientInstance(
self.release_track).projects_locations_imageVersions
return self.client
def List(self, project_location_ref):
"""Retrieves list of supported images version from the Image Version API."""
# TODO(b/122741565): Add support for paging
request = self.messages.ComposerProjectsLocationsImageVersionsListRequest
locations = [project_location_ref]
return api_util.AggregateListResults(request, self.GetClient(), locations,
LIST_FIELD_NAME, PAGE_SIZE)

View File

@@ -0,0 +1,139 @@
# -*- coding: utf-8 -*- #
# Copyright 2018 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Utilities for calling the Composer Operations API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import sys
from googlecloudsdk.api_lib.composer import util as api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.composer import util as command_util
# TODO(b/111385813): Refactor utils into a class
def GetService(release_track=base.ReleaseTrack.GA):
return api_util.GetClientInstance(
release_track=release_track).projects_locations_operations
def Delete(operation_resource, release_track=base.ReleaseTrack.GA):
"""Calls the Composer Operations.Delete method.
Args:
operation_resource: Resource, the Composer operation resource to
delete.
release_track: base.ReleaseTrack, the release track of command. Will dictate
which Composer client library will be used.
Returns:
Empty
"""
return GetService(release_track=release_track).Delete(
api_util.GetMessagesModule(release_track=release_track)
.ComposerProjectsLocationsOperationsDeleteRequest(
name=operation_resource.RelativeName()))
def Get(operation_resource, release_track=base.ReleaseTrack.GA):
"""Calls the Composer Operations.Get method.
Args:
operation_resource: Resource, the Composer operation resource to
retrieve.
release_track: base.ReleaseTrack, the release track of command. Will dictate
which Composer client library will be used.
Returns:
Operation: the requested operation
"""
return GetService(release_track=release_track).Get(
api_util.GetMessagesModule(release_track=release_track)
.ComposerProjectsLocationsOperationsGetRequest(
name=operation_resource.RelativeName()))
def List(location_refs,
page_size,
limit=sys.maxsize,
release_track=base.ReleaseTrack.GA):
"""Lists Composer Operations across all locations.
Uses a hardcoded list of locations, as there is way to dynamically
discover the list of supported locations. Support for new locations
will be aligned with Cloud SDK releases.
Args:
location_refs: [core.resources.Resource], a list of resource reference to
locations in which to list operations.
page_size: An integer specifying the maximum number of resources to be
returned in a single list call.
limit: An integer specifying the maximum number of operations to list.
None if all available operations should be returned.
release_track: base.ReleaseTrack, the release track of command. Will dictate
which Composer client library will be used.
Returns:
list: a generator over Operations within the locations in `location_refs`.
"""
return api_util.AggregateListResults(
api_util.GetMessagesModule(release_track=release_track)
.ComposerProjectsLocationsOperationsListRequest,
GetService(release_track=release_track),
location_refs,
'operations',
page_size,
limit=limit,
location_attribute='name')
def WaitForOperation(operation, message, release_track=base.ReleaseTrack.GA):
"""Waits for an operation to complete.
Polls the operation at least every 15 seconds, showing a progress indicator.
Returns when the operation has completed.
Args:
operation: Operation Message, the operation to poll
message: str, a message to display with the progress indicator. For
example, 'Waiting for deletion of [some resource]'.
release_track: base.ReleaseTrack, the release track of command. Will dictate
which Composer client library will be used.
"""
waiter.WaitFor(
_OperationPoller(release_track=release_track),
operation.name,
message,
max_wait_ms=3600 * 1000,
wait_ceiling_ms=15 * 1000)
class _OperationPoller(waiter.CloudOperationPollerNoResources):
""" Class for polling Composer longrunning Operations. """
def __init__(self, release_track=base.ReleaseTrack.GA):
super(_OperationPoller, self).__init__(
GetService(release_track=release_track), lambda x: x)
def IsDone(self, operation):
if operation.done:
if operation.error:
raise command_util.OperationError(operation.name,
operation.error.message)
return True
return False

View File

@@ -0,0 +1,112 @@
# -*- 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.
"""Utilities for calling the Composer API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import itertools
from apitools.base.py import encoding
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.util import apis
from googlecloudsdk.calliope import base
import six
COMPOSER_API_NAME = 'composer'
COMPOSER_GA_API_VERSION = 'v1'
COMPOSER_BETA_API_VERSION = 'v1beta1'
COMPOSER_ALPHA_API_VERSION = 'v1alpha2'
DEFAULT_PAGE_SIZE = 30
def GetApiVersion(release_track=base.ReleaseTrack.GA):
if release_track == base.ReleaseTrack.BETA:
return COMPOSER_BETA_API_VERSION
elif release_track == base.ReleaseTrack.ALPHA:
return COMPOSER_ALPHA_API_VERSION
return COMPOSER_GA_API_VERSION
def GetClientInstance(release_track=base.ReleaseTrack.GA):
return apis.GetClientInstance(
COMPOSER_API_NAME, GetApiVersion(release_track=release_track))
def GetMessagesModule(release_track=base.ReleaseTrack.GA):
return apis.GetMessagesModule(
COMPOSER_API_NAME, GetApiVersion(release_track=release_track))
def AggregateListResults(request_cls,
service,
location_refs,
field,
page_size,
limit=None,
location_attribute='parent'):
"""Collects the results of a List API call across a list of locations.
Args:
request_cls: class, the apitools.base.protorpclite.messages.Message class
corresponding to the API request message used to list resources in a
location.
service: apitools.base.py.BaseApiService, a service whose list
method to call with an instance of `request_cls`
location_refs: [core.resources.Resource], a list of resource references to
locations in which to list resources.
field: str, the name of the field within the list method's response from
which to extract a list of resources
page_size: int, the maximum number of resources to retrieve in each API
call
limit: int, the maximum number of results to return. None if all available
results should be returned.
location_attribute: str, the name of the attribute in `request_cls` that
should be populated with the name of the location
Returns:
A generator over up to `limit` resources if `limit` is not None. If `limit`
is None, the generator will yield all resources in all requested locations.
"""
results = []
for location_ref in location_refs:
request = request_cls()
setattr(request, location_attribute, location_ref.RelativeName())
results = itertools.chain(
results,
list_pager.YieldFromList(
service,
request=request,
field=field,
limit=None if limit is None else limit,
batch_size=DEFAULT_PAGE_SIZE if page_size is None else page_size,
batch_size_attribute='pageSize'))
return itertools.islice(results, limit)
def ParseOperationJsonMetadata(metadata_value, metadata_type):
if not metadata_value:
return metadata_type()
return encoding.JsonToMessage(metadata_type,
encoding.MessageToJson(metadata_value))
def DictToMessage(dictionary, msg_type):
return msg_type(additionalProperties=[
msg_type.AdditionalProperty(key=key, value=value)
for key, value in six.iteritems(dictionary)
])