From 58c06d5aeab5943f7632d292e7ed31a8fdbcf393 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 23 Feb 2020 14:58:47 +0000 Subject: [PATCH 01/48] fixed precedence on ansible.cfg --- awx/main/utils/ansible.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/utils/ansible.py b/awx/main/utils/ansible.py index fa15c47ab1..91b117ae5d 100644 --- a/awx/main/utils/ansible.py +++ b/awx/main/utils/ansible.py @@ -106,7 +106,7 @@ def could_be_inventory(project_path, dir_path, filename): def read_ansible_config(project_path, variables_of_interest): fnames = ['/etc/ansible/ansible.cfg'] if project_path: - fnames.insert(0, os.path.join(project_path, 'ansible.cfg')) + fnames.insert(1, os.path.join(project_path, 'ansible.cfg')) values = {} try: parser = ConfigParser() From 350046d495c9e2d815993b04205af64d01df37f3 Mon Sep 17 00:00:00 2001 From: gamuniz Date: Wed, 26 Feb 2020 14:28:22 +0000 Subject: [PATCH 02/48] changed syntax as insert isn't required --- awx/main/utils/ansible.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/utils/ansible.py b/awx/main/utils/ansible.py index 91b117ae5d..18011504b9 100644 --- a/awx/main/utils/ansible.py +++ b/awx/main/utils/ansible.py @@ -106,7 +106,7 @@ def could_be_inventory(project_path, dir_path, filename): def read_ansible_config(project_path, variables_of_interest): fnames = ['/etc/ansible/ansible.cfg'] if project_path: - fnames.insert(1, os.path.join(project_path, 'ansible.cfg')) + fnames.append(os.path.join(project_path, 'ansible.cfg')) values = {} try: parser = ConfigParser() From 07807c2decd82e01dc0a2047d21aba92114555b0 Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Thu, 27 Feb 2020 14:37:29 -0500 Subject: [PATCH 03/48] Fail on launch for scenario where job cannot run --- awx/api/serializers.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 93124ea19e..f4a61f0c43 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -4054,6 +4054,13 @@ class JobLaunchSerializer(BaseSerializer): **attrs) self._ignored_fields = rejected + # Basic validation - cannot run a playbook without a playbook + if not template.project: + errors['project'] = _("A project is required to run a job.") + elif template.project.status in ('error', 'failed'): + errors['playbook'] = _("Missing a revision to run due to failed project update.") + + # cannot run a playbook without an inventory if template.inventory and template.inventory.pending_deletion is True: errors['inventory'] = _("The inventory associated with this Job Template is being deleted.") elif 'inventory' in accepted and accepted['inventory'].pending_deletion: From 52a8935b20b7226555552bea3a83256303d133a0 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Tue, 4 Feb 2020 16:30:06 -0500 Subject: [PATCH 04/48] Adds WorkflowJobTemplate Add and Edit form and functionality. --- .../src/api/models/WorkflowJobTemplates.js | 31 ++- .../Template/TemplateList/TemplateList.jsx | 6 +- .../src/screens/Template/Templates.jsx | 89 ++++----- .../screens/Template/WorkflowJobTemplate.jsx | 153 ++++++++------- .../WorkflowJobTemplateAdd.jsx | 49 +++++ .../WorkflowJobTemplateAdd.test.jsx | 64 +++++++ .../Template/WorkflowJobTemplateAdd/index.js | 1 + .../WorkflowJobTemplateEdit.jsx | 76 ++++++++ .../WorkflowJobTemplateEdit.test.jsx | 97 ++++++++++ .../Template/WorkflowJobTemplateEdit/index.js | 1 + .../shared/WorkflowJobTemplateForm.jsx | 176 ++++++++++++++++++ .../shared/WorkflowJobTemplateForm.test.jsx | 137 ++++++++++++++ .../src/screens/Template/shared/index.js | 3 +- 13 files changed, 767 insertions(+), 116 deletions(-) create mode 100644 awx/ui_next/src/screens/Template/WorkflowJobTemplateAdd/WorkflowJobTemplateAdd.jsx create mode 100644 awx/ui_next/src/screens/Template/WorkflowJobTemplateAdd/WorkflowJobTemplateAdd.test.jsx create mode 100644 awx/ui_next/src/screens/Template/WorkflowJobTemplateAdd/index.js create mode 100644 awx/ui_next/src/screens/Template/WorkflowJobTemplateEdit/WorkflowJobTemplateEdit.jsx create mode 100644 awx/ui_next/src/screens/Template/WorkflowJobTemplateEdit/WorkflowJobTemplateEdit.test.jsx create mode 100644 awx/ui_next/src/screens/Template/WorkflowJobTemplateEdit/index.js create mode 100644 awx/ui_next/src/screens/Template/shared/WorkflowJobTemplateForm.jsx create mode 100644 awx/ui_next/src/screens/Template/shared/WorkflowJobTemplateForm.test.jsx diff --git a/awx/ui_next/src/api/models/WorkflowJobTemplates.js b/awx/ui_next/src/api/models/WorkflowJobTemplates.js index 691c444379..922d5cde00 100644 --- a/awx/ui_next/src/api/models/WorkflowJobTemplates.js +++ b/awx/ui_next/src/api/models/WorkflowJobTemplates.js @@ -6,6 +6,24 @@ class WorkflowJobTemplates extends Base { this.baseUrl = '/api/v2/workflow_job_templates/'; } + associateLabel(id, label, orgId) { + return this.http.post(`${this.baseUrl}${id}/labels/`, { + name: label.name, + organization: orgId, + }); + } + + createNode(id, data) { + return this.http.post(`${this.baseUrl}${id}/workflow_nodes/`, data); + } + + disassociateLabel(id, label) { + return this.http.post(`${this.baseUrl}${id}/labels/`, { + id: label.id, + disassociate: true, + }); + } + launch(id, data) { return this.http.post(`${this.baseUrl}${id}/launch/`, data); } @@ -20,17 +38,16 @@ class WorkflowJobTemplates extends Base { }); } + readScheduleList(id, params) { + return this.http.get(`${this.baseUrl}${id}/schedules/`, { + params + }); + } + readWebhookKey(id) { return this.http.get(`${this.baseUrl}${id}/webhook_key/`); } - createNode(id, data) { - return this.http.post(`${this.baseUrl}${id}/workflow_nodes/`, data); - } - - readScheduleList(id, params) { - return this.http.get(`${this.baseUrl}${id}/schedules/`, { params }); - } } export default WorkflowJobTemplates; diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index 717b1b5f89..913fcfb648 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -2,7 +2,7 @@ import React, { useEffect, useState, useCallback } from 'react'; import { useParams, useLocation } from 'react-router-dom'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; -import { Card } from '@patternfly/react-core'; +import { Card, PageSection } from '@patternfly/react-core'; import { JobTemplatesAPI, @@ -141,7 +141,7 @@ function TemplateList({ i18n }) { ); return ( - <> + - + ); } diff --git a/awx/ui_next/src/screens/Template/Templates.jsx b/awx/ui_next/src/screens/Template/Templates.jsx index c8eb2f243e..456f8b3ca4 100644 --- a/awx/ui_next/src/screens/Template/Templates.jsx +++ b/awx/ui_next/src/screens/Template/Templates.jsx @@ -2,7 +2,6 @@ import React, { Component } from 'react'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { Route, withRouter, Switch } from 'react-router-dom'; -import { PageSection } from '@patternfly/react-core'; import { Config } from '@contexts/Config'; import Breadcrumbs from '@components/Breadcrumbs/Breadcrumbs'; @@ -10,6 +9,7 @@ import { TemplateList } from './TemplateList'; import Template from './Template'; import WorkflowJobTemplate from './WorkflowJobTemplate'; import JobTemplateAdd from './JobTemplateAdd'; +import WorkflowJobTemplateAdd from './WorkflowJobTemplateAdd'; class Templates extends Component { constructor(props) { @@ -20,6 +20,9 @@ class Templates extends Component { breadcrumbConfig: { '/templates': i18n._(t`Templates`), '/templates/job_template/add': i18n._(t`Create New Job Template`), + '/templates/workflow_job_template/add': i18n._( + t`Create New Workflow Job Template` + ), }, }; } @@ -56,47 +59,49 @@ class Templates extends Component { return ( <> - - - } - /> - ( - - {({ me }) => ( -