示例#1
0
    def test_file_decriptors(self):
        """Test whether file descriptors are closed properly.

        This test targets the following issue:
        `Pulp #4073 <https://pulp.plan.io/issues/4073>`_

        Do the following:
        1. Check if 'lsof' is installed. If it is not, skip this test.
        2. Create and sync a repo.
        3. Run the 'lsof' command to verify that files in the
           path ``/var/lib/pulp/`` are closed after the sync.
        4. Assert that issued command returns `0` opened files.
        """
        cli_client = cli.Client(self.cfg, cli.echo_handler)

        # check if 'lsof' is available
        if cli_client.run(('which', 'lsof')).returncode != 0:
            raise unittest.SkipTest('lsof package is not present')

        repo = self.client.post(REPO_PATH, gen_repo())
        self.addCleanup(self.client.delete, repo['pulp_href'])

        remote = self.client.post(DOCKER_REMOTE_PATH, gen_docker_remote())
        self.addCleanup(self.client.delete, remote['pulp_href'])

        sync(self.cfg, remote, repo)

        cmd = 'lsof -t +D {}'.format(MEDIA_PATH).split()
        response = cli_client.run(cmd).stdout
        self.assertEqual(len(response), 0, response)
示例#2
0
    def test_all(self):
        """Test whether content unit used by a repo version can be deleted.

        Do the following:

        1. Sync content to a repository.
        2. Attempt to delete a content unit present in a repository version.
           Assert that a HTTP exception was raised.
        3. Assert that number of content units present on the repository
           does not change after the attempt to delete one content unit.
        """
        cfg = config.get_config()
        client = api.Client(cfg, api.json_handler)

        body = gen_docker_remote()
        remote = client.post(DOCKER_REMOTE_PATH, body)
        self.addCleanup(client.delete, remote['_href'])

        repo = client.post(REPO_PATH, gen_repo())
        self.addCleanup(client.delete, repo['_href'])

        sync(cfg, remote, repo)

        repo = client.get(repo['_href'])
        content = get_content(repo)
        with self.assertRaises(HTTPError):
            client.delete(choice(content)['_href'])
        self.assertEqual(len(content), len(get_content(repo)))
示例#3
0
    def test_file_decriptors(self):
        """Test whether file descriptors are closed properly.

        This test targets the following issue:
        `Pulp #4073 <https://pulp.plan.io/issues/4073>`_

        Do the following:
        1. Check if 'lsof' is installed. If it is not, skip this test.
        2. Create and sync a repo.
        3. Run the 'lsof' command to verify that files in the
           path ``/var/lib/pulp/`` are closed after the sync.
        4. Assert that issued command returns `0` opened files.
        """
        cli_client = cli.Client(self.cfg, cli.echo_handler)

        # check if 'lsof' is available
        if cli_client.run(('which', 'lsof')).returncode != 0:
            raise unittest.SkipTest('lsof package is not present')

        repo = self.client.post(REPO_PATH, gen_repo())
        self.addCleanup(self.client.delete, repo['_href'])

        remote = self.client.post(DOCKER_REMOTE_PATH, gen_docker_remote())
        self.addCleanup(self.client.delete, remote['_href'])

        sync(self.cfg, remote, repo)

        cmd = 'lsof -t +D {}'.format(MEDIA_PATH).split()
        response = cli_client.run(cmd).stdout
        self.assertEqual(len(response), 0, response)
示例#4
0
    def test_sync(self):
        """Sync repositories with the docker plugin.

        In order to sync a repository a remote has to be associated within
        this repository. When a repository is created this version field is set
        as None. After a sync the repository version is updated.

        Do the following:

        1. Create a repository, and a remote.
        2. Assert that repository version is None.
        3. Sync the remote.
        4. Assert that repository version is not None.
        5. Sync the remote one more time.
        6. Assert that repository version is different from the previous one.
        """
        repo = self.client.post(REPO_PATH, gen_repo())
        self.addCleanup(self.client.delete, repo['_href'])

        remote = self.client.post(DOCKER_REMOTE_PATH, gen_docker_remote())
        self.addCleanup(self.client.delete, remote['_href'])

        # Sync the repository.
        self.assertIsNone(repo['_latest_version_href'])
        sync(self.cfg, remote, repo)
        repo = self.client.get(repo['_href'])
        self.assertIsNotNone(repo['_latest_version_href'])

        # Sync the repository again.
        latest_version_href = repo['_latest_version_href']
        sync(self.cfg, remote, repo)
        repo = self.client.get(repo['_href'])
        self.assertNotEqual(latest_version_href, repo['_latest_version_href'])
