def make_repo(self, cfg, dist_cfg_updates):
        """Create a repository with an importer and pair of distributors.

        Create an RPM repository with:

        * A yum importer with a valid feed.
        * A yum distributor.
        * An RPM rsync distributor referencing the yum distributor.

        In addition, schedule the repository for deletion.

        :param pulp_smash.config.ServerConfig cfg: Information about the Pulp
            server being targeted.
        :param dist_cfg_updates: A dict to be merged into the RPM rsync
            distributor's ``distributor_config`` dict. At a minimum, this
            argument should have a value of ``{'remote': {…}}``.
        :returns: A detailed dict of information about the repo.
        """
        api_client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        body['distributors'].append({
            'distributor_id': utils.uuid4(),
            'distributor_type_id': 'rpm_rsync_distributor',
            'distributor_config': {
                'predistributor_id': body['distributors'][0]['distributor_id'],
            }
        })
        body['distributors'][1]['distributor_config'].update(dist_cfg_updates)
        repo = api_client.post(REPOSITORY_PATH, body)
        self.addCleanup(api_client.delete, repo['_href'])
        return api_client.get(repo['_href'], params={'details': True})
Example #2
0
    def health_check(self):
        """Execute step three of the test plan."""
        client = api.Client(self.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(api.Client(self.cfg).delete, repo['_href'])
        client.post(
            urljoin(repo['_href'], 'actions/sync/'),
            {'override_config': {}},
        )
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )
        client.response_handler = api.safe_handler
        url = urljoin('/pulp/repos/', distributor['config']['relative_url'])
        url = urljoin(url, RPM)
        pulp_rpm = client.get(url).content

        # Does this RPM match the original RPM?
        rpm = client.get(urljoin(RPM_FEED_URL, RPM)).content
        self.assertEqual(rpm, pulp_rpm)
    def test_publish_override_config(self):
        """Use the ``packages_directory`` publish override option.

        Create a distributor with default options, and use it to publish the
        repository. Specify the ``packages_directory`` option during the
        publish as an override option. Verify packages end up in the specified
        directory, relative to the published repository's root.
        """
        if selectors.bug_is_untestable(1976, self.cfg.version):
            self.skipTest('https://pulp.plan.io/issues/1976')
        client = api.Client(self.cfg, api.json_handler)
        distributor = client.post(
            urljoin(self.repo_href, 'distributors/'),
            gen_distributor(),
        )
        packages_dir = utils.uuid4()
        client.post(
            urljoin(self.repo_href, 'actions/publish/'), {
                'id': distributor['id'],
                'override_config': {
                    'packages_directory': packages_dir
                },
            })
        primary_xml = get_parse_repodata_primary_xml(self.cfg, distributor)
        package_hrefs = get_package_hrefs(primary_xml)
        self.assertGreater(len(package_hrefs), 0)
        for package_href in package_hrefs:
            with self.subTest(package_href=package_href):
                self.assertEqual(os.path.dirname(package_href), packages_dir)
    def setUpClass(cls):
        """Create a schedule to publish the repository.

        Do the following:

        1. Create a repository with a valid feed
        2. Sync it
        3. Schedule publish to run every 30 seconds
        """
        super(CreateSuccessTestCase, cls).setUpClass()
        client = api.Client(cls.cfg)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body).json()
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])

        # Schedule a publish to run every 30 seconds
        distributor = gen_distributor()
        distributor_url = urljoin(repo['_href'], 'distributors/')
        client.post(
            distributor_url,
            distributor
        )
        scheduling_url = urljoin(
            distributor_url,
            '{}/schedules/publish/'.format(distributor['distributor_id']),
        )
        cls.response = client.post(
            scheduling_url,
            {'schedule': 'PT30S'}
        )
        cls.attrs = cls.response.json()
Example #5
0
    def setUpClass(cls):
        """Bind a consumer to a distributor.

        Do the following:

        1. Add a consumer.
        2. Add a repository.
        3. Add a distributor to the repository.
        4. Bind the consumer to the distributor.
        """
        super(BindConsumerTestCase, cls).setUpClass()

        # Steps 1–3
        client = api.Client(cls.cfg, api.json_handler)
        cls.consumer = client.post(CONSUMER_PATH, {'id': utils.uuid4()})
        repository = client.post(REPOSITORY_PATH, gen_repo())
        distributor = client.post(
            urljoin(repository['_href'], 'distributors/'),
            gen_distributor()
        )
        cls.resources.add(repository['_href'])

        # Step 4
        client.response_handler = api.safe_handler
        path = urljoin(CONSUMER_PATH, cls.consumer['consumer']['id'] + '/')
        path = urljoin(path, 'bindings/')
        cls.request = {
            'binding_config': {'B': 21},
            'distributor_id': distributor['id'],
            'notify_agent': False,
            'repo_id': distributor['repo_id'],
        }
        cls.response = client.post(path, cls.request)
Example #6
0
    def setUpClass(cls):
        """Publish a yum repo containing some updates."""
        super(UpdateInfoTestCase, cls).setUpClass()

        cls.tasks = {}
        cls.errata = {}

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

        # Create a repository for use by the test.
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])

        # add yum distributor to the repo
        distribute = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor())

        # import some errata
        cls.import_updates(client, repo)

        # ask for it to be published
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distribute['id']})

        repo_url = urljoin('/pulp/repos/',
                           distribute['config']['relative_url'])
        cls.updateinfo_tree = cls.get_repodata_xml(repo_url, 'updateinfo')
    def setUpClass(cls):
        """Create a schedule to publish a repo, verify the ``total_run_count``.

        Do the following:

        1. Create a repository with a valid feed
        2. Sync it
        3. Schedule publish to run every 2 minutes
        4. Wait for 130 seconds and read the schedule to get the number of
           "publish" runs
        """
        super(ScheduledPublishTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])

        # Schedule a publish to run every 2 minutes
        distributor = gen_distributor()
        client.post(urljoin(repo['_href'], 'distributors/'), distributor)
        scheduling_url = '/'.join([
            'distributors', distributor['distributor_id'], 'schedules/publish/'
        ])
        schedule_path = urljoin(repo['_href'], scheduling_url)
        schedule = client.post(schedule_path, {'schedule': 'PT2M'})

        # Wait for publish to run
        time.sleep(130)

        # Read the schedule
        cls.response = client.get(schedule['_href'])
    def test_update_checksum_type(self):
        """Check if RPM distributor can receive null checksum_type.

        See: https://pulp.plan.io/issues/2134.
        """
        if self.cfg.version < version.Version('2.9'):
            raise unittest.SkipTest('This test requires Pulp 2.9 or above.')
        client = api.Client(self.cfg, api.json_handler)
        distributor = gen_distributor()
        body = gen_repo()
        body['distributors'] = [distributor]
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(client.delete, repo['_href'])
        for checksum_type in (None, 'sha256', None):
            client.put(
                repo['_href'], {
                    'distributor_configs': {
                        distributor['distributor_id']: {
                            'checksum_type': checksum_type,
                        }
                    }
                })
            repo = client.get(repo['_href'], params={'details': True})
            config = repo['distributors'][0]['config']
            self.assertEqual(config.get('checksum_type'), checksum_type)
