mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 18:09:57 -03:30
update adhoc feature, add tests and modularize
This commit is contained in:
parent
5727d722b6
commit
7fd24987d7
317
awx/ui/client/src/adhoc/adhoc.controller.js
Normal file
317
awx/ui/client/src/adhoc/adhoc.controller.js
Normal file
@ -0,0 +1,317 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name controllers.function:Adhoc
|
||||
* @description This controller controls the adhoc form creation, command launching and navigating to standard out after command has been succesfully ran.
|
||||
*/
|
||||
function adhocController($q, $scope, $rootScope, $location, $routeParams,
|
||||
CheckPasswords, PromptForPasswords, CreateLaunchDialog, adhocForm,
|
||||
GenerateForm, Rest, ProcessErrors, ClearScope, GetBasePath, GetChoices,
|
||||
KindChange, LookUpInit, CredentialList, Empty, Wait) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
// this is done so that we can access private functions for testing, but
|
||||
// we don't want to populate the "public" scope with these internal
|
||||
// functions
|
||||
var privateFn = {};
|
||||
this.privateFn = privateFn;
|
||||
|
||||
// note: put any urls that the controller will use in here!!!!
|
||||
privateFn.setAvailableUrls = function() {
|
||||
return {
|
||||
adhocUrl: GetBasePath('inventory') + id + '/ad_hoc_commands/',
|
||||
inventoryUrl: GetBasePath('inventory') + id + '/',
|
||||
machineCredentialUrl: GetBasePath('credentials') + '?kind=ssh'
|
||||
};
|
||||
};
|
||||
|
||||
var id = $routeParams.inventory_id,
|
||||
urls = privateFn.setAvailableUrls(),
|
||||
hostPattern = $rootScope.hostPatterns || "all";
|
||||
|
||||
// set the default options for the selects of the adhoc form
|
||||
privateFn.setFieldDefaults = function(verbosity_options, forks_default) {
|
||||
var verbosity;
|
||||
for (verbosity in verbosity_options) {
|
||||
if (verbosity_options[verbosity].isDefault) {
|
||||
$scope.verbosity = verbosity_options[verbosity];
|
||||
}
|
||||
}
|
||||
$("#forks-number").spinner("value", forks_default);
|
||||
$scope.forks = forks_default;
|
||||
};
|
||||
|
||||
// set when "working" starts and stops
|
||||
privateFn.setLoadingStartStop = function() {
|
||||
var asyncHelper = {},
|
||||
formReadyPromise = 0;
|
||||
|
||||
Wait('start');
|
||||
|
||||
if (asyncHelper.removeChoicesReady) {
|
||||
asyncHelper.removeChoicesReady();
|
||||
}
|
||||
asyncHelper.removeChoicesReady = $scope.$on('adhocFormReady',
|
||||
isFormDone);
|
||||
|
||||
// check to see if all requests have completed
|
||||
function isFormDone() {
|
||||
formReadyPromise++;
|
||||
|
||||
if (formReadyPromise === 2) {
|
||||
privateFn.setFieldDefaults($scope.adhoc_verbosity_options,
|
||||
$scope.forks_field.default);
|
||||
Wait('stop');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
privateFn.getInventoryNameForBreadcrumbs = function(url) {
|
||||
|
||||
Rest.setUrl(url);
|
||||
var promise = Rest.get();
|
||||
promise.then(function (response) {
|
||||
$scope.inv_name = response.data.name;
|
||||
});
|
||||
promise.catch(function (response) {
|
||||
ProcessErrors($rootScope, response.data, response.status, null, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get inventory name. GET returned status: ' +
|
||||
response.status });
|
||||
$location.path("/inventories/");
|
||||
});
|
||||
return promise;
|
||||
};
|
||||
|
||||
// set the arguments help to watch on change of the module
|
||||
privateFn.instantiateArgumentHelp = function() {
|
||||
$scope.$watch('module_name', function(val) {
|
||||
if (val) {
|
||||
// give the docs for the selected module in the popover
|
||||
$scope.argsPopOver = '<p>These arguments are used with the ' +
|
||||
'specified module. You can find information about the ' +
|
||||
val.value + ' module <a ' +
|
||||
'id=\"adhoc_module_arguments_docs_link_for_module_' +
|
||||
val.value + '\" href=\"http://docs.ansible.com/' +
|
||||
val.value + '_module.html\" ' +
|
||||
'target=\"_blank\">here</a>.</p>';
|
||||
} else {
|
||||
// no module selected
|
||||
$scope.argsPopOver = "<p>These arguments are used with the" +
|
||||
" specified module.</p>";
|
||||
}
|
||||
}, true);
|
||||
|
||||
// initially set to the same as no module selected
|
||||
$scope.argsPopOver = "<p>These arguments are used with the " +
|
||||
"specified module.</p>";
|
||||
};
|
||||
|
||||
// pre-populate host patterns from the inventory page and
|
||||
// delete the value off of rootScope
|
||||
privateFn.instantiateHostPatterns = function(hostPattern) {
|
||||
$scope.limit = hostPattern;
|
||||
$scope.providedHostPatterns = $scope.limit;
|
||||
delete $rootScope.hostPatterns;
|
||||
};
|
||||
|
||||
// call helpers to initialize lookup and select fields through get
|
||||
// requests
|
||||
privateFn.initializeFields = function(machineCredentialUrl, adhocUrl) {
|
||||
// setup machine credential lookup
|
||||
LookUpInit({
|
||||
url: machineCredentialUrl,
|
||||
scope: $scope,
|
||||
form: adhocForm,
|
||||
current_item: (!Empty($scope.credential_id)) ?
|
||||
$scope.credential_id : null,
|
||||
list: CredentialList,
|
||||
field: 'credential',
|
||||
input_type: 'radio'
|
||||
});
|
||||
|
||||
// setup module name select
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: adhocUrl,
|
||||
field: 'module_name',
|
||||
variable: 'adhoc_module_options',
|
||||
callback: 'adhocFormReady'
|
||||
});
|
||||
|
||||
// setup verbosity options select
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: adhocUrl,
|
||||
field: 'verbosity',
|
||||
variable: 'adhoc_verbosity_options',
|
||||
callback: 'adhocFormReady'
|
||||
});
|
||||
};
|
||||
|
||||
// instantiate all variables on scope for display in the partial
|
||||
privateFn.initializeForm = function(id, urls, hostPattern) {
|
||||
// inject the adhoc command form
|
||||
GenerateForm.inject(adhocForm,
|
||||
{ mode: 'edit', related: true, scope: $scope });
|
||||
|
||||
// set when "working" starts and stops
|
||||
privateFn.setLoadingStartStop();
|
||||
|
||||
// put the inventory id on scope for the partial to use
|
||||
$scope.inv_id = id;
|
||||
|
||||
// get the inventory name
|
||||
privateFn.getInventoryNameForBreadcrumbs(urls.inventoryUrl);
|
||||
|
||||
// set the arguments help to watch on change of the module
|
||||
privateFn.instantiateArgumentHelp();
|
||||
|
||||
// pre-populate host patterns from the inventory page and
|
||||
// delete the value off of rootScope
|
||||
privateFn.instantiateHostPatterns(hostPattern);
|
||||
|
||||
privateFn.initializeFields(urls.machineCredentialUrl, urls.adhocUrl);
|
||||
};
|
||||
|
||||
privateFn.initializeForm(id, urls, hostPattern);
|
||||
|
||||
// remove all data input into the form and reset the form back to defaults
|
||||
$scope.formReset = function () {
|
||||
GenerateForm.reset();
|
||||
|
||||
// pre-populate host patterns from the inventory page and
|
||||
// delete the value off of rootScope
|
||||
privateFn.instantiateHostPatterns($scope.providedHostPatterns);
|
||||
|
||||
KindChange({ scope: $scope, form: adhocForm, reset: false });
|
||||
|
||||
// set the default options for the selects of the adhoc form
|
||||
privateFn.setFieldDefaults($scope.adhoc_verbosity_options,
|
||||
$scope.forks_default);
|
||||
};
|
||||
|
||||
// launch the job with the provided form data
|
||||
$scope.launchJob = function () {
|
||||
var adhocUrl = GetBasePath('inventory') + $routeParams.inventory_id +
|
||||
'/ad_hoc_commands/', fld, data={}, html;
|
||||
|
||||
html = '<form class="ng-valid ng-valid-required" ' +
|
||||
'name="job_launch_form" id="job_launch_form" autocomplete="off" ' +
|
||||
'nonvalidate>';
|
||||
|
||||
// stub the payload with defaults from DRF
|
||||
data = {
|
||||
"job_type": "run",
|
||||
"limit": "",
|
||||
"credential": null,
|
||||
"module_name": "command",
|
||||
"module_args": "",
|
||||
"forks": 0,
|
||||
"verbosity": 0,
|
||||
"privilege_escalation": ""
|
||||
};
|
||||
|
||||
GenerateForm.clearApiErrors();
|
||||
|
||||
// populate data with the relevant form values
|
||||
for (fld in adhocForm.fields) {
|
||||
if (adhocForm.fields[fld].type === 'select') {
|
||||
data[fld] = $scope[fld].value;
|
||||
} else {
|
||||
data[fld] = $scope[fld];
|
||||
}
|
||||
}
|
||||
|
||||
Wait('start');
|
||||
|
||||
if ($scope.removeStartAdhocRun) {
|
||||
$scope.removeStartAdhocRun();
|
||||
}
|
||||
$scope.removeStartAdhocRun = $scope.$on('StartAdhocRun', function() {
|
||||
var password;
|
||||
for (password in $scope.passwords) {
|
||||
data[$scope.passwords[password]] = $scope[
|
||||
$scope.passwords[password]
|
||||
];
|
||||
}
|
||||
// Launch the adhoc job
|
||||
Rest.setUrl(GetBasePath('inventory') +
|
||||
$routeParams.inventory_id + '/ad_hoc_commands/');
|
||||
Rest.post(data)
|
||||
.success(function (data) {
|
||||
Wait('stop');
|
||||
$location.path("/ad_hoc_commands/" + data.id);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, adhocForm, {
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to launch adhoc command. POST ' +
|
||||
'returned status: ' + status });
|
||||
});
|
||||
});
|
||||
|
||||
if ($scope.removeCreateLaunchDialog) {
|
||||
$scope.removeCreateLaunchDialog();
|
||||
}
|
||||
$scope.removeCreateLaunchDialog = $scope.$on('CreateLaunchDialog',
|
||||
function(e, html, url) {
|
||||
CreateLaunchDialog({
|
||||
scope: $scope,
|
||||
html: html,
|
||||
url: url,
|
||||
callback: 'StartAdhocRun'
|
||||
});
|
||||
});
|
||||
|
||||
if ($scope.removePromptForPasswords) {
|
||||
$scope.removePromptForPasswords();
|
||||
}
|
||||
$scope.removePromptForPasswords = $scope.$on('PromptForPasswords',
|
||||
function(e, passwords_needed_to_start,html, url) {
|
||||
PromptForPasswords({ scope: $scope,
|
||||
passwords: passwords_needed_to_start,
|
||||
callback: 'CreateLaunchDialog',
|
||||
html: html,
|
||||
url: url
|
||||
});
|
||||
});
|
||||
|
||||
if ($scope.removeContinueCred) {
|
||||
$scope.removeContinueCred();
|
||||
}
|
||||
$scope.removeContinueCred = $scope.$on('ContinueCred', function(e,
|
||||
passwords) {
|
||||
if(passwords.length>0){
|
||||
$scope.passwords_needed_to_start = passwords;
|
||||
// only go through the password prompting steps if there are
|
||||
// passwords to prompt for
|
||||
$scope.$emit('PromptForPasswords', passwords, html, adhocUrl);
|
||||
} else {
|
||||
// if not, go straight to trying to run the job.
|
||||
$scope.$emit('StartAdhocRun', adhocUrl);
|
||||
}
|
||||
});
|
||||
|
||||
// start adhoc launching routine
|
||||
CheckPasswords({
|
||||
scope: $scope,
|
||||
credential: $scope.credential,
|
||||
callback: 'ContinueCred'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default ['$q', '$scope', '$rootScope', '$location', '$routeParams',
|
||||
'CheckPasswords', 'PromptForPasswords', 'CreateLaunchDialog', 'adhocForm',
|
||||
'GenerateForm', 'Rest', 'ProcessErrors', 'ClearScope', 'GetBasePath',
|
||||
'GetChoices', 'KindChange', 'LookUpInit', 'CredentialList', 'Empty', 'Wait',
|
||||
adhocController];
|
||||
143
awx/ui/client/src/adhoc/adhoc.form.js
Normal file
143
awx/ui/client/src/adhoc/adhoc.form.js
Normal file
@ -0,0 +1,143 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name forms.function:Adhoc
|
||||
* @description This form is for executing an adhoc command
|
||||
*/
|
||||
|
||||
export default function() {
|
||||
return {
|
||||
editTitle: 'Execute Command',
|
||||
name: 'adhoc',
|
||||
well: true,
|
||||
forceListeners: true,
|
||||
|
||||
fields: {
|
||||
module_name: {
|
||||
label: 'Module',
|
||||
excludeModal: true,
|
||||
type: 'select',
|
||||
ngOptions: 'module.label for module in adhoc_module_options' +
|
||||
' track by module.value',
|
||||
ngChange: 'moduleChange()',
|
||||
editRequired: true,
|
||||
awPopOver:'<p>These are the modules that Tower supports ' +
|
||||
'running commands against.',
|
||||
dataTitle: 'Module',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body'
|
||||
},
|
||||
module_args: {
|
||||
label: 'Arguments',
|
||||
type: 'text',
|
||||
awPopOverWatch: 'argsPopOver',
|
||||
awPopOver: '{{ argsPopOver }}',
|
||||
dataTitle: 'Arguments',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
editRequired: false,
|
||||
autocomplete: false
|
||||
},
|
||||
limit: {
|
||||
label: 'Host Pattern',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>The pattern used to target hosts in the ' +
|
||||
'inventory. Leaving the field blank, all, and * will ' +
|
||||
'all target all hosts in the inventory. You can find ' +
|
||||
'more information about Ansible\'s host patterns ' +
|
||||
'<a id=\"adhoc_form_hostpatterns_doc_link\"' +
|
||||
'href=\"http://docs.ansible.com/intro_patterns.html\" ' +
|
||||
'target=\"_blank\">here</a>.</p>',
|
||||
dataTitle: 'Host Pattern',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body'
|
||||
},
|
||||
credential: {
|
||||
label: 'Machine Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
class: 'squeeze',
|
||||
awPopOver: '<p>Select the credential you want to use when ' +
|
||||
'accessing the remote hosts to run the command. ' +
|
||||
'Choose the credential containing ' +
|
||||
'the username and SSH key or password that Ansbile ' +
|
||||
'will need to log into the remote hosts.</p>',
|
||||
dataTitle: 'Credential',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
awRequiredWhen: {
|
||||
variable: 'credRequired',
|
||||
init: 'false'
|
||||
}
|
||||
},
|
||||
become_enabled: {
|
||||
label: 'Enable Privilege Escalation',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
column: 2,
|
||||
awPopOver: "<p>If enabled, run this playbook as an administrator. This is the equivalent of passing the<code> --become</code> option to the <code> ansible</code> command. </p>",
|
||||
dataPlacement: 'right',
|
||||
dataTitle: 'Become Privilege Escalation',
|
||||
dataContainer: "body"
|
||||
},
|
||||
verbosity: {
|
||||
label: 'Verbosity',
|
||||
excludeModal: true,
|
||||
type: 'select',
|
||||
ngOptions: 'verbosity.label for verbosity in ' +
|
||||
'adhoc_verbosity_options ' +
|
||||
'track by verbosity.value',
|
||||
editRequired: true,
|
||||
awPopOver:'<p>These are the verbosity levels for standard ' +
|
||||
'out of the command run that are supported.',
|
||||
dataTitle: 'Module',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
"default": 1
|
||||
},
|
||||
forks: {
|
||||
label: 'Forks',
|
||||
id: 'forks-number',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
min: 0,
|
||||
spinner: true,
|
||||
"default": 0,
|
||||
addRequired: false,
|
||||
editRequired: true,
|
||||
'class': "input-small",
|
||||
column: 1,
|
||||
awPopOver: '<p>The number of parallel or simultaneous processes to use while executing the command. 0 signifies ' +
|
||||
'the default value from the <a id="ansible_forks_docs" href=\"http://docs.ansible.com/intro_configuration.html#the-ansible-configuration-file\" ' +
|
||||
' target=\"_blank\">ansible configuration file</a>.</p>',
|
||||
dataTitle: 'Forks',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
|
||||
buttons: {
|
||||
launch: {
|
||||
label: 'Launch',
|
||||
ngClick: 'launchJob()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
related: {}
|
||||
};
|
||||
}
|
||||
19
awx/ui/client/src/adhoc/adhoc.route.js
Normal file
19
awx/ui/client/src/adhoc/adhoc.route.js
Normal file
@ -0,0 +1,19 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
import {templateUrl} from '../shared/template-url/template-url.factory';
|
||||
|
||||
export default {
|
||||
route: '/inventories/:inventory_id/adhoc',
|
||||
name: 'inventoryAdhoc',
|
||||
templateUrl: templateUrl('adhoc/adhoc'),
|
||||
controller: 'adhocController',
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
};
|
||||
12
awx/ui/client/src/adhoc/main.js
Normal file
12
awx/ui/client/src/adhoc/main.js
Normal file
@ -0,0 +1,12 @@
|
||||
import route from './adhoc.route';
|
||||
import adhocController from './adhoc.controller';
|
||||
import form from './adhoc.form';
|
||||
|
||||
export default angular.module('adhoc', ["ngRoute"])
|
||||
.controller('adhocController', adhocController)
|
||||
.config(['$routeProvider', function($routeProvider) {
|
||||
var url = route.route;
|
||||
delete route.route;
|
||||
$routeProvider.when(url, route);
|
||||
}])
|
||||
.factory('adhocForm', form);
|
||||
@ -43,6 +43,7 @@ import browserData from './browser-data/main';
|
||||
import dashboard from './dashboard/main';
|
||||
import moment from './shared/moment/main';
|
||||
import templateUrl from './shared/template-url/main';
|
||||
import adhoc from './adhoc/main';
|
||||
|
||||
import {JobDetailController} from './controllers/JobDetail';
|
||||
import {JobStdoutController} from './controllers/JobStdout';
|
||||
@ -52,7 +53,6 @@ import {ScheduleEditController} from './controllers/Schedules';
|
||||
import {ProjectsList, ProjectsAdd, ProjectsEdit} from './controllers/Projects';
|
||||
import {OrganizationsList, OrganizationsAdd, OrganizationsEdit} from './controllers/Organizations';
|
||||
import {InventoriesList, InventoriesAdd, InventoriesEdit, InventoriesManage} from './controllers/Inventories';
|
||||
import {AdhocCtrl} from './controllers/Adhoc';
|
||||
import {AdminsList} from './controllers/Admins';
|
||||
import {UsersList, UsersAdd, UsersEdit} from './controllers/Users';
|
||||
import {TeamsList, TeamsAdd, TeamsEdit} from './controllers/Teams';
|
||||
@ -93,6 +93,7 @@ var tower = angular.module('Tower', [
|
||||
dashboard.name,
|
||||
moment.name,
|
||||
templateUrl.name,
|
||||
adhoc.name,
|
||||
'templates',
|
||||
'AuthService',
|
||||
'Utilities',
|
||||
@ -112,7 +113,6 @@ var tower = angular.module('Tower', [
|
||||
'RefreshHelper',
|
||||
'AdminListDefinition',
|
||||
'AWDirectives',
|
||||
'AdhocFormDefinition',
|
||||
'InventoriesListDefinition',
|
||||
'InventoryFormDefinition',
|
||||
'InventoryHelper',
|
||||
@ -182,9 +182,6 @@ var tower = angular.module('Tower', [
|
||||
'SocketHelper',
|
||||
'AboutAnsibleHelpModal',
|
||||
'PortalJobsListDefinition',
|
||||
|
||||
|
||||
'AdhocHelper',
|
||||
'features',
|
||||
'longDateFilter'
|
||||
])
|
||||
@ -468,17 +465,6 @@ var tower = angular.module('Tower', [
|
||||
}
|
||||
}).
|
||||
|
||||
when('/inventories/:inventory_id/adhoc', {
|
||||
name: 'inventoryAdhoc',
|
||||
templateUrl: urlPrefix + 'partials/adhoc.html',
|
||||
controller: AdhocCtrl,
|
||||
resolve: {
|
||||
features: ['FeaturesService', function(FeaturesService) {
|
||||
return FeaturesService.get();
|
||||
}]
|
||||
}
|
||||
}).
|
||||
|
||||
when('/organizations', {
|
||||
name: 'organizations',
|
||||
templateUrl: urlPrefix + 'partials/organizations.html',
|
||||
|
||||
@ -1,248 +0,0 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name controllers.function:Adhoc
|
||||
* @description This controller controls the adhoc form creation, command launching and navigating to standard out after command has been succesfully ran.
|
||||
*/
|
||||
export function AdhocCtrl($scope, $rootScope, $location, $routeParams,
|
||||
CheckPasswords, PromptForPasswords, CreateLaunchDialog, AdhocForm, GenerateForm, Rest, ProcessErrors, ClearScope,
|
||||
GetBasePath, GetChoices, KindChange, LookUpInit, CredentialList, Empty,
|
||||
Wait) {
|
||||
|
||||
ClearScope();
|
||||
|
||||
var url = GetBasePath('inventory') + $routeParams.inventory_id +
|
||||
'/ad_hoc_commands/',
|
||||
generator = GenerateForm,
|
||||
form = AdhocForm,
|
||||
master = {},
|
||||
id = $routeParams.inventory_id,
|
||||
choicesReadyCount = 0,
|
||||
data;
|
||||
|
||||
$scope.inv_id = id;
|
||||
|
||||
Rest.setUrl(GetBasePath('inventory') + $routeParams.inventory_id + '/');
|
||||
Rest.get(data)
|
||||
.success(function (data) {
|
||||
$scope.inv_name = data.name;
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to get inventory name. POST returned ' +
|
||||
'status: ' + status });
|
||||
});
|
||||
|
||||
// inject the adhoc command form
|
||||
generator.inject(form, { mode: 'edit', related: true, scope: $scope });
|
||||
generator.reset();
|
||||
|
||||
// BEGIN: populate scope with the things needed to make the adhoc form
|
||||
// display
|
||||
Wait('start');
|
||||
$scope.id = id;
|
||||
$scope.argsPopOver = "<p>These arguments are used with the" +
|
||||
" specified module.</p>";
|
||||
|
||||
// fix arguments help popover based on the module selected
|
||||
$scope.moduleChange = function () {
|
||||
// NOTE: for selenium testing link -
|
||||
// link will be displayed with id adhoc_module_arguments_docs_link
|
||||
// only when a module is selected
|
||||
if ($scope.module_name) {
|
||||
// give the docs for the selected module
|
||||
$scope.argsPopOver = "<p>These arguments are used with the" +
|
||||
" specified module. You can find information about the " +
|
||||
$scope.module_name.value + " module " +
|
||||
" <a id=\"adhoc_module_arguments_docs_link_for_module_" +
|
||||
$scope.module_name.value +
|
||||
"\"" +
|
||||
" href=\"http://docs.ansible.com/" + $scope.module_name.value +
|
||||
"_module.html\" target=\"_blank\">here</a>.</p>";
|
||||
} else {
|
||||
// no module selected
|
||||
$scope.argsPopOver = "<p>These arguments are used with the" +
|
||||
" specified module.</p>";
|
||||
}
|
||||
};
|
||||
|
||||
// pre-populate hostPatterns from the inventory page and
|
||||
// delete the value off of rootScope
|
||||
$scope.limit = $rootScope.hostPatterns || "all";
|
||||
$scope.providedHostPatterns = $scope.limit;
|
||||
delete $rootScope.hostPatterns;
|
||||
|
||||
LookUpInit({
|
||||
url: GetBasePath('credentials') + '?kind=ssh',
|
||||
scope: $scope,
|
||||
form: form,
|
||||
current_item: (!Empty($scope.credential_id)) ? $scope.credential_id : null,
|
||||
list: CredentialList,
|
||||
field: 'credential',
|
||||
input_type: 'radio'
|
||||
});
|
||||
|
||||
if ($scope.removeChoicesReady) {
|
||||
$scope.removeChoicesReady();
|
||||
}
|
||||
$scope.removeChoicesReady = $scope.$on('choicesReadyAdhoc', function () {
|
||||
choicesReadyCount++;
|
||||
|
||||
if (choicesReadyCount === 2) {
|
||||
var verbosity;
|
||||
// this sets the default options for the selects as specified by the controller.
|
||||
for (verbosity in $scope.adhoc_verbosity_options) {
|
||||
if ($scope.adhoc_verbosity_options[verbosity].isDefault) {
|
||||
$scope.verbosity = $scope.adhoc_verbosity_options[verbosity];
|
||||
}
|
||||
}
|
||||
$("#forks-number").spinner("value", $scope.forks_field.default);
|
||||
$scope.forks = $scope.forks_field.default;
|
||||
Wait('stop'); // END: form population
|
||||
}
|
||||
});
|
||||
|
||||
// setup Machine Credential lookup
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: url,
|
||||
field: 'module_name',
|
||||
variable: 'adhoc_module_options',
|
||||
callback: 'choicesReadyAdhoc'
|
||||
});
|
||||
|
||||
// setup verbosity options lookup
|
||||
GetChoices({
|
||||
scope: $scope,
|
||||
url: url,
|
||||
field: 'verbosity',
|
||||
variable: 'adhoc_verbosity_options',
|
||||
callback: 'choicesReadyAdhoc'
|
||||
});
|
||||
|
||||
// launch the job with the provided form data
|
||||
$scope.launchJob = function () {
|
||||
var fld, data={}, html;
|
||||
|
||||
html = '<form class="ng-valid ng-valid-required" name="job_launch_form"' +
|
||||
'id="job_launch_form" autocomplete="off" nonvalidate>';
|
||||
|
||||
// stub the payload with defaults from DRF
|
||||
data = {
|
||||
"job_type": "run",
|
||||
"limit": "",
|
||||
"credential": null,
|
||||
"module_name": "command",
|
||||
"module_args": "",
|
||||
"forks": 0,
|
||||
"verbosity": 0,
|
||||
"privilege_escalation": ""
|
||||
};
|
||||
|
||||
generator.clearApiErrors();
|
||||
|
||||
// populate data with the relevant form values
|
||||
for (fld in form.fields) {
|
||||
if (form.fields[fld].type === 'select') {
|
||||
data[fld] = $scope[fld].value;
|
||||
} else {
|
||||
data[fld] = $scope[fld];
|
||||
}
|
||||
}
|
||||
|
||||
Wait('start');
|
||||
|
||||
if ($scope.removeStartAdhocRun) {
|
||||
$scope.removeStartAdhocRun();
|
||||
}
|
||||
$scope.removeStartAdhocRun = $scope.$on('StartAdhocRun', function() {
|
||||
var password;
|
||||
for (password in $scope.passwords) {
|
||||
data[$scope.passwords[password]] = $scope[$scope.passwords[password]];
|
||||
}
|
||||
// Launch the adhoc job
|
||||
Rest.setUrl(GetBasePath('inventory') +
|
||||
$routeParams.inventory_id + '/ad_hoc_commands/');
|
||||
Rest.post(data)
|
||||
.success(function (data) {
|
||||
Wait('stop');
|
||||
$location.path("/ad_hoc_commands/" + data.id);
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to launch adhoc command. POST returned ' +
|
||||
'status: ' + status });
|
||||
});
|
||||
});
|
||||
|
||||
if ($scope.removeCreateLaunchDialog) {
|
||||
$scope.removeCreateLaunchDialog();
|
||||
}
|
||||
$scope.removeCreateLaunchDialog = $scope.$on('CreateLaunchDialog',
|
||||
function(e, html, url) {
|
||||
CreateLaunchDialog({
|
||||
scope: $scope,
|
||||
html: html,
|
||||
url: url,
|
||||
callback: 'StartAdhocRun'
|
||||
});
|
||||
});
|
||||
|
||||
if ($scope.removePromptForPasswords) {
|
||||
$scope.removePromptForPasswords();
|
||||
}
|
||||
$scope.removePromptForPasswords = $scope.$on('PromptForPasswords', function(e, passwords_needed_to_start,html, url) {
|
||||
PromptForPasswords({ scope: $scope,
|
||||
passwords: passwords_needed_to_start,
|
||||
callback: 'CreateLaunchDialog',
|
||||
html: html,
|
||||
url: url
|
||||
});
|
||||
});
|
||||
|
||||
if ($scope.removeContinueCred) {
|
||||
$scope.removeContinueCred();
|
||||
}
|
||||
$scope.removeContinueCred = $scope.$on('ContinueCred', function(e, passwords) {
|
||||
if(passwords.length>0){
|
||||
$scope.passwords_needed_to_start = passwords;
|
||||
// only go through the password prompting steps if there are
|
||||
// passwords to prompt for
|
||||
$scope.$emit('PromptForPasswords', passwords, html, url);
|
||||
} else {
|
||||
// if not, go straight to trying to run the job.
|
||||
$scope.$emit('StartAdhocRun', url);
|
||||
}
|
||||
});
|
||||
|
||||
// start adhoc launching routine
|
||||
CheckPasswords({
|
||||
scope: $scope,
|
||||
credential: $scope.credential,
|
||||
callback: 'ContinueCred'
|
||||
});
|
||||
};
|
||||
|
||||
// Remove all data input into the form
|
||||
$scope.formReset = function () {
|
||||
generator.reset();
|
||||
for (var fld in master) {
|
||||
$scope[fld] = master[fld];
|
||||
}
|
||||
$scope.limit = $scope.providedHostPatterns;
|
||||
KindChange({ scope: $scope, form: form, reset: false });
|
||||
$scope.verbosity = $scope.adhoc_verbosity_options[$scope.verbosity_field.default];
|
||||
$("#forks-number").spinner("value", $scope.forks_field.default);
|
||||
$scope.forks = $scope.forks_field.default;
|
||||
};
|
||||
}
|
||||
|
||||
AdhocCtrl.$inject = ['$scope', '$rootScope', '$location', '$routeParams',
|
||||
'CheckPasswords', 'PromptForPasswords', 'CreateLaunchDialog', 'AdhocForm',
|
||||
'GenerateForm', 'Rest', 'ProcessErrors', 'ClearScope', 'GetBasePath',
|
||||
'GetChoices', 'KindChange', 'LookUpInit', 'CredentialList', 'Empty', 'Wait'];
|
||||
@ -6,7 +6,6 @@
|
||||
|
||||
import ActivityDetail from "./forms/ActivityDetail";
|
||||
import Credentials from "./forms/Credentials";
|
||||
import Adhoc from "./forms/Adhoc";
|
||||
import EventsViewer from "./forms/EventsViewer";
|
||||
import Groups from "./forms/Groups";
|
||||
import HostGroups from "./forms/HostGroups";
|
||||
@ -33,7 +32,6 @@ import Users from "./forms/Users";
|
||||
export
|
||||
{ ActivityDetail,
|
||||
Credentials,
|
||||
Adhoc,
|
||||
EventsViewer,
|
||||
Groups,
|
||||
HostGroups,
|
||||
|
||||
@ -1,143 +0,0 @@
|
||||
/*************************************************
|
||||
* Copyright (c) 2015 Ansible, Inc.
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name forms.function:Adhoc
|
||||
* @description This form is for executing an adhoc command
|
||||
*/
|
||||
|
||||
export default
|
||||
angular.module('AdhocFormDefinition', [])
|
||||
.value('AdhocForm', {
|
||||
editTitle: 'Execute Command',
|
||||
name: 'adhoc',
|
||||
well: true,
|
||||
forceListeners: true,
|
||||
|
||||
fields: {
|
||||
module_name: {
|
||||
label: 'Module',
|
||||
excludeModal: true,
|
||||
type: 'select',
|
||||
ngOptions: 'module.label for module in adhoc_module_options' +
|
||||
' track by module.value',
|
||||
ngChange: 'moduleChange()',
|
||||
editRequired: true,
|
||||
awPopOver:'<p>These are the modules that Tower supports ' +
|
||||
'running commands against.',
|
||||
dataTitle: 'Module',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body'
|
||||
},
|
||||
module_args: {
|
||||
label: 'Arguments',
|
||||
type: 'text',
|
||||
awPopOverWatch: 'argsPopOver',
|
||||
awPopOver: '{{ argsPopOver }}',
|
||||
dataTitle: 'Arguments',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
editRequired: false,
|
||||
autocomplete: false
|
||||
},
|
||||
limit: {
|
||||
label: 'Host Pattern',
|
||||
type: 'text',
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
awPopOver: '<p>The pattern used to target hosts in the ' +
|
||||
'inventory. Leaving the field blank, all, and * will ' +
|
||||
'all target all hosts in the inventory. You can find ' +
|
||||
'more information about Ansible\'s host patterns ' +
|
||||
'<a id=\"adhoc_form_hostpatterns_doc_link\"' +
|
||||
'href=\"http://docs.ansible.com/intro_patterns.html\" ' +
|
||||
'target=\"_blank\">here</a>.</p>',
|
||||
dataTitle: 'Host Pattern',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body'
|
||||
},
|
||||
credential: {
|
||||
label: 'Machine Credential',
|
||||
type: 'lookup',
|
||||
sourceModel: 'credential',
|
||||
sourceField: 'name',
|
||||
ngClick: 'lookUpCredential()',
|
||||
class: 'squeeze',
|
||||
awPopOver: '<p>Select the credential you want to use when ' +
|
||||
'accessing the remote hosts to run the command. ' +
|
||||
'Choose the credential containing ' +
|
||||
'the username and SSH key or password that Ansbile ' +
|
||||
'will need to log into the remote hosts.</p>',
|
||||
dataTitle: 'Credential',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
awRequiredWhen: {
|
||||
variable: 'credRequired',
|
||||
init: 'false'
|
||||
}
|
||||
},
|
||||
become_enabled: {
|
||||
label: 'Enable Privilege Escalation',
|
||||
type: 'checkbox',
|
||||
addRequired: false,
|
||||
editRequird: false,
|
||||
column: 2,
|
||||
awPopOver: "<p>If enabled, run this playbook as an administrator. This is the equivalent of passing the<code> --become</code> option to the <code> ansible</code> command. </p>",
|
||||
dataPlacement: 'right',
|
||||
dataTitle: 'Become Privilege Escalation',
|
||||
dataContainer: "body"
|
||||
},
|
||||
verbosity: {
|
||||
label: 'Verbosity',
|
||||
excludeModal: true,
|
||||
type: 'select',
|
||||
ngOptions: 'verbosity.label for verbosity in ' +
|
||||
'adhoc_verbosity_options ' +
|
||||
'track by verbosity.value',
|
||||
editRequired: true,
|
||||
awPopOver:'<p>These are the verbosity levels for standard ' +
|
||||
'out of the command run that are supported.',
|
||||
dataTitle: 'Module',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: 'body',
|
||||
"default": 1
|
||||
},
|
||||
forks: {
|
||||
label: 'Forks',
|
||||
id: 'forks-number',
|
||||
type: 'number',
|
||||
integer: true,
|
||||
min: 0,
|
||||
spinner: true,
|
||||
"default": 0,
|
||||
addRequired: false,
|
||||
editRequired: false,
|
||||
'class': "input-small",
|
||||
column: 1,
|
||||
awPopOver: '<p>The number of parallel or simultaneous processes to use while executing the command. 0 signifies ' +
|
||||
'the default value from the <a id="ansible_forks_docs" href=\"http://docs.ansible.com/intro_configuration.html#the-ansible-configuration-file\" ' +
|
||||
' target=\"_blank\">ansible configuration file</a>.</p>',
|
||||
dataTitle: 'Forks',
|
||||
dataPlacement: 'right',
|
||||
dataContainer: "body"
|
||||
},
|
||||
},
|
||||
|
||||
buttons: {
|
||||
launch: {
|
||||
label: 'Launch',
|
||||
ngClick: 'launchJob()',
|
||||
ngDisabled: true
|
||||
},
|
||||
reset: {
|
||||
ngClick: 'formReset()',
|
||||
ngDisabled: true
|
||||
}
|
||||
},
|
||||
|
||||
related: {}
|
||||
});
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name helpers.function:Adhoc
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name helpers.function:Jobs
|
||||
|
||||
220
awx/ui/client/tests/adhoc/adhoc.controller-test.js
Normal file
220
awx/ui/client/tests/adhoc/adhoc.controller-test.js
Normal file
@ -0,0 +1,220 @@
|
||||
import '../support/node';
|
||||
|
||||
import adhocModule from 'adhoc/main';
|
||||
import RestStub from '../support/rest-stub';
|
||||
|
||||
describe("adhoc.controller", function() {
|
||||
var $scope, $rootScope, $location, $routeParams,
|
||||
CheckPasswords, PromptForPasswords, CreateLaunchDialog, AdhocForm,
|
||||
GenerateForm, Rest, ProcessErrors, ClearScope, GetBasePath, GetChoices,
|
||||
KindChange, LookUpInit, CredentialList, Empty, Wait;
|
||||
|
||||
var $controller, ctrl, generateFormCallback, waitCallback, locationCallback,
|
||||
getBasePath, processErrorsCallback, restCallback;
|
||||
|
||||
beforeEach("instantiate the adhoc module", function() {
|
||||
angular.mock.module(adhocModule.name);
|
||||
});
|
||||
|
||||
before("create spies", function() {
|
||||
getBasePath = function(path) {
|
||||
return '/' + path + '/';
|
||||
};
|
||||
generateFormCallback = {
|
||||
inject: angular.noop
|
||||
};
|
||||
waitCallback = sinon.spy();
|
||||
locationCallback = {
|
||||
path: sinon.spy()
|
||||
};
|
||||
processErrorsCallback = sinon.spy();
|
||||
restCallback = new RestStub();
|
||||
});
|
||||
|
||||
beforeEach("mock dependencies", angular.mock.module(['$provide', function(_provide_) {
|
||||
var $provide = _provide_;
|
||||
|
||||
$provide.value('$location', locationCallback);
|
||||
$provide.value('CheckPasswords', angular.noop);
|
||||
$provide.value('PromptForPasswords', angular.noop);
|
||||
$provide.value('CreateLaunchDialog', angular.noop);
|
||||
$provide.value('AdhocForm', angular.noop);
|
||||
$provide.value('GenerateForm', generateFormCallback);
|
||||
$provide.value('Rest', restCallback);
|
||||
$provide.value('ProcessErrors', processErrorsCallback);
|
||||
$provide.value('ClearScope', angular.noop);
|
||||
$provide.value('GetBasePath', getBasePath);
|
||||
$provide.value('GetChoices', angular.noop);
|
||||
$provide.value('KindChange', angular.noop);
|
||||
$provide.value('LookUpInit', angular.noop);
|
||||
$provide.value('CredentialList', angular.noop);
|
||||
$provide.value('Empty', angular.noop);
|
||||
$provide.value('Wait', waitCallback);
|
||||
}]));
|
||||
|
||||
beforeEach("put $q in scope", window.inject(['$q', function($q) {
|
||||
restCallback.$q = $q;
|
||||
}]));
|
||||
|
||||
beforeEach("put the controller in scope", inject(function($injector) {
|
||||
$rootScope = $injector.get('$rootScope');
|
||||
$controller = $injector.get('$controller');
|
||||
$scope = $rootScope.$new();
|
||||
ctrl = $controller('adhocController', {$scope: $scope});
|
||||
}));
|
||||
|
||||
describe("setAvailableUrls", function() {
|
||||
it('should only have the specified urls ' +
|
||||
'available for adhoc commands', function() {
|
||||
var urls = ctrl.privateFn.setAvailableUrls();
|
||||
expect(urls).to.have.keys('adhocUrl', 'inventoryUrl',
|
||||
'machineCredentialUrl');
|
||||
|
||||
var count = 0;
|
||||
var i;
|
||||
|
||||
for (i in urls) {
|
||||
if (urls.hasOwnProperty(i)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
expect(count).to.equal(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setFieldDefaults", function() {
|
||||
it('should set the select form field defaults' +
|
||||
'based on user settings', function() {
|
||||
var verbosity_options = [
|
||||
{label: "0 (Foo)", value: 0, name: "0 (Foo)",
|
||||
isDefault: false},
|
||||
{label: "1 (Bar)", value: 1, name: "1 (Bar)",
|
||||
isDefault: true},
|
||||
],
|
||||
forks_field = {};
|
||||
|
||||
forks_field.default = 3;
|
||||
|
||||
$scope.$apply(function() {
|
||||
ctrl.privateFn.setFieldDefaults(verbosity_options,
|
||||
forks_field.default);
|
||||
});
|
||||
|
||||
expect($scope.forks).to.equal(forks_field.default);
|
||||
expect($scope.verbosity.value).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setLoadingStartStop", function() {
|
||||
it('should start the controller working state when the form is ' +
|
||||
'loading', function() {
|
||||
waitCallback.reset();
|
||||
ctrl.privateFn.setLoadingStartStop();
|
||||
expect(waitCallback).to.have.been.calledWith("start");
|
||||
});
|
||||
it('should stop the indicator after all REST calls in the form load have ' +
|
||||
'completed', function() {
|
||||
var forks_field = {},
|
||||
adhoc_verbosity_options = {};
|
||||
forks_field.default = "1";
|
||||
$scope.$apply(function() {
|
||||
$scope.forks_field = forks_field;
|
||||
$scope.adhoc_verbosity_options = adhoc_verbosity_options;
|
||||
});
|
||||
waitCallback.reset();
|
||||
$scope.$emit('adhocFormReady');
|
||||
$scope.$emit('adhocFormReady');
|
||||
expect(waitCallback).to.have.been.calledWith("stop");
|
||||
});
|
||||
});
|
||||
|
||||
describe("getInventoryNameForBreadcrumbs", function() {
|
||||
it('should set the inventory name on scope', function() {
|
||||
var req = ctrl.privateFn.getInventoryNameForBreadcrumbs("foo");
|
||||
var response = { data: { name: "foo" } };
|
||||
|
||||
restCallback.succeed(response);
|
||||
restCallback.flush();
|
||||
|
||||
return req.then(function() {
|
||||
expect($scope.inv_name).to.equal('foo');
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to the inventory manage page when the inventory ' +
|
||||
'can not be found', function() {
|
||||
var req = ctrl.privateFn.getInventoryNameForBreadcrumbs("foo");
|
||||
var response = { "detail": "Not found", status: "bad" };
|
||||
|
||||
restCallback.fail(response);
|
||||
restCallback.flush();
|
||||
|
||||
return req.catch(function() {
|
||||
expect(processErrorsCallback).to.have.been.called;
|
||||
expect(locationCallback.path).to.have.been.calledWith("/inventories/");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("instantiateArgumentHelp", function() {
|
||||
it("should initially provide a canned argument help response", function() {
|
||||
expect($scope.argsPopOver).to.equal('<p>These arguments are used ' +
|
||||
'with the specified module.</p>');
|
||||
});
|
||||
|
||||
it("should change the help response when the module changes", function() {
|
||||
$scope.$apply(function () {
|
||||
$scope.module_name = {value: 'foo'};
|
||||
});
|
||||
expect($scope.argsPopOver).to.equal('<p>These arguments are used ' +
|
||||
'with the specified module. You can find information about ' +
|
||||
'the foo module <a ' +
|
||||
'id=\"adhoc_module_arguments_docs_link_for_module_foo\" ' +
|
||||
'href=\"http://docs.ansible.com/foo_module.html\" ' +
|
||||
'target=\"_blank\">here</a>.</p>');
|
||||
});
|
||||
|
||||
it("should change the help response when the module changes again", function() {
|
||||
$scope.$apply(function () {
|
||||
$scope.module_name = {value: 'bar'};
|
||||
});
|
||||
expect($scope.argsPopOver).to.equal('<p>These arguments are used ' +
|
||||
'with the specified module. You can find information about ' +
|
||||
'the bar module <a ' +
|
||||
'id=\"adhoc_module_arguments_docs_link_for_module_bar\" ' +
|
||||
'href=\"http://docs.ansible.com/bar_module.html\" ' +
|
||||
'target=\"_blank\">here</a>.</p>');
|
||||
});
|
||||
|
||||
it("should change the help response back to the canned response " +
|
||||
"when no module is selected", function() {
|
||||
$scope.$apply(function () {
|
||||
$scope.module_name = null;
|
||||
});
|
||||
expect($scope.argsPopOver).to.equal('<p>These arguments are used ' +
|
||||
'with the specified module.</p>');
|
||||
});
|
||||
});
|
||||
|
||||
describe("instantiateHostPatterns", function() {
|
||||
it("should initialize the limit object based on the provided host " +
|
||||
"pattern", function() {
|
||||
ctrl.privateFn.instantiateHostPatterns("foo:bar");
|
||||
expect($scope.limit).to.equal("foo:bar");
|
||||
});
|
||||
|
||||
it("should set the providedHostPatterns variable to the provided host " +
|
||||
"pattern so it is accesible on form reset", function() {
|
||||
ctrl.privateFn.instantiateHostPatterns("foo:bar");
|
||||
expect($scope.providedHostPatterns).to.equal("foo:bar");
|
||||
});
|
||||
|
||||
it("should remove the hostPattern from rootScope after it has been " +
|
||||
"utilized", function() {
|
||||
$rootScope.hostPatterns = "foo";
|
||||
expect($rootScope.hostPatterns).to.exist;
|
||||
ctrl.privateFn.instantiateHostPatterns("foo");
|
||||
expect($rootScope.hostPatterns).to.not.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -11,8 +11,10 @@
|
||||
require('./setup/jsdom');
|
||||
require('./setup/mocha');
|
||||
require('./setup/jquery');
|
||||
require('./setup/jquery-ui');
|
||||
require('./setup/angular');
|
||||
require('./setup/angular-mocks');
|
||||
require('./setup/angular-route');
|
||||
require('./setup/angular-templates');
|
||||
require('./setup/sinon');
|
||||
require('./setup/chai');
|
||||
|
||||
1
awx/ui/client/tests/support/node/setup/angular-route.js
vendored
Normal file
1
awx/ui/client/tests/support/node/setup/angular-route.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
require('angular-route/angular-route');
|
||||
4
awx/ui/client/tests/support/node/setup/jquery-ui.js
vendored
Normal file
4
awx/ui/client/tests/support/node/setup/jquery-ui.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
var exportGlobal = require('../export-global');
|
||||
global.document = window.document;
|
||||
global.navigator = window.navigator;
|
||||
require('jquery-ui/jquery-ui');
|
||||
Loading…
x
Reference in New Issue
Block a user