Esempio n. 1
0
def PULL(image, download_folder=None, layerfile=None):
    '''PULL will retrieve a Singularity Hub image and
    download to the local file system, to the variable
    specified by SINGULARITY_PULLFOLDER.
    :param image: the singularity hub image name
    :param download folder: the folder to pull the image to.
    :param layerfile: if defined, write pulled image to file
    '''
    client = SingularityApiConnection(image=image)
    manifest = client.get_manifest()

    if download_folder is None:
        cache_base = get_cache(subfolder="shub")
    else:
        cache_base = os.path.abspath(download_folder)

    bot.debug("Pull folder set to %s" % cache_base)

    # The image name is the md5 hash, download if it's not there
    image_name = get_image_name(manifest)

    # Did the user specify an absolute path?
    custom_folder = os.path.dirname(image_name)
    if custom_folder not in [None, ""]:
        cache_base = custom_folder
        image_name = os.path.basename(image_name)

    image_file = "%s/%s" % (cache_base, image_name)

    bot.debug('Pulling to %s' % image_file)
    if not os.path.exists(image_file):
        image_file = client.download_image(manifest=manifest,
                                           download_folder=cache_base,
                                           image_name=image_name)
    else:
        if not bot.is_quiet():  # not --quiet
            print("Image already exists at %s, skipping download" % image_file)

    if not bot.is_quiet():  # not --quiet
        print("Singularity Hub Image Download: %s" % image_file)

    manifest = {
        'image_file': image_file,
        'manifest': manifest,
        'cache_base': cache_base,
        'image': image
    }

    if layerfile is not None:
        bot.debug("Writing Singularity Hub image path to %s" % layerfile)
        write_file(layerfile, image_file, mode="w")

    return manifest
Esempio n. 2
0
def extract_metadata_tar(manifest,
                         image_name,
                         include_env=True,
                         include_labels=True,
                         runscript=None):

    '''extract_metadata_tar will write a tarfile with the environment,
    labels, and runscript. include_env and include_labels should be booleans,
    and runscript should be None or a string to write to the runscript.
    '''
    tar_file = None
    files = []
    if include_env or include_labels:

        # Extract and add environment
        if include_env:
            environ = extract_env(manifest)
            if environ not in [None, ""]:
                bot.verbose3('Adding Docker environment to metadata tar')
                template = get_template('tarinfo')
                template['name'] = './%s/env/%s-%s.sh' % (METADATA_FOLDER_NAME,
                                                          DOCKER_NUMBER,
                                                          DOCKER_PREFIX)
                template['content'] = environ
                files.append(template)

        # Extract and add labels
        if include_labels:
            labels = extract_labels(manifest)
            if labels is not None:
                if isinstance(labels, dict):
                    labels = print_json(labels)
                bot.verbose3('Adding Docker labels to metadata tar')
                template = get_template('tarinfo')
                template['name'] = "./%s/labels.json" % METADATA_FOLDER_NAME
                template['content'] = labels
                files.append(template)

        if runscript is not None:
            bot.verbose3('Adding Docker runscript to metadata tar')
            template = get_template('tarinfo')
            template['name'] = "./%s/runscript" % METADATA_FOLDER_NAME
            template['content'] = runscript
            files.append(template)

    if len(files) > 0:
        output_folder = get_cache(subfolder="metadata", quiet=True)
        tar_file = create_tar(files, output_folder)
    else:
        bot.warning("No metadata will be included.")
    return tar_file