Example #9
0
    def setUpClass(cls):
        """Generate, fetch and parse a ``repomd.xml`` file.

        Do the following:

        1. Create an RPM repository, add a YUM distributor, and publish the
           repository.
        2. Fetch the ``repomd.xml`` file from the distributor, and parse it.
        """
        super(RepoMDTestCase, cls).setUpClass()
        if check_issue_2277(cls.cfg):
            raise unittest.SkipTest('https://pulp.plan.io/issues/2277')

        # Create a repository. Add a yum distributor and publish it.
        client = api.Client(cls.cfg, api.json_handler)
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch and parse repomd.xml
        client.response_handler = xml_handler
        path = urljoin('/pulp/repos/', distributor['config']['relative_url'])
        path = urljoin(path, 'repodata/repomd.xml')
        cls.root_element = client.get(path)
    def setUpClass(cls):
        """Upload an erratum to a repo, publish, and download the erratum.

        Do the following:

        1. Create an RPM repository with a distributor.
        2. Upload an erratum to the repository.
        3. Publish the repository.
        4. Fetch the repository's ``updateinfo.xml`` file.
        """
        super(UploadErratumTestCase, cls).setUpClass()
        cls.erratum = gen_erratum()

        # Create an RPM repository with a feed and distributor.
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Sync content into the repository, and give it an erratum.
        utils.sync_repo(cls.cfg, repo['_href'])
        utils.upload_import_erratum(cls.cfg, cls.erratum, repo['_href'])
        repo = client.get(repo['_href'], params={'details': True})

        # Publish the repository, and fetch and parse updateinfo.xml
        distributor = repo['distributors'][0]
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )
        path = urljoin('/pulp/repos/', distributor['config']['relative_url'])
        cls.updateinfo = get_repomd_xml(cls.cfg, path, 'updateinfo')
    def setUpClass(cls):
        """Create, sync and publish a repository. Fetch its ``comps.xml``."""
        super(SyncRepoTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)

        # Create a repo.
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Sync and publish the repo.
        repo = client.get(repo['_href'], params={'details': True})
        utils.sync_repo(cls.cfg, repo['_href'])
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': repo['distributors'][0]['id']},
        )
        repo = client.get(repo['_href'], params={'details': True})

        # Fetch and parse comps.xml.
        dist = repo['distributors'][0]
        dist_url = urljoin('/pulp/repos/', dist['config']['relative_url'])
        cls.root_element = get_repomd_xml(cls.cfg, dist_url, 'group')
        cls.xml_as_str = ElementTree.tostring(cls.root_element)
    def setUpClass(cls):
        """Create, sync and publish a repository. Fetch its ``comps.xml``."""
        super(SyncRepoTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)

        # Create a repo.
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Sync and publish the repo.
        repo = client.get(repo['_href'], params={'details': True})
        utils.sync_repo(cls.cfg, repo['_href'])
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': repo['distributors'][0]['id']},
        )
        repo = client.get(repo['_href'], params={'details': True})

        # Fetch and parse comps.xml.
        dist = repo['distributors'][0]
        dist_url = urljoin('/pulp/repos/', dist['config']['relative_url'])
        cls.root_element = get_repomd_xml(cls.cfg, dist_url, 'group')
        cls.xml_as_str = ElementTree.tostring(cls.root_element)
    def setUpClass(cls):
        """Create an RPM repository, upload package groups, and publish."""
        super(UploadPackageGroupsTestCase, cls).setUpClass()

        # Create a repository and add a distributor to it.
        client = api.Client(cls.cfg, api.json_handler)
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )

        # Generate several package groups, import them into the repository, and
        # publish the repository.
        cls.package_groups = {
            'minimal': _gen_minimal_group(),
            'realistic': _gen_realistic_group(),
        }
        cls.tasks = {}
        for key, package_group in cls.package_groups.items():
            report = _upload_import_package_group(cls.cfg, repo, package_group)
            cls.tasks[key] = tuple(api.poll_spawned_tasks(cls.cfg, report))
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch the generated repodata of type 'group' (a.k.a. 'comps')
        cls.root_element = get_repomd_xml(
            cls.cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'group'
        )
Example #14
0
    def setUpClass(cls):
        """Publish a yum repo containing some updates."""
        super(UpdateInfoTestCase, cls).setUpClass()

        cls.tasks = {}
        cls.errata = {}

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

        # Create a repository for use by the test.
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])

        # add yum distributor to the repo
        distribute = client.post(urljoin(repo['_href'], 'distributors/'),
                                 gen_distributor())

        # import some errata
        cls.import_updates(client, repo)

        # ask for it to be published
        client.post(urljoin(repo['_href'], 'actions/publish/'),
                    {'id': distribute['id']})

        repo_url = urljoin('/pulp/repos/',
                           distribute['config']['relative_url'])
        cls.updateinfo_tree = cls.get_repodata_xml(repo_url, 'updateinfo')
Example #15
0
    def setUpClass(cls):
        """Generate, fetch and parse a ``repomd.xml`` file.

        Do the following:

        1. Create an RPM repository with a YUM distributor and publish it.
        2. Fetch the ``repomd.xml`` file from the distributor, and parse it.
        """
        super(RepoMDTestCase, cls).setUpClass()
        if check_issue_2277(cls.cfg):
            raise unittest.SkipTest('https://pulp.plan.io/issues/2277')

        # Create a repository with a yum distributor and publish it.
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        repo = client.get(repo['_href'], params={'details': True})
        cls.resources.add(repo['_href'])
        utils.publish_repo(cls.cfg, repo)

        # Fetch and parse repomd.xml
        client.response_handler = xml_handler
        path = urljoin(
            '/pulp/repos/',
            repo['distributors'][0]['config']['relative_url'],
        )
        path = urljoin(path, 'repodata/repomd.xml')
        cls.root_element = client.get(path)
    def test_publish_override_config(self):
        """Use the ``packages_directory`` publish override option.

        Create a distributor with default options, and use it to publish the
        repository. Specify the ``packages_directory`` option during the
        publish as an override option. Verify packages end up in the specified
        directory, relative to the published repository's root.
        """
        if selectors.bug_is_untestable(1976, self.cfg.version):
            self.skipTest('https://pulp.plan.io/issues/1976')
        client = api.Client(self.cfg, api.json_handler)
        distributor = client.post(
            urljoin(self.repo_href, 'distributors/'),
            gen_distributor(),
        )
        packages_dir = utils.uuid4()
        client.post(urljoin(self.repo_href, 'actions/publish/'), {
            'id': distributor['id'],
            'override_config': {'packages_directory': packages_dir},
        })
        primary_xml = get_parse_repodata_primary_xml(self.cfg, distributor)
        package_hrefs = get_package_hrefs(primary_xml)
        self.assertGreater(len(package_hrefs), 0)
        for package_href in package_hrefs:
            with self.subTest(package_href=package_href):
                self.assertEqual(os.path.dirname(package_href), packages_dir)
    def make_repo(self, cfg, remote):
        """Create a repository with an importer and pair of distributors.

        Create an RPM repository with:

        * A yum importer with a valid feed.
        * A yum distributor.
        * An RPM rsync distributor referencing the yum distributor.

        In addition, schedule the repository for deletion.

        :param pulp_smash.config.ServerConfig cfg: Information about the Pulp
            server being targeted.
        :param remote: A dict for the RPM rsync distributor's ``remote``
            section.
        :returns: The repository's href, as a string.
        """
        api_client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        body['distributors'] = [gen_distributor()]
        body['distributors'].append({
            'distributor_id': utils.uuid4(),
            'distributor_type_id': 'rpm_rsync_distributor',
            'distributor_config': {
                'predistributor_id': body['distributors'][0]['distributor_id'],
                'remote': remote,
            }
        })
        repo_href = api_client.post(REPOSITORY_PATH, body)['_href']
        self.addCleanup(api_client.delete, repo_href)
        return repo_href
    def setUpClass(cls):
        """Bind a consumer to a distributor.

        Do the following:

        1. Add a consumer.
        2. Add a repository.
        3. Add a distributor to the repository.
        4. Bind the consumer to the distributor.
        """
        super(BindConsumerTestCase, cls).setUpClass()

        # Steps 1–3
        client = api.Client(cls.cfg, api.json_handler)
        cls.consumer = client.post(CONSUMER_PATH, {'id': utils.uuid4()})
        repository = client.post(REPOSITORY_PATH, gen_repo())
        distributor = client.post(
            urljoin(repository['_href'], 'distributors/'), gen_distributor())
        cls.resources.add(repository['_href'])

        # Step 4
        client.response_handler = api.safe_handler
        path = urljoin(CONSUMER_PATH, cls.consumer['consumer']['id'] + '/')
        path = urljoin(path, 'bindings/')
        cls.request = {
            'binding_config': {
                'B': 21
            },
            'distributor_id': distributor['id'],
            'notify_agent': False,
            'repo_id': distributor['repo_id'],
        }
        cls.response = client.post(path, cls.request)
    def make_repo(self, cfg, dist_cfg_updates):
        """Create a repository with an importer and pair of distributors.

        Create an RPM repository with:

        * A yum importer with a valid feed.
        * A yum distributor.
        * An RPM rsync distributor referencing the yum distributor.

        In addition, schedule the repository for deletion.

        :param pulp_smash.config.ServerConfig cfg: Information about the Pulp
            server being targeted.
        :param dist_cfg_updates: A dict to be merged into the RPM rsync
            distributor's ``distributor_config`` dict. At a minimum, this
            argument should have a value of ``{'remote': {…}}``.
        :returns: The repository's href, as a string.
        """
        api_client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        body['distributors'].append({
            'distributor_id': utils.uuid4(),
            'distributor_type_id': 'rpm_rsync_distributor',
            'distributor_config': {
                'predistributor_id': body['distributors'][0]['distributor_id'],
            }
        })
        body['distributors'][1]['distributor_config'].update(dist_cfg_updates)
        repo_href = api_client.post(REPOSITORY_PATH, body)['_href']
        self.addCleanup(api_client.delete, repo_href)
        return repo_href
    def setUpClass(cls):
        """Create a schedule to publish the repository.

        Do the following:

        1. Create a repository with a valid feed
        2. Sync it
        3. Schedule publish to run every 30 seconds
        """
        super(CreateSuccessTestCase, cls).setUpClass()
        client = api.Client(cls.cfg)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        repo = client.post(REPOSITORY_PATH, body).json()
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])

        # Schedule a publish to run every 30 seconds
        distributor = gen_distributor()
        distributor_url = urljoin(repo['_href'], 'distributors/')
        client.post(distributor_url, distributor)
        scheduling_url = urljoin(
            distributor_url,
            '{}/schedules/publish/'.format(distributor['distributor_id']),
        )
        cls.response = client.post(scheduling_url, {'schedule': 'PT30S'})
        cls.attrs = cls.response.json()
