def test_multistage_dockerfiles(name, inherited_user, dockerfile, expect_cleanup_lines,
                                base_from_scratch, tmpdir):
    # expect repo ADD instructions where indicated in the content, and RUN rm at the end.
    # begin by splitting on "### ADD HERE" so we know where to expect changes.
    segments = re.split(r'^.*ADD HERE.*$\n?', dockerfile, flags=re.M)
    segment_lines = [seg.splitlines(True) for seg in segments]

    # build expected contents by manually inserting expected ADD lines between the segments
    for lines in segment_lines[:-1]:
        lines.append("ADD %s* '/etc/yum.repos.d/'\n" % RELATIVE_REPOS_PATH)
    expected_lines = list(itertools.chain.from_iterable(segment_lines))  # flatten lines

    # now run the plugin to transform the given dockerfile
    df = df_parser(str(tmpdir))
    df.content = ''.join(segments)  # dockerfile without the "### ADD HERE" lines
    tasker, workflow = prepare(df.dockerfile_path, inherited_user)
    workflow.builder.set_base_from_scratch(base_from_scratch)
    repo_file = 'myrepo.repo'
    repo_path = os.path.join(YUM_REPOS_DIR, repo_file)
    workflow.files[repo_path] = repocontent
    runner = PreBuildPluginsRunner(tasker, workflow, [{
            'name': InjectYumRepoPlugin.key,
            'args': {}}])
    runner.run()

    # assert the Dockerfile has changed as expected up to the cleanup lines
    new_df = df.lines
    assert new_df[:len(expected_lines)] == expected_lines

    # the rest of the lines should be cleanup lines
    cleanup_lines = new_df[len(expected_lines):]
    assert remove_lines_match(cleanup_lines, expect_cleanup_lines, [repo_file])
def test_add_labels_equal_aliases(tmpdir, docker_tasker, caplog,
                                  base_l, df_l, expected, expected_log,
                                  reactor_config_map):
    if MOCK:
        mock_docker()

    df_content = "FROM fedora\n"
    plugin_labels = {}
    if df_l[0]:
        df_content += 'LABEL description="{0}"\n'.format(df_l[0])
    if df_l[1]:
        df_content += 'LABEL io.k8s.description="{0}"\n'.format(df_l[1])

    base_labels = {INSPECT_CONFIG: {"Labels": {}}}
    if base_l[0]:
        base_labels[INSPECT_CONFIG]["Labels"]["description"] = base_l[0]
    if base_l[1]:
        base_labels[INSPECT_CONFIG]["Labels"]["io.k8s.description"] = base_l[1]

    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X())
    setattr(workflow.builder, 'df_path', df.dockerfile_path)
    setattr(workflow.builder, 'base_image_inspect', base_labels)

    if reactor_config_map:
        make_and_store_reactor_config_map(
            workflow,
            {
                'image_labels': plugin_labels,
                'image_equal_labels': [['description', 'io.k8s.description']]})

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {
                'labels': plugin_labels,
                'dont_overwrite': [],
                'auto_labels': [],
                'aliases': {},
                'equal_labels': [['description', 'io.k8s.description']]
            }
        }]
    )

    runner.run()
    assert AddLabelsPlugin.key is not None
    result_fst = df.labels.get("description") or \
        base_labels[INSPECT_CONFIG]["Labels"].get("description")
    result_snd = df.labels.get("io.k8s.description") or \
        base_labels[INSPECT_CONFIG]["Labels"].get("io.k8s.description")
    assert result_fst == expected[0]
    assert result_snd == expected[1]

    if expected_log:
        assert expected_log in caplog.text
def test_flatpak_create_dockerfile(tmpdir, docker_tasker):
    workflow = mock_workflow(tmpdir)

    args = {
        'base_image': "registry.fedoraproject.org/fedora:latest",
    }

    mmd = ModuleMetadata()
    mmd.loads(FLATPAK_APP_MODULEMD)

    base_module = ModuleInfo(MODULE_NAME, MODULE_STREAM, LATEST_VERSION,
                             mmd, FLATPAK_APP_RPMS)
    repo_url = 'http://odcs.example/composes/latest-odcs-42-1/compose/Temporary/$basearch/os/'
    compose_info = ComposeInfo(MODULE_STREAM + '-' + MODULE_STREAM,
                               42, base_module,
                               {'eog': base_module},
                               repo_url)
    set_compose_info(workflow, compose_info)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': FlatpakCreateDockerfilePlugin.key,
            'args': args
        }]
    )

    runner.run()

    assert os.path.exists(workflow.builder.df_path)
    assert os.path.exists(os.path.join(workflow.builder.df_dir, 'cleanup.sh'))
def test_retry_pull_base_image(exc, failures, should_succeed):
    if MOCK:
        mock_docker(remember_images=True)

    tasker = DockerTasker()
    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = MockBuilder()
    workflow.builder.base_image = ImageName.parse('parent-image')

    class MockResponse(object):
        content = ''

    expectation = flexmock(tasker).should_receive('tag_image')
    for _ in range(failures):
        expectation = expectation.and_raise(exc('', MockResponse()))

    expectation.and_return('foo')
    expectation.and_return('parent-image')

    runner = PreBuildPluginsRunner(
        tasker,
        workflow,
        [{
            'name': PullBaseImagePlugin.key,
            'args': {'parent_registry': 'registry.example.com',
                     'parent_registry_insecure': True},
        }],
    )

    if should_succeed:
        runner.run()
    else:
        with pytest.raises(Exception):
            runner.run()
def test_add_labels_plugin_generated(tmpdir, docker_tasker, auto_label, value_re_part):
    df = df_parser(str(tmpdir))
    df.content = DF_CONTENT

    if MOCK:
        mock_docker()

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X)
    flexmock(workflow, source=MockSource())
    flexmock(workflow, base_image_inspect=LABELS_CONF_BASE)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {'labels': {}, "dont_overwrite": [], "auto_labels": [auto_label],
                     'aliases': {'Build_Host': 'com.redhat.build-host'}}
        }]
    )

    runner.run()
    if value_re_part:
        assert re.match(value_re_part, df.labels[auto_label])

    if auto_label == "build-date":
        utc_dt = datetime.datetime.utcfromtimestamp(atomic_reactor_start_time).isoformat()
        assert df.labels[auto_label] == utc_dt
def test_assertlabels_plugin(tmpdir, df_content, req_labels, expected):
    df = DockerfileParser(str(tmpdir))
    df.content = df_content

    tasker = DockerTasker()
    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    runner = PreBuildPluginsRunner(
        tasker,
        workflow,
        [{
            'name': AssertLabelsPlugin.key,
            'args': {'required_labels': req_labels}
        }]
    )

    assert AssertLabelsPlugin.key is not None

    if isinstance(expected, PluginFailedException):
        with pytest.raises(PluginFailedException):
            runner.run()
    else:
        runner.run()
def test_adddockerfile_nvr_from_labels(tmpdir, docker_tasker):
    df_content = """
FROM fedora
RUN yum install -y python-django
LABEL Name="jboss-eap-6-docker" "Version"="6.4" "Release"=77
CMD blabla"""
    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddDockerfilePlugin.key
        }]
    )
    runner.run()
    assert AddDockerfilePlugin.key is not None

    assert "ADD Dockerfile-jboss-eap-6-docker-6.4-77 /root/buildinfo/Dockerfile-jboss-eap-6-docker-6.4-77" in df.content
def test_returndockerfile_plugin(tmpdir):
    df_content = """
FROM fedora
RUN yum install -y python-django
CMD blabla"""
    df = DockerfileParser(str(tmpdir))
    df.content = df_content

    tasker = DockerTasker()
    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    runner = PreBuildPluginsRunner(
        tasker,
        workflow,
        [{
            'name': CpDockerfilePlugin.key
        }]
    )
    runner.run()
    assert CpDockerfilePlugin.key is not None

    assert workflow.prebuild_results.get(CpDockerfilePlugin.key, "") == df_content
