diff --git a/awx/ui/client/src/organizations/add/organizations-add.controller.js b/awx/ui/client/src/organizations/add/organizations-add.controller.js index 009f9240e6..4b6e4a5e66 100644 --- a/awx/ui/client/src/organizations/add/organizations-add.controller.js +++ b/awx/ui/client/src/organizations/add/organizations-add.controller.js @@ -6,26 +6,32 @@ export default ['$scope', '$rootScope', '$location', '$stateParams', 'OrganizationForm', 'GenerateForm', 'Rest', 'Alert', - 'ProcessErrors', 'GetBasePath', 'Wait', 'CreateSelect2', '$state','InstanceGroupsService', + 'ProcessErrors', 'GetBasePath', 'Wait', 'CreateSelect2', '$state','InstanceGroupsService', 'ConfigData', function($scope, $rootScope, $location, $stateParams, OrganizationForm, - GenerateForm, Rest, Alert, ProcessErrors, GetBasePath, Wait, CreateSelect2, $state, InstanceGroupsService) { + GenerateForm, Rest, Alert, ProcessErrors, GetBasePath, Wait, CreateSelect2, $state, InstanceGroupsService, ConfigData) { Rest.setUrl(GetBasePath('organizations')); Rest.options() - .then(({data}) => { - if (!data.actions.POST) { - $state.go("^"); - Alert('Permission Error', 'You do not have permission to add an organization.', 'alert-info'); - } - }); + .then(({data}) => { + if (!data.actions.POST) { + $state.go("^"); + Alert('Permission Error', 'You do not have permission to add an organization.', 'alert-info'); + } + }); var form = OrganizationForm(), - base = $location.path().replace(/^\//, '').split('/')[0]; + base = $location.path().replace(/^\//, '').split('/')[0]; init(); function init(){ // @issue What is this doing, why $scope.$emit("HideOrgListHeader"); + $scope.custom_virtualenvs_options = ConfigData.custom_virtualenvs; + CreateSelect2({ + element: '#organization_custom_virtualenv', + multiple: false, + opts: $scope.custom_virtualenvs_options + }); // apply form definition's default field values GenerateForm.applyDefaults(form, $scope); @@ -39,7 +45,8 @@ export default ['$scope', '$rootScope', '$location', '$stateParams', Rest.setUrl(url); Rest.post({ name: $scope.name, - description: $scope.description + description: $scope.description, + custom_virtualenv: $scope.custom_virtualenv }) .then(({data}) => { const organization_id = data.id, diff --git a/awx/ui/client/src/organizations/edit/organizations-edit.controller.js b/awx/ui/client/src/organizations/edit/organizations-edit.controller.js index 3cf0c5fc5f..d44ee45746 100644 --- a/awx/ui/client/src/organizations/edit/organizations-edit.controller.js +++ b/awx/ui/client/src/organizations/edit/organizations-edit.controller.js @@ -6,10 +6,10 @@ export default ['$scope', '$location', '$stateParams', 'OrganizationForm', 'Rest', 'ProcessErrors', 'Prompt', - 'GetBasePath', 'Wait', '$state', 'ToggleNotification', 'CreateSelect2', 'InstanceGroupsService', 'InstanceGroupsData', + 'GetBasePath', 'Wait', '$state', 'ToggleNotification', 'CreateSelect2', 'InstanceGroupsService', 'InstanceGroupsData', 'ConfigData', function($scope, $location, $stateParams, OrganizationForm, Rest, ProcessErrors, Prompt, - GetBasePath, Wait, $state, ToggleNotification, CreateSelect2, InstanceGroupsService, InstanceGroupsData) { + GetBasePath, Wait, $state, ToggleNotification, CreateSelect2, InstanceGroupsService, InstanceGroupsData, ConfigData) { let form = OrganizationForm(), defaultUrl = GetBasePath('organizations'), @@ -29,6 +29,7 @@ export default ['$scope', '$location', '$stateParams', $scope.$emit("HideOrgListHeader"); $scope.instance_groups = InstanceGroupsData; + $scope.custom_virtualenvs_options = ConfigData.custom_virtualenvs; } @@ -36,20 +37,26 @@ export default ['$scope', '$location', '$stateParams', Wait('start'); Rest.setUrl(defaultUrl + id + '/'); Rest.get() - .then(({data}) => { - let fld; + .then(({data}) => { + let fld; - $scope.organization_name = data.name; - for (fld in form.fields) { - if (data[fld]) { - $scope[fld] = data[fld]; - master[fld] = data[fld]; - } + $scope.organization_name = data.name; + for (fld in form.fields) { + if (data[fld]) { + $scope[fld] = data[fld]; + master[fld] = data[fld]; } + } - $scope.organization_obj = data; - $scope.$emit('organizationLoaded'); - Wait('stop'); + CreateSelect2({ + element: '#organization_custom_virtualenv', + multiple: false, + opts: $scope.custom_virtualenvs_options + }); + + $scope.organization_obj = data; + $scope.$emit('organizationLoaded'); + Wait('stop'); }); $scope.toggleNotification = function(event, id, column) { diff --git a/awx/ui/client/src/organizations/main.js b/awx/ui/client/src/organizations/main.js index 128676263d..bb21bfb6c0 100644 --- a/awx/ui/client/src/organizations/main.js +++ b/awx/ui/client/src/organizations/main.js @@ -55,7 +55,15 @@ angular.module('Organizations', [ activityStreamTarget: 'organization' }, resolve: { + add: { + ConfigData: ['ConfigService', (ConfigService) => { + return ConfigService.getConfig().then(response => response); + }] + }, edit: { + ConfigData: ['ConfigService', (ConfigService) => { + return ConfigService.getConfig().then(response => response); + }], InstanceGroupsData: ['$stateParams', 'Rest', 'GetBasePath', 'ProcessErrors', function($stateParams, Rest, GetBasePath, ProcessErrors){ let path = `${GetBasePath('organizations')}${$stateParams.organization_id}/instance_groups/`; diff --git a/awx/ui/client/src/organizations/organizations.form.js b/awx/ui/client/src/organizations/organizations.form.js index 2a79118d70..14883a3428 100644 --- a/awx/ui/client/src/organizations/organizations.form.js +++ b/awx/ui/client/src/organizations/organizations.form.js @@ -42,6 +42,17 @@ export default ['NotificationsList', 'i18n', dataContainer: 'body', dataPlacement: 'right', control: '', + }, + custom_virtualenv: { + label: i18n._('Ansible Environment'), + defaultText: i18n._('Select Ansible Environment'), + type: 'select', + ngOptions: 'venv for venv in custom_virtualenvs_options track by venv', + awPopOver: "

" + i18n._("Select the custom Python virtual environment for this organization to run on.") + "

", + dataTitle: i18n._('Ansible Environment'), + dataContainer: 'body', + dataPlacement: 'right', + ngDisabled: '!(organization_obj.summary_fields.user_capabilities.edit || canAdd)' } }, diff --git a/awx/ui/client/src/projects/add/projects-add.controller.js b/awx/ui/client/src/projects/add/projects-add.controller.js index e4304ccb32..a5ccdbdbf2 100644 --- a/awx/ui/client/src/projects/add/projects-add.controller.js +++ b/awx/ui/client/src/projects/add/projects-add.controller.js @@ -7,12 +7,12 @@ export default ['$scope', '$location', '$stateParams', 'GenerateForm', 'ProjectsForm', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'GetProjectPath', 'GetChoices', 'Wait', '$state', 'CreateSelect2', 'i18n', - 'CredentialTypes', + 'CredentialTypes', 'ConfigData', function($scope, $location, $stateParams, GenerateForm, ProjectsForm, Rest, Alert, ProcessErrors, GetBasePath, GetProjectPath, GetChoices, Wait, $state, - CreateSelect2, i18n, CredentialTypes) { + CreateSelect2, i18n, CredentialTypes, ConfigData) { - var form = ProjectsForm(), + let form = ProjectsForm(), base = $location.path().replace(/^\//, '').split('/')[0], defaultUrl = GetBasePath('projects'), master = {}; @@ -21,13 +21,21 @@ export default ['$scope', '$location', '$stateParams', 'GenerateForm', function init() { $scope.canEditOrg = true; + $scope.custom_virtualenvs_options = ConfigData.custom_virtualenvs; + Rest.setUrl(GetBasePath('projects')); Rest.options() - .then(({data}) => { - if (!data.actions.POST) { - $state.go("^"); - Alert(i18n._('Permission Error'), i18n._('You do not have permission to add a project.'), 'alert-info'); - } + .then(({data}) => { + if (!data.actions.POST) { + $state.go("^"); + Alert(i18n._('Permission Error'), i18n._('You do not have permission to add a project.'), 'alert-info'); + } + }); + + CreateSelect2({ + element: '#project_custom_virtualenv', + multiple: false, + opts: $scope.custom_virtualenvs_options }); // apply form definition's default field values diff --git a/awx/ui/client/src/projects/edit/projects-edit.controller.js b/awx/ui/client/src/projects/edit/projects-edit.controller.js index 7d1acb1bc1..457a21545a 100644 --- a/awx/ui/client/src/projects/edit/projects-edit.controller.js +++ b/awx/ui/client/src/projects/edit/projects-edit.controller.js @@ -8,14 +8,14 @@ export default ['$scope', '$rootScope', '$stateParams', 'ProjectsForm', 'Rest', 'Alert', 'ProcessErrors', 'GenerateForm', 'Prompt', 'GetBasePath', 'GetProjectPath', 'Authorization', 'GetChoices', 'Empty', 'Wait', 'ProjectUpdate', '$state', 'CreateSelect2', 'ToggleNotification', - 'i18n', 'CredentialTypes', 'OrgAdminLookup', + 'i18n', 'CredentialTypes', 'OrgAdminLookup', 'ConfigData', function($scope, $rootScope, $stateParams, ProjectsForm, Rest, Alert, ProcessErrors, GenerateForm, Prompt, GetBasePath, GetProjectPath, Authorization, GetChoices, Empty, Wait, ProjectUpdate, $state, CreateSelect2, ToggleNotification, i18n, CredentialTypes, - OrgAdminLookup) { + OrgAdminLookup, ConfigData) { - var form = ProjectsForm(), + let form = ProjectsForm(), defaultUrl = GetBasePath('projects') + $stateParams.project_id + '/', master = {}, id = $stateParams.project_id; @@ -25,6 +25,7 @@ export default ['$scope', '$rootScope', '$stateParams', 'ProjectsForm', 'Rest', function init() { $scope.project_local_paths = []; $scope.base_dir = ''; + $scope.custom_virtualenvs_options = ConfigData.custom_virtualenvs; } $scope.$watch('project_obj.summary_fields.user_capabilities.edit', function(val) { @@ -147,6 +148,12 @@ export default ['$scope', '$rootScope', '$stateParams', 'ProjectsForm', 'Rest', $scope.canEditOrg = canEditOrg; }); + CreateSelect2({ + element: '#project_custom_virtualenv', + multiple: false, + opts: $scope.custom_virtualenvs_options + }); + $scope.project_obj = data; $scope.name = data.name; $scope.$emit('projectLoaded'); diff --git a/awx/ui/client/src/projects/main.js b/awx/ui/client/src/projects/main.js index 7bd3616c23..c997f2a5c0 100644 --- a/awx/ui/client/src/projects/main.js +++ b/awx/ui/client/src/projects/main.js @@ -32,7 +32,7 @@ angular.module('Projects', []) let stateDefinitions = stateDefinitionsProvider.$get(); let stateExtender = $stateExtenderProvider.$get(); var projectResolve = { - CredentialTypes: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors', + CredentialTypes: ['Rest', '$stateParams', 'GetBasePath', 'ProcessErrors', (Rest, $stateParams, GetBasePath, ProcessErrors) => { var path = GetBasePath('credential_types'); Rest.setUrl(path); @@ -47,7 +47,10 @@ angular.module('Projects', []) }); }); } - ] + ], + ConfigData: ['ConfigService', (ConfigService) => { + return ConfigService.getConfig().then(response => response); + }] }; function generateStateTree() { diff --git a/awx/ui/client/src/projects/projects.form.js b/awx/ui/client/src/projects/projects.form.js index a9d6762860..7982175d78 100644 --- a/awx/ui/client/src/projects/projects.form.js +++ b/awx/ui/client/src/projects/projects.form.js @@ -52,6 +52,17 @@ export default ['i18n', 'NotificationsList', 'TemplateList', ngDisabled: '!(project_obj.summary_fields.user_capabilities.edit || canAdd) || !canEditOrg', awLookupWhen: '(project_obj.summary_fields.user_capabilities.edit || canAdd) && canEditOrg' }, + custom_virtualenv: { + label: i18n._('Ansible Environment'), + type: 'select', + defaultText: i18n._('Select Ansible Environment'), + ngOptions: 'venv for venv in custom_virtualenvs_options track by venv', + awPopOver: "

" + i18n._("Select the custom Python virtual environment for this project to run on.") + "

", + dataTitle: i18n._('Ansible Environment'), + dataContainer: 'body', + dataPlacement: 'right', + ngDisabled: '!(project_obj.summary_fields.user_capabilities.edit || canAdd)' + }, scm_type: { label: i18n._('SCM Type'), type: 'select', diff --git a/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js b/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js index b213d3d498..10754cb0e7 100644 --- a/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js +++ b/awx/ui/client/src/templates/job_templates/add-job-template/job-template-add.controller.js @@ -9,13 +9,15 @@ '$stateParams', 'JobTemplateForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'md5Setup', 'ParseTypeChange', 'Wait', 'Empty', 'ToJSON', 'CallbackHelpInit', 'GetChoices', '$state', 'availableLabels', - 'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService', 'MultiCredentialService', + 'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService', + 'MultiCredentialService', 'ConfigData', function( $filter, $scope, $stateParams, JobTemplateForm, GenerateForm, Rest, Alert, ProcessErrors, GetBasePath, md5Setup, ParseTypeChange, Wait, Empty, ToJSON, CallbackHelpInit, GetChoices, - $state, availableLabels, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService, MultiCredentialService + $state, availableLabels, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService, + MultiCredentialService, ConfigData ) { // Inject dynamic view @@ -50,12 +52,12 @@ $scope.surveyTooltip = i18n._('Please save before adding a survey to this job template.'); MultiCredentialService.getCredentialTypes() - .then(({ data }) => { - $scope.multiCredential = { - credentialTypes: data.results, - selectedCredentials: [] - }; - }); + .then(({ data }) => { + $scope.multiCredential = { + credentialTypes: data.results, + selectedCredentials: [] + }; + }); } callback = function() { @@ -80,6 +82,7 @@ } } $scope.job_type = $scope.job_type_options[form.fields.job_type.default]; + $scope.custom_virtualenvs_options = ConfigData.custom_virtualenvs; CreateSelect2({ element:'#job_template_job_type', @@ -109,6 +112,12 @@ multiple: true, addNew: true }); + + CreateSelect2({ + element: '#job_template_custom_virtualenv', + multiple: false, + opts: $scope.custom_virtualenvs_options + }); } }); @@ -259,7 +268,7 @@ try { for (fld in form.fields) { if (form.fields[fld].type === 'select' && - fld !== 'playbook' && $scope[fld]) { + fld !== 'playbook' && fld !== 'custom_virtualenv' && $scope[fld]) { data[fld] = $scope[fld].value; } else if(form.fields[fld].type === 'checkbox_group') { diff --git a/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js b/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js index c7cc71ce4b..38b32b2942 100644 --- a/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js +++ b/awx/ui/client/src/templates/job_templates/edit-job-template/job-template-edit.controller.js @@ -17,16 +17,19 @@ export default 'ParseTypeChange', 'Wait', 'selectedLabels', 'i18n', 'Empty', 'Prompt', 'ToJSON', 'GetChoices', 'CallbackHelpInit', 'InitiatePlaybookRun' , 'initSurvey', '$state', 'CreateSelect2', - 'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData', 'MultiCredentialService', 'availableLabels', - 'projectGetPermissionDenied', 'inventoryGetPermissionDenied', 'jobTemplateData', 'ParseVariableString', + 'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData', + 'MultiCredentialService', 'availableLabels', 'projectGetPermissionDenied', + 'inventoryGetPermissionDenied', 'jobTemplateData', 'ParseVariableString', 'ConfigData', function( $filter, $scope, $rootScope, $location, $stateParams, JobTemplateForm, GenerateForm, Rest, Alert, ProcessErrors, GetBasePath, md5Setup, ParseTypeChange, Wait, selectedLabels, i18n, - Empty, Prompt, ToJSON, GetChoices, CallbackHelpInit, InitiatePlaybookRun, SurveyControllerInit, $state, - CreateSelect2, ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData, MultiCredentialService, availableLabels, - projectGetPermissionDenied, inventoryGetPermissionDenied, jobTemplateData, ParseVariableString + Empty, Prompt, ToJSON, GetChoices, CallbackHelpInit, + InitiatePlaybookRun, SurveyControllerInit, $state, CreateSelect2, + ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData, + MultiCredentialService, availableLabels, projectGetPermissionDenied, + inventoryGetPermissionDenied, jobTemplateData, ParseVariableString, ConfigData ) { $scope.$watch('job_template_obj.summary_fields.user_capabilities.edit', function(val) { @@ -60,6 +63,7 @@ export default $scope.surveyTooltip = i18n._('Surveys allow users to be prompted at job launch with a series of questions related to the job. This allows for variables to be defined that affect the playbook run at time of launch.'); $scope.job_tag_options = []; $scope.skip_tag_options = []; + $scope.custom_virtualenvs_options = ConfigData.custom_virtualenvs; SurveyControllerInit({ scope: $scope, @@ -198,6 +202,12 @@ export default multiple: true, addNew: true }); + + CreateSelect2({ + element: '#job_template_custom_virtualenv', + multiple: false, + opts: $scope.custom_virtualenvs_options + }); } $scope.toggleForm = function(key) { @@ -598,7 +608,7 @@ export default try { for (fld in form.fields) { if (form.fields[fld].type === 'select' && - fld !== 'playbook' && $scope[fld]) { + fld !== 'playbook' && fld !== 'custom_virtualenv' && $scope[fld]) { data[fld] = $scope[fld].value; } else if(form.fields[fld].type === 'checkbox_group') { diff --git a/awx/ui/client/src/templates/job_templates/job-template.form.js b/awx/ui/client/src/templates/job_templates/job-template.form.js index 02eaeff943..bb9d57467b 100644 --- a/awx/ui/client/src/templates/job_templates/job-template.form.js +++ b/awx/ui/client/src/templates/job_templates/job-template.form.js @@ -103,6 +103,17 @@ function(NotificationsList, CompletedJobsList, i18n) { ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate) || !canGetAllRelatedResources', awLookupWhen: 'canGetAllRelatedResources' }, + custom_virtualenv: { + label: i18n._('Ansible Environment'), + type: 'select', + defaultText: i18n._('Select Ansible Environment'), + ngOptions: 'venv for venv in custom_virtualenvs_options track by venv', + awPopOver: "

" + i18n._("Select the custom Python virtual environment for this job template to run on.") + "

", + dataTitle: i18n._('Ansible Environment'), + dataContainer: 'body', + dataPlacement: 'right', + ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAdd)' + }, playbook: { label: i18n._('Playbook'), type:'select', diff --git a/awx/ui/client/src/templates/main.js b/awx/ui/client/src/templates/main.js index 5d1eee77d8..21ec6ce323 100644 --- a/awx/ui/client/src/templates/main.js +++ b/awx/ui/client/src/templates/main.js @@ -129,7 +129,10 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p response.status }); }); - }] + }], + ConfigData: ['ConfigService', (ConfigService) => { + return ConfigService.getConfig().then(response => response); + }] } } }); @@ -260,6 +263,9 @@ angular.module('templates', [surveyMaker.name, jobTemplates.name, labels.name, p response.status }); }); + }], + ConfigData: ['ConfigService', (ConfigService) => { + return ConfigService.getConfig().then(response => response); }] } }