Example #21
0
    def setUpClass(cls):
        """Creates, publishes repo and fetches repomd.xml."""
        super(RepoMDTestCase, cls).setUpClass()

        cls.tasks = {}
        cls.errata = {}

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

        # Create a repository for use by the test.
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])

        # add yum distributor to the repo
        distribute = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor())

        # ask for it to be published
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distribute['id']})

        # fetch the repomd.xml
        repo_url = urljoin('/pulp/repos/',
                           distribute['config']['relative_url'])
        repomd_url = urljoin(repo_url, 'repodata/repomd.xml')

        client = api.Client(cls.cfg, xml_handler)
        cls.repomd_tree = client.get(repomd_url)
Example #22
0
    def health_check(self):
        """Execute step three of the test plan."""
        client = api.Client(self.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(api.Client(self.cfg).delete, repo['_href'])
        client.post(
            urljoin(repo['_href'], 'actions/sync/'),
            {'override_config': {}},
        )
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )
        client.response_handler = api.safe_handler
        url = urljoin('/pulp/repos/', distributor['config']['relative_url'])
        url = urljoin(url, RPM)
        pulp_rpm = client.get(url).content

        # Does this RPM match the original RPM?
        rpm = client.get(urljoin(RPM_FEED_URL, RPM)).content
        self.assertEqual(rpm, pulp_rpm)
    def setUpClass(cls):
        """Create a schedule to publish a repo, verify the ``total_run_count``.

        Do the following:

        1. Create a repository with a valid feed
        2. Sync it
        3. Schedule publish to run every 2 minutes
        4. Wait for 130 seconds and read the schedule to get the number of
           "publish" runs
        """
        super(ScheduledPublishTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body["importer_config"]["feed"] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo["_href"])
        utils.sync_repo(cls.cfg, repo["_href"])

        # Schedule a publish to run every 2 minutes
        distributor = gen_distributor()
        client.post(urljoin(repo["_href"], "distributors/"), distributor)
        scheduling_url = "/".join(["distributors", distributor["distributor_id"], "schedules/publish/"])
        schedule_path = urljoin(repo["_href"], scheduling_url)
        schedule = client.post(schedule_path, {"schedule": "PT2M"})

        # Wait for publish to run
        time.sleep(130)

        # Read the schedule
        cls.response = client.get(schedule["_href"])
Example #24
0
    def setUpClass(cls):
        """Generate, fetch and parse a ``repomd.xml`` file.

        Do the following:

        1. Create an RPM repository, add a YUM distributor, and publish the
           repository.
        2. Fetch the ``repomd.xml`` file from the distributor, and parse it.
        """
        super(RepoMDTestCase, cls).setUpClass()

        # Create a repository. Add a yum distributor and publish it.
        client = api.Client(cls.cfg, api.json_handler)
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch and parse repomd.xml
        client.response_handler = xml_handler
        path = urljoin('/pulp/repos/', distributor['config']['relative_url'])
        path = urljoin(path, 'repodata/repomd.xml')
        cls.root_element = client.get(path)
    def setUpClass(cls):
        """Create an RPM repository, upload package groups, and publish."""
        super(UploadPackageGroupsTestCase, cls).setUpClass()

        # Create a repository and add a distributor to it.
        client = api.Client(cls.cfg, api.json_handler)
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )

        # Generate several package groups, import them into the repository, and
        # publish the repository.
        cls.package_groups = {
            'minimal': _gen_minimal_group(),
            'realistic': _gen_realistic_group(),
        }
        cls.tasks = {}
        for key, package_group in cls.package_groups.items():
            report = _upload_import_package_group(cls.cfg, repo, package_group)
            cls.tasks[key] = tuple(api.poll_spawned_tasks(cls.cfg, report))
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch the generated repodata of type 'group' (a.k.a. 'comps')
        cls.root_element = get_repomd_xml(
            cls.cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'group')
Example #26
0
def _create_distributor(
        server_config, href, distributor_type_id, checksum_type=None):
    """Create an export distributor for the entity at ``href``."""
    path = urljoin(href, 'distributors/')
    body = gen_distributor()
    body['distributor_type_id'] = distributor_type_id
    if checksum_type is not None:
        body['distributor_config']['checksum_type'] = checksum_type
    return api.Client(server_config).post(path, body).json()