Esempio n. 3
0
def PULL(image, download_folder=None, layerfile=None):
    '''PULL will retrieve a Singularity Hub image and
    download to the local file system, to the variable
    specified by SINGULARITY_PULLFOLDER.
    :param image: the singularity hub image name
    :param download folder: the folder to pull the image to.
    :param layerfile: if defined, write pulled image to file
    '''
    client = SingularityApiConnection(image=image)
    manifest = client.get_manifest()

    if download_folder is None:
        cache_base = get_cache(subfolder="shub")
    else:
        cache_base = os.path.abspath(download_folder)

    bot.debug("Pull folder set to %s" % cache_base)

    # The image name is the md5 hash, download if it's not there
    image_name = get_image_name(manifest)

    # Did the user specify an absolute path?
    custom_folder = os.path.dirname(image_name)
    if custom_folder not in [None, ""]:
        cache_base = custom_folder
        image_name = os.path.basename(image_name)

    image_file = "%s/%s" % (cache_base, image_name)

    bot.debug('Pulling to %s' % image_file)
    if not os.path.exists(image_file):
        image_file = client.download_image(manifest=manifest,
                                           download_folder=cache_base)
    else:
        if not bot.is_quiet():  # not --quiet
            print("Image already exists at %s, skipping download" % image_file)

    if not bot.is_quiet():  # not --quiet
        print("Singularity Hub Image Download: %s" % image_file)

    manifest = {'image_file': image_file,
                'manifest': manifest,
                'cache_base': cache_base,
                'image': image}

    if layerfile is not None:
        bot.debug("Writing Singularity Hub image path to %s" % layerfile)
        write_file(layerfile, image_file, mode="w")

    return manifest
Esempio n. 4
0
def extract_metadata_tar(manifest,
                         image_name,
                         include_env=True,
                         include_labels=True,
                         runscript=None):
    '''extract_metadata_tar will write a tarfile with the environment,
    labels, and runscript. include_env and include_labels should be booleans,
    and runscript should be None or a string to write to the runscript.
    '''
    tar_file = None
    files = []
    if include_env or include_labels:

        # Extract and add environment
        if include_env:
            environ = extract_env(manifest)
            if environ not in [None, ""]:
                bot.verbose3('Adding Docker environment to metadata tar')
                template = get_template('tarinfo')
                template['name'] = './%s/env/%s-%s.sh' % (
                    METADATA_FOLDER_NAME, DOCKER_NUMBER, DOCKER_PREFIX)
                template['content'] = environ
                files.append(template)

        # Extract and add labels
        if include_labels:
            labels = extract_labels(manifest)
            if labels is not None:
                if isinstance(labels, dict):
                    labels = print_json(labels)
                bot.verbose3('Adding Docker labels to metadata tar')
                template = get_template('tarinfo')
                template['name'] = "./%s/labels.json" % METADATA_FOLDER_NAME
                template['content'] = labels
                files.append(template)

        if runscript is not None:
            bot.verbose3('Adding Docker runscript to metadata tar')
            template = get_template('tarinfo')
            template['name'] = "./%s/runscript" % METADATA_FOLDER_NAME
            template['content'] = runscript
            files.append(template)

    if len(files) > 0:
        output_folder = get_cache(subfolder="metadata", quiet=True)
        tar_file = create_tar(files, output_folder)
    else:
        bot.warning("No metadata will be included.")
    return tar_file
Esempio n. 5
0
def IMPORT(image, auth=None, layerfile=None):
    '''IMPORT is the main script that will obtain docker layers,
    runscript information (either entrypoint or cmd), and environment
    and return a list of tarballs to extract into the image
    :param auth: if needed, an authentication header (default None)
    :param layerfile: The file to write layers to extract into
    '''
    bot.debug("Starting Docker IMPORT, includes env, runscript, and metadata.")
    bot.verbose("Docker image: %s" % image)

    # Does the user want to override default of using ENTRYPOINT?
    if INCLUDE_CMD:
        bot.verbose2("Specified Docker CMD as %runscript.")
    else:
        bot.verbose2("Specified Docker ENTRYPOINT as %runscript.")

    # Input Parsing ----------------------------
    # Parse image name, repo name, and namespace
    client = DockerApiConnection(image=image, auth=auth)

    docker_image_uri = "Docker image path: %s" % client.assemble_uri("/")
    bot.info(docker_image_uri)

    # IMAGE METADATA -------------------------------------------
    # Use Docker Registry API (version 2.0) to get images ids, manifest

    images = client.get_images()

    #  DOWNLOAD LAYERS -------------------------------------------
    # Each is a .tar.gz file, obtained from registry with curl

    # Get the cache (or temporary one) for docker
    cache_base = get_cache(subfolder="docker")
    download_client = MultiProcess()

    # Generate a queue of tasks to run with MultiProcess
    layers = []
    tasks = []
    for ii in range(len(images)):
        image_id = images[ii]
        targz = "%s/%s.tar.gz" % (cache_base, image_id)
        if not os.path.exists(targz):
            tasks.append((client, image_id, cache_base))
        layers.append(targz)

    # Does the user want to change permissions of tar?
    func2 = None
    if PLUGIN_FIXPERMS:
        func2 = change_permissions

    if len(tasks) > 0:
        download_layers = download_client.run(func=download_layer,
                                              func2=func2,
                                              tasks=tasks)

    # Get Docker runscript
    runscript = extract_runscript(manifest=client.manifestv1,
                                  includecmd=INCLUDE_CMD)

    # Add the environment export
    tar_file = extract_metadata_tar(client.manifestv1,
                                    client.assemble_uri(),
                                    runscript=runscript)

    bot.verbose2('Tar file with Docker env and labels: %s' % tar_file)

    # Write all layers to the layerfile
    if layerfile is not None:
        bot.verbose3("Writing Docker layers files to %s" % layerfile)
        write_file(layerfile, "\n".join(layers), mode="w")
        if tar_file is not None:
            write_file(layerfile, "\n%s" % tar_file, mode="a")

    # Return additions dictionary
    additions = {"layers": layers,
                 "image": image,
                 "manifest": client.manifest,
                 "manifestv1": client.manifestv1,
                 "cache_base": cache_base,
                 "metadata": tar_file}

    bot.debug("*** FINISHING DOCKER IMPORT PYTHON PORTION ****\n")

    return additions
