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,26 @@
# -*- 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.
"""The super-group for commands to inspect APIs in gcloud."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
class APIs(base.Group):
"""Inspect the APIs registered in gcloud."""

View File

@@ -0,0 +1,26 @@
# -*- 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.
"""The super-group for commands to inspect APIs in gcloud."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
class Collections(base.Group):
"""Inspect the API collections registered in gcloud."""

View File

@@ -0,0 +1,40 @@
# -*- 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.
"""A command that describes a resource collection for a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import registry
class Describe(base.DescribeCommand):
"""Describe the details of a collection for an API."""
@staticmethod
def Args(parser):
flags.API_VERSION_FLAG.AddToParser(parser)
parser.add_argument(
'collection',
completer=flags.CollectionCompleter,
help='The name of the collection to get the details of.')
def Run(self, args):
return registry.GetAPICollection(args.collection,
api_version=args.api_version)

View File

@@ -0,0 +1,84 @@
# -*- 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.
"""A command that lists the resource collections for a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import registry
class Lint(base.ListCommand):
"""Show which collections have non-compliant list API methods."""
@staticmethod
def Args(parser):
base.PAGE_SIZE_FLAG.RemoveFromParser(parser)
base.URI_FLAG.RemoveFromParser(parser)
parser.add_argument(
'--api',
completer=flags.APICompleter,
help='The name of the API to get the collections for.')
flags.API_VERSION_FLAG.AddToParser(parser)
parser.display_info.AddFormat("""\
table(
collection:sort=6,
has_list:sort=1,
resource_arg:sort=2,
flattened:sort=3,
pageable:sort=4,
page_size:sort=5)
""")
def Run(self, args):
if args.api_version and not args.api:
raise exceptions.RequiredArgumentException(
'--api',
'The --api-version flag can only be specified when using the --api '
'flag.')
collections = registry.GetAPICollections(api_name=args.api,
api_version=args.api_version)
results = []
for c in collections:
methods = registry.GetMethods(c.full_name, api_version=c.api_version)
if not methods:
# Synthetic collection
continue
list_methods = [m for m in methods if m.IsList()]
if list_methods:
method = list_methods[0]
results.append({'collection': c.full_name,
'has_list': True,
'resource_arg': bool(method.request_collection),
'flattened': bool(method.ListItemField()),
'pageable': method.HasTokenizedRequest(),
'page_size': bool(method.BatchPageSizeField())})
else:
results.append({'collection': c.full_name, 'has_list': False})
# Filter out anything that is fully within spec.
results = [r for r in results if not (r['has_list'] and
r['resource_arg'] and
r['flattened'] and
r['pageable'] and
r['page_size'])]
return results

View File

@@ -0,0 +1,55 @@
# -*- 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.
"""A command that lists the resource collections for a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import registry
class List(base.ListCommand):
"""List the resource collections for an API."""
@staticmethod
def Args(parser):
base.PAGE_SIZE_FLAG.RemoveFromParser(parser)
base.URI_FLAG.RemoveFromParser(parser)
parser.add_argument(
'--api',
completer=flags.APICompleter,
help='The name of the API to get the collections for.')
flags.API_VERSION_FLAG.AddToParser(parser)
parser.display_info.AddFormat("""
table(
full_name:sort=1:label=COLLECTION_NAME,
detailed_path
)
""")
def Run(self, args):
if args.api_version and not args.api:
raise exceptions.RequiredArgumentException(
'--api',
'The --api-version flag can only be specified when using the --api '
'flag.')
return registry.GetAPICollections(api_name=args.api,
api_version=args.api_version)

View File

@@ -0,0 +1,39 @@
# -*- 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.
"""A command that describes a registered gcloud API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import registry
class Describe(base.DescribeCommand):
"""Describe the details of an API registered in gcloud."""
@staticmethod
def Args(parser):
flags.API_VERSION_FLAG.AddToParser(parser)
parser.add_argument(
'api_name',
completer=flags.APICompleter,
help='The name of the API to show the details of.')
def Run(self, args):
return registry.GetAPI(args.api_name, api_version=args.api_version)