Example #27
0
    def test_all(self):
        """Sync a repo whose updateinfo file has multiple pkglist sections.

        Do the following:

        1. Create and sync a repository with an importer and distributor.
           Ensure the importer's feed is set to
           :data:`pulp_smash.constants.RPM_PKGLISTS_UPDATEINFO_FEED_URL`.
        2. Publish the repository, and fetch and parse its updateinfo file.
        3. Verify the updateinfo contains the correct number of ``<pkglists>``
           sections, with the correct contents in each.
        """
        cfg = config.get_config()
        if selectors.bug_is_untestable(2227, cfg.version):
            self.skipTest('https://pulp.plan.io/issues/2277')

        # Create and sync a repository.
        client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_PKGLISTS_UPDATEINFO_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(client.delete, repo['_href'])
        utils.sync_repo(cfg, repo['_href'])

        # Publish the repository, and fetch and parse its updateinfo file.
        repo = client.get(repo['_href'], params={'details': True})
        self.assertEqual(len(repo['distributors']), 1, repo['distributors'])
        distributor = repo['distributors'][0]
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )
        root_element = get_repomd_xml(
            cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'updateinfo'
        )

        # Verify the contents of the updateinfo file.
        debug = ElementTree.tostring(root_element)
        pkglists = root_element.find('update').findall('pkglist')
        self.assertEqual(len(pkglists), 3, debug)

        collections = [pkglist.find('collection') for pkglist in pkglists]
        names = {collection.find('name').text for collection in collections}
        self.assertEqual(names, {'1', '2', '3'}, debug)

        packages = {
            collection.find('package').find('filename').text
            for collection in collections
        }
        self.assertEqual(packages, {
            'penguin-0.9.1-1.noarch.rpm',
            'shark-0.1-1.noarch.rpm',
            'walrus-5.21-1.noarch.rpm',
        }, debug)
    def setUpClass(cls):  # pylint:disable=arguments-differ
        """Create two repositories, first is feed of second one.

        Provides server config and set of iterable to delete. Following steps
        are executed:

        1. Create repository foo with feed, sync and publish it.
        2. Create repository bar with foo as a feed with
           ``retain_old_count=0``.
        3. Run sync of repo foo.
        4. Get information on both repositories.
        """
        super(RetainOldCountTestCase, cls).setUpClass()
        client = api.Client(cls.cfg)
        cls.responses = {}
        hrefs = []  # repository hrefs

        # Create and sync the first repository.
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        hrefs.append(client.post(REPOSITORY_PATH, body).json()['_href'])
        cls.responses['first sync'] = client.post(
            urljoin(hrefs[0], 'actions/sync/'),
            {'override_config': {}}
        )

        # Add distributor and publish
        cls.responses['distribute'] = client.post(
            urljoin(hrefs[0], 'distributors/'),
            gen_distributor(),
        )
        cls.responses['publish'] = client.post(
            urljoin(hrefs[0], 'actions/publish/'),
            {'id': cls.responses['distribute'].json()['id']},
        )

        # Create and sync the second repository. Ensure it fetches content from
        # the first, and that the `retain_old_count` option is set correctly.
        # We disable SSL validation for a practical reason: each HTTPS feed
        # must have a certificate to work, which is burdensome to do here.
        body = gen_repo()
        body['importer_config']['feed'] = urljoin(
            cls.cfg.base_url,
            _PUBLISH_DIR +
            cls.responses['distribute'].json()['config']['relative_url'],
        )
        body['importer_config']['retain_old_count'] = 0  # see docstring
        body['importer_config']['ssl_validation'] = False
        hrefs.append(client.post(REPOSITORY_PATH, body).json()['_href'])
        cls.responses['second sync'] = client.post(
            urljoin(hrefs[1], 'actions/sync/'),
            {'override_config': {}}
        )

        # Read the repositories and mark them for deletion.
        cls.repos = [client.get(href).json() for href in hrefs]
        cls.resources.update(set(hrefs))
    def setUpClass(cls):
        """Create several schedules.

        Each schedule is created to test a different failure scenario.
        """
        super(CreateFailureTestCase, cls).setUpClass()
        client = api.Client(cls.cfg)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        repo = client.post(REPOSITORY_PATH, body).json()
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])

        # Add a distibutor
        distributor = gen_distributor()
        client.post(urljoin(repo['_href'], 'distributors/'), distributor)
        client.response_handler = api.echo_handler
        cls.bodies = (
            {
                'schedule': None
            },  # 400
            {
                'unknown': 'parameter',
                'schedule': 'PT30S'
            },  # 400
            ['Incorrect data type'],  # 400
            {
                'missing_required_keys': 'schedule'
            },  # 400
            {
                'schedule': 'PT30S'
            },  # tests incorrect distributor in url, 404
            {
                'schedule': 'PT30S'
            },  # tests incorrect repo in url, 404
        )
        scheduling_url = '/'.join([
            'distributors', distributor['distributor_id'], 'schedules/publish/'
        ])
        bad_distributor_url = '/'.join(
            ['distributors',
             utils.uuid4(), 'schedules/publish/'])
        bad_repo_path = '/'.join([REPOSITORY_PATH, utils.uuid4()])
        cls.paths = (urljoin(repo['_href'], scheduling_url),
                     urljoin(repo['_href'], scheduling_url),
                     urljoin(repo['_href'], scheduling_url),
                     urljoin(repo['_href'], scheduling_url),
                     urljoin(repo['_href'], bad_distributor_url),
                     urljoin(bad_repo_path, scheduling_url))
        cls.status_codes = (400, 400, 400, 400, 404, 404)
        cls.responses = [
            client.post(path, req_body)
            for path, req_body in zip(cls.paths, cls.bodies)
        ]
Example #30
0
def _create_distributor(server_config,
                        href,
                        distributor_type_id,
                        checksum_type=None):
    """Create an export distributor for the entity at ``href``."""
    path = urljoin(href, 'distributors/')
    body = gen_distributor()
    body['distributor_type_id'] = distributor_type_id
    if checksum_type is not None:
        body['distributor_config']['checksum_type'] = checksum_type
    return api.Client(server_config).post(path, body).json()
 def setUpClass(cls):
     """Create and sync a repository."""
     super(ForceFullTestCase, cls).setUpClass()
     client = api.Client(cls.cfg, api.json_handler)
     body = gen_repo()
     body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
     body['distributors'] = [gen_distributor()]
     repo = client.post(REPOSITORY_PATH, body)
     cls.resources.add(repo['_href'])
     utils.sync_repo(cls.cfg, repo['_href'])
     cls.repo = client.get(repo['_href'], params={'details': True})
 def setUpClass(cls):
     """Create and sync a repository."""
     super(ForceFullTestCase, cls).setUpClass()
     client = api.Client(cls.cfg, api.json_handler)
     body = gen_repo()
     body['importer_config']['feed'] = RPM_FEED_URL
     body['distributors'] = [gen_distributor()]
     repo = client.post(REPOSITORY_PATH, body)
     cls.resources.add(repo['_href'])
     utils.sync_repo(cls.cfg, repo['_href'])
     cls.repo = client.get(repo['_href'], params={'details': True})
    def setUpClass(cls):  # pylint:disable=arguments-differ
        """Create two repositories, first is feed of second one.

        Provides server config and set of iterable to delete. Following steps
        are executed:

        1. Create repository foo with feed, sync and publish it.
        2. Create repository bar with foo as a feed with
           ``retain_old_count=0``.
        3. Run sync of repo foo.
        4. Get information on both repositories.
        """
        super(RetainOldCountTestCase, cls).setUpClass()
        if check_issue_2277(cls.cfg):
            raise unittest.SkipTest('https://pulp.plan.io/issues/2277')
        client = api.Client(cls.cfg)
        cls.responses = {}
        hrefs = []  # repository hrefs

        # Create and sync the first repository.
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        hrefs.append(client.post(REPOSITORY_PATH, body).json()['_href'])
        cls.responses['first sync'] = utils.sync_repo(cls.cfg, hrefs[0])

        # Add distributor and publish
        cls.responses['distribute'] = client.post(
            urljoin(hrefs[0], 'distributors/'),
            gen_distributor(),
        )
        cls.responses['publish'] = client.post(
            urljoin(hrefs[0], 'actions/publish/'),
            {'id': cls.responses['distribute'].json()['id']},
        )

        # Create and sync the second repository. Ensure it fetches content from
        # the first, and that the `retain_old_count` option is set correctly.
        # We disable SSL validation for a practical reason: each HTTPS feed
        # must have a certificate to work, which is burdensome to do here.
        body = gen_repo()
        body['importer_config']['feed'] = urljoin(
            cls.cfg.base_url,
            _PUBLISH_DIR +
            cls.responses['distribute'].json()['config']['relative_url'],
        )
        body['importer_config']['retain_old_count'] = 0  # see docstring
        body['importer_config']['ssl_validation'] = False
        hrefs.append(client.post(REPOSITORY_PATH, body).json()['_href'])
        cls.responses['second sync'] = utils.sync_repo(cls.cfg, hrefs[1])

        # Read the repositories and mark them for deletion.
        cls.repos = [client.get(href).json() for href in hrefs]
        cls.resources.update(set(hrefs))