Esempio n. 6
0
def IMPORT(image, auth=None, layerfile=None):
    '''IMPORT is the main script that will obtain docker layers,
    runscript information (either entrypoint or cmd), and environment
    and return a list of tarballs to extract into the image
    :param auth: if needed, an authentication header (default None)
    :param layerfile: The file to write layers to extract into
    '''
    bot.debug("Starting Docker IMPORT, includes env, runscript, and metadata.")
    bot.verbose("Docker image: %s" % image)

    # Does the user want to override default of using ENTRYPOINT?
    if INCLUDE_CMD:
        bot.verbose2("Specified Docker CMD as %runscript.")
    else:
        bot.verbose2("Specified Docker ENTRYPOINT as %runscript.")

    # Input Parsing ----------------------------
    # Parse image name, repo name, and namespace
    client = DockerApiConnection(image=image, auth=auth)

    docker_image_uri = "Docker image path: %s" % client.assemble_uri("/")
    bot.info(docker_image_uri)

    # IMAGE METADATA -------------------------------------------
    # Use Docker Registry API (version 2.0) to get images ids, manifest

    images = client.get_images()

    #  DOWNLOAD LAYERS -------------------------------------------
    # Each is a .tar.gz file, obtained from registry with curl

    # Get the cache (or temporary one) for docker
    cache_base = get_cache(subfolder="docker")
    download_client = MultiProcess()

    # Generate a queue of tasks to run with MultiProcess
    layers = []
    tasks = []
    for ii in range(len(images)):
        image_id = images[ii]
        targz = "%s/%s.tar.gz" % (cache_base, image_id)
        if not os.path.exists(targz):
            tasks.append((client, image_id, cache_base))
        layers.append(targz)

    # Does the user want to change permissions of tar?
    func2 = None
    if PLUGIN_FIXPERMS:
        func2 = change_permissions

    if len(tasks) > 0:
        download_layers = download_client.run(func=download_layer,
                                              func2=func2,
                                              tasks=tasks)

    # Get Docker runscript
    runscript = extract_runscript(manifest=client.manifestv1,
                                  includecmd=INCLUDE_CMD)

    # Add the environment export
    tar_file = extract_metadata_tar(client.manifestv1,
                                    client.assemble_uri(),
                                    runscript=runscript)

    bot.verbose2('Tar file with Docker env and labels: %s' % tar_file)

    # Write all layers to the layerfile
    if layerfile is not None:
        bot.verbose3("Writing Docker layers files to %s" % layerfile)
        write_file(layerfile, "\n".join(layers), mode="w")
        if tar_file is not None:
            write_file(layerfile, "\n%s" % tar_file, mode="a")

    # Return additions dictionary
    additions = {
        "layers": layers,
        "image": image,
        "manifest": client.manifest,
        "manifestv1": client.manifestv1,
        "cache_base": cache_base,
        "metadata": tar_file
    }

    bot.debug("*** FINISHING DOCKER IMPORT PYTHON PORTION ****\n")

    return additions