mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 19:10:07 -03:30
Remove the natural key lookup dict and make each Page responsible instead
This commit is contained in:
parent
07ba521b8b
commit
e92c8cfdcc
@ -35,50 +35,6 @@ EXPORTABLE_DEPENDENT_OBJECTS = [
|
||||
]
|
||||
|
||||
|
||||
NATURAL_KEYS = {
|
||||
'user': ('username',),
|
||||
'organization': ('name',),
|
||||
'team': ('organization', 'name'),
|
||||
'credential_type': ('name', 'kind'),
|
||||
'credential': ('organization', 'name', 'credential_type'),
|
||||
'notification_template': ('organization', 'name'),
|
||||
'project': ('organization', 'name'),
|
||||
'inventory': ('organization', 'name'),
|
||||
'job_template': ('organization', 'name'),
|
||||
'workflow_job_template': ('organization', 'name'),
|
||||
|
||||
# related resources
|
||||
'role': ('name', ':content_object'),
|
||||
'notification_template': ('organization', 'name'),
|
||||
'label': ('organization', 'name'), # FIXME: label will need to be fully constructed from this
|
||||
'workflow_job_template_node': ('workflow_job_template', 'identifier'),
|
||||
'schedule': ('unified_job_template', 'name'),
|
||||
}
|
||||
|
||||
|
||||
def get_natural_key(pg):
|
||||
natural_key = {'type': pg['type']}
|
||||
lookup = NATURAL_KEYS.get(pg['type'], ())
|
||||
|
||||
for key in lookup or ():
|
||||
if key.startswith(':'):
|
||||
# treat it like a special-case related object
|
||||
related_objs = [
|
||||
related for name, related in pg.related.items()
|
||||
if name not in ('users', 'teams')
|
||||
]
|
||||
if related_objs:
|
||||
natural_key[key[1:]] = get_natural_key(related_objs[0].get())
|
||||
elif key in pg.related:
|
||||
natural_key[key] = get_natural_key(pg.related[key].get())
|
||||
elif key in pg:
|
||||
natural_key[key] = pg[key]
|
||||
|
||||
if not natural_key:
|
||||
return None
|
||||
return natural_key
|
||||
|
||||
|
||||
def freeze(key):
|
||||
if key is None:
|
||||
return None
|
||||
@ -113,10 +69,11 @@ class ApiV2(base.Base):
|
||||
key: asset.json[key] for key in options
|
||||
if key in asset.json and key not in asset.related and key != 'id'
|
||||
}
|
||||
fields['natural_key'] = get_natural_key(asset)
|
||||
fields['natural_key'] = asset.get_natural_key()
|
||||
|
||||
fk_fields = {
|
||||
key: get_natural_key(asset.related[key].get()) for key in options
|
||||
# FIXME: use caching by url
|
||||
key: asset.related[key].get().get_natural_key() for key in options
|
||||
if key in asset.related
|
||||
}
|
||||
|
||||
@ -124,7 +81,7 @@ class ApiV2(base.Base):
|
||||
for key, related_endpoint in asset.related.items():
|
||||
if key in asset.json or not related_endpoint:
|
||||
continue
|
||||
if key == 'object_roles':
|
||||
if key == 'object_roles': # FIXME
|
||||
continue
|
||||
rel = related_endpoint._create()
|
||||
|
||||
@ -139,7 +96,7 @@ class ApiV2(base.Base):
|
||||
if 'results' in data:
|
||||
related_options = self._get_options(related_endpoint)
|
||||
related[key] = [
|
||||
get_natural_key(x) if by_natural_key else self._serialize_asset(x, related_options)
|
||||
x.get_natural_key() if by_natural_key else self._serialize_asset(x, related_options)
|
||||
for x in data.results
|
||||
]
|
||||
else:
|
||||
@ -190,7 +147,7 @@ class ApiV2(base.Base):
|
||||
yield page_resource[page_cls]
|
||||
|
||||
def _register_page(self, page):
|
||||
natural_key = freeze(get_natural_key(page))
|
||||
natural_key = freeze(page.get_natural_key())
|
||||
# FIXME: we need to keep a reference for the case where we
|
||||
# don't have a natural key, so we can delete
|
||||
if natural_key is not None:
|
||||
|
||||
@ -149,6 +149,8 @@ def get_payload_field_and_value_from_kwargs_or_config_cred(
|
||||
|
||||
class CredentialType(HasCreate, base.Base):
|
||||
|
||||
NATURAL_KEY = ('name', 'kind')
|
||||
|
||||
def silent_delete(self):
|
||||
if not self.managed_by_tower:
|
||||
return super(CredentialType, self).silent_delete()
|
||||
@ -204,6 +206,7 @@ class Credential(HasCopy, HasCreate, base.Base):
|
||||
|
||||
dependencies = [CredentialType]
|
||||
optional_dependencies = [Organization, User, Team]
|
||||
NATURAL_KEY = ('organization', 'name', 'credential_type')
|
||||
|
||||
def payload(
|
||||
self,
|
||||
|
||||
@ -32,6 +32,7 @@ log = logging.getLogger(__name__)
|
||||
class Inventory(HasCopy, HasCreate, HasInstanceGroups, HasVariables, base.Base):
|
||||
|
||||
dependencies = [Organization]
|
||||
NATURAL_KEY = ('organization', 'name')
|
||||
|
||||
def print_ini(self):
|
||||
"""Print an ini version of the inventory"""
|
||||
|
||||
@ -24,6 +24,7 @@ class JobTemplate(
|
||||
UnifiedJobTemplate):
|
||||
|
||||
optional_dependencies = [Inventory, Credential, Project]
|
||||
NATURAL_KEY = ('organization', 'name')
|
||||
|
||||
def launch(self, payload={}):
|
||||
"""Launch the job_template using related->launch endpoint."""
|
||||
|
||||
@ -9,6 +9,7 @@ from . import page
|
||||
class Label(HasCreate, base.Base):
|
||||
|
||||
dependencies = [Organization]
|
||||
NATURAL_KEY = ('organization', 'name')
|
||||
|
||||
def silent_delete(self):
|
||||
"""Label pages do not support DELETE requests. Here, we override the base page object
|
||||
|
||||
@ -24,6 +24,7 @@ notification_types = (
|
||||
class NotificationTemplate(HasCopy, HasCreate, base.Base):
|
||||
|
||||
dependencies = [Organization]
|
||||
NATURAL_KEY = ('organization', 'name')
|
||||
|
||||
def test(self):
|
||||
"""Create test notification"""
|
||||
|
||||
@ -8,6 +8,8 @@ from . import page
|
||||
|
||||
class Organization(HasCreate, HasInstanceGroups, HasNotifications, base.Base):
|
||||
|
||||
NATURAL_KEY = ('name',)
|
||||
|
||||
def add_admin(self, user):
|
||||
if isinstance(user, page.Page):
|
||||
user = user.json
|
||||
|
||||
@ -317,6 +317,24 @@ class Page(object):
|
||||
page_cls = get_registered_page(endpoint)
|
||||
return page_cls(self.connection, endpoint=endpoint).get(**kw)
|
||||
|
||||
def get_natural_key(self):
|
||||
if not getattr(self, 'NATURAL_KEY', None):
|
||||
raise exc.NoNaturalKey(
|
||||
"Page does not have a natural key: {}".format(getattr(self, 'endpoint', repr(self.__class__)))
|
||||
)
|
||||
natural_key = {}
|
||||
for key in self.NATURAL_KEY:
|
||||
if key in self.related:
|
||||
# FIXME: use caching by url
|
||||
natural_key[key] = self.related[key].get().get_natural_key()
|
||||
elif key in self:
|
||||
natural_key[key] = self[key]
|
||||
if not natural_key:
|
||||
return None
|
||||
|
||||
natural_key['type'] = self['type']
|
||||
return natural_key
|
||||
|
||||
|
||||
_exception_map = {http.NO_CONTENT: exc.NoContent,
|
||||
http.NOT_FOUND: exc.NotFound,
|
||||
@ -376,6 +394,9 @@ class PageList(object):
|
||||
def create(self, *a, **kw):
|
||||
return self.__item_class__(self.connection).create(*a, **kw)
|
||||
|
||||
def get_natural_key(self):
|
||||
raise exc.NoNaturalKey
|
||||
|
||||
|
||||
class TentativePage(str):
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ class Project(HasCopy, HasCreate, HasNotifications, UnifiedJobTemplate):
|
||||
|
||||
optional_dependencies = [Credential, Organization]
|
||||
optional_schedule_fields = tuple()
|
||||
NATURAL_KEY = ('organization', 'name')
|
||||
|
||||
def payload(self, organization, scm_type='git', **kwargs):
|
||||
payload = PseudoNamespace(
|
||||
|
||||
@ -5,7 +5,19 @@ from . import page
|
||||
|
||||
class Role(base.Base):
|
||||
|
||||
pass
|
||||
NATURAL_KEY = ('name',)
|
||||
|
||||
def get_natural_key(self):
|
||||
natural_key = super(Role, self).get_natural_key()
|
||||
related_objs = [
|
||||
related for name, related in self.related.items()
|
||||
if name not in ('users', 'teams')
|
||||
]
|
||||
if related_objs:
|
||||
# FIXME: use caching by url
|
||||
natural_key['content_object'] = related_objs[0].get().get_natural_key()
|
||||
|
||||
return natural_key
|
||||
|
||||
|
||||
page.register_page(resources.role, Role)
|
||||
|
||||
@ -8,7 +8,7 @@ from . import base
|
||||
|
||||
class Schedule(UnifiedJob):
|
||||
|
||||
pass
|
||||
NATURAL_KEY = ('unified_job_template', 'name')
|
||||
|
||||
|
||||
page.register_page([resources.schedule,
|
||||
|
||||
@ -11,6 +11,7 @@ from . import page
|
||||
class Team(HasCreate, base.Base):
|
||||
|
||||
dependencies = [Organization]
|
||||
NATURAL_KEY = ('organization', 'name')
|
||||
|
||||
def add_user(self, user):
|
||||
if isinstance(user, page.Page):
|
||||
|
||||
@ -9,6 +9,8 @@ from . import page
|
||||
|
||||
class User(HasCreate, base.Base):
|
||||
|
||||
NATURAL_KEY = ('username',)
|
||||
|
||||
def payload(self, **kwargs):
|
||||
payload = PseudoNamespace(
|
||||
username=kwargs.get('username') or 'User-{}'.format(
|
||||
|
||||
@ -10,6 +10,7 @@ from . import page
|
||||
class WorkflowJobTemplateNode(HasCreate, base.Base):
|
||||
|
||||
dependencies = [WorkflowJobTemplate, UnifiedJobTemplate]
|
||||
NATURAL_KEY = ('workflow_job_template', 'identifier')
|
||||
|
||||
def payload(self, workflow_job_template, unified_job_template, **kwargs):
|
||||
if not unified_job_template:
|
||||
|
||||
@ -13,6 +13,7 @@ from . import page
|
||||
class WorkflowJobTemplate(HasCopy, HasCreate, HasNotifications, HasSurvey, UnifiedJobTemplate):
|
||||
|
||||
optional_dependencies = [Organization]
|
||||
NATURAL_KEY = ('organization', 'name')
|
||||
|
||||
def launch(self, payload={}):
|
||||
"""Launch using related->launch endpoint."""
|
||||
|
||||
@ -101,3 +101,8 @@ class UnexpectedAWXState(Common):
|
||||
class IsMigrating(Common):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class NoNaturalKey(Common):
|
||||
|
||||
pass
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user