Example #34
0
    def test_all(self):
        """Publish a repository with the repoview feature on and off."""
        cfg = config.get_config()
        if cfg.version < Version('2.9'):
            self.skipTest('https://pulp.plan.io/issues/189')

        # Create a repo, and add content
        client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['distributors'] = [gen_distributor()]
        repo_href = client.post(constants.REPOSITORY_PATH, body)['_href']
        self.addCleanup(client.delete, repo_href)
        rpm = utils.http_get(constants.RPM_UNSIGNED_URL)
        utils.upload_import_unit(cfg, rpm, 'rpm', repo_href)

        # Gather some facts about the repo distributor
        dist = client.get(urljoin(repo_href, 'distributors/'))[0]
        dist_url = urljoin('/pulp/repos/', dist['config']['relative_url'])

        # Publish the repo
        client.response_handler = api.safe_handler
        client.post(urljoin(repo_href, 'actions/publish/'), {'id': dist['id']})
        response = client.get(dist_url)
        with self.subTest(comment='first publish'):
            self.assertEqual(len(response.history), 0, response.history)

        # Publish the repo a second time
        client.post(
            urljoin(repo_href, 'actions/publish/'),
            {
                'id': dist['id'],
                'override_config': {
                    'generate_sqlite': True,
                    'repoview': True,
                }
            },
        )
        response = client.get(dist_url)
        with self.subTest(comment='second publish'):
            self.assertEqual(len(response.history), 1, response.history)
            self.assertEqual(
                response.request.url,
                urljoin(response.history[0].request.url,
                        'repoview/index.html'))

        # Publish the repo a third time
        if selectors.bug_is_untestable(2349, cfg.version):
            self.skipTest('https://pulp.plan.io/issues/2349')
        client.post(urljoin(repo_href, 'actions/publish/'), {'id': dist['id']})
        response = client.get(dist_url)
        with self.subTest(comment='third publish'):
            self.assertEqual(len(response.history), 0, response.history)
Example #35
0
    def _create_sync_repo(self, cfg):
        """Create and sync a repository. Return a detailed dict of repo info.

        Also, schedule the repository for deletion with ``addCleanup()``.
        """
        client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_UNSIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(client.delete, repo['_href'])
        utils.sync_repo(cfg, repo['_href'])
        repo = client.get(repo['_href'], params={'details': True})
        return client.get(repo['_href'], params={'details': True})
Example #36
0
    def _create_sync_repo(self, cfg):
        """Create and sync a repository. Return a detailed dict of repo info.

        Also, schedule the repository for deletion with ``addCleanup()``.
        """
        client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_UNSIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(client.delete, repo['_href'])
        utils.sync_repo(cfg, repo['_href'])
        repo = client.get(repo['_href'], params={'details': True})
        return client.get(repo['_href'], params={'details': True})
def _create_repo(server_config, download_policy):
    """Create an RPM repository with the given download policy.

    The repository has a valid feed and is configured to auto-publish. Return
    the JSON-decoded response body.
    """
    body = gen_repo()
    body['importer_config']['download_policy'] = download_policy
    body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
    distributor = gen_distributor()
    distributor['auto_publish'] = True
    distributor['distributor_config']['relative_url'] = body['id']
    body['distributors'] = [distributor]
    return api.Client(server_config).post(REPOSITORY_PATH, body).json()
Example #38
0
def _create_repo(server_config, download_policy):
    """Create an RPM repository with the given download policy.

    The repository has a valid feed and is configured to auto-publish. Return
    the JSON-decoded response body.
    """
    body = gen_repo()
    body['importer_config']['download_policy'] = download_policy
    body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
    distributor = gen_distributor()
    distributor['auto_publish'] = True
    distributor['distributor_config']['relative_url'] = body['id']
    body['distributors'] = [distributor]
    return api.Client(server_config).post(REPOSITORY_PATH, body).json()
    def setUpClass(cls):
        """Create several schedules.

        Each schedule is created to test a different failure scenario.
        """
        super(CreateFailureTestCase, cls).setUpClass()
        client = api.Client(cls.cfg)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body).json()
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])

        # Add a distibutor
        distributor = gen_distributor()
        client.post(
            urljoin(repo['_href'], 'distributors/'),
            distributor
        )
        client.response_handler = api.echo_handler
        cls.bodies = (
            {'schedule': None},  # 400
            {'unknown': 'parameter', 'schedule': 'PT30S'},  # 400
            ['Incorrect data type'],  # 400
            {'missing_required_keys': 'schedule'},  # 400
            {'schedule': 'PT30S'},  # tests incorrect distributor in url, 404
            {'schedule': 'PT30S'},  # tests incorrect repo in url, 404
        )
        scheduling_url = '/'.join([
            'distributors', distributor['distributor_id'], 'schedules/publish/'
        ])
        bad_distributor_url = '/'.join([
            'distributors', utils.uuid4(), 'schedules/publish/'
        ])
        bad_repo_path = '/'.join([REPOSITORY_PATH, utils.uuid4()])
        cls.paths = (
            urljoin(repo['_href'], scheduling_url),
            urljoin(repo['_href'], scheduling_url),
            urljoin(repo['_href'], scheduling_url),
            urljoin(repo['_href'], scheduling_url),
            urljoin(repo['_href'], bad_distributor_url),
            urljoin(bad_repo_path, scheduling_url)
        )
        cls.status_codes = (400, 400, 400, 400, 404, 404)
        cls.responses = [
            client.post(path, req_body) for path, req_body in zip(
                cls.paths, cls.bodies)
        ]
Example #40
0
    def setUpClass(cls):
        """Create RPM repository, delete a package, and publish the repository.

        More specifically, do the following:

        1. Create an RPM repository.
        2. Add a YUM distributor.
        3. Sync the created repository.
        4. Remove the ``gorilla`` package
        5. Publish the repository. Fetch the ``updateinfo.xml`` file from the
           distributor (via ``repomd.xml``), and parse it.
        """
        super(ErratumPkgListCountTestCase, cls).setUpClass()

        # Create a repository, sync it, and add a yum distributor.
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )

        # Remove the gorilla package unit
        client.post(
            urljoin(repo['_href'], 'actions/unassociate/'),
            {'criteria': get_unit_unassociate_criteria(RPM_ERRATUM_RPM_NAME)},
        )

        # Publish the repository
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch and parse updateinfo.xml (or updateinfo.xml.gz), via repomd.xml
        root_element = get_repomd_xml(
            cls.cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'updateinfo'
        )

        # Fetch the erratum and erratum pkglist for the gorilla package
        updates = _get_updates_by_id(root_element)
        erratum = updates[RPM_ERRATUM_ID]
        cls.erratum_pkglists = erratum.findall('pkglist')
