Exemplo n.º 1
0
def _ValidateAndGetDockerVersion(version_or_tag):
    """Validates a version_or_tag and returns the validated DockerVersion object.

  Args:
    version_or_tag: a docker version or a docker tag.

  Returns:
    a DockerVersion object.

  Raises:
    ar_exceptions.InvalidInputValueError if version_or_tag is not valid.
  """
    try:
        if isinstance(version_or_tag, DockerVersion):
            # We have all the information about the docker digest.
            # Call the API to make sure it exists.
            ar_requests.GetVersion(ar_requests.GetClient(),
                                   ar_requests.GetMessages(),
                                   version_or_tag.GetVersionName())
            return version_or_tag
        elif isinstance(version_or_tag, DockerTag):
            digest = ar_requests.GetVersionFromTag(ar_requests.GetClient(),
                                                   ar_requests.GetMessages(),
                                                   version_or_tag.GetTagName())
            docker_version = DockerVersion(version_or_tag.image, digest)
            return docker_version
        else:
            raise ar_exceptions.InvalidInputValueError(
                _INVALID_DOCKER_IMAGE_ERROR)
    except api_exceptions.HttpNotFoundError:
        raise ar_exceptions.InvalidInputValueError(_DOCKER_IMAGE_NOT_FOUND)
Exemplo n.º 2
0
def ListDockerTags(args):
    """Lists Docker tags."""
    resource = _ParseDockerImagePath(args.IMAGE_PATH)

    client = ar_requests.GetClient()
    messages = ar_requests.GetMessages()
    img_list = []
    if isinstance(resource, DockerRepo):
        log.status.Print(
            "Listing items under project {}, location {}, repository {}.\n".
            format(resource.project, resource.location, resource.repo))
        for pkg in ar_requests.ListPackages(client, messages,
                                            resource.GetRepositoryName()):
            img_list.append(DockerImage(resource, pkg.name.split("/")[-1]))
    elif isinstance(resource, DockerImage):
        log.status.Print(
            "Listing items under project {}, location {}, repository {}.\n".
            format(resource.docker_repo.project, resource.docker_repo.location,
                   resource.docker_repo.repo))
        img_list.append(resource)

    tag_list = []
    for img in img_list:
        for tag in ar_requests.ListTags(client, messages,
                                        img.GetPackageName()):
            tag_list.append({
                "tag": tag.name,
                "image": img.GetDockerString(),
                "version": tag.version,
            })
    return tag_list
Exemplo n.º 3
0
def AddDockerTag(args):
    """Adds a Docker tag."""
    src_image, version_or_tag = _ParseDockerImage(args.DOCKER_IMAGE,
                                                  _INVALID_DOCKER_IMAGE_ERROR)
    if version_or_tag is None:
        raise ar_exceptions.InvalidInputValueError(_INVALID_DOCKER_IMAGE_ERROR)

    dest_image, tag = _ParseDockerTag(args.DOCKER_TAG)

    if src_image.GetPackageName() != dest_image.GetPackageName():
        raise ar_exceptions.InvalidInputValueError(
            "Image {}\ndoes not match image {}".format(
                src_image.GetDockerString(), dest_image.GetDockerString()))

    client = ar_requests.GetClient()
    messages = ar_requests.GetMessages()
    docker_version = version_or_tag
    if isinstance(version_or_tag, DockerTag):
        docker_version = DockerVersion(
            version_or_tag.image,
            ar_requests.GetVersionFromTag(client, messages,
                                          version_or_tag.GetTagName()))

    try:
        ar_requests.GetTag(client, messages, tag.GetTagName())
    except api_exceptions.HttpNotFoundError:
        ar_requests.CreateDockerTag(client, messages, tag, docker_version)
    else:
        ar_requests.DeleteTag(client, messages, tag.GetTagName())
        ar_requests.CreateDockerTag(client, messages, tag, docker_version)

    log.status.Print("Added tag [{}] to image [{}].".format(
        tag.GetDockerString(), args.DOCKER_IMAGE))
