Esempio n. 1
0
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
Esempio n. 2
0
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}')
Esempio n. 3
0
def FromArgs(args):
    """Populates a docker_image_list.Platform object from the provided args."""
    p = {}

    def _SetField(k, v):
        if v is not None:
            p[k] = v

    _SetField('os', args.os)
    _SetField('os.version', args.os_version)
    _SetField('os.features', args.os_features)
    _SetField('architecture', args.architecture)
    _SetField('variant', args.variant)
    _SetField('features', args.features)

    return docker_image_list.Platform(p)
Esempio n. 4
0
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)