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,27 @@
# -*- 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 main command group for Cloud Pub/Sub subscriptions."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.UniverseCompatible
class Subscriptions(base.Group):
"""Manage Cloud Pub/Sub subscriptions."""
pass

View File

@@ -0,0 +1,120 @@
# -*- 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.
"""Cloud Pub/Sub subscriptions ack command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as api_ex
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
def _Run(args, ack_ids, legacy_output=False, capture_failures=False):
"""Acks one or more messages."""
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
if not capture_failures:
result = client.Ack(ack_ids, subscription_ref)
log.status.Print(
'Acked the messages with the following ackIds: [{}]'.format(
','.join(ack_ids)))
if legacy_output:
return {
'subscriptionId': subscription_ref.RelativeName(),
'ackIds': ack_ids
}, {}
else:
return result, {}
result = None
ack_ids_and_failure_reasons = {}
try:
result = client.Ack(ack_ids, subscription_ref)
except api_ex.HttpError as error:
ack_ids_and_failure_reasons = util.HandleExactlyOnceDeliveryError(error)
failed_ack_ids, successfully_processed_ack_ids = util.ParseExactlyOnceAckIdsAndFailureReasons(
ack_ids_and_failure_reasons, ack_ids)
log.status.Print('Acked the messages with the following ackIds: [{}]'.format(
','.join(successfully_processed_ack_ids)))
if failed_ack_ids:
log.status.Print(
'Failed to ack the messages with the following ackIds: [{}]'.format(
','.join(failed_ack_ids)))
if legacy_output:
result = {
'subscriptionId': subscription_ref.RelativeName(),
'ackIds': ack_ids
}
return result, ack_ids_and_failure_reasons
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Ack(base.Command):
"""Acknowledges one or more messages on the specified subscription."""
detailed_help = {
'DESCRIPTION':
"""\
Acknowledges one or more messages as having been successfully received.
If a delivered message is not acknowledged within the Subscription's
ack deadline, Cloud Pub/Sub will attempt to deliver it again.
To automatically acknowledge messages when pulling from a Subscription,
you can use the `--auto-ack` flag on `gcloud pubsub subscriptions pull`.
"""
}
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'to ACK messages on.')
flags.AddAckIdFlag(parser, 'acknowledge.')
def Run(self, args):
result, ack_ids_and_failure_reasons = _Run(
args, args.ack_ids, capture_failures=True)
if ack_ids_and_failure_reasons:
return ack_ids_and_failure_reasons
return result
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
class AckBeta(Ack):
"""Acknowledges one or more messages on the specified subscription."""
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'to ACK messages on.')
flags.AddAckIdFlag(parser, 'acknowledge.', add_deprecated=True)
def Run(self, args):
ack_ids = flags.ParseAckIdsArgs(args)
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
result, ack_ids_and_failure_reasons = _Run(
args, ack_ids, capture_failures=True, legacy_output=legacy_output)
if ack_ids_and_failure_reasons:
return ack_ids_and_failure_reasons
return result

View File

@@ -0,0 +1,60 @@
release_tracks: [GA, BETA, ALPHA]
help_text:
brief: Add IAM policy binding to a subscription.
description: |
Add an IAM policy binding to a Cloud Pub/Sub Subscription.
examples: |
To add an IAM policy binding with the role of 'roles/editor' for the user 'test-user@example.com'
on the subscription 'my-subscription', run:
$ {command} my-subscription --member='user:test-user@example.com' --role='roles/editor'
To add an IAM policy binding with the role of 'roles/editor' for the service account
'my-iam-account@my-project.iam.gserviceaccount.com' on the subscription 'my-subscription', run:
$ {command} my-subscription \
--member='serviceAccount:my-iam-account@my-project.iam.gserviceaccount.com' \
--role='roles/editor'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
request:
collection: pubsub.projects.subscriptions
arguments:
resource:
help_text: The subscription to add the IAM policy binding.
spec: !REF googlecloudsdk.command_lib.pubsub.resources:subscription
ALPHA:
help_text:
brief: Add IAM policy binding to a subscription.
description: |
Add an IAM policy binding to the IAM policy of a Cloud Pub/Sub Subscription. One binding consists of a member,
a role, and an optional condition.
examples: |
To add an IAM policy binding with the role of 'roles/editor' for the user
'test-user@example.com' on the subscription 'my-subscription', run:
$ {command} my-subscription --member='user:test-user@example.com' --role='roles/editor'
To add an IAM policy binding with the role of 'roles/editor' for the service account
'my-iam-account@my-project.iam.gserviceaccount.com' on the subscription 'my-subscription', run:
$ {command} my-subscription \
--member='serviceAccount:my-iam-account@my-project.iam.gserviceaccount.com' \
--role='roles/editor'
To add an IAM policy binding which expires at the end of the year 2018 for the role of
'roles/pubsub.subscriber' and the user 'test-user@example.com' with subscription 'my-subscription', run:
$ {command} my-subscription --member='user:test-user@example.com' --role='roles/pubsub.subscriber' --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.
iam:
enable_condition: true

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 Pub/Sub subscription 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 Pub/Sub subscription configurations."""

View File