def test_adddockerfile_plugin(tmpdir, docker_tasker):
    df_content = """
FROM fedora
RUN yum install -y python-django
CMD blabla"""
    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddDockerfilePlugin.key,
            'args': {'nvr': 'rhel-server-docker-7.1-20'}
        }]
    )
    runner.run()
    assert AddDockerfilePlugin.key is not None

    expected_output = """
FROM fedora
RUN yum install -y python-django
ADD Dockerfile-rhel-server-docker-7.1-20 /root/buildinfo/Dockerfile-rhel-server-docker-7.1-20
CMD blabla"""
    assert df.content == expected_output
def test_adddockerfile_nvr_from_labels2(tmpdir, docker_tasker):
    df_content = """
FROM fedora
RUN yum install -y python-django
CMD blabla"""
    df = df_parser(str(tmpdir))
    df.content = df_content

    if MOCK:
        mock_docker()

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    flexmock(workflow, base_image_inspect={INSPECT_CONFIG: {"Labels": {}}})
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {'labels': {'Name': 'jboss-eap-6-docker',
                                'Version': '6.4',
                                'Release': '77'},
                     'auto_labels': []}
         },
         {
            'name': AddDockerfilePlugin.key
        }]
    )
    runner.run()
    assert AddDockerfilePlugin.key is not None

    assert "ADD Dockerfile-jboss-eap-6-docker-6.4-77 /root/buildinfo/Dockerfile-jboss-eap-6-docker-6.4-77" in df.content
def test_adddockerfile_todest(tmpdir, docker_tasker):
    df_content = """
FROM fedora
RUN yum install -y python-django
CMD blabla"""
    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddDockerfilePlugin.key,
            'args': {'nvr': 'jboss-eap-6-docker-6.4-77',
                     'destdir': '/usr/share/doc/'}
        }]
    )
    runner.run()
    assert AddDockerfilePlugin.key is not None

    expected_output = """
FROM fedora
RUN yum install -y python-django
ADD Dockerfile-jboss-eap-6-docker-6.4-77 /usr/share/doc/Dockerfile-jboss-eap-6-docker-6.4-77
CMD blabla"""
    assert df.content == expected_output
def test_fetch_maven_artifacts_url_allowed_domains(tmpdir, docker_tasker, domains, raises,
                                                   reactor_config_map):
    """Validate URL domain is allowed when fetching remote file."""
    workflow = mock_workflow(tmpdir)
    mock_koji_session()
    mock_fetch_artifacts_by_url(str(tmpdir))
    mock_url_downloads()

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow, {'artifacts_allowed_domains': domains})

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': FetchMavenArtifactsPlugin.key,
            'args': {
                'koji_hub': KOJI_HUB,
                'koji_root': KOJI_ROOT,
                'allowed_domains': domains,
            }
        }]
    )

    if raises:
        with pytest.raises(PluginFailedException) as e:
            runner.run()
        assert 'is not in list of allowed domains' in str(e)

    else:
        results = runner.run()
        plugin_result = results[FetchMavenArtifactsPlugin.key]
        for download in plugin_result:
            dest = os.path.join(str(tmpdir), FetchMavenArtifactsPlugin.DOWNLOAD_DIR, download.dest)
            assert os.path.exists(dest)
def test_add_labels_plugin_explicit(tmpdir, docker_tasker, auto_label, labels_docker, labels_base):
    df = df_parser(str(tmpdir))
    df.content = labels_docker

    if MOCK:
        mock_docker()

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X)
    flexmock(workflow, source=MockSource())
    flexmock(workflow, base_image_inspect=labels_base)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)

    prov_labels = {}
    prov_labels[auto_label] = 'explicit_value'

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {'labels': prov_labels, "dont_overwrite": [], "auto_labels": [auto_label],
                     'aliases': {'Build_Host': 'com.redhat.build-host'}}
        }]
    )

    runner.run()

    assert df.labels[auto_label] == 'explicit_value'
def test_distgit_fetch_artefacts_failure(tmpdir, docker_tasker):  # noqa
    command = 'fedpkg sources'
    expected_command = ['fedpkg', 'sources']

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X()
    workflow.source = flexmock(path=str(tmpdir))

    initial_dir = os.getcwd()
    assert initial_dir != str(tmpdir)

    (flexmock(pre_pyrpkg_fetch_artefacts.subprocess)
        .should_receive('check_call')
        .with_args(expected_command)
        .and_raise(RuntimeError)
        .once())

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': DistgitFetchArtefactsPlugin.key,
            'args': {'command': command}
        }]
    )
    with pytest.raises(PluginFailedException):
        runner.run()

    assert os.getcwd() == initial_dir
def test_add_labels_plugin(tmpdir, labels_conf_base, labels_conf, dont_overwrite, expected_output):
    df = DockerfileParser(str(tmpdir))
    df.content = DF_CONTENT

    tasker = DockerTasker()
    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X)
    flexmock(workflow, base_image_inspect=labels_conf_base)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)

    runner = PreBuildPluginsRunner(
        tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {'labels': labels_conf, "dont_overwrite": dont_overwrite}
        }]
    )

    if isinstance(expected_output, RuntimeError):
        with pytest.raises(RuntimeError):
            runner.run()
    else:
        runner.run()
        assert AddLabelsPlugin.key is not None
        assert df.content in expected_output
def test_distgit_fetch_artefacts_plugin(tmpdir, docker_tasker):  # noqa
    command = 'fedpkg sources'
    expected_command = ['fedpkg', 'sources']

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X()
    workflow.source = flexmock(path=str(tmpdir))

    initial_dir = os.getcwd()
    assert initial_dir != str(tmpdir)

    def assert_tmpdir(*args, **kwargs):
        assert os.getcwd() == str(tmpdir)

    (flexmock(pre_pyrpkg_fetch_artefacts.subprocess)
        .should_receive('check_call')
        .with_args(expected_command)
        .replace_with(assert_tmpdir)
        .once())

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': DistgitFetchArtefactsPlugin.key,
            'args': {'command': command}
        }]
    )
    runner.run()

    assert os.getcwd() == initial_dir
def test_pull_base_image_plugin(df_base, parent_registry, expected_w_reg, expected_wo_reg):
    if MOCK:
        mock_docker(remember_images=True)

    tasker = DockerTasker()
    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = MockBuilder()
    workflow.builder.base_image = ImageName.parse(df_base)

    assert not tasker.image_exists(BASE_IMAGE)
    assert not tasker.image_exists(BASE_IMAGE_W_REGISTRY)

    runner = PreBuildPluginsRunner(
        tasker,
        workflow,
        [{
            'name': PullBaseImagePlugin.key,
            'args': {'parent_registry': parent_registry, 'parent_registry_insecure': True}
        }]
    )

    runner.run()

    assert tasker.image_exists(BASE_IMAGE) == expected_wo_reg
    assert tasker.image_exists(BASE_IMAGE_W_REGISTRY) == expected_w_reg

    try:
        tasker.remove_image(BASE_IMAGE)
        tasker.remove_image(BASE_IMAGE_W_REGISTRY)
    except:
        pass
def test_yuminject_plugin_notwrapped(tmpdir):
    df_content = """\
FROM fedora
RUN yum install -y python-django
CMD blabla"""
    df = DockerfileParser(str(tmpdir))
    df.content = df_content

    tasker, workflow = prepare(df.dockerfile_path)

    metalink = 'https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=$basearch'

    workflow.files[os.path.join(YUM_REPOS_DIR, DEFAULT_YUM_REPOFILE_NAME)] = render_yum_repo(OrderedDict(
        (('name', 'my-repo'),
         ('metalink', metalink),
         ('enabled', 1),
         ('gpgcheck', 0)),
    ))

    runner = PreBuildPluginsRunner(tasker, workflow, [{
        'name': InjectYumRepoPlugin.key,
        'args': {
            "wrap_commands": False
        }
    }])
    runner.run()
    assert InjectYumRepoPlugin.key is not None

    expected_output = r"""FROM fedora
ADD atomic-reactor-repos/* '/etc/yum.repos.d/'
RUN yum install -y python-django
CMD blabla
RUN rm -f '/etc/yum.repos.d/atomic-reactor-injected.repo'
"""
    assert expected_output == df.content
