wip - integrate adhoc and workflow

This commit is contained in:
Jake McDermott
2018-03-27 12:39:30 -04:00
parent 91e5659042
commit b10dc6d4ff
10 changed files with 103 additions and 46 deletions

View File

@@ -12,6 +12,8 @@ let resource;
let strings; let strings;
let wait; let wait;
let vm;
function mapChoices (choices) { function mapChoices (choices) {
if (!choices) return {}; if (!choices) return {};
return Object.assign(...choices.map(([k, v]) => ({ [k]: v }))); return Object.assign(...choices.map(([k, v]) => ({ [k]: v })));
@@ -33,7 +35,7 @@ function getStatusDetails (status) {
return { label, icon, value }; return { label, icon, value };
} }
function getStartTimeDetails (started) { function getStartDetails (started) {
const unfiltered = started || resource.model.get('started'); const unfiltered = started || resource.model.get('started');
const label = 'Started'; const label = 'Started';
@@ -49,7 +51,7 @@ function getStartTimeDetails (started) {
return { label, value }; return { label, value };
} }
function getFinishTimeDetails (finished) { function getFinishDetails (finished) {
const unfiltered = finished || resource.model.get('finished'); const unfiltered = finished || resource.model.get('finished');
const label = 'Finished'; const label = 'Finished';
@@ -416,6 +418,17 @@ function cancelJob () {
function deleteJob () {} function deleteJob () {}
function handleSocketEvent (data) {
const project = resource.model.get('project');
if (resource.model.get('id') === data.unified_job_id) {
vm.status = getStatusDetails(data.status);
} else if (project && (project === data.project_id)) {
vm.project.update = vm.project.update || {};
vm.project.update.status = data.status;
}
};
function AtDetailsController ( function AtDetailsController (
_$http_, _$http_,
_$filter_, _$filter_,
@@ -427,7 +440,7 @@ function AtDetailsController (
ParseTypeChange, ParseTypeChange,
ParseVariableString, ParseVariableString,
) { ) {
const vm = this || {}; vm = this || {};
$http = _$http_; $http = _$http_;
$filter = _$filter_; $filter = _$filter_;
@@ -444,8 +457,8 @@ function AtDetailsController (
resource = $scope.resource; // eslint-disable-line prefer-destructuring resource = $scope.resource; // eslint-disable-line prefer-destructuring
vm.status = getStatusDetails(); vm.status = getStatusDetails();
vm.started = getStartTimeDetails(); vm.started = getStartDetails();
vm.finished = getFinishTimeDetails(); vm.finished = getFinishDetails();
vm.jobType = getJobTypeDetails(); vm.jobType = getJobTypeDetails();
vm.jobTemplate = getJobTemplateDetails(); vm.jobTemplate = getJobTemplateDetails();
vm.sourceWorkflowJob = getSourceWorkflowJobDetails(); vm.sourceWorkflowJob = getSourceWorkflowJobDetails();
@@ -488,13 +501,10 @@ function AtDetailsController (
vm.deleteJob = deleteJob; vm.deleteJob = deleteJob;
vm.toggleLabels = toggleLabels; vm.toggleLabels = toggleLabels;
const observe = (key, transform) => { $scope.$watch('started', value => { vm.started = getStartDetails(value); });
$scope.$watch(key, value => { vm[key] = transform(value); }); $scope.$watch('finished', value => { vm.finished = getFinishDetails(value); });
};
observe('finished', getFinishTimeDetails); $scope.$on(resource.ws.status, (e, data) => handleSocketEvent(data));
observe('status', getStatusDetails);
observe('started', getStartTimeDetails);
}; };
} }
@@ -525,10 +535,9 @@ function atDetails () {
link: atDetailsLink, link: atDetailsLink,
controller: AtDetailsController, controller: AtDetailsController,
scope: { scope: {
resource: '=',
status: '=',
started: '=',
finished: '=', finished: '=',
started: '=',
resource: '=',
}, },
}; };
} }

View File

@@ -84,12 +84,14 @@ function JobsIndexController (
eventCounter = null; eventCounter = null;
statsEvent = resource.stats; statsEvent = resource.stats;
// Panel Title
vm.title = resource.model.get('name');
// Status Bar // Status Bar
vm.status = { vm.status = {
stats: statsEvent, stats: statsEvent,
elapsed: resource.model.get('elapsed'), elapsed: resource.model.get('elapsed'),
running: Boolean(resource.model.get('started')) && !resource.model.get('finished'), running: Boolean(resource.model.get('started')) && !resource.model.get('finished'),
title: resource.model.get('name'),
plays: null, plays: null,
tasks: null, tasks: null,
}; };
@@ -99,7 +101,6 @@ function JobsIndexController (
resource, resource,
started: resource.model.get('started'), started: resource.model.get('started'),
finished: resource.model.get('finished'), finished: resource.model.get('finished'),
status: resource.model.get('status'),
}; };
render.requestAnimationFrame(() => init(!vm.status.running)); render.requestAnimationFrame(() => init(!vm.status.running));
@@ -143,7 +144,7 @@ function init (pageMode) {
} }
}); });
$scope.$on(resource.ws.namespace, handleSocketEvent); $scope.$on(resource.ws.events, handleSocketEvent);
if (pageMode) { if (pageMode) {
next(); next();

View File

@@ -32,6 +32,7 @@ function resolveResource (
Wait Wait
) { ) {
const { id, type, job_event_search } = $stateParams; // eslint-disable-line camelcase const { id, type, job_event_search } = $stateParams; // eslint-disable-line camelcase
const { name, key } = getWebSocketResource(type);
let Resource; let Resource;
let related = 'events'; let related = 'events';
@@ -50,9 +51,9 @@ function resolveResource (
case 'system': case 'system':
Resource = SystemJob; Resource = SystemJob;
break; break;
case 'workflow': // case 'workflow':
Resource = WorkflowJob; // todo: integrate workflow chart components into this view
break; // break;
default: default:
// Redirect // Redirect
return null; return null;
@@ -87,7 +88,8 @@ function resolveResource (
model, model,
related, related,
ws: { ws: {
namespace: `${WS_PREFIX}-${getWebSocketResource(type).key}-${id}` events: `${WS_PREFIX}-${key}-${id}`,
status: `${WS_PREFIX}-${name}`,
}, },
page: { page: {
cache: PAGE_CACHE, cache: PAGE_CACHE,
@@ -99,22 +101,23 @@ function resolveResource (
.finally(() => Wait('stop')); .finally(() => Wait('stop'));
} }
function resolveWebSocketConnection (SocketService, $stateParams) { function resolveWebSocketConnection ($stateParams, SocketService) {
const { type, id } = $stateParams; const { type, id } = $stateParams;
const resource = getWebSocketResource(type); const { name, key } = getWebSocketResource(type);
const state = { const state = {
data: { data: {
socket: { socket: {
groups: { groups: {
[resource.name]: ['status_changed', 'summary'], [name]: ['status_changed', 'summary'],
[resource.key]: [] [key]: []
} }
} }
} }
}; };
SocketService.addStateResolve(state, id); return SocketService.addStateResolve(state, id);
} }
function resolveBreadcrumb (strings) { function resolveBreadcrumb (strings) {
@@ -129,19 +132,19 @@ function getWebSocketResource (type) {
switch (type) { switch (type) {
case 'system': case 'system':
name = 'system_jobs'; name = 'jobs';
key = 'system_job_events'; key = 'system_job_events';
break; break;
case 'project': case 'project':
name = 'project_updates'; name = 'jobs';
key = 'project_update_events'; key = 'project_update_events';
break; break;
case 'command': case 'command':
name = 'ad_hoc_commands'; name = 'jobs';
key = 'ad_hoc_command_events'; key = 'ad_hoc_command_events';
break; break;
case 'inventory': case 'inventory':
name = 'inventory_updates'; name = 'jobs';
key = 'inventory_update_events'; key = 'inventory_update_events';
break; break;
case 'playbook': case 'playbook':
@@ -188,10 +191,10 @@ function JobsRun ($stateRegistry) {
resolveBreadcrumb resolveBreadcrumb
], ],
webSocketConnection: [ webSocketConnection: [
'SocketService',
'$stateParams', '$stateParams',
'SocketService',
resolveWebSocketConnection resolveWebSocketConnection
] ],
}, },
}; };
@@ -208,6 +211,7 @@ angular
.service('JobStrings', Strings) .service('JobStrings', Strings)
.service('JobPageService', PageService) .service('JobPageService', PageService)
.service('JobScrollService', ScrollService) .service('JobScrollService', ScrollService)
.service('JobRenderService', RenderService)
.service('JobEventEngine', EngineService) .service('JobEventEngine', EngineService)
.directive('atDetails', DetailsDirective) .directive('atDetails', DetailsDirective)
.directive('atSearchKey', SearchKeyDirective) .directive('atSearchKey', SearchKeyDirective)

View File

@@ -3,7 +3,6 @@
<at-panel> <at-panel>
<at-details <at-details
resource="vm.details.resource" resource="vm.details.resource"
status="vm.details.status"
started="vm.details.started" started="vm.details.started"
finished="vm.details.finished"> finished="vm.details.finished">
</at-details> </at-details>
@@ -13,6 +12,7 @@
<div class="col-md-8"> <div class="col-md-8">
<at-panel class="at-Stdout"> <at-panel class="at-Stdout">
<div class="at-Panel-headingTitle">{{ vm.title }}</div>
<at-stats <at-stats
elapsed="vm.status.elapsed" elapsed="vm.status.elapsed"
running="vm.status.running" running="vm.status.running"

View File

@@ -48,9 +48,7 @@ function AtStatsController (strings) {
}; };
vm.init = scope => { vm.init = scope => {
const { elapsed, running, stats, title, plays, tasks } = scope; const { elapsed, running, stats, plays, tasks } = scope;
vm.title = title;
vm.plays = plays; vm.plays = plays;
vm.tasks = tasks; vm.tasks = tasks;
@@ -99,7 +97,6 @@ function atStats () {
elapsed: '=', elapsed: '=',
running: '=', running: '=',
stats: '=', stats: '=',
title: '=',
plays: '=', plays: '=',
tasks: '=', tasks: '=',
}, },

View File

@@ -1,3 +1,42 @@
<!-- todo: styling, css etc. - disposition according to project lib conventions -->
<div class="at-u-floatRight">
<span class="at-Panel-label">plays</span>
<span ng-show="!vm.plays" class="at-Panel-headingTitleBadge">...</span>
<span ng-show="vm.plays" class="at-Panel-headingTitleBadge">{{ vm.plays }}</span>
<span class="at-Panel-label">tasks</span>
<span ng-show="!vm.tasks" class="at-Panel-headingTitleBadge">...</span>
<span ng-show="vm.tasks" class="at-Panel-headingTitleBadge">{{ vm.tasks }}</span>
<span class="at-Panel-label">hosts</span>
<span ng-show="!vm.hosts" class="at-Panel-headingTitleBadge">...</span>
<span ng-show="vm.hosts" class="at-Panel-headingTitleBadge">{{ vm.hosts }}</span>
<span class="at-Panel-label">elapsed</span>
<span ng-show="!vm.elapsed" class="at-Panel-headingTitleBadge">...</span>
<span ng-show="vm.elapsed" class="at-Panel-headingTitleBadge">
{{ vm.elapsed * 1000 | duration: "hh:mm:ss" }}
</span>
<button class="btn at-Input-button at-u-noBorder"
aw-tool-tip="{{ toggleStdoutFullscreenTooltip }}"
data-tip-watch="toggleStdoutFullscreenTooltip"
data-placement="top"
ng-class="{'StandardOut-actionButton--active': stdoutFullScreen}"
ng-click="toggleStdoutFullscreen()">
<i class="fa fa-arrows-alt"></i>
</button>
<a ng-show="true" href="/api/v2/jobs/{{ job.id }}/stdout?format=txt_download">
<button class="btn at-Input-button at-u-noBorder"
aw-tool-tip="{{ standardOutTooltip }}"
data-tip-watch="standardOutTooltip"
data-placement="top">
<i class="fa fa-download"></i>
</button>
</a>
</div>
<div class="HostStatusBar"> <div class="HostStatusBar">
<div class="HostStatusBar-ok" <div class="HostStatusBar-ok"
data-placement="top" data-placement="top"
@@ -19,10 +58,10 @@
aw-tool-tip="{{ vm.tooltips.failures }}" aw-tool-tip="{{ vm.tooltips.failures }}"
data-tip-watch="vm.tooltips.failures"> data-tip-watch="vm.tooltips.failures">
</div> </div>
<div class="HostStatusBar-unreachable" <div class="HostStatusBar-dark"
data-placement="top" data-placement="top"
aw-tool-tip="{{ vm.tooltips.unreachable }}" aw-tool-tip="{{ vm.tooltips.dark }}"
data-tip-watch="vm.tooltips.unreachable"> data-tip-watch="vm.tooltips.dark">
</div> </div>
<div class="HostStatusBar-noData" <div class="HostStatusBar-noData"
ng-show="vm.running" ng-show="vm.running"

View File

@@ -23,6 +23,8 @@ function atRelaunchCtrl (
const jobObj = new Job(); const jobObj = new Job();
const jobTemplate = new JobTemplate(); const jobTemplate = new JobTemplate();
const checkRelaunchPlaybook = (option) => { const checkRelaunchPlaybook = (option) => {
jobObj.getRelaunch({ jobObj.getRelaunch({
id: vm.job.id id: vm.job.id
@@ -182,7 +184,7 @@ function atRelaunchCtrl (
project.postUpdate(vm.job.project) project.postUpdate(vm.job.project)
.then((postUpdateRes) => { .then((postUpdateRes) => {
if (!$state.includes('jobs')) { if (!$state.includes('jobs')) {
$state.go('scmUpdateStdout', { id: postUpdateRes.data.id }, { reload: true }); $state.go('jobz', { id: postUpdateRes.data.id, type: 'project' }, { reload: true });
} }
}); });
} else { } else {
@@ -218,7 +220,7 @@ function atRelaunchCtrl (
id: vm.job.id id: vm.job.id
}).then((launchRes) => { }).then((launchRes) => {
if (!$state.includes('jobs')) { if (!$state.includes('jobs')) {
$state.go('adHocJobStdout', { id: launchRes.data.id }, { reload: true }); $state.go('jobz', { id: launchRes.data.id, type: 'command' }, { reload: true });
} }
}); });
} }

View File

@@ -19,12 +19,17 @@ function postRelaunch (params) {
return $http(req); return $http(req);
} }
function getStats () {
return Promise.resolve(null);
}
function AdHocCommandModel (method, resource, config) { function AdHocCommandModel (method, resource, config) {
BaseModel.call(this, 'ad_hoc_commands'); BaseModel.call(this, 'ad_hoc_commands');
this.Constructor = AdHocCommandModel; this.Constructor = AdHocCommandModel;
this.postRelaunch = postRelaunch.bind(this); this.postRelaunch = postRelaunch.bind(this);
this.getRelaunch = getRelaunch.bind(this); this.getRelaunch = getRelaunch.bind(this);
this.getStats = getStats.bind(this);
return this.create(method, resource, config); return this.create(method, resource, config);
} }

View File

@@ -216,7 +216,7 @@ export default
// socket-enabled AND socket-disabled, and whether the $state // socket-enabled AND socket-disabled, and whether the $state
// requires a subscribe or an unsubscribe // requires a subscribe or an unsubscribe
var self = this; var self = this;
socketPromise.promise.then(function(){ return socketPromise.promise.then(function(){
if(!state.data || !state.data.socket){ if(!state.data || !state.data.socket){
_.merge(state.data, {socket: {groups: {}}}); _.merge(state.data, {socket: {groups: {}}});
self.unsubscribe(state); self.unsubscribe(state);

View File

@@ -898,13 +898,13 @@ export default ['$state','moment', '$timeout', '$window', '$filter', 'Rest', 'Ge
let goToJobResults = function(job_type) { let goToJobResults = function(job_type) {
if(job_type === 'job') { if(job_type === 'job') {
$state.go('jobResult', {id: d.job.id}); $state.go('jobz', {id: d.job.id, type: 'playbook'});
} }
else if(job_type === 'inventory_update') { else if(job_type === 'inventory_update') {
$state.go('inventorySyncStdout', {id: d.job.id}); $state.go('jobz', {id: d.job.id, type: 'inventory'});
} }
else if(job_type === 'project_update') { else if(job_type === 'project_update') {
$state.go('scmUpdateStdout', {id: d.job.id}); $state.go('jobz', {id: d.job.id, type: 'project'});
} }
}; };