def test_pull_base_image_with_registry(tmpdir):
    mock_docker()
    source_params = {"provider": "path", "uri": "file://%s" % str(tmpdir), "tmpdir": str(tmpdir)}
    with open(os.path.join(str(tmpdir), DOCKERFILE_FILENAME), "wt") as fp:
        fp.writelines(["FROM %s/namespace/repo:tag\n" % LOCALHOST_REGISTRY])

    s = get_source_instance_for(source_params)
    t = DockerTasker()
    b = InsideBuilder(s, "")
    pulled_tags = b.pull_base_image(LOCALHOST_REGISTRY, insecure=True)
    assert isinstance(pulled_tags, set)
def test_pull_base_image(tmpdir, source_params):
    if MOCK:
        mock_docker()

    source_params.update({"tmpdir": str(tmpdir)})
    s = get_source_instance_for(source_params)
    t = DockerTasker()
    b = InsideBuilder(s, "")
    pulled_tags = b.pull_base_image(LOCALHOST_REGISTRY, insecure=True)
    assert isinstance(pulled_tags, set)
    assert len(pulled_tags) == 2
    for reg_img_name in pulled_tags:
        reg_img_name = ImageName.parse(reg_img_name)
        assert t.inspect_image(reg_img_name) is not None
        assert reg_img_name.repo == git_base_image.repo
        assert reg_img_name.tag == git_base_image.tag
    # clean
    t.remove_image(git_base_image)
Exemple #3
0
class DockerBuildWorkflow(object):
    """
    This class defines a workflow for building images:

    1. pull image from registry
    2. tag it properly if needed
    3. obtain source
    4. build image
    5. tag it
    6. push it to registries
    """

    def __init__(self, source, image, parent_registry=None, target_registries=None,
                 prebuild_plugins=None, prepublish_plugins=None, postbuild_plugins=None,
                 plugin_files=None, parent_registry_insecure=False,
                 target_registries_insecure=False, dont_pull_base_image=False, **kwargs):
        """
        :param source: dict, where/how to get source code to put in image
        :param image: str, tag for built image ([registry/]image_name[:tag])
        :param parent_registry: str, registry to pull base image from
        :param target_registries: list of str, list of registries to push image to (might change in future)
        :param prebuild_plugins: dict, arguments for pre-build plugins
        :param prepublish_plugins: dict, arguments for test-build plugins
        :param postbuild_plugins: dict, arguments for post-build plugins
        :param plugin_files: list of str, load plugins also from these files
        :param parent_registry_insecure: bool, allow connecting to parent registry over plain http
        :param target_registries_insecure: bool, allow connecting to target registries over plain http
        :param dont_pull_base_image: bool, don't pull or update base image specified in dockerfile
        """
        self.source = get_source_instance_for(source, tmpdir=tempfile.mkdtemp())
        self.image = image

        self.parent_registry = parent_registry
        self.parent_registry_insecure = parent_registry_insecure

        self.prebuild_plugins_conf = prebuild_plugins
        self.prepublish_plugins_conf = prepublish_plugins
        self.postbuild_plugins_conf = postbuild_plugins
        self.prebuild_results = {}
        self.postbuild_results = {}
        self.plugin_files = plugin_files

        self.kwargs = kwargs

        self.builder = None
        self.build_logs = None
        self.built_image_inspect = None
        self.base_image_inspect = None

        self.dont_pull_base_image = dont_pull_base_image
        self.pulled_base_images = set()

        # squashed image tarball
        # set by squash plugin
        self.exported_squashed_image = {}

        self.tag_conf = TagConf()
        self.push_conf = PushConf()
        if target_registries:
            self.push_conf.add_docker_registries(target_registries, insecure=target_registries_insecure)

        # mapping of downloaded files; DON'T PUT ANYTHING BIG HERE!
        # "path/to/file" -> "content"
        self.files = {}

        if kwargs:
            logger.warning("unprocessed keyword arguments: %s", kwargs)

    def build_docker_image(self):
        """
        build docker image

        :return: BuildResults
        """
        self.builder = InsideBuilder(self.source, self.image)
        try:
            if not self.dont_pull_base_image:
                self.pulled_base_images = self.builder.pull_base_image(self.parent_registry,
                                                                       insecure=self.parent_registry_insecure)

            self.base_image_inspect = self.builder.tasker.inspect_image(self.builder.base_image)

            # time to run pre-build plugins, so they can access cloned repo,
            # base image
            logger.info("running pre-build plugins")
            prebuild_runner = PreBuildPluginsRunner(self.builder.tasker, self, self.prebuild_plugins_conf,
                                                    plugin_files=self.plugin_files)
            try:
                prebuild_runner.run()
            except PluginFailedException as ex:
                logger.error("one or more prebuild plugins failed: %s", ex)
                return

            build_result = self.builder.build()
            self.build_logs = build_result.logs

            if not build_result.is_failed():
                self.built_image_inspect = self.builder.inspect_built_image()

            # run prepublish plugins
            prepublish_runner = PrePublishPluginsRunner(self.builder.tasker, self, self.prepublish_plugins_conf,
                                                        plugin_files=self.plugin_files)
            try:
                prepublish_runner.run()
            except PluginFailedException as ex:
                logger.error("one or more prepublish plugins failed: %s", ex)
                return

            if not build_result.is_failed():
                for registry in self.push_conf.docker_registries:
                    self.builder.push_built_image(registry.uri,
                                                  insecure=registry.insecure)

            postbuild_runner = PostBuildPluginsRunner(self.builder.tasker, self, self.postbuild_plugins_conf,
                                                      plugin_files=self.plugin_files)
            try:
                postbuild_runner.run()
            except PluginFailedException as ex:
                logger.error("one or more postbuild plugins failed: %s", ex)
                return

            return build_result
        finally:
            self.source.remove_tmpdir()