Add the Angular LBaaS V2 'Update Member List' Table Action

This change adds the Update Member list table action to the pool members
table.  This wizard allows you to Add or Remove members from the current list
of members associated with a particular pool.

Partially-Implements: blueprint horizon-lbaas-v2-ui
Change-Id: I640fdf2597e4a16191dbce8c20450c7c0dc882f0
This commit is contained in:
Lucas Palm 2016-03-09 11:00:15 -06:00
parent 1240c01a84
commit 06ed719b69
15 changed files with 703 additions and 33 deletions

View File

@ -171,16 +171,15 @@ def add_member(request, **kwargs):
"""
data = request.DATA
members = data.get('members')
pool_id = kwargs.get('pool_id')
if kwargs.get('members_to_add'):
members_to_add = kwargs['members_to_add']
index = [members.index(member) for member in members
if member['id'] == members_to_add[0]][0]
pool_id = data['pool'].get('id')
loadbalancer_id = data.get('loadbalancer_id')
else:
index = kwargs.get('index')
pool_id = kwargs.get('pool_id')
loadbalancer_id = kwargs.get('loadbalancer_id')
member = members[index]
@ -203,7 +202,8 @@ def add_member(request, **kwargs):
kwargs = {'callback_kwargs': {
'existing_members': kwargs.get('existing_members'),
'members_to_add': members_to_add,
'members_to_delete': kwargs.get('members_to_delete')}}
'members_to_delete': kwargs.get('members_to_delete'),
'pool_id': pool_id}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
elif len(members) > index:
args = (request, loadbalancer_id, add_member)
@ -224,7 +224,7 @@ def remove_member(request, **kwargs):
"""
data = request.DATA
loadbalancer_id = data.get('loadbalancer_id')
pool_id = data['pool']['id']
pool_id = kwargs.get('pool_id')
if kwargs.get('members_to_delete'):
members_to_delete = kwargs['members_to_delete']
@ -299,21 +299,18 @@ def update_pool(request, **kwargs):
# Assemble the lists of member id's to add and remove, if any exist
tenant_id = request.user.project_id
new_members = data.get('members', [])
request_member_data = data.get('members', [])
existing_members = neutronclient(request).list_lbaas_members(
pool_id, tenant_id=tenant_id).get('members')
new_member_ids = [member['id'] for member in new_members]
existing_member_ids = [member['id'] for member in existing_members]
members_to_add = [member_id for member_id in new_member_ids
if member_id not in existing_member_ids]
members_to_delete = [member_id for member_id in existing_member_ids
if member_id not in new_member_ids]
(members_to_add, members_to_delete) = get_members_to_add_remove(
request_member_data, existing_members)
if members_to_add or members_to_delete:
args = (request, loadbalancer_id, update_member_list)
kwargs = {'callback_kwargs': {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete}}
'members_to_delete': members_to_delete,
'pool_id': pool_id}}
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
elif data.get('monitor'):
args = (request, loadbalancer_id, update_monitor)
@ -355,25 +352,38 @@ def update_member_list(request, **kwargs):
"""
data = request.DATA
loadbalancer_id = data.get('loadbalancer_id')
pool_id = kwargs.get('pool_id')
existing_members = kwargs.get('existing_members')
members_to_add = kwargs.get('members_to_add')
members_to_delete = kwargs.get('members_to_delete')
if members_to_add:
if members_to_delete:
kwargs = {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete}
add_member(request, **kwargs)
elif members_to_delete:
kwargs = {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete}
'members_to_delete': members_to_delete,
'pool_id': pool_id}
remove_member(request, **kwargs)
elif members_to_add:
kwargs = {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete,
'pool_id': pool_id}
add_member(request, **kwargs)
elif data.get('monitor'):
args = (request, loadbalancer_id, update_monitor)
thread.start_new_thread(poll_loadbalancer_status, args)
def get_members_to_add_remove(request_member_data, existing_members):
new_member_ids = [member['id'] for member in request_member_data]
existing_member_ids = [member['id'] for member in existing_members]
members_to_add = [member_id for member_id in new_member_ids
if member_id not in existing_member_ids]
members_to_delete = [member_id for member_id in existing_member_ids
if member_id not in new_member_ids]
return members_to_add, members_to_delete
def add_floating_ip_info(request, loadbalancers):
"""Add floating IP address info to each load balancer.
@ -653,6 +663,26 @@ class Members(generic.View):
tenant_id=tenant_id)
return {'items': result.get('members')}
@rest_utils.ajax()
def put(self, request, pool_id):
"""Update the list of members for the current project.
"""
# Assemble the lists of member id's to add and remove, if any exist
tenant_id = request.user.project_id
request_member_data = request.DATA.get('members', [])
existing_members = neutronclient(request).list_lbaas_members(
pool_id, tenant_id=tenant_id).get('members')
(members_to_add, members_to_delete) = get_members_to_add_remove(
request_member_data, existing_members)
if members_to_add or members_to_delete:
kwargs = {'existing_members': existing_members,
'members_to_add': members_to_add,
'members_to_delete': members_to_delete,
'pool_id': pool_id}
update_member_list(request, **kwargs)
@urls.register
class Member(generic.View):

