wip - integrate adhoc and workflow

This commit is contained in:
Jake McDermott 2018-03-27 12:39:30 -04:00
parent 91e5659042
commit b10dc6d4ff
No known key found for this signature in database
GPG Key ID: 3B02CAD476EECB35
10 changed files with 103 additions and 46 deletions

View File

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

View File

@ -84,12 +84,14 @@ function JobsIndexController (
eventCounter = null;
statsEvent = resource.stats;
// Panel Title
vm.title = resource.model.get('name');
// Status Bar
vm.status = {
stats: statsEvent,
elapsed: resource.model.get('elapsed'),
running: Boolean(resource.model.get('started')) && !resource.model.get('finished'),
title: resource.model.get('name'),
plays: null,
tasks: null,
};
@ -99,7 +101,6 @@ function JobsIndexController (
resource,
started: resource.model.get('started'),
finished: resource.model.get('finished'),
status: resource.model.get('status'),
};
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) {
next();

View File

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

View File

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

View File

@ -48,9 +48,7 @@ function AtStatsController (strings) {
};
vm.init = scope => {
const { elapsed, running, stats, title, plays, tasks } = scope;
vm.title = title;
const { elapsed, running, stats, plays, tasks } = scope;
vm.plays = plays;
vm.tasks = tasks;
@ -99,7 +97,6 @@ function atStats () {
elapsed: '=',
running: '=',
stats: '=',
title: '=',
plays: '=',
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-ok"
data-placement="top"
@ -19,10 +58,10 @@
aw-tool-tip="{{ vm.tooltips.failures }}"
data-tip-watch="vm.tooltips.failures">
</div>
<div class="HostStatusBar-unreachable"
<div class="HostStatusBar-dark"
data-placement="top"
aw-tool-tip="{{ vm.tooltips.unreachable }}"
data-tip-watch="vm.tooltips.unreachable">
aw-tool-tip="{{ vm.tooltips.dark }}"
data-tip-watch="vm.tooltips.dark">
</div>
<div class="HostStatusBar-noData"
ng-show="vm.running"

View File

@ -23,6 +23,8 @@ function atRelaunchCtrl (
const jobObj = new Job();
const jobTemplate = new JobTemplate();
const checkRelaunchPlaybook = (option) => {
jobObj.getRelaunch({
id: vm.job.id
@ -182,7 +184,7 @@ function atRelaunchCtrl (
project.postUpdate(vm.job.project)
.then((postUpdateRes) => {
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 {
@ -218,7 +220,7 @@ function atRelaunchCtrl (
id: vm.job.id
}).then((launchRes) => {
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);
}
function getStats () {
return Promise.resolve(null);
}
function AdHocCommandModel (method, resource, config) {
BaseModel.call(this, 'ad_hoc_commands');
this.Constructor = AdHocCommandModel;
this.postRelaunch = postRelaunch.bind(this);
this.getRelaunch = getRelaunch.bind(this);
this.getStats = getStats.bind(this);
return this.create(method, resource, config);
}

View File

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

View File

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