def test_check_and_set_platforms_no_koji(tmpdir, caplog, platforms, platform_only, result):
    write_container_yaml(tmpdir, platform_only=platform_only)

    tasker, workflow = prepare(tmpdir)

    if platforms:
        set_orchestrator_platforms(workflow, platforms.split())

    build_json = {'metadata': {'labels': {}}}
    flexmock(util).should_receive('get_build_json').and_return(build_json)

    mock_config = MockConfig(platforms)
    flexmock(reactor_config).should_receive('get_config').and_return(mock_config)

    runner = PreBuildPluginsRunner(tasker, workflow, [{
        'name': PLUGIN_CHECK_AND_SET_PLATFORMS_KEY,
    }])

    if platforms:
        plugin_result = runner.run()
        # Build up the message to avoid wrapping
        no_koji_msg = "No koji platforms. "
        platform_msg = "User specified platforms are {0}".format(sorted(platforms.split()))
        user_msg = no_koji_msg + platform_msg
        assert user_msg in caplog.text
        assert plugin_result[PLUGIN_CHECK_AND_SET_PLATFORMS_KEY]
        assert plugin_result[PLUGIN_CHECK_AND_SET_PLATFORMS_KEY] == set(result)
    else:
        with pytest.raises(Exception) as e:
            plugin_result = runner.run()
            assert "no koji target or platform list" in str(e)
    def run_plugin_with_args(self, workflow, plugin_args=None, expect_result=None,
                             expect_error=None):
        plugin_args = plugin_args or {}
        plugin_args.setdefault('odcs_url', ODCS_URL)
        plugin_args.setdefault('koji_target', KOJI_TARGET_NAME)
        plugin_args.setdefault('koji_hub', KOJI_HUB)

        runner = PreBuildPluginsRunner(
            workflow.builder.tasker,
            workflow,
            [
                {'name': ReactorConfigPlugin.key, 'args': {'config_path': str(workflow._tmpdir)}},
                {'name': ResolveComposesPlugin.key, 'args': plugin_args},
            ]
        )

        if expect_error:
            with pytest.raises(PluginFailedException) as exc_info:
                runner.run()
            assert expect_error in str(exc_info.value)
            return

        results = runner.run()[ResolveComposesPlugin.key]
        if results:
            assert len(self.get_override_yum_repourls(workflow)) > 0
            assert set(results.keys()) == set(['signing_intent', 'signing_intent_overridden',
                                               'composes'])
        else:
            assert self.get_override_yum_repourls(workflow) is None
            assert results is None
        return results
def test_add_labels_plugin(tmpdir, docker_tasker,
                           df_content, labels_conf_base, labels_conf, dont_overwrite, aliases,
                           expected_output, caplog):
    df = DockerfileParser(str(tmpdir))
    df.content = df_content

    if MOCK:
        mock_docker()

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X)
    flexmock(workflow, base_image_inspect=labels_conf_base)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {
                'labels': labels_conf,
                'dont_overwrite': dont_overwrite,
                'auto_labels': [],
                'aliases': aliases,
            }
        }]
    )

    runner.run()
    if isinstance(expected_output, RuntimeError):
        assert "plugin 'add_labels_in_dockerfile' raised an exception: RuntimeError" in caplog.text()

    else:
        assert AddLabelsPlugin.key is not None
        assert df.content in expected_output
def test_fetch_maven_artifacts_nvr_no_match(tmpdir, docker_tasker, nvr_requests, error_msg,
                                            reactor_config_map):
    """Err when a requested archive is not found in Koji build."""
    workflow = mock_workflow(tmpdir)
    mock_koji_session()
    mock_fetch_artifacts_by_nvr(str(tmpdir), contents=yaml.safe_dump(nvr_requests))
    mock_nvr_downloads()

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': FetchMavenArtifactsPlugin.key,
            'args': {'koji_hub': KOJI_HUB, 'koji_root': KOJI_ROOT}
        }]
    )

    with pytest.raises(PluginFailedException) as e:
        runner.run()

    assert 'failed to find archives' in str(e)
    assert error_msg in str(e)
def test_fetch_maven_artifacts_nvr_bad_nvr(tmpdir, docker_tasker, reactor_config_map):
    """Err when given nvr is not a valid build in Koji."""
    workflow = mock_workflow(tmpdir)
    mock_koji_session()
    contents = dedent("""\
        - nvr: where-is-this-build-3.0-2
        """)
    mock_fetch_artifacts_by_nvr(str(tmpdir), contents=contents)
    mock_nvr_downloads()

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': FetchMavenArtifactsPlugin.key,
            'args': {'koji_hub': KOJI_HUB, 'koji_root': KOJI_ROOT}
        }]
    )

    with pytest.raises(PluginFailedException) as e:
        runner.run()

    assert 'Build where-is-this-build-3.0-2 not found' in str(e)
Exemple #24
0
    def build_docker_image(self):
        """
        build docker image

        :return: BuildResults
        """
        self.builder = InsideBuilder(self.source, self.image)
        try:
            # time to run pre-build plugins, so they can access cloned repo
            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)
                raise

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

            self.build_failed = build_result.is_failed()

            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)
                raise

            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)
                raise

            return build_result
        finally:
            self.source.remove_tmpdir()

            exit_runner = ExitPluginsRunner(self.builder.tasker, self,
                                            self.exit_plugins_conf,
                                            plugin_files=self.plugin_files)
            try:
                exit_runner.run()
            except PluginFailedException as ex:
                logger.error("one or more exit plugins failed: %s", ex)
def test_no_repourls(inject_proxy):
    tasker, workflow = prepare()
    runner = PreBuildPluginsRunner(tasker, workflow, [{
        'name': AddYumRepoByUrlPlugin.key,
        'args': {'repourls': [], 'inject_proxy': inject_proxy}}])
    runner.run()
    assert AddYumRepoByUrlPlugin.key is not None
    assert workflow.files == {}
def test_add_labels_aliases(tmpdir, docker_tasker, caplog,
                            df_old_as_plugin_arg, df_new_as_plugin_arg,
                            base_old, base_new, df_old, df_new, exp_old, exp_new, exp_log):
    if MOCK:
        mock_docker()

    df_content = "FROM fedora\n"
    plugin_labels = {}
    if df_old:
        if df_old_as_plugin_arg:
            plugin_labels["label_old"] = df_old
        else:
            df_content += 'LABEL label_old="{0}"\n'.format(df_old)
    if df_new:
        if df_new_as_plugin_arg:
            plugin_labels["label_new"] = df_new
        else:
            df_content += 'LABEL label_new="{0}"\n'.format(df_new)

    base_labels = {INSPECT_CONFIG: {"Labels": {}}}
    if base_old:
        base_labels[INSPECT_CONFIG]["Labels"]["label_old"] = base_old
    if base_new:
        base_labels[INSPECT_CONFIG]["Labels"]["label_new"] = base_new

    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X)
    flexmock(workflow, base_image_inspect=base_labels)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {
                'labels': plugin_labels,
                'dont_overwrite': [],
                'auto_labels': [],
                'aliases': {"label_old": "label_new"},
            }
        }]
    )

    runner.run()
    assert AddLabelsPlugin.key is not None
    result_old = df.labels.get("label_old") or \
        base_labels[INSPECT_CONFIG]["Labels"].get("label_old")
    result_new = df.labels.get("label_new") or \
        base_labels[INSPECT_CONFIG]["Labels"].get("label_new")
    assert result_old == exp_old
    assert result_new == exp_new

    if exp_log:
        assert exp_log in caplog.text()
