Ejemplo n.º 1
0
    def test_pull_push_vs_sync(self, push, sync):
        workflow = self.workflow(push=push, sync=sync)
        tasker = MockerTasker()

        test_id = 'sha256:(new)'

        getter = self.custom_get_v1

        if sync:
            (flexmock(requests.Session)
                .should_receive('get')
                .replace_with(getter))
        else:
            (flexmock(requests.Session)
                .should_receive('get')
                .never())

        (flexmock(tasker)
            .should_call('pull_image')
            .with_args(self.EXPECTED_IMAGE, insecure=False)
            .and_return(self.EXPECTED_PULLSPEC)
            .ordered())

        (flexmock(tasker)
            .should_receive('inspect_image')
            .with_args(self.EXPECTED_PULLSPEC)
            .and_return({'Id': test_id}))

        workflow.postbuild_plugins_conf = []

        plugin = PulpPullPlugin(tasker, workflow)
        plugin.run()

        assert workflow.builder.image_id == test_id
        assert len(tasker.pulled_images) == 1
Ejemplo n.º 2
0
    def test_pull_push_vs_sync(self, push, sync):
        workflow = self.workflow(push=push, sync=sync)
        tasker = MockerTasker()

        test_id = 'sha256:(new)'

        getter = self.custom_get_v1

        if sync:
            (flexmock(requests.Session)
                .should_receive('get')
                .replace_with(getter))
        else:
            (flexmock(requests.Session)
                .should_receive('get')
                .never())

        (flexmock(tasker)
            .should_call('pull_image')
            .with_args(self.EXPECTED_IMAGE, insecure=False)
            .and_return(self.EXPECTED_PULLSPEC)
            .ordered())

        (flexmock(tasker)
            .should_receive('inspect_image')
            .with_args(self.EXPECTED_PULLSPEC)
            .and_return({'Id': test_id}))

        workflow.postbuild_plugins_conf = []

        plugin = PulpPullPlugin(tasker, workflow)
        plugin.run()

        assert workflow.builder.image_id == test_id
        assert len(tasker.pulled_images) == 1
Ejemplo n.º 3
0
    def test_pull_first_time(self):
        workflow = self.workflow()
        tasker = MockerTasker()
        expected_pullspec = '%s/%s' % (self.CRANE_URI, self.TEST_UNIQUE_IMAGE)
        test_id = 'sha256:(new)'

        (flexmock(tasker).should_call('pull_image').and_return(
            expected_pullspec).once().ordered())

        (flexmock(tasker).should_receive('inspect_image').with_args(
            expected_pullspec).and_return({
                'Id': test_id
            }).once())

        plugin = PulpPullPlugin(tasker, workflow)

        # Plugin return value is the new ID
        assert plugin.run() == test_id

        assert len(tasker.pulled_images) == 1
        pulled = tasker.pulled_images[0].to_str()
        assert pulled == expected_pullspec

        # Image ID is updated in workflow
        assert workflow.builder.image_id == test_id
Ejemplo n.º 4
0
    def test_pull_first_time(self, insecure):
        workflow = self.workflow()
        tasker = MockerTasker()

        test_id = 'sha256:(new)'

        (flexmock(tasker).should_call('pull_image').with_args(
            self.EXPECTED_IMAGE, insecure=insecure).and_return(
                self.EXPECTED_PULLSPEC).once().ordered())

        (flexmock(tasker).should_receive('inspect_image').with_args(
            self.EXPECTED_PULLSPEC).and_return({
                'Id': test_id
            }).once())

        plugin = PulpPullPlugin(tasker, workflow, insecure=insecure)

        # Plugin return value is the new ID
        assert plugin.run() == test_id

        assert len(tasker.pulled_images) == 1
        pulled = tasker.pulled_images[0].to_str()
        assert pulled == self.EXPECTED_PULLSPEC

        # Image ID is updated in workflow
        assert workflow.builder.image_id == test_id
