Merge "Do not allow deleting a listener that has a default pool"

This commit is contained in:
Jenkins 2016-03-11 00:24:50 +00:00 committed by Gerrit Code Review
commit acb50bfc16
2 changed files with 60 additions and 12 deletions

View File

@ -48,13 +48,15 @@
* @param toast The horizon message service.
* @param qExtensions Horizon extensions to the $q service.
* @param gettext The horizon gettext function for translation.
* @returns The load balancers table delete service.
* @returns The listeners table delete service.
*/
function deleteService(
$q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext
) {
var loadbalancerId, statePromise;
var notAllowedMessage = gettext('The following listeners will not be deleted ' +
'due to existing pools: %s.');
var context = {
labels: {
title: gettext('Confirm Delete Listeners'),
@ -87,19 +89,19 @@
}
function perform(items) {
if (!angular.isArray(items)) {
items = [items];
if (angular.isArray(items)) {
qExtensions.allSettled(items.map(checkPermission)).then(afterCheck);
} else {
deleteModal.open({ $emit: actionComplete }, [items], context);
}
deleteModal.open({ $emit: actionComplete }, items, context);
}
function allowed(/*item*/) {
return $q.all([
statePromise,
// This rule is made up and should therefore always pass. I assume at some point there
// will be a valid rule similar to this that we will want to use.
policy.ifAllowed({ rules: [['neutron', 'delete_listener']] })
]);
function allowed(item) {
var promises = [policy.ifAllowed({ rules: [['neutron', 'delete_listener']] }), statePromise];
if (item) {
promises.push(qExtensions.booleanAsPromise(!item.default_pool_id));
}
return $q.all(promises);
}
function deleteItem(id) {
@ -122,5 +124,34 @@
}
}
function checkPermission(item) {
return { promise: canBeDeleted(item), context: item };
}
function afterCheck(result) {
if (result.fail.length > 0) {
toast.add('error', getMessage(notAllowedMessage, result.fail));
}
if (result.pass.length > 0) {
deleteModal.open({ $emit: actionComplete }, result.pass.map(getEntity), context);
}
}
function canBeDeleted(item) {
return qExtensions.booleanAsPromise(!item.default_pool_id);
}
function getMessage(message, entities) {
return interpolate(message, [entities.map(getName).join(", ")]);
}
function getName(result) {
return getEntity(result).name;
}
function getEntity(result) {
return result.context;
}
}
})();

View File

@ -96,11 +96,15 @@
expect(allowed()).toBe(true);
});
it('should not allow deleting listener from load balancer in a PENDING state', function() {
it('should not allow deleting a listener from load balancer in a PENDING state', function() {
service.init('1', makePromise(true));
expect(allowed()).toBe(false);
});
it('should not allow deleting a listener that has a default pool', function() {
expect(allowed({default_pool_id: 'pool1'})).toBe(false);
});
it('should open the delete modal', function() {
spyOn(modal, 'open');
service.perform(items[0]);
@ -157,5 +161,18 @@
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted listeners: First.');
});
it('should show message if any selected items do not allow for delete (batch)', function() {
spyOn(modal, 'open');
spyOn(toast, 'add');
items[0].default_pool_id = 'pool1';
items[1].default_pool_id = 'pool2';
service.perform(items);
$scope.$apply();
expect(modal.open).not.toHaveBeenCalled();
expect(toast.add).toHaveBeenCalledWith('error',
'The following listeners will not be deleted ' +
'due to existing pools: First, Second.');
});
});
})();