Exemplo n.º 4
0
def _GetDockerVersions(docker_img, include_tags, is_nested=False):
  """Gets a list of versions for a Docker image."""
  client = ar_requests.GetClient()
  messages = ar_requests.GetMessages()
  ver_view = (
      messages
      .ArtifactregistryProjectsLocationsRepositoriesPackagesVersionsListRequest
      .ViewValueValuesEnum.BASIC)
  if include_tags:
    ver_view = (
        messages.
        ArtifactregistryProjectsLocationsRepositoriesPackagesVersionsListRequest
        .ViewValueValuesEnum.FULL)
  ver_list = ar_requests.ListVersions(client, messages,
                                      docker_img.GetPackageName(), ver_view)

  # If there's no result, the package name might be part of a nested package.
  # E.g. us-west1-docker.pkg.dev/fake-project/docker-repo/nested1 in
  # us-west1-docker.pkg.dev/fake-project/docker-repo/nested1/nested2/test-image
  # Try to get the list of versions through the list of all packages.
  if not ver_list and not is_nested:
    return _GetDockerNestedVersions(docker_img, include_tags, is_nested=True)

  img_list = []
  for ver in ver_list:
    img_list.append({
        "package": docker_img.GetDockerString(),
        "tags": ", ".join([tag.name.split("/")[-1] for tag in ver.relatedTags]),
        "version": ver.name,
        "createTime": ver.createTime,
        "updateTime": ver.updateTime
    })
  return img_list
Exemplo n.º 5
0
def DeleteDockerImage(args):
    """Deletes a Docker digest or image.

  If input is an image, delete the image along with its resources.

  If input is an image identified by digest, delete the digest.
  If input is an image identified by tag, delete the digest and the tag.
  If --delete-tags is specified, delete all tags associated with the image
  digest.

  Args:
    args: user input arguments.

  Returns:
    The long-running operation from DeletePackage API call.
  """
    image, version_or_tag = _ParseDockerImage(args.IMAGE, _INVALID_IMAGE_ERROR)
    _ValidateDockerRepo(image.docker_repo.GetRepositoryName())
    client = ar_requests.GetClient()
    messages = ar_requests.GetMessages()
    if not version_or_tag:
        console_io.PromptContinue(
            message="\nThis operation will delete all tags and images for " +
            image.GetDockerString() + ".",
            cancel_on_no=True)
        return ar_requests.DeletePackage(client, messages,
                                         image.GetPackageName())

    else:
        tags_to_delete = []
        docker_version = version_or_tag
        if isinstance(version_or_tag, DockerTag):
            docker_version = DockerVersion(
                version_or_tag.image,
                ar_requests.GetVersionFromTag(client, messages,
                                              version_or_tag.GetTagName()))
            tags_to_delete.append(version_or_tag)
        existing_tags = _GetDockerVersionTags(client, messages, docker_version)
        if args.delete_tags:
            tags_to_delete.extend(existing_tags)

        if len(existing_tags) != len(tags_to_delete):
            raise ar_exceptions.ArtifactRegistryError(
                "Cannot delete image {} because it is tagged. "
                "Existing tags are:\n- {}".format(
                    args.IMAGE, "\n- ".join(tag.GetDockerString()
                                            for tag in existing_tags)))

        _LogResourcesToDelete(docker_version, tags_to_delete)
        console_io.PromptContinue(
            message="\nThis operation will delete the above resources.",
            cancel_on_no=True)

        for tag in tags_to_delete:
            ar_requests.DeleteTag(client, messages, tag.GetTagName())
        return ar_requests.DeleteVersion(client, messages,
                                         docker_version.GetVersionName())
Exemplo n.º 6
0
def DeleteDockerTag(args):
    """Deletes a Docker tag."""
    _, tag = _ParseDockerTag(args.DOCKER_TAG)

    console_io.PromptContinue(
        message="You are about to delete tag [{}]".format(
            tag.GetDockerString()),
        cancel_on_no=True)
    ar_requests.DeleteTag(ar_requests.GetClient(), ar_requests.GetMessages(),
                          tag.GetTagName())
    log.status.Print("Deleted tag [{}].".format(tag.GetDockerString()))
Exemplo n.º 7
0
def DeleteDockerTag(args):
  """Deletes a Docker tag."""
  img, tag = _ParseDockerTag(args.DOCKER_TAG)

  ar_util.ValidateLocation(img.docker_repo.location, img.docker_repo.project)
  _ValidateDockerRepo(img.docker_repo.GetRepositoryName())

  console_io.PromptContinue(
      message="You are about to delete tag [{}]".format(tag.GetDockerString()),
      cancel_on_no=True)
  ar_requests.DeleteTag(ar_requests.GetClient(), ar_requests.GetMessages(),
                        tag.GetTagName())
  log.status.Print("Deleted tag [{}].".format(tag.GetDockerString()))
Exemplo n.º 8
0
def _GetDockerPackagesAndVersions(docker_repo, include_tags, is_nested=False):
    """Gets a list of packages with versions for a Docker repository."""
    client = ar_requests.GetClient()
    messages = ar_requests.GetMessages()
    img_list = []
    for pkg in ar_requests.ListPackages(client, messages,
                                        docker_repo.GetRepositoryName()):
        parts = pkg.name.split("/")
        if len(parts) != 8:
            raise ar_exceptions.ArtifactRegistryError(
                "Internal error. Corrupted package name: {}".format(pkg.name))
        img = DockerImage(DockerRepo(parts[1], parts[3], parts[5]), parts[7])
        img_list.extend(_GetDockerVersions(img, include_tags, is_nested))
    return img_list