Ejemplo n.º 5
0
    def test_pull_retry(self):
        workflow = self.workflow()
        tasker = MockerTasker()
        expected_pullspec = '%s/%s' % (self.CRANE_URI, self.TEST_UNIQUE_IMAGE)
        test_id = 'sha256:(new)'

        (flexmock(tasker).should_call('pull_image').and_return(
            expected_pullspec).times(3))

        (flexmock(tasker).should_receive('inspect_image').with_args(
            expected_pullspec).and_raise(
                NotFound('message', flexmock(content=None))).and_raise(
                    NotFound('message', flexmock(content=None))).and_return({
                        'Id':
                        test_id
                    }).times(3))

        plugin = PulpPullPlugin(tasker, workflow, timeout=1, retry_delay=0.6)

        # Plugin return value is the new ID
        assert plugin.run() == test_id

        assert len(tasker.pulled_images) == 3
        for image in tasker.pulled_images:
            pulled = image.to_str()
            assert pulled == expected_pullspec

        # Image ID is updated in workflow
        assert workflow.builder.image_id == test_id
Ejemplo n.º 6
0
    def test_expectations(self, group, has_v2list, expect_success):
        def get_manifest(request):
            media_types = request.headers.get('Accept', '').split(',')
            content_type = media_types[0]
            v2_content_type = 'application/vnd.docker.distribution.manifest.list.v2+json'
            if (not has_v2list) and v2_content_type in media_types:
                content_type = 'application/vnd.docker.distribution.manifest.v2+json'

            return (200, {'Content-Type': content_type}, '{}')

        url = re.compile(r'.*//crane.example.com/v2/.*/manifests/.*')
        responses.add_callback(responses.GET, url, callback=get_manifest)
        digests = {'digest': None} if group else {}
        workflow = self.workflow(postbuild_results={
            PLUGIN_GROUP_MANIFESTS_KEY: digests,
        })
        workflow.postbuild_plugins_conf = [{'name': 'pulp_sync'}]
        tasker = MockerTasker()
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.2,
                                retry_delay=0.1, expect_v2schema2=True)
        if expect_success:
            plugin.run()
        else:
            with pytest.raises(CraneTimeoutError):
                plugin.run()
Ejemplo n.º 7
0
    def test_expect_v2schema2list_only(self, caplog, expect_v2, platforms, platform_descriptors,
                                       manifest_list_only):
        def get_manifest(request):
            media_types = request.headers.get('Accept', '').split(',')
            content_type = media_types[0]
            return (200, {'Content-Type': content_type}, '{}')

        url = re.compile(r'.*//crane.example.com/v2/.*/manifests/.*')
        responses.add_callback(responses.GET, url, callback=get_manifest)
        digests = {'digest': None}
        workflow = self.workflow(
            platform_descriptors=platform_descriptors,
            postbuild_results={PLUGIN_GROUP_MANIFESTS_KEY: digests},
            prebuild_results={PLUGIN_CHECK_AND_SET_PLATFORMS_KEY: set(platforms)},
        )
        workflow.postbuild_plugins_conf = [{'name': 'pulp_sync'}]
        tasker = MockerTasker()
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.2,
                                retry_delay=0.1, expect_v2schema2=expect_v2)
        media_types = plugin.run()

        expected_media_types = [MEDIA_TYPE_DOCKER_V2_MANIFEST_LIST]
        if not manifest_list_only:
            expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA1)
            expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA2)
        else:
            assert "Only V2 schema 2 manifest list is expected, " in caplog.text
        assert set(media_types) == set(expected_media_types)
Ejemplo n.º 8
0
    def test_expect_v2schema2list_only(self, caplog, expect_v2, platforms, platform_descriptors,
                                       manifest_list_only):
        def get_manifest(request):
            media_types = request.headers.get('Accept', '').split(',')
            content_type = media_types[0]
            return (200, {'Content-Type': content_type}, '{}')

        url = re.compile(r'.*//crane.example.com/v2/.*/manifests/.*')
        responses.add_callback(responses.GET, url, callback=get_manifest)
        digests = {'digest': None}
        workflow = self.workflow(
            platform_descriptors=platform_descriptors,
            postbuild_results={PLUGIN_GROUP_MANIFESTS_KEY: digests},
            prebuild_results={PLUGIN_CHECK_AND_SET_PLATFORMS_KEY: set(platforms)},
        )
        workflow.postbuild_plugins_conf = [{'name': 'pulp_sync'}]
        tasker = MockerTasker()
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.2,
                                retry_delay=0.1, expect_v2schema2=expect_v2)
        media_types = plugin.run()

        expected_media_types = [MEDIA_TYPE_DOCKER_V2_MANIFEST_LIST]
        if not manifest_list_only:
            expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA1)
            expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA2)
        else:
            assert "Only V2 schema 2 manifest list is expected, " in caplog.text()
        assert set(media_types) == set(expected_media_types)