示例#5
0
    def test_sync(self):
        """Sync repositories with the docker plugin.

        In order to sync a repository a remote has to be associated within
        this repository. When a repository is created this version field is set
        as None. After a sync the repository version is updated.

        Do the following:

        1. Create a repository, and a remote.
        2. Assert that repository version is None.
        3. Sync the remote.
        4. Assert that repository version is not None.
        5. Sync the remote one more time.
        6. Assert that repository version is different from the previous one.
        """
        repo = self.client.post(REPO_PATH, gen_repo())
        self.addCleanup(self.client.delete, repo['pulp_href'])

        remote = self.client.post(DOCKER_REMOTE_PATH, gen_docker_remote())
        self.addCleanup(self.client.delete, remote['pulp_href'])

        # Sync the repository.
        self.assertIsNone(repo['latest_version_href'])
        sync(self.cfg, remote, repo)
        repo = self.client.get(repo['pulp_href'])
        self.assertIsNotNone(repo['latest_version_href'])

        # Sync the repository again.
        latest_version_href = repo['latest_version_href']
        sync(self.cfg, remote, repo)
        repo = self.client.get(repo['pulp_href'])
        self.assertNotEqual(latest_version_href, repo['latest_version_href'])
示例#6
0
    def setUpClass(cls):
        """Create class-wide variables.

        1. Create a repository.
        2. Create a remote pointing to external registry.
        3. Sync the repository using the remote and re-read the repo data.
        4. Create a docker distribution to serve the repository
        5. Create another docker distribution to the serve the repository version

        This tests targets the following issue:

        * `Pulp #4460 <https://pulp.plan.io/issues/4460>`_
        """
        cls.cfg = config.get_config()
        cls.client = api.Client(cls.cfg, api.page_handler)
        cls.teardown_cleanups = []

        with contextlib.ExitStack() as stack:
            # ensure tearDownClass runs if an error occurs here
            stack.callback(cls.tearDownClass)

            # Step 1
            _repo = cls.client.post(REPO_PATH, gen_repo())
            cls.teardown_cleanups.append(
                (cls.client.delete, _repo['pulp_href']))

            # Step 2
            cls.remote = cls.client.post(DOCKER_REMOTE_PATH,
                                         gen_docker_remote())
            cls.teardown_cleanups.append(
                (cls.client.delete, cls.remote['pulp_href']))

            # Step 3
            sync(cls.cfg, cls.remote, _repo)
            cls.repo = cls.client.get(_repo['pulp_href'])

            # Step 4.
            response_dict = cls.client.using_handler(api.task_handler).post(
                DOCKER_DISTRIBUTION_PATH,
                gen_distribution(repository=cls.repo['pulp_href']))
            distribution_href = response_dict['pulp_href']
            cls.distribution_with_repo = cls.client.get(distribution_href)
            cls.teardown_cleanups.append(
                (cls.client.delete, cls.distribution_with_repo['pulp_href']))

            # Step 5.
            response_dict = cls.client.using_handler(api.task_handler).post(
                DOCKER_DISTRIBUTION_PATH,
                gen_distribution(
                    repository_version=cls.repo['latest_version_href']))
            distribution_href = response_dict['pulp_href']
            cls.distribution_with_repo_version = cls.client.get(
                distribution_href)
            cls.teardown_cleanups.append(
                (cls.client.delete,
                 cls.distribution_with_repo_version['pulp_href']))

            # remove callback if everything goes well
            stack.pop_all()
示例#7
0
 def setUpClass(cls):
     """Create class-wide variables."""
     cls.cfg = config.get_config()
     cls.client = api.Client(cls.cfg, api.json_handler)
     cls.from_repo = cls.client.post(REPO_PATH, gen_repo())
     remote_data = gen_docker_remote(upstream_name=DOCKERHUB_PULP_FIXTURE_1)
     cls.remote = cls.client.post(DOCKER_REMOTE_PATH, remote_data)
     delete_orphans(cls.cfg)
