def Run(self, args):
        """This is what is called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Raises:
      util.InvalidImageNameError: If the user specified an invalid
      (or non-existent) image name.
    Returns:
      A list of the deleted docker_name.Tag objects
    """
        # IMAGE_NAME: The fully-qualified image name to delete (with a tag).
        # Removes the tag from the image. Ex. gcr.io/google-appengine/java:TAG.

        http_obj = util.Http()
        # collect input/validate
        tags = self._ParseArgs(args.image_names)

        digests = dict()
        with util.WrapExpectedDockerlessErrors():
            for tag in tags:
                try:
                    # Resolve tags to digests. Throws InvalidImageNameError on 404.
                    digests[tag] = util.GetDigestFromName(six.text_type(tag))
                except util.InvalidImageNameError:
                    # We already validated the image string in _ParseArgs, this is a 404
                    raise util.InvalidImageNameError(
                        'Image could not be found: [{}]'.format(
                            six.text_type(tag)))

            if not tags:
                log.warning('No tags found matching image names [%s].',
                            ', '.join(args.image_names))
                return
            for tag, digest in six.iteritems(digests):
                log.status.Print('Tag: [{}]'.format(six.text_type(tag)))
                log.status.Print('- referencing digest: [{}]'.format(
                    six.text_type(digest)))
                log.status.Print('')

            console_io.PromptContinue(
                'This operation will remove the above tags. '
                'Tag removals only delete the tags; '
                'The underlying image layers (referenced by the above digests) will '
                'continue to exist.',
                cancel_on_no=True)

            # delete and collect output
            result = []
            for tag in tags:
                self._DeleteDockerTag(tag, digests, http_obj)
                result.append({'name': six.text_type(tag)})
            return result
    def Run(self, args):
        # pylint: disable=missing-docstring
        def Push(image, dest_names, creds, http_obj, src_name,
                 session_push_type):
            for dest_name in dest_names:
                with session_push_type(dest_name, creds, http_obj) as push:
                    push.upload(image)
                    log.CreatedResource(dest_name)
            log.UpdatedResource(src_name)

        http_obj = util.Http()

        src_name = util.GetDockerImageFromTagOrDigest(args.src_image)

        dest_names = []
        for dest_image in args.dest_image:
            try:
                dest_name = docker_name.Tag(dest_image)
            except docker_name.BadNameException as e:
                raise util.InvalidImageNameError(six.text_type(e))

            if '/' not in dest_name.repository:
                raise exceptions.Error(
                    'Pushing to project root-level images is disabled. '
                    'Please designate an image within a project, '
                    'e.g. gcr.io/project-id/my-image:tag')
            dest_names.append(dest_name)

        console_io.PromptContinue('This will tag {} with:\n{}'.format(
            src_name, '\n'.join(str(dest_name) for dest_name in dest_names)),
                                  default=True,
                                  cancel_on_no=True)
        creds = util.CredentialProvider()
        with util.WrapExpectedDockerlessErrors():
            with docker_image_list.FromRegistry(src_name, creds,
                                                http_obj) as manifest_list:
                if manifest_list.exists():
                    Push(manifest_list, dest_names, creds, http_obj, src_name,
                         v2_2_session.Push)
                    return

            with v2_2_image.FromRegistry(src_name,
                                         creds,
                                         http_obj,
                                         accepted_mimes=docker_http.
                                         SUPPORTED_MANIFEST_MIMES) as v2_2_img:
                if v2_2_img.exists():
                    Push(v2_2_img, dest_names, creds, http_obj, src_name,
                         v2_2_session.Push)
                    return

            with v2_image.FromRegistry(src_name, creds, http_obj) as v2_img:
                Push(v2_img, dest_names, creds, http_obj, src_name,
                     v2_session.Push)
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Raises:
      ArgumentError: If the user provided the flag --show-occurrences-from but
        --show-occurrences=False.
      InvalidImageNameError: If the user specified an invalid image name.
    Returns:
      Some value that we want to have printed later.
    """
        # Verify that --show-occurrences-from is set iff --show-occurrences=True.
        if args.IsSpecified(
                'show_occurrences_from') and not args.show_occurrences:
            raise ArgumentError(
                '--show-occurrences-from may only be set if --show-occurrences=True'
            )

        repository = util.ValidateRepositoryPath(args.image_name)
        http_obj = util.Http()
        with util.WrapExpectedDockerlessErrors(repository):
            with docker_image.FromRegistry(
                    basic_creds=util.CredentialProvider(),
                    name=repository,
                    transport=http_obj) as image:
                manifests = image.manifests()
                # Only consider the top _DEFAULT_SHOW_OCCURRENCES_FROM images
                # to reduce computation time.
                most_recent_resource_urls = None
                occ_filter = filter_util.ContainerAnalysisFilter()
                occ_filter.WithCustomFilter(args.occurrence_filter)
                occ_filter.WithResourcePrefix('https://{}'.format(repository))
                if args.show_occurrences_from:
                    # This block is skipped when the user provided
                    # --show-occurrences-from=unlimited on the CLI.
                    most_recent_resource_urls = [
                        'https://%s@%s' % (args.image_name, k)
                        for k in heapq.nlargest(
                            args.show_occurrences_from,
                            manifests,
                            key=lambda k: manifests[k]['timeCreatedMs'])
                    ]
                    occ_filter.WithResources(most_recent_resource_urls)
                return util.TransformManifests(
                    manifests,
                    repository,
                    show_occurrences=args.show_occurrences,
                    occurrence_filter=occ_filter)
示例#4
0
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Returns:
      Some value that we want to have printed later.

    Raises:
      exceptions.Error: If the repository could not be found, or access was
      denied.
      docker_http.V2DiagnosticException: Any other error occurred while
      accessing GCR.
    """
        repository_arg = args.repository
        self._epilog = None
        if not repository_arg:
            project_id = properties.VALUES.core.project.Get(required=True)
            # Handle domain-scoped projects...
            project_id = project_id.replace(':', '/', 1)
            repository_arg = 'gcr.io/{0}'.format(project_id)
            self._epilog = 'Only listing images in {0}. '.format(
                repository_arg)
            self._epilog += 'Use --repository to list images in other repositories.'

        # Throws if invalid.
        repository = util.ValidateRepositoryPath(repository_arg)

        def _DisplayName(c):
            """Display the fully-qualified name."""
            return '{0}/{1}'.format(repository, c)

        http_obj = util.Http()
        with util.WrapExpectedDockerlessErrors(repository):
            with docker_image.FromRegistry(
                    basic_creds=util.CredentialProvider(),
                    name=repository,
                    transport=http_obj) as r:
                images = [{'name': _DisplayName(c)} for c in r.children()]
                return images
    def Run(self, args):
        """This is what gets called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Raises:
      InvalidImageNameError: If the user specified an invalid image name.
    Returns:
      Some value that we want to have printed later.
    """
        repository = util.ValidateRepositoryPath(args.image_name)
        http_obj = util.Http()
        with util.WrapExpectedDockerlessErrors(repository):
            with docker_image.FromRegistry(
                    basic_creds=util.CredentialProvider(),
                    name=repository,
                    transport=http_obj) as image:
                manifests = image.manifests()
                return util.TransformManifests(manifests, repository)
    def Run(self, args):
        """This is what ts called when the user runs this command.

    Args:
      args: an argparse namespace. All the arguments that were provided to this
        command invocation.

    Raises:
      InvalidImageNameError: If the user specified an invalid image name.
    Returns:
      A list of the deleted docker_name.Tag and docker_name.Digest objects
    """
        # IMAGE_NAME: The fully-qualified image name to delete (with a digest).
        # Deletes the layers. Ex. gcr.io/google-appengine/java(@DIGEST|:TAG).

        http_obj = util.Http()
        with util.WrapExpectedDockerlessErrors():
            # collect input/validate
            digests, explicit_tags = self._ProcessImageNames(args.image_names)

            # Resolve tags to digests.
            for tag in explicit_tags:
                digests.add(util.GetDigestFromName(six.text_type(tag)))

            # Find all the tags that reference digests to be deleted.
            all_tags = set()
            for digest in digests:
                all_tags.update(util.GetDockerTagsForDigest(digest, http_obj))

            # Find all the tags that weren't specified explicitly.
            implicit_tags = all_tags.difference(explicit_tags)

            if implicit_tags and not args.force_delete_tags:
                log.error('Tags:')
                for tag in explicit_tags:
                    log.error('- ' + six.text_type(tag))
                raise exceptions.Error(
                    'This operation will implicitly delete the tags listed above. '
                    'Please manually remove with the `untag` command or re-run with '
                    '--force-delete-tags to confirm.')

            # Print the digests to be deleted.
            if digests:
                log.status.Print('Digests:')
            for digest in digests:
                self._PrintDigest(digest, http_obj)

            # Print the tags to be deleted.
            if explicit_tags:
                log.status.Print('Tags:')
            for tag in explicit_tags:
                log.status.Print('- ' + six.text_type(tag))

            # Prompt the user for consent to delete all the above.
            console_io.PromptContinue(
                'This operation will delete the tags and images identified by the '
                'digests above.',
                default=True,
                cancel_on_no=True)

            # The user has given explicit consent, merge the tags.
            explicit_tags.update(implicit_tags)

            # delete and collect output
            result = []
            for tag in explicit_tags:  # tags must be deleted before digests
                self._DeleteDockerTagOrDigest(tag, http_obj)
                result.append({'name': six.text_type(tag)})
            for digest in digests:
                self._DeleteDockerTagOrDigest(digest, http_obj)
                result.append({'name': six.text_type(digest)})
            return result