def test_dont_overwrite_if_in_dockerfile(tmpdir, docker_tasker, label_names, dont_overwrite,
                                         parent_val, docker_val, result_val, reactor_config_map):
    default_value = 'default_value'
    df_content = "FROM fedora\n"
    if docker_val:
        for label_name in label_names:
            df_content += 'LABEL {0}="{1}"\n'.format(label_name, docker_val)

    if parent_val:
        labels_conf_base = {INSPECT_CONFIG: {"Labels": {}}}

        for label_name in label_names:
            labels_conf_base[INSPECT_CONFIG]["Labels"][label_name] = parent_val
    else:
        labels_conf_base = {INSPECT_CONFIG: {"Labels": {}}}

    df = df_parser(str(tmpdir))
    df.content = df_content

    if MOCK:
        mock_docker()

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X())
    setattr(workflow.builder, 'df_path', df.dockerfile_path)
    setattr(workflow.builder, 'base_image_inspect', labels_conf_base)

    image_labels = {}
    for label_name in label_names:
        image_labels[label_name] = default_value
    wf_args = {
        'labels': image_labels,
        'auto_labels': [],
        'aliases': {},
    }
    if dont_overwrite:
        wf_args["dont_overwrite_if_in_dockerfile"] = label_names

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow, {'image_labels': image_labels})

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': wf_args
        }]
    )

    runner.run()

    for label_name in label_names:
        result = df.labels.get(label_name)
        assert result == result_val
def test_try_with_library_pull_base_image(library, reactor_config_map):
    if MOCK:
        mock_docker(remember_images=True)

    tasker = DockerTasker(retry_times=0)
    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = MockBuilder()

    if library:
        base_image = 'library/parent-image'
    else:
        base_image = 'parent-image'
    workflow.builder.base_image = ImageName.parse(base_image)
    workflow.builder.parent_images = {ImageName.parse(base_image): None}

    class MockResponse(object):
        content = ''

    cr = CommandResult()
    cr._error = "cmd_error"
    cr._error_detail = {"message": "error_detail"}

    if library:
        call_wait = 1
    else:
        call_wait = 2

    (flexmock(atomic_reactor.util)
        .should_receive('wait_for_command')
        .times(call_wait)
        .and_return(cr))

    error_message = 'registry.example.com/' + base_image

    if reactor_config_map:
        workflow.plugin_workspace[ReactorConfigPlugin.key] = {}
        workflow.plugin_workspace[ReactorConfigPlugin.key][WORKSPACE_CONF_KEY] =\
            ReactorConfig({'version': 1,
                           'source_registry': {'url': 'registry.example.com',
                                               'insecure': True}})

    runner = PreBuildPluginsRunner(
        tasker,
        workflow,
        [{
            'name': PullBaseImagePlugin.key,
            'args': {'parent_registry': 'registry.example.com',
                     'parent_registry_insecure': True},
        }],
    )

    with pytest.raises(PluginFailedException) as exc:
        runner.run()

    assert error_message in exc.value.args[0]
def test_single_repourl():
    tasker, workflow = prepare()
    url = 'http://example.com/example%20repo.repo'
    filename = 'example repo.repo'
    runner = PreBuildPluginsRunner(tasker, workflow, [{
        'name': AddYumRepoByUrlPlugin.key,
        'args': {'repourls': [url]}}])
    runner.run()
    # next(iter(...)) is for py 2/3 compatibility
    assert next(iter(workflow.files.keys())) == os.path.join(YUM_REPOS_DIR, filename)
    assert next(iter(workflow.files.values())) == repocontent
    assert len(workflow.files) == 1
    def run_plugin_with_args(self, workflow, plugin_args=None,
                             expect_error=None, reactor_config_map=False,
                             platforms=ODCS_COMPOSE_DEFAULT_ARCH_LIST, is_pulp=None,
                             check_for_default_id=True):
        plugin_args = plugin_args or {}
        plugin_args.setdefault('odcs_url', ODCS_URL)
        plugin_args.setdefault('koji_target', KOJI_TARGET_NAME)
        plugin_args.setdefault('koji_hub', KOJI_HUB)
        reactor_conf =\
            deepcopy(workflow.plugin_workspace[ReactorConfigPlugin.key][WORKSPACE_CONF_KEY].conf)

        if reactor_config_map:
            reactor_conf['koji'] = {'hub_url': KOJI_HUB, 'root_url': '', 'auth': {}}
            if 'koji_ssl_certs_dir' in plugin_args:
                reactor_conf['koji']['auth']['ssl_certs_dir'] = plugin_args['koji_ssl_certs_dir']
            workflow.plugin_workspace[ReactorConfigPlugin.key][WORKSPACE_CONF_KEY] =\
                ReactorConfig(reactor_conf)

        runner = PreBuildPluginsRunner(
            workflow.builder.tasker,
            workflow,
            [
                {'name': ResolveComposesPlugin.key, 'args': plugin_args},
            ]
        )

        if expect_error:
            with pytest.raises(PluginFailedException) as exc_info:
                runner.run()
            assert expect_error in str(exc_info.value)
            return

        results = runner.run()[ResolveComposesPlugin.key]
        if results:
            for platform in platforms or []:
                yum_repourls = self.get_override_yum_repourls(workflow, platform)
                # Koji tag compose is present in each one
                if check_for_default_id:
                    assert ODCS_COMPOSE['result_repofile'] in yum_repourls
                if is_pulp:
                    pulp_repo = ODCS_COMPOSE_REPO + '/pulp_compose-' + platform
                    assert pulp_repo in yum_repourls
            yum_repourls = self.get_override_yum_repourls(workflow, None)
            if platforms:
                assert yum_repourls is None
            else:
                assert ODCS_COMPOSE['result_repofile'] in yum_repourls
            assert set(results.keys()) == set(['signing_intent', 'signing_intent_overridden',
                                               'composes'])
        else:
            assert self.get_override_yum_repourls(workflow) is None
            assert results is None
        return results
Exemple #31
0
def test_use_check_and_set_platforms_result(tmpdir, docker_tasker,
                                            global_arches, param_arches,
                                            expected_arches):
    """
    global_arches: list of architectures returned by check_and_set_platforms plugin
    param_arches: list of architectures given to add_filesystem plugin as parameter
    """
    if MOCK:
        mock_docker()

    workflow = mock_workflow(tmpdir)
    mock_koji_session(arches=expected_arches)
    mock_image_build_file(str(tmpdir))

    if global_arches:
        workflow.prebuild_results[PLUGIN_CHECK_AND_SET_PLATFORMS_KEY] = set(
            global_arches)

    plugin_args = {}
    if param_arches:
        plugin_args['architectures'] = param_arches

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': PLUGIN_ADD_FILESYSTEM_KEY,
                                       'args': plugin_args
                                   }])

    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]
    assert 'base-image-id' in plugin_result
    assert plugin_result['base-image-id'] is None
    assert 'filesystem-koji-task-id' in plugin_result
Exemple #32
0
def test_add_filesystem_plugin_legacy(tmpdir, docker_tasker, scratch,
                                      reactor_config_map):
    if MOCK:
        mock_docker()

    workflow = mock_workflow(tmpdir)
    mock_koji_session(scratch=scratch)
    mock_image_build_file(str(tmpdir))

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow, {
            'root_url': '',
            'auth': {}
        })

    runner = PreBuildPluginsRunner(docker_tasker, workflow, [{
        'name': PLUGIN_ADD_FILESYSTEM_KEY,
        'args': {
            'koji_hub': KOJI_HUB,
        }
    }])

    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]
    assert 'base-image-id' in plugin_result
    assert plugin_result['base-image-id'] == IMPORTED_IMAGE_ID
    assert 'filesystem-koji-task-id' in plugin_result