示例#8
0
    def test_02_create_same_name(self):
        """Try to create a second remote with an identical name.

        See: `Pulp Smash #1055
        <https://github.com/PulpQE/pulp-smash/issues/1055>`_.
        """
        body = gen_docker_remote()
        body['name'] = self.remote['name']
        with self.assertRaises(HTTPError):
            self.client.post(DOCKER_REMOTE_PATH, body)
示例#9
0
    def test_02_create_same_name(self):
        """Try to create a second remote with an identical name.

        See: `Pulp Smash #1055
        <https://github.com/PulpQE/pulp-smash/issues/1055>`_.
        """
        body = gen_docker_remote()
        body['name'] = self.remote['name']
        with self.assertRaises(HTTPError):
            self.client.post(DOCKER_REMOTE_PATH, body)
示例#10
0
    def test_all(self):
        """Test whether a particular repository version can be published.

        1. Create a repository with at least 2 repository versions.
        2. Create a publication by supplying the latest ``repository_version``.
        3. Assert that the publication ``repository_version`` attribute points
           to the latest repository version.
        4. Create a publication by supplying the non-latest ``repository_version``.
        5. Assert that the publication ``repository_version`` attribute points
           to the supplied repository version.
        6. Assert that an exception is raised when providing two different
           repository versions to be published at same time.
        """
        body = gen_docker_remote()
        remote = self.client.post(DOCKER_REMOTE_PATH, body)
        self.addCleanup(self.client.delete, remote['_href'])

        repo = self.client.post(REPO_PATH, gen_repo())
        self.addCleanup(self.client.delete, repo['_href'])

        sync(self.cfg, remote, repo)

        publisher = self.client.post(DOCKER_PUBLISHER_PATH, gen_docker_publisher())
        self.addCleanup(self.client.delete, publisher['_href'])

        # Step 1
        repo = self.client.post(REPO_PATH, gen_repo())
        self.addCleanup(self.client.delete, repo['_href'])
        for docker_content in self.client.get(DOCKER_CONTENT_PATH)['results']:
            self.client.post(
                repo['_versions_href'],
                {'add_content_units': [docker_content['_href']]}
            )
        version_hrefs = tuple(ver['_href'] for ver in get_versions(repo))
        non_latest = choice(version_hrefs[:-1])

        # Step 2
        publication = publish(self.cfg, publisher, repo)

        # Step 3
        self.assertEqual(publication['repository_version'], version_hrefs[-1])

        # Step 4
        publication = publish(self.cfg, publisher, repo, non_latest)

        # Step 5
        self.assertEqual(publication['repository_version'], non_latest)

        # Step 6
        with self.assertRaises(HTTPError):
            body = {
                'repository': repo['_href'],
                'repository_version': non_latest
            }
            self.client.post(urljoin(publisher['_href'], 'publish/'), body)
示例#11
0
    def test_all(self):
        """Verify whether is possible to create a remote without a URL.

        This test targets the following issues:

        * `Pulp #3395 <https://pulp.plan.io/issues/3395>`_
        * `Pulp Smash #984 <https://github.com/PulpQE/pulp-smash/issues/984>`_
        """
        body = gen_docker_remote()
        del body['url']
        with self.assertRaises(HTTPError):
            api.Client(config.get_config()).post(DOCKER_REMOTE_PATH, body)
示例#12
0
    def test_all(self):
        """Verify whether is possible to create a remote without a URL.

        This test targets the following issues:

        * `Pulp #3395 <https://pulp.plan.io/issues/3395>`_
        * `Pulp Smash #984 <https://github.com/PulpQE/pulp-smash/issues/984>`_
        """
        body = gen_docker_remote()
        del body['url']
        with self.assertRaises(HTTPError):
            api.Client(config.get_config()).post(DOCKER_REMOTE_PATH, body)
示例#13
0
 def setUpClass(cls):
     """Sync pulp/test-fixture-1 so we can copy content from it."""
     cls.cfg = config.get_config()
     cls.client = api.Client(cls.cfg, api.json_handler)
     cls.from_repo = cls.client.post(REPO_PATH, gen_repo())
     remote_data = gen_docker_remote(upstream_name=DOCKERHUB_PULP_FIXTURE_1)
     cls.remote = cls.client.post(DOCKER_REMOTE_PATH, remote_data)
     sync(cls.cfg, cls.remote, cls.from_repo)
     latest_version = cls.client.get(
         cls.from_repo['pulp_href'])['latest_version_href']
     cls.latest_from_version = "repository_version={version}".format(
         version=latest_version)
