diff options
author | Hao Liu <haoli@redhat.com> | 2022-07-13 01:02:23 +0200 |
---|---|---|
committer | Hao Liu <haoli@redhat.com> | 2022-07-13 01:48:02 +0200 |
commit | 769c253ac2b264a138a83bbbfd325e5d0928513a (patch) | |
tree | 94a5ed652581ec58b17e9c1d273a4378b8b5d504 /awxkit | |
parent | Translate contents of Hosts Automated field as a single string (#12480) (diff) | |
download | awx-769c253ac2b264a138a83bbbfd325e5d0928513a.tar.xz awx-769c253ac2b264a138a83bbbfd325e5d0928513a.zip |
fix WorkflowJobTemplate export where WorkflowApprovalTemplate is not properly exported
fixes https://github.com/ansible/awx/issues/7946
- added WorkflowApprovalTemplate page type to allow URL registration
- added resources regex that’s associated resource URL with WorkflowApprovalTemplate
- registered the new resource regex with WorkflowApprovalTemplate page type
- modified `DEPENDENT_EXPORT` handling (insisted by @jbradberry)
- added special case handling for WorkflowApprovalTemplate due to its unique nature
unique nature of WorkflowApprovalTemplate
- when exporting WorkflowJobTemplate with approval node the WorkflowJobTemplateNode need to contain a related "create_approval_template" the POST data for "create_approval_template" need to come from the "workflow_approval_template"
- during the export of a WorkflowJobTemplateNode that is an approval node we need to get the data from "workflow_approval_template" and use that to populate the "create_approval_template"
Co-Authored-By: Jeff Bradberry <685957+jbradberry@users.noreply.github.com>
Signed-off-by: Hao Liu <haoli@redhat.com>
Diffstat (limited to 'awxkit')
-rw-r--r-- | awxkit/awxkit/api/pages/__init__.py | 1 | ||||
-rw-r--r-- | awxkit/awxkit/api/pages/api.py | 70 | ||||
-rw-r--r-- | awxkit/awxkit/api/pages/workflow_approval_templates.py | 25 | ||||
-rw-r--r-- | awxkit/awxkit/api/resources.py | 3 |
4 files changed, 80 insertions, 19 deletions
diff --git a/awxkit/awxkit/api/pages/__init__.py b/awxkit/awxkit/api/pages/__init__.py index aa55a938e6..628e5e186d 100644 --- a/awxkit/awxkit/api/pages/__init__.py +++ b/awxkit/awxkit/api/pages/__init__.py @@ -40,3 +40,4 @@ from .instance_groups import * # NOQA from .credential_input_sources import * # NOQA from .metrics import * # NOQA from .subscriptions import * # NOQA +from .workflow_approval_templates import * # NOQA diff --git a/awxkit/awxkit/api/pages/api.py b/awxkit/awxkit/api/pages/api.py index 72b2618792..359ca7359b 100644 --- a/awxkit/awxkit/api/pages/api.py +++ b/awxkit/awxkit/api/pages/api.py @@ -36,14 +36,15 @@ EXPORTABLE_RELATIONS = ['Roles', 'NotificationTemplates', 'WorkflowJobTemplateNo # These are special-case related objects, where we want only in this # case to export a full object instead of a natural key reference. DEPENDENT_EXPORT = [ - ('JobTemplate', 'labels'), - ('JobTemplate', 'survey_spec'), - ('WorkflowJobTemplate', 'labels'), - ('WorkflowJobTemplate', 'survey_spec'), - ('WorkflowJobTemplate', 'workflow_nodes'), - ('Inventory', 'groups'), - ('Inventory', 'hosts'), - ('Inventory', 'labels'), + ('JobTemplate', 'Label'), + ('JobTemplate', 'SurveySpec'), + ('WorkflowJobTemplate', 'Label'), + ('WorkflowJobTemplate', 'SurveySpec'), + ('WorkflowJobTemplate', 'WorkflowJobTemplateNode'), + ('Inventory', 'Group'), + ('Inventory', 'Host'), + ('Inventory', 'Label'), + ('WorkflowJobTemplateNode', 'WorkflowApprovalTemplate'), ] @@ -57,6 +58,7 @@ DEPENDENT_NONEXPORT = [ ('Group', 'all_hosts'), ('Group', 'potential_children'), ('Host', 'all_groups'), + ('WorkflowJobTemplateNode', 'create_approval_template'), ] @@ -85,6 +87,7 @@ class ApiV2(base.Base): # Note: doing _page[key] automatically parses json blob strings, which can be a problem. fields = {key: _page.json[key] for key in post_fields if key in _page.json and key not in _page.related and key != 'id'} + # iterate over direct fields in the object for key in post_fields: if key in _page.related: related = _page.related[key] @@ -114,6 +117,12 @@ class ApiV2(base.Base): return None log.warning("Foreign key %r export failed for object %s, setting to null", key, _page.endpoint) continue + + # Workflow approval templates have a special creation endpoint, + # therefore we are skipping the export via natural key. + if rel_endpoint.__item_class__.__name__ == 'WorkflowApprovalTemplate': + continue + rel_natural_key = rel_endpoint.get_natural_key(self._cache) if rel_natural_key is None: log.error("Unable to construct a natural key for foreign key %r of object %s.", key, _page.endpoint) @@ -121,19 +130,38 @@ class ApiV2(base.Base): return None # This foreign key has unresolvable dependencies fields[key] = rel_natural_key + # iterate over related fields in the object related = {} for key, rel_endpoint in _page.related.items(): - if key in post_fields or not rel_endpoint: + # skip if no endpoint for this related object + if not rel_endpoint: continue rel = rel_endpoint._create() + + if rel.__item_class__.__name__ != 'WorkflowApprovalTemplate': + if key in post_fields: + continue + is_relation = rel.__class__.__name__ in EXPORTABLE_RELATIONS - is_dependent = (_page.__item_class__.__name__, key) in DEPENDENT_EXPORT + + # determine if the parent object and the related object that we are processing through are related + # if this tuple is in the DEPENDENT_EXPORT than we output the full object + # else we output the natural key + is_dependent = (_page.__item_class__.__name__, rel.__item_class__.__name__) in DEPENDENT_EXPORT + is_blocked = (_page.__item_class__.__name__, key) in DEPENDENT_NONEXPORT if is_blocked or not (is_relation or is_dependent): continue - rel_post_fields = utils.get_post_fields(rel_endpoint, self._cache) + # if the rel is of WorkflowApprovalTemplate type, get rel_post_fields from create_approval_template endpoint + rel_option_endpoint = rel_endpoint + export_key = key + if rel.__item_class__.__name__ == 'WorkflowApprovalTemplate': + export_key = 'create_approval_template' + rel_option_endpoint = _page.related.get('create_approval_template') + + rel_post_fields = utils.get_post_fields(rel_option_endpoint, self._cache) if rel_post_fields is None: log.debug("%s is a read-only endpoint.", rel_endpoint) continue @@ -147,24 +175,28 @@ class ApiV2(base.Base): continue rel_page = self._cache.get_page(rel_endpoint) + if rel_page is None: continue if 'results' in rel_page: results = (x.get_natural_key(self._cache) if by_natural_key else self._export(x, rel_post_fields) for x in rel_page.results) - related[key] = [x for x in results if x is not None] + related[export_key] = [x for x in results if x is not None] + elif rel.__item_class__.__name__ == 'WorkflowApprovalTemplate': + related[export_key] = self._export(rel_page, rel_post_fields) else: - related[key] = rel_page.json + related[export_key] = rel_page.json if related: fields['related'] = related - natural_key = _page.get_natural_key(self._cache) - if natural_key is None: - log.error("Unable to construct a natural key for object %s.", _page.endpoint) - self._has_error = True - return None - fields['natural_key'] = natural_key + if _page.__item_class__.__name__ != 'WorkflowApprovalTemplate': + natural_key = _page.get_natural_key(self._cache) + if natural_key is None: + log.error("Unable to construct a natural key for object %s.", _page.endpoint) + self._has_error = True + return None + fields['natural_key'] = natural_key return utils.remove_encrypted(fields) diff --git a/awxkit/awxkit/api/pages/workflow_approval_templates.py b/awxkit/awxkit/api/pages/workflow_approval_templates.py new file mode 100644 index 0000000000..2796a81f25 --- /dev/null +++ b/awxkit/awxkit/api/pages/workflow_approval_templates.py @@ -0,0 +1,25 @@ +from awxkit.api.pages.unified_job_templates import UnifiedJobTemplate +from awxkit.api.resources import resources +from . import page + + +class WorkflowApprovalTemplate(UnifiedJobTemplate): + + pass + + +page.register_page( + [ + resources.workflow_approval_template, + resources.workflow_job_template_node_create_approval_template, + ], + WorkflowApprovalTemplate, +) + + +class WorkflowApprovalTemplates(page.PageList, WorkflowApprovalTemplate): + + pass + + +page.register_page(resources.workflow_approval_templates, WorkflowApprovalTemplates) diff --git a/awxkit/awxkit/api/resources.py b/awxkit/awxkit/api/resources.py index 9ae22ad1e5..815f10ac9d 100644 --- a/awxkit/awxkit/api/resources.py +++ b/awxkit/awxkit/api/resources.py @@ -82,6 +82,9 @@ class Resources(object): _inventory_variable_data = r'inventories/\d+/variable_data/' _workflow_approval = r'workflow_approvals/\d+/' _workflow_approvals = 'workflow_approvals/' + _workflow_approval_template = r'workflow_approval_templates/\d+/' + _workflow_approval_templates = 'workflow_approval_templates/' + _workflow_job_template_node_create_approval_template = r'workflow_job_template_nodes/\d+/create_approval_template/' _job = r'jobs/\d+/' _job_cancel = r'jobs/\d+/cancel/' _job_create_schedule = r'jobs/\d+/create_schedule/' |