AC-503 Latest cloud inventory changes.

This commit is contained in:
chouseknecht
2013-10-01 21:39:40 -04:00
parent 8fa1c66caf
commit 32d3914270
9 changed files with 638 additions and 227 deletions

View File

@@ -18,6 +18,7 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP
var generator = GenerateForm;
var form = InventoryGroupsForm;
var defaultUrl=GetBasePath('inventory');
$('#tree-view').empty();
var scope = generator.inject(form, { mode: 'edit', related: true, buildTree: true });
var base = $location.path().replace(/^\//,'').split('/')[0];
@@ -127,10 +128,13 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP
var type = node.attr('type');
var url;
scope['nodeSelectValue'] = n;
scope['selectedNode'] = node;
scope['selectedNodeName'] = node.attr('name');
scope['grpBtnDisable'] = false;
scope['flashMessage'] = null;
scope['groupUpdateHide'] = true;
$('#tree-view').jstree('open_node',node);
if (type == 'group') {
@@ -145,11 +149,13 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP
// Load the form
GroupsEdit({ "inventory_id": id, group_id: scope.group_id });
//scope.groupName = n.data;
//scope.groupTitle = '<h4>' + n.data + '</h4>';
//scope.groupTitle += (node.attr('description')) ? '<p>' + node.attr('description') + '</p>' : '';
// Slide in the group properties form
$('#tree-form').show();
$('input:first').focus();
}
else if (type == 'inventory') {
$('#tree-form').hide().empty();
url = node.attr('hosts');
scope.groupAddHide = true;
scope.groupCreateHide = false;
@@ -157,8 +163,6 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP
scope.inventoryEditHide=false;
scope.groupDeleteHide = true;
scope.createButtonShow = false;
//scope.groupName = 'All Hosts';
//scope.groupTitle = '<h4>All Hosts</h4>';
scope.group_id = null;
}
@@ -177,14 +181,7 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP
scope.editGroup = function() {
// Slide in the group properties form
$('#tree-form').show('slide', {direction: 'up'}, 500);
// Set the focust to the first form field
$('input:first').focus();
// Disable all the group related buttons
scope.grpBtnDisable = true;
setTimeout(function() {
$('#tree-form').show('slide', {direction: 'up'}, 500, function() {
// Remove any tooltips that might be lingering
$('.tooltip').each( function(index) {
$(this).remove();
@@ -193,7 +190,19 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP
// remove lingering popover <div>. Seems to be a bug in TB3 RC1
$(this).remove();
});
}, 1000);
// Set the focust to the first form field
$('input:first').focus();
});
// Disable all the group related buttons
scope.grpBtnDisable = false;
}
scope.closeForm = function() {
// Slide in the group properties form
$('#tree-form').hide('slide',{ direction: 'right' }, 500, function() { $('#tree-form').empty(); });
scope.grpBtnDisable = false;
}
scope.editInventory = function() {

View File

@@ -238,54 +238,18 @@ function InventoriesEdit ($scope, $rootScope, $compile, $location, $log, $routeP
}
};
// Related set: Add button
scope.add = function(set) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/groups/' + scope.group_id + '/' + set + '/add');
};
// Related set: Edit button
scope.edit = function(set, id, name) {
$rootScope.flashMessage = null;
$location.path('/' + base + '/' + $routeParams.id + '/' + set + '/' + id);
};
if (scope.removeInventorySaved) {
scope.removeInventorySaved();
}
scope.removeInventorySaved = scope.$on('inventorySaved', function() {
$location.path('/inventories');
});
scope.formSave = function() {
generator.clearApiErrors();
SaveInventory({ scope: scope });
}
// Related set: Delete button
scope['delete'] = function(set, itm_id, name, title) {
$rootScope.flashMessage = null;
var action = function() {
var url = defaultUrl + id + '/' + set + '/';
Rest.setUrl(url);
Rest.post({ id: itm_id, disassociate: 1 })
.success( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
scope.search(form.related[set].iterator);
})
.error( function(data, status, headers, config) {
$('#prompt-modal').modal('hide');
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST returned status: ' + status });
});
};
Prompt({ hdr: 'Delete',
body: 'Are you sure you want to remove ' + name + ' from ' + scope.name + ' ' + title + '?',
action: action
});
};
}
InventoriesEdit.$inject = [ '$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'InventoryForm',

View File

@@ -11,21 +11,15 @@ angular.module('GroupFormDefinition', [])
'GroupForm', {
addTitle: 'Create Group', //Legend in add mode
editTitle: '{{ name }}', //Legend in edit mode
editTitle: 'Group Properties: {{ name }}', //Legend in edit mode
showTitle: true,
cancelButton: false,
name: 'group', //Form name attribute
well: false, //Wrap the form with TB well
//formLabelSize: 'col-lg-3',
//formFieldSize: 'col-lg-9',
formLabelSize: 'col-lg-3',
formFieldSize: 'col-lg-9',
fields: {
/*has_active_failures: {
label: 'Status',
control: '<div class="job-failures-\{\{ has_active_failures \}\}">' +
'<i class="icon-exclamation-sign"></i> Contains hosts with failed jobs</div>',
type: 'custom',
ngShow: 'has_active_failures',
readonly: true
},*/
name: {
label: 'Name',
type: 'text',
@@ -44,11 +38,11 @@ angular.module('GroupFormDefinition', [])
addRequired: false,
editRequird: false,
rows: 10,
"class": 'modal-input-xlarge',
"default": "---",
'default': '---',
dataTitle: 'Group Variables',
dataPlacement: 'left',
awPopOver: "<p>Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
awPopOver: "<p>Variables defined here apply to all child groups and hosts. Enter variables using either JSON or YAML syntax. Use the " +
"radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
@@ -56,10 +50,164 @@ angular.module('GroupFormDefinition', [])
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://www.ansibleworks.com/docs/YAMLSyntax.html" target="_blank">ansibleworks.com</a></p>',
dataContainer: 'body'
}
},
source: {
label: 'Source',
excludeModal: true,
type: 'select',
ngOptions: 'source.label for source in source_type_options',
ngChange: 'sourceChange()',
addRequired: false,
editRequired: false,
'default': { label: 'Manual', value: null }
},
source_path: {
label: 'Script Path',
excludeModal: true,
ngShow: "source.value == 'file'",
type: 'text',
awRequiredWhen: {variable: "sourcePathRequired", init: "false" }
},
source_env: {
label: 'Script Environment Variables',
ngShow: "source.value == 'file'",
type: 'textarea',
addRequired: false,
editRequird: false,
excludeModal: true,
rows: 10,
'default': '---',
parseTypeName: 'envParseType',
dataTitle: 'Script Environment Variables',
dataPlacement: 'left',
awPopOver: "<p>Define environment variables here that will be referenced by the inventory script at runtime. " +
"Enter variables using either JSON or YAML syntax. Use the radio button to toggle between the two.</p>" +
"JSON:<br />\n" +
"<blockquote>{<br />\"somevar\": \"somevalue\",<br />\"password\": \"magic\"<br /> }</blockquote>\n" +
"YAML:<br />\n" +
"<blockquote>---<br />somevar: somevalue<br />password: magic<br /></blockquote>\n" +
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://www.ansibleworks.com/docs/YAMLSyntax.html" target="_blank">ansibleworks.com</a></p>',
dataContainer: 'body',
awPopOverRight: true
},
source_username: {
labelBind: 'sourceUsernameLabel',
excludeModal: true,
type: 'text',
ngShow: "source.value == 'rackspace' || source.value == 'ec2'",
awRequiredWhen: {variable: "sourceUsernameRequired", init: "false" }
},
source_password: {
labelBind: 'sourcePasswordLabel',
excludeModal: true,
type: 'password',
ngShow: "source.value == 'rackspace' || source.value == 'ec2'",
editRequired: false,
addRequired: false,
ngChange: "clearPWConfirm('source_password_confirm')",
ask: true,
clear: true,
associated: 'source_password_confirm',
autocomplete: false
},
source_password_confirm: {
labelBind: 'sourcePasswordConfirmLabel',
type: 'password',
ngShow: "source.value == 'rackspace' || source.value == 'ec2'",
addRequired: false,
editRequired: false,
awPassMatch: true,
associated: 'source_password',
autocomplete: false
},
source_regions: {
label: 'Regions',
excludeModal: true,
type: 'text',
ngShow: "source.value == 'rackspace' || source.value == 'ec2'",
addRequired: false,
editRequired: false
},
source_tags: {
label: 'Tags',
excludeModal: true,
type: 'text',
ngShow: "source.value == 'rackspace' || source.value == 'ec2'",
addRequired: false,
editRequired: false
},
checkbox_group: {
label: 'Update Options',
type: 'checkbox_group',
ngShow: "source.value !== '' && source.value !== null",
fields: [
{
name: 'overwite_hosts',
label: 'Overwrite Hosts',
type: 'checkbox',
ngShow: "source.value !== '' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>Replace AWX inventory hosts with cloud inventory hosts.</p>',
dataTitle: 'Overwrite Hosts',
dataContainer: 'body',
dataPlacement: 'left',
labelClass: 'checkbox-options',
inline: false
},
{
name: 'overwite_vars',
label: 'Overwrite Variables',
type: 'checkbox',
ngShow: "source.value !== '' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p></p>',
dataTitle: 'Overwrite Variables',
dataContainer: 'body',
dataPlacement: 'left',
labelClass: 'checkbox-options',
inline: false
},
{
name: 'keep_vars',
label: 'Keep Variables',
type: 'checkbox',
ngShow: "source.value !== '' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p></p>',
dataTitle: 'Keep Variables',
dataContainer: 'body',
dataPlacement: 'left',
labelClass: 'checkbox-options',
inline: false
},
{
name: 'update_on_launch',
label: 'Update on Launch',
type: 'checkbox',
ngShow: "source.value !== '' && source.value !== null",
addRequired: false,
editRequired: false,
awPopOver: '<p>Each time a job runs using this inventory, refresh the inventory from the selected source</p>',
dataTitle: 'Update on Launch',
dataContainer: 'body',
dataPlacement: 'left',
labelClass: 'checkbox-options',
inline: false
}
]
}
},
buttons: { //for now always generates <button> tags
labelClass: 'col-lg-3',
controlClass: 'col-lg-5',
save: {
label: 'Save',
icon: 'icon-ok',

View File

@@ -76,8 +76,8 @@ angular.module('InventoryFormDefinition', [])
'<p>View JSON examples at <a href="http://www.json.org" target="_blank">www.json.org</a></p>' +
'<p>View YAML examples at <a href="http://www.ansibleworks.com/docs/YAMLSyntax.html" target="_blank">ansibleworks.com</a></p>',
dataTitle: 'Inventory Variables',
dataPlacement: 'bottom',
dataContainer: '#inventory'
dataPlacement: 'left',
dataContainer: 'body'
}
},

View File

@@ -12,6 +12,17 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
'InventoryHelper', 'SelectionHelper'
])
.factory('getSourceTypeOptions', [ function() {
return function() {
return [
{ label: 'Manual', value: null },
{ label: 'Amazon EC2', value: 'ec2' },
{ label: 'Rackspace', value: 'rackspace' },
{ label: 'Local script', value: 'file' }
];
}
}])
.factory('GroupsList', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupList', 'GenerateList',
'Prompt', 'SearchInit', 'PaginateInit', 'ProcessErrors', 'GetBasePath', 'GroupsAdd', 'RefreshTree', 'SelectionInit',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupList, GenerateList, Prompt, SearchInit, PaginateInit,
@@ -113,9 +124,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
.factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshTree', 'ParseTypeChange',
'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshTree', 'ParseTypeChange', 'GroupsEdit',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, RefreshTree, ParseTypeChange) {
GetBasePath, RefreshTree, ParseTypeChange, GroupsEdit) {
return function(params) {
var inventory_id = params.inventory_id;
@@ -132,9 +143,14 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
scope.formModalHeader = 'Create New Group';
scope.formModalCancelShow = true;
scope.parseType = 'yaml';
scope.source = { label: 'Manual', value: null };
ParseTypeChange(scope);
$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
$('#form-modal').off('hide.bs.modal').on('hide.bs.modal', function() {
//GroupsEdit({ "inventory_id": scope['inventory_id'], group_id: scope['group_id'] });
scope.$emit('NodeSelect', scope['nodeSelectValue']);
});
generator.reset();
var master={};
@@ -218,9 +234,9 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
.factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshGroupName', 'ParseTypeChange',
'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshGroupName', 'ParseTypeChange', 'getSourceTypeOptions',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, RefreshGroupName, ParseTypeChange) {
GetBasePath, RefreshGroupName, ParseTypeChange, getSourceTypeOptions) {
return function(params) {
var group_id = params.group_id;
@@ -229,27 +245,30 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
var form = GroupForm;
var defaultUrl = GetBasePath('groups') + group_id + '/';
$('#tree-form').hide('slide',{ direction: 'right' }, 500);
$('#tree-form').empty();
$('#tree-form').hide().empty();
var scope = generator.inject(form, { mode: 'edit', modal: false, related: false, id: 'tree-form', breadCrumbs: false });
//$('#tree-form').show('slide',{ direction: 'up' }, 500);
/*
var scope = generator.inject(form, { mode: 'edit', modal: true, related: false});
*/
generator.reset();
var master = {};
var relatedSets = {};
//scope.formModalActionLabel = 'Save';
//scope.formModalHeader = 'Edit Group';
//scope.formModalCancelShow = true;
scope.source_type_options = getSourceTypeOptions();
scope.parseType = 'yaml';
scope[form.fields['source_env'].parseTypeName] = 'yaml';
scope.sourcePasswordRequired = false;
scope.sourceUsernameRequired = false;
scope.sourceUsernameLabel = 'Username';
scope.sourcePasswordLabel = 'Password';
scope.sourcePasswordConfirmLabel = 'Confirm Password';
scope.sourcePathRequired = false;
ParseTypeChange(scope);
ParseTypeChange(scope, 'source_env', form.fields['source_env'].parseTypeName);
//$('#form-modal .btn-none').removeClass('btn-none').addClass('btn-success');
// After the group record is loaded, retrieve any group variables
// After the group record is loaded, retrieve related data
if (scope.groupLoadedRemove) {
scope.groupLoadedRemove();
}
@@ -258,6 +277,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
scope.search(relatedSets[set].iterator);
}
if (scope.variable_url) {
// get group variables
Rest.setUrl(scope.variable_url);
Rest.get()
.success( function(data, status, headers, config) {
@@ -278,6 +298,65 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
scope.variables = "---";
}
master.variables = scope.variables;
if (scope.source_url) {
// get source data
Rest.setUrl(scope.source_url);
Rest.get()
.success( function(data, status, headers, config) {
for (var fld in form.fields) {
if (fld == 'checkbox_group') {
for (var i = 0; i < form.fields[fld].fields.length; i++) {
var flag = form.fields[fld].fields[i];
if (data[flag.name] !== undefined) {
scope[flag.name] = data[flag.name];
master[flag.name] = scope[flag.name];
}
}
}
if (fld == 'source') {
var found = false;
if (data['source'] == '') {
data['source'] = null;
}
for (var i=0; i < scope.source_type_options.length; i++) {
if (scope.source_type_options[i].value == data['source']) {
scope['source'] = scope.source_type_options[i];
found = true;
}
}
if (!found || scope['source'].value == null) {
scope['groupUpdateHide'] = true;
}
else {
scope['groupUpdateHide'] = false;
}
master['source'] = scope['source'];
}
else if (fld == 'source_env') {
// Parse source_env, converting to YAML.
if ($.isEmptyObject(data.source_env) || data.source_env == "\{\}" ||
data.source_env == "null" || data.source_env == "") {
scope.source_env = "---";
}
else {
var json_obj = JSON.parse(data.extra_vars);
scope.source_env = jsyaml.safeDump(json_obj);
}
master.source_env = scope.variables;
}
else if (data[fld]) {
scope[fld] = data[fld];
master[fld] = scope[fld];
}
}
})
.error( function(data, status, headers, config) {
scope.source = null;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to retrieve inventory source. GET status: ' + status });
});
}
});
// Retrieve detail record and prepopulate the form
@@ -297,6 +376,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
}
scope.variable_url = data.related.variable_data;
scope.source_url = data.related.inventory_source;
scope.$emit('groupLoaded');
})
.error( function(data, status, headers, config) {
@@ -307,9 +387,73 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
if (!scope.$$phase) {
scope.$digest();
}
if (scope.removeFormSaveSuccess) {
scope.removeFormSaveSuccess();
}
scope.removeFormSaveSuccess = scope.$on('formSaveSuccess', function(e, group_id) {
var parseError = false;
var saveError = false;
if (scope.source.value !== null && scope.source.value !== '') {
var data = { group: group_id,
source: scope['source'].value,
source_path: scope['source_path'],
source_username: scope['source_username'],
source_password: scope['source_password'],
source_regions: scope['source_regions'],
source_tags: scope['source_tags'],
overwrite_hosts: scope['overwite_hosts'],
overwrite_vars: scope['overwite_vars'],
keep_vars: scope['keep_vars'],
update_on_launch: scope['update_on_launch']
};
if (scope['source'].value == 'file') {
try {
// Make sure we have valid variable data
if (scope.envParseType == 'json') {
var json_data = JSON.parse(scope.source_env); //make sure JSON parses
}
else {
var json_data = jsyaml.load(scope.source_env); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
data.source_env = JSON.stringify(json_data, undefined, '\t');
}
catch(err) {
parseError = true;
Alert("Error", "Error parsing extra variables. Parser returned: " + err);
}
}
if (!parseError) {
Rest.setUrl(scope.source_url)
Rest.put(data)
.error( function(data, status, headers, config) {
saveError = true;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update group inventory source. PUT status: ' + status });
});
}
}
if (!saveError && !parseError) {
// Reset the form, adjust buttons and let user know changese saved
scope[form.name + '_form'].$setPristine();
scope['groupUpdateHide'] = (scope['source'].value !== null && scope['source'].value !== '') ? false : true;
Alert("Changes Saved", "Your changes to inventory group " + scope['name'] + " were successfully saved.", 'alert-info');
}
});
// Save changes to the parent
scope.formModalAction = function() {
scope.formSave = function() {
try {
var refreshHosts = false;
@@ -332,39 +476,19 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
data['inventory'] = inventory_id;
// Update hosts with new group name/description
if (master['description'] != data['description'] ||
master['name'] != data['name']) {
scope.groupTitle = '<h4>' + data['name'] + '</h4>';
scope.groupTitle += '<p>' + data['description'] + '</p>';
}
Rest.setUrl(defaultUrl);
Rest.put(data)
.success( function(data, status, headers, config) {
if (scope.variables) {
//update group variables
Rest.setUrl(GetBasePath('groups') + data.id + '/variable_data/');
Rest.setUrl(scope.variable_url);
Rest.put(json_data)
.success( function(data, status, headers, config) {
$('#form-modal').modal('hide');
RefreshGroupName($('li[group_id="' + group_id + '"]'), scope['name'])
if (refreshHosts) {
scope.$emit('hostsReload');
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update group varaibles. PUT returned status: ' + status });
{ hdr: 'Error!', msg: 'Failed to update group varaibles. PUT status: ' + status });
});
}
else {
$('#form-modal').modal('hide');
RefreshGroupName($('li[group_id="' + group_id + '"]'), scope['name']);
if (refreshHosts) {
scope.$emit('hostsReload');
}
}
scope.$emit('formSaveSuccess', data.id);
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, form,
@@ -376,14 +500,79 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
};
scope.sourceChange = function() {
if (scope['source'].value == 'ec2' || scope['source'].value == 'rackspace') {
scope.sourcePasswordRequired = true;
scope.sourceUsernameRequired = true;
if (scope['source'].value == 'ec2') {
scope.sourceUsernameLabel = 'Access Key ID';
scope.sourcePasswordLabel = 'Secret Access Key';
scope.sourcePasswordConfirmLabel = 'Confirm Secret Access Key';
}
else {
scope.sourceUsernameLabel = 'Username';
scope.sourcePasswordLabel = 'Password';
scope.sourcePasswordConfirmLabel = 'Confirm Password';
}
}
else {
scope.sourcePasswordRequired = false;
scope.sourceUsernameRequired = false;
// reset fields
scope.source_password = '';
scope.source_password_confirm = '';
scope.source_username = '';
scope[form.name + '_form']['source_username'].$setValidity('required',true);
}
if (scope['source'].value == 'file') {
scope.sourcePathRequired = true;
}
else {
scope.sourcePathRequired = false;
// reset fields
scope.source_path = '';
scope[form.name + '_form']['source_path'].$setValidity('required',true);
}
}
// Password change
scope.clearPWConfirm = function(fld) {
// If password value changes, make sure password_confirm must be re-entered
scope[fld] = '';
scope[form.name + '_form'][fld].$setValidity('awpassmatch', false);
}
// Respond to 'Ask at runtime?' checkbox
scope.ask = function(fld, associated) {
if (scope[fld + '_ask']) {
scope[fld] = 'ASK';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
else {
scope[fld] = '';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
}
}
// Click clear button
scope.clear = function(fld, associated) {
scope[fld] = '';
scope[associated] = '';
scope[form.name + '_form'][associated].$setValidity('awpassmatch', true);
scope[form.name + '_form'].$setDirty();
}
// Cancel
scope.formReset = function() {
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
scope.parseType = 'yaml';
}
generator.reset();
for (var fld in master) {
scope[fld] = master[fld];
}
scope.parseType = 'yaml';
}
}
}])

View File

@@ -20,10 +20,10 @@ angular.module('ParseHelper', [])
scope.blockParseTypeWatch = false;
scope.blockVariableDataWatch = false;
if (scope.removeParseTypeWatch) {
scope.removeParseTypeWatch();
if (scope['remove' + fld + 'Watch']) {
scope['remove' + fld + 'Watch']();
}
scope.removeParseTypeWatch = scope.$watch(pfld, function(newVal, oldVal) {
scope['remove' + fld + 'Watch'] = scope.$watch(pfld, function(newVal, oldVal) {
if (newVal !== oldVal) {
if (newVal == 'json') {
if ( scope[fld] && !/^---$/.test(scope[fld])) {

View File

@@ -28,8 +28,7 @@ angular.module('InventoriesListDefinition', [])
badgeTipPlacement: 'bottom'
},
description: {
label: 'Description',
link: true
label: 'Description'
},
organization: {
label: 'Organization',