예제 #1
0
 def test_v2(self):
     """Test that repo is present, sync-able, and has content."""
     repo_path = '{}/'.format(DOCKER_V2_REPO)
     repo = {'_href': urljoin(REPOSITORY_PATH, repo_path)}
     sync_report = utils.sync_repo(self.cfg, repo)
     api.poll_spawned_tasks(self.cfg, sync_report.json())
     units = utils.search_units(self.cfg, repo)
     self.assertGreater(len(units), 0, 'No units found in repo')
예제 #2
0
 def test_all(self):
     """Test that repo is present, sync-able, and has content."""
     repo_path = '{}/'.format(RPM_REPO)
     repo = {'_href': urljoin(REPOSITORY_PATH, repo_path)}
     repo = self.client.get(repo['_href'], params={'details': True})
     sync_report = utils.sync_repo(self.cfg, repo)
     api.poll_spawned_tasks(self.cfg, sync_report.json())
     units = utils.search_units(self.cfg, repo)
     self.assertGreater(len(units), 0, 'No units found in repo')
     download_rpm(self.cfg, repo['distributors'][0], RPM)
예제 #3
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 with the "background" download policy.
        3. Sync and publish the repository.
        4. Download an RPM from the repository.
        """
        super(BackgroundTestCase, cls).setUpClass()
        if (selectors.bug_is_untestable(1905, cls.cfg.version)
                and _os_is_rhel6(cls.cfg)):
            raise unittest.SkipTest('https://pulp.plan.io/issues/1905')

        # Required to ensure content is actually downloaded.
        utils.reset_squid(cls.cfg)
        utils.reset_pulp(cls.cfg)

        # Create, sync and publish a repository.
        repo = _create_repo(cls.cfg, 'background')
        cls.resources.add(repo['_href'])
        report = utils.sync_repo(cls.cfg, repo['_href']).json()

        # Record the tasks spawned when syncing the repository, and the state
        # of the repository itself after the sync.
        client = api.Client(cls.cfg)
        cls.repo = client.get(repo['_href'], params={'details': True}).json()
        cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, report))

        # Download an RPM.
        path = urljoin('/pulp/repos/', repo['id'] + '/')
        path = urljoin(path, RPM)
        cls.rpm = client.get(path)
예제 #4
0
    def setUpClass(cls):
        """Create and sync two puppet repositories."""
        super(SyncValidFeedTestCase, cls).setUpClass()
        utils.reset_pulp(cls.cfg)  # See: https://pulp.plan.io/issues/1406
        bodies = tuple((_gen_repo() for _ in range(2)))
        for i, query in enumerate((
                _PUPPET_QUERY, _PUPPET_QUERY.replace('-', '_'))):
            bodies[i]['importer_config'] = {
                'feed': _PUPPET_FEED,
                'queries': [query],
            }
        client = api.Client(cls.cfg, api.json_handler)
        repos = [client.post(REPOSITORY_PATH, body) for body in bodies]
        cls.resources.update({repo['_href'] for repo in repos})

        # Trigger repository sync and collect completed tasks.
        cls.reports = []  # raw responses to "start syncing" commands
        cls.tasks = []  # completed tasks
        client.response_handler = api.echo_handler
        for repo in repos:
            report = client.post(urljoin(repo['_href'], 'actions/sync/'))
            report.raise_for_status()
            cls.reports.append(report)
            for task in api.poll_spawned_tasks(cls.cfg, report.json()):
                cls.tasks.append(task)
예제 #5
0
def gen_python_publication(cfg,
                           repository=None,
                           repository_version=None,
                           **kwargs):
    """
    Create a Python Publication from a repository or a repository version.

    Args:
     cfg (pulp_smash.config.PulpSmashConfig): Information about the Pulp host.

    Kwargs:
        repository (str): _href of a repository
        repository_version (str): _href of a repository version
    """
    body = {}
    if repository_version:
        body.update({"repository_version": repository_version['pulp_href']})

    # Both are ifs so we can do both at once (to test the error)
    if repository:
        body.update({"repository": repository['pulp_href']})

    client = api.Client(cfg, api.json_handler)
    call_report = client.post(PYTHON_PUBLICATION_PATH, body)
    tasks = tuple(api.poll_spawned_tasks(cfg, call_report))
    return client.get(tasks[-1]["created_resources"][0])
예제 #6
0
    def sync_and_inspect_task_report(self,
                                     remote,
                                     repo,
                                     download_count,
                                     mirror=None,
                                     policy="immediate"):
        """Do a sync and verify the number of downloaded artifacts.

        Returns:
            Task report structure

        """
        if mirror is None:
            sync_resp = sync_raw(self.cfg, remote, repo)
        else:
            sync_resp = sync_raw(self.cfg, remote, repo, mirror=mirror)
        tasks = tuple(api.poll_spawned_tasks(self.cfg, sync_resp))
        self.assertEqual(len(tasks), 1)
        for report in tasks[0]["progress_reports"]:
            if report["message"] == "Downloading Artifacts":
                if policy != "immediate":
                    self.fail(
                        f"'Downloading Artifacts' stage in task report for {policy} policy"
                    )
                self.assertEqual(report["done"], download_count)
                break
        else:
            if policy == "immediate":
                self.fail(
                    "Could not find 'Downloading Artifacts' stage in task report"
                )
        return tasks[0]
예제 #7
0
    def setUpClass(cls):
        """Create and sync two puppet repositories."""
        super(SyncValidFeedTestCase, cls).setUpClass()
        utils.reset_pulp(cls.cfg)  # See: https://pulp.plan.io/issues/1406
        bodies = tuple((_gen_repo() for _ in range(2)))
        for i, query in enumerate(
            (_PUPPET_QUERY, _PUPPET_QUERY.replace('-', '_'))):
            bodies[i]['importer_config'] = {
                'feed': _PUPPET_FEED,
                'queries': [query],
            }
        client = api.Client(cls.cfg, api.json_handler)
        repos = [client.post(REPOSITORY_PATH, body) for body in bodies]
        cls.resources.update({repo['_href'] for repo in repos})

        # Trigger repository sync and collect completed tasks.
        cls.reports = []  # raw responses to "start syncing" commands
        cls.tasks = []  # completed tasks
        client.response_handler = api.echo_handler
        for repo in repos:
            report = client.post(urljoin(repo['_href'], 'actions/sync/'))
            report.raise_for_status()
            cls.reports.append(report)
            for task in api.poll_spawned_tasks(cls.cfg, report.json()):
                cls.tasks.append(task)
예제 #8
0
    def repository_setup(self, first, second):
        """Set up a repository for download policy switch test.

        Create a repository using the first download policy, assert it was set,
        update to the second download policy, assert it was set, then sync the
        repository and finally poll the spawned tasks.

        Return a tuple with the repository and tasks.
        """
        client = api.Client(self.cfg)
        # Create repo with the first download policy
        repo = _create_repo(self.cfg, first)
        self.addCleanup(client.delete, repo['_href'])
        repo = client.get(repo['_href'], params={'details': True}).json()
        self.assertEqual(repo['importers'][0]['config']['download_policy'],
                         first)
        # Update the importer to the second download policy
        client.put(repo['importers'][0]['_href'], {
            'importer_config': {
                'download_policy': second
            },
        })
        repo = client.get(repo['_href'], params={'details': True}).json()
        self.assertEqual(repo['importers'][0]['config']['download_policy'],
                         second)
        report = sync_repo(self.cfg, repo).json()
        tasks = tuple(api.poll_spawned_tasks(self.cfg, report))
        return repo, tasks
    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 with the "background" download policy.
        3. Sync and publish the repository.
        4. Download an RPM from the repository.
        """
        super().setUpClass()
        if check_issue_3104(cls.cfg):
            raise unittest.SkipTest('https://pulp.plan.io/issues/3104')
        if (not selectors.bug_is_fixed(1905, cls.cfg.pulp_version)
                and os_is_rhel6(cls.cfg)):
            raise unittest.SkipTest('https://pulp.plan.io/issues/1905')

        # Required to ensure content is actually downloaded.
        reset_squid(cls.cfg)
        reset_pulp(cls.cfg)

        # Create, sync and publish a repository.
        repo = _create_repo(cls.cfg, 'background')
        cls.resources.add(repo['_href'])
        report = sync_repo(cls.cfg, repo).json()

        # Record the tasks spawned when syncing the repository, and the state
        # of the repository itself after the sync.
        client = api.Client(cls.cfg)
        cls.repo = client.get(repo['_href'], params={'details': True}).json()
        cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, report))

        # Download an RPM.
        cls.rpm = get_unit(cls.cfg, cls.repo['distributors'][0], RPM)
