예제 #1
0
    def Run(self, args):
        """Create a domain mapping."""
        # domains.cloudrun.com api group only supports v1alpha1 on clusters.
        conn_context = connection_context.GetConnectionContext(
            args,
            flags.Product.RUN,
            self.ReleaseTrack(),
            version_override=('v1alpha1'
                              if flags.GetPlatform() != flags.PLATFORM_MANAGED
                              else None))
        domain_mapping_ref = args.CONCEPTS.domain.Parse()
        changes = [
            config_changes.SetLaunchStageAnnotationChange(self.ReleaseTrack())
        ]

        # Check if the provided domain has already been verified
        # if mapping to a non-CRoGKE service
        if flags.GetPlatform() == flags.PLATFORM_MANAGED:
            client = global_methods.GetServerlessClientInstance()
            all_domains = global_methods.ListVerifiedDomains(client)
            # If not already verified, explain and error out
            if all(d.id not in domain_mapping_ref.Name() for d in all_domains):
                if not all_domains:
                    domains_text = 'You currently have no verified domains.'
                else:
                    domains = ['* {}'.format(d.id) for d in all_domains]
                    domains_text = ('Currently verified domains:\n{}'.format(
                        '\n'.join(domains)))
                raise exceptions.DomainMappingCreationError(
                    'The provided domain does not appear to be verified '
                    'for the current account so a domain mapping '
                    'cannot be created. Visit [{help}] for more information.'
                    '\n{domains}'.format(help=DOMAIN_MAPPINGS_HELP_DOCS_URL,
                                         domains=domains_text))

        with serverless_operations.Connect(conn_context) as client:
            try:
                mapping = client.CreateDomainMapping(domain_mapping_ref,
                                                     args.service, changes,
                                                     args.force_override)
            except exceptions.DomainMappingAlreadyExistsError as e:
                if console_io.CanPrompt() and console_io.PromptContinue(
                    ('This domain is already being used as a mapping elsewhere. '
                     'The existing mapping can be overriden by passing '
                     '`--force-override` or by continuing at the prompt below.'
                     ),
                        prompt_string='Override the existing mapping'):
                    client.DeleteDomainMapping(domain_mapping_ref)
                    mapping = client.CreateDomainMapping(
                        domain_mapping_ref, args.service, changes, True)
                else:
                    raise e

            for record in mapping.records:
                record.name = record.name or mapping.route_name
            return mapping.records
예제 #2
0
def GetConnectionContext(args,
                         product=flags.Product.RUN,
                         release_track=base.ReleaseTrack.GA,
                         version_override=None):
    """Gets the regional, kubeconfig, or GKE connection context.

  Args:
    args: Namespace, the args namespace.
    product: Which product is requesting connection context.
    release_track: Release track of the command being run.
    version_override: If specified, the given api version will be used no matter
      the other parameters.

  Raises:
    ArgumentError if region or cluster is not specified.

  Returns:
    A GKE or regional ConnectionInfo object.
  """
    if flags.GetPlatform() == flags.PLATFORM_KUBERNETES:
        kubeconfig = flags.GetKubeconfig(args)
        api_name = _GetApiName(product, release_track, is_cluster=True)
        api_version = _GetApiVersion(product,
                                     release_track,
                                     is_cluster=True,
                                     version_override=version_override)
        return _KubeconfigConnectionContext(kubeconfig, api_name, api_version,
                                            args.context)

    if flags.GetPlatform() == flags.PLATFORM_GKE:
        cluster_ref = args.CONCEPTS.cluster.Parse()
        if not cluster_ref:
            raise flags.ArgumentError(
                'You must specify a cluster in a given location. '
                'Either use the `--cluster` and `--cluster-location` flags '
                'or set the run/cluster and run/cluster_location properties.')
        api_name = _GetApiName(product, release_track, is_cluster=True)
        api_version = _GetApiVersion(product,
                                     release_track,
                                     is_cluster=True,
                                     version_override=version_override)
        return _GKEConnectionContext(cluster_ref, api_name, api_version)

    if flags.GetPlatform() == flags.PLATFORM_MANAGED:
        region = flags.GetRegion(args, prompt=True)
        if not region:
            raise flags.ArgumentError(
                'You must specify a region. Either use the `--region` flag '
                'or set the run/region property.')
        api_name = _GetApiName(product, release_track)
        api_version = _GetApiVersion(product,
                                     release_track,
                                     version_override=version_override)
        return _RegionalConnectionContext(region, api_name, api_version)
