Clean up create load balancer workflow

There were a few problems identified with the create load balancer
workflow and this patch corrects them. It sets a default port when
selecting a listener protocol, updates the allowed health monitor
status codes, removes the pool member description since an
instance does not have a description, removes the HTTPS options for
listener and health monitor protocols, and removes the pool protocol
selection since this can be determined by the listener protocol.

Partially-Implements: blueprint horizon-lbaas-v2-ui
Change-Id: Ica296495b02689bc8616a52dfd709dc323e9bf45
This commit is contained in:
Justin Pomeroy 2016-02-15 09:30:32 -06:00
parent c3ec347a54
commit 1b7b60ddb5
13 changed files with 119 additions and 230 deletions

View File

@ -38,8 +38,8 @@
ipv4: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$',
ipv6: '^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$',
/* eslint-enable max-len */
// HTTP status codes - comma separated numbers or ranges
httpStatusCodes: /^\d+(\s*-\s*\d+)?(,\s*\d+(\s*-\s*\d+)?)*$/,
// HTTP status codes - a single number, comma separated numbers, or a range of numbers.
httpStatusCodes: /^\d+((\s*-\s*\d+)|(\s*,\s*\d+)+)?$/,
// URL path - must start with "/" and can include anything after that
urlPath: /^((\/)|(\/[^/]+)+)$/
})

View File

@ -63,6 +63,16 @@
});
});
it('should define correct pattern for health monitor status codes', function () {
expect(Object.keys(patterns).length).toBe(4);
var regex = patterns.httpStatusCodes;
expect(regex.test('200')).toBe(true);
expect(regex.test('200-204')).toBe(true);
expect(regex.test('200,203,204')).toBe(true);
expect(regex.test('foo')).toBe(false);
expect(regex.test('200,202-204')).toBe(false);
});
it('should define popovers', function () {
expect(popovers).toBeDefined();
});

View File