예제 #10
0
    def test_workflow_01(self):
        """
        Verify workflow 1
        """
        repo = self.client.post(PYTHON_REPO_PATH, gen_repo())
        self.addCleanup(self.client.delete, repo["pulp_href"])

        artifacts = []
        for pkg in self.PACKAGES_FILES:
            artifacts.append(self.client.post(ARTIFACTS_PATH, files=pkg))

        for filename, artifact in zip(PYTHON_FIXTURES_FILENAMES, artifacts):
            task_url = self.client.post(
                PYTHON_CONTENT_PATH,
                data={
                    "filename": filename,
                    "relative_path": filename,
                    "artifact": artifact["pulp_href"],
                },
            )
            task = tuple(api.poll_spawned_tasks(self.cfg, task_url))
            content_url = task[-1]["created_resources"][0]
            self.client.post(
                urljoin(repo["pulp_href"], "modify/"),
                {"add_content_units": [content_url]},
            )
        repo = self.client.get(repo["pulp_href"])
        distribution = self.gen_pub_dist(repo)
        self.addCleanup(delete_orphans, self.cfg)
        self.check_consume(distribution)
예제 #11
0
    def setUpClass(cls):
        """Create an RPM repository, upload package groups, and publish."""
        super().setUpClass()
        if check_issue_3104(cls.cfg):
            raise unittest.SkipTest('https://pulp.plan.io/issues/3104')

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

        # 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))
        publish_repo(cls.cfg, repo)

        # Fetch the generated repodata of type 'group' (a.k.a. 'comps')
        cls.root_element = (get_repodata(cls.cfg, repo['distributors'][0],
                                         'group'))
    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')
    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 with the "background" download policy.
        3. Sync and publish the repository.
        4. Download an RPM from the repository.
        """
        super(BackgroundTestCase, cls).setUpClass()
        if (selectors.bug_is_untestable(1905, cls.cfg.version) and
                _os_is_rhel6(cls.cfg)):
            raise unittest.SkipTest('https://pulp.plan.io/issues/1905')

        # Required to ensure content is actually downloaded.
        utils.reset_squid(cls.cfg)
        utils.reset_pulp(cls.cfg)

        # Create, sync and publish a repository.
        repo = _create_repo(cls.cfg, 'background')
        cls.resources.add(repo['_href'])
        report = utils.sync_repo(cls.cfg, repo['_href']).json()

        # Record the tasks spawned when syncing the repository, and the state
        # of the repository itself after the sync.
        client = api.Client(cls.cfg)
        cls.repo = client.get(repo['_href'], params={'details': True}).json()
        cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, report))

        # Download an RPM.
        path = urljoin('/pulp/repos/', repo['id'] + '/')
        path = urljoin(path, RPM)
        cls.rpm = client.get(path)
예제 #14
0
 def test_all(self):
     """Check if Pulp only associate missing repo content."""
     cfg = config.get_config()
     if cfg.pulp_version < Version('2.11'):
         self.skipTest(
             'Selective association is available on Pulp 2.11+ see Pulp '
             '#2457 for more information'
         )
     client = api.Client(cfg, api.json_handler)
     body = gen_repo()
     body['importer_config']['feed'] = RPM_UNSIGNED_FEED_URL
     repo = client.post(REPOSITORY_PATH, body)
     self.addCleanup(client.delete, repo['_href'])
     sync_repo(cfg, repo)
     rpm_units = (
         _get_units_by_type(search_units(cfg, repo), 'rpm')
     )
     # Let's select up to 1/5 of the available units to remove
     to_remove = random.sample(
         rpm_units, random.randrange(int(RPM_UNSIGNED_FEED_COUNT / 4)))
     for unit in to_remove:
         _remove_unit(cfg, repo, unit)
     report = client.post(urljoin(repo['_href'], 'actions/sync/'))
     tasks = tuple(api.poll_spawned_tasks(cfg, report))
     self.assertEqual(len(tasks), 1, tasks)
     self.assertEqual(
         tasks[0]['result']['added_count'], len(to_remove), to_remove)
예제 #15
0
파일: utils.py 프로젝트: dralley/pulp-smash
def publish(cfg, publisher, repo, version_href=None):
    """Publish a repository.

    :param pulp_smash.config.PulpSmashConfig cfg: Information about the Pulp
        host.
    :param publisher: A dict of information about the publisher of the
        repository to be published.
    :param repo: A dict of information about the repository.
    :param version_href: The repository version to be published.
    :returns: A publication. A dict of information about the just created
        publication.
    """
    if version_href is None:
        body = {'repository': repo['_href']}
    else:
        body = {'repository_version': version_href}
    client = api.Client(cfg, api.json_handler)
    call_report = client.post(urljoin(publisher['_href'], 'publish/'), body)
    # As of this writing, Pulp 3 only returns one task. If Pulp 3 starts
    # returning multiple tasks, this may need to be re-written.
    tasks = tuple(api.poll_spawned_tasks(cfg, call_report))
    if len(tasks) != 1:
        message = (
            'Multiple tasks were spawned in response to API call. This is '
            'unexpected, and Pulp Smash may handle the response incorrectly. '
            'Here is the tasks generated: {}'
        )
        message = message.format(tasks)
        warnings.warn(message, RuntimeWarning)
    return client.get(tasks[-1]['created_resources'][0])
    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'
        )
예제 #17
0
def publish(cfg, publisher, repo, version_href=None):
    """Publish a repository.

    :param pulp_smash.config.PulpSmashConfig cfg: Information about the Pulp
        host.
    :param publisher: A dict of information about the publisher of the
        repository to be published.
    :param repo: A dict of information about the repository.
    :param version_href: The repository version to be published.
    :returns: A publication. A dict of information about the just created
        publication.
    """
    if version_href is None:
        body = {"repository": repo["_href"]}
    else:
        body = {"repository_version": version_href}
    client = api.Client(cfg, api.json_handler)
    call_report = client.post(urljoin(publisher["_href"], "publish/"), body)
    # As of this writing, Pulp 3 only returns one task. If Pulp 3 starts
    # returning multiple tasks, this may need to be re-written.
    tasks = tuple(api.poll_spawned_tasks(cfg, call_report))
    if len(tasks) != 1:
        message = (
            "Multiple tasks were spawned in response to API call. This is "
            "unexpected, and Pulp Smash may handle the response incorrectly. "
            "Here is the tasks generated: {}")
        message = message.format(tasks)
        warnings.warn(message, RuntimeWarning)
    return client.get(tasks[-1]["created_resources"][0])
예제 #18
0
 def sync_repo(self, repo):
     """Sync a repository, and verify no tasks contain an error message."""
     report = utils.sync_repo(self.cfg, repo).json()
     for task in api.poll_spawned_tasks(self.cfg, report):
         self.assertIsNone(task['progress_report']['puppet_importer']
                           ['metadata']['error_message']  # noqa pylint:disable=line-too-long
                           )
예제 #19
0
 def test_04_delete_all(self):
     """Delete all orphans."""
     call_report = api.Client(self.cfg).delete(ORPHANS_PATH).json()
     if not selectors.bug_is_fixed(1268, self.cfg.pulp_version):
         self.skipTest('https://pulp.plan.io/issues/1268')
     task = tuple(api.poll_spawned_tasks(self.cfg, call_report))[-1]
     self.assertIsInstance(task['result'], dict)
     self.assertGreater(sum(task['result'].values()), 0)
예제 #20
0
 def setUpClass(cls):
     """Create an OSTree repository with a valid feed and branch."""
     super(SyncTestCase, cls).setUpClass()
     body = gen_repo()
     body['importer_config']['feed'] = _FEED
     body['importer_config']['branches'] = [_BRANCHES[0]]
     repo_href, cls.report = create_sync_repo(cls.cfg, body)
     cls.resources.add(repo_href)
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #21
0
 def test_01_create_content_unit(self):
     """Create content unit."""
     attrs = gen_file_content_attrs(self.artifact)
     call_report = self.client.post(FILE_CONTENT_PATH, data=attrs)
     created_resources = next(api.poll_spawned_tasks(self.cfg, call_report))["created_resources"]
     self.content_unit.update(self.client.get(created_resources[0]))
     for key, val in attrs.items():
         with self.subTest(key=key):
             self.assertEqual(self.content_unit[key], val)
예제 #22
0
    def test_all(self):
        """Re-sync a child repository with the ``remove_missing`` enabled."""
        repos = []
        cfg = config.get_config()
        if selectors.bug_is_untestable(2616, cfg.pulp_version):
            self.skipTest('https://pulp.plan.io/issues/2616')

        # Create 1st repo, sync and publish it.
        client = api.Client(cfg, api.json_handler)
        body = gen_repo()
        body['importer_config']['feed'] = RPM_UNSIGNED_FEED_URL
        body['distributors'] = [gen_distributor()]
        repos.append(client.post(REPOSITORY_PATH, body))
        self.addCleanup(client.delete, repos[0]['_href'])
        repos[0] = _get_details(cfg, repos[0])
        utils.sync_repo(cfg, repos[0])
        utils.publish_repo(cfg, repos[0])

        # Create 2nd repo, sync.
        body = gen_repo()
        body['importer_config']['feed'] = urljoin(
            cfg.get_base_url(),
            _PUBLISH_DIR +
            repos[0]['distributors'][0]['config']['relative_url'],
        )
        body['importer_config']['remove_missing'] = True
        repos.append(client.post(REPOSITORY_PATH, body))
        self.addCleanup(client.delete, repos[1]['_href'])
        repos[1] = _get_details(cfg, repos[1])
        utils.sync_repo(cfg, repos[1])

        # Remove an arbitrary number of units from 1st repo, re-publish it.
        units = _get_rpms(cfg, repos[0])
        marked_units = random.sample(units, random.randint(1, len(units)))
        for marked_unit in marked_units:
            criteria = {
                'filters': {
                    'unit': {
                        'name': marked_unit['metadata']['name']
                    }
                },
                'type_ids': [marked_unit['unit_type_id']],
            }
            client.post(
                urljoin(repos[0]['_href'], 'actions/unassociate/'),
                {'criteria': criteria},
            )
        utils.publish_repo(cfg, repos[0])

        # Re-sync 2nd repo.
        report = utils.sync_repo(cfg, repos[1])
        tasks = tuple(api.poll_spawned_tasks(cfg, report.json()))
        self.assertEqual(
            tasks[0]['result']['removed_count'],
            len(marked_units),
        )
예제 #23
0
    def test_01_force_full_false(self):
        """Publish the repository and set ``force_full`` to false.

        A full publish should occur.
        """
        call_report = self.publish_repo(force_full=False)
        last_task = next(api.poll_spawned_tasks(self.cfg, call_report))
        task_steps = last_task['result']['details']
        step = self.get_step(task_steps, 'rpms')
        self.assertGreater(step['num_processed'], 0, step)
    def test_01_force_full_false(self):
        """Publish the repository and set ``force_full`` to false.

        A full publish should occur.
        """
        call_report = self.publish_repo(force_full=False)
        last_task = next(api.poll_spawned_tasks(self.cfg, call_report))
        task_steps = last_task['result']['details']
        step = self.get_step(task_steps, 'rpms')
        self.assertGreater(step['num_processed'], 0, step)
예제 #25
0
 def setUpClass(cls):
     """Create an OSTree repository with a valid feed and branch."""
     super(SyncTestCase, cls).setUpClass()
     body = gen_repo()
     body['importer_config']['feed'] = OSTREE_FEED
     body['importer_config']['branches'] = [OSTREE_BRANCH]
     repo = api.Client(cls.cfg).post(REPOSITORY_PATH, body).json()
     cls.resources.add(repo['_href'])
     cls.report = utils.sync_repo(cls.cfg, repo['_href'])
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #26
0
 def setUpClass(cls):
     """Create an RPM repository with an invalid feed and sync it."""
     super(SyncInvalidFeedTestCase, cls).setUpClass()
     client = api.Client(cls.cfg, api.json_handler)
     body = gen_repo()
     body["importer_config"]["feed"] = utils.uuid4()
     repo = client.post(REPOSITORY_PATH, body)
     client.response_handler = api.echo_handler
     cls.report = client.post(urljoin(repo["_href"], "actions/sync/"))
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
     cls.resources.add(repo["_href"])
예제 #27
0
 def setUpClass(cls):
     """Create an RPM repository with an invalid feed and sync it."""
     super(SyncInvalidFeedTestCase, cls).setUpClass()
     client = api.Client(cls.cfg, api.json_handler)
     body = gen_repo()
     body['importer_config']['feed'] = utils.uuid4()
     repo = client.post(REPOSITORY_PATH, body)
     client.response_handler = api.echo_handler
     cls.report = client.post(urljoin(repo['_href'], 'actions/sync/'))
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
     cls.resources.add(repo['_href'])
예제 #28
0
    def test_task_progress_report(self):
        """Assert no task's progress report contains error details.

        Other assertions about the final state of each task are handled by the
        client's response handler. (For more information, see the source of
        ``pulp_smash.api.safe_handler``.)
        """
        tasks = tuple(api.poll_spawned_tasks(self.cfg, self.report.json()))
        for i, task in enumerate(tasks):
            with self.subTest(i=i):
                error_details = task['progress_report']['yum_importer']['content']['error_details']  # pylint:disable=line-too-long
                self.assertEqual(error_details, [], task)
예제 #29
0
 def setUpClass(cls):
     """Create an OSTree repository with a valid feed and branch."""
     super(SyncTestCase, cls).setUpClass()
     if selectors.bug_is_untestable(1934, cls.cfg.version):
         raise unittest2.SkipTest('https://pulp.plan.io/issues/1934')
     body = gen_repo()
     body['importer_config']['feed'] = OSTREE_FEED
     body['importer_config']['branches'] = [OSTREE_BRANCH]
     repo = api.Client(cls.cfg).post(REPOSITORY_PATH, body).json()
     cls.resources.add(repo['_href'])
     cls.report = utils.sync_repo(cls.cfg, repo['_href'])
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #30
0
 def setUpClass(cls):
     """Create an OSTree repository with a valid feed and branch."""
     super().setUpClass()
     if not selectors.bug_is_fixed(1934, cls.cfg.pulp_version):
         raise unittest.SkipTest('https://pulp.plan.io/issues/1934')
     body = gen_repo()
     body['importer_config']['feed'] = OSTREE_FEED
     body['importer_config']['branches'] = OSTREE_BRANCHES
     repo = api.Client(cls.cfg).post(REPOSITORY_PATH, body).json()
     cls.resources.add(repo['_href'])
     cls.report = sync_repo(cls.cfg, repo)
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #31
0
    def test_task_progress_report(self):
        """Assert no task's progress report contains error details.

        Other assertions about the final state of each task are handled by the
        client's response handler. (For more information, see the source of
        :func:`pulp_smash.api.safe_handler`.)
        """
        tasks = tuple(api.poll_spawned_tasks(self.cfg, self.report.json()))
        for i, task in enumerate(tasks):
            with self.subTest(i=i):
                error_details = task['progress_report']['yum_importer']['content']['error_details']  # noqa pylint:disable=line-too-long
                self.assertEqual(error_details, [], task)
예제 #32
0
    def test_01_force_full_false(self):
        """Publish the repository and set ``force_full`` to false.

        A full publish should occur.
        """
        call_report = utils.publish_repo(self.cfg, self.repo, {
            'id': self.repo['distributors'][0]['id'],
            'override_config': {'force_full': False}
        }).json()
        last_task = next(api.poll_spawned_tasks(self.cfg, call_report))
        task_steps = last_task['result']['details']
        step = self.get_step(task_steps, 'rpms')
        self.assertGreater(step['num_processed'], 0, step)
예제 #33
0
    def test_no_change_in_second_sync(self):
        """Verify that syncing a second time has no changes.

        If the repository have not changed then Pulp must state that anything
        was changed when doing a second sync.
        """
        report = utils.sync_repo(self.cfg, self.repo)
        tasks = tuple(api.poll_spawned_tasks(self.cfg, report.json()))
        with self.subTest(comment='spawned tasks'):
            self.assertEqual(len(tasks), 1)
        for count_type in ('added_count', 'removed_count', 'updated_count'):
            with self.subTest(comment=count_type):
                self.assertEqual(tasks[0]['result'][count_type], 0)
예제 #34
0
    def test_01_force_full_false(self):
        """Publish the repository and set ``force_full`` to false.

        A full publish should occur.
        """
        call_report = utils.publish_repo(self.cfg, self.repo, {
            'id': self.repo['distributors'][0]['id'],
            'override_config': {'force_full': False}
        }).json()
        last_task = next(api.poll_spawned_tasks(self.cfg, call_report))
        task_steps = last_task['result']['details']
        step = self.get_step(task_steps, 'rpms')
        self.assertGreater(step['num_processed'], 0, step)
예제 #35
0
    def setUpClass(cls):
        """Create a puppet repository with an invalid feed and sync it."""
        super(SyncInvalidFeedTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config'] = {'feed': 'http://' + utils.uuid4()}
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Trigger a repository sync and collect completed tasks.
        client.response_handler = api.code_handler
        cls.report = client.post(urljoin(repo['_href'], 'actions/sync/'))
        cls.tasks = list(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #36
0
def _sync_repo(server_config, href):
    """Sync a repository and wait for the sync to complete.

    Verify only the call report's status code. Do not verify each individual
    task, as the default response handler does. Return ``call_report, tasks``.
    """
    response = api.Client(server_config, api.echo_handler).post(
        urljoin(href, 'actions/sync/'),
        {'override_config': {}},
    )
    response.raise_for_status()
    tasks = tuple(api.poll_spawned_tasks(server_config, response.json()))
    return response, tasks
예제 #37
0
def _sync_repo(cfg, href):
    """Sync a repository and wait for the sync to complete.

    Verify only the HTTP status codes of Pulp's responses. Don't verify
    response contents, as the default response handler does. Return ``call
    report, tasks``.
    """
    response = api.Client(cfg, api.code_handler).post(
        urljoin(href, 'actions/sync/'),
        {'override_config': {}},
    )
    tasks = tuple(api.poll_spawned_tasks(cfg, response.json()))
    return response, tasks
예제 #38
0
def _sync_repo(server_config, href):
    """Sync a repository and wait for the sync to complete.

    Verify only the call report's status code. Do not verify each individual
    task, as the default response handler does. Return ``call_report, tasks``.
    """
    response = api.Client(server_config, api.echo_handler).post(
        urljoin(href, 'actions/sync/'),
        {'override_config': {}},
    )
    response.raise_for_status()
    tasks = tuple(api.poll_spawned_tasks(server_config, response.json()))
    return response, tasks
예제 #39
0
    def test_no_change_in_second_sync(self):
        """Verify that syncing a second time has no changes.

        If the repository have not changed then Pulp must state that anything
        was changed when doing a second sync.
        """
        report = utils.sync_repo(self.cfg, self.repo_href)
        tasks = tuple(api.poll_spawned_tasks(self.cfg, report.json()))
        with self.subTest(comment='spawned tasks'):
            self.assertEqual(len(tasks), 1)
        for count_type in ('added_count', 'removed_count', 'updated_count'):
            with self.subTest(comment=count_type):
                self.assertEqual(tasks[0]['result'][count_type], 0)
예제 #40
0
 def setUpClass(cls):
     """Create an RPM repository with an invalid feed and sync it."""
     super(SyncInvalidFeedTestCase, cls).setUpClass()
     client = api.Client(cls.cfg, api.json_handler)
     body = _gen_repo()
     body['importer_config']['feed'] = utils.uuid4()
     repo = client.post(REPOSITORY_PATH, body)
     client.response_handler = api.echo_handler
     path = urljoin(repo['_href'], 'actions/sync/')
     cls.report = client.post(path, {'override_config': {}})
     cls.report.raise_for_status()
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
     cls.resources.add(repo['_href'])
예제 #41
0
    def setUpClass(cls):
        """Create repository with the feed pointing to a valid manifest."""
        super().setUpClass()
        client = api.Client(cls.cfg)
        body = gen_repo()
        body['importer_config'] = {
            'feed': 'http://repos.fedorapeople.org/repos/pulp/pulp/demo_repos/puppet_manifest/modules/'  # pylint:disable=line-too-long
        }
        repo = client.post(REPOSITORY_PATH, body).json()
        cls.resources.add(repo['_href'])

        # Trigger a repository sync and collect completed tasks.
        cls.report = sync_repo(cls.cfg, repo)
        cls.tasks = list(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #42
0
def _create_sync_repo(server_config, body):
    # Create repository.
    client = api.Client(server_config, api.json_handler)
    repo = client.post(REPOSITORY_PATH, body)

    # Sync repository and collect task statuses.
    client.response_handler = api.echo_handler
    response = client.post(
        urljoin(repo['_href'], 'actions/sync/'),
        {'override_config': {}},
    )
    response.raise_for_status()
    tasks = tuple(api.poll_spawned_tasks(server_config, response.json()))
    return repo['_href'], response, tasks
예제 #43
0
    def setUpClass(cls):
        """Create repository with the feed pointing to a valid manifest."""
        super(SyncValidManifestFeedTestCase, cls).setUpClass()
        client = api.Client(cls.cfg)
        body = gen_repo()
        body['importer_config'] = {
            'feed': 'http://repos.fedorapeople.org/repos/pulp/pulp/demo_repos/puppet_manifest/modules/'  # noqa pylint:disable=line-too-long
        }
        repo = client.post(REPOSITORY_PATH, body).json()
        cls.resources.add(repo['_href'])

        # Trigger a repository sync and collect completed tasks.
        cls.report = utils.sync_repo(cls.cfg, repo['_href'])
        cls.tasks = list(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #44
0
 def test_all(self):
     """Verify whether task report shows repository version was created."""
     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_file_remote()
     remote = client.post(FILE_REMOTE_PATH, body)
     self.addCleanup(client.delete, remote['_href'])
     call_report = sync(cfg, remote, repo)
     last_task = next(api.poll_spawned_tasks(cfg, call_report))
     for key in ('repositories', 'versions'):
         self.assertIn(key, last_task['created_resources'][0],
                       last_task['created_resources'])
예제 #45
0
    def setUpClass(cls):
        """Create a puppet repository with an invalid feed and sync it."""
        super(SyncInvalidFeedTestCase, cls).setUpClass()
        client = api.Client(cls.cfg, api.json_handler)
        body = gen_repo()
        body['importer_config'] = {'feed': 'http://' + utils.uuid4()}
        repo = client.post(REPOSITORY_PATH, body)
        cls.resources.add(repo['_href'])

        # Trigger a repository sync and collect completed tasks.
        client.response_handler = api.echo_handler
        cls.report = client.post(urljoin(repo['_href'], 'actions/sync/'))
        cls.report.raise_for_status()
        cls.tasks = list(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
예제 #46
0
    def test_02_force_full_omit(self):
        """Publish the repository and omit ``force_full``.

        A fast-forward publish should occur. This test targets `Pulp #1966`_.

        .. _Pulp #1966: https://pulp.plan.io/issues/1966
        """
        if (self.cfg.version >= Version('2.9') and
                selectors.bug_is_untestable(1966, self.cfg.version)):
            self.skipTest('https://pulp.plan.io/issues/1966')
        call_report = self.publish_repo()
        last_task = next(api.poll_spawned_tasks(self.cfg, call_report))
        task_steps = last_task['result']['details']
        step = self.get_step(task_steps, 'rpms')
        self.assertEqual(step['num_processed'], 0, step)
예제 #47
0
 def setUpClass(cls):
     """Create an RPM repo with a valid feed, sync it, and read the repo."""
     super(SyncValidFeedTestCase, cls).setUpClass()
     client = api.Client(cls.cfg, api.json_handler)
     body = gen_repo()
     body['importer_config']['feed'] = RPM_FEED_URL
     repo = client.post(REPOSITORY_PATH, body)
     client.response_handler = api.echo_handler
     path = urljoin(repo['_href'], 'actions/sync/')
     cls.report = client.post(path, {'override_config': {}})
     cls.report.raise_for_status()
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
     client.response_handler = api.json_handler
     cls.repo = client.get(repo['_href'])
     cls.resources.add(repo['_href'])
예제 #48
0
 def setUpClass(cls):
     """Create an RPM repo with a valid feed, sync it, and read the repo."""
     super(SyncValidFeedTestCase, cls).setUpClass()
     client = api.Client(cls.cfg, api.json_handler)
     body = gen_repo()
     body['importer_config']['feed'] = RPM_FEED_URL
     repo = client.post(REPOSITORY_PATH, body)
     client.response_handler = api.echo_handler
     path = urljoin(repo['_href'], 'actions/sync/')
     cls.report = client.post(path, {'override_config': {}})
     cls.report.raise_for_status()
     cls.tasks = tuple(api.poll_spawned_tasks(cls.cfg, cls.report.json()))
     client.response_handler = api.json_handler
     cls.repo = client.get(repo['_href'])
     cls.resources.add(repo['_href'])
예제 #49
0
    def verify_sync(self, cfg, call_report):
        """Verify the call to sync the Python repository succeeded.

        Assert that:

        * The call report has an HTTP 202 status code.
        * None of the tasks spawned by the "sync" request contain errors.
        """
        self.assertEqual(call_report.status_code, 202)
        tasks = tuple(api.poll_spawned_tasks(cfg, call_report.json()))
        for i, task in enumerate(tasks):
            step_reports = task['progress_report']['python_importer']
            for step in step_reports:
                with self.subTest(i=i):
                    error_details = step['error_details']
                    self.assertEqual(error_details, [], task)
예제 #50
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'
        )
예제 #51
0
    def test_second_publish_tasks(self):
        """Assert the second publish's last task reports a no-op publish."""
        call_report = self.call_reports[1]
        last_task = next(api.poll_spawned_tasks(self.cfg, call_report))

        if hasattr(self, 'cfg') and self.cfg.version < Version('2.10'):
            summary = 'Skipped. Nothing changed since last publish'
        else:
            summary = (
                'Skipped: Repository content has not changed since last '
                'publish.'
            )
        self.assertEqual(
            last_task['result']['summary'],
            summary,
            last_task,
        )