View File

@ -56,7 +56,8 @@
getHealthMonitor: getHealthMonitor,
deleteHealthMonitor: deleteHealthMonitor,
createHealthMonitor: createHealthMonitor,
editHealthMonitor: editHealthMonitor
editHealthMonitor: editHealthMonitor,
updateMemberList: updateMemberList
};
return service;
@ -345,8 +346,6 @@
});
}
// Health Monitors
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editMember
* @description
@ -364,6 +363,23 @@
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.updateMemberList
* @description
* Update the list of pool members by adding or removing the necessary members.
* @param {string} poolId
* Specifies the id of the pool the members belong to.
* @param {object} spec
* Specifies the data used to update the member list.
*/
function updateMemberList(poolId, spec) {
return apiService.put('/api/lbaas/pools/' + poolId + '/members/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update member list.'));
});
}
// Health Monitors
/**

View File

@ -219,6 +219,14 @@
error: 'Unable to create health monitor.',
data: { name: 'healthmonitor-1' },
testInput: [ { name: 'healthmonitor-1' } ]
},
{
func: 'updateMemberList',
method: 'put',
path: '/api/lbaas/pools/1234/members/',
error: 'Unable to update member list.',
data: { name: 'member-1' },
testInput: [ '1234', { name: 'member-1' } ]
}
];

View File

@ -0,0 +1,73 @@
/*
* 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.members')
.factory('horizon.dashboard.project.lbaasv2.members.actions.batchActions',
tableBatchActions);
tableBatchActions.$inject = [
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list'
];
/**
* @ngdoc service
* @ngname horizon.dashboard.project.lbaasv2.pools.actions.batchActions
*
* @description
* Provides the service for the Members table batch actions.
*
* @param gettext The horizon gettext function for translation.
* @param loadBalancersService The LBaaS v2 load balancers service.
* @param updateMemberListService The LBaaS v2 update member list service.
* @returns Members table batch actions service object.
*/
function tableBatchActions(
gettext, loadBalancersService, updateMemberListService
) {
var loadBalancerIsActionable, loadBalancerId;
var service = {
actions: actions,
init: init
};
return service;
///////////////
function init(_loadBalancerId_) {
loadBalancerId = _loadBalancerId_;
loadBalancerIsActionable = loadBalancersService.isActionable(loadBalancerId);
return service;
}
function actions() {
return [{
service: updateMemberListService.init(loadBalancerIsActionable).update,
template: {
text: gettext('Add/Remove Pool Members')
}
}];
}
}
})();

View File

@ -0,0 +1,67 @@
/*
* 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 Members Table Batch Actions Service', function() {
var actions;
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) {
var response = {
data: {
id: '1'
}
};
var modal = {
open: function() {
return {
result: {
then: function(func) {
func(response);
}
}
};
}
};
$provide.value('$modal', modal);
}));
beforeEach(inject(function ($injector) {
var batchActionsService = $injector.get(
'horizon.dashboard.project.lbaasv2.members.actions.batchActions');
actions = batchActionsService.actions();
}));
it('should define correct table batch actions', function() {
expect(actions.length).toBe(1);
expect(actions[0].template.text).toBe('Add/Remove Pool Members');
});
it('should have the "allowed" and "perform" functions', function() {
actions.forEach(function(action) {
expect(action.service.allowed).toBeDefined();
expect(action.service.perform).toBeDefined();
});
});
});
})();

View File

@ -0,0 +1,83 @@
/*
* 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.members')
.factory('horizon.dashboard.project.lbaasv2.members.actions.update-member-list',
updateMemberListService);
updateMemberListService.$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.listeners.actions.updateMemberListService
* @description
* Provides the service for updating the list of pool members.
* @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 load balancers members update member list service.
*/
function updateMemberListService(
$q, $route, workflowModal, policy, gettext
) {
var statePromise;
var updateList = workflowModal.init({
controller: 'UpdateMemberListWizardController',
message: gettext('The pool members have been updated.'),
handle: onUpdate,
allowed: allowed
});
var service = {
init: init,
update: updateList
};
return service;
//////////////
function init(_statePromise_) {
statePromise = _statePromise_;
return service;
}
function allowed(/*item*/) {
return $q.all([
statePromise,
policy.ifAllowed({ rules: [['neutron', 'update_member_list']] })
]);
}
function onUpdate(/*response*/) {
$route.reload();
}
}
})();

