def Run(self, args): """Executes when the user runs the describe command.""" conn_context = connection_context.GetConnectionContext( args, product=connection_context.Product.EVENTS) trigger_ref = args.CONCEPTS.trigger.Parse() with eventflow_operations.Connect(conn_context) as client: trigger_obj = client.GetTrigger(trigger_ref) source_obj = None if trigger_obj is not None: source_crds = client.ListSourceCustomResourceDefinitions() source_obj_ref = trigger_obj.dependency source_crd = next((s for s in source_crds if s.source_kind == source_obj_ref.kind), None) if source_crd is not None: source_ref = util.GetSourceRef(source_obj_ref.name, source_obj_ref.namespace, source_crd) source_obj = client.GetSource(source_ref, source_crd) if not trigger_obj: raise exceptions.TriggerNotFound('Trigger [{}] not found.'.format( trigger_ref.Name())) if not source_obj: log.warning('No matching event source for trigger [{}].'.format( trigger_ref.Name())) return SerializedTriggerAndSource( trigger_obj.MakeSerializable(), source_obj.MakeSerializable() if source_obj else None)
def CreateTriggerAndSource(self, trigger_obj, trigger_ref, namespace_ref, source_obj, event_type, parameters, broker, target_service, tracker): """Create a linked trigger and source pair. Trigger and source are linked via a dependency annotation on the trigger as well as the opaque knsourcetrigger field in the trigger filter and the source override. If the passed trigger_obj is not None, then a new trigger is not created, only a source. Args: trigger_obj: trigger.Trigger, the existing trigger or None if no trigger already exists. trigger_ref: googlecloudsdk.core.resources.Resource, trigger resource. namespace_ref: googlecloudsdk.core.resources.Resource, namespace resource. source_obj: source.Source. The source object being created. event_type: custom_resource_definition.EventTypeDefinition, the event type the source will filter by. parameters: dict, additional parameters to set on the source spec. broker: str, name of the broker to act as a sink for the source. target_service: str, name of the Cloud Run service to subscribe to the trigger. tracker: progress_tracker.StagedProgressTracker to update as the trigger is created and becomes ready. """ # Create trigger if it doesn't already exist if trigger_obj is None: trigger_obj = self.CreateTrigger(trigger_ref, source_obj, event_type, target_service, broker) # Create source self.CreateSource(source_obj, event_type.crd, trigger_obj, namespace_ref, broker, parameters) # Wait for source to be Ready == True source_ref = util.GetSourceRef(source_obj.name, source_obj.namespace, event_type.crd) source_getter = functools.partial(self.GetSource, source_ref, event_type.crd) poller = UnfailingConditionPoller(source_getter, tracker, stages.TriggerSourceDependencies()) util.WaitForCondition(poller, exceptions.SourceCreationError) # Manually complete the stage indicating source readiness because we can't # track a terminal (Ready) condition in the ConditionPoller. tracker.CompleteStage(stages.SOURCE_READY) # Wait for trigger to be Ready == True trigger_getter = functools.partial(self.GetTrigger, trigger_ref) poller = UnfailingConditionPoller(trigger_getter, tracker, stages.TriggerSourceDependencies()) util.WaitForCondition(poller, exceptions.TriggerCreationError)
def Run(self, args): conn_context = connection_context.GetConnectionContext( args, product=connection_context.Product.EVENTS) if conn_context.supports_one_platform: raise exceptions.UnsupportedArgumentError( 'Events are only available with Cloud Run for Anthos.') trigger_ref = args.CONCEPTS.trigger.Parse() namespace_ref = trigger_ref.Parent() with eventflow_operations.Connect(conn_context) as client: source_crds = client.ListSourceCustomResourceDefinitions() event_type = util.EventTypeFromTypeString(source_crds, args.type) source_obj = source.Source.New(client.client, namespace_ref.Name(), event_type.crd.source_kind, event_type.crd.source_api_category) source_obj.name = _SOURCE_NAME_PATTERN.format( trigger=trigger_ref.Name()) trigger_obj = client.GetTrigger(trigger_ref) if trigger_obj is not None: # If trigger already exists, validate it has the attributes we're trying # to set right now. try: util.ValidateTrigger(trigger_obj, source_obj, event_type) except AssertionError: raise exceptions.TriggerCreationError( 'Trigger [{}] already exists with attributes not ' 'matching this event type.'.format(trigger_obj.name)) # If the trigger has the right attributes, check if there's already # a source that matches the attributes as well. source_ref = util.GetSourceRef( source_obj.name, source_obj.namespace, event_type.crd) if client.GetSource(source_ref, event_type.crd) is not None: raise exceptions.TriggerCreationError( 'Trigger [{}] already exists.'.format(trigger_obj.name)) parameters = events_flags.GetAndValidateParameters(args, event_type) # Create the trigger and source with progress_tracker.StagedProgressTracker( 'Initializing trigger...', stages.TriggerSourceStages(), failure_message='Trigger creation failed') as tracker: client.CreateTriggerAndSource( trigger_obj, trigger_ref, namespace_ref, source_obj, event_type, parameters, args.broker, args.target_service, tracker )
def PollSource(self, source_obj, event_type, tracker): """Wait for source to be Ready == True.""" source_ref = util.GetSourceRef(source_obj.name, source_obj.namespace, event_type.crd, True) source_getter = functools.partial(self.GetSource, source_ref, event_type.crd) poller = SourceConditionPoller(source_getter, tracker, stages.TriggerSourceDependencies()) util.WaitForCondition(poller, exceptions.SourceCreationError) # Manually complete the stage indicating source readiness because we can't # track the Ready condition in the ConditionPoller. tracker.CompleteStage(stages.SOURCE_READY)
def PollSource(self, source_obj, event_type_obj, tracker): """Wait for source to be Ready == True.""" source_ref = util.GetSourceRef(source_obj.name, source_obj.namespace, event_type_obj.crd, True) source_getter = functools.partial(self.GetSource, source_ref, event_type_obj.crd) # b/179156386 Increase grace period from default of 15 to 45 seconds for # sources, because asia-southeast1 and asia-east1's sources are unable to # resolve within the default grace period. sources_grace_period = datetime.timedelta(seconds=45) poller = SourceConditionPoller( source_getter, tracker, dependencies=stages.TriggerSourceDependencies(), grace_period=sources_grace_period) util.WaitForCondition(poller, exceptions.SourceCreationError) # Manually complete the stage indicating source readiness because we can't # track the Ready condition in the ConditionPoller. tracker.CompleteStage(stages.SOURCE_READY)
def Run(self, args): conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) trigger_ref = args.CONCEPTS.trigger.Parse() namespace_ref = trigger_ref.Parent() with eventflow_operations.Connect(conn_context) as client: if client.IsCluster(): trigger_ref = resources.REGISTRY.Parse( trigger_ref.RelativeName(), collection=util.ANTHOS_TRIGGER_COLLECTION_NAME, api_version=client.api_version) namespace_ref = trigger_ref.Parent() if args.custom_type: event_type = args.type source_obj = None tracker_stages = stages.TriggerStages() else: source_crds = client.ListSourceCustomResourceDefinitions() event_type = util.EventTypeFromTypeString( source_crds, args.type, args.source) source_obj = source.Source.New( client.client, namespace_ref.Name(), event_type.crd.source_kind, event_type.crd.source_api_category) source_obj.name = _SOURCE_NAME_PATTERN.format( trigger=trigger_ref.Name()) parameters = flags.GetAndValidateParameters(args, event_type) tracker_stages = stages.TriggerAndSourceStages() trigger_obj = client.GetTrigger(trigger_ref) if trigger_obj is not None: if args.custom_type: # If custom type, no need to check idempotency since there's only # a trigger to worry about. raise exceptions.TriggerCreationError( 'Trigger [{}] already exists.'.format( trigger_obj.name)) else: # If trigger already exists, validate it has the attributes we're # trying to set right now to see if this is a case of idempotency. try: util.ValidateTrigger(trigger_obj, source_obj, event_type) except AssertionError: raise exceptions.TriggerCreationError( 'Trigger [{}] already exists with attributes not ' 'matching this event type.'.format( trigger_obj.name)) # If the trigger has the right attributes, check if there's already # a source that matches the attributes as well. source_ref = util.GetSourceRef(source_obj.name, source_obj.namespace, event_type.crd, client.IsCluster()) if client.GetSource(source_ref, event_type.crd) is not None: raise exceptions.TriggerCreationError( 'Trigger [{}] already exists.'.format( trigger_obj.name)) # Create the trigger and source with progress_tracker.StagedProgressTracker( 'Initializing trigger...', tracker_stages, failure_message='Trigger creation failed') as tracker: if trigger_obj is None: trigger_obj = client.CreateTrigger( trigger_ref, source_obj, event_type if args.custom_type else event_type.type, args.trigger_filters, args.target_service, args.broker) if not args.custom_type: client.CreateSource(source_obj, event_type.crd, trigger_obj, namespace_ref, args.broker, parameters) client.PollSource(source_obj, event_type, tracker) client.PollTrigger(trigger_ref, tracker)