예제 #52
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'
        )
예제 #53
0
파일: utils.py 프로젝트: pulp/pulp_rpm
def publish(cfg, repo, version_href=None):
    """Publish a repository.

    :param pulp_smash.config.PulpSmashConfig cfg: Information about the Pulp
        host.
    :param repo: A dict of information about the repository.
    :param version_href: A href for the repo version to be published.
    :returns: A publication. A dict of information about the just created
        publication.
    """
    if version_href:
        body = {"repository_version": version_href}
    else:
        body = {"repository": repo["_href"]}

    client = api.Client(cfg, api.json_handler)
    call_report = client.post(RPM_PUBLICATION_PATH, body)
    tasks = tuple(api.poll_spawned_tasks(cfg, call_report))
    return client.get(tasks[-1]["created_resources"][0])
예제 #54
0
    def test_03_force_full_true(self):
        """Publish the repository and set ``force_full`` to true.

        A full publish should occur. The "force" publish feature was introduced
        in Pulp 2.9, and as such, this test will skip when run against an older
        version of Pulp. See `Pulp #1938`_.

        .. _Pulp #1938: https://pulp.plan.io/issues/1938
        """
        if self.cfg.version < Version('2.9'):
            self.skipTest(
                'This test requires Pulp 2.9. See: '
                'https://pulp.plan.io/issues/1938'
            )
        call_report = self.publish_repo(force_full=True)
        last_task = next(api.poll_spawned_tasks(self.cfg, call_report))
        task_steps = last_task['result']['details']
        step = self.get_step(task_steps, 'rpms')
        self.assertGreater(step['num_processed'], 0, step)