@@ -0,0 +1,38 @@
release_tracks: [ALPHA]
command_type: CONFIG_EXPORT
help_text:
brief: Export the configuration for a Pub/Sub subscription.
description: |
*{command}* exports the configuration for a Pub/Sub subscription.
Subscription 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
subscriptions within the project.
Specifying `--path` allows you to export the configuration(s) to
a local directory.
examples: |
To export the configuration for a subscription, run:
$ {command} my-subscription
To export the configuration for a subscription to a file, run:
$ {command} my-subscription --path=/path/to/dir/
To export the configuration for a subscription in Terraform
HCL format, run:
$ {command} my-subscription --resource-format=terraform
To export the configurations for all subscriptions within a
project, run:
$ {command} --all
arguments:
resource:
help_text: Subscription to export the configuration for.
spec: !REF googlecloudsdk.command_lib.pubsub.resources:subscription

View File

@@ -0,0 +1,269 @@
# -*- 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.
"""Cloud Pub/Sub subscriptions create command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as api_ex
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.api_lib.util import exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.command_lib.util.args import labels_util
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
def _Run(
args,
/,
*,
enable_labels=False,
legacy_output=False,
enable_push_to_cps=False,
enable_vertex_ai_smt=False,
):
"""Creates one or more subscriptions."""
flags.ValidateDeadLetterPolicy(args)
client = subscriptions.SubscriptionsClient()
topic_ref = args.CONCEPTS.topic.Parse()
push_config = util.ParsePushConfig(args)
enable_message_ordering = getattr(args, 'enable_message_ordering', None)
filter_string = getattr(args, 'message_filter', None)
dead_letter_topic = getattr(args, 'dead_letter_topic', None)
max_delivery_attempts = getattr(args, 'max_delivery_attempts', None)
retain_acked_messages = getattr(args, 'retain_acked_messages', None)
retention_duration = getattr(args, 'message_retention_duration', None)
enable_exactly_once_delivery = getattr(
args, 'enable_exactly_once_delivery', None
)
if args.IsSpecified('message_retention_duration'):
retention_duration = util.FormatDuration(retention_duration)
min_retry_delay = getattr(args, 'min_retry_delay', None)
if args.IsSpecified('min_retry_delay'):
min_retry_delay = util.FormatDuration(min_retry_delay)
max_retry_delay = getattr(args, 'max_retry_delay', None)
if args.IsSpecified('max_retry_delay'):
max_retry_delay = util.FormatDuration(max_retry_delay)
bigquery_table = getattr(args, 'bigquery_table', None)
use_topic_schema = getattr(args, 'use_topic_schema', None)
use_table_schema = getattr(args, 'use_table_schema', None)
write_metadata = getattr(args, 'write_metadata', None)
drop_unknown_fields = getattr(args, 'drop_unknown_fields', None)
bigquery_service_account_email = getattr(
args, 'bigquery_service_account_email', None
)
cloud_storage_bucket = getattr(args, 'cloud_storage_bucket', None)
cloud_storage_file_prefix = getattr(args, 'cloud_storage_file_prefix', None)
cloud_storage_file_suffix = getattr(args, 'cloud_storage_file_suffix', None)
cloud_storage_file_datetime_format = getattr(
args, 'cloud_storage_file_datetime_format', None
)
cloud_storage_max_bytes = getattr(args, 'cloud_storage_max_bytes', None)
cloud_storage_max_duration = getattr(args, 'cloud_storage_max_duration', None)
cloud_storage_max_messages = getattr(args, 'cloud_storage_max_messages', None)
if args.IsSpecified('cloud_storage_max_duration'):
cloud_storage_max_duration = util.FormatDuration(cloud_storage_max_duration)
cloud_storage_output_format_list = getattr(
args, 'cloud_storage_output_format', None
)
cloud_storage_output_format = None
if cloud_storage_output_format_list:
cloud_storage_output_format = cloud_storage_output_format_list[0]
cloud_storage_use_topic_schema = getattr(
args, 'cloud_storage_use_topic_schema', None
)
cloud_storage_write_metadata = getattr(
args, 'cloud_storage_write_metadata', None
)
cloud_storage_service_account_email = getattr(
args, 'cloud_storage_service_account_email', None
)
pubsub_export_topic = (
getattr(args, 'pubsub_export_topic', None) if enable_push_to_cps else None
)
pubsub_export_topic_region = getattr(args, 'pubsub_export_topic_region', None)
message_transforms_file = getattr(args, 'message_transforms_file', None)
no_expiration = False
expiration_period = getattr(args, 'expiration_period', None)
if args.IsSpecified('expiration_period'):
if expiration_period == subscriptions.NEVER_EXPIRATION_PERIOD_VALUE:
no_expiration = True
expiration_period = None
if dead_letter_topic:
dead_letter_topic = args.CONCEPTS.dead_letter_topic.Parse().RelativeName()
if pubsub_export_topic:
pubsub_export_topic = (
args.CONCEPTS.pubsub_export_topic.Parse().RelativeName()
)
labels = None
if enable_labels:
labels = labels_util.ParseCreateArgs(
args, client.messages.Subscription.LabelsValue
)
tags = flags.GetTagsMessage(args, client.messages.Subscription.TagsValue)
failed = []
for subscription_ref in args.CONCEPTS.subscription.Parse():
try:
result = client.Create(
subscription_ref,
topic_ref,
args.ack_deadline,
push_config,
retain_acked_messages,
retention_duration,
labels=labels,
no_expiration=no_expiration,
expiration_period=expiration_period,
enable_message_ordering=enable_message_ordering,
filter_string=filter_string,
dead_letter_topic=dead_letter_topic,
max_delivery_attempts=max_delivery_attempts,
min_retry_delay=min_retry_delay,
max_retry_delay=max_retry_delay,
enable_exactly_once_delivery=enable_exactly_once_delivery,
bigquery_table=bigquery_table,
use_topic_schema=use_topic_schema,
use_table_schema=use_table_schema,
write_metadata=write_metadata,
drop_unknown_fields=drop_unknown_fields,
bigquery_service_account_email=bigquery_service_account_email,
cloud_storage_bucket=cloud_storage_bucket,
cloud_storage_file_prefix=cloud_storage_file_prefix,
cloud_storage_file_suffix=cloud_storage_file_suffix,
cloud_storage_file_datetime_format=cloud_storage_file_datetime_format,
cloud_storage_max_bytes=cloud_storage_max_bytes,
cloud_storage_max_duration=cloud_storage_max_duration,
cloud_storage_max_messages=cloud_storage_max_messages,
cloud_storage_output_format=cloud_storage_output_format,
cloud_storage_use_topic_schema=cloud_storage_use_topic_schema,
cloud_storage_write_metadata=cloud_storage_write_metadata,
cloud_storage_service_account_email=cloud_storage_service_account_email,
pubsub_export_topic=pubsub_export_topic,
pubsub_export_topic_region=pubsub_export_topic_region,
message_transforms_file=message_transforms_file,
tags=tags,
enable_vertex_ai_smt=enable_vertex_ai_smt,
)
except api_ex.HttpError as error:
exc = exceptions.HttpException(error)
log.CreatedResource(
subscription_ref.RelativeName(),
kind='subscription',
failed=util.CreateFailureErrorMessage(exc.payload.status_message),
)
failed.append(subscription_ref.subscriptionsId)
continue
if legacy_output:
result = util.SubscriptionDisplayDict(result)
log.CreatedResource(subscription_ref.RelativeName(), kind='subscription')
yield result
if failed:
raise util.RequestsFailedError(failed, 'create')
def _Args(parser, enable_push_to_cps=False):
"""Add flags to the arg parser for creating a subscription."""
topic_help_text = (
'from which this subscription is receiving messages. Each subscription is'
' attached to a single topic.'
)
topic = resource_args.CreateTopicResourceArg(
topic_help_text, positional=False
)
subscription = resource_args.CreateSubscriptionResourceArg(
'to create.', plural=True
)
resource_args.AddResourceArgs(parser, [topic, subscription])
flags.AddSubscriptionSettingsFlags(
parser, enable_push_to_cps=enable_push_to_cps
)
labels_util.AddCreateLabelsFlags(parser)
flags.AddMessageTransformsFlags(parser)
flags.AddTagsFlag(parser)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Creates one or more Cloud Pub/Sub subscriptions."""
detailed_help = {'DESCRIPTION': """\
Creates one or more Cloud Pub/Sub subscriptions for a given topic.
The new subscription defaults to a PULL subscription unless a push
endpoint is specified."""}
@classmethod
def Args(cls, parser):
_Args(parser)
def Run(self, args):
flags.ValidateFilterString(args)
return _Run(args, enable_labels=True)
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class CreateBeta(Create):
"""Creates one or more Cloud Pub/Sub subscriptions."""
@classmethod
def Args(cls, parser):
_Args(parser, enable_push_to_cps=True)
def Run(self, args):
flags.ValidateFilterString(args)
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
return _Run(
args,
enable_labels=True,
legacy_output=legacy_output,
enable_push_to_cps=True,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(CreateBeta):
"""Creates one or more Cloud Pub/Sub subscriptions."""
@classmethod
def Args(cls, parser):
super(CreateAlpha, cls).Args(parser)
def Run(self, args):
flags.ValidateFilterString(args)
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
return _Run(
args,
enable_labels=True,
legacy_output=legacy_output,
enable_push_to_cps=True,
enable_vertex_ai_smt=True,
)

View File

@@ -0,0 +1,82 @@
# -*- 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.
"""Cloud Pub/Sub subscription delete command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as api_ex
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.api_lib.util import exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
def _Run(args, legacy_output=False):
"""Deletes one or more subscriptions."""
client = subscriptions.SubscriptionsClient()
failed = []
for subscription_ref in args.CONCEPTS.subscription.Parse():
try:
result = client.Delete(subscription_ref)
except api_ex.HttpError as error:
exc = exceptions.HttpException(error)
log.DeletedResource(
subscription_ref.RelativeName(),
kind='subscription',
failed=util.CreateFailureErrorMessage(exc.payload.status_message),
)
failed.append(subscription_ref.subscriptionsId)
continue
subscription = client.messages.Subscription(
name=subscription_ref.RelativeName())
if legacy_output:
result = util.SubscriptionDisplayDict(subscription)
log.DeletedResource(subscription_ref.RelativeName(), kind='subscription')
yield result
if failed:
raise util.RequestsFailedError(failed, 'delete')
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Deletes one or more Cloud Pub/Sub subscriptions."""
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'to delete.', plural=True)
def Run(self, args):
return _Run(args)
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
class DeleteBeta(Delete):
"""Deletes one or more Cloud Pub/Sub subscriptions."""
def Run(self, args):
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
return _Run(args, legacy_output=legacy_output)

