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) http_obj = http.Http() with docker_image.FromRegistry( basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as image: try: return util.TransformManifests( image.manifests(), repository, show_occurrences=args.show_occurrences, occurrence_filter=args.occurrence_filter) except docker_http.V2DiagnosticException as err: raise util.GcloudifyRecoverableV2Errors(err, { 403: 'Access denied: {0}'.format(repository), 404: 'Not found: {0}'.format(repository) })
def ImageDigestForContainerImage(name, tag): """Given a container image and tag, returns the digest for that image version. Args: name: the gcr.io registry name plus the image name tag: the image tag Returns: The digest of the image, or None if there is no such image. Raises: googlecloudsdk.core.UnsupportedRegistryError: If the path is valid, but belongs to an unsupported registry. i_util.InvalidImageNameError: If the image name is invalid. i_util.TokenRefreshError: If there is an error refreshing credentials needed to access the GCR repo. i_util.UserRecoverableV2Error: If a user-recoverable error occurs accessing the GCR repo. """ def _TaggedImage(): """Display the fully-qualified name.""" return '{}:{}'.format(name, tag) name = i_util.ValidateRepositoryPath(name) with i_util.WrapExpectedDockerlessErrors(name): with docker_image.FromRegistry( basic_creds=i_util.CredentialProvider(), name=docker_name.Tag(_TaggedImage()), transport=http.Http()) as r: return r.digest()
def Run(self, args): def Push(image, dest_name, creds, http_obj, src_name, session_push_type): with session_push_type(dest_name, creds, http_obj) as push: push.upload(image) log.CreatedResource(dest_name) log.UpdatedResource(src_name) http_obj = http.Http() src_name = util.GetDockerImageFromTagOrDigest(args.src_image) dest_name = docker_name.Tag(args.dest_image) console_io.PromptContinue('This will tag {0} with {1}'.format( src_name, dest_name), default=True, cancel_on_no=True) creds = util.CredentialProvider() with v2_2_image.FromRegistry(src_name, creds, http_obj) as v2_2_img: if v2_2_img.exists(): Push(v2_2_img, dest_name, 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_name, 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. Returns: Some value that we want to have printed later. """ repository_arg = args.repository if not repository_arg: repository_arg = 'gcr.io/{0}'.format( properties.VALUES.core.project.Get(required=True)) # Throws if invalid. repository = util.ValidateRepositoryPath(repository_arg) def _DisplayName(c): """Display the fully-qualified name.""" return '{0}/{1}'.format(repository, c) http_obj = http.Http() 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 _DeleteDockerTag(self, tag, digests, http_obj): # calling Delete on an image referenced by tag only deletes the tag docker_session.Delete(creds=util.CredentialProvider(), name=tag, transport=http_obj) log.DeletedResource('[{tag}] (referencing [{digest}])'.format( tag=tag, digest=digests[tag]))
def Run(self, args): # pylint: disable=missing-docstring def Push(image, dest_name, creds, http_obj, src_name, session_push_type): try: with session_push_type(dest_name, creds, http_obj) as push: push.upload(image) log.CreatedResource(dest_name) log.UpdatedResource(src_name) except docker_http.V2DiagnosticException as err: raise util.GcloudifyRecoverableV2Errors( err, { 403: 'Tagging failed, access denied: {0}'.format(dest_name) }) http_obj = http.Http() src_name = util.GetDockerImageFromTagOrDigest(args.src_image) dest_name = docker_name.Tag(args.dest_image) console_io.PromptContinue('This will tag {0} with {1}'.format( src_name, dest_name), default=True, cancel_on_no=True) creds = util.CredentialProvider() with v2_2_image.FromRegistry(src_name, creds, http_obj) as v2_2_img: if v2_2_img.exists(): Push(v2_2_img, dest_name, 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_name, creds, http_obj, src_name, v2_session.Push)
def _DeleteDockerTagOrDigest(self, tag_or_digest, http_obj): try: docker_session.Delete(creds=util.CredentialProvider(), name=tag_or_digest, transport=http_obj) log.DeletedResource(tag_or_digest) except docker_http.V2DiagnosticException as err: raise self._MapDeleteErr(err, tag_or_digest)
def _DeleteDigestAndAssociatedTags(self, digest, http_obj): # digest must not have any tags in order to be deleted util.DeleteTagsFromDigest(digest, http_obj) tag_list = util.GetTagNamesForDigest(digest, http_obj) for tag in tag_list: log.DeletedResource(tag) docker_session.Delete(creds=util.CredentialProvider(), name=digest, transport=http_obj) log.DeletedResource(digest)
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 = http.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(six.text_type(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. 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 = http.Http() try: with docker_image.FromRegistry( basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as r: try: images = [{'name': _DisplayName(c)} for c in r.children()] return images except docker_http.V2DiagnosticException as err: if err.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]: raise exceptions.Error( 'Access denied: {0}'.format(repository)) elif err.status == httplib.NOT_FOUND: raise exceptions.Error( 'Not found: {0}'.format(repository)) else: raise except docker_http.BadStateException as e: raise exceptions.Error(e)
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 = http.Http() with docker_image.FromRegistry(basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as image: try: manifests = image.manifests() # Only consider the top _DEFAULT_SHOW_OCCURRENCES_FROM images # to reduce computation time. most_recent_resource_urls = None 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']) ] return util.TransformManifests( manifests, repository, show_occurrences=args.show_occurrences, occurrence_filter=args.occurrence_filter, resource_urls=most_recent_resource_urls) except docker_http.V2DiagnosticException as err: raise util.GcloudifyRecoverableV2Errors( err, { 403: 'Access denied: {0}'.format(repository), 404: 'Not found: {0}'.format(repository) })
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 = http.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)
def _DeleteDigestAndAssociatedTags(self, digest, http_obj): # Digest must not have any tags in order to be deleted. # Errors raised from tag deletion are deliberately uncaught. util.DeleteTagsFromDigest(digest, http_obj) tag_list = util.GetTagNamesForDigest(digest, http_obj) for tag in tag_list: log.DeletedResource(tag) try: docker_session.Delete( creds=util.CredentialProvider(), name=digest, transport=http_obj) log.DeletedResource(digest) except docker_http.V2DiagnosticException as err: raise self._MapDeleteErr(err, digest)
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 = http.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 _DeleteDockerTagOrDigest(self, tag_or_digest, http_obj): docker_session.Delete(creds=util.CredentialProvider(), name=tag_or_digest, transport=http_obj) log.DeletedResource(tag_or_digest)