def test_update(self, attrs): """@Test: Create a repository and update its attributes. @Assert: The repository's attributes are updated. @Feature: Repository """ client.put( self.repository.path(), attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() real_attrs = self.repository.read_json() for name, value in attrs.items(): self.assertIn(name, real_attrs.keys()) if name == 'content_type': # Cannot update a repository's content type. self.assertEqual( entities.Repository.content_type.default, real_attrs[name] ) else: self.assertEqual(value, real_attrs[name])
def test_update(self, entity): """@Test: Check whether the "edit_*" role has an effect. @Assert: A user cannot update an entity when missing the "edit_*" role, and they can update an entity when given the "edit_*" role. @Feature: Role NOTE: This method will only work if ``entity`` has a name. """ entity_obj = entity(id=entity().create()['id']) with self.assertRaises(HTTPError): client.put( entity_obj.path(), {u'name': entity.name.gen_value()}, auth=self.auth, verify=False, ).raise_for_status() self.give_user_permission(_permission_name(entity, 'update')) client.put( entity_obj.path(), {u'name': entity.name.gen_value()}, auth=self.auth, verify=False, ).raise_for_status()
def test_update_docker_repo_url(self, name): """@Test: Create a Docker-type repository and update its URL. @Assert: A repository is created with a Docker image and that its URL can be updated. @Feature: Docker """ new_url = gen_url(scheme='https') prod_id = entities.Product( organization=self.org_id ).create_json()['id'] repo_id = _create_repository(prod_id, name)['id'] real_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(real_attrs['url'], DOCKER_REGISTRY_HUB) # Update the repository URL real_attrs['url'] = new_url client.put( entities.Repository(id=repo_id).path(), real_attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() new_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(new_attrs['url'], new_url) self.assertNotEqual(new_attrs['url'], DOCKER_REGISTRY_HUB)
def give_user_permission(self, perm_name): """Give ``self.user`` the ``perm_name`` permission. This method creates a role and filter to accomplish the above goal. When complete, the relevant relationhips look like this: user → role ← filter → permission :param str perm_name: The name of a permission. For example: 'create_architectures'. :raises: ``AssertionError`` if more than one permission is found when searching for the permission with name ``perm_name``. :raises: ``requests.exceptions.HTTPError`` if an error occurs when updating ``self.user``'s roles. :returns: Nothing. """ role_id = entities.Role().create()['id'] permission_ids = [ permission['id'] for permission in entities.Permission(name=perm_name).search() ] self.assertEqual(len(permission_ids), 1) entities.Filter(permission=permission_ids, role=role_id).create() # NOTE: An extra hash is used due to an API bug. client.put( self.user.path(), {u'user': {u'role_ids': [role_id]}}, auth=get_server_credentials(), verify=False, ).raise_for_status()
def test_add_normal_cv_to_composite(self): """@Test: Create normal content view, publish and add it to a new composite content view @Assert: Content view can be created and assigned to composite one through content view versions mechanism @Feature: ContentView """ content_view = entities.ContentView(organization=self.org.id).create() content_view.set_repository_ids([self.yum_repo.id]) content_view.publish() cvv_id = content_view.read_json()['versions'][0]['id'] composite_cv = entities.ContentView( composite=True, organization=self.org.id, ).create() client.put( composite_cv.path(), {'content_view': {'component_ids': [cvv_id]}}, auth=get_server_credentials(), verify=False, ).raise_for_status() cv_attrs = composite_cv.read_json() self.assertEqual(cvv_id, cv_attrs['component_ids'][0]) self.assertEqual( content_view.id, cv_attrs['components'][0]['content_view_id'], )
def test_update_gpgkey(self): """@Test: Create a repository and update its GPGKey @Assert: The updated repository points to a new GPG key. @Feature: Repository """ # Create a repo and make it point to a GPG key. key_1_id = entities.GPGKey( content=read_data_file(VALID_GPG_KEY_FILE), organization=self.org_id, ).create_json()['id'] repo_id = entities.Repository( gpg_key=key_1_id, product=self.prod_id, ).create_json()['id'] # Update the repo and make it point to a new GPG key. key_2_id = entities.GPGKey( content=read_data_file(VALID_GPG_KEY_BETA_FILE), organization=self.org_id, ).create_json()['id'] client.put( entities.Repository(id=repo_id).path(), {u'gpg_key_id': key_2_id}, auth=get_server_credentials(), verify=False, ).raise_for_status() # Verify the repository's attributes. attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(attrs['gpg_key_id'], key_2_id)
def test_update(self, entity_cls): """@Test: Check whether the "edit_*" role has an effect. @Assert: A user cannot update an entity when missing the "edit_*" role, and they can update an entity when given the "edit_*" role. @Feature: Role NOTE: This method will only work if ``entity`` has a name. """ entity_id = entity_cls().create_json()['id'] entity = entity_cls(self.server_config, id=entity_id) with self.assertRaises(HTTPError): client.put( entity.path(), {u'name': entity_cls.name.gen_value()}, auth=self.server_config.auth, verify=self.server_config.verify, ).raise_for_status() self.give_user_permission(_permission_name(entity_cls, 'update')) client.put( entity.path(), {u'name': entity_cls.name.gen_value()}, auth=self.server_config.auth, verify=self.server_config.verify, ).raise_for_status()
def give_user_permission(self, perm_name): """Give ``self.user`` the ``perm_name`` permission. This method creates a role and filter to accomplish the above goal. When complete, the relevant relationhips look like this: user → role ← filter → permission :param str perm_name: The name of a permission. For example: 'create_architectures'. :raises: ``AssertionError`` if more than one permission is found when searching for the permission with name ``perm_name``. :raises: ``requests.exceptions.HTTPError`` if an error occurs when updating ``self.user``'s roles. :rtype: None """ role_id = entities.Role().create()['id'] permission_ids = [ permission['id'] for permission in entities.Permission(name=perm_name).search() ] self.assertEqual(len(permission_ids), 1) entities.Filter(permission=permission_ids, role=role_id).create() # NOTE: An extra hash is used due to an API bug. client.put( self.user.path(), {u'user': {u'role_ids': [role_id]}}, auth=get_server_credentials(), verify=False, ).raise_for_status()
def test_update_docker_repo_url(self, name): """@Test: Create a Docker-type repository and update its URL. @Assert: A repository is created with a Docker image and that its URL can be updated. @Feature: Docker """ new_url = gen_url(scheme='https') prod_id = entities.Product( organization=self.org_id).create_json()['id'] repo_id = _create_repository(prod_id, name)['id'] real_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(real_attrs['url'], DOCKER_REGISTRY_HUB) # Update the repository URL real_attrs['url'] = new_url client.put( entities.Repository(id=repo_id).path(), real_attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() new_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(new_attrs['url'], new_url) self.assertNotEqual(new_attrs['url'], DOCKER_REGISTRY_HUB)
def test_positive_update(self): """Create a repository and update its attributes. @Assert: The repository's attributes are updated. @Feature: Repository """ for attrs in _test_data(): with self.subTest(attrs): client.put( self.repository.path(), attrs, auth=settings.server.get_credentials(), verify=False, ).raise_for_status() real_attrs = self.repository.read_json() for name, value in attrs.items(): self.assertIn(name, real_attrs.keys()) if name == 'content_type': # Cannot update a repository's content type. con_type = self.repository.get_fields()['content_type'] self.assertEqual( con_type.default, real_attrs[name] ) else: self.assertEqual(value, real_attrs[name])
def test_update_name(self, content_type): """@Test: Update a repository's name. @Assert: The repository's name is updated. @Feature: Repository The only data provided with the PUT request is a name. No other information about the repository (such as its URL) is provided. """ if content_type == 'docker' and bz_bug_is_open(1194476): self.skipTest(1194476) repo_id = entities.Repository( content_type=content_type ).create_json()['id'] name = entities.Repository.name.gen_value() repository = entities.Repository(id=repo_id) client.put( repository.path(), {'name': name}, auth=get_server_credentials(), verify=False, ).raise_for_status() self.assertEqual(name, repository.read_json()['name'])
def test_update_gpgkey(self): """@Test: Create a repository and update its GPGKey @Assert: The updated repository points to a new GPG key. @Feature: Repository """ # Create a repo and make it point to a GPG key. key_1_id = entities.GPGKey( content=read_data_file(VALID_GPG_KEY_FILE), organization=self.org_id, ).create()['id'] repo_id = entities.Repository( gpg_key=key_1_id, product=self.prod_id, ).create()['id'] # Update the repo and make it point to a new GPG key. key_2_id = entities.GPGKey( content=read_data_file(VALID_GPG_KEY_BETA_FILE), organization=self.org_id, ).create()['id'] client.put( entities.Repository(id=repo_id).path(), { u'gpg_key_id': key_2_id }, auth=get_server_credentials(), verify=False, ).raise_for_status() # Verify the repository's attributes. attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(attrs['gpg_key_id'], key_2_id)
def test_update_name(self, content_type): """@Test: Update a repository's name. @Assert: The repository's name is updated. @Feature: Repository The only data provided with the PUT request is a name. No other information about the repository (such as its URL) is provided. """ if content_type == 'docker' and bz_bug_is_open(1194476): self.skipTest(1194476) repo_id = entities.Repository( content_type=content_type).create_json()['id'] name = entities.Repository.name.gen_value() repository = entities.Repository(id=repo_id) client.put( repository.path(), { 'name': name }, auth=get_server_credentials(), verify=False, ).raise_for_status() self.assertEqual(name, repository.read_json()['name'])
def test_update_docker_repo_upstream_name(self, name): """@Test: Create a Docker-type repository and update its upstream name. @Assert: A repository is created with a Docker image and that its upstream name can be updated. @Feature: Docker @BZ: 1193669 """ upstream_name = u'busybox' new_upstream_name = u'fedora/ssh' content_type = u'docker' prod_id = entities.Product( organization=self.org_id).create_json()['id'] repo_id = _create_repository(prod_id, name, upstream_name)['id'] real_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(real_attrs['name'], name) self.assertEqual(real_attrs['docker_upstream_name'], upstream_name) self.assertEqual(real_attrs['content_type'], content_type) # Update the repository upstream name real_attrs['docker_upstream_name'] = new_upstream_name client.put( entities.Repository(id=repo_id).path(), real_attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() new_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(new_attrs['docker_upstream_name'], new_upstream_name) self.assertNotEqual(new_attrs['name'], upstream_name)
def test_update_docker_repo_upstream_name(self, name): """@Test: Create a Docker-type repository and update its upstream name. @Assert: A repository is created with a Docker image and that its upstream name can be updated. @Feature: Docker @BZ: 1193669 """ upstream_name = u'busybox' new_upstream_name = u'fedora/ssh' content_type = u'docker' prod_id = entities.Product( organization=self.org_id ).create_json()['id'] repo_id = _create_repository(prod_id, name, upstream_name)['id'] real_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(real_attrs['name'], name) self.assertEqual(real_attrs['docker_upstream_name'], upstream_name) self.assertEqual(real_attrs['content_type'], content_type) # Update the repository upstream name real_attrs['docker_upstream_name'] = new_upstream_name client.put( entities.Repository(id=repo_id).path(), real_attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() new_attrs = entities.Repository(id=repo_id).read_json() self.assertEqual(new_attrs['docker_upstream_name'], new_upstream_name) self.assertNotEqual(new_attrs['name'], upstream_name)
def test_update_auto_attach(self): """@Test: Create an activation key, then update the auto_attach field with the inverse boolean value. @Feature: ActivationKey @Assert: 1. The update succeeds with an HTTP 200 return code. 2. The value was changed. """ attrs = entities.ActivationKey().create_json() activation_key = entities.ActivationKey(id=attrs['id']) client.put( activation_key.path(), {'auto_attach': not attrs['auto_attach']}, auth=get_server_credentials(), verify=False, ).raise_for_status() # Status code is OK. Was `auto_attach` changed? self.assertNotEqual( activation_key.read_json()['auto_attach'], attrs['auto_attach'], )
def test_delete_version_default(self): """@Test: Delete a content-view version associated to 'Library' @Assert: Deletion fails @Feature: ContentViewVersion """ key_content = read_data_file(ZOO_CUSTOM_GPG_KEY) org = entities.Organization().create() gpgkey_id = entities.GPGKey( content=key_content, organization=org.id ).create_json()['id'] # Creates new product without selecting GPGkey product_id = entities.Product( organization=org.id ).create_json()['id'] # Creates new repository with GPGKey repo = entities.Repository( url=FAKE_1_YUM_REPO, product=product_id, gpg_key=gpgkey_id, ).create() # sync repository repo.sync() # Create content view cv = entities.ContentView( organization=org.id ).create() # Associate repository to new content view client.put( cv.path(), {u'repository_ids': [repo.id]}, auth=get_server_credentials(), verify=False, ).raise_for_status() # Publish content view cv.publish() # Get published content-view version info cv_info = entities.ContentView(id=cv.id).read_json() self.assertEqual(len(cv_info['versions']), 1) # API returns version like '1.0' version_num = cv_info['versions'][0]['version'] # WebUI displays version like 'Version 1.0' version = 'Version {0}'.format(version_num) with Session(self.browser) as session: session.nav.go_to_select_org(org.name) session.nav.go_to_content_views() self.content_views.delete_version(cv.name, version) self.content_views.check_progress_bar_status(version) self.content_views.validate_version_deleted(cv.name, version)
def _add_repo_to_content_view(repo_id, cv_id): """Adds a repository to an existing content view. :param int repo_id: The ID for an existing repository. :param int cv_id: The ID for an existing content view. """ client.put(entities.ContentView(id=cv_id).path(), auth=get_server_credentials(), verify=False, data={ u'repository_ids': [repo_id] }).raise_for_status()
def _add_repo_to_content_view(repo_id, cv_id): """Adds a repository to an existing content view. :param int repo_id: The ID for an existing repository. :param int cv_id: The ID for an existing content view. """ client.put( entities.ContentView(id=cv_id).path(), auth=get_server_credentials(), verify=False, data={u'repository_ids': [repo_id]} ).raise_for_status()
def _add_content_view_to_composite_view(cv_id, cv_version_id): """Adds a published content view to a composite content view. :param int cv_id: The ID for an existing composite content view. :param int cv_version_id: The ID for a published non-composite content view. """ client.put(entities.ContentView(id=cv_id).path(), auth=get_server_credentials(), verify=False, data={ u'component_ids': [cv_version_id] }).raise_for_status()
def _add_content_view_to_composite_view(cv_id, cv_version_id): """Adds a published content view to a composite content view. :param int cv_id: The ID for an existing composite content view. :param int cv_version_id: The ID for a published non-composite content view. """ client.put( entities.ContentView(id=cv_id).path(), auth=get_server_credentials(), verify=False, data={u'component_ids': [cv_version_id]} ).raise_for_status()
def test_put_status_code(self, entity_cls): """@Test Issue a PUT request and check the returned status code. @Feature: Test multiple API paths @Assert: HTTP 200 is returned with an ``application/json`` content-type """ logger.debug('test_put_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) if entity_cls in BZ_1154156_ENTITIES and bz_bug_is_open(1154156): self.skipTest("Bugzilla bug 1154156 is open.") # Create an entity entity = entity_cls(id=entity_cls().create_json()['id']) # Update that entity. entity.create_missing() response = client.put( entity.path(), entity.create_payload(), # FIXME: use entity.update_payload() auth=get_server_credentials(), verify=False, ) self.assertEqual(httplib.OK, response.status_code) self.assertIn('application/json', response.headers['content-type'])
def test_positive_update_1(self, name_generator): """@Test: Update a role with and give a name of ``name_generator()``. @Feature: Role @Assert: The role is updated with the given name. """ if decorators.bz_bug_is_open(1112657) and ( name_generator is gen_cjk or name_generator is gen_latin1 or name_generator is gen_utf8): self.skipTest('Bugzilla bug 1112657 is open.') try: role_id = entities.Role().create_json()['id'] except HTTPError as err: self.fail(err) # fail instead of error role = entities.Role(id=role_id) name = name_generator() response = client.put( role.path(), {u'name': name}, auth=get_server_credentials(), verify=False, ) response.raise_for_status() self.assertEqual(role.read_json()['name'], name)
def test_positive_put_status_code(self, entity_cls): """Issue a PUT request and check the returned status code. :id: 1a2186b1-0709-4a73-8199-71114e10afce :parametrized: yes :expectedresults: HTTP 200 is returned with an ``application/json`` content-type :CaseImportance: Critical :BZ: 1378009 """ # Create an entity entity_id = entity_cls().create_json()['id'] # Update that entity. entity = entity_cls() entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), entity.update_payload(), auth=settings.server.get_credentials(), verify=False, ) assert http.client.OK == response.status_code assert 'application/json' in response.headers['content-type']
def test_positive_put_status_code(self): """Issue a PUT request and check the returned status code. :id: 1a2186b1-0709-4a73-8199-71114e10afce :expectedresults: HTTP 200 is returned with an ``application/json`` content-type :CaseImportance: Critical :BZ: 1378009 """ exclude_list = (entities.TemplateKind, ) # see comments in class definition for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): self.logger.info('test_put_status_code arg: %s', entity_cls) # Create an entity entity_id = entity_cls().create_json()['id'] # Update that entity. entity = entity_cls() entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), entity.update_payload(), auth=settings.server.get_credentials(), verify=False, ) self.assertEqual(http.client.OK, response.status_code) self.assertIn('application/json', response.headers['content-type'])
def test_positive_update_1(self, name_generator): """@Test: Update a role with and give a name of ``name_generator()``. @Feature: Role @Assert: The role is updated with the given name. """ if decorators.bz_bug_is_open(1112657) and ( name_generator is gen_cjk or name_generator is gen_latin1 or name_generator is gen_utf8): self.skipTest('Bugzilla bug 1112657 is open.') try: role_id = entities.Role().create()['id'] except HTTPError as err: self.fail(err) # fail instead of error role = entities.Role(id=role_id) name = name_generator() response = client.put( role.path(), {u'name': name}, auth=get_server_credentials(), verify=False, ) response.raise_for_status() self.assertEqual(role.read_json()['name'], name)
def test_positive_put_status_code(self): """Issue a PUT request and check the returned status code. @id: 1a2186b1-0709-4a73-8199-71114e10afce @Assert: HTTP 200 is returned with an ``application/json`` content-type """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) if bz_bug_is_open(1378009): exclude_list += (entities.HostGroup,) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): self.logger.info('test_put_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) # Create an entity entity_id = entity_cls().create_json()['id'] # Update that entity. entity = entity_cls() entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), # FIXME: use entity.update_payload() entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) self.assertEqual(http_client.OK, response.status_code) self.assertIn( 'application/json', response.headers['content-type'] )
def test_put_and_get(self, entity_cls): """@Test: Update an entity, then read it back. @Feature: Test multiple API paths @Assert: The entity is updated with the given attributes. """ logger.debug('test_put_and_get arg: %s', entity_cls) skip_if_sam(self, entity_cls) if entity_cls in BZ_1154156_ENTITIES and bz_bug_is_open(1154156): self.skipTest("Bugzilla bug 1154156 is open.") # Create an entity. entity_id = entity_cls().create_json()['id'] # Update that entity. FIXME: This whole procedure is a hack. entity = entity_cls() entity.create_missing() # Generate randomized instance attributes response = client.put( entity_cls(id=entity_id).path(), entity.create_payload(), auth=get_server_credentials(), verify=False, ) response.raise_for_status() # Compare `payload` against entity information returned by the server. payload = _get_readable_attributes(entity) entity_attrs = entity_cls(id=entity_id).read_json() for key, value in payload.items(): self.assertIn(key, entity_attrs.keys()) self.assertEqual(value, entity_attrs[key], key)
def test_put_status_code(self, entity_cls): """@Test Issue a PUT request and check the returned status code. @Feature: Test multiple API paths @Assert: HTTP 200 is returned with an ``application/json`` content-type """ logger.debug('test_put_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) if entity_cls in BZ_1154156_ENTITIES and bz_bug_is_open(1154156): self.skipTest("Bugzilla bug 1154156 is open.") # Create an entity entity_id = entity_cls().create_json()['id'] # Update that entity. entity = entity_cls() entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), entity.create_payload(), # FIXME: use entity.update_payload() auth=get_server_credentials(), verify=False, ) self.assertEqual(httplib.OK, response.status_code) self.assertIn('application/json', response.headers['content-type'])
def test_put_and_get(self): """@Test: Issue a PUT request and GET the updated system. @Feature: System APIs @Assert: The updated system has the correct attributes. """ system = System(uuid=System().create_json()['uuid']) logger.debug('system uuid: {0}'.format(system.uuid)) # Generate some attributes and use them to update `system`. system.create_missing() response = client.put( system.path(), system.create_payload(), auth=get_server_credentials(), verify=False, ) self.assertEqual(response.status_code, httplib.OK) # Get the just-updated system and examine its attributes. attrs = system.read_json() for key, value in system.create_payload().items(): self.assertIn(key, attrs.keys()) self.assertEqual(value, attrs[key])
def test_positive_put_status_code(self): """Issue a PUT request and check the returned status code. @id: 1a2186b1-0709-4a73-8199-71114e10afce @Assert: HTTP 200 is returned with an ``application/json`` content-type """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) if bz_bug_is_open(1378009): exclude_list += (entities.HostGroup,) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_put_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) # Create an entity entity_id = entity_cls().create_json()['id'] # Update that entity. entity = entity_cls() entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), # FIXME: use entity.update_payload() entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) self.assertEqual(http_client.OK, response.status_code) self.assertIn( 'application/json', response.headers['content-type'] )
def test_update_max_content_hosts(self): """@Test: Create an activation key with ``max_content_hosts == 1``, then update that field with a string value. @Feature: ActivationKey @Assert: The update fails with an HTTP 422 return code. """ attrs = entities.ActivationKey(max_content_hosts=1).create() path = entities.ActivationKey(id=attrs['id']).path() new_attrs = attrs.copy() new_attrs['max_content_hosts'] = 'foo' response = client.put( path, new_attrs, auth=get_server_credentials(), verify=False, ) self.assertEqual( response.status_code, httplib.UNPROCESSABLE_ENTITY, status_code_error(path, httplib.UNPROCESSABLE_ENTITY, response), ) # Status code is OK. Was `max_content_hosts` changed, or is it still 1? response = entities.ActivationKey(id=attrs['id']).read_json() self.assertEqual(response['max_content_hosts'], 1)
def test_associate_subnet_with_organization(self): """@Test: Update an organization, associate subnet with it. @Assert: Subnet is associated with organization. @Feature: Organization """ subnet_id = entities.Subnet().create_json()['id'] client.put( self.organization.path(), {'organization': {'subnet_ids': [subnet_id]}}, verify=False, auth=get_server_credentials(), ).raise_for_status() new_attrs = self.organization.read_json() self.assertEqual(1, len(new_attrs['subnets'])) self.assertEqual(subnet_id, new_attrs['subnets'][0]['id'])
def test_positive_update_1(self, attrs): """@Test: Update a product with a new name or description. @Assert: The given attributes are used. @Feature: Product """ client.put( self.product_n.path(), attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() new_attrs = self.product_n.read_json() for name, value in attrs.items(): self.assertIn(name, new_attrs.keys()) self.assertEqual(value, new_attrs[name])
def test_positive_update(self, attrs): """@Test: Update an organization's attributes with valid values. @Assert: The organization's attributes are updated. @Feature: Organization """ client.put( self.organization.path(), attrs, verify=False, auth=get_server_credentials(), ).raise_for_status() # Read the organization and validate its attributes. new_attrs = self.organization.read_json() for name, value in attrs.items(): self.assertIn(name, new_attrs.keys()) self.assertEqual(new_attrs[name], value)
def test_positive_update(self, attrs): """@Test: Update a content view and provide valid attributes. @Assert: The update succeeds. @Feature: ContentView """ client.put( self.content_view.path(), attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() # Read the content view and validate its attributes. new_attrs = self.content_view.read_json() for name, value in attrs.items(): self.assertIn(name, new_attrs.keys()) self.assertEqual(new_attrs[name], value)
def update_raw(self, fields=None): """Update the current entity. Make an HTTP PUT call to ``self.path('base')``. The request payload consists of whatever is returned by :meth:`update_payload`. Return the response. :param fields: See :meth:`update`. :return: A ``requests.response`` object. """ return client.put(self.path('self'), self.update_payload(fields), **self._server_config.get_client_kwargs())
def test_update(self, attrs): """@Test: Create a repository and update its attributes. @Assert: The repository's attributes are updated. @Feature: Repository """ client.put( self.repository.path(), attrs, auth=get_server_credentials(), verify=False, ).raise_for_status() real_attrs = self.repository.read_json() for name, value in attrs.items(): self.assertIn(name, real_attrs.keys()) if name == 'content_type': # Cannot update a repository's content type. self.assertEqual(entities.Repository.content_type.default, real_attrs[name]) else: self.assertEqual(value, real_attrs[name])
def test_negative_update(self, attrs): """@Test: Update an organization's attributes with invalid values. @Assert: The organization's attributes are not updated. @Feature: Organization """ response = client.put( self.organization.path(), attrs, verify=False, auth=get_server_credentials(), ) with self.assertRaises(HTTPError): response.raise_for_status()
def update_raw(self, fields=None): """Update the current entity. Make an HTTP PUT call to ``self.path('base')``. The request payload consists of whatever is returned by :meth:`update_payload`. Return the response. :param fields: See :meth:`update`. :return: A ``requests.response`` object. """ return client.put( self.path('self'), self.update_payload(fields), **self._server_config.get_client_kwargs() )
def test_update_admin(self, admin): """@Test: Update a user and provide the ``admin`` attribute. @Assert: The user's ``admin`` attribute is updated. @Feature: User """ user_id = entities.User(admin=admin).create_json()['id'] user = entities.User(id=user_id) response = client.put( user.path(), {'admin': not admin}, auth=get_server_credentials(), verify=False, ) response.raise_for_status() self.assertEqual(user.read().admin, not admin)
def test_put_status_code(self): """@Test: Issue a PUT request and check the returned status code. @Feature: System APIs @Assert: HTTP 200 is returned with an ``application/json`` content-type """ system = System(uuid=System().create_json()['uuid']) logger.debug('system uuid: {0}'.format(system.uuid)) system.create_missing() response = client.put( system.path(), system.create_payload(), auth=get_server_credentials(), verify=False, ) self.assertEqual(httplib.OK, response.status_code) self.assertIn('application/json', response.headers['content-type'])
def test_negative_update_1(self, max_content_hosts): """@Test: Create activation key then update its limit to invalid value. @Assert: 1. Activation key is created 2. Update fails 3. Record is not changed @Feature: ActivationKey """ try: attrs = entities.ActivationKey().create() except HTTPError as err: self.fail(err) activationkey = entities.ActivationKey(id=attrs['id']) # Update the activation key with semantically incorrect values. response = client.put( activationkey.path(), { u'unlimited_content_hosts': False, u'max_content_hosts': max_content_hosts }, auth=get_server_credentials(), verify=False, ) self.assertEqual( response.status_code, httplib.UNPROCESSABLE_ENTITY, status_code_error( activationkey.path(), httplib.UNPROCESSABLE_ENTITY, response ), ) # Make sure no attributes have changed. new_attrs = activationkey.read_json() for attr in ('unlimited_content_hosts', 'max_content_hosts'): self.assertEqual(attrs[attr], new_attrs[attr]) self.assertTrue(new_attrs['unlimited_content_hosts'])
def test_negative_update_1(self, attrs): """@Test: Update a content view and provide an invalid attribute. @Assert: The content view's attributes are not updated. @Feature: ContentView """ bug_id = attrs.pop('bz-bug', None) if bug_id is not None and bz_bug_is_open(bug_id): self.skipTest('Bugzilla bug {0} is open.'.format(bug_id)) response = client.put( self.content_view.path(), attrs, auth=get_server_credentials(), verify=False, ) with self.assertRaises(HTTPError): response.raise_for_status()
def test_positive_put_and_get_requests(self): """Update an entity, then read it back. :id: f5d3039f-5468-4dd2-8ac9-6e948ef39866 :expectedresults: The entity is updated with the given attributes. :CaseImportance: Critical """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) if bz_bug_is_open(1378009): exclude_list += (entities.HostGroup, ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): self.logger.info('test_put_and_get arg: %s', entity_cls) skip_if_sam(self, entity_cls) # Create an entity. entity_id = entity_cls().create_json()['id'] # Update that entity. FIXME: This whole procedure is a hack. entity = entity_cls() # Generate randomized instance attributes entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) response.raise_for_status() # Compare `payload` against entity information returned by the # server. payload = _get_readable_attributes(entity) entity_attrs = entity_cls(id=entity_id).read_json() for key, value in payload.items(): self.assertIn(key, entity_attrs.keys()) self.assertEqual(value, entity_attrs[key], key)
def test_update_owner_type(self, owner_type): """@Test: Update a host and specify an ``owner_type``. @Feature: Host @Assert: The host can be read back, and the ``owner_type`` attribute is correct. """ host_id = entities.Host().create_json()['id'] response = client.put( entities.Host(id=host_id).path(), {'host': {'owner_type': owner_type}}, auth=get_server_credentials(), verify=False, ) response.raise_for_status() self.assertEqual( entities.Host(id=host_id).read_json()['owner_type'], owner_type, )
def test_positive_put_and_get_requests(self): """Update an entity, then read it back. @Feature: Test multiple API paths @Assert: The entity is updated with the given attributes. """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_put_and_get arg: %s', entity_cls) skip_if_sam(self, entity_cls) if (entity_cls in BZ_1154156_ENTITIES and bz_bug_is_open(1154156)): self.skipTest("Bugzilla bug 1154156 is open.") # Create an entity. entity_id = entity_cls().create_json()['id'] # Update that entity. FIXME: This whole procedure is a hack. entity = entity_cls() # Generate randomized instance attributes entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) response.raise_for_status() # Compare `payload` against entity information returned by the # server. payload = _get_readable_attributes(entity) entity_attrs = entity_cls(id=entity_id).read_json() for key, value in payload.items(): self.assertIn(key, entity_attrs.keys()) self.assertEqual(value, entity_attrs[key], key)
def test_positive_put_and_get_requests(self, entity_cls): """Update an entity, then read it back. :id: f5d3039f-5468-4dd2-8ac9-6e948ef39866 :parametrized: yes :expectedresults: The entity is updated with the given attributes. :CaseImportance: Medium :BZ: 1378009 """ # Create an entity. entity = entity_cls().create_json() # Update that entity. FIXME: This whole procedure is a hack. kwargs = { 'organization': entity['organization_id'] } if 'organization_id' in entity else {} new_entity = entity_cls(**kwargs) # Generate randomized instance attributes new_entity.create_missing() response = client.put( entity_cls(id=entity['id']).path(), new_entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) response.raise_for_status() # Compare `payload` against entity information returned by the # server. payload = _get_readable_attributes(new_entity) entity_attrs = entity_cls(id=entity['id']).read_json() for key, value in payload.items(): assert key in entity_attrs.keys() assert value == entity_attrs[key]
def test_positive_put_status_code(self): """Issue a PUT request and check the returned status code. @Feature: Test multiple API paths @Assert: HTTP 200 is returned with an ``application/json`` content-type """ exclude_list = ( entities.TemplateKind, # see comments in class definition ) for entity_cls in set(valid_entities()) - set(exclude_list): with self.subTest(entity_cls): logger.debug('test_put_status_code arg: %s', entity_cls) skip_if_sam(self, entity_cls) if (entity_cls in BZ_1154156_ENTITIES and bz_bug_is_open(1154156)): self.skipTest("Bugzilla bug 1154156 is open.") # Create an entity entity_id = entity_cls().create_json()['id'] # Update that entity. entity = entity_cls() entity.create_missing() response = client.put( entity_cls(id=entity_id).path(), # FIXME: use entity.update_payload() entity.create_payload(), auth=settings.server.get_credentials(), verify=False, ) self.assertEqual(http_client.OK, response.status_code) self.assertIn( 'application/json', response.headers['content-type'] )
def test_smoke(self): """@Test: Check that basic content can be created 1. Create a new user with admin permissions 2. Using the new user from above: 1. Create a new organization 2. Create two new lifecycle environments 3. Create a custom product 4. Create a custom YUM repository 5. Create a custom PUPPET repository 6. Synchronize both custom repositories 7. Create a new content view 8. Associate both repositories to new content view 9. Publish content view 10. Promote content view to both lifecycles 11. Create a new libvirt compute resource 12. Create a new subnet 13. Create a new domain 14. Create a new hostgroup and associate previous entities to it @Feature: Smoke Test @Assert: All entities are created and associated. """ # prep work # # FIXME: Use a larger charset when authenticating users. # # It is possible to create a user with a wide range of characters. (see # the "User" entity). However, Foreman supports only HTTP Basic # authentication, and the requests lib enforces the latin1 charset in # this auth mode. We then further restrict ourselves to the # alphanumeric charset, because Foreman complains about incomplete # multi-byte chars when latin1 chars are used. # login = gen_string('alphanumeric') password = gen_string('alphanumeric') # step 1: Create a new user with admin permissions entities.User(admin=True, login=login, password=password).create() # step 2.1: Create a new organization org = entities.Organization().create(auth=(login, password)) # step 2.2: Create 2 new lifecycle environments le1 = entities.LifecycleEnvironment(organization=org['id']).create() le2 = entities.LifecycleEnvironment( organization=org['id'], prior=le1['id']).create() # step 2.3: Create a custom product prod = entities.Product(organization=org['id']).create() # step 2.4: Create custom YUM repository repo1 = entities.Repository( product=prod['id'], content_type=u'yum', url=GOOGLE_CHROME_REPO ).create() # step 2.5: Create custom PUPPET repository repo2 = entities.Repository( product=prod['id'], content_type=u'puppet', url=FAKE_0_PUPPET_REPO ).create() # step 2.6: Synchronize both repositories for repo in [repo1, repo2]: response = client.post( entities.Repository(id=repo['id']).path('sync'), { u'ids': [repo['id']], u'organization_id': org['id'] }, auth=get_server_credentials(), verify=False, ).json() self.assertGreater( len(response['id']), 1, u"Was not able to fetch a task ID.") task_status = entities.ForemanTask(id=response['id']).poll() self.assertEqual( task_status['result'], u'success', u"Sync for repository {0} failed.".format(repo['name'])) # step 2.7: Create content view content_view = entities.ContentView(organization=org['id']).create() # step 2.8: Associate YUM repository to new content view response = client.put( entities.ContentView(id=content_view['id']).path(), auth=get_server_credentials(), verify=False, data={u'repository_ids': [repo1['id']]}) # Fetch all available puppet modules puppet_mods = client.get( entities.ContentView(id=content_view['id']).path( 'available_puppet_module_names'), auth=get_server_credentials(), verify=False).json() self.assertGreater( puppet_mods['results'], 0, u"No puppet modules were found") # Select a random puppet module from the results puppet_mod = random.choice(puppet_mods['results']) # ... and associate it to the content view path = entities.ContentView(id=content_view['id']).path( 'content_view_puppet_modules') response = client.post( path, auth=get_server_credentials(), verify=False, data={u'name': puppet_mod['module_name']}) self.assertEqual( response.status_code, httplib.OK, status_code_error(path, httplib.OK, response) ) self.assertEqual( response.json()['name'], puppet_mod['module_name'], ) # step 2.9: Publish content view task_status = entities.ContentView(id=content_view['id']).publish() self.assertEqual( task_status['result'], u'success', u"Publishing {0} failed.".format(content_view['name'])) # step 2.10: Promote content view to both lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 1, u"Content view should be present on 1 lifecycle only") task_status = entities.ContentViewVersion( id=content_view['versions'][0]['id'] ).promote(le1['id']) self.assertEqual( task_status['result'], u'success', u"Promoting {0} to {1} failed.".format( content_view['name'], le1['name'])) # Check that content view exists in 2 lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 2, u"Content view should be present on 2 lifecycles only") task_status = entities.ContentViewVersion( id=content_view['versions'][0]['id'] ).promote(le2['id']) self.assertEqual( task_status['result'], u'success', u"Promoting {0} to {1} failed.".format( content_view['name'], le2['name'])) # Check that content view exists in 2 lifecycles content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual( len(content_view['versions']), 1, u'There should only be 1 version published.') self.assertEqual( len(content_view['versions'][0]['environment_ids']), 3, u"Content view should be present on 3 lifecycle only") # BONUS: Create a content host and associate it with promoted # content view and last lifecycle where it exists content_host = entities.System( content_view=content_view['id'], environment=le2['id'] ).create() # Check that content view matches what we passed self.assertEqual( content_host['content_view_id'], content_view['id'], u"Content views do not match." ) # Check that lifecycle environment matches self.assertEqual( content_host['environment']['id'], le2['id'], u"Environments do not match." )
def test_end_to_end(self): """@Test: Perform end to end smoke tests using RH repos. 1. Create new organization and environment 2. Clone and upload manifest 3. Sync a RedHat repository 4. Create content-view 5. Add repository to contet-view 6. Promote/publish content-view 7. Create an activation-key 8. Add product to activation-key 9. Create new virtualmachine 10. Pull rpm from Foreman server and install on client 11. Register client with foreman server using activation-key 12. Install rpm on client @Feature: Smoke test @Assert: All tests should succeed and Content should be successfully fetched by client """ product = "Red Hat Enterprise Linux Server" reposet = ("Red Hat Enterprise Virtualization Agents " "for RHEL 6 Server (RPMs)") repo = ("Red Hat Enterprise Virtualization Agents for RHEL 6 Server " "RPMs x86_64 6Server") activation_key_name = gen_string('alpha') # step 1.1: Create a new organization org = entities.Organization().create() # step 1.2: Create new lifecycle environments lifecycle_env = entities.LifecycleEnvironment( organization=org['id'] ).create() # step 2: Upload manifest manifest_path = manifests.clone() task = entities.Organization( id=org['id'] ).upload_manifest(path=manifest_path) self.assertEqual( u'success', task['result'], task['humanized']['errors'] ) # step 3.1: Enable RH repo and fetch repository_id repo_id = utils.enable_rhrepo_and_fetchid( basearch="x86_64", org_id=org['id'], product=product, repo=repo, reposet=reposet, releasever="6Server", ) # step 3.2: sync repository task_result = entities.Repository(id=repo_id).sync()['result'] self.assertEqual( task_result, u'success', u" Error while syncing repository '{0}' and state is {1}." .format(repo, task_result)) # step 4: Create content view content_view = entities.ContentView(organization=org['id']).create() # step 5: Associate repository to new content view response = client.put( entities.ContentView(id=content_view['id']).path(), {u'repository_ids': [repo_id]}, auth=get_server_credentials(), verify=False, ) response.raise_for_status() # step 6.1: Publish content view task_status = entities.ContentView(id=content_view['id']).publish() self.assertEqual( task_status['result'], u'success', u"Error publishing content-view {0} and state is {1}." .format(content_view['name'], task_status['result'])) # step 6.2: Promote content view to lifecycle_env content_view = entities.ContentView(id=content_view['id']).read_json() self.assertEqual(len(content_view['versions']), 1) task_status = entities.ContentViewVersion( id=content_view['versions'][0]['id'] ).promote(lifecycle_env['id']) self.assertEqual( task_status['result'], u'success', u"Error promoting {0} to {1} and state is {2}." .format(content_view['name'], lifecycle_env['name'], task_status['result'])) # step 7: Create activation key ak_id = entities.ActivationKey( name=activation_key_name, environment=lifecycle_env['id'], organization=org['id'], content_view=content_view['id'], ).create_json()['id'] # Walk through the list of subscriptions. Find the "Red Hat Employee # Subscription" and attach it to the just-created activation key. for subscription in entities.Organization(id=org['id']).subscriptions(): if subscription['product_name'] == "Red Hat Employee Subscription": # 'quantity' must be 1, not subscription['quantity']. Greater # values produce this error: "RuntimeError: Error: Only pools # with multi-entitlement product subscriptions can be added to # the activation key with a quantity greater than one." entities.ActivationKey(id=ak_id).add_subscriptions({ 'quantity': 1, 'subscription_id': subscription['id'], }) break # Create VM package_name = "python-kitchen" with VirtualMachine(distro='rhel66') as vm: # Download and Install rpm result = vm.run( "wget -nd -r -l1 --no-parent -A '*.noarch.rpm' http://{0}/pub/" .format(conf.properties['main.server.hostname']) ) self.assertEqual( result.return_code, 0, "failed to fetch katello-ca rpm: {0}, return code: {1}" .format(result.stderr, result.return_code) ) result = vm.run( 'rpm -i katello-ca-consumer*.noarch.rpm' ) self.assertEqual( result.return_code, 0, "failed to install katello-ca rpm: {0} and return code: {1}" .format(result.stderr, result.return_code) ) # Register client with foreman server using activation-key result = vm.run( u'subscription-manager register --activationkey {0} ' '--org {1} --force' .format(activation_key_name, org['label']) ) self.assertEqual( result.return_code, 0, "failed to register client:: {0} and return code: {1}" .format(result.stderr, result.return_code) ) # Enable Red Hat Enterprise Virtualization Agents repo via cli # As the below repo is disabled by default under ak's prd-content result = vm.run( 'subscription-manager repos --enable ' 'rhel-6-server-rhev-agent-rpms' ) self.assertEqual( result.return_code, 0, "Enabling repo failed: {0} and return code: {1}" .format(result.stderr, result.return_code) ) # Install contents from sat6 server result = vm.run('yum install -y {0}'.format(package_name)) self.assertEqual( result.return_code, 0, "Package install failed: {0} and return code: {1}" .format(result.stderr, result.return_code) ) # Verify if package is installed by query it result = vm.run('rpm -q {0}'.format(package_name)) self.assertIn(package_name, result.stdout[0])