예제 #1
0
 def test_dockerhub_v2_registry_without_namespace(self, http_threaded_downloader):
     name = 'test_image'
     registry_url = "https://registry-1.docker.io"
     download_config = mock.MagicMock()
     working_dir = '/a/working/dir'
     r = registry.V2Repository(name, download_config, registry_url, working_dir)
     self.assertEqual('library/test_image', r.name, "Non-name-spaced image not prepended")
예제 #2
0
    def test_get_tags(self):
        """
        Assert correct behavior from get_tags().
        """
        def download_one(request):
            """
            Mock the download_one() method to manipulate the path.
            """
            self.assertEqual(request.url, 'https://registry.example.com/v2/pulp/tags/list')
            self.assertEqual(type(request.destination), type(StringIO()))
            report = DownloadReport(request.url, request.destination)
            report.download_succeeded()
            report.headers = {}
            report.destination.write('{"name": "pulp", "tags": ["best_ever", "latest", "decent"]}')
            return report

        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)
        r.downloader.download_one = mock.MagicMock(side_effect=download_one)

        tags = r.get_tags()

        self.assertEqual(tags, ["best_ever", "latest", "decent"])
예제 #3
0
    def test__get_path_success(self):
        """
        Test _get_path() for the case when the download is successful.
        """
        def download_one(request):
            """
            Mock the download_one() method.
            """
            self.assertEqual(request.url, 'https://registry.example.com/some/path')
            self.assertEqual(type(request.destination), type(StringIO()))
            report = DownloadReport(request.url, request.destination)
            report.download_succeeded()
            report.headers = {'some': 'cool stuff'}
            report.destination.write("This is the stuff you've been waiting for.")
            return report

        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)
        r.downloader.download_one = mock.MagicMock(side_effect=download_one)

        headers, body = r._get_path('/some/path')

        self.assertEqual(headers, {'some': 'cool stuff'})
        self.assertEqual(body, "This is the stuff you've been waiting for.")
예제 #4
0
    def test_api_version_check_missing_header(self):
        """
        The the api_version_check() method when the response is missing the
        Docker-Distribution-API-Version header. Since we want to support servers that are just
        serving simple directories of files, it should be OK if the header is not present.
        """
        def download_one(request):
            """
            Mock the download_one() method to manipulate the path.
            """
            self.assertEqual(request.url, 'https://registry.example.com/v2/')
            self.assertEqual(type(request.destination), type(StringIO()))
            report = DownloadReport(request.url, request.destination)
            report.download_succeeded()
            # The Version header is not present
            report.headers = {}
            report.destination.write("")
            return report

        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)
        r.downloader.download_one = mock.MagicMock(side_effect=download_one)

        # This should not raise an Exception
        r.api_version_check()
예제 #5
0
    def test_get_manifest(self):
        """
        Assert correct behavior from get_manifest().
        """
        def download_one(request):
            """
            Mock the download_one() method to manipulate the path.
            """
            self.assertEqual(request.url,
                             'https://registry.example.com/v2/pulp/manifests/best_version_ever')
            self.assertEqual(type(request.destination), type(StringIO()))
            report = DownloadReport(request.url, request.destination)
            report.download_succeeded()
            schema2 = 'application/vnd.docker.distribution.manifest.v2+json'
            report.headers = {'Docker-Distribution-API-Version': 'registry/2.0',
                              'docker-content-digest': digest,
                              'content-type': schema2}
            report.destination.write(manifest)
            return report

        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)
        r.downloader.download_one = mock.MagicMock(side_effect=download_one)
        digest = 'sha256:46356a7d9575b4cee21e7867b1b83a51788610b7719a616096d943b44737ad9a'
        with open(os.path.join(TEST_DATA_PATH, 'manifest_repeated_layers.json')) as manifest_file:
            manifest = manifest_file.read()

        schema2 = 'application/vnd.docker.distribution.manifest.v2+json'
        m = r.get_manifest('best_version_ever', None, None)

        self.assertEqual([(manifest, digest, schema2)], m)
예제 #6
0
    def test_api_version_check_successful(self):
        """
        The the api_version_check() method when the registry_url is indeed a Docker v2 registry.
        """
        def download_one(request):
            """
            Mock the download_one() method to manipulate the path.
            """
            self.assertEqual(request.url, 'https://registry.example.com/v2/')
            self.assertEqual(type(request.destination), type(StringIO()))
            report = DownloadReport(request.url, request.destination)
            report.download_succeeded()
            report.headers = {'Docker-Distribution-API-Version': 'registry/2.0'}
            report.destination.write("")
            return report

        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)
        r.downloader.download_one = mock.MagicMock(side_effect=download_one)

        # This should not raise an Exception
        r.api_version_check()
예제 #7
0
    def test_api_version_check_incorrect_header(self):
        """
        The the api_version_check() method when the response has the Docker-Distribution-API-Version
        header, but it is not the correct value for a Docker v2 registry.
        """
        def download_one(request):
            """
            Mock the download_one() method to manipulate the path.
            """
            self.assertEqual(request.url, 'https://registry.example.com/v2/')
            self.assertEqual(type(request.destination), type(StringIO()))
            report = DownloadReport(request.url, request.destination)
            report.download_succeeded()
            report.headers = {'Docker-Distribution-API-Version': 'WRONG_VALUE!'}
            report.destination.write("")
            return report

        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)
        r.downloader.download_one = mock.MagicMock(side_effect=download_one)

        self.assertFalse(r.api_version_check())
