def test_positive_add_repo_from_product_with_repo(self): """@test: Create gpg key with valid name and valid gpg key via file import then associate it to repository from custom product that has one repository @feature: GPG Keys @assert: gpg key is associated with the repository but not with the product """ product = make_product({'organization-id': self.org['id']}) repo = make_repository({'product-id': product['id']}) gpg_key = make_gpg_key({'organization-id': self.org['id']}) Repository.update({ 'gpg-key-id': gpg_key['id'], 'id': repo['id'], 'organization-id': self.org['id'], }) product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) repo = Repository.info({'id': repo['id']}) self.assertEqual(repo['gpg-key']['id'], gpg_key['id']) self.assertNotEqual(product['gpg'].get('gpg-key-id'), gpg_key['id'])
def test_positive_synchronize_2(self): """@Test: Check if Docker repository can be created and synced @Feature: Repository @Assert: Docker repository is created and synced """ new_repo = self._make_repository({ u'name': u'busybox', u'url': DOCKER_REGISTRY_HUB, u'content-type': u'docker', }) # Assertion that repo is not yet synced self.assertEqual(new_repo['sync']['status'], 'Not Synced') # Synchronize it result = Repository.synchronize({'id': new_repo['id']}) self.assertEqual(result.return_code, 0) self.assertEqual(len(result.stderr), 0) # Verify it has finished result = Repository.info({'id': new_repo['id']}) self.assertEqual(result.stdout['sync']['status'], 'Finished')
def test_positive_add_repo_from_product_with_repos(self): """@test: Create gpg key via file import and associate with custom repo GPGKey should contain valid name and valid key and should be associated to one repository from custom product. Make sure custom product should have more than one repository. @feature: GPG Keys @assert: gpg key is associated with the repository """ product = make_product({'organization-id': self.org['id']}) repos = [ make_repository({'product-id': product['id']}) for _ in range(gen_integer(2, 5)) ] gpg_key = make_gpg_key({'organization-id': self.org['id']}) Repository.update({ 'gpg-key': gpg_key['name'], 'id': repos[0]['id'], 'organization-id': self.org['id'], }) product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertNotEqual(product['gpg'].get('gpg-key-id'), gpg_key['id']) # First repo should have a valid gpg key assigned repo = Repository.info({'id': repos.pop(0)['id']}) self.assertEqual(repo['gpg-key']['id'], gpg_key['id']) # The rest of repos should not for repo in repos: repo = Repository.info({'id': repo['id']}) self.assertNotEqual(repo['gpg-key'].get('id'), gpg_key['id'])
def test_enable_manifest_reposet(self): """@Test: enable repository set (positive) @Feature: Subscriptions/Repository Sets @Assert: you are able to enable and synchronize repository contained in a manifest """ self._upload_manifest(self.manifest, self.org['id']) Subscription.list( {'organization-id': self.org['id']}, per_page=False, ) RepositorySet.enable({ 'basearch': 'x86_64', 'name': ( 'Red Hat Enterprise Virtualization Agents ' 'for RHEL 6 Workstation (RPMs)' ), 'organization-id': self.org['id'], 'product': 'Red Hat Enterprise Linux Workstation', 'releasever': '6Workstation', }) Repository.synchronize({ 'name': ( 'Red Hat Enterprise Virtualization Agents ' 'for RHEL 6 Workstation ' 'RPMs x86_64 6Workstation' ), 'organization-id': self.org['id'], 'product': 'Red Hat Enterprise Linux Workstation', })
def test_positive_list_multiple_repos(self): """Verify that puppet-modules list for specific repo is correct and does not affected by other repositories. @id: f36d25b3-2495-4e89-a1cf-e39d52762d95 @Assert: Number of modules has no changed after a second repo was synced. """ # Verify that number of synced modules is correct repo1 = Repository.info({'id': self.repo['id']}) repo_content_count = repo1['content-counts']['puppet-modules'] modules_num = len( PuppetModule.list({'repository-id': repo1['id']})) self.assertEqual(repo_content_count, str(modules_num)) # Create and sync second repo repo2 = make_repository({ u'organization-id': self.org['id'], u'product-id': self.product['id'], u'content-type': u'puppet', u'url': FAKE_1_PUPPET_REPO, }) Repository.synchronize({'id': repo2['id']}) # Verify that number of modules from the first repo has not changed self.assertEqual( modules_num, len(PuppetModule.list({'repository-id': repo1['id']})) )
def test_positive_synchronize_1(self, test_data): """@Test: Check if repository can be created and synced @Feature: Repository @Assert: Repository is created and synced """ new_repo = self._make_repository({ u'url': test_data['url'], u'content-type': test_data['content-type'], }) # Assertion that repo is not yet synced self.assertEqual( new_repo['sync']['status'], 'Not Synced', "The status of repository should be 'Not Synced'") # Synchronize it result = Repository.synchronize({'id': new_repo['id']}) self.assertEqual( result.return_code, 0, "Repository was not synchronized") self.assertEqual( len(result.stderr), 0, "No error was expected") # Verify it has finished result = Repository.info({'id': new_repo['id']}) self.assertEqual( result.stdout['sync']['status'], 'Finished', "The new status of repository should be 'Finished'")
def test_positive_update_url(self): """Update the original url for a repository @id: 1a2cf29b-5c30-4d4c-b6d1-2f227b0a0a57 @Assert: Repository url is updated """ new_repo = self._make_repository() # generate repo URLs with all valid credentials auth_repos = [ repo.format(creds['login'], creds['pass']) for creds in valid_http_credentials(url_encoded=True) for repo in (FAKE_5_YUM_REPO, FAKE_7_PUPPET_REPO) ] for url in [FAKE_4_YUM_REPO, FAKE_1_PUPPET_REPO, FAKE_2_PUPPET_REPO, FAKE_3_PUPPET_REPO, FAKE_2_YUM_REPO] + auth_repos: with self.subTest(url): # Update the url Repository.update({ u'id': new_repo['id'], u'url': url, }) # Fetch it again result = Repository.info({'id': new_repo['id']}) self.assertEqual(result['url'], url)
def test_positive_synchronize_auth_yum_repo(self): """Check if secured repository can be created and synced @id: b0db676b-e0f0-428c-adf3-1d7c0c3599f0 @Assert: Repository is created and synced @CaseLevel: Integration """ url = FAKE_5_YUM_REPO for creds in [cred for cred in valid_http_credentials(url_encoded=True) if cred['http_valid']]: url_encoded = url.format( creds['login'], creds['pass'] ) with self.subTest(url): new_repo = self._make_repository({ u'content-type': u'yum', u'url': url_encoded, }) # Assertion that repo is not yet synced self.assertEqual(new_repo['sync']['status'], 'Not Synced') # Synchronize it Repository.synchronize({'id': new_repo['id']}) # Verify it has finished new_repo = Repository.info({'id': new_repo['id']}) self.assertEqual(new_repo['sync']['status'], 'Success')
def test_positive_update_1(self, url): """@Test: Update the original url for a repository @Feature: Repository @Assert: Repository url is updated """ new_repo = self._make_repository() # Update the url result = Repository.update({ u'id': new_repo['id'], u'url': url, }) self.assertEqual(result.return_code, 0) self.assertEqual(len(result.stderr), 0) # Fetch it again result = Repository.info({'id': new_repo['id']}) self.assertEqual(result.return_code, 0) self.assertEqual(len(result.stderr), 0) self.assertNotEqual(result.stdout['url'], new_repo['url']) self.assertEqual(result.stdout['url'], url)
def test_positive_update_checksum_type(self): """Create a YUM repository and update the checksum type @Feature: Repository @Assert: A YUM repository is updated and contains the correct checksum type @BZ: 1208305 """ content_type = u'yum' repository = self._make_repository({ u'content-type': content_type }) self.assertEqual(repository['content-type'], content_type) self.assertEqual(repository['checksum-type'], '') for checksum_type in u'sha1', u'sha256': with self.subTest(checksum_type): # Update the checksum Repository.update({ u'checksum-type': checksum_type, u'id': repository['id'], }) # Fetch it again result = Repository.info({'id': repository['id']}) self.assertEqual(result['checksum-type'], checksum_type)
def test_positive_sync_publish_promote_cv(self): """Synchronize repository with DRPMs, add repository to content view, publish and promote content view to lifecycle environment @id: a01cb12b-d388-4902-8532-714f4e28ec56 @Assert: drpms can be listed in content view in proper lifecycle environment """ lce = make_lifecycle_environment({"organization-id": self.org["id"]}) repo = make_repository({"product-id": self.product["id"], "url": FAKE_YUM_DRPM_REPO}) Repository.synchronize({"id": repo["id"]}) cv = make_content_view({"organization-id": self.org["id"]}) ContentView.add_repository({"id": cv["id"], "repository-id": repo["id"]}) ContentView.publish({"id": cv["id"]}) content_view = ContentView.info({"id": cv["id"]}) cvv = content_view["versions"][0] ContentView.version_promote({"id": cvv["id"], "to-lifecycle-environment-id": lce["id"]}) result = ssh.command( "ls /var/lib/pulp/published/yum/https/repos/{}/{}/{}/custom/{}/{}" "/drpms/ | grep .drpm".format( self.org["label"], lce["label"], cv["label"], self.product["label"], repo["label"] ) ) self.assertEqual(result.return_code, 0) self.assertGreaterEqual(len(result.stdout), 1)
def test_negative_update_auth_url_too_long(self): """Update the original url for a repository to value which is too long @id: a703de60-8631-4e31-a9d9-e51804f27f03 @Assert: Repository url not updated """ new_repo = self._make_repository() # generate repo URLs with all invalid credentials auth_repos = [ repo.format(cred['login'], cred['pass']) for cred in invalid_http_credentials() for repo in (FAKE_5_YUM_REPO, FAKE_7_PUPPET_REPO) ] for url in auth_repos: with self.subTest(url): with self.assertRaises(CLIReturnCodeError): Repository.update({ u'id': new_repo['id'], u'url': url, }) # Fetch it again result = Repository.info({'id': new_repo['id']}) self.assertEqual(result['url'], new_repo['url'])
def test_positive_add_repo_from_product_with_repo(self): """Create gpg key with valid name and valid gpg key via file import then associate it to repository from custom product that has one repository @id: 1427f145-9faf-41ef-ae42-dc91d61ce1f6 @assert: gpg key is associated with the repository but not with the product @CaseLevel: Integration """ product = make_product({'organization-id': self.org['id']}) repo = make_repository({'product-id': product['id']}) gpg_key = make_gpg_key({'organization-id': self.org['id']}) Repository.update({ 'gpg-key-id': gpg_key['id'], 'id': repo['id'], 'organization-id': self.org['id'], }) product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) repo = Repository.info({'id': repo['id']}) self.assertEqual(repo['gpg-key']['id'], gpg_key['id']) self.assertNotEqual(product['gpg'].get('gpg-key-id'), gpg_key['id'])
def test_positive_synchronize_auth_puppet_repo(self): """Check if secured puppet repository can be created and synced @id: 1d2604fc-8a18-4cbe-bf4c-5c7d9fbdb82c @Assert: Repository is created and synced @CaseLevel: Integration """ url = FAKE_7_PUPPET_REPO for creds in [cred for cred in valid_http_credentials(url_encoded=True) if cred['http_valid']]: url_encoded = url.format(creds['login'], creds['pass']) with self.subTest(url): new_repo = self._make_repository({ u'content-type': u'yum', u'url': url_encoded, }) # Assertion that repo is not yet synced self.assertEqual(new_repo['sync']['status'], 'Not Synced') # Synchronize it Repository.synchronize({'id': new_repo['id']}) # Verify it has finished new_repo = Repository.info({'id': new_repo['id']}) self.assertEqual(new_repo['sync']['status'], 'Success')
def test_negative_update_auth_url_with_special_characters(self): """Verify that repository URL credentials cannot be updated to contain the forbidden characters @id: 566553b2-d077-4fd8-8ed5-00ba75355386 @Assert: Repository url not updated """ new_repo = self._make_repository() # get auth repos with credentials containing unquoted special chars auth_repos = [ repo.format(cred['login'], cred['pass']) for cred in valid_http_credentials() if cred['quote'] for repo in (FAKE_5_YUM_REPO, FAKE_7_PUPPET_REPO) ] for url in auth_repos: with self.subTest(url): with self.assertRaises(CLIReturnCodeError): Repository.update({ u'id': new_repo['id'], u'url': url, }) # Fetch it again result = Repository.info({'id': new_repo['id']}) self.assertEqual(result['url'], new_repo['url'])
def setUpClass(cls): """Create Directory for all CV Sync Tests in /tmp""" super(ContentViewSync, cls).setUpClass() cls.exporting_org = make_org() cls.exporting_prod = gen_string('alpha') product = make_product({ 'organization-id': cls.exporting_org['id'], 'name': cls.exporting_prod }) cls.exporting_repo = gen_string('alpha') repo = make_repository({ 'name': cls.exporting_repo, 'download-policy': 'immediate', 'product-id': product['id'] }) Repository.synchronize({'id': repo['id']}) cls.exporting_cv = gen_string('alpha') content_view = make_content_view({ 'name': cls.exporting_cv, 'organization-id': cls.exporting_org['id'] }) ContentView.add_repository({ 'id': content_view['id'], 'organization-id': cls.exporting_org['id'], 'repository-id': repo['id'] }) ContentView.publish({u'id': content_view['id']}) content_view = ContentView.info({u'id': content_view['id']}) cls.exporting_cvv_id = content_view['versions'][0]['id']
def test_positive_enable_manifest_reposet(self): """enable repository set :id: cc0f8f40-5ea6-4fa7-8154-acdc2cb56b45 :expectedresults: you are able to enable and synchronize repository contained in a manifest :CaseLevel: Integration :CaseImportance: Critical """ self._upload_manifest(self.org['id']) Subscription.list( {'organization-id': self.org['id']}, per_page=False, ) RepositorySet.enable({ 'basearch': 'x86_64', 'name': REPOSET['rhva6'], 'organization-id': self.org['id'], 'product': PRDS['rhel'], 'releasever': '6Server', }) Repository.synchronize({ 'name': REPOS['rhva6']['name'], 'organization-id': self.org['id'], 'product': PRDS['rhel'], })
def setUpClass(cls): """Init single organization, product and repository for all tests""" super(TestContentViewFilter, cls).setUpClass() cls.org = make_org() cls.product = make_product({u'organization-id': cls.org['id']}) cls.repo = make_repository({u'product-id': cls.product['id']}) Repository.synchronize({u'id': cls.repo['id']})
def test_delete_random_docker_repo(self): """@Test: Create Docker-type repositories on multiple products and delete a random repository from a random product. @Assert: Random repository can be deleted from random product without altering the other products. @Feature: Docker """ products = [ make_product({'organization-id': self.org_id}) for _ in range(randint(2, 5)) ] repos = [] for product in products: for _ in range(randint(2, 3)): repos.append(_make_docker_repo(product['id'])) # Select random repository and delete it repo = choice(repos) repos.remove(repo) result = Repository.delete({'id': repo['id']}) self.assertEqual(result.return_code, 0) result = Repository.info({'id': repo['id']}) self.assertNotEqual(result.return_code, 0) # Verify other repositories were not touched for repo in repos: result = Repository.info({'id': repo['id']}) self.assertEqual(result.return_code, 0) self.assertIn( result.stdout['product']['id'], [product['id'] for product in products], )
def test_add_synced_docker_repo_to_content_view(self): """@Test: Create and sync a Docker-type repository @Assert: A repository is created with a Docker repository and it is synchronized. @Feature: Docker """ repo = _make_docker_repo( make_product({'organization-id': self.org_id})['id']) result = Repository.synchronize({'id': repo['id']}) self.assertEqual(result.return_code, 0) repo = Repository.info({'id': repo['id']}).stdout self.assertGreaterEqual( int(repo['content-counts']['docker-images']), 1) content_view = make_content_view({ 'composite': False, 'organization-id': self.org_id, }) result = ContentView.add_repository({ 'id': content_view['id'], 'repository-id': repo['id'], }) self.assertEqual(result.return_code, 0) content_view = ContentView.info({'id': content_view['id']}).stdout self.assertIn( repo['id'], [repo_['id'] for repo_ in content_view['docker-repositories']], )
def create(self, organization_id, product_id=None, download_policy=DOWNLOAD_POLICY_ON_DEMAND, synchronize=True): # type: (int, Optional[int], Optional[str], Optional[bool]) -> Dict """Create an RH repository""" if not self.cdn and not self.url: raise ValueError('Can not handle Custom repository with url not supplied') if self.cdn: data = self.data RepositorySet.enable({ 'organization-id': organization_id, 'product': data['product'], 'name': data['repository-set'], 'basearch': data.get('arch', DEFAULT_ARCHITECTURE), 'releasever': data.get('releasever'), }) repo_info = Repository.info({ 'organization-id': organization_id, 'name': data['repository'], 'product': data['product'], }) if download_policy: # Set download policy Repository.update({ 'download-policy': download_policy, 'id': repo_info['id'], }) self._repo_info = repo_info if synchronize: self.synchronize() else: repo_info = super(GenericRHRepository, self).create( organization_id, product_id, download_policy=download_policy) return repo_info
def test_positive_enable_manifest_reposet(self): """enable repository set @Feature: Subscriptions/Repository Sets @Assert: you are able to enable and synchronize repository contained in a manifest """ self._upload_manifest(self.org['id']) Subscription.list( {'organization-id': self.org['id']}, per_page=False, ) RepositorySet.enable({ 'basearch': 'x86_64', 'name': REPOSET['rhva6'], 'organization-id': self.org['id'], 'product': PRDS['rhel'], 'releasever': '6Server', }) Repository.synchronize({ 'name': REPOS['rhva6']['name'], 'organization-id': self.org['id'], 'product': PRDS['rhel'], })
def test_positive_update_key_for_product_with_repos(self): """Create gpg key with valid name and valid gpg key via file import then associate it with custom product that has more than one repository then update the key @id: a95eb51b-4b6b-4c04-bb4d-cbe600431850 @assert: gpg key is associated with product before/after update as well as with the repositories @CaseLevel: Integration """ # Create a product and a gpg key product = make_product({'organization-id': self.org['id']}) gpg_key = make_gpg_key({'organization-id': self.org['id']}) # Create repositories and assign them to the product repos = [ make_repository({'product-id': product['id']}) for _ in range(gen_integer(2, 5)) ] # Associate gpg key with a product Product.update({ 'gpg-key': gpg_key['name'], 'id': product['id'], 'organization-id': self.org['id'], }) # Verify gpg key was associated product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertEqual(product['gpg']['gpg-key'], gpg_key['name']) for repo in repos: repo = Repository.info({'id': repo['id']}) self.assertEqual(repo['gpg-key'].get('name'), gpg_key['name']) # Update the gpg key new_name = gen_choice(valid_data_list()) GPGKey.update({ 'name': gpg_key['name'], 'new-name': new_name, 'organization-id': self.org['id'], }) # Verify changes are reflected in the gpg key gpg_key = GPGKey.info({ 'id': gpg_key['id'], 'organization-id': self.org['id'], }) self.assertEqual(gpg_key['name'], new_name) # Verify changes are reflected in the product product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertEqual(product['gpg']['gpg-key'], new_name) # Verify changes are reflected in the repositories for repo in repos: repo = Repository.info({'id': repo['id']}) self.assertEqual(repo['gpg-key'].get('name'), new_name)
def setUpClass(cls): """Init single organization, product and repository for all tests""" super(TestContentViewFilter, cls).setUpClass() cls.org = make_org() cls.product = make_product({u"organization-id": cls.org["id"]}) cls.repo = make_repository({u"product-id": cls.product["id"]}) Repository.synchronize({u"id": cls.repo["id"]}) cls.content_view = make_content_view({u"organization-id": cls.org["id"]}) ContentView.add_repository({u"id": cls.content_view["id"], u"repository-id": cls.repo["id"]})
def test_positive_update_key_for_repo_from_product_with_repos(self): """Create gpg key with valid name and valid gpg key via file import then associate it to repository from custom product that has more than one repository then update the key :id: 773a9141-9f04-40ba-b3df-4b6d80db25a6 :expectedresults: gpg key is associated with a single repository before/after update and not associated with product or other repositories :CaseLevel: Integration """ # Create a product and a gpg key product = make_product({'organization-id': self.org['id']}) gpg_key = make_gpg_key({'organization-id': self.org['id']}) # Create repositories and assign them to the product repos = [ make_repository({'product-id': product['id']}) for _ in range(gen_integer(2, 5)) ] # Associate gpg key with a single repository Repository.update({ 'gpg-key': gpg_key['name'], 'id': repos[0]['id'], 'organization-id': self.org['id'], }) # Verify gpg key was associated repos[0] = Repository.info({'id': repos[0]['id']}) self.assertEqual(repos[0]['gpg-key']['name'], gpg_key['name']) # Update the gpg key new_name = gen_choice(valid_data_list()) GPGKey.update({ 'name': gpg_key['name'], 'new-name': new_name, 'organization-id': self.org['id'], }) # Verify changes are reflected in the gpg key gpg_key = GPGKey.info({ 'id': gpg_key['id'], 'organization-id': self.org['id'], }) self.assertEqual(gpg_key['name'], new_name) # Verify changes are reflected in the associated repository repos[0] = Repository.info({'id': repos[0]['id']}) self.assertEqual(repos[0]['gpg-key'].get('name'), new_name) # Verify changes are not reflected in the product product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertNotEqual(product['gpg']['gpg-key'], new_name) # Verify changes are not reflected in the rest of repositories for repo in repos[1:]: repo = Repository.info({'id': repo['id']}) self.assertNotEqual(repo['gpg-key'].get('name'), new_name)
def test_positive_delete_key_for_product_with_repos(self): """Create gpg key with valid name and valid gpg key via file import then associate it with custom product that has more than one repository then delete it @id: f92d4643-1892-4f95-ae6b-fcea8e726946 @assert: gpg key is associated with product and its repositories during creation but removed from the product and the repositories after deletion @CaseLevel: Integration """ # Create product, repositories and gpg key product = make_product({'organization-id': self.org['id']}) repos = [ make_repository({'product-id': product['id']}) for _ in range(gen_integer(2, 5)) ] gpg_key = make_gpg_key({'organization-id': self.org['id']}) # Associate gpg key with a product Product.update({ 'gpg-key': gpg_key['name'], 'id': product['id'], 'organization-id': self.org['id'], }) # Verify gpg key was associated with product and its repositories product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertEqual(product['gpg']['gpg-key'], gpg_key['name']) for repo in repos: repo = Repository.info({'id': repo['id']}) self.assertEqual(repo['gpg-key'].get('name'), gpg_key['name']) # Delete the gpg key GPGKey.delete({ 'name': gpg_key['name'], 'organization-id': self.org['id'], }) # Verify gpg key was actually deleted with self.assertRaises(CLIReturnCodeError): GPGKey.info({ 'id': gpg_key['id'], 'organization-id': self.org['id'], }) # Verify gpg key was disassociated from the product and its # repositories product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertNotEqual(product['gpg']['gpg-key'], gpg_key['name']) for repo in repos: repo = Repository.info({'id': repo['id']}) self.assertNotEqual(repo['gpg-key'].get('name'), gpg_key['name'])
def test_reimport_repo_negative(self, test_data): """@test: Import and enable all Repositories from the default data set (predefined source), then try to Import Repositories from the same CSV again. @feature: Repetitive Import Enable Repositories @assert: 3 Repositories imported and enabled, second run should trigger no action. """ # randomize the values for orgs and repos files = dict(self.default_dataset[1]) for file_ in zip( ['users', 'repositories'], [u'organization_id', u'org_id'], ): files[file_[0]] = update_csv_values( files[file_[0]], file_[1], test_data[file_[0]], self.default_dataset[0] ) # import the prerequisities import_org = Import.organization_with_tr_data( {'csv-file': files['users']} ) # now proceed with importing the repositories import_repo = Import.repository_with_tr_data({ 'csv-file': files['repositories'], 'synchronize': True, 'wait': True, }) for result in (import_org, import_repo): self.assertEqual(result[0].return_code, 0) # get the sat6 mapping of the imported organizations imp_orgs = get_sat6_id(csv_to_dataset([files['users']]), import_org[1]) repos_before = [ Repository.list({'organization-id': imp_org['sat6']}).stdout for imp_org in imp_orgs ] # Reimport the same repos and check for changes in sat6 self.assertEqual( Import.repository({ 'csv-file': files['repositories'], 'synchronize': True, 'wait': True, }).return_code, 0 ) self.assertEqual( repos_before, [ Repository.list({'organization-id': imp_org['sat6']}).stdout for imp_org in imp_orgs ] )
def test_negative_update_to_invalid_download_policy(self): """Verify that YUM repository cannot be updated to invalid download policy @id: 5bd6a2e4-7ff0-42ac-825a-6b2a2f687c89 @Assert: YUM repository is not updated to invalid download policy """ with self.assertRaises(CLIReturnCodeError): new_repo = self._make_repository({u"content-type": u"yum"}) Repository.update({u"id": new_repo["id"], u"download-policy": gen_string("alpha", 5)})
def test_positive_update_publish_method(self): """Update the original publishing method @id: e7bd2667-4851-4a64-9c70-1b5eafbc3f71 @Assert: Repository publishing method is updated """ new_repo = self._make_repository({u"publish-via-http": "no"}) Repository.update({u"id": new_repo["id"], u"publish-via-http": "yes"}) result = Repository.info({"id": new_repo["id"]}) self.assertEqual(result["publish-via-http"], "yes")
def test_positive_update_key_for_product_with_repo(self): """Create gpg key with valid name and valid gpg key via file import then associate it with custom product that has one repository then update the key @id: 3fb550a7-507e-4988-beb6-35bdfc2e99a8 @assert: gpg key is associated with product before/after update as well as with the repository @CaseLevel: Integration """ # Create a product and a gpg key product = make_product({'organization-id': self.org['id']}) gpg_key = make_gpg_key({'organization-id': self.org['id']}) # Create a repository and assign it to the product repo = make_repository({'product-id': product['id']}) # Associate gpg key with a product Product.update({ 'gpg-key': gpg_key['name'], 'id': product['id'], 'organization-id': self.org['id'], }) # Verify gpg key was associated product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) repo = Repository.info({'id': repo['id']}) self.assertEqual(product['gpg']['gpg-key'], gpg_key['name']) self.assertEqual(repo['gpg-key'].get('name'), gpg_key['name']) # Update the gpg key new_name = gen_choice(valid_data_list()) GPGKey.update({ 'name': gpg_key['name'], 'new-name': new_name, 'organization-id': self.org['id'], }) # Verify changes are reflected in the gpg key gpg_key = GPGKey.info({ 'id': gpg_key['id'], 'organization-id': self.org['id'], }) self.assertEqual(gpg_key['name'], new_name) # Verify changes are reflected in the product product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertEqual(product['gpg']['gpg-key'], new_name) # Verify changes are reflected in the repository repo = Repository.info({'id': repo['id']}) self.assertEqual(repo['gpg-key'].get('id'), gpg_key['id'])
def setup_content(request): """Pytest fixture for setting up an organization, manifest, content-view, lifecycle environment, and activation key with subscriptions""" org = make_org() with manifests.clone() as manifest: upload_file(manifest.content, manifest.filename) new_product = make_product({'organization-id': org['id']}) new_repo = make_repository({'product-id': new_product['id']}) Repository.synchronize({'id': new_repo['id']}) content_view = make_content_view({'organization-id': org['id']}) ContentView.add_repository({ 'id': content_view['id'], 'organization-id': org['id'], 'repository-id': new_repo['id'] }) ContentView.publish({'id': content_view['id']}) env = make_lifecycle_environment({'organization-id': org['id']}) cvv = ContentView.info({'id': content_view['id']})['versions'][0] ContentView.version_promote({ 'id': cvv['id'], 'to-lifecycle-environment-id': env['id'] }) new_ak = make_activation_key({ 'lifecycle-environment-id': env['id'], 'content-view': content_view['name'], 'organization-id': org['id'], 'auto-attach': False, }) subs_id = Subscription.list({'organization-id': org['id']}, per_page=False) ActivationKey.add_subscription({ 'id': new_ak['id'], 'subscription-id': subs_id[0]['id'] }) request.cls.setup_org = org request.cls.setup_new_ak = new_ak request.cls.setup_subs_id = subs_id request.cls.setup_env = env request.cls.setup_content_view = content_view
def test_positive_update_checksum_type(self): """Create a YUM repository and update the checksum type @Feature: Repository @Assert: A YUM repository is updated and contains the correct checksum type @BZ: 1208305 """ content_type = u'yum' repository = self._make_repository({u'content-type': content_type}) self.assertEqual(repository['content-type'], content_type) for checksum_type in u'sha1', u'sha256': with self.subTest(checksum_type): # Update the checksum Repository.update({ u'checksum-type': checksum_type, u'id': repository['id'], }) # Fetch it again result = Repository.info({'id': repository['id']}) self.assertEqual(result['checksum-type'], checksum_type)
def validate_repo_content(repo, content_types, after_sync=True): """Check whether corresponding content is present in repository before or after synchronization is performed :param repo: Repository instance to be validated :param content_types: List of repository content entities that should be validated (e.g. package, erratum, puppet_module) :param bool after_sync: Specify whether you perform validation before synchronization procedure is happened or after """ repo = Repository.info({'id': repo['id']}) for content in content_types: count = int(repo['content-counts'][content]) assert count > 0 if after_sync else count == 0
def make_file_repository_upload_contents(self, options=None): """Makes a new File repository, Upload File/Multiple Files and asserts its success. """ if options is None: options = { 'name': self.file_repo_name, 'product-id': self.product['id'], 'content-type': 'file', } if not options.get('content-type'): raise CLIFactoryError('Please provide a valid Content Type.') file_repo = make_repository(options) remote_path = f"/tmp/{RPM_TO_UPLOAD}" if 'multi_upload' not in options or not options['multi_upload']: ssh.upload_file(local_file=get_data_file(RPM_TO_UPLOAD), remote_file=remote_path) else: remote_path = "/tmp/{}/".format(gen_string('alpha')) ssh.upload_files(local_dir=os.getcwd() + "/../data/", remote_dir=remote_path) result = Repository.upload_content({ 'name': file_repo['name'], 'organization': file_repo['organization'], 'path': remote_path, 'product-id': file_repo['product']['id'], }) self.assertIn(f"Successfully uploaded file '{RPM_TO_UPLOAD}'", result[0]['message']) file_repo = Repository.info({'id': file_repo['id']}) self.assertGreater(int(file_repo['content-counts']['files']), 0) return file_repo
def test_positive_add_repo_from_product_with_repos(self): """Create gpg key via file import and associate with custom repo GPGKey should contain valid name and valid key and should be associated to one repository from custom product. Make sure custom product should have more than one repository. :id: 9796f6f0-e688-4f14-89ec-447feb4e4911 :expectedresults: gpg key is associated with the repository :CaseLevel: Integration """ product = make_product({'organization-id': self.org['id']}) repos = [ make_repository({'product-id': product['id']}) for _ in range(gen_integer(2, 5)) ] gpg_key = make_gpg_key({'organization-id': self.org['id']}) Repository.update({ 'gpg-key': gpg_key['name'], 'id': repos[0]['id'], 'organization-id': self.org['id'], }) product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertNotEqual(product['gpg'].get('gpg-key-id'), gpg_key['id']) # First repo should have a valid gpg key assigned repo = Repository.info({'id': repos.pop(0)['id']}) self.assertEqual(repo['gpg-key']['id'], gpg_key['id']) # The rest of repos should not for repo in repos: repo = Repository.info({'id': repo['id']}) self.assertNotEqual(repo['gpg-key'].get('id'), gpg_key['id'])
def test_positive_add_repo_from_product_with_repos(module_org): """Create gpg key via file import and associate with custom repo GPGKey should contain valid name and valid key and should be associated to one repository from custom product. Make sure custom product should have more than one repository. :id: e3019a61-ec32-4044-9087-e420b8db4e09 :expectedresults: gpg key is associated with the repository :CaseLevel: Integration """ product = make_product({'organization-id': module_org.id}) repos = [ make_repository({'product-id': product['id']}) for _ in range(gen_integer(2, 5)) ] gpg_key = make_content_credential({'organization-id': module_org.id}) Repository.update({ 'gpg-key': gpg_key['name'], 'id': repos[0]['id'], 'organization-id': module_org.id }) product = Product.info({ 'id': product['id'], 'organization-id': module_org.id }) assert product['gpg'].get('gpg-key-id') != gpg_key['id'] # First repo should have a valid gpg key assigned repo = Repository.info({'id': repos.pop(0)['id']}) assert repo['gpg-key']['id'] == gpg_key['id'] # The rest of repos should not for repo in repos: repo = Repository.info({'id': repo['id']}) assert repo['gpg-key'].get('id') != gpg_key['id']
def test_positive_delete_1(self, test_data): """ @Test: Check if repository can be created and deleted @Feature: Repository @Assert: Repository is created and then deleted """ new_repo = self._make_repository({u'name': test_data['name']}) # Assert that name matches data passed self.assertEqual(new_repo['name'], test_data['name'], "Names don't match") # Delete it result = Repository.delete({u'id': new_repo['id']}) self.assertEqual(result.return_code, 0, "Repository was not deleted") self.assertEqual(len(result.stderr), 0, "No error was expected") # Fetch it result = Repository.info({ u'id': new_repo['id'], }) self.assertNotEqual(result.return_code, 0, "Repository should not be found") self.assertGreater(len(result.stderr), 0, "Expected an error here")
def test_positive_create_8(self, test_data): """ @Test: Create repository not published via http @Feature: Repository @Assert: Repository is created and is not published via http """ new_repo = self._make_repository({'publish-via-http': test_data}) # Fetch it again result = Repository.info({'id': new_repo['id']}) self.assertEqual(result.return_code, 0, "Repository was not found") self.assertEqual(len(result.stderr), 0, "No error was expected") self.assertEqual(result.stdout['publish-via-http'], u'no', "Publishing methods don't match")
def test_positive_add_custom_product(self): """Test that custom product can be associated to Activation Keys @Feature: Activation key - Product @Assert: Custom products are successfully associated to Activation key """ result = setup_org_for_a_custom_repo({ u'url': FAKE_0_YUM_REPO, u'organization-id': self.org['id'], }) repo = Repository.info({u'id': result['repository-id']}) content = ActivationKey.product_content({ u'id': result['activationkey-id'], u'organization-id': self.org['id'], }) self.assertEqual(content[0]['name'], repo['name'])
def test_product_list_with_default_settings(self): """Listing product of an organization apart from default organization using hammer does not return output if a defaults settings are applied on org. :id: d5c5edac-b19c-4277-92fe-28d9b9fa43ef :BZ: 1745575 :expectedresults: product/reporsitory list should work as expected. """ default_product_name = gen_string('alpha') non_default_product_name = gen_string('alpha') default_org = self.org non_default_org = make_org() default_product = make_product( {'name': default_product_name, 'organization-id': default_org['id']} ) non_default_product = make_product( {'name': non_default_product_name, 'organization-id': non_default_org['id']} ) for product in (default_product, non_default_product): make_repository({'product-id': product['id'], 'url': FAKE_0_YUM_REPO}) Defaults.add({'param-name': 'organization_id', 'param-value': default_org['id']}) result = ssh.command('hammer defaults list') self.assertTrue(default_org['id'] in "".join(result.stdout)) try: # Verify --organization-id is not required to pass if defaults are set result = ssh.command('hammer product list') self.assertTrue(default_product_name in "".join(result.stdout)) result = ssh.command('hammer repository list') self.assertTrue(default_product_name in "".join(result.stdout)) # verify that defaults setting should not affect other entities product_list = Product.list({'organization-id': non_default_org['id']}) self.assertEquals(non_default_product_name, product_list[0]['name']) repository_list = Repository.list({'organization-id': non_default_org['id']}) self.assertEquals(non_default_product_name, repository_list[0]['product']) finally: Defaults.delete({'param-name': 'organization_id'}) result = ssh.command('hammer defaults list') self.assertTrue(default_org['id'] not in "".join(result.stdout))
def test_positive_update_key_for_repo_from_product_with_repo(self): """Create gpg key with valid name and valid gpg key via file import then associate it to repository from custom product that has one repository then update the key :id: 549e2e1e-fd10-4487-a3a5-fdee9b8cfc48 :expectedresults: gpg key is associated with the repository before/after update, but not with the product :CaseLevel: Integration """ # Create a product and a gpg key product = make_product({'organization-id': self.org['id']}) gpg_key = make_gpg_key({'organization-id': self.org['id']}) # Create repository, assign product and gpg-key repo = make_repository({ 'gpg-key-id': gpg_key['id'], 'product-id': product['id'], }) # Verify gpg key was associated self.assertEqual(repo['gpg-key'].get('name'), gpg_key['name']) # Update the gpg key new_name = gen_choice(valid_data_list()) GPGKey.update({ 'name': gpg_key['name'], 'new-name': new_name, 'organization-id': self.org['id'], }) # Verify changes are reflected in the gpg key gpg_key = GPGKey.info({ 'id': gpg_key['id'], 'organization-id': self.org['id'], }) self.assertEqual(gpg_key['name'], new_name) # Verify changes are reflected in the repositories repo = Repository.info({'id': repo['id']}) self.assertEqual(repo['gpg-key'].get('name'), new_name) # Verify gpg key wasn't added to the product product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'], }) self.assertNotEqual(product['gpg']['gpg-key'], new_name)
def test_positive_update_key_for_repo_from_product_with_repo(module_org): """Create gpg key with valid name and valid gpg key via file import then associate it to repository from custom product that has one repository then update the key :id: 2fee5f35-6e0e-4b7c-8a8a-46ee1e77919d :expectedresults: gpg key is associated with the repository before/after update, but not with the product :CaseLevel: Integration """ # Create a product and a gpg key product = make_product({'organization-id': module_org.id}) gpg_key = make_content_credential({'organization-id': module_org.id}) # Create repository, assign product and gpg-key repo = make_repository({ 'gpg-key-id': gpg_key['id'], 'product-id': product['id'] }) # Verify gpg key was associated assert repo['gpg-key'].get('name') == gpg_key['name'] # Update the gpg key new_name = gen_choice(list(valid_data_list().values())) ContentCredential.update({ 'name': gpg_key['name'], 'new-name': new_name, 'organization-id': module_org.id }) # Verify changes are reflected in the gpg key gpg_key = ContentCredential.info({ 'id': gpg_key['id'], 'organization-id': module_org.id }) assert gpg_key['name'] == new_name # Verify changes are reflected in the repositories repo = Repository.info({'id': repo['id']}) assert repo['gpg-key'].get('name') == new_name # Verify gpg key wasn't added to the product product = Product.info({ 'id': product['id'], 'organization-id': module_org.id }) assert product['gpg']['gpg-key'] != new_name
def test_positive_add_custom_product(self): """Test that custom product can be associated to Activation Keys @id: 96ace967-e165-4069-8ff7-f54c4c822de0 @Assert: Custom products are successfully associated to Activation key @CaseLevel: System """ result = setup_org_for_a_custom_repo({ u'url': FAKE_0_YUM_REPO, u'organization-id': self.org['id'], }) repo = Repository.info({u'id': result['repository-id']}) content = ActivationKey.product_content({ u'id': result['activationkey-id'], u'organization-id': self.org['id'], }) self.assertEqual(content[0]['name'], repo['name'])
def test_positive_add_redhat_and_custom_products(self): """Test if RH/Custom product can be associated to Activation key :id: 74c77426-18f5-4abb-bca9-a2135f7fcc1f :Steps: 1. Create Activation key 2. Associate RH product(s) to Activation Key 3. Associate custom product(s) to Activation Key :expectedresults: RH/Custom product is successfully associated to Activation key :CaseLevel: System :BZ: 1426386 """ org = make_org() # Using CDN as we need this repo to be RH one no matter are we in # downstream or cdn result = setup_org_for_a_rh_repo({ u'product': PRDS['rhel'], u'repository-set': REPOSET['rhst7'], u'repository': REPOS['rhst7']['name'], u'organization-id': org['id'], }, force_use_cdn=True) result = setup_org_for_a_custom_repo({ u'url': FAKE_0_YUM_REPO, u'organization-id': org['id'], u'activationkey-id': result['activationkey-id'], u'content-view-id': result['content-view-id'], u'lifecycle-environment-id': result['lifecycle-environment-id'], }) repo = Repository.info({u'id': result['repository-id']}) content = ActivationKey.product_content({ u'id': result['activationkey-id'], u'organization-id': org['id'], }) self.assertEqual(len(content), 2) self.assertEqual( {REPOSET['rhst7'], repo['name']}, {pc['name'] for pc in content})
def _make_repository(self, options=None): """ Makes a new repository and asserts its success """ if options is None: options = {} if not options.get('product-id', None): options[u'product-id'] = self.product['id'] new_repo = make_repository(options) # Fetch it result = Repository.info({u'id': new_repo['id']}) self.assertEqual(result.return_code, 0, "Repository was not found") self.assertEqual(len(result.stderr), 0, "No error was expected") # Return the repository dictionary return new_repo
def repository_single_sync(cls, repo_id, repo_name, thread_id): """Single Synchronization :param str repo_id: Repository id to be synchronized :param str repo_name: Repository name :return: time measure for a single sync :rtype: float """ LOGGER.info('Synchronize {0} by thread-{1}:'.format( repo_name, thread_id)) result = Repository.synchronize({'id': repo_id}, return_raw_response=True) if result.return_code != 0: LOGGER.error('Sync repository {0} by thread-{1} failed!'.format( repo_name, thread_id)) return 0 LOGGER.info('Sync repository {0} by thread-{1} successful!'.format( repo_name, thread_id)) return cls.get_elapsed_time(result.stderr)
def get_enabled_repos(org_id): """Get all enabled repositories ids and names :return map_repo_name_id: The dictionary contains all enabled repositories in Satellite. Map repo-name as key, repo-id as value :raises ``RumtimeException`` if there's no enabled repository in default organization denoted by ``org_id`` """ LOGGER.info('Searching for enabled repositories by hammer CLI:') try: result = Repository.list({'organization-id': org_id}, per_page=False) except CLIReturnCodeError: raise RuntimeError( 'No enabled repository found in organization {0}!'.format( org_id)) # map repository name with id map_repo_name_id = {} for repo in result: map_repo_name_id[repo['name']] = repo['id'] return map_repo_name_id
def test_positive_export_custom_product(self): """Export a repository from the custom product :id: 9c855866-b9b1-4e32-b3eb-7342fdaa7116 :expectedresults: Repository was successfully exported, rpm files are present on satellite machine :CaseLevel: System """ # Create custom product and repository product = make_product({'organization-id': self.org['id']}) repo = make_repository({ 'download-policy': 'immediate', 'organization-id': self.org['id'], 'product-id': product['id'], }) backend_identifier = entities.Repository( id=repo['id']).read().backend_identifier repo_export_dir = '/mnt/{0}/{1}/{2}/{3}/custom/{4}/{5}'.format( self.export_dir, backend_identifier, self.org['label'], ENVIRONMENT, product['label'], repo['label'], ) # Export the repository Repository.export({'id': repo['id']}) # Verify export directory is empty result = ssh.command("find {} -name '*.rpm'".format(repo_export_dir)) self.assertEqual(len(result.stdout), 0) # Synchronize the repository Repository.synchronize({'id': repo['id']}) # Export the repository once again Repository.export({'id': repo['id']}) # Verify RPMs were successfully exported result = ssh.command("find {} -name '*.rpm'".format(repo_export_dir)) self.assertEqual(result.return_code, 0) self.assertGreaterEqual(len(result.stdout), 1)
def test_positive_add_redhat_and_custom_products(self): """Test if RH/Custom product can be associated to Activation key @id: 74c77426-18f5-4abb-bca9-a2135f7fcc1f @Steps: 1. Create Activation key 2. Associate RH product(s) to Activation Key 3. Associate custom product(s) to Activation Key @Assert: RH/Custom product is successfully associated to Activation key @CaseLevel: System """ org = make_org() result = setup_org_for_a_rh_repo({ u'product': PRDS['rhel'], u'repository-set': REPOSET['rhst7'], u'repository': REPOS['rhst7']['name'], u'organization-id': org['id'], }) result = setup_org_for_a_custom_repo({ u'url': FAKE_0_YUM_REPO, u'organization-id': org['id'], u'activationkey-id': result['activationkey-id'], u'content-view-id': result['content-view-id'], u'lifecycle-environment-id': result['lifecycle-environment-id'], }) repo = Repository.info({u'id': result['repository-id']}) content = ActivationKey.product_content({ u'id': result['activationkey-id'], u'organization-id': org['id'], }) self.assertEqual(len(content), 2) self.assertEqual( {REPOSET['rhst7'], repo['name']}, {pc['name'] for pc in content})
def test_positive_add_redhat_and_custom_products(self): """Test if RH/Custom product can be associated to Activation key @Feature: Activation key - Product @Steps: 1. Create Activation key 2. Associate RH product(s) to Activation Key 3. Associate custom product(s) to Activation Key @BZ: 1293585 @Assert: RH/Custom product is successfully associated to Activation key """ result = setup_org_for_a_rh_repo({ u'product': PRDS['rhel'], u'repository-set': REPOSET['rhst7'], u'repository': REPOS['rhst7']['name'], u'organization-id': self.org['id'], }) result = setup_org_for_a_custom_repo({ u'url': FAKE_0_YUM_REPO, u'organization-id': self.org['id'], u'activationkey-id': result['activationkey-id'], u'content-view-id': result['content-view-id'], u'lifecycle-environment-id': result['lifecycle-environment-id'], }) repo = Repository.info({u'id': result['repository-id']}) content = ActivationKey.product_content({ u'id': result['activationkey-id'], u'organization-id': self.org['id'], }) self.assertEqual(len(content), 2) self.assertEqual(content[0]['name'], REPOSET['rhst7']) self.assertEqual(content[1]['name'], repo['name'])
def _enable_repositories(self): for i, repo in enumerate(self.repository_list): repo_id = repo[0] basearch = repo[1] releasever = repo[2] self.logger.info('Enabling product {0}: repository id {1} ' 'with baserach {2} and release {3}'.format( i, repo_id, basearch, releasever)) # Enable repos from Repository Set result = RepositorySet.enable({ 'product-id': self.pid, 'basearch': basearch, 'releasever': releasever, 'id': repo_id }) # verify enabled repository list result = Repository.list({'organization-id': self.org_id}, per_page=False) # repo_list_ids would contain all repositories in the hammer repo list repo_list_ids = [repo['id'] for repo in result.stdout] self.logger.debug(repo_list_ids)
def test_positive_upload_content_srpm(self): """Create repository and upload a SRPM content @id: 706dc3e2-dacb-4fdd-8eef-5715ce498888 @Assert: File successfully uploaded """ new_repo = self._make_repository({'name': gen_string('alpha', 15)}) ssh.upload_file(local_file=get_data_file(SRPM_TO_UPLOAD), remote_file="/tmp/{0}".format(SRPM_TO_UPLOAD)) result = Repository.upload_content({ 'name': new_repo['name'], 'organization': new_repo['organization'], 'path': "/tmp/{0}".format(SRPM_TO_UPLOAD), 'product-id': new_repo['product']['id'], }) self.assertIn( "Successfully uploaded file '{0}'".format(SRPM_TO_UPLOAD), result[0]['message'], )
def test_positive_upload_content(self): """Create repository and upload content @id: eb0ec599-2bf1-483a-8215-66652f948d67 @Assert: upload content is successful """ new_repo = self._make_repository({'name': gen_string('alpha', 15)}) ssh.upload_file(local_file=get_data_file(RPM_TO_UPLOAD), remote_file="/tmp/{0}".format(RPM_TO_UPLOAD)) result = Repository.upload_content({ 'name': new_repo['name'], 'organization': new_repo['organization'], 'path': "/tmp/{0}".format(RPM_TO_UPLOAD), 'product-id': new_repo['product']['id'], }) self.assertIn( "Successfully uploaded file '{0}'".format(RPM_TO_UPLOAD), result[0]['message'], )
def test_positive_export_custom_product(self): """Export a repository from the custom product @Feature: Repository - Export @Assert: Repository was successfully exported, rpm files are present on satellite machine """ # Create custom product and repository product = make_product({'organization-id': self.org['id']}) repo = make_repository({ 'download-policy': 'immediate', 'organization-id': self.org['id'], 'product-id': product['id'], }) repo_export_dir = '/mnt/{0}/{1}-{2}-{3}/{1}/{4}/custom/{2}/{3}'.format( self.export_dir, self.org['label'], product['label'], repo['label'], ENVIRONMENT, ) # Export the repository Repository.export({'id': repo['id']}) # Verify export directory is empty result = ssh.command('ls -l {0} | grep .rpm'.format(repo_export_dir)) self.assertEqual(len(result.stdout), 0) # Synchronize the repository Repository.synchronize({'id': repo['id']}) # Export the repository once again Repository.export({'id': repo['id']}) # Verify RPMs were successfully exported result = ssh.command('ls -l {0} | grep .rpm'.format(repo_export_dir)) self.assertEqual(result.return_code, 0) self.assertGreaterEqual(len(result.stdout), 1)
def test_positive_CRUD(self): """Check if product can be created, updated, synchronized and deleted :id: 9d7b5ec8-59d0-4371-b5d2-d43145e4e2db :expectedresults: Product is created, updated, synchronized and deleted :BZ: 1422552 :CaseImportance: Critical """ desc = list(valid_data_list().values())[0] gpg_key = make_gpg_key({'organization-id': self.org['id']}) name = list(valid_data_list().values())[0] label = valid_labels_list()[0] sync_plan = make_sync_plan({'organization-id': self.org['id']}) product = make_product({ 'description': desc, 'gpg-key-id': gpg_key['id'], 'label': label, 'name': name, 'organization-id': self.org['id'], 'sync-plan-id': sync_plan['id'], }) self.assertEqual(product['name'], name) self.assertGreater(len(product['label']), 0) self.assertEqual(product['label'], label) self.assertEqual(product['description'], desc) self.assertEqual(product['gpg']['gpg-key-id'], gpg_key['id']) self.assertEqual(product['sync-plan-id'], sync_plan['id']) # update desc = list(valid_data_list().values())[0] new_gpg_key = make_gpg_key({'organization-id': self.org['id']}) new_sync_plan = make_sync_plan({'organization-id': self.org['id']}) new_prod_name = gen_string('alpha', 8) Product.update({ 'description': desc, 'id': product['id'], 'gpg-key-id': new_gpg_key['id'], 'sync-plan-id': new_sync_plan['id'], 'name': new_prod_name, }) product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'] }) self.assertEqual(product['name'], new_prod_name) self.assertEqual(product['description'], desc) self.assertEqual(product['gpg']['gpg-key-id'], new_gpg_key['id']) self.assertNotEqual(product['gpg']['gpg-key-id'], gpg_key['id']) self.assertEqual(product['sync-plan-id'], new_sync_plan['id']) self.assertNotEqual(product['sync-plan-id'], sync_plan['id']) # synchronize repo = make_repository({ 'product-id': product['id'], 'url': FAKE_0_YUM_REPO }) Product.synchronize({ 'id': product['id'], 'organization-id': self.org['id'] }) packages = Package.list({'product-id': product['id']}) repo = Repository.info({'id': repo['id']}) self.assertEqual(int(repo['content-counts']['packages']), len(packages)) self.assertEqual(len(packages), FAKE_0_YUM_REPO_PACKAGES_COUNT) # delete Product.remove_sync_plan({'id': product['id']}) product = Product.info({ 'id': product['id'], 'organization-id': self.org['id'] }) self.assertEqual(len(product['sync-plan-id']), 0) Product.delete({'id': product['id']}) wait_for_tasks( search_query='label = Actions::Katello::Product::Destroy' ' and resource_id = {}'.format(product['id']), max_tries=10, ) with self.assertRaises(CLIReturnCodeError): Product.info({ 'id': product['id'], 'organization-id': self.org['id'] })
def test_positive_assign_http_proxy_to_products(self): """Assign http_proxy to Products and perform product sync. :id: 6af7b2b8-15d5-4d9f-9f87-e76b404a966f :expectedresults: HTTP Proxy is assigned to all repos present in Products and sync operation performed successfully. :CaseImportance: Critical """ # create HTTP proxies http_proxy_a = HttpProxy.create({ 'name': gen_string('alpha', 15), 'url': settings.http_proxy.un_auth_proxy_url, 'organization-id': self.org['id'], }) http_proxy_b = HttpProxy.create({ 'name': gen_string('alpha', 15), 'url': settings.http_proxy.auth_proxy_url, 'username': settings.http_proxy.username, 'password': settings.http_proxy.password, 'organization-id': self.org['id'], }) # Create products and repositories product_a = make_product({'organization-id': self.org['id']}) product_b = make_product({'organization-id': self.org['id']}) repo_a1 = make_repository({ 'product-id': product_a['id'], 'url': FAKE_0_YUM_REPO, 'http-proxy-policy': 'none' }) repo_a2 = make_repository({ 'product-id': product_a['id'], 'url': FAKE_0_YUM_REPO, 'http-proxy-policy': 'use_selected_http_proxy', 'http-proxy-id': http_proxy_a['id'], }) repo_b1 = make_repository({ 'product-id': product_b['id'], 'url': FAKE_0_YUM_REPO, 'http-proxy-policy': 'none' }) repo_b2 = make_repository({ 'product-id': product_b['id'], 'url': FAKE_0_YUM_REPO }) # Add http_proxy to products Product.update_proxy({ 'ids': '{},{}'.format(product_a['id'], product_b['id']), 'http-proxy-policy': 'use_selected_http_proxy', 'http-proxy-id': http_proxy_b['id'], }) # Perform sync and verify packages count Product.synchronize({ 'id': product_a['id'], 'organization-id': self.org['id'] }) Product.synchronize({ 'id': product_b['id'], 'organization-id': self.org['id'] }) repo_a1 = Repository.info({'id': repo_a1['id']}) repo_a2 = Repository.info({'id': repo_a2['id']}) repo_b1 = Repository.info({'id': repo_b1['id']}) repo_b2 = Repository.info({'id': repo_b2['id']}) assert repo_a1['http-proxy'][ 'http-proxy-policy'] == "use_selected_http_proxy" assert repo_a2['http-proxy'][ 'http-proxy-policy'] == "use_selected_http_proxy" assert repo_b1['http-proxy'][ 'http-proxy-policy'] == "use_selected_http_proxy" assert repo_b2['http-proxy'][ 'http-proxy-policy'] == "use_selected_http_proxy" assert repo_a1['http-proxy']['id'] == http_proxy_b['id'] assert repo_a2['http-proxy']['id'] == http_proxy_b['id'] assert repo_b1['http-proxy']['id'] == http_proxy_b['id'] assert repo_b2['http-proxy']['id'] == http_proxy_b['id'] assert int(repo_a1['content-counts'] ['packages']) == FAKE_0_YUM_REPO_PACKAGES_COUNT assert int(repo_a2['content-counts'] ['packages']) == FAKE_0_YUM_REPO_PACKAGES_COUNT assert int(repo_b1['content-counts'] ['packages']) == FAKE_0_YUM_REPO_PACKAGES_COUNT assert int(repo_b2['content-counts'] ['packages']) == FAKE_0_YUM_REPO_PACKAGES_COUNT Product.update_proxy({ 'ids': '{},{}'.format(product_a['id'], product_b['id']), 'http-proxy-policy': 'none' }) repo_a1 = Repository.info({'id': repo_a1['id']}) repo_a2 = Repository.info({'id': repo_a2['id']}) repo_b1 = Repository.info({'id': repo_b1['id']}) repo_b2 = Repository.info({'id': repo_b2['id']}) assert repo_a1['http-proxy']['http-proxy-policy'] == "none" assert repo_a2['http-proxy']['http-proxy-policy'] == "none" assert repo_b1['http-proxy']['http-proxy-policy'] == "none" assert repo_b2['http-proxy']['http-proxy-policy'] == "none"
def synchronize(self): """Synchronize the repository""" Repository.synchronize({'id': self.repo_info['id']}, timeout=4800)
def test_cv_postupgrade_scenario(self): """This is post-upgrade scenario test to verify if we can update content-view created in pre-upgrade scenario with various repositories. :id: a4ebbfa1-106a-4962-9c7c-082833879ae8 :steps: 1. Remove yum repository which was added to content-view before upgrade. 2. Create new yum repository and add it to content-view. 3. Remove puppet module which was added to content-view before upgrade. 4. Add another puppet module to content-view 5. Publish content-view :expectedresults: content-view updated with various repositories. """ product_id = Repository.info({ 'name': self.yum_repo1_name, 'organization': self.org_name, 'product': self.product_name })['product']['id'] ContentView.remove_repository({ 'organization': self.org_name, 'name': self.cv_name, 'repository': self.yum_repo1_name }) content_view = ContentView.info({ 'name': self.cv_name, 'organization': self.org_name }) self.assertNotIn(self.yum_repo1_name, content_view['yum-repositories']) yum_repo2 = make_repository({ 'name': self.yum_repo2_name, 'organization': self.org_name, 'content-type': 'yum', 'product-id': product_id, 'url': FAKE_2_YUM_REPO }) Repository.synchronize({ 'id': yum_repo2['id'], 'organization': self.org_name }) ContentView.add_repository({ 'name': self.cv_name, 'organization': self.org_name, 'product': self.product_name, 'repository-id': yum_repo2['id'] }) content_view = ContentView.info({ 'name': self.cv_name, 'organization': self.org_name }) self.assertEqual( content_view['yum-repositories'][0]['name'], self.yum_repo2_name, 'Repo was not associated to CV', ) ContentView.puppet_module_remove({ 'organization': self.org_name, 'content-view': self.cv_name, 'name': self.puppet_module_name, 'author': self.puppet_module_author, }) content_view = ContentView.info({ 'name': self.cv_name, 'organization': self.org_name }) self.assertEqual(len(content_view['puppet-modules']), 0) module = {'name': 'versioned', 'version': '2.2.2'} puppet_module = PuppetModule.list( {'search': 'name={name} and version={version}'.format(**module)})[0] ContentView.puppet_module_add({ 'organization': self.org_name, 'content-view': self.cv_name, 'name': puppet_module['name'], 'author': puppet_module['author'], }) content_view = ContentView.info({'id': content_view['id']}) self.assertGreater(len(content_view['puppet-modules']), 0) ContentView.publish({ 'name': self.cv_name, 'organization': self.org_name }) content_view = ContentView.info({ 'name': self.cv_name, 'organization': self.org_name }) self.assertEqual(len(content_view['versions']), 2)
def test_positive_end_to_end(self): """Perform end to end smoke tests using RH and custom repos. 1. Create a new user with admin permissions 2. Using the new user from above 1. Create a new organization 2. Clone and upload manifest 3. Create a new lifecycle environment 4. Create a custom product 5. Create a custom YUM repository 6. Create a custom PUPPET repository 7. Enable a Red Hat repository 8. Synchronize the three repositories 9. Create a new content view 10. Associate the YUM and Red Hat repositories to new content view 11. Add a PUPPET module to new content view 12. Publish content view 13. Promote content view to the lifecycle environment 14. Create a new activation key 15. Add the products to the activation key 16. Create a new libvirt compute resource 17. Create a new subnet 18. Create a new domain 19. Create a new hostgroup and associate previous entities to it 20. Provision a client @id: 8c8b3ffa-0d54-436b-8eeb-1a3542e100a8 @Assert: All tests should succeed and Content should be successfully fetched by client. """ # step 1: Create a new user with admin permissions password = gen_alphanumeric() user = make_user({u'admin': u'true', u'password': password}) user['password'] = password # step 2.1: Create a new organization org = self._create(user, Org, {u'name': gen_alphanumeric()}) # step 2.2: Clone and upload manifest if self.fake_manifest_is_set: with manifests.clone() as manifest: ssh.upload_file(manifest.content, manifest.filename) Subscription.upload({ u'file': manifest.filename, u'organization-id': org['id'], }) # step 2.3: Create a new lifecycle environment lifecycle_environment = self._create( user, LifecycleEnvironment, { u'name': gen_alphanumeric(), u'organization-id': org['id'], u'prior': u'Library', }) # step 2.4: Create a custom product product = self._create(user, Product, { u'name': gen_alphanumeric(), u'organization-id': org['id'], }) repositories = [] # step 2.5: Create custom YUM repository yum_repo = self._create( user, Repository, { u'content-type': u'yum', u'name': gen_alphanumeric(), u'product-id': product['id'], u'publish-via-http': u'true', u'url': GOOGLE_CHROME_REPO, }) repositories.append(yum_repo) # step 2.6: Create custom PUPPET repository puppet_repo = self._create( user, Repository, { u'content-type': u'puppet', u'name': gen_alphanumeric(), u'product-id': product['id'], u'publish-via-http': u'true', u'url': FAKE_0_PUPPET_REPO, }) repositories.append(puppet_repo) # step 2.7: Enable a Red Hat repository if self.fake_manifest_is_set: RepositorySet.enable({ u'basearch': 'x86_64', u'name': REPOSET['rhva6'], u'organization-id': org['id'], u'product': PRDS['rhel'], u'releasever': '6Server', }) rhel_repo = Repository.info({ u'name': REPOS['rhva6']['name'], u'organization-id': org['id'], u'product': PRDS['rhel'], }) repositories.append(rhel_repo) # step 2.8: Synchronize the three repositories for repo in repositories: Repository.with_user(user['login'], user['password']).synchronize( {u'id': repo['id']}) # step 2.9: Create content view content_view = self._create(user, ContentView, { u'name': gen_alphanumeric(), u'organization-id': org['id'], }) # step 2.10: Associate the YUM and Red Hat repositories to new content # view repositories.remove(puppet_repo) for repo in repositories: ContentView.add_repository({ u'id': content_view['id'], u'organization-id': org['id'], u'repository-id': repo['id'], }) # step 2.11: Add a PUPPET module to new content view result = PuppetModule.with_user(user['login'], user['password']).list({ u'repository-id': puppet_repo['id'], u'per-page': False, }) ContentView.with_user(user['login'], user['password']).puppet_module_add({ u'content-view-id': content_view['id'], u'id': random.choice(result)['id'], }) # step 2.12: Publish content view ContentView.with_user(user['login'], user['password']).publish( {u'id': content_view['id']}) # step 2.13: Promote content view to the lifecycle environment content_view = ContentView.with_user( user['login'], user['password']).info({u'id': content_view['id']}) self.assertEqual(len(content_view['versions']), 1) cv_version = ContentView.with_user( user['login'], user['password']).version_info({ 'id': content_view['versions'][0]['id'], }) self.assertEqual(len(cv_version['lifecycle-environments']), 1) ContentView.with_user(user['login'], user['password']).version_promote({ u'id': cv_version['id'], u'to-lifecycle-environment-id': lifecycle_environment['id'], }) # check that content view exists in lifecycle content_view = ContentView.with_user( user['login'], user['password']).info({u'id': content_view['id']}) self.assertEqual(len(content_view['versions']), 1) cv_version = ContentView.with_user( user['login'], user['password']).version_info({ 'id': content_view['versions'][0]['id'], }) self.assertEqual(len(cv_version['lifecycle-environments']), 2) self.assertEqual(cv_version['lifecycle-environments'][-1]['id'], lifecycle_environment['id']) # step 2.14: Create a new activation key activation_key = self._create( user, ActivationKey, { u'content-view-id': content_view['id'], u'lifecycle-environment-id': lifecycle_environment['id'], u'name': gen_alphanumeric(), u'organization-id': org['id'], }) # step 2.15: Add the products to the activation key subscription_list = Subscription.with_user( user['login'], user['password']).list({u'organization-id': org['id']}, per_page=False) for subscription in subscription_list: if subscription['name'] == DEFAULT_SUBSCRIPTION_NAME: ActivationKey.with_user(user['login'], user['password']).add_subscription({ u'id': activation_key['id'], u'quantity': 1, u'subscription-id': subscription['id'], }) # step 2.15.1: Enable product content if self.fake_manifest_is_set: ActivationKey.with_user(user['login'], user['password']).content_override({ u'content-label': AK_CONTENT_LABEL, u'id': activation_key['id'], u'organization-id': org['id'], u'value': '1', }) # BONUS: Create a content host and associate it with promoted # content view and last lifecycle where it exists content_host_name = gen_alphanumeric() content_host = Host.with_user(user['login'], user['password']).subscription_register({ u'content-view-id': content_view['id'], u'lifecycle-environment-id': lifecycle_environment['id'], u'name': content_host_name, u'organization-id': org['id'], }) if bz_bug_is_open(1328202): results = ContentHost.with_user(user['login'], user['password']).list( {'organization-id': org['id']}) # Content host registration converts the name to lowercase, make # sure to use the same format while matching against the result content_host_name = content_host_name.lower() for result in results: if result['name'] == content_host_name: content_host = result content_host = ContentHost.with_user( user['login'], user['password']).info({'id': content_host['id']}) # check that content view matches what we passed self.assertEqual(content_host['content-view'], content_view['name']) # check that lifecycle environment matches self.assertEqual(content_host['lifecycle-environment'], lifecycle_environment['name']) # step 2.16: Create a new libvirt compute resource self._create( user, ComputeResource, { u'name': gen_alphanumeric(), u'provider': u'Libvirt', u'url': u'qemu+ssh://root@{0}/system'.format( settings.compute_resources.libvirt_hostname), }) # step 2.17: Create a new subnet subnet = self._create( user, Subnet, { u'name': gen_alphanumeric(), u'network': gen_ipaddr(ip3=True), u'mask': u'255.255.255.0', }) # step 2.18: Create a new domain domain = self._create(user, Domain, {u'name': gen_alphanumeric()}) # step 2.19: Create a new hostgroup and associate previous entities to # it host_group = self._create( user, HostGroup, { u'domain-id': domain['id'], u'name': gen_alphanumeric(), u'subnet-id': subnet['id'], }) if not bz_bug_is_open('1326101'): Org.with_user(user['login'], user['password']).add_hostgroup({ u'hostgroup-id': host_group['id'], u'id': org['id'], }) # step 2.20: Provision a client self.client_provisioning(activation_key['name'], org['label'])
def test_positive_synchronize_rh_product_future_sync_date(module_org): """Create a sync plan with sync date in a future and sync one RH product with it automatically. :id: 6ce2f777-f230-4bb8-9822-2cf3580c21aa :expectedresults: Product is synchronized successfully. :CaseLevel: System :BZ: 1655595 """ delay = 2 * 60 # delay for sync date in seconds org = make_org() with manifests.clone() as manifest: upload_file(manifest.content, manifest.filename) Subscription.upload({ 'file': manifest.filename, 'organization-id': org['id'] }) RepositorySet.enable({ 'name': REPOSET['rhva6'], 'organization-id': org['id'], 'product': PRDS['rhel'], 'releasever': '6Server', 'basearch': 'x86_64', }) product = Product.info({ 'name': PRDS['rhel'], 'organization-id': org['id'] }) repo = Repository.info({ 'name': REPOS['rhva6']['name'], 'product': product['name'], 'organization-id': org['id'] }) sync_plan = make_sync_plan({ 'enabled': 'true', 'organization-id': module_org.id, 'sync-date': (datetime.utcnow().replace(second=0) + timedelta(seconds=delay)).strftime(SYNC_DATE_FMT), 'cron-expression': ["*/4 * * * *"], }) # Verify product is not synced and doesn't have any content with pytest.raises(AssertionError): validate_task_status(repo['id'], max_tries=1) validate_repo_content(repo, ['errata', 'packages'], after_sync=False) # Associate sync plan with product Product.set_sync_plan({ 'id': product['id'], 'sync-plan-id': sync_plan['id'] }) # Wait quarter of expected time logger.info('Waiting {} seconds to check product {}' ' was not synced'.format(delay / 4, product['name'])) sleep(delay / 4) # Verify product has not been synced yet with pytest.raises(AssertionError): validate_task_status(repo['id'], max_tries=1) validate_repo_content(repo, ['errata', 'packages'], after_sync=False) # Wait the rest of expected time logger.info('Waiting {} seconds to check product {}' ' was synced'.format((delay * 3 / 4), product['name'])) sleep(delay * 3 / 4) # Verify product was synced successfully validate_task_status(repo['id'], repo_name=repo['name']) validate_repo_content(repo, ['errata', 'packages'])