예제 #1
0
def get_commands_from_history(image_layer):
    '''Given the image layer object and the shell, get the list of command
    objects that created the layer'''
    # set up notice origin for the layer
    origin_layer = 'Layer: ' + image_layer.fs_hash[:10]
    if image_layer.created_by:
        instruction = created_to_instruction(image_layer.created_by)
        image_layer.origins.add_notice_to_origins(
            origin_layer,
            Notice(
                formats.dockerfile_line.format(
                    dockerfile_instruction=instruction), 'info'))
    else:
        image_layer.origins.add_notice_to_origins(
            origin_layer, Notice(formats.no_created_by, 'warning'))
    command_line = instruction.split(' ', 1)[1]
    # Image layers are created with the directives RUN, ADD and COPY
    # For ADD and COPY instructions, there is no information about the
    # packages added
    if 'ADD' in instruction or 'COPY' in instruction:
        image_layer.origins.add_notice_to_origins(
            origin_layer,
            Notice(errors.unknown_content.format(files=command_line),
                   'warning'))
        # return an empty list as we cannot find any commands
        return []
    else:
        # for RUN instructions we can return a list of commands
        command_list, msg = common.filter_install_commands(command_line)
        if msg:
            image_layer.origins.add_notice_to_origins(origin_layer,
                                                      Notice(msg, 'warning'))
        return command_list
예제 #2
0
def get_dockerfile_packages():
    '''Given a Dockerfile return an approximate image object. This is mosty
    guess work and shouldn't be relied on for accurate information. Add
    Notice messages indicating as such:
        1. Create an image with a placeholder repotag
        2. For each RUN command, create a package list
        3. Create layer objects with incremental integers and add the package
        list to that layer with a Notice about parsing
        4. Return stub image'''
    stub_image = Image('easteregg:cookie')
    layer_count = 0
    for inst in docker.docker_commands:
        if inst[0] == 'RUN':
            layer_count = layer_count + 1
            layer = ImageLayer(layer_count)
            install_commands, msg = common.filter_install_commands(inst[1])
            if msg:
                layer.origins.add_notice_to_origins(
                    inst[1], Notice(msg, 'info'))
            pkg_names = []
            for command in install_commands:
                pkg_names.append(common.get_installed_package_names(command))
            for pkg_name in pkg_names:
                pkg = Package(pkg_name)
                # shell parser does not parse version pins yet
                # when that is enabled, Notices for no versions need to be
                # added here
                layer.add_package(pkg)
    return stub_image
예제 #3
0
파일: docker.py 프로젝트: v2d1rkf/tern
def add_packages_from_history(image_obj, shell):
    '''Given a DockerImage object, get package objects installed in each layer
    Assume that the imported images have already gone through this process and
    have their layer's packages populated. So collecting package object occurs
    from the last linked layer:
        1. For each layer get a list of package names
        2. For each package name get a list of dependencies
        3. Create a list of package objects with metadata
        4. Add this to the layer'''
    image_layers = image_obj.layers[image_obj.get_last_import_layer() + 1:]
    logger.debug('Retrieving metadata for remaining {} layers'.format(
        len(image_layers)))
    for layer in image_layers:
        instruction = created_to_instruction(layer.created_by)
        origin_layer = instruction + ' -> ' + layer.diff_id[:10]
        layer.origins.add_notice_origin(origin_layer)
        origin_info = formats.invoke_for_snippets
        layer.origins.add_notice_origin(origin_info)
        if 'RUN' in instruction:
            # for Docker the created_by comes from the instruction in the
            # dockerfile
            run_command_line = instruction.split(' ', 1)[1]
            cmd_list, msg = common.filter_install_commands(run_command_line)
            if msg:
                layer.origins.add_notice_to_origins(origin_info,
                                                    Notice(msg, 'warning'))
            for command in cmd_list:
                origin_cmd = content.print_package_invoke(command.name)
                layer.origins.add_notice_origin(origin_cmd)
                pkg_list = common.get_installed_package_names(command)
                all_pkgs = []
                for pkg_name in pkg_list:
                    pkg_listing = command_lib.get_package_listing(
                        command.name, pkg_name)
                    deps, deps_msg = common.get_package_dependencies(
                        pkg_listing, pkg_name, shell)
                    if deps_msg:
                        logger.warning(deps_msg)
                    all_pkgs.append(pkg_name)
                    all_pkgs.extend(deps)
                unique_pkgs = list(set(all_pkgs))
                for pkg_name in unique_pkgs:
                    pkg = Package(pkg_name)
                    pkg_listing = command_lib.get_package_listing(
                        command.name, pkg_name)
                    common.fill_package_metadata(pkg, pkg_listing, shell)
                    layer.add_package(pkg)