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,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The triggers command group for Eventarc."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Triggers(base.Group):
"""Manage Eventarc triggers."""
category = base.SERVERLESS_CATEGORY

View File

@@ -0,0 +1,223 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to create a trigger."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import encoding
from googlecloudsdk.api_lib.eventarc import triggers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.eventarc import flags
from googlecloudsdk.command_lib.eventarc import types
from googlecloudsdk.command_lib.util.args import labels_util
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
_DETAILED_HELP = {
'DESCRIPTION': '{description}',
'EXAMPLES': """ \
To create a new trigger ``my-trigger'' for events of type ``google.cloud.pubsub.topic.v1.messagePublished'' with destination Cloud Run service ``my-service'', run:
$ {command} my-trigger --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" --destination-run-service=my-service
""",
}
class NoDestinationLocationSpecifiedError(exceptions.Error):
"""Error when no destination location was specified for a global trigger."""
class UnsupportedDestinationError(exceptions.Error):
"""Error when none of the supported destination args is specified."""
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Create(base.CreateCommand):
"""Create an Eventarc trigger."""
detailed_help = _DETAILED_HELP
@classmethod
def Args(cls, parser):
flags.AddCreateTrigerResourceArgs(parser, cls.ReleaseTrack())
flags.AddEventFiltersArg(parser, cls.ReleaseTrack(), required=True)
flags.AddEventFiltersPathPatternArg(parser, cls.ReleaseTrack())
flags.AddEventDataContentTypeArg(parser, cls.ReleaseTrack())
flags.AddServiceAccountArg(parser)
flags.AddCreateDestinationArgs(parser, cls.ReleaseTrack(), required=True)
flags.AddTransportTopicResourceArg(parser)
flags.AddTriggerRetryPolicyArgs(parser)
labels_util.AddCreateLabelsFlags(parser)
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Run the create command."""
client = triggers.TriggersClientV1()
trigger_ref = args.CONCEPTS.trigger.Parse()
channel_ref = flags.GetChannelArg(args, self.ReleaseTrack())
transport_topic_ref = args.CONCEPTS.transport_topic.Parse()
event_filters = flags.GetEventFiltersArg(args, self.ReleaseTrack())
event_filters_path_pattern = flags.GetEventFiltersPathPatternArg(
args, self.ReleaseTrack()
)
event_data_content_type = flags.GetEventDataContentTypeArg(
args, self.ReleaseTrack()
)
# destination Cloud Run
if args.IsSpecified('destination_run_service') or args.IsKnownAndSpecified(
'destination_run_job'
):
resource_type = (
'service' if args.IsSpecified('destination_run_service') else 'job'
)
destination_run_region = self.GetDestinationLocation(
args,
trigger_ref,
'destination_run_region',
'Cloud Run {}'.format(resource_type),
)
# Jobs only exist in the v1 API and thus only in the GA track.
# This extra check is needed so we don't throw trying to access a flag
# which doesn't exist.
run_job = (
args.destination_run_job if 'destination_run_job' in args else None
)
destination_message = client.BuildCloudRunDestinationMessage(
args.destination_run_service,
run_job,
args.destination_run_path,
destination_run_region,
)
dest_str = 'Cloud Run {} [{}]'.format(
resource_type, args.destination_run_service or run_job
)
loading_msg = ''
# destination GKE service
elif args.IsSpecified('destination_gke_service'):
destination_gke_location = self.GetDestinationLocation(
args, trigger_ref, 'destination_gke_location', 'GKE service'
)
destination_gke_namespace = args.destination_gke_namespace or 'default'
destination_message = client.BuildGKEDestinationMessage(
args.destination_gke_cluster,
destination_gke_location,
destination_gke_namespace,
args.destination_gke_service,
args.destination_gke_path,
)
dest_str = 'GKE service [{}] in cluster [{}]'.format(
args.destination_gke_service, args.destination_gke_cluster
)
loading_msg = 'this operation may take several minutes'
# destination Http Endpoint
elif args.IsSpecified('destination_http_endpoint_uri'):
destination_message = client.BuildHTTPEndpointDestinationMessage(
args.destination_http_endpoint_uri,
args.network_attachment,
)
dest_str = 'HTTP endpoint [{}]'.format(args.destination_http_endpoint_uri)
loading_msg = 'this operation may take several minutes'
# destination Workflow
elif args.IsSpecified('destination_workflow'):
destination_workflow_location = self.GetDestinationLocation(
args, trigger_ref, 'destination_workflow_location', 'Workflow'
)
destination_message = client.BuildWorkflowDestinationMessage(
trigger_ref.Parent().Parent().Name(),
args.destination_workflow,
destination_workflow_location,
)
dest_str = 'Workflow [{}]'.format(args.destination_workflow)
loading_msg = ''
# Destination Cloud Function
elif args.IsSpecified('destination_function'):
destination_function_location = self.GetDestinationLocation(
args, trigger_ref, 'destination_function_location', 'Function'
)
destination_message = client.BuildFunctionDestinationMessage(
trigger_ref.Parent().Parent().Name(),
args.destination_function,
destination_function_location,
)
dest_str = 'Cloud Function [{}]'.format(args.destination_function)
loading_msg = ''
else:
raise UnsupportedDestinationError('Must specify a valid destination.')
trigger_message = client.BuildTriggerMessage(
trigger_ref,
event_filters,
event_filters_path_pattern,
event_data_content_type,
args.service_account,
destination_message,
transport_topic_ref,
channel_ref,
args.max_retry_attempts,
labels_util.ParseCreateArgs(args, client.LabelsValueClass()),
)
operation = client.Create(trigger_ref, trigger_message)
self._event_type = event_filters['type']
if args.async_:
return operation
response = client.WaitFor(operation, 'Creating', trigger_ref, loading_msg)
trigger_dict = encoding.MessageToPyValue(response)
if types.IsPubsubType(self._event_type):
topic = trigger_dict['transport']['pubsub']['topic']
if args.IsSpecified('transport_topic'):
log.status.Print(
'Publish to Pub/Sub topic [{}] to receive events in {}.'.format(
topic, dest_str
)
)
else:
log.status.Print('Created Pub/Sub topic [{}].'.format(topic))
log.status.Print(
'Publish to this topic to receive events in {}.'.format(dest_str)
)
return response
def Epilog(self, resources_were_displayed):
if resources_were_displayed:
log.warning(
'It may take up to {} minutes for the new trigger to become active.'
.format(triggers.MAX_ACTIVE_DELAY_MINUTES)
)
def GetDestinationLocation(
self, args, trigger_ref, location_arg_name, destination_type
):
# If no Destination region was provided, use the trigger's location instead.
if not args.IsSpecified(location_arg_name):
destination_location = trigger_ref.Parent().Name()
if destination_location == 'global':
raise NoDestinationLocationSpecifiedError(
'The `{}` flag is required when creating a global trigger with a '
'destination {}.'.format(
args.GetFlag(location_arg_name), destination_type
)
)
else:
destination_location = args.GetValue(location_arg_name)
return destination_location

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to delete a trigger."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.eventarc import triggers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.eventarc import flags
_DETAILED_HELP = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
""" \
To delete the trigger ``my-trigger'', run:
$ {command} my-trigger
""",
}
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Delete(base.DeleteCommand):
"""Delete an Eventarc trigger."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
flags.AddTriggerResourceArg(parser, 'The trigger to delete.', required=True)
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Run the delete command."""
client = triggers.TriggersClientV1()
trigger_ref = args.CONCEPTS.trigger.Parse()
operation = client.Delete(trigger_ref)
if args.async_:
return operation
return client.WaitFor(operation, 'Deleting', trigger_ref)

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to describe a trigger."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.eventarc import triggers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.eventarc import flags
from googlecloudsdk.core import log
_DETAILED_HELP = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
""" \
To describe the trigger ``my-trigger'', run:
$ {command} my-trigger
""",
}
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Describe(base.DescribeCommand):
"""Describe an Eventarc trigger."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
flags.AddTriggerResourceArg(
parser, 'The trigger to describe.', required=True)
def Run(self, args):
"""Run the describe command."""
client = triggers.TriggersClientV1()
trigger_ref = args.CONCEPTS.trigger.Parse()
trigger = client.Get(trigger_ref)
event_type = client.GetEventType(trigger)
self._active_time = triggers.TriggerActiveTime(event_type,
trigger.updateTime)
return trigger
def Epilog(self, resources_were_displayed):
if resources_were_displayed and self._active_time:
log.warning(
'The trigger was recently modified and will become active by {}.'
.format(self._active_time))