View File

@@ -0,0 +1,37 @@
# -*- 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.
"""Cloud Pub/Sub subscription describe command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import resource_args
class Describe(base.DescribeCommand):
"""Describes a Cloud Pub/Sub subscription."""
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'to describe.')
def Run(self, args):
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
return client.Get(subscription_ref)

View File

@@ -0,0 +1,51 @@
# -*- 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.
"""Cloud Pub/Sub subscriptions get-iam-policy command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import resource_args
@base.ReleaseTracks(base.ReleaseTrack.GA, base.ReleaseTrack.BETA)
class GetIamPolicy(base.ListCommand):
"""Get the IAM policy for a Cloud Pub/Sub Subscription."""
detailed_help = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
"""\
To print the IAM policy for a given subscription, run:
$ {command} my-subscription
""",
}
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser,
'to get the IAM policy of.')
base.URI_FLAG.RemoveFromParser(parser)
def Run(self, args):
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
return client.GetIamPolicy(subscription_ref)

View File

@@ -0,0 +1,23 @@
- release_tracks: [ALPHA]
help_text:
brief: Get the IAM policy for a subscription.
description: |
*{command}* displays the IAM policy associated with a subscription.
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 subscription, run:
$ {command} my-subscription
request:
collection: pubsub.projects.subscriptions
arguments:
resource:
help_text: The subscription for which to display the IAM policy.
spec: !REF googlecloudsdk.command_lib.pubsub.resources:subscription