View File

@@ -0,0 +1,26 @@
# -*- 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.
"""The super-group for commands to retrieve APIs definitions."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
class Discovery(base.Group):
"""Inspect the Google Cloud Platform APIs through the discovery service."""

View File

@@ -0,0 +1,44 @@
# -*- 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.
"""A command that describes a API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.util import apis
from googlecloudsdk.calliope import base
class Describe(base.DescribeCommand):
"""Describe the details of an API in discovery service."""
@staticmethod
def Args(parser):
parser.add_argument(
'api',
help='The api_name/api_version to show the details of.')
parser.display_info.AddFormat('json')
def Run(self, args):
client = apis.GetClientInstance('discovery', 'v1')
messages = client.MESSAGES_MODULE
api_name, api_version = args.api.split('/')
request = messages.DiscoveryApisGetRestRequest(
api=api_name, version=api_version)
return client.apis.GetRest(request)

View File

@@ -0,0 +1,49 @@
# -*- 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.
"""A command that lists the registered APIs in gcloud.."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.util import apis
from googlecloudsdk.calliope import base
class List(base.ListCommand):
"""List the APIs available via discovery service."""
@staticmethod
def Args(parser):
base.PAGE_SIZE_FLAG.RemoveFromParser(parser)
parser.display_info.AddUriFunc(lambda x: x.discoveryRestUrl)
parser.display_info.AddFormat("""
table(
name:sort=1,
version:sort=2,
title,
preferred.yesno(yes='*', no=''),
labels.list()
)""")
def Run(self, args):
client = apis.GetClientInstance('discovery', 'v1')
messages = client.MESSAGES_MODULE
request = messages.DiscoveryApisListRequest()
# Cannot use list_pager here since this api method
# does not support page tokens.
return client.apis.List(request).items

View File

@@ -0,0 +1,43 @@
# -*- 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.
"""A command that lists the registered APIs in gcloud.."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.util.apis import registry
class List(base.ListCommand):
"""List the APIs registered in gcloud."""
@staticmethod
def Args(parser):
base.PAGE_SIZE_FLAG.RemoveFromParser(parser)
base.URI_FLAG.RemoveFromParser(parser)
parser.display_info.AddFormat("""
table(
name:sort=1,
version:sort=2,
is_default.yesno(yes='*', no=''),
base_url
)
""")
def Run(self, args):
return registry.GetAllAPIs()

View File

@@ -0,0 +1,26 @@
# -*- 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.
"""The group for commands to inspect API messages in gcloud."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
class Messages(base.Group):
"""Inspect the API messages in an API."""

View File

@@ -0,0 +1,49 @@
# -*- 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.
"""A command that describes a message from a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import arg_utils
from googlecloudsdk.command_lib.util.apis import registry
class Describe(base.DescribeCommand):
"""Describe the details of a proto message in an API."""
@staticmethod
def Args(parser):
flags.API_REQUIRED_FLAG.AddToParser(parser)
flags.API_VERSION_FLAG.AddToParser(parser)
parser.add_argument(
'message',
help='The name of the message you want to describe.')
def Run(self, args):
api = registry.GetAPI(args.api, api_version=args.api_version)
try:
message = getattr(api.GetMessagesModule(), args.message)
return arg_utils.GetRecursiveMessageSpec(message)
except AttributeError:
raise exceptions.InvalidArgumentException(
'message', 'Message [{}] does not exist for API [{}]'.format(
args.message, args.api))

View File