예제 #8
0
 def test_non_dockerhub_v2_registry_without_namespace(self, http_threaded_downloader):
     name = 'test_image'
     registry_url = "https://somewhere.not-docker.io"
     download_config = mock.MagicMock()
     working_dir = '/a/working/dir'
     r = registry.V2Repository(name, download_config, registry_url, working_dir)
     self.assertNotEqual('library/test_image', r.name,
                         "Non-docker hub image prepended with library")
예제 #9
0
    def __init__(self, repo=None, conduit=None, config=None):
        """
        This method initializes the SyncStep. It first validates the config to ensure that the
        required keys are present. It then constructs some needed items (such as a download config),
        and determines whether the feed URL is a Docker v2 registry or not. If it is, it
        instantiates child tasks that are appropriate for syncing a v2 registry, and if it is not it
        raises a NotImplementedError.

        :param repo:        repository to sync
        :type  repo:        pulp.plugins.model.Repository
        :param conduit:     sync conduit to use
        :type  conduit:     pulp.plugins.conduits.repo_sync.RepoSyncConduit
        :param config:      config object for the sync
        :type  config:      pulp.plugins.config.PluginCallConfiguration
        """
        super(SyncStep, self).__init__(
            step_type=constants.SYNC_STEP_MAIN, repo=repo, conduit=conduit, config=config,
            plugin_type=constants.IMPORTER_TYPE_ID)
        self.description = _('Syncing Docker Repository')

        self._validate(config)
        download_config = nectar_config.importer_config_to_nectar_config(config.flatten())
        upstream_name = config.get(constants.CONFIG_KEY_UPSTREAM_NAME)
        url = config.get(importer_constants.KEY_FEED)
        # The DownloadMetadataSteps will set these to a list of Manifests and Blobs
        self.available_manifests = []
        self.available_blobs = []

        # Unit keys, populated by v1_sync.GetMetadataStep
        self.v1_available_units = []
        # populated by v1_sync.GetMetadataStep
        self.v1_tags = {}

        # Create a Repository object to interact with.
        self.index_repository = registry.V2Repository(
            upstream_name, download_config, url, self.get_working_dir())
        self.v1_index_repository = registry.V1Repository(upstream_name, download_config, url,
                                                         self.get_working_dir())

        # determine which API versions are supported and add corresponding steps
        v2_enabled = config.get(constants.CONFIG_KEY_ENABLE_V2, default=True)
        v1_enabled = config.get(constants.CONFIG_KEY_ENABLE_V1, default=False)
        if not v2_enabled:
            _logger.debug(_('v2 API skipped due to config'))
        if not v1_enabled:
            _logger.debug(_('v1 API skipped due to config'))
        v2_found = v2_enabled and self.index_repository.api_version_check()
        v1_found = v1_enabled and self.v1_index_repository.api_version_check()
        if v2_found:
            _logger.debug(_('v2 API found'))
            self.add_v2_steps(repo, conduit, config)
        if v1_found:
            _logger.debug(_('v1 API found'))
            self.add_v1_steps(repo, config)
        if not any((v1_found, v2_found)):
            raise PulpCodedException(error_code=error_codes.DKR1008, registry=url)
예제 #10
0
    def test_api_version_check_ioerror(self, mock_get_path):
        """
        The the api_version_check() method when _get_path() raises an IOError.
        """
        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)

        self.assertFalse(r.api_version_check())
예제 #11
0
    def test__get_path_failed(self):
        """
        Test _get_path() for the case when an IOError is raised by the downloader.
        """
        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url,
                                  working_dir)

        # The request will fail because the requested path does not exist
        self.assertRaises(IOError, r._get_path, '/some/path')
예제 #12
0
    def test_get_tags_failed(self, mock_download_one):
        """
        When get_tags fails, make sure the correct exception is raised.
        """
        name = 'pulp'
        download_config = DownloaderConfig()
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)

        with self.assertRaises(PulpCodedException) as assertion:
            r.get_tags()

        self.assertEqual(assertion.exception.error_code, error_codes.DKR1007)
예제 #13
0
    def test_create_blob_download_request(self):
        """
        Assert correct behavior from create_blob_download_request().
        """
        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)
        digest = 'sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef'

        request = r.create_blob_download_request(digest)

        self.assertEqual(request.url,
                         'https://registry.example.com/v2/pulp/blobs/{0}'.format(digest))
        self.assertEqual(request.destination, os.path.join(working_dir, digest))
예제 #14
0
    def test___init__(self):
        """
        Assert that __init__() initializes all the correct attributes.
        """
        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)

        self.assertEqual(r.name, name)
        self.assertEqual(r.download_config, download_config)
        self.assertEqual(r.registry_url, registry_url)
        self.assertEqual(type(r.downloader), HTTPThreadedDownloader)
        self.assertEqual(r.downloader.config, download_config)
        self.assertEqual(r.working_dir, working_dir)
예제 #15
0
    def test__get_path_failed(self, mock_download_one, mock_request_token):
        """
        Test _get_path() for the case when an IOError is raised by the downloader.
        """
        name = 'pulp'
        download_config = DownloaderConfig(max_concurrent=25)
        registry_url = 'https://registry.example.com'
        working_dir = '/a/working/dir'
        r = registry.V2Repository(name, download_config, registry_url, working_dir)

        report = DownloadReport(registry_url + '/some/path', StringIO())
        report.error_report['response_code'] = httplib.UNAUTHORIZED
        report.state = DownloadReport.DOWNLOAD_FAILED
        report.headers = {}
        mock_download_one.return_value = report

        # The request will fail because the requested path does not exist
        self.assertRaises(IOError, r._get_path, '/some/path')