예제 #3
0
 def _Call(self, parsed_args):
     if (flags.GetPlatform() == flags.PLATFORM_GKE
             or flags.GetPlatform() == flags.PLATFORM_KUBERNETES):
         return 'default'
     elif not (getattr(parsed_args, 'project', None)
               or properties.VALUES.core.project.Get()):
         # HACK: Compensate for how "namespace" is actually "project" in Cloud Run
         # by providing an error message explicitly early here.
         raise flags.ArgumentError(
             'The [project] resource is not properly specified. '
             'Please specify the argument [--project] on the command line or '
             'set the property [core/project].')
     return None
예제 #4
0
    def _Prompt(self, parsed_args):
        """Fallthrough to reading the cluster location from an interactive prompt.

    Only prompt for cluster location if the user-specified platform is GKE
    and if cluster name is already defined.

    Args:
      parsed_args: Namespace, the args namespace.

    Returns:
      A cluster location string
    """
        cluster_name = (getattr(parsed_args, 'cluster', None)
                        or properties.VALUES.run.cluster.Get())
        if flags.GetPlatform() == flags.PLATFORM_GKE and cluster_name:
            clusters = [
                c for c in global_methods.ListClusters()
                if c.name == cluster_name
            ]
            if not clusters:
                raise exceptions.ConfigurationError(
                    'No cluster locations found for cluster [{}]. '
                    'Ensure your clusters have Cloud Run enabled.'.format(
                        cluster_name))
            cluster_locations = [c.zone for c in clusters]
            idx = console_io.PromptChoice(
                cluster_locations,
                message='GKE cluster location for [{}]:'.format(cluster_name),
                cancel_option=True)
            location = cluster_locations[idx]
            log.status.Print(
                'To make this the default cluster location, run '
                '`gcloud config set run/cluster_location {}`.\n'.format(
                    location))
            return location
예제 #5
0
  def Run(self, args):
    """Update the traffic split for the service.

    Args:
      args: Args!

    Returns:
      List of traffic.TrafficTargetStatus instances reflecting the change.
    """
    # TODO(b/143898356) Begin code that should be in Args
    resource_printer.RegisterFormatter(
        traffic_printer.TRAFFIC_PRINTER_FORMAT,
        traffic_printer.TrafficPrinter)
    args.GetDisplayInfo().AddFormat('traffic')
    # End code that should be in Args

    conn_context = connection_context.GetConnectionContext(
        args, flags.Product.RUN, self.ReleaseTrack())
    service_ref = flags.GetService(args)

    changes = flags.GetConfigurationChanges(args)
    if not changes:
      raise exceptions.NoConfigurationChangeError(
          'No traffic configuration change requested.')

    is_managed = flags.GetPlatform() == flags.PLATFORM_MANAGED
    with serverless_operations.Connect(conn_context) as client:
      deployment_stages = stages.UpdateTrafficStages()
      try:
        with progress_tracker.StagedProgressTracker(
            'Updating traffic...',
            deployment_stages,
            failure_message='Updating traffic failed',
            suppress_output=args.async_) as tracker:
          client.UpdateTraffic(service_ref, changes, tracker, args.async_)
      except:
        serv = client.GetService(service_ref)
        if serv:
          resources = traffic_pair.GetTrafficTargetPairs(
              serv.spec_traffic,
              serv.status_traffic,
              is_managed,
              serv.status.latestReadyRevisionName,
              serv.status.url)
          display.Displayer(
              self, args, resources,
              display_info=args.GetDisplayInfo()).Display()
        raise

    if args.async_:
      pretty_print.Success('Updating traffic asynchronously.')
    else:
      serv = client.GetService(service_ref)
      resources = traffic_pair.GetTrafficTargetPairs(
          serv.spec_traffic,
          serv.status_traffic,
          is_managed,
          serv.status.latestReadyRevisionName,
          serv.status.url)
      return resources