View File

@@ -0,0 +1,158 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to list all triggers in a project and location."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import re
from googlecloudsdk.api_lib.eventarc import triggers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.eventarc import flags
from googlecloudsdk.command_lib.eventarc import types
_DETAILED_HELP = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
""" \
To list all triggers in location ``us-central1'', run:
$ {command} --location=us-central1
To list all triggers in all locations, run:
$ {command} --location=-
or
$ {command}
""",
}
_FORMAT = """ \
table(
name.scope("triggers"):label=NAME,
eventFilters.type():label=TYPE,
destination():label=DESTINATION,
active_status():label=ACTIVE,
name.scope("locations").segment(0):label=LOCATION
)
"""
_FORMAT_BETA = """ \
table(
name.scope("triggers"):label=NAME,
matchingCriteria.type():label=TYPE,
destination.cloudRunService.service:label=DESTINATION_RUN_SERVICE,
destination.cloudRunService.path:label=DESTINATION_RUN_PATH,
active_status():label=ACTIVE
)
"""
def _ActiveStatus(trigger):
event_filters = trigger.get('eventFilters', trigger.get('matchingCriteria'))
event_type = types.EventFiltersDictToType(event_filters)
active_time = triggers.TriggerActiveTime(event_type, trigger['updateTime'])
return 'By {}'.format(active_time) if active_time else 'Yes'
def _Destination(trigger):
"""Generate a destination string for the trigger.
Based on different destination types, this function returns a destination
string accordingly:
* Cloud Run trigger: "Cloud Run: {cloud run service or job}"
* GKE trigger: "GKE: {gke service}"
* Workflows trigger: "Workflows: {workflow name}"
* Cloud Functions trigger: "Cloud Functions: {cloud function name}"
For unknown destination (e.g. new types of destination and corrupted
destination), this function returns an empty string.
Args:
trigger: eventarc trigger proto in python map format.
Returns:
A string representing the destination for the trigger.
"""
destination = trigger.get('destination')
if destination is None:
return ''
if 'cloudRun' in destination:
dest = destination.get('cloudRun')
# While not explicit in the API, these are effectively oneof.
job = dest.get('job')
if job:
return 'Cloud Run job: {}'.format(job)
service = dest.get('service')
return 'Cloud Run service: {}'.format(service)
elif 'gke' in destination:
dest = destination.get('gke')
return 'GKE: {}'.format(dest.get('service'))
elif 'cloudFunction' in destination:
cloud_function_str_pattern = '^projects/.*/locations/.*/functions/(.*)$'
dest = destination.get('cloudFunction')
match = re.search(cloud_function_str_pattern, dest)
return 'Cloud Functions: {}'.format(match.group(1)) if match else ''
elif 'workflow' in destination:
workflows_str_pattern = '^projects/.*/locations/.*/workflows/(.*)$'
dest = destination.get('workflow')
match = re.search(workflows_str_pattern, dest)
return 'Workflows: {}'.format(match.group(1)) if match else ''
elif 'httpEndpoint' in destination:
dest = destination.get('httpEndpoint')
return 'HTTP endpoint: {}'.format(dest.get('uri'))
else:
# For new types of triggers, return empty string for now.
return ''
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class List(base.ListCommand):
"""List Eventarc triggers."""
detailed_help = _DETAILED_HELP
@staticmethod
def Args(parser):
flags.AddLocationResourceArg(
parser,
'The location for which to list triggers. This should be either '
"``global'' or one of the supported regions.",
required=False,
allow_aggregation=True,
)
flags.AddProjectResourceArg(parser)
parser.display_info.AddFormat(_FORMAT)
parser.display_info.AddUriFunc(triggers.GetTriggerURI)
parser.display_info.AddTransforms({
'active_status': _ActiveStatus,
'destination': _Destination,
'type': types.EventFiltersDictToType,
})
def Run(self, args):
"""Run the list command."""
client = triggers.TriggersClientV1()
args.CONCEPTS.project.Parse()
location_ref = args.CONCEPTS.location.Parse()
return client.List(location_ref, args.limit, args.page_size)