@ -31,27 +31,29 @@
* @description
* The `ListenerDetailsController` controller provides functions for
* configuring the listener details step of the LBaaS wizard.
* @param $scope The angular scope object.
* @param gettext The horizon gettext function for translation.
* @returns undefined
*/
function ListenerDetailsController($scope, gettext) {
var ctrl = this;
ctrl.protocolChange = protocolChange;
// Error text for invalid fields
ctrl.portError = gettext('The port must be a number between 1 and 65535.');
ctrl.certificatesError = gettext('There was an error obtaining certificates from the ' +
'key-manager service. The TERMINATED_HTTPS protocol is unavailable.');
ctrl.protocolChange = protocolChange;
////////////
//////////
function protocolChange(protocol) {
$scope.model.spec.listener.port = { HTTP: 80, TERMINATED_HTTPS: 443 }[protocol];
var members = $scope.model.members.concat($scope.model.spec.members);
members.forEach(function setMemberPort(member) {
member.port = { HTTP: 80, TERMINATED_HTTPS: 80 }[protocol];
});
// Called when the listener protocol is changed. Shows the SSL Certificates step if
// TERMINATED_HTTPS is selected.
function protocolChange() {
var protocol = $scope.model.spec.listener.protocol;
var workflow = $scope.workflow;
var certificates = workflow.steps.some(function checkCertificatesStep(step) {
return step.id === 'certificates';

View File

@ -22,7 +22,7 @@
beforeEach(module('horizon.dashboard.project.lbaasv2'));
describe('ListenerDetailsController', function() {
var ctrl, workflow, listener;
var ctrl, workflow, listener, scope;
beforeEach(inject(function($controller) {
workflow = {
@ -34,10 +34,12 @@
listener = {
protocol: null
};
var scope = {
scope = {
model: {
members: [{port: ''}, {port: ''}],
spec: {
listener: listener
listener: listener,
members: [{port: ''}, {port: ''}]
}
},
workflow: workflow
@ -51,30 +53,67 @@
});
it('should show certificates step if selecting TERMINATED_HTTPS', function() {
listener.protocol = 'TERMINATED_HTTPS';
workflow.steps.push(workflow.certificatesStep);
spyOn(workflow, 'after');
ctrl.protocolChange();
ctrl.protocolChange('TERMINATED_HTTPS');
expect(workflow.after).not.toHaveBeenCalled();
workflow.steps.splice(1, 1);
ctrl.protocolChange();
ctrl.protocolChange('TERMINATED_HTTPS');
expect(workflow.after).toHaveBeenCalledWith('listener', workflow.certificatesStep);
});
it('should hide certificates step if not selecting TERMINATED_HTTPS', function() {
listener.protocol = 'HTTP';
spyOn(workflow, 'remove');
ctrl.protocolChange();
ctrl.protocolChange('HTTP');
expect(workflow.remove).not.toHaveBeenCalled();
workflow.steps.push(workflow.certificatesStep);
ctrl.protocolChange();
ctrl.protocolChange('HTTP');
expect(workflow.remove).toHaveBeenCalledWith('certificates');
});
it('should update port on protocol change to HTTP', function() {
ctrl.protocolChange('HTTP');
expect(listener.port).toBe(80);
});
it('should update port on protocol change to TERMINATED_HTTPS', function() {
ctrl.protocolChange('TERMINATED_HTTPS');
expect(listener.port).toBe(443);
});
it('should update port on protocol change to TCP', function() {
ctrl.protocolChange('TCP');
expect(listener.port).toBeUndefined();
});
it('should update member ports on protocol change to TERMINATED_HTTPS', function() {
ctrl.protocolChange('TERMINATED_HTTPS');
scope.model.members.concat(scope.model.spec.members).forEach(function(member) {
expect(member.port).toBe(80);
});
});
it('should update member ports on protocol change to HTTP', function() {
ctrl.protocolChange('HTTP');
scope.model.members.concat(scope.model.spec.members).forEach(function(member) {
expect(member.port).toBe(80);
});
});
it('should update member ports on protocol change to TCP', function() {
ctrl.protocolChange('TCP');
scope.model.members.concat(scope.model.spec.members).forEach(function(member) {
expect(member.port).toBeUndefined();
});
});
});
});
})();

View File

@ -39,7 +39,7 @@
popover-trigger="hover"></span>
<select class="form-control input-sm" name="listener-protocol" id="listener-protocol"
ng-model="model.spec.listener.protocol" ng-required="model.context.resource === 'listener'"
ng-change="ctrl.protocolChange()" ng-disabled="model.context.id">
ng-change="ctrl.protocolChange(model.spec.listener.protocol)" ng-disabled="model.context.id">
<option ng-repeat="protocol in model.listenerProtocols" value="{$ protocol $}"
ng-disabled="protocol==='TERMINATED_HTTPS' && model.certificatesError">{$ protocol $}</option>
</select>

View File

@ -114,7 +114,7 @@
id: memberCounter++,
address: null,
subnet: null,
port: { HTTP: 80, HTTPS: 443 }[protocol],
port: { HTTP: 80 }[protocol],
weight: 1
});
}

View File

@ -139,9 +139,7 @@
</th>
</tr>
<tr>
<th class="expander"></th>
<th st-sort="name" st-sort-default class="rsp-p2" translate>Name</th>
<th class="rsp-p3" translate>Description</th>
<th st-sort="name" st-sort-default class="rsp-p1" translate>Name</th>
<th class="rsp-p1" translate>IP Address</th>
<th></th>
</tr>
@ -154,16 +152,9 @@
</div>
</td>
</tr>
<tr ng-repeat-start="row in ctrl.tableData.displayedAvailable track by row.id"
<tr ng-repeat="row in ctrl.tableData.displayedAvailable track by row.id"
ng-if="!trCtrl.allocatedIds[row.id]">
<td class="expander">
<i class="fa fa-chevron-right"
hz-expand-detail
duration="200">
</i>
</td>
<td class="rsp-p2">{$ ::row.name $}</td>
<td class="rsp-p3">{$ ::row.description | noValue $}</td>
<td class="rsp-p1">{$ ::row.name $}</td>
<td class="rsp-p1">
<span ng-if="row.addresses.length === 1">{$ row.address.ip $}</span>
<!-- The current version of the popover directive doesn't seem to allow HTML content (0.11.0) -->
@ -183,20 +174,6 @@
</action-list>
</td>
</tr>
<tr ng-repeat-end class="detail-row">
<td class="detail" colspan="100">
<div class="row">
<dl class="rsp-alt-p2 col-sm-2">
<dt translate>Name</dt>
<dd>{$ ::row.name $}</dd>
</dl>
<dl class="rsp-alt-p3 col-sm-2">
<dt translate>Description</dt>
<dd>{$ ::row.description | noValue $}</dd>
</dl>
</div>
</td>
</tr>
</tbody>
</table>
</available>

View File

@ -85,10 +85,9 @@
visibleResources: [],
subnets: [],
members: [],
listenerProtocols: ['TCP', 'HTTP', 'HTTPS', 'TERMINATED_HTTPS'],
poolProtocols: ['TCP', 'HTTP', 'HTTPS'],
methods: ['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP'],
monitorTypes: ['HTTP', 'HTTPS', 'PING', 'TCP'],
listenerProtocols: ['HTTP', 'TCP', 'TERMINATED_HTTPS'],
methods: ['LEAST_CONNECTIONS', 'ROUND_ROBIN', 'SOURCE_IP'],
monitorTypes: ['HTTP', 'PING', 'TCP'],
monitorMethods: ['GET', 'HEAD'],
certificates: [],
@ -155,9 +154,9 @@
monitor: {
id: null,
type: null,
interval: null,
retry: null,
timeout: null,
interval: 5,
retry: 3,
timeout: 5,
method: 'GET',
status: '200',
path: '/'
@ -295,11 +294,14 @@
function cleanFinalSpecPool(finalSpec) {
var resource = model.context.resource;
// Pool requires protocol and method, and also the listener
if (resource !== 'pool' && !finalSpec.listener ||
!finalSpec.pool.protocol ||
!finalSpec.pool.method) {
// Pool requires method and also the listener
if (resource !== 'pool' && !finalSpec.listener || !finalSpec.pool.method) {
delete finalSpec.pool;
} else {
// The pool protocol must be HTTP if the listener protocol is TERMINATED_HTTPS and
// otherwise has to match it.
var protocol = finalSpec.listener.protocol;
finalSpec.pool.protocol = protocol === 'TERMINATED_HTTPS' ? 'HTTP' : protocol;
}
}
@ -315,8 +317,8 @@
var members = [];
angular.forEach(finalSpec.members, function cleanMember(member) {
if (member.address && member.port) {
['name', 'description', 'addresses', 'allocatedMember'].forEach(
function deleteProperty(prop) {
var propsToRemove = ['name', 'description', 'addresses', 'allocatedMember'];
propsToRemove.forEach(function deleteProperty(prop) {
if (angular.isDefined(member[prop])) {
delete member[prop];
}
@ -393,7 +395,6 @@
members.push({
id: server.id,
name: server.name,
description: server.description,
weight: 1
});
});
@ -586,7 +587,7 @@
// cannot support the TERMINATED_HTTPS listener protocol so we hide the option if creating
// a new load balancer or listener. However for editing we still need it.
if (!model.context.id) {
model.listenerProtocols.splice(3, 1);
model.listenerProtocols.splice(2, 1);
}
}

View File

@ -298,20 +298,16 @@
expect(model.certificates).toEqual([]);
});
it('has array of pool protocols', function() {
expect(model.poolProtocols).toEqual(['TCP', 'HTTP', 'HTTPS']);
});
it('has array of listener protocols', function() {
expect(model.listenerProtocols).toEqual(['TCP', 'HTTP', 'HTTPS', 'TERMINATED_HTTPS']);
expect(model.listenerProtocols).toEqual(['HTTP', 'TCP', 'TERMINATED_HTTPS']);
});
it('has array of pool methods', function() {
expect(model.methods).toEqual(['ROUND_ROBIN', 'LEAST_CONNECTIONS', 'SOURCE_IP']);
expect(model.methods).toEqual(['LEAST_CONNECTIONS', 'ROUND_ROBIN', 'SOURCE_IP']);
});
it('has array of monitor types', function() {
expect(model.monitorTypes).toEqual(['HTTP', 'HTTPS', 'PING', 'TCP']);
expect(model.monitorTypes).toEqual(['HTTP', 'PING', 'TCP']);
});
it('has array of monitor methods', function() {
@ -412,11 +408,11 @@
expect(model.spec.pool.method).toBeNull();
});
it('should initialize monitor model spec properties to null', function() {
it('should initialize monitor model spec properties', function() {
expect(model.spec.monitor.type).toBeNull();
expect(model.spec.monitor.interval).toBeNull();
expect(model.spec.monitor.retry).toBeNull();
expect(model.spec.monitor.timeout).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('/');
@ -433,8 +429,8 @@
});
it('should initialize listener protocols', function() {
expect(model.listenerProtocols.length).toBe(4);
expect(model.listenerProtocols.indexOf('TERMINATED_HTTPS')).toBe(3);
expect(model.listenerProtocols.length).toBe(3);
expect(model.listenerProtocols.indexOf('TERMINATED_HTTPS')).toBe(2);
});
});
@ -447,7 +443,7 @@
});
it('should initialize listener protocols', function() {
expect(model.listenerProtocols.length).toBe(3);
expect(model.listenerProtocols.length).toBe(2);
expect(model.listenerProtocols.indexOf('TERMINATED_HTTPS')).toBe(-1);
});
});
@ -663,16 +659,16 @@
expect(model.spec.monitor.type).toBeNull();
});
it('sets monitor interval to null', function() {
expect(model.spec.monitor.interval).toBeNull();
it('sets monitor interval to 5', function() {
expect(model.spec.monitor.interval).toBe(5);
});
it('sets monitor retry count to null', function() {
expect(model.spec.monitor.retry).toBeNull();
it('sets monitor retry count to 3', function() {
expect(model.spec.monitor.retry).toBe(3);
});
it('sets monitor timeout to null', function() {
expect(model.spec.monitor.timeout).toBeNull();
it('sets monitor timeout to 5', function() {
expect(model.spec.monitor.timeout).toBe(5);
});
it('sets monitor method to default', function() {
@ -782,11 +778,10 @@
it('should set final spec properties', function() {
model.spec.loadbalancer.ip = '1.2.3.4';
model.spec.loadbalancer.subnet = model.subnets[0];
model.spec.listener.protocol = 'HTTPS';
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.protocol = 'HTTP';
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
address: { ip: '1.2.3.4', subnet: '1' },
@ -794,7 +789,6 @@
{ ip: '2.3.4.5', subnet: '2' }],
id: '1',
name: 'foo',
description: 'bar',
port: 80,
weight: 1
}, {
@ -835,12 +829,12 @@
expect(finalSpec.listener.name).toBe('Listener 1');
expect(finalSpec.listener.description).toBeUndefined();
expect(finalSpec.listener.protocol).toBe('HTTPS');
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('HTTP');
expect(finalSpec.pool.protocol).toBe('TCP');
expect(finalSpec.pool.method).toBe('LEAST_CONNECTIONS');
expect(finalSpec.members.length).toBe(3);
@ -877,6 +871,7 @@
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',
@ -893,6 +888,7 @@
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']);
});
@ -907,7 +903,7 @@
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 = 'HTTPS';
model.spec.listener.protocol = 'HTTP';
var finalSpec = model.submit();
@ -946,7 +942,7 @@
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 = 'HTTPS';
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
var finalSpec = model.submit();
@ -959,9 +955,8 @@
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 = 'HTTPS';
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.protocol = 'HTTP';
model.spec.pool.method = 'LEAST_CONNECTIONS';
var finalSpec = model.submit();
@ -975,9 +970,8 @@
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 = 'HTTPS';
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.protocol = 'HTTP';
model.spec.pool.method = 'LEAST_CONNECTIONS';
model.spec.members = [{
id: 'foo',
@ -996,13 +990,13 @@
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 = 'HTTPS';
model.spec.listener.protocol = 'HTTP';
model.spec.listener.port = 80;
model.spec.pool.protocol = 'HTTP';
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();

View File

@ -50,7 +50,7 @@
ctrl.pathError = gettext('The URL path is not valid.');
// Field level help text
ctrl.statusHelp = gettext('Enter comma separated values or ranges.');
ctrl.statusHelp = gettext('Must be one of a single value, a comma separated list, or a range.');
ctrl.intervalHelp = gettext('The delay between health check calls.');
ctrl.retryHelp = interpolate(
/* eslint-disable max-len */

View File

@ -1,55 +0,0 @@
/*
* 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')
.controller('CreatePoolDetailsController', CreatePoolDetailsController);
CreatePoolDetailsController.$inject = [
'$scope'
];
/**
* @ngdoc controller
* @name CreatePoolDetailsController
* @description
* The `CreatePoolDetailsController` controller provides functions for configuring
* pool details.
* @param $scope The angular scope object.
* @returns undefined
*/
function CreatePoolDetailsController($scope) {
var ctrl = this;
ctrl.protocolChange = protocolChange;
//////////
function protocolChange(protocol) {
var port = { HTTP: 80, HTTPS: 443 }[protocol];
$scope.model.members.forEach(function setAvailableInstancePort(member) {
member.port = port;
});
$scope.model.spec.members.forEach(function setAllocatedMemberPort(member) {
member.port = port;
});
}
}
})();

View File

@ -1,66 +0,0 @@
/*
* 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('Create Pool Details Step', function() {
var ctrl;
var availableMembers = [{port: ''}, {port: ''}];
var allocatedMembers = [{port: ''}, {port: ''}];
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(inject(function($controller) {
var scope = {
model: {
members: availableMembers,
spec: {
members: allocatedMembers
}
}
};
ctrl = $controller('CreatePoolDetailsController', { $scope: scope });
}));
it('should define protocolChange function', function() {
expect(ctrl.protocolChange).toBeDefined();
});
it('should update member ports on protocol change to HTTP', function() {
ctrl.protocolChange('HTTP');
availableMembers.concat(allocatedMembers).forEach(function(member) {
expect(member.port).toBe(80);
});
});
it('should update member ports on protocol change to HTTPS', function() {
ctrl.protocolChange('HTTPS');
availableMembers.concat(allocatedMembers).forEach(function(member) {
expect(member.port).toBe(443);
});
});
it('should update member ports on protocol change to TCP', function() {
ctrl.protocolChange('TCP');
availableMembers.concat(allocatedMembers).forEach(function(member) {
expect(member.port).toBeUndefined();
});
});
});
})();

View File

@ -1,4 +1,4 @@
<div ng-controller="CreatePoolDetailsController as ctrl">
<div>
<h1 translate>Pool Details</h1>
<!--content-->
@ -29,19 +29,6 @@
<div class="row form-group">
<div class="col-sm-6 col-md-3">
<div class="form-field required pool-protocol">
<label translate class="on-top" for="pool-protocol">Protocol</label>
<select class="form-control input-sm" name="pool-protocol"
id="pool-protocol"
ng-options="protocol for protocol in model.poolProtocols"
ng-model="model.spec.pool.protocol"
ng-change="ctrl.protocolChange(model.spec.pool.protocol)"
ng-disabled="model.context.id">
</select>
</div>
</div>
<div class="col-sm-6 col-md-3">
<div class="form-field required pool-method">
<label translate class="on-top" for="pool-method">Method</label>