summaryrefslogtreecommitdiffstats
path: root/awxkit
diff options
context:
space:
mode:
authorHao Liu <haoli@redhat.com>2022-07-13 01:02:23 +0200
committerHao Liu <haoli@redhat.com>2022-07-13 01:48:02 +0200
commit769c253ac2b264a138a83bbbfd325e5d0928513a (patch)
tree94a5ed652581ec58b17e9c1d273a4378b8b5d504 /awxkit
parentTranslate contents of Hosts Automated field as a single string (#12480) (diff)
downloadawx-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__.py1
-rw-r--r--awxkit/awxkit/api/pages/api.py70
-rw-r--r--awxkit/awxkit/api/pages/workflow_approval_templates.py25
-rw-r--r--awxkit/awxkit/api/resources.py3
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/'