示例#14
0
def _gen_verbose_remote():
    """Return a semi-random dict for use in defining a remote.

    For most tests, it's desirable to create remotes with as few attributes
    as possible, so that the tests can specifically target and attempt to break
    specific features. This module specifically targets remotes, so it makes
    sense to provide as many attributes as possible.

    Note that 'username' and 'password' are write-only attributes.
    """
    attrs = gen_docker_remote()
    attrs.update({
        'password': utils.uuid4(),
        'username': utils.uuid4(),
        'validate': choice((False, True)),
    })
    return attrs
示例#15
0
def _gen_verbose_remote():
    """Return a semi-random dict for use in defining a remote.

    For most tests, it's desirable to create remotes with as few attributes
    as possible, so that the tests can specifically target and attempt to break
    specific features. This module specifically targets remotes, so it makes
    sense to provide as many attributes as possible.

    Note that 'username' and 'password' are write-only attributes.
    """
    attrs = gen_docker_remote()
    attrs.update({
        'password': utils.uuid4(),
        'username': utils.uuid4(),
        'policy': choice(DOWNLOAD_POLICIES),
        'validate': choice((False, True)),
    })
    return attrs
示例#16
0
    def test_all(self):
        """
        Sync a repository using a Remote url that does not exist.

        Test that we get a task failure.

        """
        cfg = config.get_config()
        client = api.Client(cfg, api.json_handler)

        repo = client.post(REPO_PATH, gen_repo())
        self.addCleanup(client.delete, repo['_href'])

        body = gen_docker_remote(url="http://i-am-an-invalid-url.com/invalid/")
        remote = client.post(DOCKER_REMOTE_PATH, body)
        self.addCleanup(client.delete, remote['_href'])

        with self.assertRaises(exceptions.TaskReportError):
            sync(cfg, remote, repo)
示例#17
0
    def test_sync(self):
        """Sync repositories with the docker plugin.

        In order to sync a repository a remote has to be associated within
        this repository. When a repository is created this version field is set
        as None. After a sync the repository version is updated.

        Do the following:

        1. Create a repository, and a remote.
        2. Assert that repository version is None.
        3. Sync the remote.
        4. Assert that repository version is not None.
        5. Sync the remote one more time.
        6. Assert that repository version is different from the previous one.
        """
        client = api.Client(self.cfg, api.json_handler)

        repo = client.post(REPO_PATH, gen_repo())
        self.addCleanup(client.delete, repo['_href'])

        body = gen_docker_remote()
        remote = client.post(DOCKER_REMOTE_PATH, body)
        self.addCleanup(client.delete, remote['_href'])

        # Sync the repository.
        self.assertIsNone(repo['_latest_version_href'])
        sync(self.cfg, remote, repo)
        repo = client.get(repo['_href'])

        self.assertIsNotNone(repo['_latest_version_href'])
        self.assertEqual(len(get_content(repo)), DOCKER_FIXTURE_COUNT)
        self.assertEqual(len(get_added_content(repo)), DOCKER_FIXTURE_COUNT)

        # Sync the repository again.
        latest_version_href = repo['_latest_version_href']
        sync(self.cfg, remote, repo)
        repo = client.get(repo['_href'])

        self.assertNotEqual(latest_version_href, repo['_latest_version_href'])
        self.assertEqual(len(get_content(repo)), DOCKER_FIXTURE_COUNT)
        self.assertEqual(len(get_added_content(repo)), 0)