@@ -0,0 +1,89 @@
# -*- 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.
"""A command that generates YAML export schemas for a message in a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import arg_utils
from googlecloudsdk.command_lib.util.apis import export
from googlecloudsdk.command_lib.util.apis import registry
class GenerateExportSchemas(base.SilentCommand):
"""Generate YAML export schemas for a message in a given API.
*gcloud* commands that have "too many" *create*/*update* command flags may
also provide *export*/*import* commands. *export* lists the current state
of a resource in a YAML *export* format. *import* reads export format data
and either creates a new resource or updates an existing resource.
An export format is an abstract YAML representation of the mutable fields of a
populated protobuf message. Abstraction allows the export format to hide
implementation details of some protobuf constructs like enums and
`additionalProperties`.
One way of describing an export format is with JSON schemas. A schema
documents export format properties for a message in an API, and can also be
used to validate data on import. Validation is important because users can
modify export data before importing it again.
This command generates [JSON schemas](json-schema.org) (in YAML format, go
figure) for a protobuf message in an API. A separate schema files is
generated for each nested message in the resource message.
## CAVEATS
The generated schemas depend on the quality of the protobuf discovery
docs, including proto file comment conventions that are not error checked.
Always manually inspect schemas before using them in a release.
## EXAMPLES
To generate the WorkflowTemplate schemas in the current directory from the
dataproc v1 API:
$ {command} WorkflowTemplate --api=dataproc --api-version=v1
"""
@staticmethod
def Args(parser):
flags.API_REQUIRED_FLAG.AddToParser(parser)
flags.API_VERSION_FLAG.AddToParser(parser)
parser.add_argument(
'message',
help='The name of the message to generate the YAML export schemas for.')
parser.add_argument(
'--directory',
help=('The path name of the directory to create the YAML export '
'schema files in. If not specified then the files are created in '
'the current directory.'))
def Run(self, args):
api = registry.GetAPI(args.api, api_version=args.api_version)
try:
message = getattr(api.GetMessagesModule(), args.message)
except AttributeError:
raise exceptions.InvalidArgumentException(
'message', 'Message [{}] does not exist for API [{} {}]'.format(
args.message, args.api, api.version))
message_spec = arg_utils.GetRecursiveMessageSpec(message)
export.GenerateExportSchemas(
api, args.message, message_spec, args.directory)

View File

@@ -0,0 +1,45 @@
# -*- 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.
"""A command that lists the resource collections for a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.protorpclite import messages as _messages
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import registry
class List(base.ListCommand):
"""List the proto messages for an API."""
@staticmethod
def Args(parser):
base.PAGE_SIZE_FLAG.RemoveFromParser(parser)
base.URI_FLAG.RemoveFromParser(parser)
flags.API_REQUIRED_FLAG.AddToParser(parser)
flags.API_VERSION_FLAG.AddToParser(parser)
parser.display_info.AddFormat('table(name)')
def Run(self, args):
api = registry.GetAPI(args.api, api_version=args.api_version)
messages_module = api.GetMessagesModule()
messages = [
m for m in messages_module.__dict__.values()
if issubclass(type(m), type) and issubclass(m, _messages.Message)]
return [{'name': m.__name__} for m in messages]

View File

@@ -0,0 +1,26 @@
# -*- 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.
"""The super-group for commands to inspect APIs in gcloud."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
class Methods(base.Group):
"""Inspect the methods for an API collection registered in gcloud."""

View File

@@ -0,0 +1,53 @@
# -*- 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.
"""A command that describes a registered gcloud API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.core import properties
ENFORCE_COLLECTION_FLAG = base.Argument(
'--enforce-collection',
action='store_true',
default=True,
help='Fail unless resource belongs to specified collection. '
'This is applicable only if method being called is GET or DELETE '
'and resource identifier is URL.')
class Call(base.Command):
"""Calls an API method with specific parameters."""
@staticmethod
def Args(parser):
flags.API_VERSION_FLAG.AddToParser(parser)
flags.COLLECTION_FLAG.AddToParser(parser)
ENFORCE_COLLECTION_FLAG.AddToParser(parser)
flags.RAW_FLAG.AddToParser(parser)
parser.AddDynamicPositional(
'method',
action=flags.MethodDynamicPositionalAction,
help='The name of the API method to invoke.')
def Run(self, args):
properties.VALUES.core.enable_gri.Set(True)
response = args.method.Call()
return response

View File

