mirror of
https://github.com/ZwareBear/awx.git
synced 2026-05-15 07:48:38 -05:00
Merge branch 'devel' into 6967-prompt-credential-password
This commit is contained in:
@@ -55,6 +55,7 @@ export default [
|
||||
var formTracker = $scope.$parent.vm.formTracker;
|
||||
var dropdownValue = 'azure';
|
||||
var activeAuthForm = 'azure';
|
||||
let codeInputInitialized = false;
|
||||
|
||||
// Default active form
|
||||
if ($stateParams.currentTab === '' || $stateParams.currentTab === 'auth') {
|
||||
@@ -244,8 +245,6 @@ export default [
|
||||
// Flag to avoid re-rendering and breaking Select2 dropdowns on tab switching
|
||||
var dropdownRendered = false;
|
||||
|
||||
|
||||
|
||||
function populateLDAPGroupType(flag){
|
||||
if($scope.$parent.AUTH_LDAP_GROUP_TYPE !== null) {
|
||||
$scope.$parent.AUTH_LDAP_GROUP_TYPE = _.find($scope.$parent.AUTH_LDAP_GROUP_TYPE_options, { value: $scope.$parent.AUTH_LDAP_GROUP_TYPE });
|
||||
@@ -292,12 +291,24 @@ export default [
|
||||
populateTacacsProtocol(flag);
|
||||
});
|
||||
|
||||
$scope.$on('codeMirror_populated', function(e, key) {
|
||||
startCodeMirrors(key);
|
||||
$scope.$on('$locationChangeStart', (event, url) => {
|
||||
let parts = url.split('/');
|
||||
let tab = parts[parts.length - 1];
|
||||
|
||||
if (tab === 'auth' && !codeInputInitialized) {
|
||||
startCodeMirrors();
|
||||
codeInputInitialized = true;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on('populated', function() {
|
||||
startCodeMirrors();
|
||||
let tab = $stateParams.currentTab;
|
||||
|
||||
if (tab === 'auth') {
|
||||
startCodeMirrors();
|
||||
codeInputInitialized = true;
|
||||
}
|
||||
|
||||
populateLDAPGroupType(false);
|
||||
populateTacacsProtocol(false);
|
||||
});
|
||||
|
||||
@@ -8,28 +8,35 @@ export default [
|
||||
'$scope',
|
||||
'$rootScope',
|
||||
'$state',
|
||||
'$stateParams',
|
||||
'$timeout',
|
||||
'ConfigurationJobsForm',
|
||||
'ConfigurationService',
|
||||
'ConfigurationUtils',
|
||||
'CreateSelect2',
|
||||
'GenerateForm',
|
||||
'ParseTypeChange',
|
||||
'i18n',
|
||||
function(
|
||||
$scope,
|
||||
$rootScope,
|
||||
$state,
|
||||
$stateParams,
|
||||
$timeout,
|
||||
ConfigurationJobsForm,
|
||||
ConfigurationService,
|
||||
ConfigurationUtils,
|
||||
CreateSelect2,
|
||||
GenerateForm,
|
||||
ParseTypeChange,
|
||||
i18n
|
||||
) {
|
||||
var jobsVm = this;
|
||||
var generator = GenerateForm;
|
||||
var form = ConfigurationJobsForm;
|
||||
|
||||
let tab;
|
||||
let codeInputInitialized = false;
|
||||
|
||||
$scope.$parent.AD_HOC_COMMANDS_options = [];
|
||||
_.each($scope.$parent.configDataResolve.AD_HOC_COMMANDS.default, function(command) {
|
||||
$scope.$parent.AD_HOC_COMMANDS_options.push({
|
||||
@@ -75,6 +82,18 @@ export default [
|
||||
// Flag to avoid re-rendering and breaking Select2 dropdowns on tab switching
|
||||
var dropdownRendered = false;
|
||||
|
||||
function initializeCodeInput () {
|
||||
let name = 'AWX_TASK_ENV';
|
||||
|
||||
ParseTypeChange({
|
||||
scope: $scope.$parent,
|
||||
variable: name,
|
||||
parseType: 'application/json',
|
||||
field_id: `configuration_jobs_template_${name}`
|
||||
});
|
||||
|
||||
$scope.parseTypeChange('parseType', name);
|
||||
}
|
||||
|
||||
function populateAdhocCommand(flag){
|
||||
$scope.$parent.AD_HOC_COMMANDS = $scope.$parent.AD_HOC_COMMANDS.toString();
|
||||
@@ -107,22 +126,55 @@ export default [
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$on('AD_HOC_COMMANDS_populated', function(e, data, flag) {
|
||||
populateAdhocCommand(flag);
|
||||
});
|
||||
|
||||
$scope.$on('populated', function() {
|
||||
populateAdhocCommand(false);
|
||||
});
|
||||
|
||||
// Fix for bug where adding selected opts causes form to be $dirty and triggering modal
|
||||
// TODO Find better solution for this bug
|
||||
$timeout(function(){
|
||||
$scope.$parent.configuration_jobs_template_form.$setPristine();
|
||||
}, 1000);
|
||||
|
||||
angular.extend(jobsVm, {
|
||||
$scope.$on('AD_HOC_COMMANDS_populated', function(e, data, flag) {
|
||||
populateAdhocCommand(flag);
|
||||
});
|
||||
|
||||
/*
|
||||
* Controllers for each tab are initialized when configuration is opened. A listener
|
||||
* on the URL itself is necessary to determine which tab is active. If a non-active
|
||||
* tab initializes a codemirror, it doesn't display properly until the user navigates
|
||||
* to the tab and it's been clicked.
|
||||
*/
|
||||
$scope.$on('$locationChangeStart', (event, url) => {
|
||||
let parts = url.split('/');
|
||||
tab = parts[parts.length - 1];
|
||||
|
||||
if (tab === 'jobs' && !codeInputInitialized) {
|
||||
initializeCodeInput();
|
||||
codeInputInitialized = true;
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Necessary to listen for revert clicks and relaunch the codemirror instance.
|
||||
*/
|
||||
$scope.$on('codeMirror_populated', () => {
|
||||
if (tab === 'jobs') {
|
||||
initializeCodeInput();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* This event is fired if the user navigates directly to this tab, where the
|
||||
* $locationChangeStart does not. Watching this and location ensure proper display on
|
||||
* direct load of this tab or if the user comes from a different tab.
|
||||
*/
|
||||
$scope.$on('populated', () => {
|
||||
tab = $stateParams.currentTab;
|
||||
|
||||
if (tab === 'jobs') {
|
||||
initializeCodeInput();
|
||||
codeInputInitialized = true;
|
||||
}
|
||||
|
||||
populateAdhocCommand(false);
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
@@ -4,76 +4,82 @@
|
||||
* All Rights Reserved
|
||||
*************************************************/
|
||||
|
||||
export default ['i18n', function(i18n) {
|
||||
return {
|
||||
showHeader: false,
|
||||
name: 'configuration_jobs_template',
|
||||
showActions: true,
|
||||
export default ['i18n', function(i18n) {
|
||||
return {
|
||||
showHeader: false,
|
||||
name: 'configuration_jobs_template',
|
||||
showActions: true,
|
||||
fields: {
|
||||
AD_HOC_COMMANDS: {
|
||||
type: 'select',
|
||||
ngOptions: 'command.label for command in AD_HOC_COMMANDS_options track by command.value',
|
||||
reset: 'AD_HOC_COMMANDS',
|
||||
multiSelect: true
|
||||
},
|
||||
AWX_PROOT_BASE_PATH: {
|
||||
type: 'text',
|
||||
reset: 'AWX_PROOT_BASE_PATH',
|
||||
},
|
||||
SCHEDULE_MAX_JOBS: {
|
||||
type: 'number',
|
||||
reset: 'SCHEDULE_MAX_JOBS'
|
||||
},
|
||||
AWX_PROOT_SHOW_PATHS: {
|
||||
type: 'textarea',
|
||||
reset: 'AWX_PROOT_SHOW_PATHS',
|
||||
rows: 6
|
||||
},
|
||||
AWX_ANSIBLE_CALLBACK_PLUGINS: {
|
||||
type: 'textarea',
|
||||
reset: 'AWX_ANSIBLE_CALLBACK_PLUGINS',
|
||||
rows: 6
|
||||
},
|
||||
AWX_PROOT_HIDE_PATHS: {
|
||||
type: 'textarea',
|
||||
reset: 'AWX_PROOT_HIDE_PATHS',
|
||||
rows: 6
|
||||
},
|
||||
AWX_PROOT_ENABLED: {
|
||||
type: 'toggleSwitch',
|
||||
},
|
||||
DEFAULT_JOB_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'DEFAULT_JOB_TIMEOUT',
|
||||
},
|
||||
DEFAULT_INVENTORY_UPDATE_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'DEFAULT_INVENTORY_UPDATE_TIMEOUT',
|
||||
},
|
||||
DEFAULT_PROJECT_UPDATE_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'DEFAULT_PROJECT_UPDATE_TIMEOUT',
|
||||
},
|
||||
ANSIBLE_FACT_CACHE_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'ANSIBLE_FACT_CACHE_TIMEOUT',
|
||||
},
|
||||
AWX_TASK_ENV: {
|
||||
type: 'textarea',
|
||||
reset: 'AWX_TASK_ENV',
|
||||
rows: 6,
|
||||
codeMirror: true,
|
||||
class: 'Form-textAreaLabel Form-formGroup--fullWidth'
|
||||
}
|
||||
},
|
||||
buttons: {
|
||||
reset: {
|
||||
ngClick: 'vm.resetAllConfirm()',
|
||||
label: i18n._('Revert all to default'),
|
||||
class: 'Form-resetAll'
|
||||
},
|
||||
cancel: {
|
||||
ngClick: 'vm.formCancel()',
|
||||
},
|
||||
save: {
|
||||
ngClick: 'vm.formSave()',
|
||||
ngDisabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
fields: {
|
||||
AD_HOC_COMMANDS: {
|
||||
type: 'select',
|
||||
ngOptions: 'command.label for command in AD_HOC_COMMANDS_options track by command.value',
|
||||
reset: 'AD_HOC_COMMANDS',
|
||||
multiSelect: true
|
||||
},
|
||||
AWX_PROOT_BASE_PATH: {
|
||||
type: 'text',
|
||||
reset: 'AWX_PROOT_BASE_PATH',
|
||||
},
|
||||
SCHEDULE_MAX_JOBS: {
|
||||
type: 'number',
|
||||
reset: 'SCHEDULE_MAX_JOBS'
|
||||
},
|
||||
AWX_PROOT_SHOW_PATHS: {
|
||||
type: 'textarea',
|
||||
reset: 'AWX_PROOT_SHOW_PATHS',
|
||||
rows: 6
|
||||
},
|
||||
AWX_ANSIBLE_CALLBACK_PLUGINS: {
|
||||
type: 'textarea',
|
||||
reset: 'AWX_ANSIBLE_CALLBACK_PLUGINS',
|
||||
rows: 6
|
||||
},
|
||||
AWX_PROOT_HIDE_PATHS: {
|
||||
type: 'textarea',
|
||||
reset: 'AWX_PROOT_HIDE_PATHS',
|
||||
rows: 6
|
||||
},
|
||||
AWX_PROOT_ENABLED: {
|
||||
type: 'toggleSwitch',
|
||||
},
|
||||
DEFAULT_JOB_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'DEFAULT_JOB_TIMEOUT',
|
||||
},
|
||||
DEFAULT_INVENTORY_UPDATE_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'DEFAULT_INVENTORY_UPDATE_TIMEOUT',
|
||||
},
|
||||
DEFAULT_PROJECT_UPDATE_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'DEFAULT_PROJECT_UPDATE_TIMEOUT',
|
||||
},
|
||||
ANSIBLE_FACT_CACHE_TIMEOUT: {
|
||||
type: 'text',
|
||||
reset: 'ANSIBLE_FACT_CACHE_TIMEOUT',
|
||||
},
|
||||
},
|
||||
|
||||
buttons: {
|
||||
reset: {
|
||||
ngClick: 'vm.resetAllConfirm()',
|
||||
label: i18n._('Revert all to default'),
|
||||
class: 'Form-resetAll'
|
||||
},
|
||||
cancel: {
|
||||
ngClick: 'vm.formCancel()',
|
||||
},
|
||||
save: {
|
||||
ngClick: 'vm.formSave()',
|
||||
ngDisabled: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
+6
-36
@@ -18,8 +18,9 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
|
||||
init();
|
||||
|
||||
function init() {
|
||||
$scope.mode = 'add';
|
||||
// apply form definition's default field values
|
||||
GenerateForm.applyDefaults(form, $scope);
|
||||
GenerateForm.applyDefaults(form, $scope, true);
|
||||
$scope.canAdd = inventorySourcesOptions.actions.POST;
|
||||
$scope.envParseType = 'yaml';
|
||||
initSources();
|
||||
@@ -46,36 +47,6 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
|
||||
}
|
||||
};
|
||||
|
||||
// Detect and alert user to potential SCM status issues
|
||||
var checkSCMStatus = function () {
|
||||
if (!Empty($scope.project)) {
|
||||
Rest.setUrl(GetBasePath('projects') + $scope.project + '/');
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var msg;
|
||||
switch (data.status) {
|
||||
case 'failed':
|
||||
msg = "<div>The Project selected has a status of \"failed\". You must run a successful update before you can select an inventory file.";
|
||||
break;
|
||||
case 'never updated':
|
||||
msg = "<div>The Project selected has a status of \"never updated\". You must run a successful update before you can select an inventory file.";
|
||||
break;
|
||||
case 'missing':
|
||||
msg = '<div>The selected project has a status of \"missing\". Please check the server and make sure ' +
|
||||
' the directory exists and file permissions are set correctly.</div>';
|
||||
break;
|
||||
}
|
||||
if (msg) {
|
||||
Alert('Warning', msg, 'alert-info alert-info--noTextTransform', null, null, null, null, true);
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, form, { hdr: 'Error!',
|
||||
msg: 'Failed to get project ' + $scope.project + '. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Register a watcher on project_name
|
||||
if ($scope.getInventoryFilesUnregister) {
|
||||
$scope.getInventoryFilesUnregister();
|
||||
@@ -83,7 +54,6 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
|
||||
$scope.getInventoryFilesUnregister = $scope.$watch('project', function (newValue, oldValue) {
|
||||
if (newValue !== oldValue) {
|
||||
getInventoryFiles(newValue);
|
||||
checkSCMStatus();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -118,7 +88,6 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
|
||||
});
|
||||
};
|
||||
|
||||
$scope.projectBasePath = GetBasePath('projects');
|
||||
$scope.credentialBasePath = GetBasePath('credentials') + '?credential_type__kind__in=cloud,network';
|
||||
|
||||
$scope.sourceChange = function(source) {
|
||||
@@ -144,10 +113,11 @@ export default ['$state', '$stateParams', '$scope', 'SourcesFormDefinition',
|
||||
}
|
||||
|
||||
if (source === 'scm') {
|
||||
$scope.overwrite_vars = true;
|
||||
$scope.inventory_source_form.inventory_file.$setPristine();
|
||||
$scope.projectBasePath = GetBasePath('projects') + '?not__status=never updated';
|
||||
$scope.overwrite_vars = true;
|
||||
$scope.inventory_source_form.inventory_file.$setPristine();
|
||||
} else {
|
||||
$scope.overwrite_vars = false;
|
||||
$scope.overwrite_vars = false;
|
||||
}
|
||||
|
||||
// reset fields
|
||||
|
||||
+3
-30
@@ -8,15 +8,15 @@ export default ['$state', '$stateParams', '$scope', 'ParseVariableString',
|
||||
'rbacUiControlService', 'ToJSON', 'ParseTypeChange', 'GroupsService',
|
||||
'GetChoices', 'GetBasePath', 'CreateSelect2', 'GetSourceTypeOptions',
|
||||
'inventorySourceData', 'SourcesService', 'inventoryData', 'inventorySourcesOptions', 'Empty',
|
||||
'Wait', 'Rest', 'Alert', 'ProcessErrors',
|
||||
'Wait', 'Rest', 'Alert',
|
||||
function($state, $stateParams, $scope, ParseVariableString,
|
||||
rbacUiControlService, ToJSON,ParseTypeChange, GroupsService,
|
||||
GetChoices, GetBasePath, CreateSelect2, GetSourceTypeOptions,
|
||||
inventorySourceData, SourcesService, inventoryData, inventorySourcesOptions, Empty,
|
||||
Wait, Rest, Alert, ProcessErrors) {
|
||||
Wait, Rest, Alert) {
|
||||
|
||||
function init() {
|
||||
$scope.projectBasePath = GetBasePath('projects');
|
||||
$scope.projectBasePath = GetBasePath('projects') + '?not__status=never updated';
|
||||
$scope.canAdd = inventorySourcesOptions.actions.POST;
|
||||
// instantiate expected $scope values from inventorySourceData
|
||||
_.assign($scope,
|
||||
@@ -136,33 +136,6 @@ export default ['$state', '$stateParams', '$scope', 'ParseVariableString',
|
||||
Wait('stop');
|
||||
});
|
||||
}
|
||||
|
||||
if (!Empty($scope.project)) {
|
||||
Rest.setUrl(GetBasePath('projects') + $scope.project + '/');
|
||||
Rest.get()
|
||||
.success(function (data) {
|
||||
var msg;
|
||||
switch (data.status) {
|
||||
case 'failed':
|
||||
msg = "<div>The Project selected has a status of \"failed\". You must run a successful update before you can select an inventory file.";
|
||||
break;
|
||||
case 'never updated':
|
||||
msg = "<div>The Project selected has a status of \"never updated\". You must run a successful update before you can select an inventory file.";
|
||||
break;
|
||||
case 'missing':
|
||||
msg = '<div>The selected project has a status of \"missing\". Please check the server and make sure ' +
|
||||
' the directory exists and file permissions are set correctly.</div>';
|
||||
break;
|
||||
}
|
||||
if (msg) {
|
||||
Alert('Warning', msg, 'alert-info alert-info--noTextTransform', null, null, null, null, true);
|
||||
}
|
||||
})
|
||||
.error(function (data, status) {
|
||||
ProcessErrors($scope, data, status, null, { hdr: 'Error!',
|
||||
msg: 'Failed to get project ' + $scope.project + '. GET returned status: ' + status });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function initSourceSelect() {
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ export default {
|
||||
value: {
|
||||
page_size:"5",
|
||||
order_by:"name",
|
||||
not__status:"never updated",
|
||||
role_level:"use_role",
|
||||
},
|
||||
dynamic:true,
|
||||
|
||||
@@ -89,6 +89,7 @@ function(jobData, jobDataOptions, jobLabels, jobFinished, count, $scope, ParseTy
|
||||
$scope.machine_credential_link = getTowerLink('credential');
|
||||
$scope.cloud_credential_link = getTowerLink('cloud_credential');
|
||||
$scope.network_credential_link = getTowerLink('network_credential');
|
||||
$scope.vault_credential_link = getTowerLink('vault_credential');
|
||||
$scope.schedule_link = getTowerLink('schedule');
|
||||
};
|
||||
|
||||
|
||||
@@ -323,6 +323,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VAULT CREDENTAIL DETAIL -->
|
||||
<div class="JobResults-resultRow"
|
||||
ng-show="job.summary_fields.vault_credential.name">
|
||||
<label class="JobResults-resultRowLabel">
|
||||
Vault Credential
|
||||
</label>
|
||||
<div class="JobResults-resultRowText">
|
||||
<a href="{{ vault_credential_link }}"
|
||||
aw-tool-tip="Edit the credential"
|
||||
data-placement="top">
|
||||
{{ job.summary_fields.vault_credential.name }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FORKS DETAIL -->
|
||||
<div class="JobResults-resultRow"
|
||||
ng-show="job.forks !== undefined">
|
||||
|
||||
@@ -163,6 +163,7 @@ export default
|
||||
$scope.password_needed = data.passwords_needed_to_start && data.passwords_needed_to_start.length > 0;
|
||||
$scope.has_default_inventory = data.defaults && data.defaults.inventory && data.defaults.inventory.id;
|
||||
$scope.has_default_credential = data.defaults && data.defaults.credential && data.defaults.credential.id;
|
||||
$scope.has_default_vault_credential = data.defaults && data.defaults.vault_credential && data.defaults.vault_credential.id;
|
||||
$scope.has_default_extra_credentials = data.defaults && data.defaults.extra_credentials && data.defaults.extra_credentials.length > 0;
|
||||
|
||||
$scope.other_prompt_data = {};
|
||||
@@ -231,6 +232,10 @@ export default
|
||||
$scope.selected_credentials.machine = angular.copy($scope.defaults.credential);
|
||||
}
|
||||
|
||||
if($scope.has_default_vault_credential) {
|
||||
$scope.selected_credentials.vault = angular.copy($scope.defaults.vault_credential);
|
||||
}
|
||||
|
||||
if($scope.has_default_extra_credentials) {
|
||||
$scope.selected_credentials.extra = angular.copy($scope.defaults.extra_credentials);
|
||||
}
|
||||
@@ -361,6 +366,12 @@ export default
|
||||
else {
|
||||
$scope.selected_credentials.machine = null;
|
||||
}
|
||||
if($scope.has_default_vault_credential) {
|
||||
$scope.selected_credentials.vault = angular.copy($scope.defaults.vault_credential);
|
||||
}
|
||||
else {
|
||||
$scope.selected_credentials.vault = null;
|
||||
}
|
||||
if($scope.has_default_extra_credentials) {
|
||||
$scope.selected_credentials.extra = angular.copy($scope.defaults.extra_credentials);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,12 @@
|
||||
<span><span class="JobSubmission-previewTagLabel">{{credential_types[extraCredential.credential_type].name | uppercase}}</span>: {{extraCredential.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="JobSubmission-previewTagContainer JobSubmission-previewTagContainer--vault" ng-show="selected_credentials.vault">
|
||||
<div class="JobSubmission-previewTag JobSubmission-previewTag--vault" ng-class="{'JobSubmission-previewTag--deletable': ask_credential_on_launch}">
|
||||
<span>
|
||||
<span class="JobSubmission-previewTagLabel">VAULT</span>: {{selected_credentials.vault.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="JobSubmission-previewTagRevert" ng-if="ask_credential_on_launch">
|
||||
@@ -167,7 +173,7 @@
|
||||
</div>
|
||||
<div class="form-group Form-formGroup Form-formGroup--singleColumn" ng-if="ask_verbosity_on_launch">
|
||||
<label for="verbosity" class="prepend-asterisk Form-inputLabelContainer">
|
||||
<span class="Form-inputLabel"> Verbosity</span>
|
||||
<span class="Form-inputLabel" translate> Verbosity</span>
|
||||
</label>
|
||||
<div>
|
||||
<select
|
||||
@@ -333,6 +339,10 @@
|
||||
<span class="JobSubmission-previewItemSubTitle">{{credential_types[extraCredential.credential_type].name}}: </span>
|
||||
<span>{{extraCredential.name}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span ng-show="selected_credentials.vault" class="JobSubmission-previewItemSubTitle"><span translate>Vault</span>: </span>
|
||||
<span ng-show="selected_credentials.vault">{{selected_credentials.vault.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="JobSubmission-footerButtons">
|
||||
|
||||
@@ -564,10 +564,6 @@ function(ConfigurationUtils, i18n, $rootScope) {
|
||||
_doAutoPopulate();
|
||||
}
|
||||
});
|
||||
|
||||
if (attrs.watchbasepath === 'projectBasePath') {
|
||||
_doAutoPopulate();
|
||||
}
|
||||
}
|
||||
|
||||
function _doAutoPopulate() {
|
||||
|
||||
@@ -375,11 +375,13 @@ angular.module('FormGenerator', [GeneratorHelpers.name, 'Utilities', listGenerat
|
||||
return this.build(options);
|
||||
},
|
||||
|
||||
applyDefaults: function (form, scope) {
|
||||
// Note: This is a hack. Ideally, mode should be set in each <resource>-<mode>.controller.js
|
||||
// The mode is needed by the awlookup directive to auto-populate form fields when there is a
|
||||
// single related resource.
|
||||
scope.mode = this.mode;
|
||||
applyDefaults: function (form, scope, ignoreMode) {
|
||||
if(!ignoreMode) {
|
||||
// Note: This is a hack. Ideally, mode should be set in each <resource>-<mode>.controller.js
|
||||
// The mode is needed by the awlookup directive to auto-populate form fields when there is a
|
||||
// single related resource.
|
||||
scope.mode = this.mode;
|
||||
}
|
||||
|
||||
for (var fld in form.fields) {
|
||||
if (form.fields[fld]['default'] || form.fields[fld]['default'] === 0) {
|
||||
|
||||
+8
@@ -281,6 +281,14 @@
|
||||
} else {
|
||||
data.credential = null;
|
||||
}
|
||||
if ($scope.selectedCredentials && $scope.selectedCredentials
|
||||
.vault && $scope.selectedCredentials
|
||||
.vault.id) {
|
||||
data.vault_credential = $scope.selectedCredentials
|
||||
.vault.id;
|
||||
} else {
|
||||
data.vault_credential = null;
|
||||
}
|
||||
|
||||
data.extra_vars = ToJSON($scope.parseType,
|
||||
$scope.variables, true);
|
||||
|
||||
+9
-2
@@ -487,13 +487,20 @@ export default
|
||||
data.skip_tags = (Array.isArray($scope.skip_tags)) ? $scope.skip_tags.join() : "";
|
||||
if ($scope.selectedCredentials && $scope.selectedCredentials
|
||||
.machine && $scope.selectedCredentials
|
||||
.machine) {
|
||||
.machine.id) {
|
||||
data.credential = $scope.selectedCredentials
|
||||
.machine.id;
|
||||
} else {
|
||||
data.credential = null;
|
||||
}
|
||||
|
||||
if ($scope.selectedCredentials && $scope.selectedCredentials
|
||||
.vault && $scope.selectedCredentials
|
||||
.vault.id) {
|
||||
data.vault_credential = $scope.selectedCredentials
|
||||
.vault.id;
|
||||
} else {
|
||||
data.vault_credential = null;
|
||||
}
|
||||
data.extra_vars = ToJSON($scope.parseType,
|
||||
$scope.variables, true);
|
||||
|
||||
|
||||
+40
-1
@@ -83,6 +83,21 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile'
|
||||
$scope.credentialTypeOptions);
|
||||
};
|
||||
|
||||
let updateVaultCredentialList = function() {
|
||||
$scope.credentials.forEach(cred => {
|
||||
if (cred.credential_type === 3) {
|
||||
cred.checked = ($scope.selectedCredentials
|
||||
.vault !== null &&
|
||||
cred.id === $scope.selectedCredentials
|
||||
.vault.id) ? 1 : 0;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.credTags = MultiCredentialService
|
||||
.updateCredentialTags($scope.selectedCredentials,
|
||||
$scope.credentialTypeOptions);
|
||||
};
|
||||
|
||||
let uncheckAllCredentials = function() {
|
||||
$scope.credentials.forEach(cred => {
|
||||
cred.checked = 0;
|
||||
@@ -156,14 +171,29 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile'
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watch('selectedCredentials.vault', () => {
|
||||
if($scope.selectedCredentials &&
|
||||
$scope.selectedCredentials.vault &&
|
||||
parseInt($scope.credentialKind) === 3) {
|
||||
updateVaultCredentialList();
|
||||
} else {
|
||||
uncheckAllCredentials();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$watchGroup(['credentials',
|
||||
'selectedCredentials.machine'], () => {
|
||||
'selectedCredentials.machine',
|
||||
'selectedCredentials.vault'], () => {
|
||||
if($scope.credentials &&
|
||||
$scope.credentials.length > 0) {
|
||||
if($scope.selectedCredentials &&
|
||||
$scope.selectedCredentials.machine &&
|
||||
parseInt($scope.credentialKind) === 1) {
|
||||
updateMachineCredentialList();
|
||||
} else if($scope.selectedCredentials &&
|
||||
$scope.selectedCredentials.vault &&
|
||||
parseInt($scope.credentialKind) === 3) {
|
||||
updateVaultCredentialList();
|
||||
} else if($scope.selectedCredentials &&
|
||||
$scope.selectedCredentials.extra &&
|
||||
$scope.selectedCredentials.extra.length > 0 &&
|
||||
@@ -189,6 +219,14 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile'
|
||||
} else {
|
||||
$scope.selectedCredentials.machine = _.cloneDeep(selectedRow);
|
||||
}
|
||||
}else if(parseInt($scope.credentialKind) === 3) {
|
||||
if($scope.selectedCredentials &&
|
||||
$scope.selectedCredentials.vault &&
|
||||
$scope.selectedCredentials.vault.id === selectedRow.id) {
|
||||
$scope.selectedCredentials.vault = null;
|
||||
} else {
|
||||
$scope.selectedCredentials.vault = _.cloneDeep(selectedRow);
|
||||
}
|
||||
} else {
|
||||
let rowDeselected = false;
|
||||
for (let i = $scope.selectedCredentials.extra.length - 1; i >= 0; i--) {
|
||||
@@ -211,6 +249,7 @@ export default ['templateUrl', 'Rest', 'GetBasePath', 'generateList', '$compile'
|
||||
$scope.selectedCredentialsDirty = function() {
|
||||
if ($scope.originalSelectedCredentials) {
|
||||
return !($scope.originalSelectedCredentials.machine === null &&
|
||||
$scope.originalSelectedCredentials.vault === null &&
|
||||
$scope.originalSelectedCredentials.extra.length === 0) &&
|
||||
!_.isEqual($scope.selectedCredentials,
|
||||
$scope.originalSelectedCredentials);
|
||||
|
||||
+30
-2
@@ -84,7 +84,7 @@ export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, Pro
|
||||
data.results.forEach((credentialType => {
|
||||
credential_types[credentialType.id] = credentialType;
|
||||
if(credentialType.kind
|
||||
.match(/^(machine|cloud|net|ssh)$/)) {
|
||||
.match(/^(machine|cloud|net|ssh|vault)$/)) {
|
||||
credentialTypeOptions.push({
|
||||
name: credentialType.name,
|
||||
value: credentialType.id
|
||||
@@ -111,6 +111,7 @@ export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, Pro
|
||||
val.updateCredentialTags = (creds, typeOpts) => {
|
||||
let machineCred = [];
|
||||
let extraCreds = [];
|
||||
let vaultCred = [];
|
||||
|
||||
if (creds.machine) {
|
||||
let mach = creds.machine;
|
||||
@@ -118,6 +119,12 @@ export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, Pro
|
||||
machineCred = [mach];
|
||||
}
|
||||
|
||||
if (creds.vault) {
|
||||
let vault = creds.vault;
|
||||
vault.postType = "vault";
|
||||
vaultCred = [vault];
|
||||
}
|
||||
|
||||
if (creds.extra) {
|
||||
extraCreds = creds.extra
|
||||
.map((cred) => {
|
||||
@@ -127,7 +134,7 @@ export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, Pro
|
||||
});
|
||||
}
|
||||
|
||||
return machineCred.concat(extraCreds).map(cred => ({
|
||||
return machineCred.concat(extraCreds).concat(vaultCred).map(cred => ({
|
||||
name: cred.name,
|
||||
id: cred.id,
|
||||
postType: cred.postType,
|
||||
@@ -145,6 +152,8 @@ export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, Pro
|
||||
if (credToRemove === cred.id) {
|
||||
if (cred.postType === 'machine') {
|
||||
structuredObj[cred.postType] = null;
|
||||
} else if (cred.postType === 'vault') {
|
||||
structuredObj[cred.postType] = null;
|
||||
} else {
|
||||
structuredObj[cred.postType] = structuredObj[cred.postType]
|
||||
.filter(cred => cred
|
||||
@@ -163,6 +172,7 @@ export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, Pro
|
||||
val.loadCredentials = (data) => {
|
||||
let selectedCredentials = {
|
||||
machine: null,
|
||||
vault: null,
|
||||
extra: []
|
||||
}, credTypes, credTypeOptions, credTags;
|
||||
|
||||
@@ -187,6 +197,24 @@ export default ['Rest', 'ProcessErrors', '$q', 'GetBasePath', function(Rest, Pro
|
||||
}));
|
||||
}
|
||||
|
||||
if (data.related.vault_credential) {
|
||||
Rest.setUrl(data.related.vault_credential);
|
||||
credDefers.push(Rest.get()
|
||||
.then(({data}) => {
|
||||
selectedCredentials.vault = data;
|
||||
})
|
||||
.catch(({data, status}) => {
|
||||
ProcessErrors(
|
||||
null, data, status, null,
|
||||
{
|
||||
hdr: 'Error!',
|
||||
msg: 'Failed to get machine credential. ' +
|
||||
'Get returned status: ' +
|
||||
status
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
// get extra credentials
|
||||
if (data.related.extra_credentials) {
|
||||
Rest.setUrl(data.related.extra_credentials);
|
||||
|
||||
@@ -85,3 +85,11 @@
|
||||
.LabelList-deleteContainer:hover > .LabelList-tagDelete, .JobSubmission-previewTagContainerDelete:hover > .JobSubmission-previewTagContainerTagDelete {
|
||||
color: @default-bg;
|
||||
}
|
||||
|
||||
.JobSubmission-previewTagContainer--vault{
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.JobSubmission-previewTag--vault{
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user