View File

@@ -0,0 +1,58 @@
# -*- 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.
"""Cloud Pub/Sub subscriptions list command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.core import properties
def _Run(args, legacy_output=False):
client = subscriptions.SubscriptionsClient()
for sub in client.List(util.ParseProject(), page_size=args.page_size):
if legacy_output:
sub = util.ListSubscriptionDisplayDict(sub)
yield sub
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(base.ListCommand):
"""Lists Cloud Pub/Sub subscriptions."""
detailed_help = {
'DESCRIPTION': 'Lists all of the Cloud Pub/Sub subscriptions that exist '
'in a given project.'
}
@staticmethod
def Args(parser):
parser.display_info.AddUriFunc(util.SubscriptionUriFunc)
def Run(self, args):
return _Run(args)
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
class ListBeta(List):
"""Lists Cloud Pub/Sub subscriptions."""
def Run(self, args):
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
return _Run(args, legacy_output=legacy_output)

View File

@@ -0,0 +1,108 @@
# -*- 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.
"""Cloud Pub/Sub subscription modify command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as api_ex
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.api_lib.util import exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
@base.Deprecate(
is_removed=False,
warning='This command has been renamed. Please use '
'`modify-message-ack-deadline` instead.')
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
class ModifyAckDeadline(base.Command):
"""Modifies the ACK deadline for a specific Cloud Pub/Sub message.
This method is useful to indicate that more time is needed to process a
message by the subscriber, or to make the message available for
redelivery if the processing was interrupted.
"""
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'messages belong to.')
flags.AddAckIdFlag(parser, 'modify the deadline for.', add_deprecated=True)
flags.AddAckDeadlineFlag(parser, required=True)
def Run(self, args):
"""This is what gets called when the user runs this command.
Args:
args: an argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
Display dictionary with information about the new ACK deadline seconds
for the given subscription and ackId.
"""
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
ack_ids = flags.ParseAckIdsArgs(args)
result = None
ack_ids_and_failure_reasons = {}
try:
result = client.ModifyAckDeadline(subscription_ref, ack_ids,
args.ack_deadline)
except api_ex.HttpError as error:
exc = exceptions.HttpException(error)
ack_ids_and_failure_reasons = util.ParseExactlyOnceErrorInfo(
exc.payload.details)
# If the failure doesn't have more information (specifically for exactly
# once related failures), re-raise the exception.
if not ack_ids_and_failure_reasons:
raise
failed_ack_ids = [ack['AckId'] for ack in ack_ids_and_failure_reasons]
successfully_processed_ack_ids = [
ack_id for ack_id in ack_ids if ack_id not in failed_ack_ids
]
log.status.Print('Set ackDeadlineSeconds to [{0}] for messages with ackId '
'[{1}]] for subscription [{2}]'.format(
args.ack_deadline,
','.join(successfully_processed_ack_ids),
subscription_ref.RelativeName()))
if failed_ack_ids:
log.status.Print(
'Set ackDeadlineSeconds to [{0}] for messages with ackId '
'[{1}]] failed for subscription [{2}]'.format(
args.ack_deadline, ','.join(failed_ack_ids),
subscription_ref.RelativeName()))
if ack_ids_and_failure_reasons:
return ack_ids_and_failure_reasons
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
if legacy_output:
result = {
'subscriptionId': subscription_ref.RelativeName(),
'ackId': ack_ids,
'ackDeadlineSeconds': args.ack_deadline
}
return result

View File