Ejemplo n.º 9
0
 def test_unexpected_response(self):
     workflow = self.workflow()
     tasker = MockerTasker()
     unauthorized = requests.Response()
     flexmock(unauthorized, status_code=requests.codes.unauthorized)
     flexmock(requests.Session).should_receive('get').and_return(unauthorized)
     workflow.postbuild_plugins_conf = []
     plugin = PulpPullPlugin(tasker, workflow)
     with pytest.raises(requests.exceptions.HTTPError):
         plugin.run()
Ejemplo n.º 10
0
 def test_unexpected_response(self):
     workflow = self.workflow()
     tasker = MockerTasker()
     unauthorized = requests.Response()
     flexmock(unauthorized, status_code=requests.codes.unauthorized)
     flexmock(requests.Session).should_receive('get').and_return(unauthorized)
     workflow.postbuild_plugins_conf = []
     plugin = PulpPullPlugin(tasker, workflow)
     with pytest.raises(requests.exceptions.HTTPError):
         plugin.run()
Ejemplo n.º 11
0
    def test_pull_timeout(self):
        workflow = self.workflow()
        tasker = MockerTasker()

        (flexmock(tasker).should_call('pull_image').and_return(
            self.EXPECTED_PULLSPEC).times(3))

        (flexmock(tasker).should_receive('inspect_image').with_args(
            self.EXPECTED_PULLSPEC).and_raise(
                NotFound('message', flexmock(content=None))).times(3))

        plugin = PulpPullPlugin(tasker, workflow, timeout=1, retry_delay=0.6)

        # Should raise a timeout exception
        with pytest.raises(CraneTimeoutError):
            plugin.run()
Ejemplo n.º 12
0
    def test_pull_timeout(self):
        workflow = self.workflow()
        tasker = MockerTasker()
        expected_pullspec = '%s/%s' % (self.CRANE_URI, self.TEST_UNIQUE_IMAGE)

        (flexmock(tasker).should_call('pull_image').and_return(
            expected_pullspec).times(3))

        (flexmock(tasker).should_receive('inspect_image').with_args(
            expected_pullspec).and_raise(
                NotFound('message', flexmock(content=None))).times(3))

        plugin = PulpPullPlugin(tasker, workflow, timeout=1, retry_delay=0.6)

        # Should raise a timeout exception
        with pytest.raises(CraneTimeoutError):
            plugin.run()
Ejemplo n.º 13
0
    def test_plugin_type(self):
        # arrangement versions < 4
        assert issubclass(PulpPullPlugin, PostBuildPlugin)

        # arrangement version >= 4
        assert issubclass(PulpPullPlugin, ExitPlugin)

        # Verify the plugin does nothing when running as an exit
        # plugin for an already-failed build
        workflow = self.workflow(build_process_failed=True)
        tasker = MockerTasker()
        workflow.postbuild_plugins_conf = []
        flexmock(requests.Session).should_receive('get').never()
        flexmock(tasker).should_receive('pull_image').never()
        flexmock(tasker).should_receive('inspect_image').never()
        plugin = PulpPullPlugin(tasker, workflow)
        media_types = plugin.run()
        assert len(media_types) == 0
Ejemplo n.º 14
0
    def test_plugin_type(self):
        # arrangement versions < 4
        assert issubclass(PulpPullPlugin, PostBuildPlugin)

        # arrangement version >= 4
        assert issubclass(PulpPullPlugin, ExitPlugin)

        # Verify the plugin does nothing when running as an exit
        # plugin for an already-failed build
        workflow = self.workflow(build_process_failed=True)
        tasker = MockerTasker()
        workflow.postbuild_plugins_conf = []
        flexmock(requests.Session).should_receive('get').never()
        flexmock(tasker).should_receive('pull_image').never()
        flexmock(tasker).should_receive('inspect_image').never()
        plugin = PulpPullPlugin(tasker, workflow)
        media_types = plugin.run()
        assert len(media_types) == 0
