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 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 _ParseArgs(self, image_names): tags = set() for image_name in image_names: docker_obj = util.GetDockerImageFromTagOrDigest(image_name) if (isinstance(docker_obj, docker_name.Tag) and util.IsFullySpecified(image_name)): # Only accept explicitly named tags for removal. tags.add(docker_obj) else: raise util.InvalidImageNameError( 'IMAGE_NAME must be of the form [*.gcr.io/repository:<tag>]: ' '[{}]'.format(image_name)) return tags