Skip to content

Commit

Permalink
Merge pull request #1774 from anotherchrisberry/wait-for-cancel-delete
Browse files Browse the repository at this point in the history
poll executions before completing cancel/delete operation
  • Loading branch information
anotherchrisberry committed Dec 3, 2015
2 parents 28d861d + c8ac92f commit 0fd7604
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ module.exports = angular
header: 'Really stop execution of ' + this.execution.name + '?',
buttonText: 'Stop running ' + this.execution.name,
destructive: false,
submitMethod: () => executionService.cancelExecution(this.execution.id)
submitMethod: () => executionService.cancelExecution(this.application, this.execution.id)
});
};

Expand Down
51 changes: 33 additions & 18 deletions app/scripts/modules/core/delivery/service/execution.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
let angular = require('angular');

module.exports = angular.module('spinnaker.core.delivery.executions.service', [
require('angular-ui-router'),
require('../../scheduler/scheduler.service.js'),
require('../../cache/deckCacheFactory.js'),
require('../../utils/appendTransform.js'),
require('./executions.transformer.service.js')
])
.factory('executionService', function($stateParams, $http, $timeout, $q, $log,
.factory('executionService', function($http, $timeout, $q, $log,
scheduler, settings, appendTransform, executionsTransformer) {

const activeStatuses = ['RUNNING', 'SUSPENDED', 'NOT_STARTED'];
Expand Down Expand Up @@ -72,27 +71,47 @@ module.exports = angular.module('spinnaker.core.delivery.executions.service', [
});
}

function cancelExecution(executionId, applicationName) {
function waitUntilPipelineIsCancelled(application, executionId) {
return getRunningExecutions(application.name).then((executions) => {
let match = executions.filter((execution) => execution.id === executionId);
let deferred = $q.defer();
if (match && !match.length) {
application.reloadExecutions().then(deferred.resolve);
return deferred.promise;
}
return $timeout(() => waitUntilPipelineIsCancelled(application, executionId), 1000);
});
}

function waitUntilPipelineIsDeleted(application, executionId) {

return getExecutions(application.name).then((executions) => {
let match = executions.filter((execution) => execution.id === executionId);
let deferred = $q.defer();
if (match && !match.length) {
application.reloadExecutions().then(deferred.resolve);
return deferred.promise;
}
return $timeout(() => waitUntilPipelineIsDeleted(application, executionId), 1000);
});
}

function cancelExecution(application, executionId) {
var deferred = $q.defer();
$http({
method: 'PUT',
url: [
settings.gateUrl,
'applications',
(applicationName || $stateParams.application), // TODO: remove stateParams
application.name,
'pipelines',
executionId,
'cancel',
].join('/')
}).then(
function() {
scheduler.scheduleImmediate();
deferred.resolve();
},
function(exception) {
deferred.reject(exception && exception.data ? exception.message : null);
}
);
() => waitUntilPipelineIsCancelled(application, executionId).then(deferred.resolve),
(exception) => deferred.reject(exception && exception.data ? exception.message : null)
);
return deferred.promise;
}

Expand All @@ -106,12 +125,8 @@ module.exports = angular.module('spinnaker.core.delivery.executions.service', [
executionId,
].join('/')
}).then(
function() {
application.reloadExecutions().then(deferred.resolve);
},
function(exception) {
deferred.reject(exception && exception.data ? exception.data.message : null);
}
() => waitUntilPipelineIsDeleted(application, executionId).then(deferred.resolve),
(exception) => deferred.reject(exception && exception.data ? exception.data.message : null)
);
return deferred.promise;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

describe('Service: executionService', function () {

//NOTE: This is only testing the service dependencies. Please add more tests.

var executionService;
var $httpBackend;
var settings;
var timeout;
var $q;

beforeEach(
window.module(
Expand All @@ -15,10 +15,12 @@ describe('Service: executionService', function () {
);

beforeEach(
window.inject(function (_executionService_, _$httpBackend_, _settings_) {
window.inject(function (_executionService_, _$httpBackend_, _settings_, _$timeout_, _$q_) {
executionService = _executionService_;
$httpBackend = _$httpBackend_;
settings = _settings_;
timeout = _$timeout_;
$q = _$q_;
})
);

Expand All @@ -27,8 +29,75 @@ describe('Service: executionService', function () {
$httpBackend.verifyNoOutstandingRequest();
});

it('should instantiate the controller', function () {
expect(executionService).toBeDefined();
describe('cancelling pipeline', function () {
it('should wait until pipeline is not running, then resolve', function () {
let completed = false;
let executionId = 'abc';
let cancelUrl = [ settings.gateUrl, 'applications', 'deck', 'pipelines', executionId, 'cancel' ].join('/');
let checkUrl = [ settings.gateUrl, 'applications', 'deck', 'pipelines' ].join('/')
.concat('?statuses=RUNNING,SUSPENDED,NOT_STARTED');
let application = { name: 'deck', reloadExecutions: () => $q.when(null) };

$httpBackend.expectPUT(cancelUrl).respond(200, []);
$httpBackend.expectGET(checkUrl).respond(200, [{id: executionId}]);

executionService.cancelExecution(application, executionId).then(() => completed = true);
$httpBackend.flush();
expect(completed).toBe(false);

$httpBackend.expectGET(checkUrl).respond(200, [{id: 'some-other-execution'}]);
timeout.flush();
$httpBackend.flush();
expect(completed).toBe(true);
});

it('should propagate rejection from failed cancel', function () {
let failed = false;
let executionId = 'abc';
let cancelUrl = [ settings.gateUrl, 'applications', 'deck', 'pipelines', executionId, 'cancel' ].join('/');
let application = { name: 'deck', reloadExecutions: () => $q.when(null) };

$httpBackend.expectPUT(cancelUrl).respond(500, []);

executionService.cancelExecution(application, executionId).then(angular.noop, () => failed = true);
$httpBackend.flush();
expect(failed).toBe(true);
});
});

describe('deleting pipeline', function () {
it('should wait until pipeline is missing, then resolve', function () {
let completed = false;
let executionId = 'abc';
let deleteUrl = [ settings.gateUrl, 'pipelines', executionId ].join('/');
let checkUrl = [ settings.gateUrl, 'applications', 'deck', 'pipelines' ].join('/');
let application = { name: 'deck', reloadExecutions: () => $q.when(null) };

$httpBackend.expectDELETE(deleteUrl).respond(200, []);
$httpBackend.expectGET(checkUrl).respond(200, [{id: executionId}]);

executionService.deleteExecution(application, executionId).then(() => completed = true);
$httpBackend.flush();
expect(completed).toBe(false);

$httpBackend.expectGET(checkUrl).respond(200, [{id: 'some-other-execution'}]);
timeout.flush();
$httpBackend.flush();
expect(completed).toBe(true);
});

it('should propagate rejection from failed delete', function () {
let failed = false;
let executionId = 'abc';
let deleteUrl = [ settings.gateUrl, 'pipelines', executionId ].join('/');
let application = { name: 'deck', reloadExecutions: () => $q.when(null) };

$httpBackend.expectDELETE(deleteUrl).respond(500, []);

executionService.deleteExecution(application, executionId).then(angular.noop, () => failed = true);
$httpBackend.flush();
expect(failed).toBe(true);
});
});

describe('when fetching pipelines', function () {
Expand Down

0 comments on commit 0fd7604

Please sign in to comment.