Ejemplo n.º 15
0
    def test_forbidden_response(self):
        workflow = self.workflow()
        tasker = MockerTasker()
        forbidden = requests.Response()
        flexmock(forbidden,
                 status_code=requests.codes.forbidden,
                 request=requests.Request(url='https://crane.example.com'))
        expectation = flexmock(requests.Session).should_receive('get')
        expectation.and_return(forbidden)
        expectation.and_return(self.config_response_config_v1)
        expectation.and_return(self.config_response_config_v2)
        expectation.and_return(self.config_response_config_v2_list)
        # No OCI support in Pulp at the moment, will return a v1 response
        expectation.and_return(self.config_response_config_v1)
        expectation.and_return(self.config_response_config_v1)
        workflow.postbuild_plugins_conf = []
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.5,
                                retry_delay=0.26,
                                expect_v2schema2=True)

        plugin.run()
Ejemplo n.º 16
0
    def test_forbidden_response(self):
        workflow = self.workflow()
        tasker = MockerTasker()
        forbidden = requests.Response()
        flexmock(forbidden,
                 status_code=requests.codes.forbidden,
                 request=requests.Request(url='https://crane.example.com'))
        expectation = flexmock(requests.Session).should_receive('get')
        expectation.and_return(forbidden)
        expectation.and_return(self.config_response_config_v1)
        expectation.and_return(self.config_response_config_v2)
        expectation.and_return(self.config_response_config_v2_list)
        # No OCI support in Pulp at the moment, will return a v1 response
        expectation.and_return(self.config_response_config_v1)
        expectation.and_return(self.config_response_config_v1)
        workflow.postbuild_plugins_conf = []
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.1,
                                retry_delay=0.06,
                                expect_v2schema2=True)

        plugin.run()
Ejemplo n.º 17
0
    def test_expectations(self, group, has_v2list, expect_success):
        def get_manifest(request):
            media_types = request.headers.get('Accept', '').split(',')
            content_type = media_types[0]
            v2_content_type = 'application/vnd.docker.distribution.manifest.list.v2+json'
            if (not has_v2list) and v2_content_type in media_types:
                content_type = 'application/vnd.docker.distribution.manifest.v2+json'

            return (200, {'Content-Type': content_type}, '{}')

        url = re.compile(r'.*//crane.example.com/v2/.*/manifests/.*')
        responses.add_callback(responses.GET, url, callback=get_manifest)
        digests = {'digest': None} if group else {}
        workflow = self.workflow(postbuild_results={
            PLUGIN_GROUP_MANIFESTS_KEY: digests,
        })
        workflow.postbuild_plugins_conf = [{'name': 'pulp_sync'}]
        tasker = MockerTasker()
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.2,
                                retry_delay=0.1, expect_v2schema2=True)
        if expect_success:
            plugin.run()
        else:
            with pytest.raises(CraneTimeoutError):
                plugin.run()