@@ -0,0 +1,41 @@
# -*- 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.
"""A command that describes a resource collection for a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import registry
class Describe(base.DescribeCommand):
"""Describe the details of a collection for an API."""
@staticmethod
def Args(parser):
flags.API_VERSION_FLAG.AddToParser(parser)
flags.COLLECTION_FLAG.AddToParser(parser)
parser.add_argument(
'method',
completer=flags.MethodCompleter,
help='The name of the method to get the details of.')
def Run(self, args):
return registry.GetMethod(args.collection, args.method,
api_version=args.api_version)

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.
"""A command that lists the resource collections for a given API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import itertools
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.meta.apis import flags
from googlecloudsdk.command_lib.util.apis import registry
class List(base.ListCommand):
"""List the methods of a resource collection for an API."""
@staticmethod
def Args(parser):
base.PAGE_SIZE_FLAG.RemoveFromParser(parser)
base.URI_FLAG.RemoveFromParser(parser)
collection_flag = base.Argument(
'--collection',
completer=flags.CollectionCompleter,
help='The name of the collection for which to list methods.\n'
'If left blank, returns methods from all collections.')
collection_flag.AddToParser(parser)
flags.API_VERSION_FLAG.AddToParser(parser)
api_flag = base.Argument(
'--api',
completer=flags.APICompleter,
help=('The name of the API to get the methods for. If `--api-version` '
'is also supplied, then returns methods from specified version, '
'otherwise returns methods from all versions of this API.'))
api_flag.AddToParser(parser)
parser.display_info.AddFormat("""
table(
name:sort=1,
detailed_path:optional,
http_method,
request_type,
response_type
)
""")
def Run(self, args):
if not args.collection:
if args.api:
collections = [registry.GetAPICollections(args.api, args.api_version)]
else:
collections = [
registry.GetAPICollections(api.name, api.version)
for api in registry.GetAllAPIs()
]
collections = list(itertools.chain.from_iterable(collections))
methods = [registry.GetMethods(collection.full_name,
api_version=collection.api_version)
for collection in collections]
methods = list(itertools.chain.from_iterable(methods))
return methods
return registry.GetMethods(args.collection, api_version=args.api_version)

View File

