AC-503 latest cloud inventory changes

This commit is contained in:
chouseknecht
2013-10-03 05:26:16 -04:00
parent c7f096f16b
commit 6bf8f9cd98
9 changed files with 293 additions and 224 deletions

View File

@@ -128,6 +128,12 @@ function InventoryGroups ($scope, $rootScope, $compile, $location, $log, $routeP
var type = node.attr('type');
var url;
if ($rootScope.timer) {
// Kill any linger timers from the inventory summary page
clearInterval($rootScope.timer);
$rootScope.timer = null;
}
scope['nodeSelectValue'] = n;
scope['selectedNode'] = node;
scope['selectedNodeName'] = node.attr('name');

View File

@@ -9,7 +9,7 @@
angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', 'GroupListDefinition',
'SearchHelper', 'PaginateHelper', 'ListGenerator', 'AuthService', 'GroupsHelper',
'InventoryHelper', 'SelectionHelper', 'JobSubmissionHelper'
'InventoryHelper', 'SelectionHelper', 'JobSubmissionHelper', 'RefreshHelper'
])
.factory('getSourceTypeOptions', [ function() {
@@ -56,7 +56,7 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
GetBasePath('inventory') + inventory_id + '/groups/';
SelectionInit({ scope: scope, list: list, url: url });
var finish = scope.formModalAction;
scope.formModalAction = function() {
var groups = [];
for (var j=0; j < scope.selected.length; j++) {
@@ -93,6 +93,8 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}
}
}
var finish = scope.formModalAction;
if (scope.PostRefreshRemove) {
scope.PostRefreshRemove();
@@ -123,6 +125,112 @@ angular.module('GroupsHelper', [ 'RestServices', 'Utilities', 'ListGenerator', '
}])
.factory('InventoryStatus', [ '$rootScope', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventorySummary',
'GenerateList', 'ClearScope', 'SearchInit', 'PaginateInit', 'Refresh', 'InventoryUpdate',
function($rootScope, Rest, Alert, ProcessErrors, GetBasePath, FormatDate, InventorySummary, GenerateList, ClearScope, SearchInit,
PaginateInit, Refresh, InventoryUpdate) {
return function(params) {
//Build a summary of a given inventory
ClearScope('tree-form');
$('#tree-form').hide().empty();
var view = GenerateList;
var list = InventorySummary;
var scope = view.inject(InventorySummary, { mode: 'summary', id: 'tree-form', breadCrumbs: false });
var defaultUrl = GetBasePath('inventory') + scope['inventory_id'] + '/inventory_sources/';
if (scope.PostRefreshRemove) {
scope.PostRefreshRemove();
}
scope.PostRefreshRemove = scope.$on('PostRefresh', function() {
for (var i=0; i < scope.groups.length; i++) {
var last_update = (scope.groups[i].last_updated == null) ? '' : FormatDate(new Date(scope.groups[i].last_updated));
var source = 'Manual';
var stat;
var stat_class;
switch (scope.groups[i].status) {
case 'never updated':
stat = 'never';
stat_class = 'never';
break;
case 'none':
stat = 'n/a';
stat_class = 'na';
break;
default:
stat = scope.groups[i].status;
stat_class = stat;
}
switch (scope.groups[i].source) {
case 'file':
source = 'File';
break;
case 'ec2':
source = 'Amazon EC2';
break;
case 'rackspace':
source = 'Rackspace';
break;
}
scope.groups[i].status = stat;
scope.groups[i].source = source;
scope.groups[i].last_updated = last_update;
scope.groups[i].status_class = stat_class;
}
});
SearchInit({ scope: scope, set: 'groups', list: list, url: defaultUrl });
PaginateInit({ scope: scope, list: list, url: defaultUrl });
scope.search(list.iterator);
scope.refresh = function() {
scope['groupSearchSpin'] = true;
scope['groupLoading'] = true;
Refresh({ scope: scope, set: 'groups', iterator: 'group', url: scope['current_url'] });
}
// Start the update process
scope.updateGroup = function(id) {
for (var i=0; i < scope.groups.length; i++) {
if (scope.groups[i].id == id) {
if (scope.groups[i].source == "" || scope.groups[i].source == null) {
Alert('Missing Configuration', 'The selected group is not configured for updates. You must first edit the group, provide Source settings, ' +
'and then run an update.', 'alert-info');
}
else if (scope.groups[i].status == 'updating') {
Alert('Update in Progress', 'The inventory update process is currently running for group <em>' +
scope.groups[i].summary_fields.group.name + '</em>. Use the Refresh button to monitor the status.', 'alert-info');
}
else {
if (scope.groups[i].source == 'Amazon 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';
}
InventoryUpdate({
scope: scope,
group_id: id,
url: scope.groups[i].related.update,
group_name: scope.groups[i].summary_fields.group.name,
group_source: scope.groups[i].source
});
}
break;
}
}
}
}
}])
.factory('GroupsAdd', ['$rootScope', '$location', '$log', '$routeParams', 'Rest', 'Alert', 'GroupForm', 'GenerateForm',
'Prompt', 'ProcessErrors', 'GetBasePath', 'RefreshTree', 'ParseTypeChange', 'GroupsEdit',
function($rootScope, $location, $log, $routeParams, Rest, Alert, GroupForm, GenerateForm, Prompt, ProcessErrors,

View File

@@ -5,7 +5,7 @@
*
*/
angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'CredentialFormDefinition', 'CredentialsListDefinition',
'LookUpHelper', 'ProjectFormDefinition', 'JobSubmissionHelper', 'GroupFormDefinition'])
'LookUpHelper', 'ProjectFormDefinition', 'JobSubmissionHelper', 'GroupFormDefinition', 'GroupsHelper' ])
.factory('PromptPasswords', ['CredentialForm', 'JobTemplateForm', 'ProjectsForm', '$compile', 'Rest', '$location', 'ProcessErrors', 'GetBasePath',
'Alert',
@@ -107,7 +107,9 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
fld = passwords[i];
scope[fld] = '';
html += "<div class=\"form-group\">\n";
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + '">* ' + field.label + '</label>' + "\n";
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + "\">* ";
html += (field.labelBind) ? scope[field.labelBind] : field.label;
html += "</label>\n";
html += "<div class=\"col-lg-9\">\n";
html += "<input type=\"password\" ";
html += "ng-model=\"" + fld + '" ';
@@ -128,7 +130,9 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
field = (form.fields[field.associated]) ? form.fields[field.associated] : ProjectsForm.fields[field.associated];
scope[fld] = '';
html += "<div class=\"form-group\">\n";
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + '">* ' + field.label + '</label>' + "\n";
html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"" + fld + "\">* ";
html += (field.labelBind) ? scope[field.labelBind] : field.label;
html += "</label>\n";
html += "<div class=\"col-lg-9\">\n";
html += "<input type=\"password\" ";
html += "ng-model=\"" + fld + '" ';
@@ -357,8 +361,9 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
// Sumbit Inventory Update request
.factory('InventoryUpdate',['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert', 'GroupForm',
function(PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm) {
.factory('InventoryUpdate',['PromptPasswords', '$compile', 'Rest', '$location', 'GetBasePath', 'ProcessErrors', 'Alert',
'GroupForm', 'InventorySummary',
function(PromptPasswords, $compile, Rest, $location, GetBasePath, ProcessErrors, Alert, GroupForm, InventorySummary) {
return function(params) {
var scope = params.scope;
@@ -370,7 +375,10 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
}
scope.removeUpdateSubmitted = scope.$on('UpdateSubmitted', function() {
// Refresh the project list after update request submitted
scope.refresh();
//$location.path(GetBasePath('inventories') + inventory_id + '/groups'
InventorySummary({ scope: scope });
$('#tree-form').show();
//scope.refresh();
});
if (scope.removeInventorySubmit) {
@@ -392,37 +400,8 @@ angular.module('JobSubmissionHelper', [ 'RestServices', 'Utilities', 'Credential
Rest.get()
.success( function(data, status, headers, config) {
if (data.can_update) {
var extra_html = '';
/*
for (var i=0; i < scope.projects.length; i++) {
if (scope.projects[i].id == project_id) {
extra_html += "<div class=\"form-group\">\n";
extra_html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"scm_url\">SCM URL</label>\n";
extra_html += "<div class=\"col-lg-9\">\n";
extra_html += "<input type=\"text\" readonly";
extra_html += ' name=\"scm_url\" ';
extra_html += "class=\"form-control\" ";
extra_html += "value=\"" + scope.projects[i].scm_url + "\" ";
extra_html += "/>";
extra_html += "</div>\n";
extra_html += "</div>\n";
if (scope.projects[i].scm_username) {
extra_html += "<div class=\"form-group\">\n";
extra_html += "<label class=\"control-label col-lg-3 normal-weight\" for=\"scm_username\">SCM Username</label>\n";
extra_html += "<div class=\"col-lg-9\">\n";
extra_html += "<input type=\"text\" readonly";
extra_html += ' name=\"scm_username\" ';
extra_html += "class=\"form-control\" ";
extra_html += "value=\"" + scope.projects[i].scm_username + "\" ";
extra_html += "/>";
extra_html += "</div>\n";
extra_html += "</div>\n";
}
break;
}
}
extra_html += "</p>";
*/
var extra_html = "<div class=\"inventory-passwd-msg\">Starting inventory update for the <em>" + params.group_name +
"</em> group. Please provide the " + params.group_source + " credentials:</div>\n";
scope.$emit('InventorySubmit', data.passwords_needed_to_update, extra_html);
}
else {

View File

@@ -667,106 +667,5 @@ angular.module('InventoryHelper', [ 'RestServices', 'Utilities', 'OrganizationLi
}
return newData;
}
}])
.factory('InventoryStatus', [ '$rootScope', 'Rest', 'Alert', 'ProcessErrors', 'GetBasePath', 'FormatDate', 'InventorySummary',
'GenerateList', 'ClearScope',
function($rootScope, Rest, Aler, ProcessErrors, GetBasePath, FormatDate, InventorySummary, GenerateList, ClearScope) {
return function(params) {
//Build a summary of a given inventory
ClearScope('tree-form');
$('#tree-form').hide().empty();
var view = GenerateList;
var scope = view.inject(InventorySummary, { mode: 'summary', id: 'tree-form', breadCrumbs: false });
var total;
var cnt=0;
var groups = new Array();
if (scope.RemoveGroupsLoaded) {
scope.RemoveGroupsLoaded();
}
scope.RemoveGroupsLoaded = scope.$on('GroupsLoaded', function() {
// Using this sort of indirect method of updating scope['groups'] works. Pushing data directly into
// scope['groups'] directly causes it to grow exponentially with duplicates each time user navigates away
// and comes back -despite emptying/resetting/initializing.
scope['groups'] = groups;
if (!scope.$$phase) {
scope.$apply();
}
});
function checkSource(url) {
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
var last_update = (data.last_updated == null) ? '' : FormatDate(new Date(data.last_updated));
var source = 'Manual';
var stat;
switch (data.status) {
case 'never updated':
stat = 'never';
break;
case 'none':
stat = 'na';
break;
default:
stat = data.status;
}
switch(data.source) {
case 'file':
source = 'File';
break;
case 'ec2':
source = 'Amazon EC2';
break;
case 'rackspace':
source = 'Rackspace';
break;
}
groups.push({
name: data.summary_fields.group.name,
description: data.summary_fields.group.description,
failures: data.summary_fields.group.hosts_with_active_failures,
source: source,
last_update: last_update,
status: stat,
has_active_failures: data.summary_fields.group.has_active_failures
});
cnt++;
if (cnt >= total) {
scope.$emit('GroupsLoaded');
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST status: ' + status });
});
}
var url = GetBasePath('inventory') + scope['inventory_id'] + '/groups/';
Rest.setUrl(url);
Rest.get()
.success( function(data, status, headers, config) {
total = data.count;
for (var i=0; i < data.results.length; i++) {
if (data.results[i].related.inventory_source) {
checkSource(data.results[i].related.inventory_source);
}
}
})
.error( function(data, status, headers, config) {
ProcessErrors(scope, data, status, null,
{ hdr: 'Error!', msg: 'Call to ' + url + ' failed. POST status: ' + status });
});
}
}]);

View File

@@ -125,6 +125,11 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
scope[iterator + 'SearchParams'] = list.fields[scope[iterator + 'SearchField']].sourceModel + '__' +
list.fields[scope[iterator + 'SearchField']].sourceField + '__';
}
else if ( (list.fields[scope[iterator + 'SearchField']].searchType == 'select') &&
(scope[iterator + 'SearchSelectValue'].value == '' ||
scope[iterator + 'SearchSelectValue'].value == null) ) {
scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'];
}
else {
scope[iterator + 'SearchParams'] = scope[iterator + 'SearchField'] + '__';
}
@@ -138,6 +143,11 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
list.fields[scope[iterator + 'SearchField']].searchType == 'gtzero' ) {
scope[iterator + 'SearchParams'] += 'gt=0';
}
else if ( (list.fields[scope[iterator + 'SearchField']].searchType == 'select') &&
(scope[iterator + 'SearchSelectValue'].value == '' ||
scope[iterator + 'SearchSelectValue'].value == null) ) {
scope[iterator + 'SearchParams'] += '=';
}
else {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchType'] + '=';
}
@@ -145,7 +155,7 @@ angular.module('SearchHelper', ['RestServices', 'Utilities', 'RefreshHelper'])
if ( list.fields[scope[iterator + 'SearchField']].searchType &&
(list.fields[scope[iterator + 'SearchField']].searchType == 'boolean'
|| list.fields[scope[iterator + 'SearchField']].searchType == 'select') ) {
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value;
scope[iterator + 'SearchParams'] += scope[iterator + 'SearchSelectValue'].value;
}
else {
//if ( list.fields[scope[iterator + 'SearchField']].searchType == undefined ||

View File

@@ -23,36 +23,88 @@ angular.module('InventorySummaryDefinition', [])
key: true,
label: 'Group',
noLink: true,
ngBind: "group.summary_fields.group.name",
sourceModel: 'group',
sourceField: 'name',
badges: [
{ //Active Failures
icon: "\{\{ 'icon-failures-' + group.has_active_failures \}\}",
icon: "\{\{ 'icon-failures-' + group.summary_fields.group.has_active_failures \}\}",
toolTip: 'Indicates if inventory contains hosts with active failures',
toolTipPlacement: 'bottom'
},
{ //Cloud Status
icon: "\{\{ 'icon-cloud-' + group.status \}\}",
toolTip: 'Indicates if inventory contains hosts with active failures',
icon: "\{\{ 'icon-cloud-' + group.status_class \}\}",
toolTip: 'Indicates status of inventory update process',
toolTipPlacement: 'bottom'
}]
},
failures: {
label: 'Active<br />Failures'
label: 'Active<br>Failures',
ngBind: "group.summary_fields.group.hosts_with_active_failures",
sourceModel: 'group',
sourceField: 'hosts_with_active_failures',
searchField: 'group__has_active_failures',
searchType: 'boolean',
searchOptions: [{ name: "yes", value: 1 }, { name: "no", value: 0 }]
},
source: {
label: 'Source'
label: 'Source',
searchType: 'select',
searchOptions: [
{ name: "Amazon EC2", value: "ec2" },
{ name: "Local Script", value: "file" },
{ name: "Manual", value: "" },
{ name: "Rackspace", value: "rackspace" }]
},
last_update: {
label: 'Last<br />Updated'
last_updated: {
label: 'Last<br>Updated',
searchable: false
},
status: {
label: 'Update<br />Status'
label: 'Update<br>Status',
searchType: 'select',
searchOptions: [
{ name: "failed", value: "failed" },
{ name: "never", value: "never updated" },
{ name: "n/a", value: "none" },
{ name: "successful", value: "successful" },
{ name: "updating", value: "updating" }]
}
},
actions: {
actions: {
refresh: {
awRefresh: true,
mode: 'all'
},
help: {
awPopOver:
"<dl>\n" +
"<dt>failed</dt><dd>Errors were encountered with the most recent inventory update.</dd>\n" +
"<dt>n/a</dt><dd>The group is not configured for inventory update.</dd>\n" +
"<dt>never</dt><dd>The inventory update has never run for the group.</dd>\n" +
"<dt>successful</dt><dd>The most recent inventory update ran to completion without incident.</dd>\n" +
"<dt>updating</dt><dd>The inventory update is currently running.</dd>\n" +
"</dl>\n",
dataPlacement: 'left',
dataContainer: 'body',
icon: "icon-question-sign",
mode: 'all',
'class': 'btn-xs btn-info btn-help pull-right',
awToolTip: 'Click for help',
dataTitle: 'Update Status',
iconSize: 'large'
}
},
fieldActions: {
group_update: {
label: 'Update',
icon: 'icon-cloud-download',
"class": 'btn-xs btn-success',
ngClick: 'updateGroup(\{\{ group.id \}\})',
awToolTip: 'Perform an update on this group'
}
}
});