Exemple #33
0
def test_image_task_failure(tmpdir, raise_error):
    if MOCK:
        mock_docker()

    dockerfile = dedent("""\
        FROM koji/image-build
        RUN dnf install -y python-django
        """)

    task_result = 'task-result'

    def _mockGetTaskResult(task_id):
        if raise_error:
            raise RuntimeError(task_result)
        return task_result

    workflow = mock_workflow(tmpdir, dockerfile)
    mock_koji_session(image_task_fail=True,
                      get_task_result_mock=_mockGetTaskResult)
    mock_image_build_file(str(tmpdir))

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': AddFilesystemPlugin.key,
                                       'args': {
                                           'koji_hub': KOJI_HUB
                                       }
                                   }])

    with pytest.raises(PluginFailedException) as exc:
        results = runner.run()
    assert task_result in str(exc)
    # Also ensure getTaskResult exception message is wrapped properly
    assert 'image task,' in str(exc)
Exemple #34
0
def test_add_filesystem_plugin_generated(tmpdir, docker_tasker, scratch):
    if MOCK:
        mock_docker()

    dockerfile = dedent("""\
        FROM koji/image-build
        RUN dnf install -y python-django
        """)
    workflow = mock_workflow(tmpdir, dockerfile)
    mock_koji_session(scratch=scratch)
    mock_image_build_file(str(tmpdir))

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': AddFilesystemPlugin.key,
                                       'args': {
                                           'koji_hub': KOJI_HUB
                                       }
                                   }])

    results = runner.run()
    plugin_result = results[AddFilesystemPlugin.key]
    assert 'base-image-id' in plugin_result
    assert plugin_result['base-image-id'] == IMPORTED_IMAGE_ID
    assert 'filesystem-koji-task-id' in plugin_result
def test_add_filesystem_plugin_legacy(workflow, build_dir, scratch, caplog):
    mock_workflow(workflow, build_dir, scratch=scratch)
    workflow.data.prebuild_results[PLUGIN_RESOLVE_COMPOSES_KEY] = {
        'composes': []
    }
    mock_koji_session(scratch=scratch)
    mock_image_build_file(workflow)
    image_name = 'fedora-23-1.0.x86_64.tar.gz'
    expected_dockerfile_content = dedent(f"""\
        FROM scratch
        ADD {image_name} /
        RUN dnf install -y python-django
    """)

    make_and_store_reactor_config_map(workflow, {'root_url': '', 'auth': {}})

    runner = PreBuildPluginsRunner(workflow, [{
        'name': PLUGIN_ADD_FILESYSTEM_KEY,
        'args': {}
    }])

    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]
    assert 'filesystem-koji-task-id' in plugin_result
    assert workflow.data.labels[
        'filesystem-koji-task-id'] == FILESYSTEM_TASK_ID
    msg = f'added "{image_name}" as image filesystem'
    assert msg in caplog.text
    assert workflow.build_dir.any_platform.dockerfile.content == expected_dockerfile_content
Exemple #36
0
def test_no_base_image_in_dockerfile(tmpdir):
    dockerfile = tmpdir.join('Dockerfile')
    dockerfile.write_text('', encoding='utf8')

    tasker, workflow = prepare(str(dockerfile))
    workflow.files = {'/etc/yum.repos.d/foo.repo': 'repo'}

    runner = PreBuildPluginsRunner(tasker, workflow,
                                   [{
                                       'name': InjectYumRepoPlugin.key,
                                       'args': {},
                                   }])

    with pytest.raises(PluginFailedException) as exc:
        runner.run()
    assert "No FROM line in Dockerfile" in str(exc.value)
Exemple #37
0
def test_image_download(tmpdir, docker_tasker, architecture, architectures,
                        download_filesystem):
    if MOCK:
        mock_docker()

    dockerfile = dedent("""\
        FROM koji/image-build
        RUN dnf install -y python-django
        """)

    workflow = mock_workflow(tmpdir, dockerfile)
    mock_koji_session(download_filesystem=download_filesystem)
    mock_image_build_file(str(tmpdir))

    runner = PreBuildPluginsRunner(docker_tasker, workflow, [{
        'name': PLUGIN_ADD_FILESYSTEM_KEY,
        'args': {
            'koji_hub': KOJI_HUB,
            'architecture': architecture,
            'architectures': architectures,
        }
    }])

    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]

    assert 'base-image-id' in plugin_result
    assert 'filesystem-koji-task-id' in plugin_result

    if download_filesystem:
        assert plugin_result['base-image-id'] == IMPORTED_IMAGE_ID
        assert plugin_result['filesystem-koji-task-id'] == FILESYSTEM_TASK_ID
    else:
        assert plugin_result['base-image-id'] is None
        assert plugin_result['filesystem-koji-task-id'] is None
def test_no_repourls(tmpdir):
    for df_content in DOCKERFILES.values():
        df = df_parser(str(tmpdir))
        df.lines = df_content.lines_before_add + df_content.lines_before_remove

        tasker, workflow = prepare(df.dockerfile_path,
                                   df_content.inherited_user)
        runner = PreBuildPluginsRunner(tasker, workflow,
                                       [{
                                           'name': InjectYumRepoPlugin.key,
                                       }])
        runner.run()
        assert InjectYumRepoPlugin.key is not None

        # Should be unchanged.
        assert df.lines == df_content.lines_before_add + df_content.lines_before_remove
    def run_plugin_with_args(self, workflow, plugin_args=None, expect_result=True,  # noqa
                             reactor_config_map=False):
        plugin_args = plugin_args or {}
        plugin_args.setdefault('koji_hub', KOJI_HUB)
        plugin_args.setdefault('poll_interval', 0.01)
        plugin_args.setdefault('poll_timeout', 1)

        if reactor_config_map:

            koji_map = {
                'hub_url': KOJI_HUB,
                'root_url': '',
                'auth': {}
            }
            if 'koji_ssl_certs_dir' in plugin_args:
                koji_map['auth']['ssl_certs_dir'] = plugin_args['koji_ssl_certs_dir']
            workflow.plugin_workspace[ReactorConfigPlugin.key] = {}
            workflow.plugin_workspace[ReactorConfigPlugin.key][WORKSPACE_CONF_KEY] =\
                ReactorConfig({'version': 1, 'koji': koji_map})

        runner = PreBuildPluginsRunner(
            workflow.builder.tasker,
            workflow,
            [{'name': KojiParentPlugin.key, 'args': plugin_args}]
        )

        result = runner.run()
        if expect_result is True:
            expected_result = {BASE_IMAGE_KOJI_BUILD: KOJI_BUILD}
        elif expect_result is False:
            expected_result = None
        else:  # param provided the expected result
            expected_result = expect_result

        assert result[KojiParentPlugin.key] == expected_result
def test_platforms_from_cluster_config(tmpdir, platforms, platform_only,
                                       cluster_platforms, result):
    write_container_yaml(tmpdir, platform_only=platform_only)

    tasker, workflow = prepare(tmpdir)

    if platforms:
        set_orchestrator_platforms(workflow, platforms.split())

    build_json = {'metadata': {'labels': {}}}
    flexmock(util).should_receive('get_build_json').and_return(build_json)

    mock_config = MockConfig(cluster_platforms)
    flexmock(reactor_config).should_receive('get_config').and_return(
        mock_config)

    runner = PreBuildPluginsRunner(
        tasker, workflow, [{
            'name': PLUGIN_CHECK_AND_SET_PLATFORMS_KEY,
        }])

    plugin_result = runner.run()
    if platforms:
        assert plugin_result[PLUGIN_CHECK_AND_SET_PLATFORMS_KEY]
        assert plugin_result[PLUGIN_CHECK_AND_SET_PLATFORMS_KEY] == set(result)
    else:
        assert plugin_result[PLUGIN_CHECK_AND_SET_PLATFORMS_KEY] is None