@@ -0,0 +1,128 @@
# -*- 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.
"""Cloud Pub/Sub subscription modify command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as api_ex
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
def _Run(args, ack_ids, legacy_output=False, capture_failures=False):
"""Modifies the ack deadline for one or more messages."""
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
if not capture_failures:
result = client.ModifyAckDeadline(subscription_ref, ack_ids,
args.ack_deadline)
log.status.Print('Set ackDeadlineSeconds to [{0}] for messages with ackId '
'[{1}]] for subscription [{2}]'.format(
args.ack_deadline, ','.join(ack_ids),
subscription_ref.RelativeName()))
if legacy_output:
return {
'subscriptionId': subscription_ref.RelativeName(),
'ackId': ack_ids,
'ackDeadlineSeconds': args.ack_deadline
}, {}
else:
return result, {}
result = None
ack_ids_and_failure_reasons = {}
try:
result = client.ModifyAckDeadline(subscription_ref, ack_ids,
args.ack_deadline)
except api_ex.HttpError as error:
ack_ids_and_failure_reasons = util.HandleExactlyOnceDeliveryError(error)
failed_ack_ids, successfully_processed_ack_ids = util.ParseExactlyOnceAckIdsAndFailureReasons(
ack_ids_and_failure_reasons, ack_ids)
log.status.Print('Set ackDeadlineSeconds to [{0}] for messages with ackId '
'[{1}]] for subscription [{2}]'.format(
args.ack_deadline,
','.join(successfully_processed_ack_ids),
subscription_ref.RelativeName()))
if failed_ack_ids:
log.status.Print('Set ackDeadlineSeconds to [{0}] for messages with ackId '
'[{1}]] failed for subscription [{2}]'.format(
args.ack_deadline, ','.join(failed_ack_ids),
subscription_ref.RelativeName()))
if legacy_output:
result = {
'subscriptionId': subscription_ref.RelativeName(),
'ackId': ack_ids,
'ackDeadlineSeconds': args.ack_deadline
}
return result, ack_ids_and_failure_reasons
@base.ReleaseTracks(base.ReleaseTrack.GA)
class ModifyMessageAckDeadline(base.Command):
"""Modifies the ACK deadline for a specific Cloud Pub/Sub message."""
detailed_help = {
'DESCRIPTION':
"""\
This method is useful to indicate that more time is needed to process
a message by the subscriber, or to make the message available for
redelivery if the processing was interrupted."""
}
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'messages belong to.')
flags.AddAckIdFlag(parser, 'modify the deadline for.')
flags.AddAckDeadlineFlag(parser, required=True)
def Run(self, args):
result, ack_ids_and_failure_reasons = _Run(
args, args.ack_ids, capture_failures=True)
if ack_ids_and_failure_reasons:
return ack_ids_and_failure_reasons
return result
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
class ModifyMessageAckDeadlineBeta(ModifyMessageAckDeadline):
"""Modifies the ACK deadline for a specific Cloud Pub/Sub message."""
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'messages belong to.')
flags.AddAckIdFlag(parser, 'modify the deadline for.', add_deprecated=True)
flags.AddAckDeadlineFlag(parser, required=True)
def Run(self, args):
ack_ids = flags.ParseAckIdsArgs(args)
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
result, ack_ids_and_failure_reasons = _Run(
args, ack_ids, legacy_output=legacy_output, capture_failures=True)
if ack_ids_and_failure_reasons:
return ack_ids_and_failure_reasons
return result

View File

@@ -0,0 +1,78 @@
# -*- 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.
"""Cloud Pub/Sub subscription modify-push-config command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
def _Run(args, legacy_output=False):
"""Modifies the push config for a subscription."""
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
push_config = util.ParsePushConfig(args)
result = client.ModifyPushConfig(subscription_ref, push_config)
log.UpdatedResource(subscription_ref.RelativeName(), kind='subscription')
if legacy_output:
return {
'subscriptionId': subscription_ref.RelativeName(),
'pushEndpoint': args.push_endpoint
}
else:
return result
def _Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'to modify.')
flags.AddPushConfigFlags(
parser, required=True, is_modify_push_config_request=True
)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class ModifyPushConfig(base.Command):
"""Modifies the push configuration of a Cloud Pub/Sub subscription."""
@classmethod
def Args(cls, parser):
_Args(parser)
def Run(self, args):
return _Run(args)
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
class ModifyPushConfigBeta(ModifyPushConfig):
"""Modifies the push configuration of a Cloud Pub/Sub subscription."""
@classmethod
def Args(cls, parser):
_Args(parser)
def Run(self, args):
legacy_output = properties.VALUES.pubsub.legacy_output.GetBool()
return _Run(args, legacy_output=legacy_output)

View File