예제 #6
0
    def Run(self, args):
        """Create a domain mapping."""
        conn_context = connection_context.GetConnectionContext(
            args, product=flags.Product.RUN)
        domain_mapping_ref = args.CONCEPTS.domain.Parse()

        # Check if the provided domain has already been verified
        # if mapping to a non-CRoGKE service
        if flags.GetPlatform() == flags.PLATFORM_MANAGED:
            client = global_methods.GetServerlessClientInstance()
            all_domains = global_methods.ListVerifiedDomains(
                client, flags.GetRegion(args))
            # If not already verified, explain and error out
            if all(d.id not in domain_mapping_ref.Name() for d in all_domains):
                if not all_domains:
                    domains_text = 'You currently have no verified domains.'
                else:
                    domains = ['* {}'.format(d.id) for d in all_domains]
                    domains_text = ('Currently verified domains:\n{}'.format(
                        '\n'.join(domains)))
                raise exceptions.DomainMappingCreationError(
                    'The provided domain does not appear to be verified '
                    'for the current account so a domain mapping '
                    'cannot be created. Visit [{help}] for more information.'
                    '\n{domains}'.format(help=DOMAIN_MAPPINGS_HELP_DOCS_URL,
                                         domains=domains_text))

        with serverless_operations.Connect(conn_context) as client:
            mapping = client.CreateDomainMapping(domain_mapping_ref,
                                                 args.service,
                                                 args.force_override)
            for record in mapping.records:
                record.name = record.name or mapping.route_name
            return mapping.records
예제 #7
0
 def Run(self, args):
     """List available services."""
     is_managed = flags.GetPlatform() == flags.PLATFORM_MANAGED
     if is_managed and not args.IsSpecified('region'):
         self._SetFormat(args, show_region=True)
         client = global_methods.GetServerlessClientInstance()
         self.SetPartialApiEndpoint(client.url)
         args.CONCEPTS.namespace.Parse()  # Error if no proj.
         # Don't consider region property here, we'll default to all regions
         return commands.SortByName(global_methods.ListServices(client))
     else:
         conn_context = connection_context.GetConnectionContext(
             args, product=flags.Product.RUN)
         self._SetFormat(args,
                         show_region=is_managed,
                         show_namespace=(not is_managed))
         namespace_ref = args.CONCEPTS.namespace.Parse()
         with serverless_operations.Connect(conn_context) as client:
             self.SetCompleteApiEndpoint(conn_context.endpoint)
             if not is_managed:
                 location_msg = ' in [{}]'.format(
                     conn_context.cluster_location)
                 log.status.Print('For cluster [{cluster}]{zone}:'.format(
                     cluster=conn_context.cluster_name,
                     zone=location_msg
                     if conn_context.cluster_location else ''))
             return commands.SortByName(client.ListServices(namespace_ref))
예제 #8
0
  def Run(self, args):
    """Executes when the user runs the delete command."""
    conn_context = connection_context.GetConnectionContext(
        args, serverless_flags.Product.EVENTS, self.ReleaseTrack())

    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:
      # TODO(b/147308604): Don't delete source when Odin supports ownerRefs
      if serverless_flags.GetPlatform() == serverless_flags.PLATFORM_MANAGED:
        trigger_obj = client.GetTrigger(trigger_ref)
        if trigger_obj is not None:
          source_crds = client.ListSourceCustomResourceDefinitions()
          source_ref, source_crd = util.GetSourceRefAndCrdForTrigger(
              trigger_obj, source_crds)
          if source_ref and source_crd:
            # Delete the source before the trigger because we need the trigger
            # to exist to be able to find the source. Otherwise, we could end up
            # losing a reference to the source if trigger deletion succeeds but
            # source deletion fails.
            try:
              client.DeleteSource(source_ref, source_crd)
            except exceptions.SourceNotFound:
              # Source could have been deleted but trigger deletion failed
              # and this command was re-run, which is fine.
              pass
      client.DeleteTrigger(trigger_ref)

    log.DeletedResource(trigger_ref.Name(), 'trigger')
예제 #9
0
파일: deploy.py 프로젝트: OzLustig/MyDay
def GetAllowUnauth(args, operations, service_ref, service_exists):
    """Returns allow_unauth value for a service change.

  Args:
    args: argparse.Namespace, Command line arguments
    operations: serverless_operations.ServerlessOperations, Serverless client.
    service_ref: protorpc.messages.Message, A resource reference object
      for the service See googlecloudsdk.core.resources.Registry.ParseResourceId
      for details.
    service_exists: True if the service being changed already exists.
  Returns:
    allow_unauth value where
     True means to enable unauthenticated acess for the service.
     False means to disable unauthenticated access for the service.
     None means to retain the current value for the service.
  """
    allow_unauth = None
    if flags.GetPlatform() == flags.PLATFORM_MANAGED:
        allow_unauth = flags.GetAllowUnauthenticated(args, operations,
                                                     service_ref,
                                                     not service_exists)
        # Avoid failure removing a policy binding for a service that
        # doesn't exist.
        if not service_exists and not allow_unauth:
            allow_unauth = None
    return allow_unauth
