Add support for editing a load balancer

This adds the row action to the load balancers table to allow
editing the load balancer.

Partially-Implements: blueprint horizon-lbaas-v2-ui
Change-Id: I20b2d4171f2dc06da903036cfb5918986b5f907b
This commit is contained in:
Justin Pomeroy 2015-12-18 19:01:54 -06:00
parent 39c2a18699
commit 3c48addc20
18 changed files with 530 additions and 82 deletions

View File

@ -230,3 +230,17 @@ class LoadBalancer(generic.View):
"""
lb = neutronclient(request).show_loadbalancer(loadbalancer_id)
return lb.get('loadbalancer')
@rest_utils.ajax()
def put(self, request, loadbalancer_id):
"""Edit a load balancer.
"""
data = request.DATA
spec = {}
if data['loadbalancer'].get('name'):
spec['name'] = data['loadbalancer']['name']
if data['loadbalancer'].get('description'):
spec['description'] = data['loadbalancer']['description']
return neutronclient(request).update_loadbalancer(
loadbalancer_id, {'loadbalancer': spec}).get('loadbalancer')

View File

@ -38,8 +38,11 @@ ADD_JS_FILES = [
'dashboard/project/lbaasv2/loadbalancers/detail.controller.js',
'dashboard/project/lbaasv2/loadbalancers/filters.js',
'dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.js',
'dashboard/project/lbaasv2/loadbalancers/actions/row-actions.service.js',
('dashboard/project/lbaasv2/loadbalancers/actions/create/'
'wizard.controller.js'),
('dashboard/project/lbaasv2/loadbalancers/actions/edit/'
'wizard.controller.js'),
'dashboard/project/lbaasv2/workflow/modal.service.js',
'dashboard/project/lbaasv2/workflow/model.service.js',
'dashboard/project/lbaasv2/workflow/workflow.service.js',
@ -60,8 +63,12 @@ ADD_JS_SPEC_FILES = [
'dashboard/project/lbaasv2/loadbalancers/filters.spec.js',
('dashboard/project/lbaasv2/loadbalancers/actions/'
'batch-actions.service.spec.js'),
('dashboard/project/lbaasv2/loadbalancers/actions/'
'row-actions.service.spec.js'),
('dashboard/project/lbaasv2/loadbalancers/actions/create/'
'wizard.controller.spec.js'),
('dashboard/project/lbaasv2/loadbalancers/actions/edit/'
'wizard.controller.spec.js'),
'dashboard/project/lbaasv2/workflow/modal.service.spec.js',
'dashboard/project/lbaasv2/workflow/model.service.spec.js',
'dashboard/project/lbaasv2/workflow/workflow.service.spec.js',

View File

@ -38,7 +38,8 @@
var service = {
getLoadBalancers: getLoadBalancers,
getLoadBalancer: getLoadBalancer,
createLoadBalancer: createLoadBalancer
createLoadBalancer: createLoadBalancer,
editLoadBalancer: editLoadBalancer
};
return service;
@ -93,5 +94,21 @@
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.editLoadBalancer
* @description
* Edit a load balancer
* @param {string} id
* @param {object} spec
* Specifies the data used to update the load balancer.
*/
function editLoadBalancer(id, spec) {
return apiService.put('/api/lbaas/loadbalancers/' + id + '/', spec)
.error(function () {
toastService.add('error', gettext('Unable to update load balancer.'));
});
}
}
}());

View File

@ -60,6 +60,16 @@
"testInput": [
{ name: 'loadbalancer-1' }
]
},
{
"func": "editLoadBalancer",
"method": "put",
"path": "/api/lbaas/loadbalancers/1234/",
"error": "Unable to update load balancer.",
"data": { name: 'loadbalancer-1' },
"testInput": [
'1234', { name: 'loadbalancer-1' }
]
}
];

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.loadbalancers')
.controller('EditLoadBalancerWizardController', EditLoadBalancerWizardController);
EditLoadBalancerWizardController.$inject = [
'$scope',
'horizon.dashboard.project.lbaasv2.workflow.model',
'horizon.dashboard.project.lbaasv2.workflow.workflow',
'horizon.framework.util.i18n.gettext'
];
function EditLoadBalancerWizardController($scope, model, workflowService, gettext) {
var scope = $scope;
// Note: We set these attributes on the $scope so that the scope inheritance used all through
// the wizard continues to work. Using local var to appease eslint angular/ng_controller_as.
scope.model = model;
scope.submit = scope.model.submit;
scope.workflow = workflowService(gettext('Update Load Balancer'),
'fa fa-pencil',
['loadbalancer']);
scope.model.initialize('loadbalancer', scope.launchContext.id);
}
})();

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 Edit Load Balancer Wizard Controller', function() {
var ctrl, workflowSpy;
var model = {
submit: function() {
return 'updated';
},
initialize: angular.noop
};
var workflow = 'foo';
var scope = {
launchContext: { id: '1' }
};
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) {
spyOn(model, 'initialize');
ctrl = $controller('EditLoadBalancerWizardController', { $scope: scope });
}));
it('defines the controller', function() {
expect(ctrl).toBeDefined();
});
it('calls initialize on the given model', function() {
expect(model.initialize).toHaveBeenCalledWith('loadbalancer', '1');
});
it('sets scope.workflow to the given workflow', function() {
expect(scope.workflow).toBe(workflow);
});
it('initializes workflow with correct properties', function() {
expect(workflowSpy).toHaveBeenCalledWith('Update Load Balancer',
'fa fa-pencil', ['loadbalancer']);
});
it('defines scope.submit', function() {
expect(scope.submit).toBe(model.submit);
expect(scope.submit()).toBe('updated');
});
});
})();

View File

@ -0,0 +1,89 @@
/*
* 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.loadbalancers')
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions',
tableRowActions);
tableRowActions.$inject = [
'$q',
'$route',
'horizon.dashboard.project.lbaasv2.workflow.modal',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.util.q.extensions',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc service
* @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions
*
* @description
* Provides the service for the Load Balancers table row actions.
*
* @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 qExtensions Horizon extensions to the $q service.
* @param gettext The horizon gettext function for translation.
* @returns Load balancers table batch actions service object.
*/
function tableRowActions($q, $route, workflowModal, policy, qExtensions, gettext) {
var edit = workflowModal.init({
controller: 'EditLoadBalancerWizardController',
message: gettext('The load balancer has been updated.'),
handle: onEdit,
allowed: canEdit
});
var service = {
actions: actions
};
return service;
///////////////
function actions() {
return [{
service: edit,
template: {
text: gettext('Edit')
}
}];
}
function canEdit(item) {
return $q.all([
qExtensions.booleanAsPromise(item.provisioning_status === 'ACTIVE'),
// This rule is made up and should therefore always pass. At some point there will
// likely be a valid rule similar to this that we will want to use.
policy.ifAllowed({ rules: [['neutron', 'update_loadbalancer']] })
]);
}
function onEdit(/*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 Load Balancers Table Row Actions Service', function() {
var rowActionsService, scope, $route, actions, policy;
function canEdit(item) {
spyOn(policy, 'ifAllowed').and.returnValue(true);
var promise = actions[0].service.allowed(item);
var allowed;
promise.then(function() {
allowed = true;
}, function() {
allowed = false;
});
scope.$apply();
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_loadbalancer']]});
return allowed;
}
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.widgets.toast'));
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) {
scope = $injector.get('$rootScope').$new();
$route = $injector.get('$route');
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
rowActionsService = $injector.get(
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions');
actions = rowActionsService.actions();
}));
it('should define correct table row actions', function() {
expect(actions.length).toBe(1);
expect(actions[0].template.text).toBe('Edit');
});
it('should allow editing an ACTIVE load balancer', function() {
expect(canEdit({provisioning_status: 'ACTIVE'})).toBe(true);
});
it('should not allow editing a non-ACTIVE load balancer', function() {
expect(canEdit({provisioning_status: 'PENDING_UPDATE'})).toBe(false);
});
it('should have the "allowed" and "perform" functions', function() {
actions.forEach(function(action) {
expect(action.service.allowed).toBeDefined();
expect(action.service.perform).toBeDefined();
});
});
it('should reload table after edit', function() {
spyOn($route, 'reload').and.callThrough();
actions[0].service.perform();
expect($route.reload).toHaveBeenCalled();
});
});
})();

View File

@ -22,6 +22,7 @@
LoadBalancerDetailController.$inject = [
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions',
'$routeParams'
];
@ -33,14 +34,16 @@
* Controller for the LBaaS v2 load balancers detail page.
*
* @param api The LBaaS v2 API service.
* @param rowActions The load balancer row actions service.
* @param $routeParams The angular $routeParams service.
* @returns undefined
*/
function LoadBalancerDetailController(api, $routeParams) {
function LoadBalancerDetailController(api, rowActions, $routeParams) {
var ctrl = this;
ctrl.loadbalancer = {};
ctrl.loadbalancer = null;
ctrl.actions = rowActions.actions;
var loadbalancerId = $routeParams.loadbalancerId;

View File

@ -29,12 +29,16 @@
///////////////////////
beforeEach(module('horizon.framework.util.http'));
beforeEach(module('horizon.framework.widgets.toast'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.framework.util'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module(function($provide) {
$provide.value('$modal', {});
}));
beforeEach(inject(function($injector) {
loadbalancer = { id: '1234' };
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');

View File

@ -7,6 +7,8 @@
<p ng-if="::ctrl.loadbalancer.description">{$ ::ctrl.loadbalancer.description $}</p>
</div>
<div class="detail-page">
<actions allowed="ctrl.actions" type="row" item="ctrl.loadbalancer"
ng-if="ctrl.loadbalancer" class="pull-right"></actions>
<div class="detail-statuses">
<div>
<strong translate>IP Address</strong>

View File

@ -22,7 +22,8 @@
LoadBalancersTableController.$inject = [
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions'
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions',
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions'
];
/**
@ -34,16 +35,18 @@
*
* @param api The LBaaS V2 service API.
* @param batchActions The load balancer batch actions service.
* @param rowActions The load balancer row actions service.
* @returns undefined
*/
function LoadBalancersTableController(api, batchActions) {
function LoadBalancersTableController(api, batchActions, rowActions) {
var ctrl = this;
ctrl.items = [];
ctrl.src = [];
ctrl.checked = {};
ctrl.batchActions = batchActions;
ctrl.rowActions = rowActions;
init();

View File

@ -44,7 +44,6 @@
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
controller = $injector.get('$controller');
scope = $injector.get('$rootScope').$new();
scope.lbaasv2API = lbaasv2API;
spyOn(lbaasv2API, 'getLoadBalancers').and.callFake(fakeAPI);
}));
@ -58,6 +57,7 @@
expect(ctrl.src).toEqual(items);
expect(ctrl.checked).toEqual({});
expect(ctrl.batchActions).toBeDefined();
expect(ctrl.rowActions).toBeDefined();
});
it('should invoke lbaasv2 apis', function() {

View File

@ -77,6 +77,13 @@
<td class="rsp-p1">{$ item.provisioning_status | provisioningStatus $}</td>
<td class="rsp-p2">{$ item.vip_address $}</td>
<td class="rsp-p2">{$ item.listeners.length $}</td>
<td class="action-col">
<!--
Table-row-action-column:
Actions taken here apply to a single item/row.
-->
<actions allowed="table.rowActions.actions" type="row" item="item"></actions>
</td>
</tr>
<tr ng-repeat-end class="detail-row">

View File

@ -35,7 +35,7 @@
<select class="form-control input-sm" name="listener-protocol"
id="listener-protocol"
ng-options="protocol for protocol in model.listenerProtocols"
ng-model="model.spec.listener.protocol" ng-required="model.context.type === 'listener'">
ng-model="model.spec.listener.protocol" ng-required="model.context.resource === 'listener'">
</select>
</div>
</div>
@ -52,7 +52,7 @@
<input name="listener-port" id="listener-port"
type="number" class="form-control input-sm"
ng-model="model.spec.listener.port" ng-pattern="/^\d+$/" min="1" max="65535"
ng-required="model.context.type === 'listener'">
ng-required="model.context.resource === 'listener'">
</div>
</div>

View File

@ -39,7 +39,8 @@
popover-trigger="hover"></span>
<input name="loadbalancer-ip" id="loadbalancer-ip"
type="text" class="form-control input-sm"
ng-model="model.spec.loadbalancer.ip" ng-pattern="::ctrl.ipPattern">
ng-model="model.spec.loadbalancer.ip" ng-pattern="::ctrl.ipPattern"
ng-disabled="model.context.resource === 'loadbalancer' && model.context.id">
</div>
</div>
@ -49,7 +50,8 @@
<select class="form-control input-sm" name="loadbalancer-subnet"
id="loadbalancer-subnet"
ng-options="subnet.name for subnet in model.subnets"
ng-model="model.spec.loadbalancer.subnet" ng-required="true">
ng-model="model.spec.loadbalancer.subnet" ng-required="true"
ng-disabled="model.context.resource === 'loadbalancer' && model.context.id">
</select>
</div>
</div>

View File

@ -144,56 +144,27 @@
} else {
model.initializing = true;
var promises = [];
switch ((id ? 'edit' : 'create') + resource) {
case 'createloadbalancer':
promise = $q.all([
lbaasv2API.getLoadBalancers().then(onGetLoadBalancers),
neutronAPI.getSubnets().then(onGetSubnets),
neutronAPI.getPorts().then(onGetPorts),
novaAPI.getServers().then(onGetServers)
]).then(initMemberAddresses);
model.context.submit = createLoadBalancer;
break;
case 'editloadbalancer':
promise = $q.all([
lbaasv2API.getLoadBalancer(model.context.id).then(onGetLoadBalancer),
neutronAPI.getSubnets().then(onGetSubnets)
]).then(initSubnet);
model.context.submit = editLoadBalancer;
break;
default:
throw Error('Invalid resource context: ' + (id ? 'edit' : 'create') + resource);
}
promises.push(lbaasv2API.getLoadBalancers().then(onGetLoadBalancers));
promises.push(neutronAPI.getSubnets().then(onGetSubnets));
promises.push(neutronAPI.getPorts().then(onGetPorts));
promises.push(novaAPI.getServers().then(onGetServers));
model.context.submit = createLoadBalancer;
// // Create load balancer (default)
// if (resource === 'loadbalancer' && !id) {
// promises.push(lbaasv2API.getLoadBalancers().then(onGetLoadBalancers));
// promises.push(neutronAPI.getSubnets().then(onGetSubnets));
// promises.push(neutronAPI.getPorts().then(onGetPorts));
// promises.push(novaAPI.getServers().then(onGetServers));
// model.context.submit = createLoadBalancer;
// }
// // Edit load balancer
// else if (resource === 'loadbalancer' && id) {
// // Get load balancer
// model.context.submit = editLoadBalancer;
// }
// // Create listener
// else if (resource === 'listener' && !id) {
// promises.push(neutronAPI.getSubnets().then(onGetSubnets));
// promises.push(neutronAPI.getPorts().then(onGetPorts));
// promises.push(novaAPI.getServers().then(onGetServers));
// model.context.submit = createListener;
// }
// // Edit listener
// else if (resource === 'listener' && id) {
// // Get listener, pool, members, monitor
// model.context.submit = editListener;
// }
// // Edit pool
// else if (resource === 'pool' && id) {
// // Get pool, members, monitor
// model.context.submit = editPool;
// }
// // Edit monitor
// else if (resource === 'monitor' && id) {
// // Get monitor
// model.context.submit = editMonitor;
// }
// // Edit members
// else if (resource === 'members' && id) {
// // Get pool members by pool id
// model.context.submit = editMembers;
// }
promise = $q.all(promises);
promise.then(onInitSuccess, onInitFail);
}
@ -201,7 +172,6 @@
}
function onInitSuccess() {
initMemberAddresses();
model.initializing = false;
model.initialized = true;
}
@ -224,7 +194,25 @@
function submit() {
var finalSpec = angular.copy(model.spec);
var resource = model.context.resource;
cleanFinalSpecLoadBalancer(finalSpec);
cleanFinalSpecListener(finalSpec);
cleanFinalSpecPool(finalSpec);
cleanFinalSpecMembers(finalSpec);
cleanFinalSpecMonitor(finalSpec);
removeNulls(finalSpec);
return model.context.submit(finalSpec);
}
function createLoadBalancer(spec) {
return lbaasv2API.createLoadBalancer(spec);
}
function editLoadBalancer(spec) {
return lbaasv2API.editLoadBalancer(model.context.id, spec);
}
function cleanFinalSpecLoadBalancer(finalSpec) {
var context = model.context;
// Load balancer requires subnet
if (!finalSpec.loadbalancer.subnet) {
@ -233,10 +221,23 @@
finalSpec.loadbalancer.subnet = finalSpec.loadbalancer.subnet.id;
}
// Cannot edit the subnet
if (context.resource === 'loadbalancer' && context.id) {
delete finalSpec.subnet;
delete finalSpec.ip;
}
}
function cleanFinalSpecListener(finalSpec) {
// Listener requires protocol and port
if (!finalSpec.listener.protocol || !finalSpec.listener.port) {
delete finalSpec.listener;
}
}
function cleanFinalSpecPool(finalSpec) {
var resource = model.context.resource;
// Pool requires protocol and method, and also the listener
if (resource !== 'pool' && !finalSpec.listener ||
@ -244,16 +245,6 @@
!finalSpec.pool.method) {
delete finalSpec.pool;
}
cleanFinalSpecMembers(finalSpec);
cleanFinalSpecMonitor(finalSpec);
removeNulls(finalSpec);
return model.context.submit(finalSpec);
}
function createLoadBalancer(spec) {
return lbaasv2API.createLoadBalancer(spec);
}
function cleanFinalSpecMembers(finalSpec) {
@ -304,7 +295,7 @@
function onGetLoadBalancers(response) {
var existingNames = {};
angular.forEach(response.data.items, function(lb) {
angular.forEach(response.data.items, function nameExists(lb) {
existingNames[lb.name] = 1;
});
var name;
@ -324,7 +315,7 @@
function onGetServers(response) {
model.members.length = 0;
var members = [];
angular.forEach(response.data.items, function(server) {
angular.forEach(response.data.items, function addMember(server) {
members.push({
id: server.id,
name: server.name,
@ -340,13 +331,13 @@
}
function initMemberAddresses() {
angular.forEach(model.members, function(member) {
var memberPorts = ports.filter(function(port) {
angular.forEach(model.members, function initAddresses(member) {
var memberPorts = ports.filter(function filterPortByDevice(port) {
return port.device_id === member.id;
});
member.addresses = [];
angular.forEach(memberPorts, function(port) {
angular.forEach(port.fixed_ips, function(ip) {
angular.forEach(memberPorts, function addAddressesForPort(port) {
angular.forEach(port.fixed_ips, function addAddress(ip) {
member.addresses.push({
ip: ip.ip_address,
subnet: ip.subnet_id
@ -357,6 +348,22 @@
});
}
function onGetLoadBalancer(response) {
var loadbalancer = response.data;
var spec = model.spec.loadbalancer;
spec.name = loadbalancer.name || '';
spec.description = loadbalancer.description || '';
spec.ip = loadbalancer.vip_address || '';
spec.subnet = loadbalancer.vip_subnet_id;
}
function initSubnet() {
var subnet = model.subnets.filter(function filterSubnetsByLoadBalancer(s) {
return s.id === model.spec.loadbalancer.subnet;
})[0];
model.spec.loadbalancer.subnet = subnet;
}
return model;
}

View File

@ -32,8 +32,19 @@
return deferred.promise;
},
getLoadBalancer: function() {
var loadbalancer = { vip_subnet_id: 'subnet-1' };
var deferred = $q.defer();
deferred.resolve({ data: loadbalancer });
return deferred.promise;
},
createLoadBalancer: function(spec) {
return spec;
},
editLoadBalancer: function(id, spec) {
return spec;
}
});
@ -190,7 +201,7 @@
}));
beforeEach(function() {
model.initialize();
model.initialize('loadbalancer');
scope.$apply();
});
@ -202,11 +213,29 @@
});
});
describe('Resource not provided', function() {
var initModelNoContext = function() {
model.initialize();
};
var initModelNoResource = function() {
model.initialize('', 'foo');
};
it('should fail to be initialized - create', function() {
expect(initModelNoContext).toThrow(Error('Invalid resource context: createundefined'));
});
it('should fail to be initialized - edit', function() {
expect(initModelNoResource).toThrow(Error('Invalid resource context: edit'));
});
});
describe('Post initialize model - Initializing', function() {
beforeEach(function() {
model.initializing = true;
model.initialize();
model.initialize('loadbalancer');
scope.$apply();
});
@ -297,10 +326,38 @@
});
});
describe('Model submit function', function() {
describe('context (create loadbalancer)', function() {
beforeEach(function() {
model.initialize();
model.initialize('loadbalancer');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('loadbalancer');
expect(model.context.id).toBeUndefined();
expect(model.context.submit.name).toBe('createLoadBalancer');
});
});
describe('context (edit loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer', '1');
scope.$apply();
});
it('should initialize context', function() {
expect(model.context.resource).toBe('loadbalancer');
expect(model.context.id).toBe('1');
expect(model.context.submit.name).toBe('editLoadBalancer');
});
});
describe('Model submit function (create loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer');
scope.$apply();
});
@ -427,5 +484,24 @@
});
});
describe('Model submit function (edit loadbalancer)', function() {
beforeEach(function() {
model.initialize('loadbalancer', '1');
scope.$apply();
});
it('should set final spec properties', function() {
model.spec.loadbalancer.description = 'new description';
var finalSpec = model.submit();
expect(finalSpec.loadbalancer.name).toBe('');
expect(finalSpec.loadbalancer.description).toBe('new description');
expect(finalSpec.loadbalancer.ip).toBe('');
expect(finalSpec.loadbalancer.subnet).toBe('subnet-1');
});
});
});
})();