mirror of
https://github.com/ansible/awx.git
synced 2026-01-17 12:41:19 -03:30
Merge pull request #6483 from marshmalien/rampartsReadOnlyViews
Add Instance Group Fields to Inv, Org, and Job Template resources
This commit is contained in:
commit
d3c9b57133
@ -70,6 +70,7 @@ import access from './access/main';
|
||||
import './login/authenticationServices/pendo/ng-pendo';
|
||||
import footer from './footer/main';
|
||||
import scheduler from './scheduler/main';
|
||||
import instanceGroups from './instance-groups/main';
|
||||
|
||||
var tower = angular.module('Tower', [
|
||||
// how to add CommonJS / AMD third-party dependencies:
|
||||
@ -123,6 +124,7 @@ var tower = angular.module('Tower', [
|
||||
users.name,
|
||||
projects.name,
|
||||
scheduler.name,
|
||||
instanceGroups.name,
|
||||
|
||||
'Utilities',
|
||||
'templates',
|
||||
|
||||
27
awx/ui/client/src/instance-groups/instance-groups.list.js
Normal file
27
awx/ui/client/src/instance-groups/instance-groups.list.js
Normal file
@ -0,0 +1,27 @@
|
||||
export default ['i18n', function(i18n) {
|
||||
return {
|
||||
name: 'instance_groups' ,
|
||||
basePath: 'instance_groups',
|
||||
iterator: 'instance_group',
|
||||
listTitle: i18n._('INSTANCE GROUPS'),
|
||||
index: false,
|
||||
hover: false,
|
||||
|
||||
fields: {
|
||||
name: {
|
||||
key: true,
|
||||
label: i18n._('Name'),
|
||||
columnClass: 'col-md-3 col-sm-9 col-xs-9',
|
||||
modalColumnClass: 'col-md-8',
|
||||
},
|
||||
capacity: {
|
||||
label: i18n._('Capacity'),
|
||||
nosort: true,
|
||||
},
|
||||
running_jobs: {
|
||||
label: i18n._('Running Jobs'),
|
||||
nosort: true,
|
||||
},
|
||||
}
|
||||
};
|
||||
}];
|
||||
41
awx/ui/client/src/instance-groups/instance-groups.service.js
Normal file
41
awx/ui/client/src/instance-groups/instance-groups.service.js
Normal file
@ -0,0 +1,41 @@
|
||||
export default
|
||||
['Rest', function(Rest) {
|
||||
return {
|
||||
addInstanceGroups: function(url, instance_groups) {
|
||||
let groups = (instance_groups || []);
|
||||
Rest.setUrl(url);
|
||||
let defers = groups.map((group) => Rest.post(group));
|
||||
return Promise.all(defers);
|
||||
},
|
||||
editInstanceGroups: function(url, instance_groups) {
|
||||
Rest.setUrl(url);
|
||||
let currentGroups = Rest.get()
|
||||
.then(({data}) => {
|
||||
return data.results.map((i) => i.id);
|
||||
});
|
||||
|
||||
return currentGroups.then(function(current) {
|
||||
|
||||
let groupsToAdd = (instance_groups || [])
|
||||
.map(val => val.id);
|
||||
|
||||
let groupsToDisassociate = current
|
||||
.filter(val => groupsToAdd
|
||||
.indexOf(val) === -1)
|
||||
.map(val => ({id: val, disassociate: true}));
|
||||
|
||||
let groupsToAssociate = groupsToAdd
|
||||
.filter(val => current
|
||||
.indexOf(val) === -1)
|
||||
.map(val => ({id: val, associate: true}));
|
||||
|
||||
let pass = groupsToDisassociate
|
||||
.concat(groupsToAssociate);
|
||||
|
||||
Rest.setUrl(url);
|
||||
let defers = pass.map((group) => Rest.post(group));
|
||||
Promise.resolve(defers);
|
||||
});
|
||||
}
|
||||
};
|
||||
}];
|
||||
@ -0,0 +1,42 @@
|
||||
export default ['$scope', 'InstanceGroupList', 'GetBasePath', 'Rest', 'Dataset','Find', '$state', '$q',
|
||||
function($scope, InstanceGroupList, GetBasePath, Rest, Dataset, Find, $state, $q) {
|
||||
let list = InstanceGroupList;
|
||||
|
||||
init();
|
||||
|
||||
function init(){
|
||||
$scope.optionsDefer = $q.defer();
|
||||
$scope.list = list;
|
||||
$scope[`${list.iterator}_dataset`] = Dataset.data;
|
||||
$scope[list.name] = $scope[`${list.iterator}_dataset`].results;
|
||||
}
|
||||
|
||||
// iterate over the list and add fields like type label, after the
|
||||
// OPTIONS request returns, or the list is sorted/paginated/searched
|
||||
function optionsRequestDataProcessing(){
|
||||
$scope.optionsDefer.promise.then(function(options) {
|
||||
if($scope.list.name === 'instance_groups'){
|
||||
if ($scope[list.name] !== undefined) {
|
||||
$scope[list.name].forEach(function(item, item_idx) {
|
||||
var itm = $scope[list.name][item_idx];
|
||||
// Set the item type label
|
||||
if (list.fields.kind && options && options.actions && options.actions.GET && options.actions.GET.kind) {
|
||||
options.actions.GET.kind.choices.forEach(function(choice) {
|
||||
if (choice[0] === item.kind) {
|
||||
itm.kind_label = choice[1];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.$watchCollection(`${$scope.list.name}`, function() {
|
||||
optionsRequestDataProcessing();
|
||||
}
|
||||
);
|
||||
}
|
||||
];
|
||||
36
awx/ui/client/src/instance-groups/main.js
Normal file
36
awx/ui/client/src/instance-groups/main.js
Normal file
@ -0,0 +1,36 @@
|
||||
import InstanceGroupsList from './list/instance-groups-list.controller';
|
||||
import list from './instance-groups.list';
|
||||
import service from './instance-groups.service';
|
||||
import { N_ } from '../i18n';
|
||||
|
||||
export default
|
||||
angular.module('instanceGroups', [])
|
||||
.factory('InstanceGroupList', list)
|
||||
.service('InstanceGroupsService', service)
|
||||
.controller('InstanceGroupsList', InstanceGroupsList)
|
||||
.config(['$stateProvider', 'stateDefinitionsProvider',
|
||||
function($stateProvider, stateDefinitionsProvider) {
|
||||
let stateDefinitions = stateDefinitionsProvider.$get();
|
||||
|
||||
$stateProvider.state({
|
||||
name: 'instanceGroups',
|
||||
url: '/instance_groups',
|
||||
lazyLoad: () => stateDefinitions.generateTree({
|
||||
parent: 'instanceGroups',
|
||||
list: 'InstanceGroupList',
|
||||
controllers: {
|
||||
list: 'InstanceGroupsList'
|
||||
},
|
||||
data: {
|
||||
activityStream: true,
|
||||
activityStreamTarget: 'instanceGroup'
|
||||
},
|
||||
ncyBreadcrumb: {
|
||||
parent: 'setup',
|
||||
label: N_('INSTANCE GROUPS')
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
}
|
||||
]);
|
||||
@ -42,6 +42,20 @@ export default {
|
||||
.catch(function() {
|
||||
return false;
|
||||
});
|
||||
}],
|
||||
InstanceGroupsData: ['Rest', 'GetBasePath', 'ProcessErrors', (Rest, GetBasePath, ProcessErrors) => {
|
||||
const url = GetBasePath('instance_groups');
|
||||
Rest.setUrl(url);
|
||||
return Rest.get()
|
||||
.then(({data}) => {
|
||||
return data.results.map((i) => ({name: i.name, id: i.id}));
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors(null, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get instance groups info. GET returned status: ' + status
|
||||
});
|
||||
});
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
function InventoriesAdd($scope, $location,
|
||||
GenerateForm, InventoryForm, rbacUiControlService, Rest, Alert, ProcessErrors,
|
||||
ClearScope, GetBasePath, ParseTypeChange, Wait, ToJSON,
|
||||
$state, canAdd) {
|
||||
$state, canAdd, CreateSelect2, InstanceGroupsService, InstanceGroupsData) {
|
||||
|
||||
$scope.canAdd = canAdd;
|
||||
|
||||
@ -42,6 +42,13 @@ function InventoriesAdd($scope, $location,
|
||||
});
|
||||
}
|
||||
|
||||
$scope.instanceGroupOptions = InstanceGroupsData;
|
||||
CreateSelect2({
|
||||
element: '#inventory_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false
|
||||
});
|
||||
|
||||
// Save
|
||||
$scope.formSave = function() {
|
||||
Wait('start');
|
||||
@ -59,12 +66,24 @@ function InventoriesAdd($scope, $location,
|
||||
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.post(data)
|
||||
.success(function(data) {
|
||||
var inventory_id = data.id;
|
||||
Wait('stop');
|
||||
$state.go('inventories.edit', {inventory_id: inventory_id}, {reload: true});
|
||||
.then(({data}) => {
|
||||
const inventory_id = data.id,
|
||||
instance_group_url = data.related.instance_groups;
|
||||
|
||||
InstanceGroupsService.addInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||
.then(() => {
|
||||
Wait('stop');
|
||||
$state.go('inventories.edit', {inventory_id: inventory_id}, {reload: true});
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to post instance groups. POST returned ' +
|
||||
'status: ' + status
|
||||
});
|
||||
});
|
||||
})
|
||||
.error(function(data, status) {
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to add new inventory. Post returned status: ' + status
|
||||
@ -85,5 +104,5 @@ function InventoriesAdd($scope, $location,
|
||||
export default ['$scope', '$location',
|
||||
'GenerateForm', 'InventoryForm', 'rbacUiControlService', 'Rest', 'Alert',
|
||||
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ParseTypeChange',
|
||||
'Wait', 'ToJSON', '$state', 'canAdd', InventoriesAdd
|
||||
];
|
||||
'Wait', 'ToJSON', '$state','canAdd', 'CreateSelect2', 'InstanceGroupsService', 'InstanceGroupsData', InventoriesAdd
|
||||
];
|
||||
@ -13,13 +13,14 @@
|
||||
function InventoriesEdit($scope, $location,
|
||||
$stateParams, InventoryForm, Rest, ProcessErrors,
|
||||
ClearScope, GetBasePath, ParseTypeChange, Wait, ToJSON,
|
||||
ParseVariableString, $state, OrgAdminLookup, $rootScope, resourceData) {
|
||||
ParseVariableString, $state, OrgAdminLookup, $rootScope, resourceData, CreateSelect2, InstanceGroupsService, InstanceGroupsData) {
|
||||
|
||||
// Inject dynamic view
|
||||
var defaultUrl = GetBasePath('inventory'),
|
||||
let defaultUrl = GetBasePath('inventory'),
|
||||
form = InventoryForm,
|
||||
fld, data,
|
||||
inventoryData = resourceData.data;
|
||||
inventoryData = resourceData.data,
|
||||
instance_group_url = inventoryData.related.instance_groups;
|
||||
|
||||
init();
|
||||
|
||||
@ -34,6 +35,36 @@ function InventoriesEdit($scope, $location,
|
||||
$scope.inventory_variables = inventoryData.variables === null || inventoryData.variables === '' ? '---' : ParseVariableString(inventoryData.variables);
|
||||
$scope.parseType = 'yaml';
|
||||
|
||||
$scope.instanceGroupOptions = InstanceGroupsData;
|
||||
CreateSelect2({
|
||||
element: '#inventory_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false
|
||||
});
|
||||
|
||||
Rest.setUrl(instance_group_url);
|
||||
Rest.get()
|
||||
.then(({data}) => {
|
||||
if (data.results.length > 0) {
|
||||
var opts = data.results
|
||||
.map(i => ({id: i.id + "",
|
||||
name: i.name}));
|
||||
CreateSelect2({
|
||||
element:'#inventory_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false,
|
||||
opts: opts
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get instance groups. GET returned ' +
|
||||
'status: ' + status
|
||||
});
|
||||
});
|
||||
|
||||
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
|
||||
if(toState.name === 'inventories.edit') {
|
||||
ParseTypeChange({
|
||||
@ -75,11 +106,20 @@ function InventoriesEdit($scope, $location,
|
||||
|
||||
Rest.setUrl(defaultUrl + $stateParams.inventory_id + '/');
|
||||
Rest.put(data)
|
||||
.success(function() {
|
||||
Wait('stop');
|
||||
$state.go($state.current, {}, { reload: true });
|
||||
.then(() => {
|
||||
InstanceGroupsService.editInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||
.then(() => {
|
||||
Wait('stop');
|
||||
$state.go($state.current, {}, { reload: true });
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to update instance groups. POST returned status: ' + status
|
||||
});
|
||||
});
|
||||
})
|
||||
.error(function(data, status) {
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to update inventory. PUT returned status: ' + status
|
||||
@ -101,5 +141,5 @@ export default ['$scope', '$location',
|
||||
'$stateParams', 'InventoryForm', 'Rest',
|
||||
'ProcessErrors', 'ClearScope', 'GetBasePath', 'ParseTypeChange', 'Wait',
|
||||
'ToJSON', 'ParseVariableString',
|
||||
'$state', 'OrgAdminLookup', '$rootScope', 'resourceData', InventoriesEdit,
|
||||
'$state', 'OrgAdminLookup', '$rootScope', 'resourceData', 'CreateSelect2', 'InstanceGroupsService', 'InstanceGroupsData', InventoriesEdit,
|
||||
];
|
||||
|
||||
@ -79,6 +79,16 @@ function(i18n, InventoryCompletedJobsList) {
|
||||
credential_type: 13 //insights
|
||||
}
|
||||
},
|
||||
instance_groups: {
|
||||
label: i18n._('Instance Groups'),
|
||||
type: 'select',
|
||||
awPopOver: "<p>" + i18n._("Select the Instance Groups for this Inventory to run on.") + "</p>",
|
||||
dataTitle: i18n._('Instance Groups'),
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
multiSelect: true,
|
||||
ngOptions: 'group.name for group in instanceGroupOptions track by group.id',
|
||||
},
|
||||
inventory_variables: {
|
||||
realName: 'variables',
|
||||
label: i18n._('Variables'),
|
||||
|
||||
@ -357,6 +357,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- IG DETAIL -->
|
||||
<div class="JobResults-resultRow"
|
||||
ng-show="job.instance_group">
|
||||
<label class="JobResults-resultRowLabel">
|
||||
Instance Group
|
||||
</label>
|
||||
<div class="JobResults-resultRowText">
|
||||
{{ job.summary_fields.instance_group.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TAGS DETAIL -->
|
||||
<div class="JobResults-resultRow"
|
||||
ng-show="job.job_tags">
|
||||
|
||||
@ -6,10 +6,9 @@
|
||||
|
||||
export default ['$scope', '$rootScope', '$location', '$stateParams',
|
||||
'OrganizationForm', 'GenerateForm', 'Rest', 'Alert',
|
||||
'ProcessErrors', 'ClearScope', 'GetBasePath', 'Wait','$state',
|
||||
'ProcessErrors', 'ClearScope', 'GetBasePath', 'Wait', 'CreateSelect2', '$state','InstanceGroupsService','InstanceGroupsData',
|
||||
function($scope, $rootScope, $location, $stateParams, OrganizationForm,
|
||||
GenerateForm, Rest, Alert, ProcessErrors, ClearScope, GetBasePath, Wait,
|
||||
$state) {
|
||||
GenerateForm, Rest, Alert, ProcessErrors, ClearScope, GetBasePath, Wait, CreateSelect2, $state, InstanceGroupsService, InstanceGroupsData) {
|
||||
|
||||
Rest.setUrl(GetBasePath('organizations'));
|
||||
Rest.options()
|
||||
@ -24,7 +23,6 @@ export default ['$scope', '$rootScope', '$location', '$stateParams',
|
||||
|
||||
var form = OrganizationForm(),
|
||||
base = $location.path().replace(/^\//, '').split('/')[0];
|
||||
|
||||
init();
|
||||
|
||||
function init(){
|
||||
@ -35,6 +33,13 @@ export default ['$scope', '$rootScope', '$location', '$stateParams',
|
||||
GenerateForm.applyDefaults(form, $scope);
|
||||
}
|
||||
|
||||
$scope.instanceGroupOptions = InstanceGroupsData;
|
||||
CreateSelect2({
|
||||
element: '#organization_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false
|
||||
});
|
||||
|
||||
// Save
|
||||
$scope.formSave = function() {
|
||||
Wait('start');
|
||||
@ -45,16 +50,22 @@ export default ['$scope', '$rootScope', '$location', '$stateParams',
|
||||
name: $scope.name,
|
||||
description: $scope.description
|
||||
})
|
||||
.success(function(data) {
|
||||
Wait('stop');
|
||||
$rootScope.$broadcast("EditIndicatorChange", "organizations", data.id);
|
||||
$state.go('organizations.edit', {organization_id: data.id}, {reload: true});
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to add new organization. Post returned status: ' + status
|
||||
});
|
||||
.then(({data}) => {
|
||||
const organization_id = data.id,
|
||||
instance_group_url = data.related.instance_groups;
|
||||
|
||||
InstanceGroupsService.addInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||
.then(() => {
|
||||
Wait('stop');
|
||||
$rootScope.$broadcast("EditIndicatorChange", "organizations", organization_id);
|
||||
$state.go('organizations.edit', {organization_id: organization_id}, {reload: true});
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to add new organization. Post returned status: ' + status
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -6,18 +6,19 @@
|
||||
|
||||
export default ['$scope', '$location', '$stateParams',
|
||||
'OrganizationForm', 'Rest', 'ProcessErrors', 'Prompt', 'ClearScope',
|
||||
'GetBasePath', 'Wait', '$state', 'ToggleNotification',
|
||||
'GetBasePath', 'Wait', '$state', 'ToggleNotification', 'CreateSelect2', 'InstanceGroupsService', 'InstanceGroupsData',
|
||||
function($scope, $location, $stateParams,
|
||||
OrganizationForm, Rest, ProcessErrors, Prompt, ClearScope,
|
||||
GetBasePath, Wait, $state, ToggleNotification) {
|
||||
GetBasePath, Wait, $state, ToggleNotification, CreateSelect2, InstanceGroupsService, InstanceGroupsData) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
var form = OrganizationForm(),
|
||||
let form = OrganizationForm(),
|
||||
defaultUrl = GetBasePath('organizations'),
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
master = {},
|
||||
id = $stateParams.organization_id;
|
||||
id = $stateParams.organization_id,
|
||||
instance_group_url = defaultUrl + id + '/instance_groups/';
|
||||
|
||||
init();
|
||||
|
||||
@ -30,14 +31,46 @@ export default ['$scope', '$location', '$stateParams',
|
||||
|
||||
$scope.$emit("HideOrgListHeader");
|
||||
$scope.organization_id = id;
|
||||
|
||||
$scope.instanceGroupOptions = InstanceGroupsData;
|
||||
CreateSelect2({
|
||||
element: '#organization_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false
|
||||
});
|
||||
|
||||
Rest.setUrl(instance_group_url);
|
||||
Rest.get()
|
||||
.then(({data}) => {
|
||||
if (data.results.length > 0) {
|
||||
let opts = data.results
|
||||
.map(i => ({id: i.id + "",
|
||||
name: i.name}));
|
||||
CreateSelect2({
|
||||
element: '#organization_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false,
|
||||
opts: opts
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get instance groups. GET returned ' +
|
||||
'status: ' + status
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Retrieve detail record and prepopulate the form
|
||||
Wait('start');
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.get()
|
||||
.success(function(data) {
|
||||
var fld;
|
||||
let fld;
|
||||
|
||||
$scope.organization_name = data.name;
|
||||
for (fld in form.fields) {
|
||||
if (data[fld]) {
|
||||
@ -45,16 +78,11 @@ export default ['$scope', '$location', '$stateParams',
|
||||
master[fld] = data[fld];
|
||||
}
|
||||
}
|
||||
|
||||
$scope.organization_obj = data;
|
||||
$scope.$emit('organizationLoaded');
|
||||
Wait('stop');
|
||||
})
|
||||
.error(function(data, status) {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to retrieve organization: ' + $stateParams.id + '. GET status: ' + status
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$scope.toggleNotification = function(event, id, column) {
|
||||
var notifier = this.notification;
|
||||
@ -82,13 +110,22 @@ export default ['$scope', '$location', '$stateParams',
|
||||
}
|
||||
Rest.setUrl(defaultUrl + id + '/');
|
||||
Rest.put(params)
|
||||
.success(function() {
|
||||
Wait('stop');
|
||||
.then(() => {
|
||||
InstanceGroupsService.editInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||
.then(() => {
|
||||
Wait('stop');
|
||||
$state.go($state.current, {}, { reload: true });
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to update instance groups. POST returned status: ' + status
|
||||
});
|
||||
});
|
||||
$scope.organization_name = $scope.name;
|
||||
master = params;
|
||||
$state.go($state.current, {}, { reload: true });
|
||||
})
|
||||
.error(function(data, status) {
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, OrganizationForm, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to update organization: ' + id + '. PUT status: ' + status
|
||||
|
||||
@ -27,7 +27,23 @@ angular.module('Organizations', [
|
||||
.config(['$stateProvider', 'stateDefinitionsProvider', '$stateExtenderProvider',
|
||||
function($stateProvider, stateDefinitionsProvider, $stateExtenderProvider) {
|
||||
let stateExtender = $stateExtenderProvider.$get(),
|
||||
stateDefinitions = stateDefinitionsProvider.$get();
|
||||
stateDefinitions = stateDefinitionsProvider.$get(),
|
||||
organizationResolve = {
|
||||
InstanceGroupsData: ['Rest', 'GetBasePath', 'ProcessErrors', (Rest, GetBasePath, ProcessErrors) => {
|
||||
const url = GetBasePath('instance_groups');
|
||||
Rest.setUrl(url);
|
||||
return Rest.get()
|
||||
.then(({data}) => {
|
||||
return data.results.map((i) => ({name: i.name, id: i.id}));
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors(null, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get instance groups info. GET returned status: ' + status
|
||||
});
|
||||
});
|
||||
}]
|
||||
};
|
||||
|
||||
// lazily generate a tree of substates which will replace this node in ui-router's stateRegistry
|
||||
// see: stateDefinition.factory for usage documentation
|
||||
@ -55,6 +71,10 @@ angular.module('Organizations', [
|
||||
activityStream: true,
|
||||
activityStreamTarget: 'organization'
|
||||
},
|
||||
resolve: {
|
||||
add: organizationResolve,
|
||||
edit: organizationResolve
|
||||
}
|
||||
// concat manually-defined state definitions with generated defintions
|
||||
}).then((generated) => {
|
||||
let linkoutDefinitions = _.map(OrganizationsLinkoutStates, (state) => stateExtender.buildDefinition(state));
|
||||
|
||||
@ -33,6 +33,16 @@ export default ['NotificationsList', 'i18n',
|
||||
label: i18n._('Description'),
|
||||
type: 'text',
|
||||
ngDisabled: '!(organization_obj.summary_fields.user_capabilities.edit || canAdd)'
|
||||
},
|
||||
instance_groups: {
|
||||
label: i18n._('Instance Groups'),
|
||||
type: 'select',
|
||||
awPopOver: "<p>" + i18n._("Select the Instance Groups for this Organization to run on.") + "</p>",
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
dataTitle: i18n._('Instance Groups'),
|
||||
multiSelect: true,
|
||||
ngOptions: 'group.name for group in instanceGroupOptions track by group.id',
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -56,6 +56,12 @@
|
||||
View and edit your license information.
|
||||
</p>
|
||||
</a>
|
||||
<a ui-sref="instanceGroups" class="SetupItem">
|
||||
<h4 class="SetupItem-title" translate>Instance Groups</h4>
|
||||
<p class="SetupItem-description" translate>
|
||||
View list and capacity of Tower instances.
|
||||
</p>
|
||||
</a>
|
||||
<a ui-sref="configuration" class="SetupItem" ng-if="user_is_superuser || user_is_system_auditor">
|
||||
<h4 class="SetupItem-title" translate>Configure Tower</h4>
|
||||
<p class="SetupItem-description" translate>
|
||||
|
||||
@ -130,7 +130,7 @@
|
||||
*
|
||||
* If the field type is textarea and the name is one of variables, extra_vars, inventory_variables or source_vars, then the parse type radio button group is added. This is the radio button group allowing the user to switch between JSON and YAML.
|
||||
*
|
||||
* Applying CodeMirror to the text area is handled by ParseTypeChange() found in helpers/Parse.js. Within the controller will be a call to ParseTypeChange that creates the CodeMirror object and sets up the required $scope methods for handles getting, settting and type conversion.
|
||||
* Applying CodeMirror to the text area is handled by ParseTypeChange() found in helpers/Parse.js. Within the controller will be a call to ParseTypeChange that creates the CodeMirror object and sets up the required $scope methods for handles getting, setting and type conversion.
|
||||
*/
|
||||
|
||||
import GeneratorHelpers from './generator-helpers';
|
||||
|
||||
@ -243,6 +243,16 @@ function(NotificationsList, CompletedJobsList, i18n) {
|
||||
dataContainer: "body",
|
||||
ngDisabled: '!(job_template_obj.summary_fields.user_capabilities.edit || canAddJobTemplate)'
|
||||
},
|
||||
instance_groups: {
|
||||
label: i18n._('Instance Groups'),
|
||||
type: 'select',
|
||||
awPopOver: "<p>" + i18n._("Select the Instance Groups for this Job Template to run on.") + "</p>",
|
||||
dataContainer: 'body',
|
||||
dataPlacement: 'right',
|
||||
dataTitle: i18n._('Instance Groups'),
|
||||
multiSelect: true,
|
||||
ngOptions: 'group.name for group in instanceGroupOptions track by group.id',
|
||||
},
|
||||
job_tags: {
|
||||
label: i18n._('Job Tags'),
|
||||
type: 'textarea',
|
||||
|
||||
@ -9,13 +9,14 @@
|
||||
'$stateParams', 'JobTemplateForm', 'GenerateForm', 'Rest', 'Alert',
|
||||
'ProcessErrors', 'ClearScope', 'GetBasePath', 'md5Setup', 'ParseTypeChange', 'Wait',
|
||||
'Empty', 'ToJSON', 'CallbackHelpInit', 'GetChoices', '$state',
|
||||
'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project',
|
||||
'CreateSelect2', '$q', 'i18n', 'Inventory', 'Project', 'InstanceGroupsService', 'InstanceGroupsData',
|
||||
function(
|
||||
$filter, $scope,
|
||||
$stateParams, JobTemplateForm, GenerateForm, Rest, Alert,
|
||||
ProcessErrors, ClearScope, GetBasePath, md5Setup, ParseTypeChange, Wait,
|
||||
Empty, ToJSON, CallbackHelpInit, GetChoices,
|
||||
$state, CreateSelect2, $q, i18n, Inventory, Project
|
||||
$state, CreateSelect2, $q, i18n, Inventory, Project, InstanceGroupsService,
|
||||
InstanceGroupsData
|
||||
) {
|
||||
|
||||
Rest.setUrl(GetBasePath('job_templates'));
|
||||
@ -29,7 +30,7 @@
|
||||
|
||||
ClearScope();
|
||||
// Inject dynamic view
|
||||
var defaultUrl = GetBasePath('job_templates'),
|
||||
let defaultUrl = GetBasePath('job_templates'),
|
||||
form = JobTemplateForm(),
|
||||
generator = GenerateForm,
|
||||
master = {},
|
||||
@ -47,6 +48,13 @@
|
||||
$scope.mode = "add";
|
||||
$scope.parseType = 'yaml';
|
||||
|
||||
$scope.instanceGroupOptions = InstanceGroupsData;
|
||||
CreateSelect2({
|
||||
element: '#job_template_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false
|
||||
});
|
||||
|
||||
md5Setup({
|
||||
scope: $scope,
|
||||
master: master,
|
||||
@ -93,7 +101,6 @@
|
||||
element:'#playbook-select',
|
||||
multiple: false
|
||||
});
|
||||
|
||||
CreateSelect2({
|
||||
element:'#job_template_verbosity',
|
||||
multiple: false
|
||||
@ -266,9 +273,10 @@
|
||||
'alert-danger', saveCompleted, null, null,
|
||||
null, true);
|
||||
}
|
||||
|
||||
|
||||
var orgDefer = $q.defer();
|
||||
var associationDefer = $q.defer();
|
||||
|
||||
Rest.setUrl(data.related.labels);
|
||||
|
||||
var currentLabels = Rest.get()
|
||||
@ -433,21 +441,29 @@
|
||||
|
||||
Rest.setUrl(defaultUrl);
|
||||
Rest.post(data)
|
||||
.success(function(data) {
|
||||
$scope.$emit('templateSaveSuccess',
|
||||
data
|
||||
);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form,
|
||||
{
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to add new job ' +
|
||||
'template. POST returned status: ' +
|
||||
status
|
||||
});
|
||||
});
|
||||
.then(({data}) => {
|
||||
$scope.$emit('templateSaveSuccess', data);
|
||||
|
||||
const instance_group_url = data.related.instance_groups;
|
||||
InstanceGroupsService.addInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||
.then(() => {
|
||||
Wait('stop');
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to post instance groups. POST returned ' +
|
||||
'status: ' + status
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to add new job ' +
|
||||
'template. POST returned status: ' + status
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
Wait('stop');
|
||||
Alert("Error", "Error parsing extra variables. " +
|
||||
|
||||
@ -17,14 +17,14 @@ export default
|
||||
'ParseTypeChange', 'Wait',
|
||||
'Empty', 'Prompt', 'ToJSON', 'GetChoices', 'CallbackHelpInit',
|
||||
'InitiatePlaybookRun' , 'initSurvey', '$state', 'CreateSelect2',
|
||||
'ToggleNotification','$q',
|
||||
'ToggleNotification','$q', 'InstanceGroupsService', 'InstanceGroupsData',
|
||||
function(
|
||||
$filter, $scope, $rootScope,
|
||||
$location, $stateParams, JobTemplateForm, GenerateForm, Rest, Alert,
|
||||
ProcessErrors, ClearScope, GetBasePath, md5Setup,
|
||||
ParseTypeChange, Wait,
|
||||
Empty, Prompt, ToJSON, GetChoices, CallbackHelpInit, InitiatePlaybookRun, SurveyControllerInit, $state,
|
||||
CreateSelect2, ToggleNotification, $q
|
||||
CreateSelect2, ToggleNotification, $q, InstanceGroupsService, InstanceGroupsData
|
||||
) {
|
||||
|
||||
ClearScope();
|
||||
@ -35,17 +35,19 @@ export default
|
||||
}
|
||||
});
|
||||
|
||||
var defaultUrl = GetBasePath('job_templates'),
|
||||
let defaultUrl = GetBasePath('job_templates'),
|
||||
generator = GenerateForm,
|
||||
form = JobTemplateForm(),
|
||||
base = $location.path().replace(/^\//, '').split('/')[0],
|
||||
master = {},
|
||||
id = $stateParams.job_template_id,
|
||||
checkSCMStatus, getPlaybooks, callback,
|
||||
choicesCount = 0;
|
||||
choicesCount = 0,
|
||||
instance_group_url = defaultUrl + id + '/instance_groups';
|
||||
|
||||
init();
|
||||
function init(){
|
||||
function init() {
|
||||
|
||||
CallbackHelpInit({ scope: $scope });
|
||||
$scope.playbook_options = null;
|
||||
$scope.playbook = null;
|
||||
@ -53,6 +55,36 @@ export default
|
||||
$scope.parseType = 'yaml';
|
||||
$scope.showJobType = false;
|
||||
|
||||
$scope.instanceGroupOptions = InstanceGroupsData;
|
||||
CreateSelect2({
|
||||
element: '#job_template_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false
|
||||
});
|
||||
|
||||
Rest.setUrl(instance_group_url);
|
||||
Rest.get()
|
||||
.then(({data}) => {
|
||||
if (data.results.length > 0) {
|
||||
let opts = data.results
|
||||
.map(i => ({id: i.id + "",
|
||||
name: i.name}));
|
||||
CreateSelect2({
|
||||
element: '#job_template_instance_groups',
|
||||
multiple: true,
|
||||
addNew: false,
|
||||
opts: opts
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get instance groups. GET returned ' +
|
||||
'status: ' + status
|
||||
});
|
||||
});
|
||||
|
||||
SurveyControllerInit({
|
||||
scope: $scope,
|
||||
parent_scope: $scope,
|
||||
@ -413,6 +445,16 @@ export default
|
||||
'alert-danger', saveCompleted, null, null,
|
||||
null, true);
|
||||
}
|
||||
|
||||
InstanceGroupsService.editInstanceGroups(instance_group_url, $scope.instance_groups)
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors($scope, data, status, form, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to update instance groups. POST returned status: ' + status
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var orgDefer = $q.defer();
|
||||
var associationDefer = $q.defer();
|
||||
var associatedLabelsDefer = $q.defer();
|
||||
|
||||
@ -46,7 +46,24 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
|
||||
let stateTree, addJobTemplate, editJobTemplate, addWorkflow, editWorkflow,
|
||||
workflowMaker, inventoryLookup, credentialLookup,
|
||||
stateDefinitions = stateDefinitionsProvider.$get(),
|
||||
stateExtender = $stateExtenderProvider.$get();
|
||||
stateExtender = $stateExtenderProvider.$get(),
|
||||
instanceGroupsResolve = {
|
||||
InstanceGroupsData: ['Rest', 'GetBasePath', 'ProcessErrors', (Rest, GetBasePath, ProcessErrors) => {
|
||||
const url = GetBasePath('instance_groups');
|
||||
Rest.setUrl(url);
|
||||
return Rest.get()
|
||||
.then(({data}) => {
|
||||
return data.results.map((i) => ({name: i.name, id: i.id}));
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors(null, data, status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get instance groups info. GET returned status: ' + status
|
||||
});
|
||||
});
|
||||
}]
|
||||
};
|
||||
|
||||
|
||||
function generateStateTree() {
|
||||
|
||||
@ -85,7 +102,8 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
|
||||
});
|
||||
});
|
||||
}
|
||||
}]
|
||||
}],
|
||||
InstanceGroupsData: instanceGroupsResolve.InstanceGroupsData
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -105,6 +123,9 @@ angular.module('templates', [surveyMaker.name, templatesList.name, jobTemplatesA
|
||||
activityStream: true,
|
||||
activityStreamTarget: 'job_template',
|
||||
activityStreamId: 'job_template_id'
|
||||
},
|
||||
resolve: {
|
||||
edit: instanceGroupsResolve
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user