Ejemplo n.º 18
0
    def test_expect_v2_expect_v2list(self, caplog, has_v2, has_v2_list,
                                     expect_v2, platforms, manifest_list_only, has_v1,
                                     expect_success, manifest_list_warn, manifest2_warn):
        def get_manifest(request):
            media_types = request.headers.get('Accept', '').split(',')
            content_type = media_types[0]
            return (200, {'Content-Type': content_type}, '{}')

        url = re.compile(r'.*//crane.example.com/v2/.*/manifests/.*')
        responses.add_callback(responses.GET, url, callback=get_manifest)
        digests = {'digest': None}
        workflow = self.workflow(
            platform_descriptors=True,
            postbuild_results={PLUGIN_GROUP_MANIFESTS_KEY: digests},
            prebuild_results={PLUGIN_CHECK_AND_SET_PLATFORMS_KEY: set(platforms)},
            expectv2schema2=expect_v2,
        )
        workflow.postbuild_plugins_conf = [{'name': 'pulp_sync'}]

        not_found = requests.Response()
        flexmock(not_found, status_code=requests.codes.not_found)
        expectation = flexmock(requests.Session).should_receive('get')

        # 1st retry don't find anything
        for _ in range(5):
            expectation = expectation.and_return(not_found)

        # (for v1, v2, list.v2, oci, and oci.index media types) before get_manifest_digests
        # v1
        if has_v1:
            expectation.and_return(self.config_response_config_v1)
        else:
            expectation.and_return(not_found)

        # v2
        if has_v2:
            expectation.and_return(self.config_response_config_v2)
        elif has_v1:
            expectation.and_return(self.config_response_config_v1)
        else:
            expectation.and_return(not_found)

        # v2_list
        if has_v2_list:
            expectation.and_return(self.config_response_config_v2_list)
        else:
            expectation.and_return(not_found)

        # oci
        if has_v1:
            expectation.and_return(self.config_response_config_v1)
            expectation.and_return(self.config_response_config_v1)
        else:
            expectation.and_return(not_found)
            expectation.and_return(not_found)

        tasker = MockerTasker()
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.2,
                                retry_delay=0.2, expect_v2schema2=expect_v2)
        media_types = None

        if manifest_list_only:
            if expect_success:
                media_types = plugin.run()
            else:
                with pytest.raises(Exception):
                    plugin.run()
                if manifest_list_warn:
                    assert "Expected schema 2 manifest list" in caplog.text
        else:
            if expect_success:
                media_types = plugin.run()
            else:
                with pytest.raises(Exception):
                    plugin.run()
                if manifest_list_warn:
                    assert "Expected schema 2 manifest list" in caplog.text
                elif manifest2_warn:
                    assert "Expected schema 2 manifest" in caplog.text

        if media_types:
            expected_media_types = [MEDIA_TYPE_DOCKER_V2_MANIFEST_LIST]
            if not manifest_list_only:
                expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA1)
                expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA2)
                assert "V2 schema 2 digest found, leaving image ID unchanged" in caplog.text
            else:
                assert "Only V2 schema 2 manifest list is expected, " in caplog.text

            assert set(media_types) == set(expected_media_types)
Ejemplo n.º 19
0
    def test_pull_first_time(self, no_headers, broken_response, insecure, schema_version,
                             pulp_plugin, expected_version):
        workflow = self.workflow()
        tasker = MockerTasker()

        test_id = 'sha256:(new)'

        if schema_version == 'v2':
            # for v2, we just return pre-existing ID
            test_id = 'sha256:(old)'

        if schema_version == 'v1':
            getter = self.custom_get_v1
        elif schema_version == 'list.v2':
            getter = self.custom_get_v2_list
        elif no_headers:
            if broken_response:
                getter = self.custom_get_v2_broken
            else:
                getter = self.custom_get_v2_no_headers
        else:
            getter = self.custom_get_v2

        (flexmock(requests.Session)
            .should_receive('get')
            .replace_with(getter))

        if schema_version in ['v1', 'list.v2'] or broken_response:
            (flexmock(tasker)
                .should_call('pull_image')
                .with_args(self.EXPECTED_IMAGE, insecure=insecure)
                .and_return(self.EXPECTED_PULLSPEC)
                .once()
                .ordered())

            (flexmock(tasker)
                .should_receive('inspect_image')
                .with_args(self.EXPECTED_PULLSPEC)
                .and_return({'Id': test_id})
                .once())
        else:
            (flexmock(tasker)
                .should_call('pull_image')
                .never())

            (flexmock(tasker)
                .should_call('inspect_image')
                .never())

        # Convert pulp_plugin into a JSON string and back into an object
        # to make really sure we get a different string object back.
        workflow.postbuild_plugins_conf = json.loads(json.dumps(pulp_plugin))

        # Set the timeout parameters so that we retry exactly once, but quickly.
        # With the get_manifest_digests() API, the 'broken_response' case isn't
        # distinguishable from no manifest yet, so we retry until timout and then
        # fall through to pulp_pull.
        plugin = PulpPullPlugin(tasker, workflow, insecure=insecure,
                                timeout=0.1, retry_delay=0.25)
        version = plugin.run()

        if not broken_response:
            assert version == expected_version

        if schema_version == 'v1':
            assert len(tasker.pulled_images) == 1
            pulled = tasker.pulled_images[0].to_str()
            assert pulled == self.EXPECTED_PULLSPEC

        # Image ID is updated in workflow
        assert workflow.builder.image_id == test_id