Example #41
0
    def setUpClass(cls):
        """Create RPM repository, delete a package, and publish the repository.

        More specifically, do the following:

        1. Create an RPM repository.
        2. Add a YUM distributor.
        3. Sync the created repository.
        4. Remove the ``gorilla`` package
        5. Publish the repository. Fetch the ``updateinfo.xml`` file from the
           distributor (via ``repomd.xml``), and parse it.
        """
        super(ErratumPkgListCountTestCase, cls).setUpClass()

        # Create a repository, sync it, and add a yum distributor.
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )

        # Remove the gorilla package unit
        client.post(
            urljoin(repo['_href'], 'actions/unassociate/'),
            {'criteria': get_unit_unassociate_criteria(RPM_ERRATUM_RPM_NAME)},
        )

        # Publish the repository
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch and parse updateinfo.xml (or updateinfo.xml.gz), via repomd.xml
        root_element = get_repomd_xml(
            cls.cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'updateinfo'
        )

        # Fetch the erratum and erratum pkglist for the gorilla package
        updates = _get_updates_by_id(root_element)
        erratum = updates[RPM_ERRATUM_ID]
        cls.erratum_pkglists = erratum.findall('pkglist')
    def setUpClass(cls):
        """Create three schedules and read, update and delete them."""
        super(ReadUpdateDeleteTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body['importer_config']['feed'] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])

        # Create schedules
        distributor = gen_distributor()
        client.post(
            urljoin(repo['_href'], 'distributors/'),
            distributor
        )
        scheduling_url = '/'.join([
            'distributors', distributor['distributor_id'], 'schedules/publish/'
        ])
        scheduling_path = urljoin(repo['_href'], scheduling_url)
        cls.schedules = tuple((
            client.post(scheduling_path, {'schedule': 'PT30S'})
            for _ in range(3)
        ))
        cls.responses = {}
        client.response_handler = api.safe_handler

        # Attributes that may be changed after creation
        cls.mutable_attrs = [
            'consecutive_failures', 'last_run_at', 'last_updated', 'next_run',
            'first_run', 'remaining_runs', 'total_run_count'
        ]

        # Read the first schedule
        cls.responses['read_one'] = client.get(cls.schedules[0]['_href'])

        # Read all schedules for the repo
        cls.responses['read_many'] = client.get(scheduling_path)

        # Update the second schedule
        cls.update_body = {'schedule': 'PT1M'}
        cls.responses['update'] = client.put(
            cls.schedules[1]['_href'], cls.update_body
        )

        # Delete the third schedule
        cls.responses['delete'] = client.delete(cls.schedules[2]['_href'])
    def test_all(self):
        """Publish a repository with the repoview feature on and off."""
        cfg = config.get_config()
        if cfg.version < Version('2.9'):
            self.skipTest('https://pulp.plan.io/issues/189')

        # Create a repo, and add content
        client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['distributors'] = [gen_distributor()]
        repo_href = client.post(constants.REPOSITORY_PATH, body)['_href']
        self.addCleanup(client.delete, repo_href)
        rpm = utils.http_get(constants.RPM_UNSIGNED_URL)
        utils.upload_import_unit(cfg, rpm, 'rpm', repo_href)

        # Gather some facts about the repo distributor
        dist = client.get(urljoin(repo_href, 'distributors/'))[0]
        dist_url = urljoin('/pulp/repos/', dist['config']['relative_url'])

        # Publish the repo
        client.response_handler = api.safe_handler
        client.post(urljoin(repo_href, 'actions/publish/'), {'id': dist['id']})
        response = client.get(dist_url)
        with self.subTest(comment='first publish'):
            self.assertEqual(len(response.history), 0, response.history)

        # Publish the repo a second time
        client.post(
            urljoin(repo_href, 'actions/publish/'),
            {'id': dist['id'], 'override_config': {
                'generate_sqlite': True,
                'repoview': True,
            }},
        )
        response = client.get(dist_url)
        with self.subTest(comment='second publish'):
            self.assertEqual(len(response.history), 1, response.history)
            self.assertEqual(
                response.request.url,
                urljoin(response.history[0].request.url, 'repoview/index.html')
            )

        # Publish the repo a third time
        if selectors.bug_is_untestable(2349, cfg.version):
            self.skipTest('https://pulp.plan.io/issues/2349')
        client.post(urljoin(repo_href, 'actions/publish/'), {'id': dist['id']})
        response = client.get(dist_url)
        with self.subTest(comment='third publish'):
            self.assertEqual(len(response.history), 0, response.history)
Example #44
0
    def test_all(self):
        """Publish a repository with the repoview feature on and off."""
        cfg = config.get_config()
        if cfg.version < Version('2.9'):
            self.skipTest('https://pulp.plan.io/issues/189')

        # Create a repo, and add content
        client = api.Client(cfg)
        body = gen_repo()
        body['distributors'] = [gen_distributor()]
        repo = client.post(constants.REPOSITORY_PATH, body).json()
        self.addCleanup(client.delete, repo['_href'])
        rpm = utils.http_get(constants.RPM_UNSIGNED_URL)
        utils.upload_import_unit(cfg, rpm, 'rpm', repo['_href'])

        # Get info about the repo distributor
        repo = client.get(repo['_href'], params={'details': True}).json()
        pub_path = urljoin(
            '/pulp/repos/',
            repo['distributors'][0]['config']['relative_url']
        )

        # Publish the repo
        utils.publish_repo(cfg, repo)
        response = client.get(pub_path)
        with self.subTest(comment='first publish'):
            self.assertEqual(len(response.history), 0, response.history)

        # Publish the repo a second time
        utils.publish_repo(cfg, repo, {
            'id': repo['distributors'][0]['id'],
            'override_config': {'generate_sqlite': True, 'repoview': True},
        })
        response = client.get(pub_path)
        with self.subTest(comment='second publish'):
            self.assertEqual(len(response.history), 1, response.history)
            self.assertEqual(
                response.request.url,
                urljoin(response.history[0].request.url, 'repoview/index.html')
            )

        # Publish the repo a third time
        if selectors.bug_is_untestable(2349, cfg.version):
            self.skipTest('https://pulp.plan.io/issues/2349')
        utils.publish_repo(cfg, repo)
        response = client.get(pub_path)
        with self.subTest(comment='third publish'):
            self.assertEqual(len(response.history), 0, response.history)
