AC-1065 in anticipation of potentially having to sort the keys of any incoming json variable objects, consolidated the variable handling code into a single helper. Anytime variable data is fetched from the API it gets passed to the helper and turned into a YAML doc. The helper checks the incoming data type for string or object. If string it first attempts to parse as YAML. If it fails, then tries JSON. If no joy, fails gracefully, logging the error and notifying the user. Anytime variables need to be sent to the API, a method in the helper is called to parse the variable text into a JSON object.

This commit is contained in:
Chris Houseknecht 2014-03-05 18:13:49 -05:00
parent 1ba917afaf
commit 93bd1d859a
8 changed files with 284 additions and 420 deletions

View File

@ -85,7 +85,8 @@ angular.module('ansible', [
'StreamListDefinition',
'HomeGroupListDefinition',
'HomeHostListDefinition',
'ActivityDetailDefinition'
'ActivityDetailDefinition',
'VariablesHelper'
])
.config(['$routeProvider',
function ($routeProvider) {

View File

@ -108,7 +108,7 @@ JobTemplatesList.$inject = ['$scope', '$rootScope', '$location', '$log', '$route
function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm,
GenerateForm, Rest, Alert, ProcessErrors, LoadBreadCrumbs, ReturnToCaller, ClearScope, GetBasePath,
InventoryList, CredentialList, ProjectList, LookUpInit, md5Setup, ParseTypeChange, Wait, Empty) {
InventoryList, CredentialList, ProjectList, LookUpInit, md5Setup, ParseTypeChange, Wait, Empty, ToJSON) {
ClearScope();
@ -286,20 +286,8 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa
$scope.formSave = function () {
generator.clearApiErrors();
Wait('start');
var data = {}, json_data, fld;
var data = {}, fld;
try {
// Make sure we have valid variable data
if ($scope.parseType === 'json') {
json_data = JSON.parse($scope.variables); //make sure JSON parses
} else {
json_data = jsyaml.load($scope.variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
for (fld in form.fields) {
if (form.fields[fld].type === 'select' && fld !== 'playbook') {
data[fld] = $scope[fld].value;
@ -309,11 +297,7 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa
}
}
}
data.extra_vars = JSON.stringify(json_data, undefined, '\t');
if (Empty(data.extra_vars)) {
data.extra_vars = "";
}
data.extra_vars = ToJSON($scope.parseType, $scope.variables, true);
Rest.setUrl(defaultUrl);
Rest.post(data)
@ -346,14 +330,14 @@ function JobTemplatesAdd($scope, $rootScope, $compile, $location, $log, $routePa
JobTemplatesAdd.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'ReturnToCaller', 'ClearScope',
'GetBasePath', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit',
'md5Setup', 'ParseTypeChange', 'Wait', 'Empty'
'md5Setup', 'ParseTypeChange', 'Wait', 'Empty', 'ToJSON'
];
function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobTemplateForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, ParseTypeChange, JobStatusToolTip, FormatDate,
Wait, Stream, Empty, Prompt) {
Wait, Stream, Empty, Prompt, ParseVariableString, ToJSON) {
ClearScope();
@ -569,7 +553,7 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
Rest.setUrl(defaultUrl + ':id/');
Rest.get({ params: { id: id } })
.success(function (data) {
var fld, i, json_obj, related, set;
var fld, i, related, set;
LoadBreadCrumbs({ path: '/job_templates/' + id, title: data.name });
for (fld in form.fields) {
if (fld !== 'variables' && data[fld] !== null && data[fld] !== undefined) {
@ -589,28 +573,8 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
master[fld] = $scope[fld];
}
if (fld === 'variables') {
// Parse extra_vars, converting to YAML.
if ($.isEmptyObject(data.extra_vars) || data.extra_vars === "{}" || data.extra_vars === "null" ||
data.extra_vars === "" || data.extra_vars === null) {
$scope.variables = "---";
} else {
$scope.variables = '---';
try {
json_obj = JSON.parse(data.extra_vars);
$scope.variables = jsyaml.safeDump(json_obj);
}
catch (e) {
$log.info('Attempt to parse extra_vars as JSON faild. Attempting to parse as YAML');
try {
json_obj = jsyaml.safeLoad(data.extra_vars);
$scope.variables = jsyaml.safeDump(json_obj);
}
catch(e2) {
ProcessErrors($scope, data.extra_vars, e2.message, null, { hdr: 'Error!',
msg: 'Attempts to parse variables as JSON and YAML failed. Last attempt returned: ' + e2.message });
}
}
}
// Parse extra_vars, converting to YAML.
$scope.variables = ParseVariableString(data.extra_vars);
master.variables = $scope.variables;
}
if (form.fields[fld].type === 'lookup' && data.summary_fields[form.fields[fld].sourceModel]) {
@ -702,20 +666,10 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
$scope.formSave = function () {
generator.clearApiErrors();
Wait('start');
var data = {}, json_data, fld;
var data = {}, fld;
try {
// Make sure we have valid variable data
if ($scope.parseType === 'json') {
json_data = JSON.parse($scope.variables); //make sure JSON parses
} else {
json_data = jsyaml.load($scope.variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
data.extra_vars = ToJSON($scope.parseType, $scope.variables, true);
for (fld in form.fields) {
if (form.fields[fld].type === 'select' && fld !== 'playbook') {
data[fld] = $scope[fld].value;
@ -725,12 +679,6 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
}
}
}
data.extra_vars = JSON.stringify(json_data, undefined, '\t');
if (data.extra_vars === "null" || data.extra_vars === null) {
data.extra_vars = "";
}
Rest.setUrl(defaultUrl + id + '/');
Rest.put(data)
.success(function (data) {
@ -810,5 +758,6 @@ function JobTemplatesEdit($scope, $rootScope, $compile, $location, $log, $routeP
JobTemplatesEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobTemplateForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords',
'GetBasePath', 'md5Setup', 'ParseTypeChange', 'JobStatusToolTip', 'FormatDate', 'Wait', 'Stream', 'Empty', 'Prompt'
'GetBasePath', 'md5Setup', 'ParseTypeChange', 'JobStatusToolTip', 'FormatDate', 'Wait', 'Stream', 'Empty', 'Prompt',
'ParseVariableString', 'ToJSON'
];

View File

@ -8,8 +8,6 @@
*
*/
/* global jsyaml:false */
'use strict';
function JobsListCtrl($scope, $rootScope, $location, $log, $routeParams, Rest, Alert, JobList, GenerateList, LoadBreadCrumbs, Prompt,
@ -189,7 +187,8 @@ JobsListCtrl.$inject = ['$scope', '$rootScope', '$location', '$log', '$routePara
function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, JobForm, JobTemplateForm, GenerateForm, Rest,
Alert, ProcessErrors, LoadBreadCrumbs, RelatedSearchInit, RelatedPaginateInit, ReturnToCaller, ClearScope, InventoryList,
CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait, Empty) {
CredentialList, ProjectList, LookUpInit, PromptPasswords, GetBasePath, md5Setup, FormatDate, JobStatusToolTip, Wait, Empty,
ParseVariableString) {
ClearScope();
@ -374,28 +373,7 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
}
}
if (fld === 'variables') {
// Parse extra_vars, converting to YAML.
if ($.isEmptyObject(data.extra_vars) || data.extra_vars === "{}" || data.extra_vars === "null" ||
data.extra_vars === "" || data.extra_vars === null) {
$scope.variables = "---";
} else {
$scope.variables = '---';
try {
json_obj = JSON.parse(data.extra_vars);
$scope.variables = jsyaml.safeDump(json_obj);
}
catch (e) {
$log.info('Attempt to parse extra_vars as JSON faild. Attempting to parse as YAML');
try {
json_obj = jsyaml.safeLoad(data.extra_vars);
$scope.variables = jsyaml.safeDump(json_obj);
}
catch(e2) {
ProcessErrors($scope, data.extra_vars, e2.message, null, { hdr: 'Error!',
msg: 'Attempts to parse variables as JSON and YAML failed. Last attempt returned: ' + e2.message });
}
}
}
$scope.variables = ParseVariableString(data.extra_vars);
}
if (JobTemplateForm.fields[fld].type === 'lookup' && data.summary_fields[JobTemplateForm.fields[fld].sourceModel]) {
$scope[JobTemplateForm.fields[fld].sourceModel + '_' + JobTemplateForm.fields[fld].sourceField] =
@ -446,5 +424,5 @@ function JobsEdit($scope, $rootScope, $compile, $location, $log, $routeParams, J
JobsEdit.$inject = ['$scope', '$rootScope', '$compile', '$location', '$log', '$routeParams', 'JobForm', 'JobTemplateForm',
'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LoadBreadCrumbs', 'RelatedSearchInit', 'RelatedPaginateInit',
'ReturnToCaller', 'ClearScope', 'InventoryList', 'CredentialList', 'ProjectList', 'LookUpInit', 'PromptPasswords',
'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait', 'Empty'
'GetBasePath', 'md5Setup', 'FormatDate', 'JobStatusToolTip', 'Wait', 'Empty', 'ParseVariableString'
];

View File

@ -12,8 +12,7 @@
angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'GroupListDefinition', 'SearchHelper',
'PaginationHelpers', 'ListGenerator', 'AuthService', 'GroupsHelper', 'InventoryHelper', 'SelectionHelper',
'JobSubmissionHelper', 'RefreshHelper', 'PromptDialog', 'CredentialsListDefinition', 'InventoryTree',
'InventoryStatusDefinition'
])
'InventoryStatusDefinition', 'VariablesHelper'])
.factory('GetSourceTypeOptions', ['Rest', 'ProcessErrors', 'GetBasePath',
function (Rest, ProcessErrors, GetBasePath) {
@ -322,10 +321,10 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
.factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'ParseTypeChange', 'Wait', 'GetChoices',
'GetSourceTypeOptions', 'LookUpInit', 'BuildTree', 'SourceChange', 'WatchInventoryWindowResize',
'GetSourceTypeOptions', 'LookUpInit', 'BuildTree', 'SourceChange', 'WatchInventoryWindowResize', 'ToJSON',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, ParseTypeChange, Wait, GetChoices, GetSourceTypeOptions, LookUpInit, BuildTree,
SourceChange, WatchInventoryWindowResize) {
SourceChange, WatchInventoryWindowResize, ToJSON) {
return function (params) {
var inventory_id = params.inventory_id,
@ -403,8 +402,7 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
var parseError = false,
data = {},
regions, r, i,
json_data;
regions, r, i;
// Update the selector tree with new group name, descr
//SetNodeName({ scope: scope['selectedNode'], group_id: group_id,
@ -428,30 +426,7 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
data.source_regions = r.join();
if (scope.source.value === 'ec2') {
// for ec2, validate variable data
try {
if (scope.envParseType === 'json') {
json_data = JSON.parse(scope.source_vars); //make sure JSON parses
} else {
json_data = jsyaml.load(scope.source_vars); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
// Send JSON as a string
if ($.isEmptyObject(json_data)) {
data.source_vars = "";
} else {
data.source_vars = JSON.stringify(json_data, undefined, '\t');
}
} catch (err) {
parseError = true;
scope.$emit('SaveComplete', true);
Alert("Error", "Error parsing extra variables. Parser returned: " + err);
}
data.source_vars = ToJSON(scope.envParseType, scope.source_vars, true);
}
if (!parseError) {
@ -484,54 +459,28 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
// Save
scope.formModalAction = function () {
var json_data, data;
var data;
Wait('start');
try {
scope.formModalActionDisabled = true;
// Make sure we have valid variable data
if (scope.parseType === 'json') {
json_data = JSON.parse(scope.variables); //make sure JSON parses
} else {
json_data = jsyaml.load(scope.variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
data = {
name: scope.name,
description: scope.description
};
if (inventory_id) {
data.inventory = inventory_id;
}
if ($.isEmptyObject(json_data)) {
data.variables = "";
} else {
data.variables = JSON.stringify(json_data, undefined, '\t');
}
Rest.setUrl(defaultUrl);
Rest.post(data)
.success(function (data) {
scope.$emit('formSaveSuccess', data.id, GetBasePath('inventory_sources') + data.id + '/');
})
.error(function (data, status) {
Wait('stop');
scope.formModalActionDisabled = false;
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new group. POST returned status: ' + status });
});
} catch (err) {
Wait('stop');
scope.formModalActionDisabled = false;
Alert("Error", "Error parsing group variables. Parser returned: " + err);
scope.formModalActionDisabled = true;
data = {
name: scope.name,
description: scope.description
};
if (inventory_id) {
data.inventory = inventory_id;
}
data.variables = ToJSON(scope.parseType, scope.variables, true);
Rest.setUrl(defaultUrl);
Rest.post(data)
.success(function (data) {
scope.$emit('formSaveSuccess', data.id, GetBasePath('inventory_sources') + data.id + '/');
})
.error(function (data, status) {
Wait('stop');
scope.formModalActionDisabled = false;
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to add new group. POST returned status: ' + status });
});
};
scope.sourceChange = function () {
@ -584,9 +533,12 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
.factory('GroupsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'SetNodeName', 'ParseTypeChange', 'GetSourceTypeOptions', 'InventoryUpdate',
'LookUpInit', 'Empty', 'Wait', 'GetChoices', 'UpdateGroup', 'SourceChange', 'Find','WatchInventoryWindowResize',
'ParseVariableString', 'ToJSON',
function ($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, SetNodeName, ParseTypeChange, GetSourceTypeOptions, InventoryUpdate, LookUpInit, Empty, Wait,
GetChoices, UpdateGroup, SourceChange, Find, WatchInventoryWindowResize) {
GetChoices, UpdateGroup, SourceChange, Find, WatchInventoryWindowResize,
ParseVariableString, ToJSON) {
return function (params) {
var parent_scope = params.scope,
@ -647,11 +599,7 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
Rest.setUrl(scope.variable_url);
Rest.get()
.success(function (data) {
if ($.isEmptyObject(data)) {
scope.variables = "---";
} else {
scope.variables = jsyaml.safeDump(data);
}
scope.variables = ParseVariableString(data);
scope.$emit('groupVariablesLoaded');
})
.error(function (data, status) {
@ -670,7 +618,7 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
Rest.setUrl(scope.source_url);
Rest.get()
.success(function (data) {
var fld, i, j, flag, found, json_obj, set, opts, list;
var fld, i, j, flag, found, set, opts, list;
for (fld in form.fields) {
if (fld === 'checkbox_group') {
for (i = 0; i < form.fields[fld].fields.length; i++) {
@ -706,13 +654,7 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
}
} else if (fld === 'source_vars') {
// Parse source_vars, converting to YAML.
if ($.isEmptyObject(data.source_vars) || data.source_vars === "{}" ||
data.source_vars === "null" || data.source_vars === "") {
scope.source_vars = "---";
} else {
json_obj = JSON.parse(data.source_vars);
scope.source_vars = jsyaml.safeDump(json_obj);
}
scope.source_vars = ParseVariableString(data.source_vars);
master.source_vars = scope.variables;
} else if (data[fld]) {
scope[fld] = data[fld];
@ -882,7 +824,7 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
// related fields, then call SaveComplete to wrap things up.
var parseError = false,
regions, r, i, json_data,
regions, r, i,
data = {
group: group_id,
source: ((scope.source && scope.source.value) ? scope.source.value : ''),
@ -903,29 +845,7 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
if (scope.source && scope.source.value === 'ec2') {
// for ec2, validate variable data
try {
if (scope.envParseType === 'json') {
json_data = JSON.parse(scope.source_vars); //make sure JSON parses
} else {
json_data = jsyaml.load(scope.source_vars); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
// Send JSON as a string
if ($.isEmptyObject(json_data)) {
data.source_vars = "";
} else {
data.source_vars = JSON.stringify(json_data);
}
} catch (err) {
parseError = true;
scope.$emit('SaveComplete', true);
Alert("Error", "Error parsing extra variables. Parser returned: " + err);
}
data.source_vars = ToJSON(scope.envParseType, scope.source_vars, true);
}
if (!parseError) {
@ -953,57 +873,42 @@ angular.module('GroupsHelper', ['RestServices', 'Utilities', 'ListGenerator', 'G
// Save
scope.formModalAction = function () {
Wait('start');
try {
var fld, data, json_data;
var fld, data, json_data;
// Make sure we have valid variable data
if (scope.parseType === 'json') {
json_data = JSON.parse(scope.variables); //make sure JSON parses
} else {
json_data = jsyaml.load(scope.variables); //parse yaml
}
json_data = ToJSON(scope.parseType, scope.variables);
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
data = {};
for (fld in form.fields) {
data[fld] = scope[fld];
}
data.inventory = inventory_id;
Rest.setUrl(defaultUrl);
Rest.put(data)
.success(function () {
if (scope.variables) {
//update group variables
Rest.setUrl(scope.variable_url);
Rest.put(json_data)
.success(function () {
scope.$emit('formSaveSuccess');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update group variables. PUT status: ' + status });
});
} else {
scope.$emit('formSaveSuccess');
}
})
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to update group: ' + group_id + '. PUT status: ' + status
});
});
} catch (err) {
Wait('stop');
Alert("Error", "Error parsing group variables. Parser returned: " + err);
data = {};
for (fld in form.fields) {
data[fld] = scope[fld];
}
data.inventory = inventory_id;
Rest.setUrl(defaultUrl);
Rest.put(data)
.success(function () {
if (scope.variables) {
//update group variables
Rest.setUrl(scope.variable_url);
Rest.put(json_data)
.success(function () {
scope.$emit('formSaveSuccess');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update group variables. PUT status: ' + status });
});
} else {
scope.$emit('formSaveSuccess');
}
})
.error(function (data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form, {
hdr: 'Error!',
msg: 'Failed to update group: ' + group_id + '. PUT status: ' + status
});
});
};
// Start the update process

View File

@ -14,7 +14,7 @@
angular.module('HostsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'HostListDefinition',
'SearchHelper', 'PaginationHelpers', 'ListGenerator', 'AuthService', 'HostsHelper',
'InventoryHelper', 'RelatedSearchHelper', 'InventoryFormDefinition', 'SelectionHelper',
'HostGroupsFormDefinition'
'HostGroupsFormDefinition', 'VariablesHelper'
])
.factory('SetEnabledMsg', [ function() {
@ -320,8 +320,9 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostList, Gener
.factory('HostsCreate', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'WatchInventoryWindowResize',
'ToJSON',
function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait, WatchInventoryWindowResize) {
GetBasePath, HostsReload, ParseTypeChange, Wait, WatchInventoryWindowResize, ToJSON) {
return function(params) {
var parent_scope = params.scope,
@ -380,55 +381,27 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
Wait('start');
try {
var fld, json_data, data={};
scope.formModalActionDisabled = true;
// Make sure we have valid variable data
if (scope.parseType === 'json') {
json_data = JSON.parse(scope.variables); //make sure JSON parses
var fld, data={};
scope.formModalActionDisabled = true;
data.variables = ToJSON(scope.parseType, scope.variables, true);
for (fld in form.fields) {
if (fld !== 'variables') {
data[fld] = scope[fld];
}
else {
json_data = jsyaml.load(scope.variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
for (fld in form.fields) {
if (fld !== 'variables') {
data[fld] = scope[fld];
}
}
data.inventory = inventory_id;
if ($.isEmptyObject(json_data)) {
data.variables = "";
}
else {
data.variables = JSON.stringify(json_data, undefined, '\t');
}
Rest.setUrl(defaultUrl);
Rest.post(data)
.success( function() {
scope.$emit('HostSaveComplete');
})
.error( function(data, status) {
Wait('stop');
scope.formModalActionDisabled = false;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new host. POST returned status: ' + status });
});
}
catch(err) {
Wait('stop');
scope.formModalActionDisabled = false;
Alert("Error", "Error parsing host variables. Parser returned: " + err);
}
data.inventory = inventory_id;
Rest.setUrl(defaultUrl);
Rest.post(data)
.success( function() {
scope.$emit('HostSaveComplete');
})
.error( function(data, status) {
Wait('stop');
scope.formModalActionDisabled = false;
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to add new host. POST returned status: ' + status });
});
};
// Cancel
@ -447,9 +420,10 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
.factory('HostsEdit', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'HostForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'HostsReload', 'ParseTypeChange', 'Wait', 'Find', 'SetStatus', 'ApplyEllipsis',
'WatchInventoryWindowResize',
'WatchInventoryWindowResize', 'ToJSON', 'ParseVariableString',
function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, GenerateForm, Prompt, ProcessErrors,
GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, WatchInventoryWindowResize) {
GetBasePath, HostsReload, ParseTypeChange, Wait, Find, SetStatus, ApplyEllipsis, WatchInventoryWindowResize, ToJSON,
ParseVariableString) {
return function(params) {
var parent_scope = params.scope,
@ -486,12 +460,7 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
Rest.setUrl(scope.variable_url);
Rest.get()
.success( function(data) {
if ($.isEmptyObject(data)) {
scope.variables = "---";
}
else {
scope.variables = jsyaml.safeDump(data);
}
scope.variables = ParseVariableString(data);
scope.$emit('hostVariablesLoaded');
})
.error( function(data, status) {
@ -570,49 +539,23 @@ function($rootScope, $location, $log, $routeParams, Rest, Alert, HostForm, Gener
scope.formModalAction = function() {
Wait('start');
try {
// Make sure we have valid variable data
var fld, json_data, data={};
if (scope.parseType === 'json') {
json_data = JSON.parse(scope.variables); //make sure JSON parses
}
else {
json_data = jsyaml.load(scope.variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
for (fld in form.fields) {
data[fld] = scope[fld];
}
data.inventory = inventory_id;
if ($.isEmptyObject(json_data)) {
data.variables = "";
}
else {
data.variables = JSON.stringify(json_data, undefined, '\t');
}
Rest.setUrl(defaultUrl);
Rest.put(data)
.success( function() {
scope.$emit('saveCompleted');
})
.error( function(data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update host: ' + host_id + '. PUT returned status: ' + status });
});
}
catch(err) {
Wait('stop');
Alert("Error", "Error parsing host variables. Parser returned: " + err);
var fld, data={};
data.variables = ToJSON(scope.parseType, scope.variables, true);
for (fld in form.fields) {
data[fld] = scope[fld];
}
data.inventory = inventory_id;
Rest.setUrl(defaultUrl);
Rest.put(data)
.success( function() {
scope.$emit('saveCompleted');
})
.error( function(data, status) {
Wait('stop');
ProcessErrors(scope, data, status, form,
{ hdr: 'Error!', msg: 'Failed to update host: ' + host_id + '. PUT returned status: ' + status });
});
};
// Cancel

View File

@ -0,0 +1,109 @@
/*********************************************
* Copyright (c) 2014 AnsibleWorks, Inc.
*
* VariablesHelper
*
* Show the CodeMirror variable editor and allow
* toggle between JSON and YAML
*
*/
'use strict';
angular.module('VariablesHelper', ['Utilities'])
/**
variables: string containing YAML or JSON | a JSON object.
If JSON string, convert to JSON object and run through jsyaml.safeDump() to create a YAML document. If YAML,
will attempt to load via jsyaml.safeLoad() and return a YAML document using jsyaml.safeDump(). In all cases
a YAML document is returned.
**/
.factory('ParseVariableString', ['$log', 'ProcessErrors', function ($log, ProcessErrors) {
return function (variables) {
var result = "---", json_obj;
if (typeof variables === 'string') {
if ($.isEmptyObject(variables) || variables === "{}" || variables === "null" ||
variables === "" || variables === null) {
// String is empty, return ---
} else {
try {
json_obj = JSON.parse(variables);
result = jsyaml.safeDump(json_obj);
}
catch (e) {
$log.info('Attempt to parse extra_vars as JSON faild. Attempting to parse as YAML');
try {
json_obj = jsyaml.safeLoad(variables);
result = jsyaml.safeDump(json_obj);
}
catch(e2) {
ProcessErrors(null, variables, e2.message, null, { hdr: 'Error!',
msg: 'Attempts to parse variables as JSON and YAML failed. Last attempt returned: ' + e2.message });
}
}
}
}
else {
// an object was passed in. just convert to yaml
try {
result = jsyaml.safeDump(variables);
}
catch(e3) {
ProcessErrors(null, variables, e3.message, null, { hdr: 'Error!',
msg: 'Attempt to convert JSON object to YAML document failed: ' + e3.message });
}
}
return result;
};
}])
/**
parseType: 'json' | 'yaml'
variables: string containing JSON or YAML
stringify: optional, boolean
Parse the given string according to the parseType to a JSON object. If stringify true,
stringify the object and return the string. Otherwise, return the JSON object.
**/
.factory('ToJSON', ['$log', 'ProcessErrors', function($log, ProcessErrors) {
return function(parseType, variables, stringify) {
var json_data, result;
if (parseType === 'json') {
try {
json_data = JSON.parse(variables); //make sure JSON parses
}
catch(e) {
json_data = {};
$log.error('Failed to parse JSON string. Parser returned: ' + e.message);
ProcessErrors(null, variables, e.message, null, { hdr: 'Error!',
msg: 'Failed to parse JSON string. Parser returned: ' + e.message });
}
} else {
try {
json_data = jsyaml.load(variables);
}
catch(e) {
json_data = {};
$log.error('Failed to parse YAML string. Parser returned: ' + e.message);
ProcessErrors(null, variables, e.message, null, { hdr: 'Error!',
msg: 'Failed to parse YAML string. Parser returned: ' + e.message });
}
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
ProcessErrors(null, variables, null, null, { hdr: 'Error!',
msg: 'Failed to parse variables. Attempted to parse ' + parseType + ' Parser did not return an object.' });
}
result = json_data;
if (stringify) {
if ($.isEmptyObject(json_data)) {
result = "";
} else {
result = JSON.stringify(json_data, undefined, '\t');
}
}
return result;
};
}]);

View File

@ -11,7 +11,7 @@
'use strict';
angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationListDefinition', 'ListGenerator', 'AuthService',
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper'
'InventoryHelper', 'InventoryFormDefinition', 'ParseHelper', 'SearchHelper', 'VariablesHelper',
])
.factory('WatchInventoryWindowResize', ['ApplyEllipsis',
@ -40,8 +40,9 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis
])
.factory('SaveInventory', ['InventoryForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'Wait',
function (InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait) {
'GetBasePath', 'ParseTypeChange', 'Wait', 'ToJSON',
function (InventoryForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, Wait,
ToJSON) {
return function (params) {
// Save inventory property modifications
@ -52,67 +53,58 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis
fld, json_data, data;
Wait('start');
// Make sure we have valid variable data
json_data = ToJSON(scope.inventoryParseType, scope.inventory_variables);
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
try {
// Make sure we have valid variable data
if (scope.inventoryParseType === 'json') {
json_data = JSON.parse(scope.inventory_variables); //make sure JSON parses
} else {
json_data = jsyaml.load(scope.inventory_variables); //parse yaml
}
// Make sure our JSON is actually an object
if (typeof json_data !== 'object') {
throw "failed to return an object!";
}
data = {};
for (fld in form.fields) {
if (fld !== 'inventory_variables') {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
} else {
data[fld] = scope[fld];
}
data = {};
for (fld in form.fields) {
if (fld !== 'inventory_variables') {
if (form.fields[fld].realName) {
data[form.fields[fld].realName] = scope[fld];
} else {
data[fld] = scope[fld];
}
}
Rest.setUrl(defaultUrl + scope.inventory_id + '/');
Rest.put(data)
.success(function (data) {
if (scope.inventory_variables) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success(function () {
Wait('stop');
scope.$emit('InventorySaved');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory varaibles. PUT returned status: ' + status
});
});
} else {
scope.$emit('InventorySaved');
}
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory. POST returned status: ' + status });
});
} catch (err) {
Wait('stop');
Alert("Error", "Error parsing inventory variables. Parser returned: " + err);
}
Rest.setUrl(defaultUrl + scope.inventory_id + '/');
Rest.put(data)
.success(function (data) {
if (scope.inventory_variables) {
Rest.setUrl(data.related.variable_data);
Rest.put(json_data)
.success(function () {
Wait('stop');
scope.$emit('InventorySaved');
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory varaibles. PUT returned status: ' + status
});
});
} else {
scope.$emit('InventorySaved');
}
})
.error(function (data, status) {
ProcessErrors(scope, data, status, form, { hdr: 'Error!',
msg: 'Failed to update inventory. POST returned status: ' + status });
});
};
}
])
.factory('EditInventoryProperties', ['InventoryForm', 'GenerateForm', 'Rest', 'Alert', 'ProcessErrors', 'LookUpInit', 'OrganizationList',
'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', 'Store', 'SearchInit',
'GetBasePath', 'ParseTypeChange', 'SaveInventory', 'Wait', 'Store', 'SearchInit', 'ParseVariableString',
function (InventoryForm, GenerateForm, Rest, Alert, ProcessErrors, LookUpInit, OrganizationList, GetBasePath, ParseTypeChange, SaveInventory,
Wait, Store, SearchInit) {
Wait, Store, SearchInit, ParseVariableString) {
return function (params) {
var parent_scope = params.scope,
@ -146,23 +138,10 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis
Rest.setUrl(GetBasePath('inventory') + inventory_id + '/');
Rest.get()
.success(function (data) {
var fld, json_obj;
var fld;
for (fld in form.fields) {
if (fld === 'inventory_variables') {
// Parse variables, converting to YAML.
if ($.isEmptyObject(data.variables) || data.variables === "{}" ||
data.variables === "null" || data.variables === "") {
scope.inventory_variables = "---";
} else {
try {
json_obj = JSON.parse(data.variables);
scope.inventory_variables = jsyaml.safeDump(json_obj);
} catch (err) {
Alert('Variable Parse Error', 'Attempted to parse variables for inventory: ' + inventory_id +
'. Parse returned: ' + err);
scope.inventory_variables = '---';
}
}
scope.inventory_variables = ParseVariableString(data.variables);
master.inventory_variables = scope.variables;
} else if (fld === 'inventory_name') {
scope[fld] = data.name;
@ -174,7 +153,6 @@ angular.module('InventoryHelper', ['RestServices', 'Utilities', 'OrganizationLis
scope[fld] = data[fld];
master[fld] = scope[fld];
}
if (form.fields[fld].sourceModel && data.summary_fields &&
data.summary_fields[form.fields[fld].sourceModel]) {
scope[form.fields[fld].sourceModel + '_' + form.fields[fld].sourceField] =

View File

@ -127,6 +127,7 @@
<script src="{{ STATIC_URL }}js/helpers/Permissions.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Groups.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Hosts.js"></script>
<script src="{{ STATIC_URL }}js/helpers/Variables.js"></script>
<script src="{{ STATIC_URL }}js/widgets/JobStatus.js"></script>
<script src="{{ STATIC_URL }}js/widgets/InventorySyncStatus.js"></script>
<script src="{{ STATIC_URL }}js/widgets/SCMSyncStatus.js"></script>