예제 #55
0
    def test_all(self):
        """Verify whether task report shows repository version was created."""
        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_file_remote()
        remote = client.post(FILE_REMOTE_PATH, body)
        self.addCleanup(client.delete, remote['_href'])

        call_report = sync(cfg, remote, repo)
        last_task = next(api.poll_spawned_tasks(cfg, call_report))
        for key in ('repositories', 'versions'):
            self.assertIn(
                key,
                last_task['created_resources'][0],
                last_task['created_resources']
            )
예제 #56
0
파일: utils.py 프로젝트: dralley/pulp-smash
def delete_version(repo, version_href=None):
    """Delete a given repository version.

    :param repo: A dict of information about the repository.
    :param version_href: The repository version that should be
        deleted.
    :returns: A tuple. The tasks spawned by Pulp.
    """
    version_href = version_href or repo['_latest_version_href']

    if version_href is None:
        # Repository has no latest version.
        raise ValueError('No version exists to be deleted.')

    cfg = config.get_config()
    client = api.Client(cfg, api.json_handler)
    call_report = client.delete(version_href)
    # As of this writing, Pulp 3 only returns one task. If Pulp 3 starts
    # returning multiple tasks, this may need to be re-written.
    return tuple(api.poll_spawned_tasks(cfg, call_report))