Example #45
0
    def health_check(self):
        """Execute step three of the test plan."""
        client = api.Client(self.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(client.delete, repo['_href'])
        repo = client.get(repo['_href'], params={'details': True})
        utils.sync_repo(self.cfg, repo['_href'])
        utils.publish_repo(self.cfg, repo)
        pulp_rpm = get_unit(self.cfg, repo, RPM).content

        # Does this RPM match the original RPM?
        rpm = utils.http_get(RPM_SIGNED_URL)
        self.assertEqual(rpm, pulp_rpm)
Example #46
0
    def setUpClass(cls):
        """Create an RPM repository, upload errata, and publish the repository.

        More specifically, do the following:

        1. Create an RPM repository.
        2. Add a YUM distributor.
        3. Generate a pair of errata. Upload them to Pulp and import them into
           the repository.
        4. Publish the repository. Fetch the ``updateinfo.xml`` file from the
           distributor (via ``repomd.xml``), and parse it.
        """
        super(UpdateInfoTestCase, cls).setUpClass()
        cls.errata = {
            'import_no_pkglist': _gen_errata_no_pkglist(),
            'import_typical': _gen_errata_typical(),
        }
        cls.tasks = {}  # {'import_no_pkglist': (…), 'import_typical': (…)}

        # Create a repository and add a yum distributor.
        client = api.Client(cls.cfg, api.json_handler)
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )

        # Import errata into our repository. Publish the repository.
        for key, erratum in cls.errata.items():
            report = utils.upload_import_erratum(
                cls.cfg,
                erratum,
                repo['_href'],
            )
            cls.tasks[key] = tuple(api.poll_spawned_tasks(cls.cfg, report))
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch and parse updateinfo.xml (or updateinfo.xml.gz), via repomd.xml
        cls.root_element = get_repomd_xml(
            cls.cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'updateinfo'
        )
Example #47
0
    def setUpClass(cls):
        """Create an RPM repository, upload errata, and publish the repository.

        More specifically, do the following:

        1. Create an RPM repository.
        2. Add a YUM distributor.
        3. Generate a pair of errata. Upload them to Pulp and import them into
           the repository.
        4. Publish the repository. Fetch the ``updateinfo.xml`` file from the
           distributor (via ``repomd.xml``), and parse it.
        """
        super(UpdateInfoTestCase, cls).setUpClass()
        cls.errata = {
            'import_no_pkglist': _gen_errata_no_pkglist(),
            'import_typical': _gen_errata_typical(),
        }
        cls.tasks = {}  # {'import_no_pkglist': (…), 'import_typical': (…)}

        # Create a repository and add a yum distributor.
        client = api.Client(cls.cfg, api.json_handler)
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )

        # Import errata into our repository. Publish the repository.
        for key, erratum in cls.errata.items():
            report = utils.upload_import_erratum(
                cls.cfg,
                erratum,
                repo['_href'],
            )
            cls.tasks[key] = tuple(api.poll_spawned_tasks(cls.cfg, report))
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch and parse updateinfo.xml (or updateinfo.xml.gz), via repomd.xml
        cls.root_element = get_repomd_xml(
            cls.cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'updateinfo'
        )
Example #48
0
    def setUpClass(cls):
        """Create an RPM repository with a valid feed and sync it.

        Do the following:

        1. Reset Pulp, including the Squid cache.
        2. Create a repository. Sync and publish it using the 'on_demand'
           download policy.
        3. Download an RPM from the published repository.
        4. Download the same RPM to ensure it is served by the cache.
        """
        super(SyncOnDemandTestCase, cls).setUpClass()
        if cls.cfg.version < Version('2.8'):
            raise unittest2.SkipTest('This test requires Pulp 2.8 or greater.')

        # Ensure `locally_stored_units` is 0 before we start.
        utils.reset_squid(cls.cfg)
        utils.reset_pulp(cls.cfg)

        # Create a repository
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config'] = {
            'download_policy': 'on_demand',
            'feed': RPM_FEED_URL,
        }
        distributor = gen_distributor()
        distributor['auto_publish'] = True
        distributor['distributor_config']['relative_url'] = body['id']
        body['distributors'] = [distributor]

        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Sync and read the repository
        sync_path = urljoin(repo['_href'], 'actions/sync/')
        client.post(sync_path, {'override_config': {}})
        cls.repo = client.get(repo['_href'], params={'details': True})

        # Download the same RPM twice.
        client.response_handler = api.safe_handler
        path = urljoin('/pulp/repos/', repo['id'] + '/')
        path = urljoin(path, RPM)
        cls.rpm = client.get(path)
        cls.same_rpm = client.get(path)
Example #49
0
    def setUpClass(cls):
        """Create an RPM repository with a valid feed and sync it.

        Do the following:

        1. Reset Pulp, including the Squid cache.
        2. Create a repository. Sync and publish it using the 'on_demand'
           download policy.
        3. Download an RPM from the published repository.
        4. Download the same RPM to ensure it is served by the cache.
        """
        super(SyncOnDemandTestCase, cls).setUpClass()
        if cls.cfg.version < Version('2.8'):
            raise unittest2.SkipTest('This test requires Pulp 2.8 or greater.')

        # Ensure `locally_stored_units` is 0 before we start.
        utils.reset_squid(cls.cfg)
        utils.reset_pulp(cls.cfg)

        # Create a repository
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config'] = {
            'download_policy': 'on_demand',
            'feed': RPM_FEED_URL,
        }
        distributor = gen_distributor()
        distributor['auto_publish'] = True
        distributor['distributor_config']['relative_url'] = body['id']
        body['distributors'] = [distributor]

        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Sync and read the repository
        sync_path = urljoin(repo['_href'], 'actions/sync/')
        client.post(sync_path, {'override_config': {}})
        cls.repo = client.get(repo['_href'], params={'details': True})

        # Download the same RPM twice.
        client.response_handler = api.safe_handler
        path = urljoin('/pulp/repos/', repo['id'] + '/')
        path = urljoin(path, RPM)
        cls.rpm = client.get(path)
        cls.same_rpm = client.get(path)
Example #50
0
    def setUpClass(cls):
        """Create an RPM repository, upload comps metadata, and publish.

        More specifically:

        1. Create a repository.
        2. Add yum distributor to it.
        3. Import fixture group units.
        4. Publish repository.
        5. Fetch and parse generated ``comps.xml``.
        """
        super(CompsGroupsTestCase, cls).setUpClass()

        # Create a repository and add a distributor to it.
        client = api.Client(cls.cfg, api.json_handler)
        repo = client.post(REPOSITORY_PATH, gen_repo())
        cls.resources.add(repo['_href'])
        distributor = client.post(
            urljoin(repo['_href'], 'distributors/'),
            gen_distributor(),
        )

        # Generate several package groups, import them into the repository, and
        # publish the repository.
        #
        # NOTE: The ordering of cls.package_groups matters to test methods! It
        # may be better to make this a dict in the form {label: package_group}.
        cls.package_groups = (_gen_minimal_group(), _gen_realistic_group())
        cls.tasks = {}
        for package_group in cls.package_groups:
            report = _upload_import_package_group(cls.cfg, repo, package_group)
            cls.tasks[package_group['id']] = tuple(
                api.poll_spawned_tasks(cls.cfg, report)
            )
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )

        # Fetch the generated repodata of type 'group' (a.k.a. 'comps')
        cls.root_element = get_repomd_xml(
            cls.cfg,
            urljoin('/pulp/repos/', distributor['config']['relative_url']),
            'group'
        )