예제 #10
0
  def _Prompt(self, parsed_args):
    """Fallthrough to reading the cluster name from an interactive prompt.

    Only prompt for cluster name if the user-specified platform is GKE.

    Args:
      parsed_args: Namespace, the args namespace.

    Returns:
      A cluster name string
    """
    if flags.GetPlatform() == flags.PLATFORM_GKE:
      cluster_location = (
          getattr(parsed_args, 'cluster_location', None) or
          properties.VALUES.run.cluster_location.Get())
      cluster_location_msg = ' in [{}]'.format(
          cluster_location) if cluster_location else ''

      clusters = global_methods.ListClusters(cluster_location)
      if not clusters:
        raise exceptions.ConfigurationError(
            'No compatible clusters found{}. '
            'Ensure your cluster has Cloud Run enabled.'.format(
                cluster_location_msg))

      def _GetClusterDescription(cluster):
        """Description of cluster for prompt."""
        if cluster_location:
          return cluster.name
        return '{} in {}'.format(cluster.name, cluster.zone)

      cluster_descs = [_GetClusterDescription(c) for c in clusters]

      idx = console_io.PromptChoice(
          cluster_descs,
          message='GKE cluster{}:'.format(cluster_location_msg),
          cancel_option=True)
      cluster = clusters[idx]

      if cluster_location:
        cluster_result = cluster.name
        location_help_text = ''
      else:
        cluster_ref = flags.GetClusterRef(cluster)
        cluster_result = cluster_ref.SelfLink()
        location_help_text = (
            ' && gcloud config set run/cluster_location {}'.format(
                cluster.zone))
      log.status.Print(
          'To make this the default cluster, run '
          '`gcloud config set run/cluster {cluster}'
          '{location}`.\n'.format(
              cluster=cluster.name,
              location=location_help_text))
      return cluster_result
예제 #11
0
  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
예제 #12
0
def GetConnectionContext(args, product=Product.RUN):
    """Gets the regional, kubeconfig, or GKE connection context.

  Args:
    args: Namespace, the args namespace.
    product: Which product is requesting connection context.

  Raises:
    ArgumentError if region or cluster is not specified.

  Returns:
    A GKE or regional ConnectionInfo object.
  """
    if flags.GetPlatform() == flags.PLATFORM_KUBERNETES:
        kubeconfig = flags.GetKubeconfig(args)
        return _KubeconfigConnectionContext(kubeconfig, _CLUSTER_API_VERSION,
                                            args.context)

    if flags.GetPlatform() == flags.PLATFORM_GKE:
        cluster_ref = args.CONCEPTS.cluster.Parse()
        if not cluster_ref:
            raise flags.ArgumentError(
                'You must specify a cluster in a given location. '
                'Either use the `--cluster` and `--cluster-location` flags '
                'or set the run/cluster and run/cluster_location properties.')
        return _GKEConnectionContext(cluster_ref, _CLUSTER_API_VERSION)

    if flags.GetPlatform() == flags.PLATFORM_MANAGED:
        region = flags.GetRegion(args, prompt=True)
        if not region:
            raise flags.ArgumentError(
                'You must specify a region. Either use the `--region` flag '
                'or set the run/region property.')
        if product == Product.RUN:
            version = global_methods.SERVERLESS_API_VERSION
        elif product == Product.EVENTS:
            version = _EVENTS_API_VERSION
        else:
            raise ValueError('Unrecognized product: ' + six.u(product))
        return _RegionalConnectionContext(region, version)
예제 #13
0
    def Run(self, args):
        """Update the traffic split for the service.

    Args:
      args: Args!

    Returns:
      List of traffic.TrafficTargetStatus instances reflecting the change.
    """
        conn_context = connection_context.GetConnectionContext(
            args, product=connection_context.Product.RUN)
        service_ref = flags.GetService(args)

        changes = flags.GetConfigurationChanges(args)
        if not changes:
            raise exceptions.NoConfigurationChangeError(
                'No traffic configuration change requested.')

        self._SetFormat(args)

        is_managed = flags.GetPlatform() == flags.PLATFORM_MANAGED
        with serverless_operations.Connect(conn_context) as client:
            deployment_stages = stages.UpdateTrafficStages()
            try:
                with progress_tracker.StagedProgressTracker(
                        'Updating traffic...',
                        deployment_stages,
                        failure_message='Updating traffic failed',
                        suppress_output=args.async_) as tracker:
                    client.UpdateTraffic(service_ref, changes, tracker,
                                         args.async_)
            except:
                serv = client.GetService(service_ref)
                if serv:
                    resources = traffic.GetTrafficTargetPairs(
                        serv.spec.traffic, serv.status.traffic, is_managed,
                        serv.status.latestReadyRevisionName)
                    display.Displayer(
                        self,
                        args,
                        resources,
                        display_info=args.GetDisplayInfo()).Display()
                raise

        if args.async_:
            pretty_print.Success('Updating traffic asynchronously.')
        else:
            serv = client.GetService(service_ref)
            resources = traffic.GetTrafficTargetPairs(
                serv.spec.traffic, serv.status.traffic, is_managed,
                serv.status.latestReadyRevisionName)
            return resources