@@ -0,0 +1,195 @@
# -*- 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.
"""A command that regenerates existing or new gcloud API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import collections
import fnmatch
import os
import re
import shutil
import googlecloudsdk
from googlecloudsdk import third_party
from googlecloudsdk.api_lib.regen import generate
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import parser_errors
from googlecloudsdk.command_lib.meta import regen as regen_utils
from googlecloudsdk.core import log
from googlecloudsdk.core.util import encoding
from googlecloudsdk.core.util import files
import ruamel.yaml
import six
from six.moves import map
_API_REGEX = '([a-z0-9_]+)/([a-z0-9_]+)'
@base.UniverseCompatible
class Regen(base.Command):
"""Regenerate given API(s) in gcloud."""
@staticmethod
def Args(parser):
parser.add_argument(
'api',
type=arg_parsers.ArgList(),
help='The APIs to regenerate in api_name/api_version format. '
'These can be filename glob expressions to regenerate multiple '
'apis. For example */* to regegenerate all apis and versions, '
'or */*beta* to only regenerate existing beta apis. '
'Note that if discovery doc is supplied this cannot '
'contain any wildcards.')
parser.add_argument(
'--api-discovery-doc',
help='Path to json file describing the api. If not specified, '
'an existing discovery doc will be used.')
parser.add_argument('--config',
help='Regeneration config yaml filename. '
'If not specified canonical config will be used.')
parser.add_argument(
'--base-dir',
help='Directory where generated code will be written. '
'By default googlecloudsdk/generated_clients/apis.')
def Run(self, args):
config = _LoadConfig(args.config)
root_dir = config['root_dir']
changed_config = False
if args.api_discovery_doc:
if not os.path.isfile(args.api_discovery_doc):
raise regen_utils.DiscoveryDocError(
'File not found {}'.format(args.api_discovery_doc))
if len(args.api) != 1:
raise parser_errors.ArgumentError(
'Can only specify one api when discovery doc is provided.')
match = re.match(_API_REGEX, args.api[0])
if not match:
raise regen_utils.DiscoveryDocError(
'Api name must match {} pattern when discovery doc '
'is specified'.format(_API_REGEX))
api_name, api_version = match.group(1), match.group(2)
if api_name not in config['apis']:
log.warning('No such api %s in config, adding...', api_name)
config['apis'][api_name] = {api_version: {'discovery_doc': ''}}
changed_config = True
elif api_version not in config['apis'][api_name]:
log.warning('No such api version %s in config, adding...', api_version)
config['apis'][api_name][api_version] = {'discovery_doc': ''}
changed_config = True
api_version_config = config['apis'].get(api_name).get(api_version, {})
discovery_doc = api_name + '_' + api_version + '.json'
new_discovery_doc = os.path.realpath(args.api_discovery_doc)
old_discovery_doc = os.path.realpath(
os.path.join(args.base_dir, root_dir, discovery_doc))
if new_discovery_doc != old_discovery_doc:
log.status.Print('Copying in {}'.format(new_discovery_doc))
shutil.copyfile(new_discovery_doc, old_discovery_doc)
if api_version_config['discovery_doc'] != discovery_doc:
changed_config = True
api_version_config['discovery_doc'] = discovery_doc
regenerate_list = [
(match.group(1), match.group(2), api_version_config)
]
else:
regex_patern = '|'.join(map(fnmatch.translate, args.api))
regenerate_list = [
(api_name, api_version, api_config)
for api_name, api_version_config in six.iteritems(config['apis'])
for api_version, api_config in six.iteritems(api_version_config)
if re.match(regex_patern, api_name + '/' + api_version)
]
if not regenerate_list:
raise regen_utils.UnknownApi(
'api [{api_name}] not found in "apis" section of '
'{config_file}. Use [gcloud meta apis list] to see available apis.'
.format(api_name=','.join(args.api),
config_file=args.config))
base_dir = args.base_dir or os.path.dirname(
os.path.dirname(googlecloudsdk.__file__))
for api_name, api_version, api_config in sorted(regenerate_list):
log.status.Print(
'Generating {} {} from {}'
.format(api_name,
api_version,
os.path.join(root_dir, api_config['discovery_doc'])))
discovery_doc = os.path.join(
base_dir, root_dir, api_config['discovery_doc'])
output_dir = os.path.join(base_dir, root_dir)
root_package = root_dir.replace('/', '.')
generate.GenerateApitoolsApi(
discovery_doc, output_dir, root_package, api_name, api_version,
api_config)
generate.GenerateApitoolsResourceModule(
discovery_doc,
output_dir,
api_name,
api_version,
api_config.get('resources', {}),
)
client_output_dir = os.path.join(base_dir, root_dir)
apis_config_map = collections.defaultdict(dict)
for api_name, versions_config in config['apis'].items():
for version, version_config in versions_config.items():
apis_config_map[api_name][version] = generate.ApiConfig.FromData(
data=version_config,
root_dir=root_dir,
discovery_doc_dir=client_output_dir,
)
generate.GenerateApiMap(
os.path.join(client_output_dir, 'apis_map.py'), apis_config_map)
# Now that everything passed, config can be updated if needed.
if changed_config:
log.warning('Updated %s', args.config)
with files.FileWriter(args.config) as stream:
ruamel.yaml.round_trip_dump(config, stream)
def _LoadConfig(config_file_name=None):
"""Loads regen config from given filename."""
config_file_name = config_file_name or os.path.join(
os.path.dirname(encoding.Decode(third_party.__file__)),
'regen_apis_config.yaml')
if not os.path.isfile(config_file_name):
raise regen_utils.ConfigFileError('{} Not found'.format(config_file_name))
with files.FileReader(config_file_name) as stream:
config = ruamel.yaml.round_trip_load(stream)
if not config or 'root_dir' not in config:
raise regen_utils.ConfigFileError(
'{} does not have format of gcloud api config file'
.format(config_file_name))
return config