Ejemplo n.º 20
0
    def test_expect_v2_expect_v2list(self, caplog, has_v2, has_v2_list,
                                     expect_v2, platforms, manifest_list_only, has_v1,
                                     expect_success, manifest_list_warn, manifest2_warn):
        def get_manifest(request):
            media_types = request.headers.get('Accept', '').split(',')
            content_type = media_types[0]
            return (200, {'Content-Type': content_type}, '{}')

        url = re.compile(r'.*//crane.example.com/v2/.*/manifests/.*')
        responses.add_callback(responses.GET, url, callback=get_manifest)
        digests = {'digest': None}
        workflow = self.workflow(
            platform_descriptors=True,
            postbuild_results={PLUGIN_GROUP_MANIFESTS_KEY: digests},
            prebuild_results={PLUGIN_CHECK_AND_SET_PLATFORMS_KEY: set(platforms)},
            expectv2schema2=expect_v2,
        )
        workflow.postbuild_plugins_conf = [{'name': 'pulp_sync'}]

        not_found = requests.Response()
        flexmock(not_found, status_code=requests.codes.not_found)
        expectation = flexmock(requests.Session).should_receive('get')

        # 1st retry don't find anything
        for _ in range(5):
            expectation = expectation.and_return(not_found)

        # (for v1, v2, list.v2, oci, and oci.index media types) before get_manifest_digests
        # v1
        if has_v1:
            expectation.and_return(self.config_response_config_v1)
        else:
            expectation.and_return(not_found)

        # v2
        if has_v2:
            expectation.and_return(self.config_response_config_v2)
        elif has_v1:
            expectation.and_return(self.config_response_config_v1)
        else:
            expectation.and_return(not_found)

        # v2_list
        if has_v2_list:
            expectation.and_return(self.config_response_config_v2_list)
        else:
            expectation.and_return(not_found)

        # oci
        if has_v1:
            expectation.and_return(self.config_response_config_v1)
            expectation.and_return(self.config_response_config_v1)
        else:
            expectation.and_return(not_found)
            expectation.and_return(not_found)

        tasker = MockerTasker()
        plugin = PulpPullPlugin(tasker, workflow, timeout=0.2,
                                retry_delay=0.2, expect_v2schema2=expect_v2)
        media_types = None

        if manifest_list_only:
            if expect_success:
                media_types = plugin.run()
            else:
                with pytest.raises(Exception):
                    plugin.run()
                if manifest_list_warn:
                    assert "Expected schema 2 manifest list" in caplog.text()
        else:
            if expect_success:
                media_types = plugin.run()
            else:
                with pytest.raises(Exception):
                    plugin.run()
                if manifest_list_warn:
                    assert "Expected schema 2 manifest list" in caplog.text()
                elif manifest2_warn:
                    assert "Expected schema 2 manifest" in caplog.text()

        if media_types:
            expected_media_types = [MEDIA_TYPE_DOCKER_V2_MANIFEST_LIST]
            if not manifest_list_only:
                expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA1)
                expected_media_types.append(MEDIA_TYPE_DOCKER_V2_SCHEMA2)
                assert "V2 schema 2 digest found, leaving image ID unchanged" in caplog.text()
            else:
                assert "Only V2 schema 2 manifest list is expected, " in caplog.text()

            assert set(media_types) == set(expected_media_types)