示例#18
0
    def test_all(self):
        """
        Sync a repository using a Remote url that does not exist.

        Test that we get a task failure.

        """
        cfg = config.get_config()
        client = api.Client(cfg, api.json_handler)

        repo = client.post(REPO_PATH, gen_repo())
        self.addCleanup(client.delete, repo['_href'])

        remote = client.post(
            DOCKER_REMOTE_PATH,
            gen_docker_remote(url="http://i-am-an-invalid-url.com/invalid/")
        )
        self.addCleanup(client.delete, remote['_href'])

        with self.assertRaises(exceptions.TaskReportError):
            sync(cfg, remote, repo)
    def setUpClass(cls):
        """Create class wide-variables."""
        cls.cfg = config.get_config()

        token_auth = cls.cfg.hosts[0].roles['token auth']
        client = cli.Client(cls.cfg)
        client.run('openssl ecparam -genkey -name prime256v1 -noout -out {}'
                   .format(token_auth['private key']).split())
        client.run('openssl ec -in {} -pubout -out {}'.format(
            token_auth['private key'], token_auth['public key']).split())

        cls.client = api.Client(cls.cfg, api.page_handler)

        cls.repository = cls.client.post(REPO_PATH, gen_repo())
        remote_data = gen_docker_remote(upstream_name=DOCKERHUB_PULP_FIXTURE_1)
        cls.remote = cls.client.post(DOCKER_REMOTE_PATH, remote_data)
        sync(cls.cfg, cls.remote, cls.repository)

        cls.distribution = cls.client.using_handler(api.task_handler).post(
            DOCKER_DISTRIBUTION_PATH,
            gen_distribution(repository=cls.repository['pulp_href'])
        )
示例#20
0
    def test_all(self):
        """Verify whether content served by pulp can be downloaded.

        The process of publishing content is more involved in Pulp 3 than it
        was under Pulp 2. Given a repository, the process is as follows:

        1. Create a publication from the repository. (The latest repository
           version is selected if no version is specified.) A publication is a
           repository version plus metadata.
        2. Create a distribution from the publication. The distribution defines
           at which URLs a publication is available, e.g.
           ``http://example.com/content/foo/`` and
           ``http://example.com/content/bar/``.

        Do the following:

        1. Create, populate, publish, and distribute a repository.
        2. Select a random content unit in the distribution. Download that
           content unit from Pulp, and verify that the content unit has the
           same checksum when fetched directly from Remote.
           NOTE: content unit for docker is `image` or `Layer`

        This test targets the following issues:

        * `Pulp #2895 <https://pulp.plan.io/issues/2895>`_
        * `Pulp Smash #872 <https://github.com/PulpQE/pulp-smash/issues/872>`_
        """
        cfg = config.get_config()
        client = api.Client(cfg, api.json_handler)

        repo = client.post(REPO_PATH, gen_repo())
        self.addCleanup(client.delete, repo['_href'])

        body = gen_docker_remote()
        remote = client.post(DOCKER_REMOTE_PATH, body)
        self.addCleanup(client.delete, remote['_href'])

        sync(cfg, remote, repo)
        repo = client.get(repo['_href'])

        # Create a publisher.
        publisher = client.post(DOCKER_PUBLISHER_PATH, gen_publisher())
        self.addCleanup(client.delete, publisher['_href'])

        # Create a publication.
        publication = publish(cfg, publisher, repo)
        self.addCleanup(client.delete, publication['_href'])

        # Create a distribution.
        body = gen_distribution()
        body['publication'] = publication['_href']
        distribution = client.post(DOCKER_DISTRIBUTION_PATH, body)
        self.addCleanup(client.delete, distribution['_href'])

        # Get local checksums for content synced from remote registy
        checksums = [
            content['digest'] for content
            in get_content(repo)['docker.manifest-blob']
        ]

        # Assert that at least one layer is synced from remote:latest
        # and the checksum matched with remote
        self.assertTrue(
            any(
                [
                    result['blobSum'] in checksums
                    for result in get_docker_hub_remote_blobsums()
                ]
            )
        )
