Add edit health monitor action

This adds the action to update a health monitor.

Partially-Implements: blueprint horizon-lbaas-v2-ui
Change-Id: I017c7adc885a02420e47b0dfff7c314054f189b0
This commit is contained in:
Justin Pomeroy 2016-03-04 10:39:09 -06:00
parent 9e9c74d8cc
commit 051b3cbd1e
11 changed files with 419 additions and 5 deletions

View File

@ -710,3 +710,10 @@ class HealthMonitor(generic.View):
http://localhost/api/lbaas/healthmonitors/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
neutronclient(request).delete_lbaas_healthmonitor(healthmonitor_id)
@rest_utils.ajax()
def put(self, request, healthmonitor_id):
"""Edit a health monitor.
"""
update_monitor(request)

View File

@ -54,7 +54,8 @@
getMember: getMember,
getHealthMonitor: getHealthMonitor,
deleteHealthMonitor: deleteHealthMonitor,
createHealthMonitor: createHealthMonitor
createHealthMonitor: createHealthMonitor,
editHealthMonitor: editHealthMonitor
};
return service;
@ -360,6 +361,23 @@
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editHealthMonitor
* @description
* Edit a health monitor
* @param {string} id
* Specifies the id of the health monitor to update.
* @param {object} spec
* Specifies the data used to update the health monitor.
*/
function editHealthMonitor(id, spec) {
return apiService.put('/api/lbaas/healthmonitors/' + id, spec)
.error(function () {
toastService.add('error', gettext('Unable to update health monitor.'));
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.deleteHealthMonitor
* @description

View File

@ -134,6 +134,14 @@
error: 'Unable to retrieve health monitor.',
testInput: [ '1234' ]
},
{
func: 'editHealthMonitor',
method: 'put',
path: '/api/lbaas/healthmonitors/1234',
error: 'Unable to update health monitor.',
data: { name: 'healthmonitor-1' },
testInput: [ '1234', { name: 'healthmonitor-1' } ]
},
{
func: 'deleteHealthMonitor',
method: 'delete',

View File

@ -0,0 +1,80 @@
/*
* Copyright 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.healthmonitors')
.factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit', editService);
editService.$inject = [
'$q',
'$route',
'horizon.dashboard.project.lbaasv2.workflow.modal',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngDoc factory
* @name horizon.dashboard.project.lbaasv2.healthmonitors.actions.editService
* @description
* Provides the service for editing a health monitor resource.
* @param $q The angular service for promises.
* @param $route The angular $route service.
* @param workflowModal The LBaaS workflow modal service.
* @param policy The horizon policy service.
* @param gettext The horizon gettext function for translation.
* @returns The health monitor edit service.
*/
function editService($q, $route, workflowModal, policy, gettext) {
var statePromise;
var edit = workflowModal.init({
controller: 'EditHealthMonitorWizardController',
message: gettext('The health monitor has been updated.'),
handle: handle,
allowed: allowed
});
var service = {
init: init,
edit: edit
};
return service;
//////////////
function init(_statePromise_) {
statePromise = _statePromise_;
return service;
}
function allowed(/*healthmonitor*/) {
return $q.all([
statePromise,
policy.ifAllowed({ rules: [['neutron', 'update_health_monitor']] })
]);
}
function handle(/*response*/) {
$route.reload();
}
}
})();

View File

@ -0,0 +1,98 @@
/*
* Copyright 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
describe('LBaaS v2 Edit Health Monitor Action Service', function() {
var scope, $q, $route, policy, init, service, loadBalancerState;
function allowed(item) {
spyOn(policy, 'ifAllowed').and.returnValue(true);
var promise = service.edit.allowed(item);
var allowed;
promise.then(function() {
allowed = true;
}, function() {
allowed = false;
});
scope.$apply();
expect(policy.ifAllowed).toHaveBeenCalledWith(
{rules: [['neutron', 'update_health_monitor']]});
return allowed;
}
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
$provide.value('$modal', {
open: function() {
return {
result: {
then: function(func) {
func({ data: { id: 'healthmonitor1' } });
}
}
};
}
});
}));
beforeEach(inject(function ($injector) {
scope = $injector.get('$rootScope').$new();
$q = $injector.get('$q');
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
$route = $injector.get('$route');
service = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit');
init = service.init;
loadBalancerState = $q.defer();
}));
it('should define the correct service properties', function() {
expect(service.init).toBeDefined();
expect(service.edit).toBeDefined();
});
it('should have the "allowed" and "perform" functions', function() {
expect(service.edit.allowed).toBeDefined();
expect(service.edit.perform).toBeDefined();
});
it('should allow edit a health monitor under an ACTIVE load balancer', function() {
loadBalancerState.resolve();
init(loadBalancerState.promise);
expect(allowed({})).toBe(true);
});
it('should not allow editing a health monitor under a NON-ACTIVE load balancer', function() {
loadBalancerState.reject();
init(loadBalancerState.promise);
expect(allowed({})).toBe(false);
});
it('should reload page after edit', function() {
loadBalancerState.resolve();
spyOn($route, 'reload');
init(loadBalancerState.promise).edit.allowed({});
service.edit.perform();
expect($route.reload).toHaveBeenCalled();
});
});
})();

View File

@ -0,0 +1,42 @@
/*
* Copyright 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
angular
.module('horizon.dashboard.project.lbaasv2.healthmonitors')
.controller('EditHealthMonitorWizardController', EditHealthMonitorWizardController);
EditHealthMonitorWizardController.$inject = [
'$scope',
'horizon.dashboard.project.lbaasv2.workflow.model',
'horizon.dashboard.project.lbaasv2.workflow.workflow',
'horizon.framework.util.i18n.gettext'
];
function EditHealthMonitorWizardController($scope, model, workflowService, gettext) {
var scope = $scope;
scope.model = model;
scope.submit = scope.model.submit;
scope.workflow = workflowService(
gettext('Update Health Monitor'),
'fa fa-cloud-download',
['monitor']
);
scope.model.initialize('monitor', scope.launchContext.id);
}
})();

View File

@ -0,0 +1,63 @@
/*
* Copyright 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function () {
'use strict';
describe('LBaaS v2 Edit Health Monitor Wizard Controller', function() {
var ctrl;
var model = {
submit: function() {
return 'updated';
},
initialize: angular.noop
};
var workflow = function() {
return 'foo';
};
var scope = {
launchContext: {id: 'healthmonitor1'}
};
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function ($provide) {
$provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model);
$provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflow);
}));
beforeEach(inject(function ($controller) {
spyOn(model, 'initialize');
ctrl = $controller('EditHealthMonitorWizardController', { $scope: scope });
}));
it('defines the controller', function() {
expect(ctrl).toBeDefined();
});
it('calls initialize on the given model', function() {
expect(model.initialize).toHaveBeenCalled();
});
it('sets scope.workflow to the given workflow', function() {
expect(scope.workflow).toBe('foo');
});
it('defines scope.submit', function() {
expect(scope.submit).toBeDefined();
expect(scope.submit()).toBe('updated');
});
});
})();

View File

@ -24,6 +24,7 @@
rowActions.$inject = [
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit',
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete'
];
@ -36,11 +37,12 @@
*
* @param gettext The horizon gettext function for translation.
* @param loadBalancersService The LBaaS v2 load balancers service.
* @param editService The LBaaS v2 health monitor edit service.
* @param deleteService The LBaaS v2 health monitor delete service.
* @returns Health monitor row actions service object.
*/
function rowActions(gettext, loadBalancersService, deleteService) {
function rowActions(gettext, loadBalancersService, editService, deleteService) {
var loadBalancerIsActionable, loadbalancerId, listenerId, poolId;
var service = {
@ -62,6 +64,11 @@
function actions() {
return [{
service: editService.init(loadBalancerIsActionable).edit,
template: {
text: gettext('Edit')
}
},{
service: deleteService.init(loadbalancerId, listenerId, poolId, loadBalancerIsActionable),
template: {
text: gettext('Delete Health Monitor'),

View File

@ -35,8 +35,9 @@
}));
it('should define correct table row actions', function() {
expect(actions.length).toBe(1);
expect(actions[0].template.text).toBe('Delete Health Monitor');
expect(actions.length).toBe(2);
expect(actions[0].template.text).toBe('Edit');
expect(actions[1].template.text).toBe('Delete Health Monitor');
});
it('should have the "allowed" and "perform" functions', function() {

View File

@ -190,7 +190,8 @@
'createmonitor': initCreateMonitor,
'editloadbalancer': initEditLoadBalancer,
'editlistener': initEditListener,
'editpool': initEditPool
'editpool': initEditPool,
'editmonitor': initEditMonitor
}[type](keymanagerPromise);
return promise.then(onInitSuccess, onInitFail);
@ -271,6 +272,11 @@
]).then(initMemberAddresses);
}
function initEditMonitor() {
model.context.submit = editHealthMonitor;
return lbaasv2API.getHealthMonitor(model.context.id).then(onGetHealthMonitor);
}
/**
* @ngdoc method
* @name workflowModel.submit
@ -321,6 +327,10 @@
return lbaasv2API.editPool(model.context.id, spec);
}
function editHealthMonitor(spec) {
return lbaasv2API.editHealthMonitor(model.context.id, spec);
}
function cleanFinalSpecLoadBalancer(finalSpec) {
var context = model.context;
@ -631,6 +641,10 @@
spec.path = monitor.url_path;
}
function onGetHealthMonitor(response) {
setMonitorSpec(response.data);
}
function prepareCertificates() {
return $q.all([
barbicanAPI.getCertificates(true),

View File

@ -185,6 +185,9 @@
},
createHealthMonitor: function(spec) {
return spec;
},
editHealthMonitor: function(id, spec) {
return spec;
}
});
@ -568,6 +571,42 @@
});
});
describe('Post initialize model (edit health monitor)', function() {
beforeEach(function() {
model.initialize('monitor', 'healthmonitor1');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(0);
expect(model.members.length).toBe(0);
expect(model.certificates.length).toBe(0);
expect(model.listenerPorts.length).toBe(0);
expect(model.spec.loadbalancer_id).toBeUndefined();
expect(model.spec.parentResourceId).toBeUndefined();
expect(model.spec.members.length).toBe(0);
expect(model.spec.certificates).toEqual([]);
expect(model.certificatesError).toBe(false);
expect(model.spec.monitor.id).toBe('1234');
expect(model.spec.monitor.type).toBe('HTTP');
expect(model.spec.monitor.interval).toBe(1);
expect(model.spec.monitor.timeout).toBe(1);
expect(model.spec.monitor.retry).toBe(1);
expect(model.spec.monitor.method).toBe('POST');
expect(model.spec.monitor.status).toBe('200');
expect(model.spec.monitor.path).toBe('/test');
});
it('should initialize context properties', function() {
expect(model.context.resource).toBe('monitor');
expect(model.context.id).toBe('healthmonitor1');
expect(model.context.submit.name).toBe('editHealthMonitor');
});
});
describe('Post initialize model (without barbican)', function() {
beforeEach(function() {
@ -1730,6 +1769,7 @@
});
it('should set final spec properties', function() {
var finalSpec = model.submit();
expect(finalSpec.loadbalancer).toBeUndefined();
@ -1803,6 +1843,42 @@
});
});
describe('Model submit function (edit health monitor)', function() {
beforeEach(function() {
model.initialize('monitor', 'healthmonitor1');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.monitor.interval = 10;
model.spec.monitor.retry = 6;
model.spec.monitor.timeout = 8;
model.spec.monitor.method = 'GET';
model.spec.monitor.status = '200-204';
model.spec.monitor.path = '/foo/bar';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer_id).toBeUndefined();
expect(finalSpec.parentResourceId).toBeUndefined();
expect(finalSpec.loadbalancer).toBeUndefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool).toBeUndefined();
expect(finalSpec.members).toBeUndefined();
expect(finalSpec.certificates).toBeUndefined();
expect(finalSpec.monitor.type).toBe('HTTP');
expect(finalSpec.monitor.interval).toBe(10);
expect(finalSpec.monitor.retry).toBe(6);
expect(finalSpec.monitor.timeout).toBe(8);
expect(finalSpec.monitor.method).toBe('GET');
expect(finalSpec.monitor.status).toBe('200-204');
expect(finalSpec.monitor.path).toBe('/foo/bar');
});
});
describe('Model visible resources (edit listener, no pool)', function() {
beforeEach(function() {