Exemplo n.º 9
0
def _GetDockerDigest(version_or_tag):
    """Retrieves the docker digest information.

  Args:
    version_or_tag: an object of DockerVersion or DockerTag

  Returns:
    A dictionary of information about the given docker image.
  """
    docker_version = version_or_tag
    try:
        if isinstance(version_or_tag, DockerVersion):
            # We have all the information about the docker digest.
            # Call the API to make sure it exists.
            ar_requests.GetVersion(ar_requests.GetClient(),
                                   ar_requests.GetMessages(),
                                   version_or_tag.GetVersionName())
        elif isinstance(version_or_tag, DockerTag):
            digest = ar_requests.GetVersionFromTag(ar_requests.GetClient(),
                                                   ar_requests.GetMessages(),
                                                   version_or_tag.GetTagName())
            docker_version = DockerVersion(version_or_tag.image, digest)
        else:
            raise ar_exceptions.InvalidInputValueError(
                _INVALID_DOCKER_IMAGE_ERROR)
    except api_exceptions.HttpNotFoundError:
        raise ar_exceptions.InvalidInputValueError(_DOCKER_IMAGE_NOT_FOUND)
    return {
        "digest":
        docker_version.digest,
        "fully_qualified_digest":
        docker_version.GetDockerString(),
        "registry":
        "{}-docker.pkg.dev".format(docker_version.image.docker_repo.location),
        "repository":
        docker_version.image.docker_repo.repo,
    }
Exemplo n.º 10
0
def DeleteDockerImage(args):
    """Deletes a Docker digest or image.

  If input is an image, delete the image along with its resources.

  If input is an image identified by digest, delete the digest.
  If input is an image identified by tag, delete the digest and the tag.
  If --delete-tags is specified, delete all tags associated with the image
  digest.

  Args:
    args: user input arguments.

  Returns:
    The long-running operation from DeletePackage API call.
  """
    image, version_or_tag = _ParseDockerImage(args.IMAGE, _INVALID_IMAGE_ERROR)
    client = ar_requests.GetClient()
    messages = ar_requests.GetMessages()
    if not version_or_tag:
        console_io.PromptContinue(
            message="\nThis operation will delete all tags and images for " +
            image.GetDockerString() + ".",
            cancel_on_no=True)
        return ar_requests.DeletePackage(client, messages,
                                         image.GetPackageName())

    else:
        tags_to_delete = []
        docker_version = version_or_tag
        if isinstance(version_or_tag, DockerTag):
            docker_version = DockerVersion(
                version_or_tag.image,
                ar_requests.GetVersionFromTag(client, messages,
                                              version_or_tag.GetTagName()))
            tags_to_delete.append(version_or_tag)
        if args.delete_tags:
            tags_to_delete.extend(
                _GetDockerVersionTags(client, messages, docker_version))

        _LogResourcesToDelete(docker_version, tags_to_delete)
        console_io.PromptContinue(
            message="\nThis operation will delete the above resources.",
            cancel_on_no=True)
        for tag in tags_to_delete:
            ar_requests.DeleteTag(client, messages, tag.GetTagName())
        return ar_requests.DeleteVersion(client, messages,
                                         docker_version.GetVersionName())
Exemplo n.º 11
0
def ListRepositories(args):
    """List repositories in a given project.

  If no location value is specified, list repositories across all locations.

  Args:
    args: User input arguments.

  Returns:
    List of repositories.
  """
    project = GetProject(args)
    location = args.location or properties.VALUES.artifacts.location.Get()
    if location and not IsValidLocation(location) and location != "all":
        raise ar_exceptions.UnsupportedLocationError(
            "{} is not a valid location. Valid locations are [{}].".format(
                location, ", ".join(_VALID_LOCATIONS)))

    loc_paths = []
    if location and location != "all":
        log.status.Print(
            "Listing items under project {}, location {}.\n".format(
                project, location))
        loc_paths.append("projects/{}/locations/{}".format(project, location))
        buckets = [_GCR_BUCKETS[location]] if location in _GCR_BUCKETS else []
    else:
        log.status.Print(
            "Listing items under project {}, across all locations.\n".format(
                project))
        loc_paths.extend([
            "projects/{}/locations/{}".format(project, loc)
            for loc in _VALID_LOCATIONS
        ])
        buckets = _GCR_BUCKETS.values()

    client = ar_requests.GetClient()
    messages = ar_requests.GetMessages()
    repos = []
    for loc in loc_paths:
        repos.extend(ar_requests.ListRepositories(client, messages, loc))
    gcr_repos = _GetGCRRepos(buckets, project)
    if gcr_repos:
        repos.extend(gcr_repos)
        log.status.Print(
            "Note: To perform actions on the Container Registry repositories "
            "listed below please use 'gcloud container images'.\n")

    return repos
