From 6a5a02c3ad39e84b66f67ef152d18a9e77c0ff39 Mon Sep 17 00:00:00 2001 From: Jitendra Yejare Date: Tue, 21 Nov 2017 16:27:40 +0530 Subject: [PATCH] Entity classes updated to automate 6.3 Canned Role feature (#458) --- nailgun/entities.py | 72 ++++++++++++++++++++++++++++++++++++++++-- tests/test_entities.py | 14 ++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/nailgun/entities.py b/nailgun/entities.py index 82ba22c6..1fb653eb 100644 --- a/nailgun/entities.py +++ b/nailgun/entities.py @@ -2449,7 +2449,12 @@ def read(self, entity=None, attrs=None, ignore=None, params=None): class Filter( - Entity, EntityCreateMixin, EntityDeleteMixin, EntityReadMixin): + Entity, + EntityCreateMixin, + EntityDeleteMixin, + EntityReadMixin, + EntitySearchMixin, + EntityUpdateMixin): """A representation of a Filter entity.""" def __init__(self, server_config=None, **kwargs): @@ -2459,6 +2464,8 @@ def __init__(self, server_config=None, **kwargs): 'permission': entity_fields.OneToManyField(Permission), 'role': entity_fields.OneToOneField(Role, required=True), 'search': entity_fields.StringField(), + 'override': entity_fields.BooleanField(), + 'unlimited': entity_fields.BooleanField(), } self._meta = {'api_path': 'api/v2/filters', 'server_modes': ('sat')} super(Filter, self).__init__(server_config, **kwargs) @@ -2472,6 +2479,19 @@ def create_payload(self): """ return {u'filter': super(Filter, self).create_payload()} + def read(self, entity=None, attrs=None, ignore=None, params=None): + """Deal with different named data returned from the server + """ + if attrs is None: + attrs = self.read_json() + attrs['override'] = attrs.pop('override?') + attrs['unlimited'] = attrs.pop('unlimited?') + return super(Filter, self).read(entity, attrs, ignore, params) + + def update_payload(self, fields=None): + """Wrap submitted data within an extra dict.""" + return {u'filter': super(Filter, self).update_payload(fields)} + class ForemanTask(Entity, EntityReadMixin, EntitySearchMixin): """A representation of a Foreman task.""" @@ -5563,7 +5583,9 @@ def __init__(self, server_config=None, **kwargs): str_type='alphanumeric', length=(2, 30), # min length is 2 and max length is arbitrary unique=True - ) + ), + 'location': entity_fields.OneToManyField(Location), + 'organization': entity_fields.OneToManyField(Organization), } self._meta = { 'api_path': 'api/v2/roles', @@ -5571,6 +5593,52 @@ def __init__(self, server_config=None, **kwargs): } super(Role, self).__init__(server_config, **kwargs) + def create_payload(self): + """Wrap submitted data within an extra dict. + + For more information, see `Bugzilla #1151220 + `_. + + """ + return {u'role': super(Role, self).create_payload()} + + def update_payload(self, fields=None): + """Wrap submitted data within an extra dict.""" + return {u'role': super(Role, self).update_payload(fields)} + + def path(self, which=None): + """Extend ``nailgun.entity_mixins.Entity.path``. + The format of the returned path depends on the value of ``which``: + + clone + /api/roles/:role_id/clone + + Otherwise, call ``super``. + + """ + if which == 'clone': + return '{0}/{1}'.format( + super(Role, self).path(which='self'), + which + ) + return super(Role, self).path(which) + + def clone(self, synchronous=True, **kwargs): + """Helper to clone an existing Role + + :param synchronous: What should happen if the server returns an HTTP + 202 (accepted) status code? Wait for the task to complete if + ``True``. Immediately return the server's response otherwise. + :param kwargs: Arguments to pass to requests. + :returns: The server's response, with all JSON decoded. + :raises: ``requests.exceptions.HTTPError`` If the server responds with + an HTTP 4XX or 5XX message. + """ + kwargs = kwargs.copy() + kwargs.update(self._server_config.get_client_kwargs()) + response = client.post(self.path('clone'), **kwargs) + return _handle_response(response, self._server_config, synchronous) + class Setting(Entity, EntityReadMixin, EntitySearchMixin, EntityUpdateMixin): """A representation of a Setting entity.""" diff --git a/tests/test_entities.py b/tests/test_entities.py index c5105ebc..de12dac8 100644 --- a/tests/test_entities.py +++ b/tests/test_entities.py @@ -258,6 +258,7 @@ def test_nowhich(self): (entities.Capsule, '/capsules'), (entities.ConfigTemplate, '/config_templates'), (entities.ProvisioningTemplate, '/provisioning_templates'), + (entities.Role, '/roles'), (entities.ContentView, '/content_views'), (entities.ContentViewVersion, '/content_view_versions'), (entities.DiscoveredHost, '/discovered_hosts'), @@ -305,6 +306,7 @@ def test_id_and_which(self): (entities.ActivationKey, 'subscriptions'), (entities.ConfigTemplate, 'clone'), (entities.ProvisioningTemplate, 'clone'), + (entities.Role, 'clone'), (entities.ContentView, 'available_puppet_module_names'), (entities.ContentView, 'content_view_puppet_modules'), (entities.ContentView, 'content_view_versions'), @@ -623,6 +625,7 @@ def test_no_attributes(self): entities.Media, entities.OperatingSystem, entities.Registry, + entities.Role, entities.SmartVariable, entities.Subnet, entities.User, @@ -1051,6 +1054,7 @@ def test_attrs_arg_v1(self): # entities.Product, # See Product.test_read # entities.UserGroup, # see test_attrs_arg_v2 entities.Domain, + entities.Filter, entities.Host, entities.Media, entities.RHCIDeployment, @@ -1130,6 +1134,13 @@ def test_entity_ids(self): 'installed_products': None, }, ), + ( + entities.Filter(self.cfg), + {'override?': None, + 'unlimited?': None}, + {'override': None, + 'unlimited': None}, + ) ) for entity, attrs_before, attrs_after in test_data: with self.subTest(entity): @@ -1472,6 +1483,7 @@ def test_generic(self): entities_payloads = [ (entities.AbstractComputeResource, {'compute_resource': {}}), (entities.ConfigTemplate, {'config_template': {}}), + (entities.Filter, {'filter': {}}), (entities.ProvisioningTemplate, {'provisioning_template': {}}), (entities.DiscoveredHost, {'discovered_host': {}}), (entities.DiscoveryRule, {'discovery_rule': {}}), @@ -1483,6 +1495,7 @@ def test_generic(self): (entities.Media, {'medium': {}}), (entities.OperatingSystem, {'operatingsystem': {}}), (entities.Organization, {'organization': {}}), + (entities.Role, {'role': {}}), (entities.Setting, {'setting': {}}), (entities.SmartProxy, {'smart_proxy': {}}), (entities.SmartVariable, {'smart_variable': {}}), @@ -1651,6 +1664,7 @@ def setUpClass(cls): (entities.Capsule(**generic).content_sync, 'post'), (entities.ConfigTemplate(**generic).build_pxe_default, 'post'), (entities.ConfigTemplate(**generic).clone, 'post'), + (entities.Role(**generic).clone, 'post'), ( entities.ProvisioningTemplate(**generic).build_pxe_default, 'post'