@@ -0,0 +1,165 @@
# -*- 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.
"""Cloud Pub/Sub subscription pull command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as api_ex
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.api_lib.util import exceptions as util_ex
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
import six
MESSAGE_FORMAT = """\
table[box](
message.data.decode(base64).decode(utf-8),
message.messageId,
message.orderingKey,
message.attributes.list(separator='\n'),
deliveryAttempt,
ackId.if(NOT auto_ack)
)
"""
MESSAGE_FORMAT_WITH_ACK_STATUS = """\
table[box](
message.data.decode(base64).decode(utf-8),
message.messageId,
message.orderingKey,
message.attributes.list(separator='\n'),
deliveryAttempt,
ackId.if(NOT auto_ack),
ackStatus.if(auto_ack)
)
"""
def _Run(args, max_messages, return_immediately=False):
"""Pulls messages from a subscription."""
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
pull_response = client.Pull(subscription_ref, max_messages,
return_immediately)
failed_ack_ids = {}
ack_ids_and_failure_reasons = []
if args.auto_ack and pull_response.receivedMessages:
ack_ids = [message.ackId for message in pull_response.receivedMessages]
try:
client.Ack(ack_ids, subscription_ref)
except api_ex.HttpError as error:
exc = util_ex.HttpException(error)
ack_ids_and_failure_reasons = util.ParseExactlyOnceErrorInfo(
exc.payload.details)
# If the failure doesn't have more information (specifically for exactly
# once related failures), assume all the ack ids have failed with the
# same status.
if not ack_ids_and_failure_reasons:
for ack_id in ack_ids:
failed_ack_ids[ack_id] = 'FAILURE_' + six.text_type(error.status_code)
if not failed_ack_ids:
for ack_ids_and_failure_reason in ack_ids_and_failure_reasons:
failed_ack_ids[ack_ids_and_failure_reason[
'AckId']] = ack_ids_and_failure_reason['FailureReason']
if not args.auto_ack:
return pull_response.receivedMessages
# We attempted to auto-ack this message. Augment the response with ackStatus.
return_val = []
for message in pull_response.receivedMessages:
# Copy the message into a separate object so we can mutate it.
message_copy = {}
for field in message.all_fields():
value = getattr(message, field.name)
if value:
message_copy[field.name] = value
if message.ackId in failed_ack_ids:
message_copy['ackStatus'] = failed_ack_ids[message.ackId]
else:
message_copy['ackStatus'] = 'SUCCESS'
return_val.append(message_copy)
return return_val
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Pull(base.ListCommand):
"""Pulls one or more Cloud Pub/Sub messages from a subscription."""
detailed_help = {
'DESCRIPTION':
"""\
Returns one or more messages from the specified Cloud Pub/Sub
subscription, if there are any messages enqueued.
By default, this command returns only one message from the
subscription. Use the `--limit` flag to specify the max messages to
return.
Please note that this command is not guaranteed to return all the
messages in your backlog or the maximum specified in the --limit
argument. Receiving fewer messages than available occasionally
is normal."""
}
@staticmethod
def Args(parser):
parser.display_info.AddFormat(MESSAGE_FORMAT_WITH_ACK_STATUS)
resource_args.AddSubscriptionResourceArg(parser, 'to pull messages from.')
flags.AddPullFlags(parser)
base.LIMIT_FLAG.SetDefault(parser, 1)
def Run(self, args):
return _Run(args, args.limit)
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.ALPHA)
class PullBeta(Pull):
"""Pulls one or more Cloud Pub/Sub messages from a subscription."""
@staticmethod
def Args(parser):
parser.display_info.AddFormat(MESSAGE_FORMAT_WITH_ACK_STATUS)
resource_args.AddSubscriptionResourceArg(parser, 'to pull messages from.')
flags.AddPullFlags(
parser, add_deprecated=True, add_wait=True, add_return_immediately=True
)
def Run(self, args):
if args.IsSpecified('limit'):
if args.IsSpecified('max_messages'):
raise exceptions.ConflictingArgumentsException('--max-messages',
'--limit')
max_messages = args.limit
else:
max_messages = args.max_messages
return_immediately = False
if args.IsSpecified('return_immediately'):
return_immediately = args.return_immediately
elif args.IsSpecified('wait'):
return_immediately = not args.wait
return _Run(args, max_messages, return_immediately)

View File

@@ -0,0 +1,60 @@
release_tracks: [ALPHA, BETA, GA]
help_text:
brief: Remove IAM policy binding of a subscription
description: |
Remove an IAM policy binding of a Cloud Pub/Sub Subscription.
examples: |
To Remove an IAM policy binding for the role of 'roles/editor' for the user 'test-user@gmail.com'
with subscription 'my-subscription', run:
$ {command} my-subscription --member='user:test-user@gmail.com' --role='roles/editor'
The following command will remove an IAM policy binding for the role of
'roles/editor' from all authenticated users on subscription
'my-subscription':
$ {command} my-subscription --member='allAuthenticatedUsers' \
--role='roles/editor'
See https://cloud.google.com/iam/docs/managing-policies for details of
policy role and member types.
request:
collection: pubsub.projects.subscriptions
arguments:
resource:
help_text: The subscription to remove the IAM policy binding from.
spec: !REF googlecloudsdk.command_lib.pubsub.resources:subscription
ALPHA:
help_text:
brief: Remove IAM policy binding of a subscription.
description: |
Remove an IAM policy binding from the IAM policy of a Cloud Pub/Sub Subscription. 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'
with subscription 'my-subscription', run:
$ {command} my-subscription --member='user:test-user@gmail.com' --role='roles/editor'
The following command will remove an IAM policy binding for the role of
'roles/editor' from all authenticated users on subscription
'my-subscription':
$ {command} my-subscription --member='allAuthenticatedUsers' \
--role='roles/editor'
To remove an IAM policy binding which expires at the end of the year 2018 for the role of
'roles/pubsub.subscriber' and the user 'test-user@gmail.com' with subscription 'my-subscription', run:
$ {command} my-subscription --member='user:test-user@gmail.com' --role='roles/pubsub.subscriber' --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.
iam:
enable_condition: true

View File

@@ -0,0 +1,70 @@
# -*- 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.
"""Cloud Pub/Sub subscriptions seek command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
def _Run(args):
"""This is what gets called when the user runs this command.
Args:
args: an argparse namespace. All the arguments that were provided to this
command invocation.
Returns:
A serialized object (dict) describing the results of the operation. This
description fits the Resource described in the ResourceRegistry under
'pubsub.subscriptions.seek'.
"""
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
result = {'subscriptionId': subscription_ref.RelativeName()}
snapshot_ref = None
time = None
if args.snapshot:
snapshot_ref = util.ParseSnapshot(args.snapshot, args.snapshot_project)
result['snapshotId'] = snapshot_ref.RelativeName()
else:
time = util.FormatSeekTime(args.time)
result['time'] = time
client.Seek(subscription_ref, time=time, snapshot_ref=snapshot_ref)
return result
@base.DefaultUniverseOnly
class Seek(base.Command):
"""Resets a subscription's backlog to a point in time or to a given snapshot."""
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'to affect.')
flags.AddSeekFlags(parser)
def Run(self, args):
return _Run(args)

View File