View File

@ -0,0 +1,102 @@
/*
* 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 Update Member List Action Service', function() {
var scope, $q, $route, policy, init, updateMemberListService, defer;
function allowed() {
spyOn(policy, 'ifAllowed').and.returnValue(true);
var promise = updateMemberListService.update.allowed();
var allowed;
promise.then(function() {
allowed = true;
}, function() {
allowed = false;
});
scope.$apply();
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_member_list']]});
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) {
var response = {
data: {
id: '9012'
}
};
var modal = {
open: function() {
return {
result: {
then: function(func) {
func(response);
}
}
};
}
};
$provide.value('$modal', modal);
}));
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');
updateMemberListService = $injector.get(
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list');
init = updateMemberListService.init;
defer = $q.defer();
}));
it('should define the correct service properties', function() {
expect(updateMemberListService.init).toBeDefined();
expect(updateMemberListService.update).toBeDefined();
});
it('should have the "allowed" and "perform" functions', function() {
expect(updateMemberListService.update.allowed).toBeDefined();
expect(updateMemberListService.update.perform).toBeDefined();
});
it('should allow editing a pool under an ACTIVE load balancer', function() {
defer.resolve();
init(defer.promise);
expect(allowed()).toBe(true);
});
it('should not allow editing a pool under an NON-ACTIVE load balancer', function() {
defer.reject();
init(defer.promise);
expect(allowed()).toBe(false);
});
it('should redirect after edit', function() {
spyOn($route, 'reload').and.callThrough();
updateMemberListService.update.perform();
expect($route.reload).toHaveBeenCalled();
});
});
})();

View File

@ -0,0 +1,45 @@
/*
* 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.members')
.controller('UpdateMemberListWizardController', UpdateMemberListWizardController);
UpdateMemberListWizardController.$inject = [
'$scope',
'$routeParams',
'horizon.dashboard.project.lbaasv2.workflow.model',
'horizon.dashboard.project.lbaasv2.workflow.workflow',
'horizon.framework.util.i18n.gettext'
];
function UpdateMemberListWizardController($scope, $routeParams, model, workflowService, gettext) {
var loadbalancerId = $routeParams.loadbalancerId;
var poolId = $routeParams.poolId;
var scope = $scope;
scope.model = model;
scope.submit = scope.model.submit;
scope.workflow = workflowService(
gettext('Add/Remove Pool Members'),
'fa fa-pencil',
['members']
);
scope.model.initialize('members', false, loadbalancerId, poolId);
}
})();

View File

@ -0,0 +1,69 @@
/*
* 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 Update Member List Wizard Controller', function() {
var ctrl, workflowSpy, scope;
var model = {
submit: function() {
return 'updated';
},
initialize: angular.noop
};
var workflow = 'foo';
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function ($provide) {
workflowSpy = jasmine.createSpy('workflow').and.returnValue(workflow);
$provide.value('horizon.dashboard.project.lbaasv2.workflow.model', model);
$provide.value('horizon.dashboard.project.lbaasv2.workflow.workflow', workflowSpy);
}));
beforeEach(inject(function ($controller, $injector) {
scope = $injector.get('$rootScope').$new();
spyOn(model, 'initialize').and.callThrough();
ctrl = $controller('UpdateMemberListWizardController', {
$scope: scope,
$routeParams: {loadbalancerId: 'loadbalancerId',
poolId: 'poolId'}});
}));
it('defines the controller', function() {
expect(ctrl).toBeDefined();
});
it('calls initialize on the given model', function() {
expect(model.initialize).toHaveBeenCalledWith('members', false, 'loadbalancerId', 'poolId');
});
it('sets scope.workflow to the given workflow', function() {
expect(scope.workflow).toBe(workflow);
});
it('initializes workflow with correct properties', function() {
expect(workflowSpy).toHaveBeenCalledWith('Add/Remove Pool Members',
'fa fa-pencil', ['members']);
});
it('defines scope.submit', function() {
expect(scope.submit).toBe(model.submit);
expect(scope.submit()).toBe('updated');
});
});
})();

View File

@ -23,6 +23,7 @@
MembersTableController.$inject = [
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.dashboard.project.lbaasv2.members.actions.rowActions',
'horizon.dashboard.project.lbaasv2.members.actions.batchActions',
'$routeParams'
];
@ -35,11 +36,12 @@
*
* @param api The LBaaS V2 service API.
* @param rowActions The pool members row actions service.
* @param batchActions The members batch actions service.
* @param $routeParams The angular $routeParams service.
* @returns undefined
*/
function MembersTableController(api, rowActions, $routeParams) {
function MembersTableController(api, rowActions, batchActions, $routeParams) {
var ctrl = this;
ctrl.items = [];
@ -49,6 +51,7 @@
ctrl.listenerId = $routeParams.listenerId;
ctrl.poolId = $routeParams.poolId;
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId, ctrl.poolId);
ctrl.batchActions = batchActions.init(ctrl.loadbalancerId);
init();

View File

@ -47,7 +47,13 @@
}));
function createController() {
return controller('MembersTableController', { $scope: scope });
return controller('MembersTableController', {
$scope: scope,
$routeParams: {
loadbalancerId: 'loadbaancerId',
listenerId: 'listenerId',
poolId: 'poolId'
}});
}
it('should initialize correctly', function() {
@ -55,6 +61,10 @@
expect(ctrl.items).toEqual([]);
expect(ctrl.src).toEqual(items);
expect(ctrl.checked).toEqual({});
expect(ctrl.loadbalancerId).toBeDefined();
expect(ctrl.listenerId).toBeDefined();
expect(ctrl.poolId).toBeDefined();
expect(ctrl.batchActions).toBeDefined();
});
it('should invoke lbaasv2 apis', function() {

View File

@ -17,7 +17,9 @@
This is where batch actions like searching, creating, and deleting.
-->
<th colspan="6" class="search-header">
<hz-search-bar icon-classes="fa-search"></hz-search-bar>
<hz-search-bar icon-classes="fa-search">
<actions allowed="table.batchActions.actions" type="batch"></actions>
</hz-search-bar>
</th>
</tr>

View File

@ -42,7 +42,7 @@
ng-class="{ 'has-error': memberDetailsForm['{$ ::row.id $}-address'].$invalid && memberDetailsForm['{$ ::row.id $}-address'].$dirty }">
<input name="{$ ::row.id $}-address" type="text" class="form-control"
ng-model="row.address" ng-pattern="::ctrl.ipPattern"
ng-required="true" ng-disabled="model.context.id && row.allocatedMember"
ng-required="true" ng-disabled="row.allocatedMember"
popover-placement="top" popover-append-to-body="true"
popover-trigger="focus"
ng-attr-popover="{$ memberDetailsForm[row.id + '-address'].$invalid && memberDetailsForm[row.id + '-address'].$dirty ? ctrl.ipError : '' $}">
@ -61,7 +61,7 @@
<select name="{$ ::row.id $}-subnet" class="form-control"
ng-options="subnet.name for subnet in model.subnets"
ng-model="row.subnet" ng-required="true"
ng-disabled="model.context.id && row.allocatedMember">
ng-disabled="row.allocatedMember">
</select>
</div>
<span ng-if="row.addresses">{$ ctrl.getSubnetName(row) $}</span>
@ -71,7 +71,7 @@
ng-class="{ 'has-error': memberDetailsForm['{$ ::row.id $}-port'].$invalid && memberDetailsForm['{$ ::row.id $}-port'].$dirty }">
<input name="{$ ::row.id $}-port" type="number" class="form-control"
ng-model="row.port" ng-pattern="/^\d+$/" min="1" max="65535"
ng-required="true" ng-disabled="model.context.id && row.allocatedMember"
ng-required="true" ng-disabled="row.allocatedMember"
popover-placement="top" popover-append-to-body="true"
popover-trigger="focus"
ng-attr-popover="{$ memberDetailsForm[row.id + '-port'].$invalid && memberDetailsForm[row.id + '-port'].$dirty ? ctrl.portError : '' $}">
@ -82,7 +82,7 @@
ng-class="{ 'has-error': memberDetailsForm['{$ ::row.id $}-weight'].$invalid && memberDetailsForm['{$ ::row.id $}-weight'].$dirty }">
<input name="{$ ::row.id $}-weight" type="number" class="form-control"
ng-model="row.weight" ng-pattern="/^\d+$/" min="1" max="256"
ng-disabled="model.context.id && row.allocatedMember"
ng-disabled="row.allocatedMember"
popover-placement="top" popover-append-to-body="true"
popover-trigger="focus"
ng-attr-popover="{$ memberDetailsForm[row.id + '-weight'].$invalid && memberDetailsForm[row.id + '-weight'].$dirty ? ctrl.weightError : '' $}">

View File

@ -188,6 +188,7 @@
'createlistener': initCreateListener,
'createpool': initCreatePool,
'createmonitor': initCreateMonitor,
'createmembers': initUpdateMemberList,
'editloadbalancer': initEditLoadBalancer,
'editlistener': initEditListener,
'editpool': initEditPool,
@ -246,6 +247,16 @@
return $q.when();
}
function initUpdateMemberList() {
model.context.submit = updatePoolMemberList;
return $q.all([
lbaasv2API.getPool(model.spec.parentResourceId).then(onGetPool),
neutronAPI.getSubnets().then(onGetSubnets).then(getMembers).then(onGetMembers),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers)
]).then(initMemberAddresses);
}
function initEditLoadBalancer() {
model.context.submit = editLoadBalancer;
return $q.all([
@ -331,6 +342,10 @@
return lbaasv2API.editHealthMonitor(model.context.id, spec);
}
function updatePoolMemberList(spec) {
return lbaasv2API.updateMemberList(model.spec.parentResourceId, spec);
}
function cleanFinalSpecLoadBalancer(finalSpec) {
var context = model.context;
@ -493,6 +508,10 @@
ports = response.data.items;
}
function onGetMembers(response) {
setMembersSpec(response.data.items);
}
function initMemberAddresses() {
angular.forEach(model.members, function initAddresses(member) {
var memberPorts = ports.filter(function filterPortByDevice(port) {
@ -523,6 +542,10 @@
return lbaasv2API.getPool(model.context.id, true);
}
function getMembers() {
return lbaasv2API.getMembers(model.spec.parentResourceId);
}
function onGetLoadBalancer(response) {
var loadbalancer = response.data;
setLoadBalancerSpec(loadbalancer);
@ -570,8 +593,9 @@
function onGetPool(response) {
var result = response.data;
setPoolSpec(result.pool || result);
if (result.pool) {
setPoolSpec(result.pool);
model.visibleResources.push('pool');
model.visibleResources.push('members');

View File

@ -188,6 +188,9 @@
},
editHealthMonitor: function(id, spec) {
return spec;
},
updateMemberList: function(id, spec) {
return spec;
}
});
@ -795,9 +798,90 @@
});
});
describe('Post initialize model (update member list)', function() {
beforeEach(function() {
includeChildResources = false;
model.initialize('members', false, 'loadbalancerId', 'poolId');
scope.$apply();
});
it('should initialize model properties', function() {
expect(model.initializing).toBe(false);
expect(model.initialized).toBe(true);
expect(model.subnets.length).toBe(2);
expect(model.members.length).toEqual(2);
expect(model.spec).toBeDefined();
expect(model.spec.loadbalancer_id).toBeDefined();
expect(model.spec.loadbalancer).toBeDefined();
expect(model.spec.listener).toBeDefined();
expect(model.spec.pool).toBeDefined();
expect(model.subnets.length).toBe(2);
expect(model.spec.monitor).toBeDefined();
});
it('should initialize the loadbalancer_id property', function() {
expect(model.spec.loadbalancer_id).toBe('loadbalancerId');
});
it('should initialize all loadbalancer properties to null', function() {
expect(model.spec.loadbalancer.name).toBeNull();
expect(model.spec.loadbalancer.description).toBeNull();
expect(model.spec.loadbalancer.ip).toBeNull();
expect(model.spec.loadbalancer.subnet).toBeNull();
});
it('should initialize all listener properties to null', function() {
expect(model.spec.listener.id).toBeNull();
expect(model.spec.listener.name).toBe('Listener 1');
expect(model.spec.listener.description).toBeNull();
expect(model.spec.listener.protocol).toBeNull();
expect(model.spec.listener.port).toBeNull();
});
it('should initialize all pool properties', function() {
expect(model.spec.pool.id).toBe('1234');
expect(model.spec.pool.name).toBe('Pool 1');
expect(model.spec.pool.description).toBe('pool description');
expect(model.spec.pool.protocol).toBe('HTTP');
expect(model.spec.pool.method).toBe('ROUND_ROBIN');
});
it('should initialize all monitor properties to null', function() {
expect(model.spec.monitor.id).toBeNull();
expect(model.spec.monitor.type).toBeNull();
expect(model.spec.monitor.interval).toBe(5);
expect(model.spec.monitor.retry).toBe(3);
expect(model.spec.monitor.timeout).toBe(5);
expect(model.spec.monitor.method).toBe('GET');
expect(model.spec.monitor.status).toBe('200');
expect(model.spec.monitor.path).toBe('/');
});
it('should initialize members and properties', function() {
expect(model.spec.members[0].id).toBe('1234');
expect(model.spec.members[0].address).toBe('1.2.3.4');
expect(model.spec.members[0].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[0].port).toBe(80);
expect(model.spec.members[0].weight).toBe(1);
expect(model.spec.members[1].id).toBe('5678');
expect(model.spec.members[1].address).toBe('5.6.7.8');
expect(model.spec.members[1].subnet).toEqual({ id: 'subnet-1', name: 'subnet-1' });
expect(model.spec.members[1].port).toBe(80);
expect(model.spec.members[1].weight).toBe(1);
});
it('should initialize context', function() {
expect(model.context.resource).toBe('members');
expect(model.context.id).toBeFalsy();
expect(model.context.submit).toBeDefined();
});
});
describe('Post initialize model (edit listener TERMINATED_HTTPS)', function() {
beforeEach(function() {
includeChildResources = true;
listenerResources.listener.protocol = 'TERMINATED_HTTPS';
model.initialize('listener', '1234');
scope.$apply();
@ -1052,6 +1136,20 @@
});
});
describe('context (update member list)', function() {
beforeEach(function() {
model.initialize('members', false, 'loadbalancerId', 'poolId');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('members');
expect(model.context.id).toBeFalsy();
expect(model.context.submit.name).toBe('updatePoolMemberList');
});
});
describe('Model submit function (create loadbalancer)', function() {
beforeEach(function() {
@ -1799,7 +1897,47 @@
});
});
describe('Model submit function (edit pool, no pool in response)', function() {
describe('Model submit function (update member list)', function() {
beforeEach(function() {
includeChildResources = false;
model.initialize('members', false, 'loadbalancerId', 'poolId');
scope.$apply();
});
it('should set final spec properties', function() {
var finalSpec = model.submit();
expect(finalSpec.loadbalancer_id).toBe('loadbalancerId');
expect(finalSpec.parentResourceId).toBe('poolId');
expect(finalSpec.loadbalancer).toBeUndefined();
expect(finalSpec.listener).toBeUndefined();
expect(finalSpec.pool.name).toBe('Pool 1');
expect(finalSpec.pool.description).toBe('pool description');
expect(finalSpec.pool.protocol).toBe('HTTP');
expect(finalSpec.pool.method).toBe('ROUND_ROBIN');
expect(finalSpec.members.length).toBe(2);
expect(finalSpec.members[0].id).toBe('1234');
expect(finalSpec.members[0].address).toBe('1.2.3.4');
expect(finalSpec.members[0].subnet).toBe('subnet-1');
expect(finalSpec.members[0].port).toBe(80);
expect(finalSpec.members[0].weight).toBe(1);
expect(finalSpec.members[1].id).toBe('5678');
expect(finalSpec.members[1].address).toBe('5.6.7.8');
expect(finalSpec.members[1].subnet).toBe('subnet-1');
expect(finalSpec.members[1].port).toBe(80);
expect(finalSpec.members[1].weight).toBe(1);
expect(finalSpec.monitor.interval).toBe(5);
expect(finalSpec.monitor.retry).toBe(3);
expect(finalSpec.monitor.timeout).toBe(5);
});
});
describe('Model visible resources (edit pool, no pool in response)', function() {
beforeEach(function() {
includeChildResources = true;
@ -1813,7 +1951,7 @@
});
});
describe('Model submit function (edit pool, no existing members)', function() {
describe('Model visible resources (edit pool, no existing members)', function() {
beforeEach(function() {
includeChildResources = true;
@ -1828,7 +1966,7 @@
});
});
describe('Model submit function (edit pool, no monitor)', function() {
describe('Model visible resources (edit pool, no monitor)', function() {
beforeEach(function() {
includeChildResources = true;