Exemple #41
0
def test_add_filesystem_plugin_generated(tmpdir, docker_tasker, scratch,
                                         reactor_config_map):
    if MOCK:
        mock_docker()

    workflow = mock_workflow(tmpdir, scratch=scratch)
    task_id = FILESYSTEM_TASK_ID
    mock_koji_session(scratch=scratch)
    mock_image_build_file(str(tmpdir))

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow, {
            'root_url': '',
            'auth': {}
        })

    runner = PreBuildPluginsRunner(docker_tasker, workflow, [{
        'name': PLUGIN_ADD_FILESYSTEM_KEY,
        'args': {
            'koji_hub': KOJI_HUB,
            'from_task_id': task_id,
            'architecture': 'x86_64'
        }
    }])

    expected_results = {
        'base-image-id': IMPORTED_IMAGE_ID,
        'filesystem-koji-task-id': FILESYSTEM_TASK_ID,
    }
    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]
    assert 'base-image-id' in plugin_result
    assert 'filesystem-koji-task-id' in plugin_result
    assert plugin_result == expected_results
def test_add_help_no_help_file(request, tmpdir, docker_tasker, filename):
    df_content = "FROM fedora"
    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': AddHelpPlugin.key,
                                       'args': {
                                           'help_file': filename
                                       }
                                   }])
    # Runner should not crash if no help.md found
    result = runner.run()
    assert result == {
        'add_help': {
            'status': AddHelpPlugin.NO_HELP_FILE_FOUND,
            'help_file': filename
        }
    }
def test_add_filesystem_plugin_generated(workflow, build_dir, scratch,
                                         dockerfile, expected_dockerfile,
                                         caplog):
    mock_workflow(workflow, build_dir, scratch=scratch, dockerfile=dockerfile)
    mock_koji_session(scratch=scratch)
    mock_image_build_file(workflow)
    image_name = 'fedora-23-1.0.x86_64.tar.gz'
    expected_dockerfile = expected_dockerfile.replace(
        'ADD {} {}\n', f'ADD {image_name} '
        '/\n')

    make_and_store_reactor_config_map(workflow, {'root_url': '', 'auth': {}})

    runner = PreBuildPluginsRunner(workflow, [{
        'name': PLUGIN_ADD_FILESYSTEM_KEY,
        'args': {}
    }])

    expected_results = {
        'filesystem-koji-task-id': FILESYSTEM_TASK_ID,
    }

    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]
    assert 'filesystem-koji-task-id' in plugin_result
    assert plugin_result == expected_results
    assert workflow.data.labels[
        'filesystem-koji-task-id'] == FILESYSTEM_TASK_ID
    msg = f'added "{image_name}" as image filesystem'
    assert msg in caplog.text
    assert workflow.build_dir.any_platform.dockerfile.content == expected_dockerfile
Exemple #44
0
def test_add_filesystem_plugin_generated(tmpdir, docker_tasker, scratch):
    if MOCK:
        mock_docker()

    dockerfile = dedent("""\
        FROM koji/image-build
        RUN dnf install -y python-django
        """)
    workflow = mock_workflow(tmpdir, dockerfile)
    task_id = FILESYSTEM_TASK_ID
    mock_koji_session(scratch=scratch)
    mock_image_build_file(str(tmpdir))

    runner = PreBuildPluginsRunner(docker_tasker, workflow, [{
        'name': PLUGIN_ADD_FILESYSTEM_KEY,
        'args': {
            'koji_hub': KOJI_HUB,
            'from_task_id': task_id,
            'architecture': 'x86_64'
        }
    }])

    expected_results = {
        'base-image-id': IMPORTED_IMAGE_ID,
        'filesystem-koji-task-id': FILESYSTEM_TASK_ID,
    }
    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]
    assert 'base-image-id' in plugin_result
    assert 'filesystem-koji-task-id' in plugin_result
    assert plugin_result == expected_results
    def run_plugin_with_args(
            self,
            workflow,
            plugin_args=None,
            reactor_config_map=False,  # noqa
            organization=None,
            base_from_scratch=False,
            custom_base_image=False):
        plugin_args = plugin_args or {}
        plugin_args.setdefault('koji_parent_build', KOJI_BUILD_ID)
        plugin_args.setdefault('koji_hub', KOJI_HUB)

        if reactor_config_map:
            koji_map = {'hub_url': KOJI_HUB, 'root_url': '', 'auth': {}}
            if 'koji_ssl_certs_dir' in plugin_args:
                koji_map['auth']['ssl_certs_dir'] = plugin_args[
                    'koji_ssl_certs_dir']
            workflow.plugin_workspace[ReactorConfigPlugin.key] = {}
            workflow.plugin_workspace[ReactorConfigPlugin.key][WORKSPACE_CONF_KEY] =\
                ReactorConfig({'version': 1, 'koji': koji_map,
                               'registries_organization': organization})

        runner = PreBuildPluginsRunner(workflow.builder.tasker, workflow,
                                       [{
                                           'name': InjectParentImage.key,
                                           'args': plugin_args
                                       }])

        result = runner.run()
        if base_from_scratch or custom_base_image:
            assert result[InjectParentImage.key] is None
        else:
            # Koji build ID is always used, even when NVR is given.
            assert result[InjectParentImage.key] == KOJI_BUILD_ID
            self.assert_images_to_remove(workflow)
Exemple #46
0
def test_fetch_maven_artifacts_nvr_filtering(tmpdir, docker_tasker, nvr_requests, expected):
    """Test filtering of archives in a Koji build."""
    workflow = mock_workflow(tmpdir)
    mock_koji_session()
    mock_fetch_artifacts_by_nvr(str(tmpdir), contents=yaml.safe_dump(nvr_requests))
    mock_nvr_downloads(archives=expected)
    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': FetchMavenArtifactsPlugin.key,
            'args': {'koji_hub': KOJI_HUB, 'koji_root': KOJI_ROOT}
        }]
    )

    results = runner.run()
    plugin_result = results[FetchMavenArtifactsPlugin.key]

    assert len(plugin_result) == len(expected)
    for download in plugin_result:
        assert len(download.checksums.values()) == 1
    assert (set(list(download.checksums.values())[0] for download in plugin_result) ==
            set(expectation['checksum'] for expectation in expected))
    for download in plugin_result:
        dest = os.path.join(str(tmpdir), FetchMavenArtifactsPlugin.DOWNLOAD_DIR, download.dest)
        assert os.path.exists(dest)
Exemple #47
0
def test_fetch_maven_artifacts_url_with_target(tmpdir, docker_tasker):
    """Remote file is downloaded into specified filename."""
    workflow = mock_workflow(tmpdir)
    mock_koji_session()
    remote_files = [REMOTE_FILE_WITH_TARGET]
    mock_fetch_artifacts_by_url(str(tmpdir), contents=yaml.safe_dump(remote_files))
    mock_url_downloads(remote_files)
    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': FetchMavenArtifactsPlugin.key,
            'args': {'koji_hub': KOJI_HUB, 'koji_root': KOJI_ROOT}
        }]
    )

    results = runner.run()
    plugin_result = results[FetchMavenArtifactsPlugin.key]

    assert len(plugin_result) == len(remote_files)

    download = plugin_result[0]
    dest = os.path.join(str(tmpdir), FetchMavenArtifactsPlugin.DOWNLOAD_DIR, download.dest)
    assert os.path.exists(dest)
    assert download.dest == REMOTE_FILE_WITH_TARGET['target']
    assert not REMOTE_FILE_WITH_TARGET['url'].endswith(download.dest)