Ejemplo n.º 21
0
    def test_pull_first_time(self, no_headers, broken_response, insecure, schema_version,
                             pulp_plugin, expected_version):
        workflow = self.workflow()
        tasker = MockerTasker()

        test_id = 'sha256:(new)'

        if schema_version == 'v2':
            # for v2, we just return pre-existing ID
            test_id = 'sha256:(old)'

        if schema_version == 'v1':
            getter = self.custom_get_v1
        elif schema_version == 'list.v2':
            getter = self.custom_get_v2_list
        elif no_headers:
            if broken_response:
                getter = self.custom_get_v2_broken
            else:
                getter = self.custom_get_v2_no_headers
        else:
            getter = self.custom_get_v2

        (flexmock(requests.Session)
            .should_receive('get')
            .replace_with(getter))

        if schema_version in ['v1', 'list.v2'] or broken_response:
            (flexmock(tasker)
                .should_call('pull_image')
                .with_args(self.EXPECTED_IMAGE, insecure=insecure)
                .and_return(self.EXPECTED_PULLSPEC)
                .once()
                .ordered())

            (flexmock(tasker)
                .should_receive('inspect_image')
                .with_args(self.EXPECTED_PULLSPEC)
                .and_return({'Id': test_id})
                .once())
        else:
            (flexmock(tasker)
                .should_call('pull_image')
                .never())

            (flexmock(tasker)
                .should_call('inspect_image')
                .never())

        # Convert pulp_plugin into a JSON string and back into an object
        # to make really sure we get a different string object back.
        workflow.postbuild_plugins_conf = json.loads(json.dumps(pulp_plugin))

        # Set the timeout parameters so that we retry exactly once, but quickly.
        # With the get_manifest_digests() API, the 'broken_response' case isn't
        # distinguishable from no manifest yet, so we retry until timout and then
        # fall through to pulp_pull.
        plugin = PulpPullPlugin(tasker, workflow, insecure=insecure,
                                timeout=0.1, retry_delay=0.25)
        version = plugin.run()

        if not broken_response:
            assert version == expected_version

        if schema_version == 'v1':
            assert len(tasker.pulled_images) == 1
            pulled = tasker.pulled_images[0].to_str()
            assert pulled == self.EXPECTED_PULLSPEC

        # Image ID is updated in workflow
        assert workflow.builder.image_id == test_id
Ejemplo n.º 22
0
    def test_pull_retry(self, expect_v2schema2, v2, timeout, retry_delay, failures,
                        expect_success, reactor_config):
        workflow = self.workflow(expect_v2schema2)
        tasker = MockerTasker()
        if v2:
            test_id = 'sha256:(old)'
        else:
            # Image ID is updated in workflow
            test_id = 'sha256:(new)'

        not_found = requests.Response()
        flexmock(not_found, status_code=requests.codes.not_found)
        expectation = flexmock(requests.Session).should_receive('get')
        # If pulp is returning a 404 for a manifest URL, we will get 5 requests
        # (for v1, v2, list.v2, oci, and oci.index media types) before get_manifest_digests
        # gives up, so we need to return 5 404's to equal one "failure".
        for _ in range(5 * failures):
            expectation = expectation.and_return(not_found)

        expectation.and_return(self.config_response_config_v1)
        if v2:
            expectation.and_return(self.config_response_config_v2)
        else:
            expectation.and_return(self.config_response_config_v1)
        expectation.and_return(self.config_response_config_v2_list)
        # No OCI support in Pulp at the moment, will return a v1 response
        expectation.and_return(self.config_response_config_v1)

        # A special case for retries - schema 2 manifest digest is expected,
        # but its never being sent - the test should fail on timeout
        if not v2 and expect_v2schema2:
            expect_success = False

        expectation = flexmock(tasker).should_call('pull_image')
        if v2:
            expectation.never()
        elif expect_success:
            expectation.and_return(self.EXPECTED_PULLSPEC).once()

        expectation = flexmock(tasker).should_receive('inspect_image')
        if v2:
            expectation.never()
        elif expect_success:
            (expectation
             .with_args(self.EXPECTED_PULLSPEC)
             .and_return({'Id': test_id})
             .once())
        workflow.postbuild_plugins_conf = []

        if reactor_config:
            plugin = PulpPullPlugin(tasker, workflow, timeout=timeout,
                                    retry_delay=retry_delay)
        else:
            plugin = PulpPullPlugin(tasker, workflow, timeout=timeout,
                                    retry_delay=retry_delay,
                                    expect_v2schema2=expect_v2schema2)

        if not expect_success:
            with pytest.raises(Exception):
                plugin.run()
            return

        plugin.run()

        assert len(tasker.pulled_images) == 0 if v2 else 1
        if not v2:
            img = tasker.pulled_images[0].to_str()
            assert img == self.EXPECTED_PULLSPEC

        assert workflow.builder.image_id == test_id