示例#21
0
    def test_all(self):
        """Verify whether content served by pulp can be downloaded.

        The process of publishing content is more involved in Pulp 3 than it
        was under Pulp 2. Given a repository, the process is as follows:

        1. Create a publication from the repository. (The latest repository
           version is selected if no version is specified.) A publication is a
           repository version plus metadata.
        2. Create a distribution from the publication. The distribution defines
           at which URLs a publication is available, e.g.
           ``http://example.com/content/foo/`` and
           ``http://example.com/content/bar/``.

        Do the following:

        1. Create, populate, publish, and distribute a repository.
        2. Select a random content unit in the distribution. Download that
           content unit from Pulp, and verify that the content unit has the
           same checksum when fetched directly from Pulp-Fixtures.

        This test targets the following issues:

        * `Pulp #2895 <https://pulp.plan.io/issues/2895>`_
        * `Pulp Smash #872 <https://github.com/PulpQE/pulp-smash/issues/872>`_
        """
        cfg = config.get_config()
        client = api.Client(cfg, api.json_handler)

        repo = client.post(REPO_PATH, gen_repo())
        self.addCleanup(client.delete, repo['_href'])

        body = gen_docker_remote()
        remote = client.post(DOCKER_REMOTE_PATH, body)
        self.addCleanup(client.delete, remote['_href'])

        sync(cfg, remote, repo)
        repo = client.get(repo['_href'])

        # Create a publisher.
        publisher = client.post(DOCKER_PUBLISHER_PATH, gen_docker_publisher())
        self.addCleanup(client.delete, publisher['_href'])

        # Create a publication.
        publication = publish(cfg, publisher, repo)
        self.addCleanup(client.delete, publication['_href'])

        # Create a distribution.
        body = gen_distribution()
        body['publication'] = publication['_href']
        distribution = client.post(DISTRIBUTION_PATH, body)
        self.addCleanup(client.delete, distribution['_href'])

        # Pick a content unit, and download it from both Pulp Fixtures…
        unit_path = choice(get_docker_image_paths(repo))
        fixtures_hash = hashlib.sha256(
            utils.http_get(urljoin(DOCKER_FIXTURE_URL,
                                   unit_path))).hexdigest()

        # …and Pulp.
        client.response_handler = api.safe_handler

        unit_url = cfg.get_hosts('api')[0].roles['api']['scheme']
        unit_url += '://' + distribution['base_url'] + '/'
        unit_url = urljoin(unit_url, unit_path)

        pulp_hash = hashlib.sha256(client.get(unit_url).content).hexdigest()
        self.assertEqual(fixtures_hash, pulp_hash)
示例#22
0
    def setUpClass(cls):
        """Create class-wide variables and delete orphans.

        1. Create a repository.
        2. Create a remote pointing to external registry with policy=on_demand.
        3. Sync the repository using the remote and re-read the repo data.
        4. Create a docker distribution to serve the repository
        5. Create another docker distribution to the serve the repository version

        This tests targets the following issue:

        * `Pulp #4460 <https://pulp.plan.io/issues/4460>`_
        """
        cls.cfg = config.get_config()

        token_auth = cls.cfg.hosts[0].roles['token auth']
        client = cli.Client(cls.cfg)
        client.run(
            'openssl ecparam -genkey -name prime256v1 -noout -out {}'.format(
                token_auth['private key']).split())
        client.run('openssl ec -in {} -pubout -out {}'.format(
            token_auth['private key'], token_auth['public key']).split())

        cls.client = api.Client(cls.cfg, api.page_handler)

        cls.teardown_cleanups = []

        delete_orphans(cls.cfg)

        with contextlib.ExitStack() as stack:
            # ensure tearDownClass runs if an error occurs here
            stack.callback(cls.tearDownClass)

            # Step 1
            _repo = cls.client.post(REPO_PATH, gen_repo())
            cls.teardown_cleanups.append(
                (cls.client.delete, _repo['pulp_href']))

            # Step 2
            cls.remote = cls.client.post(DOCKER_REMOTE_PATH,
                                         gen_docker_remote(policy='on_demand'))
            cls.teardown_cleanups.append(
                (cls.client.delete, cls.remote['pulp_href']))

            # Step 3
            sync(cls.cfg, cls.remote, _repo)
            cls.repo = cls.client.get(_repo['pulp_href'])
            cls.artifact_count = len(cls.client.get(ARTIFACTS_PATH))

            # Step 4.
            response_dict = cls.client.using_handler(api.task_handler).post(
                DOCKER_DISTRIBUTION_PATH,
                gen_distribution(repository=cls.repo['pulp_href']))
            distribution_href = response_dict['pulp_href']
            cls.distribution_with_repo = cls.client.get(distribution_href)
            cls.teardown_cleanups.append(
                (cls.client.delete, cls.distribution_with_repo['pulp_href']))

            # Step 5.
            response_dict = cls.client.using_handler(api.task_handler).post(
                DOCKER_DISTRIBUTION_PATH,
                gen_distribution(
                    repository_version=cls.repo['latest_version_href']))
            distribution_href = response_dict['pulp_href']
            cls.distribution_with_repo_version = cls.client.get(
                distribution_href)
            cls.teardown_cleanups.append(
                (cls.client.delete,
                 cls.distribution_with_repo_version['pulp_href']))

            # remove callback if everything goes well
            stack.pop_all()