Exemple #48
0
def test_fetch_maven_artifacts(tmpdir, docker_tasker, reactor_config_map):
    workflow = mock_workflow(tmpdir)
    mock_koji_session()
    mock_fetch_artifacts_by_nvr(str(tmpdir))
    mock_fetch_artifacts_by_url(str(tmpdir))
    mock_nvr_downloads()
    mock_url_downloads()

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow)

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': FetchMavenArtifactsPlugin.key,
                                       'args': {
                                           'koji_hub': KOJI_HUB,
                                           'koji_root': KOJI_ROOT
                                       }
                                   }])

    results = runner.run()
    plugin_result = results[FetchMavenArtifactsPlugin.key]

    assert len(
        plugin_result) == len(DEFAULT_ARCHIVES) + len(DEFAULT_REMOTE_FILES)
    for download in plugin_result:
        dest = os.path.join(str(tmpdir),
                            FetchMavenArtifactsPlugin.DOWNLOAD_DIR,
                            download.dest)
        assert os.path.exists(dest)
Exemple #49
0
def test_add_labels_plugin(tmpdir, docker_tasker, df_content, labels_conf_base,
                           labels_conf, eq_conf, dont_overwrite, aliases,
                           expected_output, caplog, reactor_config_map):
    df = df_parser(str(tmpdir))
    df.content = df_content

    if MOCK:
        mock_docker()

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)
    setattr(workflow.builder, 'base_image_inspect', labels_conf_base)

    if reactor_config_map:
        # reactor_config should not return json
        if isinstance(labels_conf, str):
            image_labels = json.loads(labels_conf)
        else:
            image_labels = deepcopy(labels_conf)
        make_and_store_reactor_config_map(workflow, {
            'image_labels': image_labels,
            'image_equal_labels': eq_conf,
        })

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': AddLabelsPlugin.key,
                                       'args': {
                                           'labels': labels_conf,
                                           'dont_overwrite': dont_overwrite,
                                           'auto_labels': [],
                                           'aliases': aliases,
                                           'equal_labels': eq_conf,
                                       }
                                   }])

    if isinstance(expected_output, RuntimeError):
        with pytest.raises(PluginFailedException):
            runner.run()
        assert "plugin 'add_labels_in_dockerfile' raised an exception: RuntimeError" \
            in caplog.text()

    else:
        runner.run()
        assert AddLabelsPlugin.key is not None
        assert df.content in expected_output
def test_add_help_plugin(tmpdir, docker_tasker, filename):
    df_content = dedent("""
        FROM fedora
        RUN yum install -y python-django
        CMD blabla""")
    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = X
    workflow.builder.df_path = df.dockerfile_path
    workflow.builder.df_dir = str(tmpdir)

    help_markdown_path = os.path.join(workflow.builder.df_dir, filename)
    generate_a_file(help_markdown_path, "foo")
    help_man_path = os.path.join(workflow.builder.df_dir,
                                 AddHelpPlugin.man_filename)
    generate_a_file(help_man_path, "bar")

    cmd = [
        'go-md2man', '-in={}'.format(help_markdown_path),
        '-out={}'.format(help_man_path)
    ]

    def check_popen(*args, **kwargs):
        assert args[0] == cmd
        return MockedPopen()

    (flexmock(subprocess).should_receive("Popen").once().replace_with(
        check_popen))

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': AddHelpPlugin.key,
                                       'args': {
                                           'help_file': filename
                                       }
                                   }])
    runner.run()

    assert df.content == dedent(
        """
        FROM fedora
        RUN yum install -y python-django
        ADD %s /%s
        CMD blabla""" %
        (AddHelpPlugin.man_filename, AddHelpPlugin.man_filename))
Exemple #51
0
def test_try_with_library_pull_base_image(library):
    if MOCK:
        mock_docker(remember_images=True)

    tasker = DockerTasker(retry_times=0)
    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    workflow.builder = MockBuilder()

    if library:
        base_image = 'library/parent-image'
    else:
        base_image = 'parent-image'
    workflow.builder.base_image = ImageName.parse(base_image)

    class MockResponse(object):
        content = ''

    cr = CommandResult()
    cr._error = "cmd_error"
    cr._error_detail = {"message": "error_detail"}

    if library:
        call_wait = 1
    else:
        call_wait = 2

    (flexmock(atomic_reactor.util)
        .should_receive('wait_for_command')
        .times(call_wait)
        .and_return(cr))

    error_message = 'registry.example.com/' + base_image

    runner = PreBuildPluginsRunner(
        tasker,
        workflow,
        [{
            'name': PullBaseImagePlugin.key,
            'args': {'parent_registry': 'registry.example.com',
                     'parent_registry_insecure': True},
        }],
    )

    with pytest.raises(PluginFailedException) as exc:
        runner.run()

    assert error_message in exc.value.args[0]
Exemple #52
0
def test_add_labels_arrangement6(tmpdir, docker_tasker, workflow, release, use_reactor):
    # explicitly test arrangement 6's handling of reactor config
    df = df_parser(str(tmpdir))
    df.content = DF_CONTENT

    if MOCK:
        mock_docker()

    setattr(workflow, 'builder', X())
    setattr(workflow.builder, 'base_image_inspect', LABELS_CONF_BASE)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)
    flexmock(workflow, source=MockSource())

    if use_reactor:
        make_and_store_reactor_config_map(workflow, {'image_labels': LABELS_CONF})
        if release is not None:
            labels = {'release': release}
        else:
            labels = None
    else:
        labels = LABELS_CONF
        if release is not None:
            labels.update({'release': release})

    runner = PreBuildPluginsRunner(
        docker_tasker,
        workflow,
        [{
            'name': AddLabelsPlugin.key,
            'args': {
                'labels': labels,
                'dont_overwrite': [],
                'auto_labels': [],
                'aliases': [],
                'equal_labels': [],
            }
        }]
    )

    runner.run()
    assert AddLabelsPlugin.key is not None
    assert 'label1' in df.content
    if release:
        assert 'release' in df.content
        assert release in df.content
    else:
        assert 'release' not in df.content
Exemple #53
0
def test_single_repourl(tmpdir):
    for df_content in DOCKERFILES.values():
        df = df_parser(str(tmpdir))
        df.lines = df_content.lines_before_add + df_content.lines_before_remove
        tasker, workflow = prepare(df.dockerfile_path,
                                   df_content.inherited_user)
        filename = 'test-ccece.repo'
        unique_filename = 'test-ccece.repo'
        repo_path = os.path.join(YUM_REPOS_DIR, filename)
        workflow.files[repo_path] = repocontent
        runner = PreBuildPluginsRunner(tasker, workflow, [{
                'name': InjectYumRepoPlugin.key,
                'args': {}}])
        runner.run()

        # Was it written correctly?
        repos_dir = os.path.join(str(tmpdir), RELATIVE_REPOS_PATH)
        repofile = os.path.join(repos_dir, unique_filename)
        with open(repofile, "r") as fp:
            assert fp.read() == repocontent

        # Remove the repos/ directory.
        os.remove(repofile)
        os.rmdir(repos_dir)

        # Examine the Dockerfile.
        newdf = df.lines
        before_add = len(df_content.lines_before_add)
        before_remove = len(df_content.lines_before_remove)

        # Start of file should be unchanged.
        assert newdf[:before_add] == df_content.lines_before_add

        # Should see a single add line.
        after_add = before_add + 1
        assert (newdf[before_add:after_add] ==
                ["ADD %s* '/etc/yum.repos.d/'\n" % RELATIVE_REPOS_PATH])

        # Lines from there up to the remove line should be unchanged.
        before_remove = after_add + len(df_content.lines_before_remove)
        assert (newdf[after_add:before_remove] ==
                df_content.lines_before_remove)

        # The 'rm' lines should match
        # There should be a final 'rm'
        remove = newdf[before_remove:]
        assert remove_lines_match(remove, df_content.remove_lines, [filename])