Ejemplo n.º 23
0
    def test_pull_retry(self, expect_v2schema2, v2, timeout, retry_delay, failures,
                        expect_success, reactor_config):
        workflow = self.workflow(expect_v2schema2)
        tasker = MockerTasker()
        if v2:
            test_id = 'sha256:(old)'
        else:
            # Image ID is updated in workflow
            test_id = 'sha256:(new)'

        not_found = requests.Response()
        flexmock(not_found, status_code=requests.codes.not_found)
        expectation = flexmock(requests.Session).should_receive('get')
        # If pulp is returning a 404 for a manifest URL, we will get 5 requests
        # (for v1, v2, list.v2, oci, and oci.index media types) before get_manifest_digests
        # gives up, so we need to return 5 404's to equal one "failure".
        for _ in range(5 * failures):
            expectation = expectation.and_return(not_found)

        expectation.and_return(self.config_response_config_v1)
        if v2:
            expectation.and_return(self.config_response_config_v2)
        else:
            expectation.and_return(self.config_response_config_v1)
        expectation.and_return(self.config_response_config_v2_list)
        # No OCI support in Pulp at the moment, will return a v1 response
        expectation.and_return(self.config_response_config_v1)

        # A special case for retries - schema 2 manifest digest is expected,
        # but its never being sent - the test should fail on timeout
        if not v2 and expect_v2schema2:
            expect_success = False

        expectation = flexmock(tasker).should_call('pull_image')
        if v2:
            expectation.never()
        elif expect_success:
            expectation.and_return(self.EXPECTED_PULLSPEC).once()

        expectation = flexmock(tasker).should_receive('inspect_image')
        if v2:
            expectation.never()
        elif expect_success:
            (expectation
             .with_args(self.EXPECTED_PULLSPEC)
             .and_return({'Id': test_id})
             .once())
        workflow.postbuild_plugins_conf = []

        if reactor_config:
            plugin = PulpPullPlugin(tasker, workflow, timeout=timeout,
                                    retry_delay=retry_delay)
        else:
            plugin = PulpPullPlugin(tasker, workflow, timeout=timeout,
                                    retry_delay=retry_delay,
                                    expect_v2schema2=expect_v2schema2)

        if not expect_success:
            with pytest.raises(Exception):
                plugin.run()
            return

        plugin.run()

        assert len(tasker.pulled_images) == 0 if v2 else 1
        if not v2:
            img = tasker.pulled_images[0].to_str()
            assert img == self.EXPECTED_PULLSPEC

        assert workflow.builder.image_id == test_id
Ejemplo n.º 24
0
    def test_pull_retry(self, expect_v2schema2, v2, timeout, retry_delay, failures,
                        expect_success):
        workflow = self.workflow()
        tasker = MockerTasker()
        if v2:
            test_id = 'sha256:(old)'
        else:
            # Image ID is updated in workflow
            test_id = 'sha256:(new)'

        not_found = requests.Response()
        flexmock(not_found, status_code=requests.codes.not_found)
        expectation = flexmock(requests.Session).should_receive('get')
        for _ in range(failures):
            expectation = expectation.and_return(not_found)

        expectation.and_return(self.config_response_config_v1)
        if v2:
            expectation.and_return(self.config_response_config_v2)
        else:
            expectation.and_return(self.config_response_config_v1)
        expectation.and_return(self.config_response_config_v2_list)

        # A special case for retries - schema 2 manifest digest is expected,
        # but its never being sent - the test should fail on timeout
        if not v2 and expect_v2schema2:
            expect_success = False

        expectation = flexmock(tasker).should_call('pull_image')
        if v2:
            expectation.never()
        elif expect_success:
            expectation.and_return(self.EXPECTED_PULLSPEC).once()

        expectation = flexmock(tasker).should_receive('inspect_image')
        if v2:
            expectation.never()
        elif expect_success:
            (expectation
             .with_args(self.EXPECTED_PULLSPEC)
             .and_return({'Id': test_id})
             .once())
        workflow.postbuild_plugins_conf = []

        plugin = PulpPullPlugin(tasker, workflow, timeout=timeout,
                                retry_delay=retry_delay,
                                expect_v2schema2=expect_v2schema2)

        if not expect_success:
            with pytest.raises(Exception):
                plugin.run()
            return

        # Plugin return value is the new ID and schema
        results, version = plugin.run()

        # Plugin return value is the new ID
        assert results == test_id

        assert len(tasker.pulled_images) == 0 if v2 else 1
        if not v2:
            img = tasker.pulled_images[0].to_str()
            assert img == self.EXPECTED_PULLSPEC

        assert workflow.builder.image_id == test_id