def Run(self, args): """Executes when the user runs the describe command.""" 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() 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 Run(self, args): """Executes when user runs the init command.""" if platforms.GetPlatform() == platforms.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') kuberun_events_flags.ValidateAuthenticationFlags(args) conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) namespace_ref = args.CONCEPTS.namespace.Parse() with eventflow_operations.Connect(conn_context) as client: product_type = init_shared.determine_product_type( client, args.authentication) if not client.GetNamespace(namespace_ref): client.CreateNamespace(namespace_ref) if args.authentication == events_constants.AUTH_SECRETS: client.CreateOrReplaceSourcesSecret(namespace_ref, product_type) log.status.Print( 'Initialized namespace [{}] for Cloud Run eventing with ' 'secret {}'.format(namespace_ref.Name(), anthosevents_operations.SOURCES_KEY))
def Run(self, args): """Executes when the user runs the delete command.""" if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') if args.BROKER != _DEFAULT_BROKER_NAME: raise exceptions.UnsupportedArgumentError( 'Only brokers named "default" may be created.') conn_context = connection_context.GetConnectionContext( args, product=serverless_flags.Product.EVENTS) service_account_ref = resources.REGISTRY.Parse( args.service_account, params={'projectsId': '-'}, collection=core_iam_util.SERVICE_ACCOUNTS_COLLECTION) namespace_ref = args.CONCEPTS.namespace.Parse() secret_ref = resources.REGISTRY.Parse( _DATA_PLANE_SECRET_NAME, params={'namespacesId': namespace_ref.Name()}, collection='run.api.v1.namespaces.secrets', api_version='v1') # Validate the service account has the necessary roles roles = iam_util.GetProjectRolesForServiceAccount(service_account_ref) if not (_OWNER_ROLE in roles or _DATA_PLANE_SECRET_MIN_REQUIRED_ROLES.issubset(roles)): missing_roles = _DATA_PLANE_SECRET_MIN_REQUIRED_ROLES - roles raise exceptions.ServiceAccountMissingRequiredPermissions( 'Service account [{}] does not have necessary role(s): {}'. format(service_account_ref.Name(), ', '.join(missing_roles))) with eventflow_operations.Connect(conn_context) as client: if console_io.CanPrompt(): console_io.PromptContinue( message='This will create a new key for the provided ' 'service account.', cancel_on_no=True) _, key_ref = client.CreateOrReplaceServiceAccountSecret( secret_ref, service_account_ref) client.UpdateNamespaceWithLabels(namespace_ref, _INJECTION_LABELS) log.status.Print('Created broker [{}] in namespace [{}] with ' 'key [{}] for service account [{}].'.format( args.BROKER, namespace_ref.Name(), key_ref.Name(), service_account_ref.Name()))
def Run(self, args): """Executes when the user runs the create command.""" if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') if args.BROKER != _DEFAULT_BROKER_NAME: raise exceptions.UnsupportedArgumentError( 'Only brokers named "default" may be created.') conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) if not args.IsSpecified('service_account'): sa_email = iam_util.GetOrCreateEventingServiceAccountWithPrompt() else: sa_email = args.service_account service_account_ref = resources.REGISTRY.Parse( sa_email, params={'projectsId': '-'}, collection=core_iam_util.SERVICE_ACCOUNTS_COLLECTION) namespace_ref = args.CONCEPTS.namespace.Parse() secret_ref = resources.REGISTRY.Parse( _DATA_PLANE_SECRET_NAME, params={'namespacesId': namespace_ref.Name()}, collection='run.api.v1.namespaces.secrets', api_version='v1') with eventflow_operations.Connect(conn_context) as client: iam_util.BindMissingRolesWithPrompt( service_account_ref, _DATA_PLANE_SECRET_MIN_REQUIRED_ROLES) if console_io.CanPrompt(): console_io.PromptContinue( message='This will create a new key for the provided ' 'service account.', cancel_on_no=True) _, key_ref = client.CreateOrReplaceServiceAccountSecret( secret_ref, service_account_ref) client.UpdateNamespaceWithLabels(namespace_ref, _INJECTION_LABELS) log.status.Print('Created broker [{}] in namespace [{}] with ' 'key [{}] for service account [{}].'.format( args.BROKER, namespace_ref.Name(), key_ref.Name(), service_account_ref.Name()))
def Run(self, args): conn_context = connection_context.GetConnectionContext(args) if conn_context.supports_one_platform: raise exceptions.UnsupportedArgumentError( 'Events are only available with Cloud Run for Anthos.') with eventflow_operations.Connect(conn_context) as client: source_crds = client.ListSourceCustomResourceDefinitions() return util.EventTypeFromTypeString(source_crds, args.event_type)
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.') with eventflow_operations.Connect(conn_context) as client: source_crds = client.ListSourceCustomResourceDefinitions() return [crd for crd in source_crds if crd.event_types]
def determine_product_type(client, authentication): """Determine eventing product type inferred by namespaces.""" product_type = _fetch_product_type(client) if (product_type == events_constants.Product.CLOUDRUN and authentication == events_constants.AUTH_WI_GSA): raise exceptions.UnsupportedArgumentError( 'This cluster version does not support using Cloud Run events ' 'with workload identity.') return product_type
def Run(self, args): if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) namespace_ref = args.CONCEPTS.namespace.Parse() with eventflow_operations.Connect(conn_context) as client: brokers = client.ListBrokers(namespace_ref.RelativeName()) return brokers
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 Run(self, args): conn_context = connection_context.GetConnectionContext(args) if conn_context.supports_one_platform: raise exceptions.UnsupportedArgumentError( 'Events are only available with Cloud Run for Anthos.') namespace_ref = args.CONCEPTS.namespace.Parse() with eventflow_operations.Connect(conn_context) as client: self.SetCompleteApiEndpoint(conn_context.endpoint) triggers = client.ListTriggers(namespace_ref) if args.target_service: triggers = [t for t in triggers if t.subscriber == args.target_service] return triggers
def Run(self, args): conn_context = connection_context.GetConnectionContext(args) if conn_context.supports_one_platform: raise exceptions.UnsupportedArgumentError( 'Events are only available with Cloud Run for Anthos.') with eventflow_operations.Connect(conn_context) as client: source_crds = client.ListSourceCustomResourceDefinitions() event_types = [] for crd in source_crds: if not args.category or args.category == crd.source_kind: event_types.extend(crd.event_types) return event_types
def Run(self, args): """Executes when the user runs the delete command.""" if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') project = properties.VALUES.core.project.Get(required=True) conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) with eventflow_operations.Connect(conn_context) as client: cloud_run_obj = client.GetCloudRun() if cloud_run_obj is None: pass elif cloud_run_obj.eventing_enabled: log.status.Print('Eventing already enabled.') else: tracker_stages = stages.EventingStages() # Enable eventing with progress_tracker.StagedProgressTracker( 'Enabling eventing...', tracker_stages, failure_message='Failed to enable eventing' ) as tracker: response = client.UpdateCloudRunWithEventingEnabled() # Wait for Operator to enable eventing client.PollCloudRunResource(tracker) log.status.Print('Enabled eventing successfully.') if client.IsClusterInitialized(): console_io.PromptContinue( message='This cluster has already been initialized.', prompt_string='Would you like to re-run initialization?', cancel_on_no=True) _EnableMissingServices(project) for sa_config in [ _CONTROL_PLANE_SERVICE_ACCOUNT_CONFIG, _BROKER_SERVICE_ACCOUNT_CONFIG, _SOURCES_SERVICE_ACCOUNT_CONFIG ]: _ConfigureServiceAccount(sa_config, client, args) client.MarkClusterInitialized() log.status.Print( _InitializedMessage(self.ReleaseTrack(), conn_context.cluster_name))
def Run(self, args): """Executes when the user runs the describe command.""" conn_context = connection_context.GetConnectionContext(args) if conn_context.supports_one_platform: raise exceptions.UnsupportedArgumentError( 'Events are only available with Cloud Run for Anthos.') trigger_ref = args.CONCEPTS.trigger.Parse() with eventflow_operations.Connect(conn_context) as client: trigger_obj = client.GetTrigger(trigger_ref) if not trigger_obj: raise exceptions.TriggerNotFound('Trigger [{}] not found.'.format( trigger_ref.Name())) return trigger_obj
def Run(self, args): """Executes when the user runs the delete command.""" conn_context = connection_context.GetConnectionContext(args) if conn_context.supports_one_platform: raise exceptions.UnsupportedArgumentError( 'Events are only available with Cloud Run for Anthos.') trigger_ref = args.CONCEPTS.trigger.Parse() console_io.PromptContinue( message='Trigger [{}] will be deleted.'.format(trigger_ref.Name()), throw_if_unattended=True, cancel_on_no=True) with eventflow_operations.Connect(conn_context) as client: client.DeleteTrigger(trigger_ref) log.DeletedResource(trigger_ref.Name(), 'trigger')
def Run(self, args): """Executes when the user runs the delete command.""" if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') project = properties.VALUES.core.project.Get(required=True) conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) _EnableMissingServices(project) if not args.IsSpecified('service_account'): sa_email = iam_util.GetOrCreateEventingServiceAccountWithPrompt() else: sa_email = args.service_account service_account_ref = resources.REGISTRY.Parse( sa_email, params={'projectsId': '-'}, collection=core_iam_util.SERVICE_ACCOUNTS_COLLECTION) secret_ref = resources.REGISTRY.Parse( _CONTROL_PLANE_SECRET_NAME, params={'namespacesId': _CONTROL_PLANE_NAMESPACE}, collection='run.api.v1.namespaces.secrets', api_version='v1') with eventflow_operations.Connect(conn_context) as client: iam_util.BindMissingRolesWithPrompt(service_account_ref, _CONTROL_PLANE_REQUIRED_ROLES) _PromptIfCanPrompt( '\nThis will create a new key for the provided service account.' ) _, key_ref = client.CreateOrReplaceServiceAccountSecret( secret_ref, service_account_ref) command_string = 'gcloud ' if self.ReleaseTrack() != base.ReleaseTrack.GA: command_string += self.ReleaseTrack().prefix + ' ' command_string += 'events brokers create' log.status.Print( 'Initialized cluster [{}] for Cloud Run eventing with ' 'key [{}] for service account [{}]. ' 'Next, create a broker in the namespace(s) you plan to ' 'use via `{}`.'.format(args.CONCEPTS.cluster.Parse().Name(), key_ref.Name(), service_account_ref.Name(), command_string))
def Run(self, args): """Executes when user runs the init command.""" if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) namespace_ref = args.CONCEPTS.namespace.Parse() with eventflow_operations.Connect(conn_context) as client: client.CreateOrReplaceSourcesSecret(namespace_ref) log.status.Print( 'Initialized namespace [{}] for Cloud Run eventing with ' 'secret {}'.format(namespace_ref.Name(), anthosevents_operations.SOURCES_KEY))
def Run(self, args): """Executes when the user runs the init command.""" if platforms.GetPlatform() == platforms.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') project = properties.VALUES.core.project.Get(required=True) conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) with eventflow_operations.Connect(conn_context) as client: operator.install_eventing_via_operator(client, self.ReleaseTrack()) # Eventing has been installed and enabled, but not initialized yet. product_type = init_shared.determine_product_type( client, args.authentication) if client.IsClusterInitialized(product_type): console_io.PromptContinue( message='This cluster has already been initialized.', prompt_string='Would you like to re-run initialization?', cancel_on_no=True) _EnableMissingServices(project) if args.authentication == events_constants.AUTH_SECRETS: # Create secrets for each Google service account and adds to cluster. gsa_emails = init_shared.construct_service_accounts( args, product_type) init_shared.initialize_eventing_secrets( client, gsa_emails, product_type) elif args.authentication == events_constants.AUTH_WI_GSA: # Bind controller and broker GSA to KSA via workload identity. gsa_emails = init_shared.construct_service_accounts( args, product_type) init_shared.initialize_workload_identity_gsa( client, gsa_emails) else: log.status.Print('Skipped initializing cluster.') log.status.Print( _InitializedMessage(self.ReleaseTrack(), conn_context.cluster_name, args.authentication))
def Run(self, args): """Executes when the user runs the describe command.""" if platforms.GetPlatform() == platforms.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) namespace_ref = args.CONCEPTS.namespace.Parse() broker_name = args.BROKER broker_full_name = namespace_ref.RelativeName() + '/brokers/' + broker_name with eventflow_operations.Connect(conn_context) as client: broker_obj = client.GetBroker(broker_full_name) if not broker_obj: raise exceptions.BrokerNotFound( 'Broker [{}] not found.'.format(broker_name)) return broker_obj
def Run(self, args): """Executes when the user runs the create command.""" if platforms.GetPlatform() == platforms.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) namespace_ref = args.CONCEPTS.namespace.Parse() with eventflow_operations.Connect(conn_context) as client: client.CreateBroker(namespace_ref.Name(), args.BROKER) broker_full_name = 'namespaces/{}/brokers/{}'.format( namespace_ref.Name(), args.BROKER) with progress_tracker.StagedProgressTracker( 'Creating Broker...', [progress_tracker.Stage('Creating Broker...')]) as tracker: client.PollBroker(broker_full_name, tracker) log.status.Print('Created broker [{}] in namespace [{}].'.format( args.BROKER, namespace_ref.Name()))
def Run(self, args): """Executes when the user runs the delete command.""" if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) namespace_ref = args.CONCEPTS.namespace.Parse() broker_name = args.BROKER console_io.PromptContinue( message='Broker [{}] will be deleted.'.format(broker_name), throw_if_unattended=True, cancel_on_no=True) conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) with eventflow_operations.Connect(conn_context) as client: client.DeleteBroker(namespace_ref.Name(), broker_name) log.DeletedResource(broker_name, 'broker')
def Run(self, args): """Executes when the user runs the delete command.""" if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'This command is only available with Cloud Run for Anthos.') conn_context = connection_context.GetConnectionContext( args, serverless_flags.Product.EVENTS, self.ReleaseTrack()) service_account_ref = resources.REGISTRY.Parse( args.service_account, params={'projectsId': '-'}, collection=core_iam_util.SERVICE_ACCOUNTS_COLLECTION) secret_ref = resources.REGISTRY.Parse( _CONTROL_PLANE_SECRET_NAME, params={'namespacesId': _CONTROL_PLANE_NAMESPACE}, collection='run.api.v1.namespaces.secrets', api_version='v1') # Validate the service account has the necessary roles roles = iam_util.GetProjectRolesForServiceAccount(service_account_ref) if _OWNER_ROLE in roles: # This role is enough to cover everything we need. Nothing more to check. pass elif _CONTROL_PLANE_SECRET_MIN_REQUIRED_ROLES.issubset(roles): # We have the minimum necessary permissions to continue. # Check if there's additional permissions the user may want to add. missing_optional_roles = _CONTROL_PLANE_SECRET_OPTIONAL_ROLES - roles if missing_optional_roles: optional_roles_msg = '\n'.join([ '- {}: {}'.format(s, ', '.join(r)) for s, r in _CONTROL_PLANE_SECRET_PER_SOURCE_ROLES.items() ]) log.warning( 'The service account has the minimum necessary project ' 'permissions, but certain source kinds may require ' 'additional permissions to use. Consider adding missing ' 'roles to the service account if you plan to ' 'use event types from these source kinds. ' 'Necessary roles per source kind:\n{}\n'.format( optional_roles_msg)) else: # Missing the minimum necessary permissions. missing_roles = _CONTROL_PLANE_SECRET_MIN_REQUIRED_ROLES - roles raise exceptions.ServiceAccountMissingRequiredPermissions( 'Service account [{}] does not have necessary role(s): {}'. format(service_account_ref.Name(), ', '.join(missing_roles))) with eventflow_operations.Connect(conn_context) as client: if console_io.CanPrompt(): console_io.PromptContinue( message='This will create a new key for the provided ' 'service account.', cancel_on_no=True) _, key_ref = client.CreateOrReplaceServiceAccountSecret( secret_ref, service_account_ref) command_string = 'gcloud ' if self.ReleaseTrack() != base.ReleaseTrack.GA: command_string += self.ReleaseTrack().prefix + ' ' command_string += 'events brokers create' log.status.Print( 'Initialized cluster [{}] for Cloud Run eventing with ' 'key [{}] for service account [{}]. ' 'Next, create a broker in the namespace(s) you plan to ' 'use via `{}`.'.format(args.CONCEPTS.cluster.Parse().Name(), key_ref.Name(), service_account_ref.Name(), command_string))
def Filter(self, context, args): if flags.GetPlatform() == flags.PLATFORM_MANAGED: raise exceptions.UnsupportedArgumentError( 'Events are only available with Cloud Run for Anthos.') return context