Exemple #54
0
def test_adddockerfile_fails(tmpdir, docker_tasker, caplog):  # noqa
    df_content = """
FROM fedora
RUN yum install -y python-django
CMD blabla"""
    df = df_parser(str(tmpdir))
    df.content = df_content

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    prepare(workflow, df.dockerfile_path)

    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       'name': AddDockerfilePlugin.key
                                   }])
    runner.run()
    assert "plugin 'add_dockerfile' raised an exception: ValueError" in caplog.text
Exemple #55
0
def test_add_labels_base_image(tmpdir, docker_tasker, parent, should_fail,
                               caplog, reactor_config_map):
    df = df_parser(str(tmpdir))
    df.content = "FROM {}\n".format(parent)

    if MOCK:
        mock_docker()

    workflow = DockerBuildWorkflow(MOCK_SOURCE, 'test-image')
    setattr(workflow, 'builder', X)
    flexmock(workflow, source=MockSource())
    setattr(workflow.builder, 'tasker', docker_tasker)
    setattr(workflow.builder, 'df_path', df.dockerfile_path)
    setattr(workflow.builder, 'base_image_inspect', {})

    # When a 'release' label is provided by parameter and used to
    # configure the plugin, it should be set in the Dockerfile even
    # when processing base images.
    prov_labels = {'release': '5'}

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow,
                                          {'image_labels': prov_labels})

    runner = PreBuildPluginsRunner(
        docker_tasker, workflow, [{
            'name': AddLabelsPlugin.key,
            'args': {
                'labels': prov_labels,
                "dont_overwrite": [],
                'aliases': {
                    'Build_Host': 'com.redhat.build-host'
                }
            }
        }])

    if should_fail:
        with caplog.atLevel(logging.ERROR):
            with pytest.raises(PluginFailedException):
                runner.run()

        msg = "base image was not inspected"
        assert msg in [x.message for x in caplog.records()]
    else:
        runner.run()
        assert df.labels['release'] == '5'
Exemple #56
0
def test_koji_plugin():
    tasker, workflow = prepare()
    runner = PreBuildPluginsRunner(tasker, workflow, [{
        'name': KojiPlugin.key,
        'args': {
            "target": KOJI_TARGET,
            "hub": "",
            "root": ROOT,
        }
    }])
    runner.run()
    assert list(workflow.files.keys())[0] == "/etc/yum.repos.d/target.repo"
    assert list(workflow.files.values())[0].startswith("[atomic-reactor-koji-plugin-target]\n")
    assert "gpgcheck=0\n" in list(workflow.files.values())[0]
    assert "enabled=1\n" in list(workflow.files.values())[0]
    assert "name=atomic-reactor-koji-plugin-target\n" in list(workflow.files.values())[0]
    assert "baseurl=http://example.com/repos/tag/2/$basearch\n" in list(workflow.files.values())[0]
Exemple #57
0
def test_single_repourl():
    tasker, workflow = prepare()
    url = 'http://example.com/example%20repo.repo'
    filename = 'example repo.repo'
    runner = PreBuildPluginsRunner(tasker, workflow,
                                   [{
                                       'name': AddYumRepoByUrlPlugin.key,
                                       'args': {
                                           'repourls': [url]
                                       }
                                   }])
    runner.run()
    # next(iter(...)) is for py 2/3 compatibility
    assert next(iter(workflow.files.keys())) == os.path.join(
        YUM_REPOS_DIR, filename)
    assert next(iter(workflow.files.values())) == repocontent
    assert len(workflow.files) == 1
Exemple #58
0
def test_non_buildstep_phase_raises_InappropriateBuildStepError(
        caplog, tmpdir, docker_tasker):  # noqa
    """
    tests that exception is raised if no buildstep_phase
    but raises InappropriateBuildStepError
    """
    workflow = mock_workflow(tmpdir)
    flexmock(PluginsRunner,
             load_plugins=lambda x: {MyPreBuildPlugin.key: MyPreBuildPlugin})
    runner = PreBuildPluginsRunner(docker_tasker, workflow,
                                   [{
                                       "name": MyPreBuildPlugin.key
                                   }])

    #    flexmock(MyBsPlugin1).should_call('run').and_raise(InappropriateBuildStepError).once()
    with pytest.raises(Exception):
        runner.run()
Exemple #59
0
def test_image_download(tmpdir, docker_tasker, parents, skip_plugin,
                        architecture, architectures, download_filesystem,
                        reactor_config_map, caplog):
    if MOCK:
        mock_docker()

    workflow = mock_workflow(tmpdir,
                             for_orchestrator=architectures is not None)
    if not skip_plugin:
        mock_koji_session(download_filesystem=download_filesystem)
    mock_image_build_file(str(tmpdir))

    workflow.builder.base_image = ImageName.parse(parents[-1])
    workflow.builder.parents_ordered = parents
    workflow.builder.custom_parent_image = 'koji/image-build' in parents
    workflow.builder.custom_base_image = 'koji/image-build' == parents[-1]
    workflow.builder.parent_images = {}
    for image in parents:
        if image == 'scratch':
            continue
        workflow.builder.parent_images[ImageName.parse(image)] = None

    if architectures:
        workflow.prebuild_results[PLUGIN_CHECK_AND_SET_PLATFORMS_KEY] = set(
            architectures)

    if reactor_config_map:
        make_and_store_reactor_config_map(workflow, {
            'root_url': '',
            'auth': {}
        })

    runner = PreBuildPluginsRunner(docker_tasker, workflow, [{
        'name': PLUGIN_ADD_FILESYSTEM_KEY,
        'args': {
            'koji_hub': KOJI_HUB,
            'architecture': architecture,
        }
    }])

    results = runner.run()
    plugin_result = results[PLUGIN_ADD_FILESYSTEM_KEY]

    if skip_plugin:
        message = 'Nothing to do for non-custom base images'
        assert message in caplog.text
        assert plugin_result is None
        return

    assert 'base-image-id' in plugin_result
    assert 'filesystem-koji-task-id' in plugin_result

    if download_filesystem:
        assert plugin_result['base-image-id'] == IMPORTED_IMAGE_ID
        assert plugin_result['filesystem-koji-task-id'] == FILESYSTEM_TASK_ID
    else:
        assert plugin_result['base-image-id'] is None
        assert plugin_result['filesystem-koji-task-id'] is None
Exemple #60
0
def test_flatpak_create_dockerfile(tmpdir, docker_tasker, config_name,
                                   breakage):
    config = CONFIGS[config_name]

    workflow = mock_workflow(tmpdir, config['container_yaml'])

    compose = setup_flatpak_compose_info(workflow, config)

    if breakage == 'branch_mismatch':
        compose.base_module.mmd.xmd['flatpak']['branch'] = 'MISMATCH'
        expected_exception = "Mismatch for 'branch'"
    else:
        assert breakage is None
        expected_exception = None

    args = {
        'base_image': "registry.fedoraproject.org/fedora:latest",
    }

    runner = PreBuildPluginsRunner(
        docker_tasker, workflow, [{
            'name': FlatpakCreateDockerfilePlugin.key,
            'args': args
        }])

    if expected_exception:
        with pytest.raises(PluginFailedException) as ex:
            runner.run()
        assert expected_exception in str(ex)
    else:
        runner.run()

        assert os.path.exists(workflow.builder.df_path)

        includepkgs_path = os.path.join(workflow.builder.df_dir,
                                        'atomic-reactor-includepkgs')
        assert os.path.exists(includepkgs_path)
        with open(includepkgs_path) as f:
            includepkgs = f.read()
            assert 'librsvg2' in includepkgs
            if config_name == 'app':
                assert 'eog-0:3.24.1-1.module_7b96ed10.x86_64' in includepkgs

        assert os.path.exists(
            os.path.join(workflow.builder.df_dir, 'cleanup.sh'))