def pulled_image( image_reference: str, credentials_lookup: typing.Callable[[image_reference, oa.Privileges, bool], oa.OciConfig], ): _tag_or_digest_reference(image_reference) transport = _mk_transport_pool() image_reference = ou.normalise_image_reference(image_reference) image_reference = docker_name.from_string(image_reference) creds = _mk_credentials( image_reference=image_reference, credentials_lookup=credentials_lookup, ) # OCI Image Manifest is compatible with Docker Image Manifest Version 2, # Schema 2. We indicate support for both formats by passing both media types # as 'Accept' headers. # # For reference: # OCI: https://github.com/opencontainers/image-spec # Docker: https://docs.docker.com/registry/spec/manifest-v2-2/ accept = docker_http.SUPPORTED_MANIFEST_MIMES try: logger.info(f'Pulling v2.2 image from {image_reference}..') with v2_2_image.FromRegistry(image_reference, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): yield v2_2_img return # XXX TODO: use streaming rather than writing to local FS # if outfile is given, we must use it instead of an ano logger.debug(f'Pulling manifest list from {image_reference}..') with image_list.FromRegistry(image_reference, creds, transport) as img_list: if img_list.exists(): platform = image_list.Platform({ 'architecture': _PROCESSOR_ARCHITECTURE, 'os': _OPERATING_SYSTEM, }) # pytype: disable=wrong-arg-types with img_list.resolve(platform) as default_child: yield default_child return logger.info(f'Pulling v2 image from {image_reference}..') with v2_image.FromRegistry(image_reference, creds, transport) as v2_img: if v2_img.exists(): with v2_compat.V22FromV2(v2_img) as v2_2_img: yield v2_2_img return raise om.OciImageNotFoundException( f'failed to retrieve {image_reference=} - does it exist?') except Exception as e: raise e
def ResolveManifestListTag(tag): with docker_image_list.FromRegistry( basic_creds=CredentialProvider(), name=tag, transport=http.Http()) as manifest_list: if manifest_list.exists(): return manifest_list.digest() return None
def to_hash_reference(image_name: str): transport = _mk_transport(size=1) image_name = normalise_image_reference(image_name) image_reference = _parse_image_reference(image_name) creds = _mk_credentials(image_reference=image_reference) accept = docker_http.SUPPORTED_MANIFEST_MIMES digest = None with image_list.FromRegistry(image_reference, creds, transport) as img_list: if img_list.exists(): digest = img_list.digest() else: logger.debug('no manifest found') # look for image with v2_2_image.FromRegistry(image_reference, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): digest = v2_2_img.digest() else: logger.debug('no img v2.2 found') if not digest: # fallback to v2 with v2_image.FromRegistry(image_reference, creds, transport) as v2_img: if v2_img.exists(): digest = v2_img.digest() else: logger.debug('no img v2 found') raise RuntimeError(f'could not access img-metadata for {image_name}') name = image_name.rsplit(':', 1)[0] return f'{name}@{digest}'
def _pull_image(image_reference: str, outfileobj=None): import ci.util ci.util.not_none(image_reference) transport = _mk_transport() image_reference = normalise_image_reference(image_reference) image_reference = _parse_image_reference(image_reference) creds = _mk_credentials(image_reference=image_reference) # OCI Image Manifest is compatible with Docker Image Manifest Version 2, # Schema 2. We indicate support for both formats by passing both media types # as 'Accept' headers. # # For reference: # OCI: https://github.com/opencontainers/image-spec # Docker: https://docs.docker.com/registry/spec/manifest-v2-2/ accept = docker_http.SUPPORTED_MANIFEST_MIMES try: # XXX TODO: use streaming rather than writing to local FS # if outfile is given, we must use it instead of an ano outfileobj = outfileobj if outfileobj else tempfile.TemporaryFile() with tarfile.open(fileobj=outfileobj, mode='w:') as tar: ci.util.verbose(f'Pulling manifest list from {image_reference}..') with image_list.FromRegistry(image_reference, creds, transport) as img_list: if img_list.exists(): platform = image_list.Platform({ 'architecture': _PROCESSOR_ARCHITECTURE, 'os': _OPERATING_SYSTEM, }) # pytype: disable=wrong-arg-types with img_list.resolve(platform) as default_child: save.tarball(_make_tag_if_digest(image_reference), default_child, tar) return outfileobj # pytype: enable=wrong-arg-types ci.util.info(f'Pulling v2.2 image from {image_reference}..') with v2_2_image.FromRegistry(image_reference, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): save.tarball(_make_tag_if_digest(image_reference), v2_2_img, tar) return outfileobj ci.util.info(f'Pulling v2 image from {image_reference}..') with v2_image.FromRegistry(image_reference, creds, transport) as v2_img: with v2_compat.V22FromV2(v2_img) as v2_2_img: save.tarball(_make_tag_if_digest(image_reference), v2_2_img, tar) return outfileobj except Exception as e: outfileobj.close() ci.util.fail(f'Error pulling and saving image {image_reference}: {e}')
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 _image_exists(image_reference: str) -> bool: transport = _mk_transport(size=1) image_reference = normalise_image_reference(image_reference) image_reference = _parse_image_reference(image_reference) creds = _mk_credentials(image_reference=image_reference) accept = docker_http.SUPPORTED_MANIFEST_MIMES with image_list.FromRegistry(image_reference, creds, transport) as img_list: if img_list.exists(): return True logger.debug('no manifest found') # look for image with v2_2_image.FromRegistry(image_reference, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): return True logger.debug('no img v2.2 found') return False
def image_exists( image_reference: str, credentials_lookup: typing.Callable[[image_reference, oa.Privileges, bool], oa.OciConfig], ) -> bool: ''' returns a boolean value indicating whether or not the given OCI Artifact exists ''' transport = _ou._mk_transport_pool(size=1) image_reference = ou.normalise_image_reference( image_reference=image_reference) image_reference = _ou.docker_name.from_string(image_reference) creds = _ou._mk_credentials( image_reference=image_reference, credentials_lookup=credentials_lookup, ) # keep import local to avoid exposure to module's users from containerregistry.client.v2_2 import docker_image_list as image_list with image_list.FromRegistry(image_reference, creds, transport) as img_list: if img_list.exists(): return True # keep import local to avoid exposure to module's users from containerregistry.client.v2_2 import docker_image as v2_2_image accept = _ou.docker_http.SUPPORTED_MANIFEST_MIMES with v2_2_image.FromRegistry(image_reference, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): return True return False
def main(): logging_setup.DefineCommandLineArgs(parser) args = parser.parse_args() logging_setup.Init(args=args) if not args.name or not args.directory: logging.fatal('--name and --directory are required arguments.') retry_factory = retry.Factory() retry_factory = retry_factory.WithSourceTransportCallable(httplib2.Http) transport = transport_pool.Http(retry_factory.Build, size=_THREADS) if '@' in args.name: name = docker_name.Digest(args.name) else: name = docker_name.Tag(args.name) # OCI Image Manifest is compatible with Docker Image Manifest Version 2, # Schema 2. We indicate support for both formats by passing both media types # as 'Accept' headers. # # For reference: # OCI: https://github.com/opencontainers/image-spec # Docker: https://docs.docker.com/registry/spec/manifest-v2-2/ accept = docker_http.SUPPORTED_MANIFEST_MIMES # Resolve the appropriate credential to use based on the standard Docker # client logic. try: creds = docker_creds.DefaultKeychain.Resolve(name) # pylint: disable=broad-except except Exception as e: logging.fatal('Error resolving credentials for %s: %s', name, e) sys.exit(1) try: logging.info('Pulling manifest list from %r ...', name) with image_list.FromRegistry(name, creds, transport) as img_list: if img_list.exists(): platform = image_list.Platform({ 'architecture': _PROCESSOR_ARCHITECTURE, 'os': _OPERATING_SYSTEM, }) # pytype: disable=wrong-arg-types with img_list.resolve(platform) as default_child: save.fast(default_child, args.directory, threads=_THREADS) return # pytype: enable=wrong-arg-types logging.info('Pulling v2.2 image from %r ...', name) with v2_2_image.FromRegistry(name, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): save.fast(v2_2_img, args.directory, threads=_THREADS) return logging.info('Pulling v2 image from %r ...', name) with v2_image.FromRegistry(name, creds, transport) as v2_img: with v2_compat.V22FromV2(v2_img) as v2_2_img: save.fast(v2_2_img, args.directory, threads=_THREADS) return # pylint: disable=broad-except except Exception as e: logging.fatal('Error pulling and saving image %s: %s', name, e) sys.exit(1)
def main(): logging_setup.DefineCommandLineArgs(parser) args = parser.parse_args() logging_setup.Init(args=args) # retry if error acc to retry plan retry_factory = retry.Factory() retry_factory = retry_factory.WithSourceTransportCallable(httplib2.Http) transport = transport_pool.Http(retry_factory.Build, size=_THREADS) if '@' in args.name: name = docker_name.Digest(args.name) else: name = docker_name.Tag(args.name) # If the user provided a client config directory, instruct the keychain # resolver to use it to look for the docker client config if args.client_config_dir is not None: docker_creds.DefaultKeychain.setCustomConfigDir(args.client_config_dir) # OCI Image Manifest is compatible with Docker Image Manifest Version 2, # Schema 2. We indicate support for both formats by passing both media types # as 'Accept' headers. # # For reference: # OCI: https://github.com/opencontainers/image-spec # Docker: https://docs.docker.com/registry/spec/manifest-v2-2/ accept = docker_http.SUPPORTED_MANIFEST_MIMES # Resolve the appropriate credential to use based on the standard Docker # client logic. try: # check username/paswd match up creds = docker_creds.DefaultKeychain.Resolve(name) # pylint: disable=broad-except except Exception as e: logging.fatal('Error resolving credentials for %s: %s', name, e) sys.exit(1) try: logging.info('Pulling manifest list from %r ...', name) # (image, [(.sha, tar)]) with image_list.FromRegistry(name, creds, transport) as img_list: if img_list.exists(): # populate docker_image_list.Platform object (runtime requirements for an object) # from the provided args # see: docker image manifest list platform = platform_args.FromArgs(args) # pytype: disable=wrong-arg-types with img_list.resolve(platform) as default_child: # save.fast( # create new filesystem (directory) with config files and sha/tars (_save.py) default_child, args.directory, threads=_THREADS, cache_directory=args.cache) return # pytype: enable=wrong-arg-types logging.info('Pulling v2.2 image from %r ...', name) with v2_2_image.FromRegistry(name, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): save.fast(v2_2_img, args.directory, threads=_THREADS, cache_directory=args.cache) return logging.info('Pulling v2 image from %r ...', name) with v2_image.FromRegistry(name, creds, transport) as v2_img: with v2_compat.V22FromV2(v2_img) as v2_2_img: save.fast(v2_2_img, args.directory, threads=_THREADS, cache_directory=args.cache) return # pylint: disable=broad-except except Exception as e: logging.fatal('Error pulling and saving image %s: %s', name, e) sys.exit(1)
def main(): logging_setup.DefineCommandLineArgs(parser) args = parser.parse_args() logging_setup.Init(args=args) retry_factory = retry.Factory() retry_factory = retry_factory.WithSourceTransportCallable(httplib2.Http) transport = transport_pool.Http(retry_factory.Build, size=8) if '@' in args.name: name = docker_name.Digest(args.name) else: name = docker_name.Tag(args.name) # OCI Image Manifest is compatible with Docker Image Manifest Version 2, # Schema 2. We indicate support for both formats by passing both media types # as 'Accept' headers. # # For reference: # OCI: https://github.com/opencontainers/image-spec # Docker: https://docs.docker.com/registry/spec/manifest-v2-2/ accept = docker_http.SUPPORTED_MANIFEST_MIMES # Resolve the appropriate credential to use based on the standard Docker # client logic. try: creds = docker_creds.DefaultKeychain.Resolve(name) # pylint: disable=broad-except except Exception as e: logging.fatal('Error resolving credentials for %s: %s', name, e) sys.exit(1) try: with tarfile.open(name=args.tarball, mode='w:') as tar: logging.info('Pulling manifest list from %r ...', name) with image_list.FromRegistry(name, creds, transport) as img_list: if img_list.exists(): platform = platform_args.FromArgs(args) # pytype: disable=wrong-arg-types with img_list.resolve(platform) as default_child: save.tarball(_make_tag_if_digest(name), default_child, tar) return # pytype: enable=wrong-arg-types logging.info('Pulling v2.2 image from %r ...', name) with v2_2_image.FromRegistry(name, creds, transport, accept) as v2_2_img: if v2_2_img.exists(): save.tarball(_make_tag_if_digest(name), v2_2_img, tar) return logging.info('Pulling v2 image from %r ...', name) with v2_image.FromRegistry(name, creds, transport) as v2_img: with v2_compat.V22FromV2(v2_img) as v2_2_img: save.tarball(_make_tag_if_digest(name), v2_2_img, tar) return # pylint: disable=broad-except except Exception as e: logging.fatal('Error pulling and saving image %s: %s', name, e) sys.exit(1)