Add the Angular LBaaS V2 'Create Listener' workflow
This change adds the Create Listener workflow action to the listeners table on the load balancer detail page. This wizard allows you to crete a new listener, as well as any resource below it in the hierarchy. Partially-Implements: blueprint horizon-lbaas-v2-ui Change-Id: I40488eac6c116e363071fb82ba3473a8b0430ed9
This commit is contained in:
parent
73f1e37304
commit
af63722e3a
@ -59,6 +59,31 @@ def poll_loadbalancer_status(request, loadbalancer_id, callback,
|
||||
callback(request, **kwargs)
|
||||
|
||||
|
||||
def create_loadbalancer(request):
|
||||
data = request.DATA
|
||||
spec = {
|
||||
'vip_subnet_id': data['loadbalancer']['subnet']
|
||||
}
|
||||
if data['loadbalancer'].get('name'):
|
||||
spec['name'] = data['loadbalancer']['name']
|
||||
if data['loadbalancer'].get('description'):
|
||||
spec['description'] = data['loadbalancer']['description']
|
||||
if data['loadbalancer'].get('ip'):
|
||||
spec['vip_address'] = data['loadbalancer']['ip']
|
||||
loadbalancer = neutronclient(request).create_loadbalancer(
|
||||
{'loadbalancer': spec}).get('loadbalancer')
|
||||
if data.get('listener'):
|
||||
# There is work underway to add a new API to LBaaS v2 that will
|
||||
# allow us to pass in all information at once. Until that is
|
||||
# available we use a separate thread to poll for the load
|
||||
# balancer status and create the other resources when it becomes
|
||||
# active.
|
||||
args = (request, loadbalancer['id'], create_listener)
|
||||
kwargs = {'from_state': 'PENDING_CREATE'}
|
||||
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
|
||||
return loadbalancer
|
||||
|
||||
|
||||
def create_listener(request, **kwargs):
|
||||
"""Create a new listener.
|
||||
|
||||
@ -391,28 +416,7 @@ class LoadBalancers(generic.View):
|
||||
Creates a new load balancer as well as other optional resources such as
|
||||
a listener, pool, monitor, etc.
|
||||
"""
|
||||
data = request.DATA
|
||||
spec = {
|
||||
'vip_subnet_id': data['loadbalancer']['subnet']
|
||||
}
|
||||
if data['loadbalancer'].get('name'):
|
||||
spec['name'] = data['loadbalancer']['name']
|
||||
if data['loadbalancer'].get('description'):
|
||||
spec['description'] = data['loadbalancer']['description']
|
||||
if data['loadbalancer'].get('ip'):
|
||||
spec['vip_address'] = data['loadbalancer']['ip']
|
||||
loadbalancer = neutronclient(request).create_loadbalancer(
|
||||
{'loadbalancer': spec}).get('loadbalancer')
|
||||
if data.get('listener'):
|
||||
# There is work underway to add a new API to LBaaS v2 that will
|
||||
# allow us to pass in all information at once. Until that is
|
||||
# available we use a separate thread to poll for the load
|
||||
# balancer status and create the other resources when it becomes
|
||||
# active.
|
||||
args = (request, loadbalancer['id'], create_listener)
|
||||
kwargs = {'from_state': 'PENDING_CREATE'}
|
||||
thread.start_new_thread(poll_loadbalancer_status, args, kwargs)
|
||||
return loadbalancer
|
||||
return create_loadbalancer(request)
|
||||
|
||||
|
||||
@urls.register
|
||||
@ -473,6 +477,16 @@ class Listeners(generic.View):
|
||||
loadbalancer_id)
|
||||
return {'items': listener_list}
|
||||
|
||||
@rest_utils.ajax()
|
||||
def post(self, request):
|
||||
"""Create a new listener.
|
||||
|
||||
Creates a new listener as well as other optional resources such as
|
||||
a pool, members, and health monitor.
|
||||
"""
|
||||
kwargs = {'loadbalancer_id': request.DATA.get('loadbalancer_id')}
|
||||
return create_listener(request, **kwargs)
|
||||
|
||||
def _filter_listeners(self, listener_list, loadbalancer_id):
|
||||
filtered_listeners = []
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
editLoadBalancer: editLoadBalancer,
|
||||
getListeners: getListeners,
|
||||
getListener: getListener,
|
||||
createListener: createListener,
|
||||
editListener: editListener,
|
||||
getPool: getPool,
|
||||
getMembers: getMembers,
|
||||
@ -181,6 +182,21 @@
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.lbaasv2.createListener
|
||||
* @description
|
||||
* Create a new listener
|
||||
* @param {object} spec
|
||||
* Specifies the data used to create the new listener.
|
||||
*/
|
||||
|
||||
function createListener(spec) {
|
||||
return apiService.post('/api/lbaas/listeners/', spec)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to create listener.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.lbaasv2.editListener
|
||||
* @description
|
||||
|
@ -134,6 +134,14 @@
|
||||
data: { name: 'loadbalancer-1' },
|
||||
testInput: [ '1234', { name: 'loadbalancer-1' } ]
|
||||
},
|
||||
{
|
||||
func: 'createListener',
|
||||
method: 'post',
|
||||
path: '/api/lbaas/listeners/',
|
||||
error: 'Unable to create listener.',
|
||||
data: { name: 'listener-1' },
|
||||
testInput: [ { name: 'listener-1' } ]
|
||||
},
|
||||
{
|
||||
func: 'editListener',
|
||||
method: 'put',
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.listeners')
|
||||
.factory('horizon.dashboard.project.lbaasv2.listeners.actions.batchActions',
|
||||
tableBatchActions);
|
||||
|
||||
tableBatchActions.$inject = [
|
||||
'$q',
|
||||
'$location',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.listeners.actions.batchActions
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Listeners table batch actions.
|
||||
*
|
||||
* @param $q The angular service for promises.
|
||||
* @param $location The angular $location service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @returns Listeners table batch actions service object.
|
||||
*/
|
||||
|
||||
function tableBatchActions($q, $location, workflowModal, policy, gettext, loadBalancersService) {
|
||||
var loadBalancerIsActive, loadBalancerId;
|
||||
|
||||
var create = workflowModal.init({
|
||||
controller: 'CreateListenerWizardController',
|
||||
message: gettext('A new listener is being created.'),
|
||||
handle: onCreate,
|
||||
allowed: canCreate
|
||||
});
|
||||
|
||||
var service = {
|
||||
actions: actions,
|
||||
init: init
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function init(loadbalancerId) {
|
||||
loadBalancerId = loadbalancerId;
|
||||
loadBalancerIsActive = loadBalancersService.isActive(loadbalancerId);
|
||||
return service;
|
||||
}
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: create,
|
||||
template: {
|
||||
type: 'create',
|
||||
text: gettext('Create Listener')
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
function canCreate() {
|
||||
return $q.all([
|
||||
loadBalancerIsActive,
|
||||
policy.ifAllowed({ rules: [['neutron', 'create_listener']] })
|
||||
]);
|
||||
}
|
||||
|
||||
function onCreate(response) {
|
||||
var id = response.data.id;
|
||||
$location.path('project/ngloadbalancersv2/' + loadBalancerId + '/listeners/' + id);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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 Listeners Table Batch Actions Service', function() {
|
||||
var $location, actions, policy, $scope, $q;
|
||||
|
||||
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: '5678'
|
||||
}
|
||||
};
|
||||
var modal = {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
$provide.value('$modal', modal);
|
||||
$provide.value('horizon.dashboard.project.lbaasv2.loadbalancers.service', {
|
||||
isActive: function() {
|
||||
return $q.when();
|
||||
}
|
||||
});
|
||||
$provide.value('horizon.app.core.openstack-service-api.policy', {
|
||||
ifAllowed: function() {
|
||||
return $q.when();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
$location = $injector.get('$location');
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$q = $injector.get('$q');
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
var batchActionsService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.batchActions');
|
||||
actions = batchActionsService.init('1234').actions();
|
||||
$scope.$apply();
|
||||
}));
|
||||
|
||||
it('should define correct table batch actions', function() {
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions[0].template.text).toBe('Create Listener');
|
||||
});
|
||||
|
||||
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 check policy to allow creating a listener', function() {
|
||||
spyOn(policy, 'ifAllowed').and.callThrough();
|
||||
|
||||
var promise = actions[0].service.allowed();
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
$scope.$apply();
|
||||
|
||||
expect(allowed).toBe(true);
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'create_listener']]});
|
||||
});
|
||||
|
||||
it('should redirect after create', function() {
|
||||
spyOn($location, 'path').and.callThrough();
|
||||
actions[0].service.perform();
|
||||
expect($location.path).toHaveBeenCalledWith('project/ngloadbalancersv2/1234/listeners/5678');
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.listeners')
|
||||
.controller('CreateListenerWizardController', CreateListenerWizardController);
|
||||
|
||||
CreateListenerWizardController.$inject = [
|
||||
'$scope',
|
||||
'$routeParams',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.model',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.workflow',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
function CreateListenerWizardController($scope, $routeParams, model, workflowService, gettext) {
|
||||
var loadbalancerId = $routeParams.loadbalancerId;
|
||||
var scope = $scope;
|
||||
scope.model = model;
|
||||
scope.submit = scope.model.submit;
|
||||
scope.workflow = workflowService(
|
||||
gettext('Create Listener'),
|
||||
'fa fa-cloud-download',
|
||||
['listener', 'pool', 'members', 'monitor']
|
||||
);
|
||||
scope.model.initialize('listener', false, loadbalancerId);
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 Create Listener Wizard Controller', function() {
|
||||
var ctrl;
|
||||
var model = {
|
||||
submit: function() {
|
||||
return 'created';
|
||||
},
|
||||
initialize: angular.noop
|
||||
};
|
||||
var workflow = function() {
|
||||
return 'foo';
|
||||
};
|
||||
var scope = {};
|
||||
|
||||
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('CreateListenerWizardController', { $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('created');
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
@ -23,7 +23,8 @@
|
||||
ListenersTableController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'$routeParams',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions'
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.batchActions'
|
||||
];
|
||||
|
||||
/**
|
||||
@ -36,16 +37,18 @@
|
||||
* @param api The LBaaS V2 service API.
|
||||
* @param $routeParams The angular $routeParams service.
|
||||
* @param rowActions The listener row actions service.
|
||||
* @param batchActions The listener batch actions service.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function ListenersTableController(api, $routeParams, rowActions) {
|
||||
function ListenersTableController(api, $routeParams, rowActions, batchActions) {
|
||||
|
||||
var ctrl = this;
|
||||
ctrl.items = [];
|
||||
ctrl.src = [];
|
||||
ctrl.checked = {};
|
||||
ctrl.loadbalancerId = $routeParams.loadbalancerId;
|
||||
ctrl.batchActions = batchActions.init(ctrl.loadbalancerId);
|
||||
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId);
|
||||
|
||||
init();
|
||||
|
@ -17,7 +17,7 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Listeners Table Controller', function() {
|
||||
var controller, lbaasv2API, rowActions;
|
||||
var controller, lbaasv2API, rowActions, batchActions;
|
||||
var items = [];
|
||||
|
||||
function fakeAPI() {
|
||||
@ -48,6 +48,8 @@
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
controller = $injector.get('$controller');
|
||||
rowActions = $injector.get('horizon.dashboard.project.lbaasv2.listeners.actions.rowActions');
|
||||
batchActions = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.batchActions');
|
||||
spyOn(rowActions, 'init').and.callFake(initMock);
|
||||
spyOn(lbaasv2API, 'getListeners').and.callFake(fakeAPI);
|
||||
}));
|
||||
@ -65,7 +67,10 @@
|
||||
expect(ctrl.checked).toEqual({});
|
||||
expect(ctrl.loadbalancerId).toEqual('1234');
|
||||
expect(rowActions.init).toHaveBeenCalledWith(ctrl.loadbalancerId);
|
||||
expect(ctrl.rowActions).toBeDefined();
|
||||
expect(ctrl.rowActions).toEqual(rowActions);
|
||||
expect(ctrl.batchActions).toBeDefined();
|
||||
expect(ctrl.batchActions).toEqual(batchActions);
|
||||
});
|
||||
|
||||
it('should invoke lbaasv2 apis', function() {
|
||||
|
@ -17,7 +17,9 @@
|
||||
This is where batch actions like searching, creating, and deleting.
|
||||
-->
|
||||
<th colspan="7" 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>
|
||||
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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';
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name horizon.dashboard.project.lbaasv2:validateUnique
|
||||
* @element ng-model
|
||||
* @description
|
||||
* The `validateUnique` directive provides validation
|
||||
* for form input elements to ensure values are unique.
|
||||
*
|
||||
* Validator returns true if model/view value is not in
|
||||
* the array of values specified.
|
||||
*
|
||||
* @restrict A
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* <input type="number" ng-model="value"
|
||||
* validate-unique="[80,443]">
|
||||
* ```
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2')
|
||||
.directive('validateUnique', validateUnique);
|
||||
|
||||
function validateUnique() {
|
||||
var directive = {
|
||||
require: 'ngModel',
|
||||
restrict: 'A',
|
||||
link: link
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
//////////
|
||||
|
||||
function link(scope, element, attrs, ctrl) {
|
||||
ctrl.$parsers.push(uniqueValidator);
|
||||
ctrl.$formatters.push(uniqueValidator);
|
||||
|
||||
attrs.$observe('validateUnique', function () {
|
||||
uniqueValidator(ctrl.$modelValue);
|
||||
});
|
||||
|
||||
function uniqueValidator(value) {
|
||||
var values = scope.$eval(attrs.validateUnique);
|
||||
if (angular.isArray(values) && values.length > 0 && values.indexOf(value) > -1) {
|
||||
ctrl.$setValidity('unique', false);
|
||||
} else {
|
||||
ctrl.$setValidity('unique', true);
|
||||
}
|
||||
// Return the value rather than undefined if invalid
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
})();
|
@ -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('validate-unique directive', function () {
|
||||
|
||||
var $compile, scope, element, port, name;
|
||||
var markup =
|
||||
'<form>' +
|
||||
'<input type="number" ng-model="port" validate-unique="ports">' +
|
||||
'<input type="string" ng-model="name" validate-unique="names">' +
|
||||
'</form>';
|
||||
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
beforeEach(inject(function ($injector) {
|
||||
$compile = $injector.get('$compile');
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
|
||||
// generate dom from markup
|
||||
element = $compile(markup)(scope);
|
||||
port = element.children('input[type="number"]');
|
||||
name = element.children('input[type="string"]');
|
||||
|
||||
// setup up initial data
|
||||
scope.ports = [80, 443];
|
||||
scope.names = ['name1', 'name2'];
|
||||
scope.$apply();
|
||||
}));
|
||||
|
||||
it('should be initially empty', function () {
|
||||
expect(port.val()).toEqual('');
|
||||
expect(name.val()).toEqual('');
|
||||
expect(port.hasClass('ng-valid')).toBe(true);
|
||||
expect(name.hasClass('ng-valid')).toBe(true);
|
||||
});
|
||||
|
||||
it('should be invalid if values are not unique', function () {
|
||||
scope.port = 80;
|
||||
scope.name = 'name1';
|
||||
scope.$apply();
|
||||
expect(port.hasClass('ng-valid')).toBe(false);
|
||||
expect(name.hasClass('ng-valid')).toBe(false);
|
||||
});
|
||||
|
||||
it('should be valid if values are unique', function () {
|
||||
scope.port = 81;
|
||||
scope.name = 'name3';
|
||||
scope.$apply();
|
||||
expect(port.hasClass('ng-valid')).toBe(true);
|
||||
expect(name.hasClass('ng-valid')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
@ -41,14 +41,21 @@
|
||||
ctrl.protocolChange = protocolChange;
|
||||
|
||||
// Error text for invalid fields
|
||||
ctrl.portError = gettext('The port must be a number between 1 and 65535.');
|
||||
ctrl.portNumberError = gettext('The port must be a number between 1 and 65535.');
|
||||
ctrl.portUniqueError = gettext(
|
||||
'The port must be unique among all listeners attached to this load balancer.');
|
||||
ctrl.certificatesError = gettext('There was an error obtaining certificates from the ' +
|
||||
'key-manager service. The TERMINATED_HTTPS protocol is unavailable.');
|
||||
|
||||
////////////
|
||||
|
||||
function protocolChange(protocol) {
|
||||
$scope.model.spec.listener.port = { HTTP: 80, TERMINATED_HTTPS: 443 }[protocol];
|
||||
var defaultPort = { HTTP: 80, TERMINATED_HTTPS: 443 }[protocol];
|
||||
while (listenerPortExists(defaultPort)) {
|
||||
defaultPort += 1;
|
||||
}
|
||||
$scope.model.spec.listener.port = defaultPort;
|
||||
|
||||
var members = $scope.model.members.concat($scope.model.spec.members);
|
||||
members.forEach(function setMemberPort(member) {
|
||||
member.port = { HTTP: 80, TERMINATED_HTTPS: 80 }[protocol];
|
||||
@ -64,5 +71,11 @@
|
||||
workflow.remove('certificates');
|
||||
}
|
||||
}
|
||||
|
||||
function listenerPortExists(port) {
|
||||
return $scope.model.listenerPorts.some(function(element) {
|
||||
return element === port;
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -32,10 +32,12 @@
|
||||
remove: angular.noop
|
||||
};
|
||||
listener = {
|
||||
protocol: null
|
||||
protocol: null,
|
||||
port: 80
|
||||
};
|
||||
scope = {
|
||||
model: {
|
||||
listenerPorts: [80],
|
||||
members: [{port: ''}, {port: ''}],
|
||||
spec: {
|
||||
listener: listener,
|
||||
@ -48,7 +50,8 @@
|
||||
}));
|
||||
|
||||
it('should define error messages for invalid fields', function() {
|
||||
expect(ctrl.portError).toBeDefined();
|
||||
expect(ctrl.portNumberError).toBeDefined();
|
||||
expect(ctrl.portUniqueError).toBeDefined();
|
||||
expect(ctrl.certificatesError).toBeDefined();
|
||||
});
|
||||
|
||||
@ -77,7 +80,7 @@
|
||||
|
||||
it('should update port on protocol change to HTTP', function() {
|
||||
ctrl.protocolChange('HTTP');
|
||||
expect(listener.port).toBe(80);
|
||||
expect(listener.port).toBe(81);
|
||||
});
|
||||
|
||||
it('should update port on protocol change to TERMINATED_HTTPS', function() {
|
||||
|
@ -53,9 +53,13 @@
|
||||
</label>
|
||||
<input name="port" id="port" type="number" class="form-control"
|
||||
ng-model="model.spec.listener.port" ng-pattern="/^\d+$/" min="1" max="65535"
|
||||
ng-required="true" ng-disabled="model.context.id">
|
||||
<span class="help-block" ng-show="listenerDetailsForm.port.$invalid && listenerDetailsForm.port.$dirty">
|
||||
{$ ::ctrl.portError $}
|
||||
ng-required="true" ng-disabled="model.context.id"
|
||||
validate-unique="model.listenerPorts">
|
||||
<span class="help-block" ng-show="(listenerDetailsForm.port.$error.number || listenerDetailsForm.port.$error.required) && listenerDetailsForm.port.$dirty">
|
||||
{$ ::ctrl.portNumberError $}
|
||||
</span>
|
||||
<span class="help-block" ng-show="!(listenerDetailsForm.port.$error.number || listenerDetailsForm.port.$error.required) && listenerDetailsForm.port.$error.unique && listenerDetailsForm.port.$dirty">
|
||||
{$ ::ctrl.portUniqueError $}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -90,6 +90,7 @@
|
||||
monitorTypes: ['HTTP', 'PING', 'TCP'],
|
||||
monitorMethods: ['GET', 'HEAD'],
|
||||
certificates: [],
|
||||
listenerPorts: [],
|
||||
|
||||
/**
|
||||
* api methods for UI controllers
|
||||
@ -116,7 +117,7 @@
|
||||
* @param id ID of the resource being edited.
|
||||
*/
|
||||
|
||||
function initialize(resource, id) {
|
||||
function initialize(resource, id, loadBalancerId) {
|
||||
var promise;
|
||||
|
||||
model.certificatesError = false;
|
||||
@ -128,9 +129,10 @@
|
||||
|
||||
model.visibleResources = [];
|
||||
model.certificates = [];
|
||||
model.listenerPorts = [];
|
||||
|
||||
model.spec = {
|
||||
loadbalancer_id: null,
|
||||
loadbalancer_id: loadBalancerId,
|
||||
loadbalancer: {
|
||||
name: null,
|
||||
description: null,
|
||||
@ -165,19 +167,23 @@
|
||||
certificates: []
|
||||
};
|
||||
|
||||
if (model.initializing) {
|
||||
return promise;
|
||||
if (!model.initializing) {
|
||||
model.initializing = true;
|
||||
promise = initializeResources();
|
||||
}
|
||||
model.initializing = true;
|
||||
return promise;
|
||||
}
|
||||
|
||||
var type = (id ? 'edit' : 'create') + resource;
|
||||
function initializeResources() {
|
||||
var promise;
|
||||
var type = (model.context.id ? 'edit' : 'create') + model.context.resource;
|
||||
keymanagerPromise = serviceCatalog.ifTypeEnabled('key-manager');
|
||||
|
||||
if (type === 'createloadbalancer' || resource === 'listener') {
|
||||
if (type === 'createloadbalancer' || model.context.resource === 'listener') {
|
||||
keymanagerPromise.then(angular.noop, certificatesNotSupported);
|
||||
}
|
||||
|
||||
switch ((id ? 'edit' : 'create') + resource) {
|
||||
switch (type) {
|
||||
case 'createloadbalancer':
|
||||
promise = $q.all([
|
||||
lbaasv2API.getLoadBalancers().then(onGetLoadBalancers),
|
||||
@ -188,6 +194,16 @@
|
||||
]).then(initMemberAddresses);
|
||||
model.context.submit = createLoadBalancer;
|
||||
break;
|
||||
case 'createlistener':
|
||||
promise = $q.all([
|
||||
lbaasv2API.getListeners(model.spec.loadbalancer_id).then(onGetListeners),
|
||||
neutronAPI.getSubnets().then(onGetSubnets),
|
||||
neutronAPI.getPorts().then(onGetPorts),
|
||||
novaAPI.getServers().then(onGetServers),
|
||||
keymanagerPromise.then(prepareCertificates)
|
||||
]).then(initMemberAddresses);
|
||||
model.context.submit = createListener;
|
||||
break;
|
||||
case 'editloadbalancer':
|
||||
promise = $q.all([
|
||||
lbaasv2API.getLoadBalancer(model.context.id).then(onGetLoadBalancer),
|
||||
@ -204,7 +220,7 @@
|
||||
model.context.submit = editListener;
|
||||
break;
|
||||
default:
|
||||
throw Error('Invalid resource context: ' + (id ? 'edit' : 'create') + resource);
|
||||
throw Error('Invalid resource context: ' + type);
|
||||
}
|
||||
|
||||
return promise.then(onInitSuccess, onInitFail);
|
||||
@ -246,6 +262,10 @@
|
||||
return lbaasv2API.createLoadBalancer(spec);
|
||||
}
|
||||
|
||||
function createListener(spec) {
|
||||
return lbaasv2API.createListener(spec);
|
||||
}
|
||||
|
||||
function editLoadBalancer(spec) {
|
||||
return lbaasv2API.editLoadBalancer(model.context.id, spec);
|
||||
}
|
||||
@ -375,6 +395,21 @@
|
||||
model.spec.loadbalancer.name = name;
|
||||
}
|
||||
|
||||
function onGetListeners(response) {
|
||||
var existingNames = {};
|
||||
angular.forEach(response.data.items, function nameExists(listener) {
|
||||
existingNames[listener.name] = 1;
|
||||
model.listenerPorts.push(listener.protocol_port);
|
||||
});
|
||||
var name;
|
||||
var index = 0;
|
||||
do {
|
||||
index += 1;
|
||||
name = interpolate(gettext('Listener %(index)s'), { index: index }, true);
|
||||
} while (name in existingNames);
|
||||
model.spec.listener.name = name;
|
||||
}
|
||||
|
||||
function onGetSubnets(response) {
|
||||
model.subnets.length = 0;
|
||||
push.apply(model.subnets, response.data.items);
|
||||
@ -426,7 +461,6 @@
|
||||
function onGetLoadBalancer(response) {
|
||||
var loadbalancer = response.data;
|
||||
setLoadBalancerSpec(loadbalancer);
|
||||
model.visibleResources.push('loadbalancer');
|
||||
}
|
||||
|
||||
function onGetListener(response) {
|
||||
|
@ -98,6 +98,17 @@
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
getListeners: function() {
|
||||
var listeners = [
|
||||
{ id: '1234', name: 'Listener 1', protocol_port: 80 },
|
||||
{ id: '5678', name: 'Listener 2', protocol_port: 81 }
|
||||
];
|
||||
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve({ data: { items: listeners } });
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
getListener: function() {
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve({ data: listenerResources });
|
||||
@ -162,6 +173,9 @@
|
||||
editLoadBalancer: function(id, spec) {
|
||||
return spec;
|
||||
},
|
||||
createListener: function(spec) {
|
||||
return spec;
|
||||
},
|
||||
editListener: function(id, spec) {
|
||||
return spec;
|
||||
}
|
||||
@ -298,6 +312,10 @@
|
||||
expect(model.certificates).toEqual([]);
|
||||
});
|
||||
|
||||
it('has empty listener ports array', function() {
|
||||
expect(model.listenerPorts).toEqual([]);
|
||||
});
|
||||
|
||||
it('has array of listener protocols', function() {
|
||||
expect(model.listenerProtocols).toEqual(['HTTP', 'TCP', 'TERMINATED_HTTPS']);
|
||||
});
|
||||
@ -340,8 +358,9 @@
|
||||
expect(model.subnets.length).toBe(2);
|
||||
expect(model.members.length).toBe(2);
|
||||
expect(model.certificates.length).toBe(2);
|
||||
expect(model.listenerPorts.length).toBe(0);
|
||||
expect(model.spec).toBeDefined();
|
||||
expect(model.spec.loadbalancer_id).toBeNull();
|
||||
expect(model.spec.loadbalancer_id).toBeUndefined();
|
||||
expect(model.spec.loadbalancer).toBeDefined();
|
||||
expect(model.spec.listener).toBeDefined();
|
||||
expect(model.spec.pool).toBeDefined();
|
||||
@ -364,6 +383,43 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('Post initialize model (create listener)', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
model.initialize('listener', false, '1234');
|
||||
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).toBe(2);
|
||||
expect(model.certificates.length).toBe(2);
|
||||
expect(model.listenerPorts.length).toBe(2);
|
||||
expect(model.spec).toBeDefined();
|
||||
expect(model.spec.loadbalancer_id).toBe('1234');
|
||||
expect(model.spec.loadbalancer).toBeDefined();
|
||||
expect(model.spec.listener).toBeDefined();
|
||||
expect(model.spec.pool).toBeDefined();
|
||||
expect(model.spec.members).toEqual([]);
|
||||
expect(model.spec.certificates).toEqual([]);
|
||||
expect(model.spec.monitor).toBeDefined();
|
||||
expect(model.certificatesError).toBe(false);
|
||||
});
|
||||
|
||||
it('should initialize names', function() {
|
||||
expect(model.spec.listener.name).toBe('Listener 3');
|
||||
expect(model.spec.pool.name).toBe('Pool 1');
|
||||
});
|
||||
|
||||
it('should initialize context properties', function() {
|
||||
expect(model.context.resource).toBe('listener');
|
||||
expect(model.context.id).toBeFalsy();
|
||||
expect(model.context.submit).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Post initialize model (edit loadbalancer)', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
@ -375,14 +431,18 @@
|
||||
expect(model.initializing).toBe(false);
|
||||
expect(model.initialized).toBe(true);
|
||||
expect(model.subnets.length).toBe(2);
|
||||
expect(model.members).toEqual([]);
|
||||
expect(model.members.length).toBe(0);
|
||||
expect(model.certificates.length).toBe(0);
|
||||
expect(model.listenerPorts.length).toBe(0);
|
||||
expect(model.spec).toBeDefined();
|
||||
expect(model.spec.loadbalancer_id).toBeNull();
|
||||
expect(model.spec.loadbalancer_id).toBeUndefined();
|
||||
expect(model.spec.loadbalancer).toBeDefined();
|
||||
expect(model.spec.listener).toBeDefined();
|
||||
expect(model.spec.pool).toBeDefined();
|
||||
expect(model.spec.members).toEqual([]);
|
||||
expect(model.spec.certificates).toEqual([]);
|
||||
expect(model.spec.monitor).toBeDefined();
|
||||
expect(model.certificatesError).toBe(false);
|
||||
});
|
||||
|
||||
it('should initialize loadbalancer model spec properties', function() {
|
||||
@ -592,7 +652,7 @@
|
||||
});
|
||||
|
||||
it('sets load balancer ID to null', function() {
|
||||
expect(model.spec.loadbalancer_id).toBeNull();
|
||||
expect(model.spec.loadbalancer_id).toBeUndefined();
|
||||
});
|
||||
|
||||
it('sets load balancer name to null', function() {
|
||||
@ -754,6 +814,20 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('context (create listener)', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
model.initialize('listener', false, '1234');
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('should initialize context', function() {
|
||||
expect(model.context.resource).toBe('listener');
|
||||
expect(model.context.id).toBeFalsy();
|
||||
expect(model.context.submit.name).toBe('createListener');
|
||||
});
|
||||
});
|
||||
|
||||
describe('context (edit listener)', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
@ -1014,6 +1088,214 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model submit function (create listener)', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
model.initialize('listener', false, '1234');
|
||||
scope.$apply();
|
||||
});
|
||||
|
||||
it('should set final spec properties', function() {
|
||||
model.spec.listener.protocol = 'TCP';
|
||||
model.spec.listener.port = 80;
|
||||
model.spec.pool.name = 'pool name';
|
||||
model.spec.pool.description = 'pool description';
|
||||
model.spec.pool.method = 'LEAST_CONNECTIONS';
|
||||
model.spec.members = [{
|
||||
address: { ip: '1.2.3.4', subnet: '1' },
|
||||
addresses: [{ ip: '1.2.3.4', subnet: '1' },
|
||||
{ ip: '2.3.4.5', subnet: '2' }],
|
||||
id: '1',
|
||||
name: 'foo',
|
||||
port: 80,
|
||||
weight: 1
|
||||
}, {
|
||||
id: 'external-member-0',
|
||||
address: '2.3.4.5',
|
||||
subnet: null,
|
||||
port: 80,
|
||||
weight: 1
|
||||
}, {
|
||||
id: 'external-member-1',
|
||||
address: null,
|
||||
subnet: null,
|
||||
port: 80,
|
||||
weight: 1
|
||||
}, {
|
||||
id: 'external-member-2',
|
||||
address: '3.4.5.6',
|
||||
subnet: { id: '1' },
|
||||
port: 80,
|
||||
weight: 1
|
||||
}];
|
||||
model.spec.monitor.type = 'PING';
|
||||
model.spec.monitor.interval = 1;
|
||||
model.spec.monitor.retry = 1;
|
||||
model.spec.monitor.timeout = 1;
|
||||
model.spec.certificates = [{
|
||||
id: 'container1',
|
||||
name: 'foo',
|
||||
expiration: '2015-03-26T21:10:45.417835'
|
||||
}];
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.listener.name).toBe('Listener 3');
|
||||
expect(finalSpec.listener.description).toBeUndefined();
|
||||
expect(finalSpec.listener.protocol).toBe('TCP');
|
||||
expect(finalSpec.listener.port).toBe(80);
|
||||
|
||||
expect(finalSpec.pool.name).toBe('pool name');
|
||||
expect(finalSpec.pool.description).toBe('pool description');
|
||||
expect(finalSpec.pool.protocol).toBe('TCP');
|
||||
expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS');
|
||||
|
||||
expect(finalSpec.members.length).toBe(3);
|
||||
expect(finalSpec.members[0].address).toBe('1.2.3.4');
|
||||
expect(finalSpec.members[0].subnet).toBe('1');
|
||||
expect(finalSpec.members[0].port).toBe(80);
|
||||
expect(finalSpec.members[0].weight).toBe(1);
|
||||
expect(finalSpec.members[0].id).toBe('1');
|
||||
expect(finalSpec.members[0].addresses).toBeUndefined();
|
||||
expect(finalSpec.members[0].name).toBeUndefined();
|
||||
expect(finalSpec.members[0].allocatedMember).toBeUndefined();
|
||||
expect(finalSpec.members[1].id).toBe('external-member-0');
|
||||
expect(finalSpec.members[1].address).toBe('2.3.4.5');
|
||||
expect(finalSpec.members[1].subnet).toBeUndefined();
|
||||
expect(finalSpec.members[1].port).toBe(80);
|
||||
expect(finalSpec.members[1].weight).toBe(1);
|
||||
expect(finalSpec.members[1].allocatedMember).toBeUndefined();
|
||||
expect(finalSpec.members[2].id).toBe('external-member-2');
|
||||
expect(finalSpec.members[2].address).toBe('3.4.5.6');
|
||||
expect(finalSpec.members[2].subnet).toBe('1');
|
||||
expect(finalSpec.members[2].port).toBe(80);
|
||||
expect(finalSpec.members[2].weight).toBe(1);
|
||||
expect(finalSpec.members[2].allocatedMember).toBeUndefined();
|
||||
|
||||
expect(finalSpec.monitor.type).toBe('PING');
|
||||
expect(finalSpec.monitor.interval).toBe(1);
|
||||
expect(finalSpec.monitor.retry).toBe(1);
|
||||
expect(finalSpec.monitor.timeout).toBe(1);
|
||||
expect(finalSpec.certificates).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should set final spec certificates', function() {
|
||||
model.spec.loadbalancer.ip = '1.2.3.4';
|
||||
model.spec.loadbalancer.subnet = model.subnets[0];
|
||||
model.spec.listener.protocol = 'TERMINATED_HTTPS';
|
||||
model.spec.listener.port = 443;
|
||||
model.spec.pool.method = 'LEAST_CONNECTIONS';
|
||||
model.spec.certificates = [{
|
||||
id: 'container1',
|
||||
name: 'foo',
|
||||
expiration: '2015-03-26T21:10:45.417835'
|
||||
}];
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.listener.name).toBe('Listener 3');
|
||||
expect(finalSpec.listener.description).toBeUndefined();
|
||||
expect(finalSpec.listener.protocol).toBe('TERMINATED_HTTPS');
|
||||
expect(finalSpec.listener.port).toBe(443);
|
||||
expect(finalSpec.pool.protocol).toBe('HTTP');
|
||||
expect(finalSpec.certificates).toEqual(['container1']);
|
||||
});
|
||||
|
||||
it('should delete listener if any required property is not set', function() {
|
||||
model.spec.loadbalancer.ip = '1.2.3.4';
|
||||
model.spec.loadbalancer.subnet = model.subnets[0];
|
||||
model.spec.listener.protocol = 'HTTP';
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.loadbalancer).toBeDefined();
|
||||
expect(finalSpec.listener).toBeUndefined();
|
||||
expect(finalSpec.pool).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete certificates if not using TERMINATED_HTTPS', function() {
|
||||
model.spec.loadbalancer.ip = '1.2.3.4';
|
||||
model.spec.loadbalancer.subnet = model.subnets[0];
|
||||
model.spec.listener.protocol = 'HTTP';
|
||||
model.spec.listener.port = 80;
|
||||
model.spec.certificates = [{id: '1'}];
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.loadbalancer).toBeDefined();
|
||||
expect(finalSpec.listener).toBeDefined();
|
||||
expect(finalSpec.certificates).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete pool if any required property is not set', function() {
|
||||
model.spec.loadbalancer.ip = '1.2.3.4';
|
||||
model.spec.loadbalancer.subnet = model.subnets[0];
|
||||
model.spec.listener.protocol = 'HTTP';
|
||||
model.spec.listener.port = 80;
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.loadbalancer).toBeDefined();
|
||||
expect(finalSpec.listener).toBeDefined();
|
||||
expect(finalSpec.pool).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete members if none selected', function() {
|
||||
model.spec.loadbalancer.ip = '1.2.3.4';
|
||||
model.spec.loadbalancer.subnet = model.subnets[0];
|
||||
model.spec.listener.protocol = 'HTTP';
|
||||
model.spec.listener.port = 80;
|
||||
model.spec.pool.method = 'LEAST_CONNECTIONS';
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.loadbalancer).toBeDefined();
|
||||
expect(finalSpec.listener).toBeDefined();
|
||||
expect(finalSpec.pool).toBeDefined();
|
||||
expect(finalSpec.members).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete members if no members are valid', function() {
|
||||
model.spec.loadbalancer.ip = '1.2.3.4';
|
||||
model.spec.loadbalancer.subnet = model.subnets[0];
|
||||
model.spec.listener.protocol = 'HTTP';
|
||||
model.spec.listener.port = 80;
|
||||
model.spec.pool.method = 'LEAST_CONNECTIONS';
|
||||
model.spec.members = [{
|
||||
id: 'foo',
|
||||
address: '2.3.4.5',
|
||||
weight: 1
|
||||
}];
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.loadbalancer).toBeDefined();
|
||||
expect(finalSpec.listener).toBeDefined();
|
||||
expect(finalSpec.pool).toBeDefined();
|
||||
expect(finalSpec.members).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should delete monitor if any required property not set', function() {
|
||||
model.spec.loadbalancer.ip = '1.2.3.4';
|
||||
model.spec.loadbalancer.subnet = model.subnets[0];
|
||||
model.spec.listener.protocol = 'HTTP';
|
||||
model.spec.listener.port = 80;
|
||||
model.spec.pool.method = 'LEAST_CONNECTIONS';
|
||||
model.spec.monitor.type = 'PING';
|
||||
model.spec.monitor.interval = 1;
|
||||
model.spec.monitor.retry = 1;
|
||||
model.spec.monitor.timeout = null;
|
||||
|
||||
var finalSpec = model.submit();
|
||||
|
||||
expect(finalSpec.loadbalancer).toBeDefined();
|
||||
expect(finalSpec.listener).toBeDefined();
|
||||
expect(finalSpec.pool).toBeDefined();
|
||||
expect(finalSpec.members).toBeUndefined();
|
||||
expect(finalSpec.monitor).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Model submit function (edit listener)', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user