View File

@@ -0,0 +1,196 @@
# -*- coding: utf-8 -*- #
# Copyright 2020 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Command to update a trigger."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.eventarc import triggers
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.command_lib.eventarc import flags
from googlecloudsdk.command_lib.eventarc import types
from googlecloudsdk.command_lib.util.args import labels_util
from googlecloudsdk.core import log
_DETAILED_HELP = {
'DESCRIPTION':
'{description}',
'EXAMPLES':
""" \
To update the trigger ``my-trigger'' by setting its destination Cloud Run service to ``my-service'', run:
$ {command} my-trigger --destination-run-service=my-service
""",
}
@base.ReleaseTracks(base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Update(base.UpdateCommand):
"""Update an Eventarc trigger."""
detailed_help = _DETAILED_HELP
@classmethod
def Args(cls, parser):
flags.AddTriggerResourceArg(parser, 'The trigger to update.', required=True)
flags.AddEventFiltersArg(parser, cls.ReleaseTrack())
flags.AddEventFiltersPathPatternArg(parser, cls.ReleaseTrack())
flags.AddEventDataContentTypeArg(parser, cls.ReleaseTrack())
flags.AddUpdateDestinationArgs(parser, cls.ReleaseTrack())
base.ASYNC_FLAG.AddToParser(parser)
service_account_group = parser.add_mutually_exclusive_group()
flags.AddServiceAccountArg(service_account_group)
flags.AddClearServiceAccountArg(service_account_group)
flags.AddTriggerRetryPolicyArgs(parser)
labels_util.AddUpdateLabelsFlags(parser)
def Run(self, args):
"""Run the update command."""
client = triggers.TriggersClientV1()
trigger_ref = args.CONCEPTS.trigger.Parse()
event_filters = flags.GetEventFiltersArg(args, self.ReleaseTrack())
event_filters_path_pattern = flags.GetEventFiltersPathPatternArg(
args, self.ReleaseTrack())
event_data_content_type = flags.GetEventDataContentTypeArg(
args, self.ReleaseTrack()
)
original_trigger = client.Get(trigger_ref)
labels_update_result = labels_util.Diff.FromUpdateArgs(args).Apply(
client.LabelsValueClass(), original_trigger.labels
)
update_mask = client.BuildUpdateMask(
event_filters=event_filters is not None,
event_filters_path_pattern=event_filters_path_pattern is not None,
event_data_content_type=event_data_content_type is not None,
service_account=args.IsSpecified('service_account')
or args.clear_service_account,
destination_run_service=args.IsSpecified('destination_run_service'),
destination_run_job=args.IsSpecified('destination_run_job'),
destination_run_path=args.IsSpecified('destination_run_path')
or args.clear_destination_run_path,
destination_run_region=args.IsSpecified('destination_run_region'),
destination_gke_namespace=args.IsSpecified('destination_gke_namespace'),
destination_gke_service=args.IsSpecified('destination_gke_service'),
destination_gke_path=args.IsSpecified('destination_gke_path')
or args.clear_destination_gke_path,
destination_workflow=args.IsSpecified('destination_workflow'),
destination_workflow_location=args.IsSpecified(
'destination_workflow_location'
),
destination_function=args.IsSpecified('destination_function'),
destination_function_location=args.IsSpecified(
'destination_function_location'
),
max_retry_attempts=args.IsSpecified('max_retry_attempts'),
labels=labels_update_result.needs_update,
)
# The type can't be updated, so it's safe to use the original trigger's
# type.
# In the async case, this is the only way to get the type.
self._event_type = client.GetEventType(original_trigger)
destination_message = None
if (args.IsSpecified('destination_run_service') or
args.IsSpecified('destination_run_job') or
args.IsSpecified('destination_run_region') or
args.IsSpecified('destination_run_path') or
args.clear_destination_run_path):
destination_message = client.BuildCloudRunDestinationMessage(
args.destination_run_service, args.destination_run_job,
args.destination_run_path, args.destination_run_region)
elif (args.IsSpecified('destination_gke_namespace') or
args.IsSpecified('destination_gke_service') or
args.IsSpecified('destination_gke_path') or
args.clear_destination_gke_path):
destination_message = client.BuildGKEDestinationMessage(
None, None, args.destination_gke_namespace,
args.destination_gke_service, args.destination_gke_path)
elif (args.IsSpecified('destination_workflow') or
args.IsSpecified('destination_workflow_location')):
location = self.GetWorkflowDestinationLocation(args, original_trigger)
workflow = self.GetWorkflowDestination(args, original_trigger)
destination_message = client.BuildWorkflowDestinationMessage(
trigger_ref.Parent().Parent().Name(), workflow, location)
elif (args.IsSpecified('destination_function') or
args.IsSpecified('destination_function_location')):
location = self.GetFunctionDestinationLocation(args, original_trigger)
function = self.GetFunctionDestination(args, original_trigger)
destination_message = client.BuildFunctionDestinationMessage(
trigger_ref.Parent().Parent().Name(), function, location)
trigger_message = client.BuildTriggerMessage(
trigger_ref,
event_filters,
event_filters_path_pattern,
event_data_content_type,
args.service_account,
destination_message,
None,
None,
args.max_retry_attempts,
labels_update_result.GetOrNone(),
)
operation = client.Patch(trigger_ref, trigger_message, update_mask)
if args.async_:
return operation
return client.WaitFor(operation, 'Updating', trigger_ref)
def Epilog(self, resources_were_displayed):
if resources_were_displayed and types.IsAuditLogType(self._event_type):
log.warning(
'It may take up to {} minutes for the update to take full effect.'
.format(triggers.MAX_ACTIVE_DELAY_MINUTES))
def GetWorkflowDestinationLocation(self, args, old_trigger):
if args.IsSpecified('destination_workflow_location'):
return args.destination_workflow_location
if old_trigger.destination.workflow:
return old_trigger.destination.workflow.split('/')[3]
raise exceptions.InvalidArgumentException(
'--destination-workflow',
'The specified trigger is not for a workflow destination.')
def GetWorkflowDestination(self, args, old_trigger):
if args.IsSpecified('destination_workflow'):
return args.destination_workflow
if old_trigger.destination.workflow:
return old_trigger.destination.workflow.split('/')[5]
raise exceptions.InvalidArgumentException(
'--destination-workflow-location',
'The specified trigger is not for a workflow destination.')
def GetFunctionDestinationLocation(self, args, old_trigger):
if args.IsSpecified('destination_function_location'):
return args.destination_function_location
if old_trigger.destination.cloudFunction:
return old_trigger.destination.cloudFunction.split('/')[3]
raise exceptions.InvalidArgumentException(
'--destination-function',
'The specified trigger is not for a function destination.')
def GetFunctionDestination(self, args, old_trigger):
if args.IsSpecified('destination_function'):
return args.destination_function
if old_trigger.destination.cloudFunction:
return old_trigger.destination.cloudFunction.split('/')[5]
raise exceptions.InvalidArgumentException(
'--destination-function-location',
'The specified trigger is not for a function destination.')