Example #51
0
    def health_check(self):
        """Execute step three of the test plan."""
        client = api.Client(self.cfg, api.json_handler)
        body = gen_repo()
        body["importer_config"]["feed"] = RPM_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        self.addCleanup(api.Client(self.cfg).delete, repo["_href"])
        utils.sync_repo(self.cfg, repo["_href"])
        distributor = client.post(urljoin(repo["_href"], "distributors/"), gen_distributor())
        client.post(urljoin(repo["_href"], "actions/publish/"), {"id": distributor["id"]})
        client.response_handler = api.safe_handler
        url = urljoin("/pulp/repos/", distributor["config"]["relative_url"])
        url = urljoin(url, RPM)
        pulp_rpm = client.get(url).content

        # Does this RPM match the original RPM?
        rpm = utils.http_get(RPM_URL)
        self.assertEqual(rpm, pulp_rpm)
    def setUpClass(cls):
        """Create three schedules and read, update and delete them."""
        super(ReadUpdateDeleteTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)

        # Create a repo with a valid feed and sync it
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])
        utils.sync_repo(cls.cfg, repo['_href'])

        # Create schedules
        distributor = gen_distributor()
        client.post(urljoin(repo['_href'], 'distributors/'), distributor)
        scheduling_url = '/'.join([
            'distributors', distributor['distributor_id'], 'schedules/publish/'
        ])
        scheduling_path = urljoin(repo['_href'], scheduling_url)
        cls.schedules = tuple((client.post(scheduling_path,
                                           {'schedule': 'PT30S'})
                               for _ in range(3)))
        cls.responses = {}
        client.response_handler = api.safe_handler

        # Attributes that may be changed after creation
        cls.mutable_attrs = [
            'consecutive_failures', 'last_run_at', 'last_updated', 'next_run',
            'first_run', 'remaining_runs', 'total_run_count'
        ]

        # Read the first schedule
        cls.responses['read_one'] = client.get(cls.schedules[0]['_href'])

        # Read all schedules for the repo
        cls.responses['read_many'] = client.get(scheduling_path)

        # Update the second schedule
        cls.update_body = {'schedule': 'PT1M'}
        cls.responses['update'] = client.put(cls.schedules[1]['_href'],
                                             cls.update_body)

        # Delete the third schedule
        cls.responses['delete'] = client.delete(cls.schedules[2]['_href'])
    def test_default_behaviour(self):
        """Do not use the ``packages_directory`` option.

        Create a distributor with default options, and use it to publish the
        repository. Verify packages end up in the current directory, relative
        to the published repository's root. (This same directory contains the
        ``repodata`` directory, and it may be changed by setting the
        distributor's ``relative_url``.)
        """
        client = api.Client(self.cfg, api.json_handler)
        distributor = client.post(
            urljoin(self.repo_href, 'distributors/'),
            gen_distributor(),
        )
        client.post(urljoin(self.repo_href, 'actions/publish/'),
                    {'id': distributor['id']})
        primary_xml = get_parse_repodata_primary_xml(self.cfg, distributor)
        package_hrefs = get_package_hrefs(primary_xml)
        self.assertGreater(len(package_hrefs), 0)
        for package_href in package_hrefs:
            with self.subTest(package_href=package_href):
                self.assertEqual(os.path.dirname(package_href), '')
    def setUpClass(cls):
        """Publish a repository, remove a unit, and publish it again.

        Specifically, do the following:

        1. Create a repository with a feed and sync it.
        2. Add a distributor to the repository and publish the repository.
        3. Select a content unit at random. Remove it from the repository, and
           re-publish the repository.
        """
        super(RemoveAndRepublishTestCase, cls).setUpClass()

        # Create and sync a repository.
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])  # mark for deletion
        utils.sync_repo(cls.cfg, repo['_href'])

        # Add a distributor and publish the repository to it.
        path = urljoin(repo['_href'], 'distributors/')
        distributor = client.post(path, gen_distributor())
        path = urljoin(repo['_href'], 'actions/publish/')
        client.post(path, {'id': distributor['id']})

        # List RPM content units in the repository. Pick one and remove it.
        # NOTE: There are two versions of the "walrus" RPM, and this works even
        # when that name is picked.
        unit = random.choice(_search_units(cls.cfg, repo['_href'], ('rpm',)))
        cls.unit_id = _get_unit_id(unit)
        _remove_unit(cls.cfg, repo['_href'], unit)

        # Re-publish the repository. sleep() for test_compare_timestamps.
        # Re-read the repository so the test methods have fresh data.
        time.sleep(2)
        path = urljoin(repo['_href'], 'actions/publish/')
        client.post(path, {'id': distributor['id']})
        cls.repo = client.get(repo['_href'], params={'details': True})
    def setUpClass(cls):
        """Create a repository with a distributor, and populate it.

        In addition, create several variables for use by the test methods.
        """
        if inspect.getmro(cls)[0] == BaseTestCase:
            raise unittest.SkipTest('Abstract base class.')
        super(BaseTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)
        repo_href = client.post(REPOSITORY_PATH, gen_repo())['_href']
        cls.resources.add(repo_href)  # mark for deletion
        client.post(
            urljoin(repo_href, 'actions/associate/'),
            {'source_repo_id': _REPO['id']},
        )
        client.post(urljoin(repo_href, 'distributors/'), gen_distributor())

        # For use by sub-classes and test methods
        cls.repo = client.get(repo_href, params={'details': True})
        assert len(cls.repo['distributors']) == 1
        cls.call_reports = []  # dicts
        cls.repomd_xmls = []  # Response objects
    def create_repo(self, cfg, feed, relative_url=None):
        """Create an RPM repository with a yum importer and distributor.

        In addition, schedule the repository for deletion with ``addCleanup``.

        :param pulp_smash.config.ServerConfig cfg: The Pulp server on which to
            create a repository.
        :param feed: A value for the yum importer's ``feed`` option.
        :param relative_url: A value for the yum distributor's ``relative_url``
            option. If ``None``, this option is not passed to Pulp.
        :returns: The repository's href.
        """
        body = gen_repo()
        body['importer_config']['feed'] = feed
        distributor = gen_distributor()
        if relative_url is not None:
            distributor['distributor_config']['relative_url'] = relative_url
        body['distributors'] = [distributor]
        client = api.Client(cfg, api.json_handler)
        repo_href = client.post(REPOSITORY_PATH, body)['_href']
        self.addCleanup(client.delete, repo_href)
        return repo_href
 def test_predistributor_id(self):
     """Pass a bogus ID as the ``predistributor_id`` config option."""
     if selectors.bug_is_untestable(2191, self.cfg.version):
         raise self.skipTest('https://pulp.plan.io/issues/2191')
     api_client = api.Client(self.cfg, api.json_handler)
     body = gen_repo()
     body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
     body['distributors'] = [gen_distributor()]
     body['distributors'].append({
         'distributor_id': utils.uuid4(),
         'distributor_type_id': 'rpm_rsync_distributor',
         'distributor_config': {
             'predistributor_id': utils.uuid4(),
             'remote': self.remote,
         }
     })
     try:
         with self.assertRaises(HTTPError, msg=body):
             repo_href = api_client.post(REPOSITORY_PATH, body)['_href']
     except AssertionError as err:
         self.addCleanup(api_client.delete, repo_href)
         raise err
Example #58
0
    def setUpClass(cls):
        """Upload an erratum to a repo, publish, and download the erratum.

        Do the following:

        1. Create an RPM repository with a distributor.
        2. Upload an erratum to the repository.
        3. Publish the repository.
        4. Fetch the repository's ``updateinfo.xml`` file.
        """
        super(UploadErratumTestCase, cls).setUpClass()
        if check_issue_2277(cls.cfg):
            raise unittest.SkipTest('https://pulp.plan.io/issues/2277')
        cls.erratum = gen_erratum()

        # Create an RPM repository with a feed and distributor.
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_SIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Sync content into the repository, and give it an erratum.
        utils.sync_repo(cls.cfg, repo['_href'])
        utils.upload_import_erratum(cls.cfg, cls.erratum, repo['_href'])
        repo = client.get(repo['_href'], params={'details': True})

        # Publish the repository, and fetch and parse updateinfo.xml
        distributor = repo['distributors'][0]
        client.post(
            urljoin(repo['_href'], 'actions/publish/'),
            {'id': distributor['id']},
        )
        path = urljoin('/pulp/repos/', distributor['config']['relative_url'])
        cls.updateinfo = get_repomd_xml(cls.cfg, path, 'updateinfo')