224 lines
8.5 KiB
Python
224 lines
8.5 KiB
Python
# -*- 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
|