예제 #57
0
    def verify_publish_is_skip(self, cfg, call_report):
        """Find the 'publish' task and verify it has a result of 'skipped'.

        Recursively search through the tasks named by ``call_report`` for a
        task with a type of ``pulp.server.managers.repo.publish.publish``.
        Assert that only one task has this type, and that this task has a
        result of ``skipped``.

        :param pulp_smash.config.ServerConfig cfg: Information about the Pulp
            server being targeted.
        :param call_report: A call report returned from Pulp after requesting a
            publish; a dict.
        :returns: Nothing.
        """
        tasks = [
            task for task in api.poll_spawned_tasks(cfg, call_report)
            if task['task_type'] == 'pulp.server.managers.repo.publish.publish'
        ]
        self.assertEqual(len(tasks), 1, tasks)
        self.assertEqual(tasks[0]['result']['result'], 'skipped', tasks[0])
예제 #58
0
    def setUpClass(cls):
        """Create distributors and update with conflicting relative_paths."""
        super(UpdateDistributorsTestCase, cls).setUpClass()

        # Create two repository + distributor pairs.
        client = api.Client(cls.cfg, api.json_handler)
        distributors = []
        for _ in range(2):
            repo = client.post(REPOSITORY_PATH, gen_repo())
            cls.resources.add(repo['_href'])  # mark for deletion
            distributors.append(client.post(
                urljoin(repo['_href'], 'distributors/'),
                _gen_distributor(_gen_rel_path()),
            ))

        # Update the second distributor several times. After each update, we
        # read the distributor. This extra read is necessary b/c the initial
        # response is a call report.
        cls.written_paths = (
            _gen_rel_path(),  # successes
            _gen_rel_path(3),
            distributors[0]['config']['relative_path'],  # failures
            distributors[0]['config']['relative_path'] + '/' + utils.uuid4(),
            '/' + distributors[0]['config']['relative_path'],
        )
        cls.responses = []
        cls.read_paths = []
        for relative_path in cls.written_paths:
            client.response_handler = api.echo_handler
            cls.responses.append(client.put(
                distributors[1]['_href'],
                {'distributor_config': {'relative_path': relative_path}},
            ))
            tuple(api.poll_spawned_tasks(cls.cfg, cls.responses[-1].json()))
            client.response_handler = api.json_handler
            cls.read_paths.append(
                client.get(distributors[1]['_href'])['config']['relative_path']
            )
예제 #59
0
파일: utils.py 프로젝트: pulp/pulp_python
def gen_python_publication(cfg, repository=None, repository_version=None, **kwargs):
    """
    Create a Python Publication from a repository or a repository version.

    Args:
     cfg (pulp_smash.config.PulpSmashConfig): Information about the Pulp host.

    Kwargs:
        repository (str): _href of a repository
        repository_version (str): _href of a repository version
    """
    body = {}
    if repository_version:
        body.update({"repository_version": repository_version['_href']})

    # Both are ifs so we can do both at once (to test the error)
    if repository:
        body.update({"repository": repository['_href']})

    client = api.Client(cfg, api.json_handler)
    call_report = client.post(PYTHON_PUBLICATION_PATH, body)
    tasks = tuple(api.poll_spawned_tasks(cfg, call_report))
    return client.get(tasks[-1]["created_resources"][0])
예제 #60
0
 def test_second_publish_tasks(self):
     """Assert the second publish's last task reports a no-op publish."""
     call_report = self.call_reports[1]
     last_task = next(api.poll_spawned_tasks(self.cfg, call_report))
     self.assertIsInstance(last_task['result']['summary'], dict, last_task)