Exemplo n.º 12
0
def WaitForOperation(operation, message):
    """Waits for the given google.longrunning.Operation to complete.

  Args:
    operation: The operation to poll.
    message: String to display for default progress_tracker.

  Raises:
    apitools.base.py.HttpError: if the request returns an HTTP error
  """
    op_service = ar_requests.GetClient().projects_locations_operations
    op_resource = resources.REGISTRY.ParseRelativeName(
        operation.name,
        collection="artifactregistry.projects.locations.operations")
    poller = waiter.CloudOperationPollerNoResources(op_service)
    waiter.WaitFor(poller, op_resource, message)
Exemplo n.º 13
0
def CreateRepository(repo):
    """Creates an Artifact Registry repostiory and waits for the operation.

  Args:
    repo: googlecloudsdk.command_lib.artifacts.docker_util.DockerRepo defining
      the repository to be created.
  """
    messages = requests.GetMessages()
    repository_message = messages.Repository(
        name=repo.GetRepositoryName(),
        description='Cloud Run Source Deployments',
        format=messages.Repository.FormatValueValuesEnum.DOCKER,
    )

    op = requests.CreateRepository(repo.project, repo.location,
                                   repository_message)
    op_resource = resources.REGISTRY.ParseRelativeName(
        op.name, collection='artifactregistry.projects.locations.operations')

    client = requests.GetClient()
    waiter.WaitFor(
        waiter.CloudOperationPoller(client.projects_locations_repositories,
                                    client.projects_locations_operations),
        op_resource)
def ListFiles(args):
    """Lists files in a given project.

  Args:
    args: User input arguments.

  Returns:
    List of files.
  """
    client = ar_requests.GetClient()
    messages = ar_requests.GetMessages()
    project = GetProject(args)
    location = args.location or properties.VALUES.artifacts.location.Get()
    repo = GetRepo(args)
    package = args.package
    version = args.version
    tag = args.tag
    page_size = args.page_size
    arg_filters = ""

    # Parse fully qualified path in package argument
    if package:
        if re.match(
                r"projects\/.*\/locations\/.*\/repositories\/.*\/packages\/.*",
                package):
            params = package.replace("projects/", "", 1).replace(
                "/locations/", " ",
                1).replace("/repositories/", " ",
                           1).replace("/packages/", " ", 1).split(" ")
            project, location, repo, package = [
                params[i] for i in range(len(params))
            ]

    # Escape slashes in package name
    if package:
        package = package.replace("/", "%2F")

    # Retrieve version from tag name
    if version and tag:
        raise ar_exceptions.InvalidInputValueError(
            "Specify either --version or --tag with --package argument.")
    if package and tag:
        tag_path = resources.Resource.RelativeName(
            resources.REGISTRY.Create(
                "artifactregistry.projects.locations.repositories.packages.tags",
                projectsId=project,
                locationsId=location,
                repositoriesId=repo,
                packagesId=package,
                tagsId=tag))
        version = ar_requests.GetVersionFromTag(client, messages, tag_path)

    if package and version:
        version_path = resources.Resource.RelativeName(
            resources.REGISTRY.Create(
                "artifactregistry.projects.locations.repositories.packages.versions",
                projectsId=project,
                locationsId=location,
                repositoriesId=repo,
                packagesId=package,
                versionsId=version))
        arg_filters = 'owner="{}"'.format(version_path)
    elif package:
        package_path = resources.Resource.RelativeName(
            resources.REGISTRY.Create(
                "artifactregistry.projects.locations.repositories.packages",
                projectsId=project,
                locationsId=location,
                repositoriesId=repo,
                packagesId=package))
        arg_filters = 'owner="{}"'.format(package_path)
    elif version or tag:
        raise ar_exceptions.InvalidInputValueError(
            "Package name is required when specifying version or tag.")

    repo_path = resources.Resource.RelativeName(
        resources.REGISTRY.Create(
            "artifactregistry.projects.locations.repositories",
            projectsId=project,
            locationsId=location,
            repositoriesId=repo))
    files = ar_requests.ListFiles(client, messages, repo_path, arg_filters,
                                  page_size)

    for file in files:
        file.name = resources.REGISTRY.ParseRelativeName(
            file.name,
            collection="artifactregistry.projects.locations.repositories.files"
        ).filesId.replace("%2F", "/")

    return files