@@ -0,0 +1,51 @@
# -*- 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.
"""Cloud Pub/Sub subscriptions set-iam-policy command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.GA, base.ReleaseTrack.BETA)
class SetIamPolicy(base.Command):
"""Set the IAM policy for a Cloud Pub/Sub Subscription."""
detailed_help = iam_util.GetDetailedHelpForSetIamPolicy(
'subscription', 'my-subscription')
@staticmethod
def Args(parser):
resource_args.AddSubscriptionResourceArg(parser, 'to set an IAM policy on.')
flags.AddIamPolicyFileFlag(parser)
def Run(self, args):
client = subscriptions.SubscriptionsClient()
messages = client.messages
subscription_ref = args.CONCEPTS.subscription.Parse()
policy = iam_util.ParsePolicyFile(args.policy_file, messages.Policy)
response = client.SetIamPolicy(subscription_ref, policy=policy)
log.status.Print('Updated IAM policy for subscription [{}].'.format(
subscription_ref.Name()))
return response

View File

@@ -0,0 +1,30 @@
- release_tracks: [ALPHA]
help_text:
brief: Set the IAM policy for a Cloud Pub/Sub Subscription.
description: |
This command replaces the existing IAM policy for a subscription, given a
subscription and a file encoded in JSON or YAML that contains the IAM
policy.
If the given policy file specifies an "etag" value, then the
replacement will succeed only if the policy already in place matches that
etag. (An etag obtained via `get-iam-policy` will prevent the replacement
if the policy for the subscription has been subsequently updated.) A
policy file that does not contain an etag value will replace any existing
policy for the subscription.
examples: |
The following command will read an IAM policy defined in 'policy.json'
and set it for a subscription 'my-sub'
$ {command} my-sub policy.json
See https://cloud.google.com/iam/docs/managing-policies for details of
the policy file format and contents.
request:
collection: pubsub.projects.subscriptions
arguments:
resource:
help_text: The subscription for which to set the IAM policy.
spec: !REF googlecloudsdk.command_lib.pubsub.resources:subscription

View File

@@ -0,0 +1,280 @@
# -*- 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.
"""Cloud Pub/Sub subscriptions update command."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.pubsub import subscriptions
from googlecloudsdk.api_lib.util import exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.pubsub import flags
from googlecloudsdk.command_lib.pubsub import resource_args
from googlecloudsdk.command_lib.pubsub import util
from googlecloudsdk.command_lib.util.args import labels_util
from googlecloudsdk.core import log
def _Args(
parser,
enable_push_to_cps=False,
):
"""Adds the arguments for this command.
Args:
parser: the parser for the command.
enable_push_to_cps: whether or not to enable Pubsub Export config flags
support.
"""
resource_args.AddSubscriptionResourceArg(parser, 'to update.')
flags.AddSubscriptionSettingsFlags(
parser,
is_update=True,
enable_push_to_cps=enable_push_to_cps,
)
labels_util.AddUpdateLabelsFlags(parser)
flags.AddMessageTransformsFlags(parser, is_update=True)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Update(base.UpdateCommand):
"""Updates an existing Cloud Pub/Sub subscription."""
@classmethod
def Args(cls, parser):
_Args(parser)
@exceptions.CatchHTTPErrorRaiseHTTPException()
def Run(
self,
args,
/,
*,
enable_push_to_cps=False,
enable_vertex_ai_smt=False,
):
"""This is what gets called when the user runs this command.
Args:
args: An argparse namespace. All the arguments that were provided to this
command invocation.
enable_push_to_cps: Whether or not to enable Pubsub Export config flags
support.
enable_vertex_ai_smt: Whether to enable Vertex AI SMTs.
Returns:
A serialized object (dict) describing the results of the operation. This
description fits the Resource described in the ResourceRegistry under
'pubsub.projects.subscriptions'.
Raises:
An HttpException if there was a problem calling the
API subscriptions.Patch command.
"""
flags.ValidateDeadLetterPolicy(args)
client = subscriptions.SubscriptionsClient()
subscription_ref = args.CONCEPTS.subscription.Parse()
dead_letter_topic = getattr(args, 'dead_letter_topic', None)
max_delivery_attempts = getattr(args, 'max_delivery_attempts', None)
clear_dead_letter_policy = getattr(args, 'clear_dead_letter_policy', None)
clear_retry_policy = getattr(args, 'clear_retry_policy', None)
clear_bigquery_config = getattr(args, 'clear_bigquery_config', None)
clear_cloud_storage_config = getattr(
args, 'clear_cloud_storage_config', None
)
clear_push_no_wrapper_config = getattr(
args, 'clear_push_no_wrapper_config', None
)
clear_pubsub_export_config = (
getattr(args, 'clear_pubsub_export_config', None)
if enable_push_to_cps
else None
)
labels_update = labels_util.ProcessUpdateArgsLazy(
args,
client.messages.Subscription.LabelsValue,
orig_labels_thunk=lambda: client.Get(subscription_ref).labels,
)
no_expiration = False
expiration_period = getattr(args, 'expiration_period', None)
if expiration_period:
if expiration_period == subscriptions.NEVER_EXPIRATION_PERIOD_VALUE:
no_expiration = True
expiration_period = None
if dead_letter_topic:
dead_letter_topic = args.CONCEPTS.dead_letter_topic.Parse().RelativeName()
min_retry_delay = getattr(args, 'min_retry_delay', None)
if args.IsSpecified('min_retry_delay'):
min_retry_delay = util.FormatDuration(min_retry_delay)
max_retry_delay = getattr(args, 'max_retry_delay', None)
if args.IsSpecified('max_retry_delay'):
max_retry_delay = util.FormatDuration(max_retry_delay)
bigquery_table = getattr(args, 'bigquery_table', None)
use_topic_schema = getattr(args, 'use_topic_schema', None)
use_table_schema = getattr(args, 'use_table_schema', None)
write_metadata = getattr(args, 'write_metadata', None)
drop_unknown_fields = getattr(args, 'drop_unknown_fields', None)
bigquery_service_account_email = getattr(
args, 'bigquery_service_account_email', None
)
cloud_storage_bucket = getattr(args, 'cloud_storage_bucket', None)
cloud_storage_file_prefix = getattr(args, 'cloud_storage_file_prefix', None)
cloud_storage_file_suffix = getattr(args, 'cloud_storage_file_suffix', None)
cloud_storage_file_datetime_format = getattr(
args, 'cloud_storage_file_datetime_format', None
)
cloud_storage_max_bytes = getattr(args, 'cloud_storage_max_bytes', None)
cloud_storage_max_duration = getattr(
args, 'cloud_storage_max_duration', None
)
cloud_storage_max_messages = getattr(
args, 'cloud_storage_max_messages', None
)
if args.IsSpecified('cloud_storage_max_duration'):
cloud_storage_max_duration = util.FormatDuration(
cloud_storage_max_duration
)
cloud_storage_output_format_list = getattr(
args, 'cloud_storage_output_format', None
)
cloud_storage_output_format = None
if cloud_storage_output_format_list:
cloud_storage_output_format = cloud_storage_output_format_list[0]
cloud_storage_use_topic_schema = getattr(
args, 'cloud_storage_use_topic_schema', None
)
cloud_storage_write_metadata = getattr(
args, 'cloud_storage_write_metadata', None
)
cloud_storage_service_account_email = getattr(
args, 'cloud_storage_service_account_email', None
)
pubsub_export_topic = (
getattr(args, 'pubsub_export_topic', None)
if enable_push_to_cps
else None
)
if pubsub_export_topic:
pubsub_export_topic = (
args.CONCEPTS.pubsub_export_topic.Parse().RelativeName()
)
pubsub_export_topic_region = getattr(
args, 'pubsub_export_topic_region', None
)
enable_exactly_once_delivery = getattr(
args, 'enable_exactly_once_delivery', None
)
message_transforms_file = getattr(args, 'message_transforms_file', None)
clear_message_transforms = getattr(args, 'clear_message_transforms', None)
try:
result = client.Patch(
subscription_ref,
ack_deadline=args.ack_deadline,
push_config=util.ParsePushConfig(args),
retain_acked_messages=args.retain_acked_messages,
labels=labels_update.GetOrNone(),
message_retention_duration=args.message_retention_duration,
no_expiration=no_expiration,
expiration_period=expiration_period,
dead_letter_topic=dead_letter_topic,
max_delivery_attempts=max_delivery_attempts,
clear_dead_letter_policy=clear_dead_letter_policy,
clear_retry_policy=clear_retry_policy,
min_retry_delay=min_retry_delay,
max_retry_delay=max_retry_delay,
enable_exactly_once_delivery=enable_exactly_once_delivery,
bigquery_table=bigquery_table,
use_topic_schema=use_topic_schema,
use_table_schema=use_table_schema,
write_metadata=write_metadata,
drop_unknown_fields=drop_unknown_fields,
bigquery_service_account_email=bigquery_service_account_email,
clear_bigquery_config=clear_bigquery_config,
cloud_storage_bucket=cloud_storage_bucket,
cloud_storage_file_prefix=cloud_storage_file_prefix,
cloud_storage_file_suffix=cloud_storage_file_suffix,
cloud_storage_file_datetime_format=cloud_storage_file_datetime_format,
cloud_storage_max_bytes=cloud_storage_max_bytes,
cloud_storage_max_duration=cloud_storage_max_duration,
cloud_storage_max_messages=cloud_storage_max_messages,
cloud_storage_output_format=cloud_storage_output_format,
cloud_storage_use_topic_schema=cloud_storage_use_topic_schema,
cloud_storage_write_metadata=cloud_storage_write_metadata,
cloud_storage_service_account_email=cloud_storage_service_account_email,
clear_cloud_storage_config=clear_cloud_storage_config,
clear_push_no_wrapper_config=clear_push_no_wrapper_config,
pubsub_export_topic=pubsub_export_topic,
pubsub_export_topic_region=pubsub_export_topic_region,
clear_pubsub_export_config=clear_pubsub_export_config,
message_transforms_file=message_transforms_file,
clear_message_transforms=clear_message_transforms,
enable_vertex_ai_smt=enable_vertex_ai_smt,
)
except subscriptions.NoFieldsSpecifiedError:
if not any(
args.IsSpecified(arg)
for arg in ('clear_labels', 'update_labels', 'remove_labels')
):
raise
log.status.Print('No update to perform.')
result = None
else:
log.UpdatedResource(subscription_ref.RelativeName(), kind='subscription')
return result
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class UpdateBeta(Update):
"""Updates an existing Cloud Pub/Sub subscription."""
@classmethod
def Args(cls, parser):
_Args(
parser,
enable_push_to_cps=True,
)
@exceptions.CatchHTTPErrorRaiseHTTPException()
def Run(self, args, /, *, enable_vertex_ai_smt=False):
return super(UpdateBeta, self).Run(
args,
enable_push_to_cps=True,
enable_vertex_ai_smt=enable_vertex_ai_smt,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(UpdateBeta):
"""Updates an existing Cloud Pub/Sub subscription."""
@classmethod
def Args(cls, parser):
super(UpdateAlpha, cls).Args(parser)
@exceptions.CatchHTTPErrorRaiseHTTPException()
def Run(self, args):
return super(UpdateAlpha, self).Run(args, enable_vertex_ai_smt=True)