예제 #14
0
    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))
예제 #15
0
 def Run(self, args):
     """List available domain mappings."""
     # domains.cloudrun.com api group only supports v1alpha1 on clusters.
     conn_context = connection_context.GetConnectionContext(
         args,
         flags.Product.RUN,
         self.ReleaseTrack(),
         version_override=('v1alpha1'
                           if flags.GetPlatform() != flags.PLATFORM_MANAGED
                           else None))
     namespace_ref = args.CONCEPTS.namespace.Parse()
     with serverless_operations.Connect(conn_context) as client:
         self.SetCompleteApiEndpoint(conn_context.endpoint)
         return commands.SortByName(
             client.ListDomainMappings(namespace_ref))
예제 #16
0
 def Run(self, args):
   """List available revisions."""
   service_name = args.service
   conn_context = connection_context.GetConnectionContext(
       args, product=flags.Product.RUN)
   namespace_ref = args.CONCEPTS.namespace.Parse()
   with serverless_operations.Connect(conn_context) as client:
     self.SetCompleteApiEndpoint(conn_context.endpoint)
     if flags.GetPlatform() != flags.PLATFORM_MANAGED:
       location_msg = ' in [{}]'.format(conn_context.cluster_location)
       log.status.Print('For cluster [{cluster}]{zone}:'.format(
           cluster=conn_context.cluster_name,
           zone=location_msg if conn_context.cluster_location else ''))
     for rev in client.ListRevisions(namespace_ref, service_name,
                                     args.limit, args.page_size):
       yield rev
예제 #17
0
 def Run(self, args):
     """Delete domain mappings."""
     # domains.cloudrun.com api group only supports v1alpha1 on clusters.
     conn_context = connection_context.GetConnectionContext(
         args,
         flags.Product.RUN,
         self.ReleaseTrack(),
         version_override=('v1alpha1'
                           if flags.GetPlatform() != flags.PLATFORM_MANAGED
                           else None))
     domain_mapping_ref = args.CONCEPTS.domain.Parse()
     with serverless_operations.Connect(conn_context) as client:
         client.DeleteDomainMapping(domain_mapping_ref)
         msg = """Mappings to [{domain}] now have been deleted.""".format(
             domain=domain_mapping_ref.domainmappingsId)
         pretty_print.Success(msg)
예제 #18
0
    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()))
예제 #19
0
    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))
예제 #20
0
 def _GetIngress(self, record):
     """Gets the ingress traffic allowed to call the service."""
     if flags.GetPlatform() == flags.PLATFORM_MANAGED:
         spec_ingress = record.annotations.get(service.INGRESS_ANNOTATION)
         status_ingress = record.annotations.get(
             service.INGRESS_STATUS_ANNOTATION)
         if spec_ingress == status_ingress:
             return spec_ingress
         else:
             spec_ingress = spec_ingress or _INGRESS_UNSPECIFIED
             status_ingress = status_ingress or _INGRESS_UNSPECIFIED
             return '{} (currently {})'.format(spec_ingress, status_ingress)
     elif (record.labels.get(
             service.ENDPOINT_VISIBILITY) == service.CLUSTER_LOCAL):
         return service.INGRESS_INTERNAL
     else:
         return service.INGRESS_ALL
예제 #21
0
    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()))
예제 #22
0
 def Run(self, args):
     """Describe a domain mapping."""
     # domains.cloudrun.com api group only supports v1alpha1 on clusters.
     conn_context = connection_context.GetConnectionContext(
         args,
         flags.Product.RUN,
         self.ReleaseTrack(),
         version_override=('v1alpha1'
                           if flags.GetPlatform() != flags.PLATFORM_MANAGED
                           else None))
     domain_mapping_ref = args.CONCEPTS.domain.Parse()
     with serverless_operations.Connect(conn_context) as client:
         domain_mapping = client.GetDomainMapping(domain_mapping_ref)
         if not domain_mapping:
             raise flags.ArgumentError(
                 'Cannot find domain mapping for domain name [{}]'.format(
                     domain_mapping_ref.domainmappingsId))
         return domain_mapping
예제 #23
0
    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))
예제 #24
0
 def Run(self, args):
     """List available configurations."""
     is_managed = flags.GetPlatform() == flags.PLATFORM_MANAGED
     conn_context = connection_context.GetConnectionContext(
         args, flags.Product.RUN, self.ReleaseTrack())
     self._SetFormat(args,
                     show_region=is_managed,
                     show_namespace=(not is_managed))
     namespace_ref = args.CONCEPTS.namespace.Parse()
     with serverless_operations.Connect(conn_context) as client:
         self.SetCompleteApiEndpoint(conn_context.endpoint)
         if not is_managed:
             zone_label = ' in zone [{}]'.format(
                 conn_context.cluster_location)
             log.status.Print('For cluster [{cluster}]{zone}:'.format(
                 cluster=conn_context.cluster_name,
                 zone=zone_label if conn_context.cluster_location else ''))
         return commands.SortByName(
             client.ListConfigurations(namespace_ref))
예제 #25
0
    def Run(self, args):
        """Executes when the user runs the describe 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
        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
예제 #26
0
  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.')

    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()))
예제 #27
0
    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')
예제 #28
0
 def _CheckPlatform(self):
     if flags.GetPlatform() == flags.PLATFORM_MANAGED:
         raise exceptions.PlatformError(
             'This command group is in beta for fully managed Cloud Run; '
             'use `gcloud beta run domain-mappings`.')
예제 #29
0
    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))
예제 #30
0
    def Run(self, args):
        """Create or Update service from YAML."""
        conn_context = connection_context.GetConnectionContext(
            args, product=flags.Product.RUN)

        with serverless_operations.Connect(conn_context) as client:
            new_service = service.Service(
                messages_util.DictToMessageWithErrorCheck(
                    args.FILE, client.messages_module.Service),
                client.messages_module)

            # If managed, namespace must match project (or will default to project if
            # not specified).
            # If not managed, namespace simply must not conflict if specified in
            # multiple places (or will default to "default" if not specified).
            namespace = args.CONCEPTS.namespace.Parse().Name(
            )  # From flag or default
            if new_service.metadata.namespace is not None:
                if (args.IsSpecified('namespace')
                        and namespace != new_service.metadata.namespace):
                    raise exceptions.ConfigurationError(
                        'Namespace specified in file does not match passed flag.'
                    )
                namespace = new_service.metadata.namespace
                if flags.GetPlatform() == flags.PLATFORM_MANAGED:
                    project = properties.VALUES.core.project.Get()
                    project_number = projects_util.GetProjectNumber(project)
                    if namespace != project and namespace != str(
                            project_number):
                        raise exceptions.ConfigurationError(
                            'Namespace must be project ID [{}] or quoted number [{}] for '
                            'Cloud Run (fully managed).'.format(
                                project, project_number))
            new_service.metadata.namespace = namespace

            changes = [config_changes.ReplaceServiceChange(new_service)]
            service_ref = resources.REGISTRY.Parse(
                new_service.metadata.name,
                params={'namespacesId': new_service.metadata.namespace},
                collection='run.namespaces.services')
            original_service = client.GetService(service_ref)

            pretty_print.Info(
                deploy.GetStartDeployMessage(conn_context, service_ref))

            deployment_stages = stages.ServiceStages()
            header = ('Deploying...'
                      if original_service else 'Deploying new service...')
            with progress_tracker.StagedProgressTracker(
                    header,
                    deployment_stages,
                    failure_message='Deployment failed',
                    suppress_output=args.async_) as tracker:
                client.ReleaseService(service_ref,
                                      changes,
                                      tracker,
                                      asyn=args.async_,
                                      allow_unauthenticated=None,
                                      for_replace=True)
            if args.async_:
                pretty_print.Success(
                    'Service [{{bold}}{serv}{{reset}}] is deploying '
                    'asynchronously.'.format(serv=service_ref.servicesId))
            else:
                pretty_print.Success(
                    deploy.GetSuccessMessageForSynchronousDeploy(
                        client, service_ref))