Able to change admin state for all resources
Also make the workflow more independent and predictable. Previously it is using the extensible workflow methods and does not make a copy of a step for each workflow, which would mess up with each other. Change-Id: I2e808282ed3c180105978f359fff7558d9e78ca7 Story: 1713844 Task: 5361
This commit is contained in:
parent
b307277abe
commit
8a8cd2b85c
@ -129,7 +129,9 @@ def create_loadbalancer(request):
|
||||
vip_subnet_id=data['loadbalancer']['subnet'],
|
||||
name=data['loadbalancer'].get('name'),
|
||||
description=data['loadbalancer'].get('description'),
|
||||
vip_address=data['loadbalancer'].get('ip'))
|
||||
vip_address=data['loadbalancer'].get('ip'),
|
||||
admin_state_up=data['loadbalancer'].get('admin_state_up')
|
||||
)
|
||||
|
||||
if data.get('listener'):
|
||||
# There is work underway to add a new API to LBaaS v2 that will
|
||||
@ -166,7 +168,9 @@ def create_listener(request, **kwargs):
|
||||
description=data['listener'].get('description'),
|
||||
connection_limit=data['listener'].get('connection_limit'),
|
||||
default_tls_container_ref=default_tls_ref,
|
||||
sni_container_refs=None)
|
||||
sni_container_refs=None,
|
||||
admin_state_up=data['listener'].get('admin_state_up')
|
||||
)
|
||||
|
||||
if data.get('pool'):
|
||||
args = (request, kwargs['loadbalancer_id'], create_pool)
|
||||
@ -201,7 +205,9 @@ def create_pool(request, **kwargs):
|
||||
session_persistence=session_persistence,
|
||||
listener_id=kwargs['listener_id'],
|
||||
name=data['pool'].get('name'),
|
||||
description=data['pool'].get('description'))
|
||||
description=data['pool'].get('description'),
|
||||
admin_state_up=data['pool'].get('admin_state_up')
|
||||
)
|
||||
|
||||
if data.get('members'):
|
||||
args = (request, kwargs['loadbalancer_id'], add_member)
|
||||
@ -232,7 +238,9 @@ def create_health_monitor(request, **kwargs):
|
||||
pool_id=kwargs['pool_id'],
|
||||
http_method=data['monitor'].get('method'),
|
||||
url_path=data['monitor'].get('path'),
|
||||
expected_codes=data['monitor'].get('status'))
|
||||
expected_codes=data['monitor'].get('status'),
|
||||
admin_state_up=data['monitor'].get('admin_state_up')
|
||||
)
|
||||
|
||||
return _get_sdk_object_dict(health_mon)
|
||||
|
||||
@ -265,7 +273,9 @@ def add_member(request, **kwargs):
|
||||
subnet_id=member['subnet'],
|
||||
weight=member.get('weight'),
|
||||
monitor_address=monitor_address if monitor_address else None,
|
||||
monitor_port=member.get('monitor_port'))
|
||||
monitor_port=member.get('monitor_port'),
|
||||
admin_state_up=member.get('admin_state_up')
|
||||
)
|
||||
|
||||
index += 1
|
||||
if kwargs.get('members_to_add'):
|
||||
@ -326,7 +336,8 @@ def update_loadbalancer(request, **kwargs):
|
||||
loadbalancer = conn.load_balancer.update_load_balancer(
|
||||
loadbalancer_id,
|
||||
name=data['loadbalancer'].get('name'),
|
||||
description=data['loadbalancer'].get('description'))
|
||||
description=data['loadbalancer'].get('description'),
|
||||
admin_state_up=data['loadbalancer'].get('admin_state_up'))
|
||||
|
||||
return _get_sdk_object_dict(loadbalancer)
|
||||
|
||||
@ -344,7 +355,9 @@ def update_listener(request, **kwargs):
|
||||
listener=listener_id,
|
||||
name=data['listener'].get('name'),
|
||||
description=data['listener'].get('description'),
|
||||
connection_limit=data['listener'].get('connection_limit'))
|
||||
connection_limit=data['listener'].get('connection_limit'),
|
||||
admin_state_up=data['listener'].get('admin_state_up')
|
||||
)
|
||||
|
||||
if data.get('pool'):
|
||||
args = (request, loadbalancer_id, update_pool)
|
||||
@ -379,7 +392,9 @@ def update_pool(request, **kwargs):
|
||||
lb_algorithm=data['pool']['method'],
|
||||
session_persistence=session_persistence,
|
||||
name=data['pool'].get('name'),
|
||||
description=data['pool'].get('description'))
|
||||
description=data['pool'].get('description'),
|
||||
admin_state_up=data['pool'].get('admin_state_up')
|
||||
)
|
||||
|
||||
# Assemble the lists of member id's to add and remove, if any exist
|
||||
request_member_data = data.get('members', [])
|
||||
@ -419,7 +434,9 @@ def update_monitor(request, **kwargs):
|
||||
max_retries_down=data['monitor'].get('retry_down'),
|
||||
http_method=data['monitor'].get('method'),
|
||||
url_path=data['monitor'].get('path'),
|
||||
expected_codes=data['monitor'].get('status'))
|
||||
expected_codes=data['monitor'].get('status'),
|
||||
admin_state_up=data['monitor'].get('admin_state_up')
|
||||
)
|
||||
|
||||
return _get_sdk_object_dict(healthmonitor)
|
||||
|
||||
@ -625,7 +642,7 @@ class Listener(generic.View):
|
||||
conn.load_balancer.members(pool_id))
|
||||
resources['members'] = member_list
|
||||
|
||||
if pool.get('healt_hmonitor_id'):
|
||||
if pool.get('health_monitor_id'):
|
||||
monitor_id = pool['health_monitor_id']
|
||||
monitor = conn.load_balancer.find_health_monitor(
|
||||
monitor_id)
|
||||
@ -844,7 +861,9 @@ class Member(generic.View):
|
||||
member = conn.load_balancer.update_member(
|
||||
member_id, pool_id, weight=data.get('weight'),
|
||||
monitor_address=monitor_address if monitor_address else None,
|
||||
monitor_port=data.get('monitor_port'))
|
||||
monitor_port=data.get('monitor_port'),
|
||||
admin_state_up=data.get('admin_state_up')
|
||||
)
|
||||
return _get_sdk_object_dict(member)
|
||||
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
scope.workflow = workflowService(
|
||||
gettext('Create Listener'),
|
||||
'fa fa-cloud-download',
|
||||
['listener', 'pool', 'members', 'monitor']
|
||||
['listener', 'certificates', 'pool', 'members', 'monitor']
|
||||
);
|
||||
scope.model.initialize('listener', false, loadbalancerId);
|
||||
}
|
||||
|
@ -45,40 +45,17 @@
|
||||
|
||||
function EditListenerWizardController($scope, $q, model, workflowService, gettext) {
|
||||
var scope = $scope;
|
||||
var defer = $q.defer();
|
||||
var steps = ['listener'];
|
||||
var protocol = scope.launchContext.protocol;
|
||||
if (protocol === 'TERMINATED_HTTPS') {
|
||||
steps = ['listener', 'certificates'];
|
||||
}
|
||||
scope.model = model;
|
||||
scope.submit = scope.model.submit;
|
||||
scope.workflow = workflowService(
|
||||
gettext('Update Listener'),
|
||||
'fa fa-pencil', ['listener'],
|
||||
defer.promise);
|
||||
var allSteps = scope.workflow.allSteps.concat([scope.workflow.certificatesStep]);
|
||||
scope.model.initialize('listener', scope.launchContext.id).then(addSteps).then(ready);
|
||||
|
||||
function addSteps() {
|
||||
var steps = scope.model.visibleResources;
|
||||
steps.map(getStep).forEach(function addStep(step) {
|
||||
if (!stepExists(step.id)) {
|
||||
scope.workflow.append(step);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getStep(id) {
|
||||
return allSteps.filter(function findStep(step) {
|
||||
return step.id === id;
|
||||
})[0];
|
||||
}
|
||||
|
||||
function stepExists(id) {
|
||||
return scope.workflow.steps.some(function exists(step) {
|
||||
return step.id === id;
|
||||
});
|
||||
}
|
||||
|
||||
function ready() {
|
||||
defer.resolve();
|
||||
}
|
||||
'fa fa-pencil', steps);
|
||||
scope.model.initialize('listener', scope.launchContext.id);
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -30,8 +30,6 @@
|
||||
};
|
||||
var workflow = {
|
||||
steps: [{id: 'listener'}],
|
||||
allSteps: [{id: 'listener'}, {id: 'pool'}, {id: 'monitor'}],
|
||||
certificatesStep: {id: 'certificates'},
|
||||
append: angular.noop
|
||||
};
|
||||
|
||||
@ -62,24 +60,17 @@
|
||||
expect(scope.workflow).toBe(workflow);
|
||||
});
|
||||
|
||||
it('initializes workflow with correct properties', function() {
|
||||
it('initializes workflow with correct properties', inject(function($controller) {
|
||||
scope.launchContext = { id: '1234', protocol: 'TERMINATED_HTTPS' };
|
||||
ctrl = $controller('EditListenerWizardController', { $scope: scope });
|
||||
expect(workflowSpy).toHaveBeenCalledWith('Update Listener',
|
||||
'fa fa-pencil', ['listener'], jasmine.any(Object));
|
||||
});
|
||||
'fa fa-pencil', jasmine.any(Object));
|
||||
}));
|
||||
|
||||
it('defines scope.submit', function() {
|
||||
expect(scope.submit).toBe(model.submit);
|
||||
expect(scope.submit()).toBe('updated');
|
||||
});
|
||||
|
||||
it('adds necessary steps after initializing', function() {
|
||||
model.visibleResources = ['listener', 'pool', 'monitor'];
|
||||
spyOn(workflow, 'append');
|
||||
scope.$apply();
|
||||
|
||||
expect(workflow.append).toHaveBeenCalledWith({id: 'pool'});
|
||||
expect(workflow.append).toHaveBeenCalledWith({id: 'monitor'});
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -50,6 +50,11 @@
|
||||
patterns, gettext, poolId, member) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.adminStateUpOptions = [
|
||||
{ label: gettext('Yes'), value: true },
|
||||
{ label: gettext('No'), value: false }
|
||||
];
|
||||
|
||||
// IP address validation pattern
|
||||
ctrl.ipPattern = [patterns.ipv4, patterns.ipv6].join('|');
|
||||
|
||||
@ -58,6 +63,7 @@
|
||||
ctrl.weight = member.weight;
|
||||
ctrl.monitor_address = member.monitor_address;
|
||||
ctrl.monitor_port = member.monitor_port;
|
||||
ctrl.admin_state_up = member.admin_state_up;
|
||||
ctrl.cancel = cancel;
|
||||
ctrl.save = save;
|
||||
ctrl.saving = false;
|
||||
@ -72,7 +78,8 @@
|
||||
return api.editMember(poolId, member.id, {
|
||||
weight: ctrl.weight,
|
||||
monitor_address: ctrl.monitor_address,
|
||||
monitor_port: ctrl.monitor_port
|
||||
monitor_port: ctrl.monitor_port,
|
||||
admin_state_up: ctrl.admin_state_up
|
||||
}).then(onSuccess, onFailure);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,8 @@
|
||||
protocol_port: '443',
|
||||
weight: 1,
|
||||
monitor_address: '1.1.1.1',
|
||||
monitor_port: 80
|
||||
monitor_port: 80,
|
||||
admin_state_up: true
|
||||
});
|
||||
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
|
||||
editMember: function() {
|
||||
@ -82,7 +83,8 @@
|
||||
expect(api.editMember).toHaveBeenCalledWith('pool1', 'member1', {
|
||||
weight: 1,
|
||||
monitor_address: '1.1.1.1',
|
||||
monitor_port: 80
|
||||
monitor_port: 80,
|
||||
admin_state_up: true
|
||||
});
|
||||
expect($uibModalInstance.close).toHaveBeenCalled();
|
||||
});
|
||||
|
@ -77,6 +77,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-8 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label required" translate>Admin State Up</label>
|
||||
<div class="form-field">
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-default"
|
||||
ng-repeat="option in modal.adminStateUpOptions"
|
||||
ng-model="modal.admin_state_up"
|
||||
uib-btn-radio="option.value">{$ ::option.label $}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<help-panel class="wizard-help">
|
||||
<ng-include src="::modal.helpUrl"></ng-include>
|
||||
|
@ -47,41 +47,13 @@
|
||||
|
||||
function EditPoolWizardController($scope, $routeParams, $q, model, workflowService, gettext) {
|
||||
var scope = $scope;
|
||||
var defer = $q.defer();
|
||||
var loadbalancerId = $routeParams.loadbalancerId;
|
||||
scope.model = model;
|
||||
scope.submit = scope.model.submit;
|
||||
scope.workflow = workflowService(
|
||||
gettext('Update Pool'),
|
||||
'fa fa-pencil', ['pool'],
|
||||
defer.promise);
|
||||
scope.model.initialize(
|
||||
'pool', scope.launchContext.id, loadbalancerId).then(addSteps).then(ready);
|
||||
|
||||
function addSteps() {
|
||||
var steps = scope.model.visibleResources;
|
||||
steps.map(getStep).forEach(function addStep(step) {
|
||||
if (!stepExists(step.id)) {
|
||||
scope.workflow.append(step);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getStep(id) {
|
||||
return scope.workflow.allSteps.filter(function findStep(step) {
|
||||
return step.id === id;
|
||||
})[0];
|
||||
}
|
||||
|
||||
function stepExists(id) {
|
||||
return scope.workflow.steps.some(function exists(step) {
|
||||
return step.id === id;
|
||||
});
|
||||
}
|
||||
|
||||
function ready() {
|
||||
defer.resolve();
|
||||
}
|
||||
'fa fa-pencil', ['pool']);
|
||||
scope.model.initialize('pool', scope.launchContext.id, loadbalancerId);
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -30,8 +30,6 @@
|
||||
};
|
||||
var workflow = {
|
||||
steps: [{id: 'pool'}],
|
||||
allSteps: [{id: 'pool'}, {id: 'pool'}, {id: 'monitor'}],
|
||||
certificatesStep: {id: 'certificates'},
|
||||
append: angular.noop
|
||||
};
|
||||
|
||||
@ -66,21 +64,13 @@
|
||||
|
||||
it('initializes workflow with correct properties', function() {
|
||||
expect(workflowSpy).toHaveBeenCalledWith('Update Pool',
|
||||
'fa fa-pencil', ['pool'], jasmine.any(Object));
|
||||
'fa fa-pencil', ['pool']);
|
||||
});
|
||||
|
||||
it('defines scope.submit', function() {
|
||||
expect(scope.submit).toBe(model.submit);
|
||||
expect(scope.submit()).toBe('updated');
|
||||
});
|
||||
|
||||
it('adds necessary steps after initializing', function() {
|
||||
model.visibleResources = ['pool', 'monitor'];
|
||||
spyOn(workflow, 'append');
|
||||
scope.$apply();
|
||||
|
||||
expect(workflow.append).toHaveBeenCalledWith({id: 'monitor'});
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -6,7 +6,7 @@
|
||||
help-text="::ctrl.tableHelp">
|
||||
|
||||
<!-- Allocated-->
|
||||
<allocated validate-number-min="1" ng-model="ctrl.tableData.allocated.length">
|
||||
<allocated validate-number-min="0" ng-model="ctrl.tableData.allocated.length">
|
||||
<table st-table="ctrl.tableData.displayedAllocated"
|
||||
st-safe-src="ctrl.tableData.allocated" hz-table
|
||||
class="table table-striped table-rsp table-detail">
|
||||
|
@ -40,6 +40,11 @@
|
||||
var ctrl = this;
|
||||
ctrl.protocolChange = protocolChange;
|
||||
|
||||
ctrl.adminStateUpOptions = [
|
||||
{ label: gettext('Yes'), value: true },
|
||||
{ label: gettext('No'), value: false }
|
||||
];
|
||||
|
||||
// Error text for invalid fields
|
||||
ctrl.portNumberError = gettext('The port must be a number between 1 and 65535.');
|
||||
ctrl.portUniqueError = gettext(
|
||||
@ -61,16 +66,6 @@
|
||||
members.forEach(function setMemberPort(member) {
|
||||
member.port = { HTTP: 80, TERMINATED_HTTPS: 80 }[protocol];
|
||||
});
|
||||
|
||||
var workflow = $scope.workflow;
|
||||
var certificates = workflow.steps.some(function checkCertificatesStep(step) {
|
||||
return step.id === 'certificates';
|
||||
});
|
||||
if (protocol === 'TERMINATED_HTTPS' && !certificates) {
|
||||
workflow.after('listener', workflow.certificatesStep);
|
||||
} else if (protocol !== 'TERMINATED_HTTPS' && certificates) {
|
||||
workflow.remove('certificates');
|
||||
}
|
||||
}
|
||||
|
||||
function listenerPortExists(port) {
|
||||
|
@ -27,7 +27,6 @@
|
||||
beforeEach(inject(function($controller) {
|
||||
workflow = {
|
||||
steps: [{ id: 'listener' }],
|
||||
certificatesStep: { id: 'certificates' },
|
||||
after: angular.noop,
|
||||
remove: angular.noop
|
||||
};
|
||||
@ -54,29 +53,6 @@
|
||||
expect(ctrl.portUniqueError).toBeDefined();
|
||||
});
|
||||
|
||||
it('should show certificates step if selecting TERMINATED_HTTPS', function() {
|
||||
workflow.steps.push(workflow.certificatesStep);
|
||||
spyOn(workflow, 'after');
|
||||
|
||||
ctrl.protocolChange('TERMINATED_HTTPS');
|
||||
expect(workflow.after).not.toHaveBeenCalled();
|
||||
|
||||
workflow.steps.splice(1, 1);
|
||||
ctrl.protocolChange('TERMINATED_HTTPS');
|
||||
expect(workflow.after).toHaveBeenCalledWith('listener', workflow.certificatesStep);
|
||||
});
|
||||
|
||||
it('should hide certificates step if not selecting TERMINATED_HTTPS', function() {
|
||||
spyOn(workflow, 'remove');
|
||||
|
||||
ctrl.protocolChange('HTTP');
|
||||
expect(workflow.remove).not.toHaveBeenCalled();
|
||||
|
||||
workflow.steps.push(workflow.certificatesStep);
|
||||
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(81);
|
||||
|
@ -81,4 +81,22 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xs-12 col-sm-8 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label required" translate>Admin State Up</label>
|
||||
<div class="form-field">
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-default"
|
||||
ng-repeat="option in ctrl.adminStateUpOptions"
|
||||
ng-model="model.spec.listener.admin_state_up"
|
||||
uib-btn-radio="option.value">{$ ::option.label $}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -40,6 +40,11 @@
|
||||
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.adminStateUpOptions = [
|
||||
{ label: gettext('Yes'), value: true },
|
||||
{ label: gettext('No'), value: false }
|
||||
];
|
||||
|
||||
// Error text for invalid fields
|
||||
ctrl.ipError = gettext('The IP address is not valid.');
|
||||
|
||||
|
@ -51,4 +51,23 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xs-12 col-sm-8 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label required" translate>Admin State Up</label>
|
||||
<div class="form-field">
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-default"
|
||||
ng-repeat="option in ctrl.adminStateUpOptions"
|
||||
ng-model="model.spec.loadbalancer.admin_state_up"
|
||||
uib-btn-radio="option.value">{$ ::option.label $}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -45,6 +45,11 @@
|
||||
var ctrl = this;
|
||||
var memberCounter = 0;
|
||||
|
||||
ctrl.adminStateUpOptions = [
|
||||
{ label: gettext('Yes'), value: true },
|
||||
{ label: gettext('No'), value: false }
|
||||
];
|
||||
|
||||
// Error text for invalid fields
|
||||
ctrl.portError = gettext('The port must be a number between 1 and 65535.');
|
||||
ctrl.weightError = gettext('The weight must be a number between 1 and 256.');
|
||||
@ -115,7 +120,10 @@
|
||||
address: null,
|
||||
subnet: null,
|
||||
port: { HTTP: 80 }[protocol],
|
||||
weight: 1
|
||||
weight: 1,
|
||||
monitor_address: null,
|
||||
monitor_port: null,
|
||||
admin_state_up: true
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@
|
||||
Can be toggled using the chevron button.
|
||||
Ensure colspan is greater or equal to number of column-headers.
|
||||
-->
|
||||
<td class="detail" colspan="7">
|
||||
<td class="detail" colspan="8">
|
||||
|
||||
<div class="row">
|
||||
<dl class="col-lg-5 col-md-5 col-sm-5">
|
||||
@ -140,15 +140,29 @@
|
||||
ng-attr-popover="{$ memberDetailsForm[row.id + '-monitor-port'].$invalid && memberDetailsForm[row.id + '-monitor-port'].$dirty ? ctrl.portError : '' $}">
|
||||
</dd>
|
||||
</dl>
|
||||
<dl class="col-lg-5 col-md-5 col-sm-5">
|
||||
<dt class="control-label required" translate>Admin State Up</dt>
|
||||
<dd class="form-group">
|
||||
<div class="form-field">
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-default"
|
||||
ng-repeat="option in ctrl.adminStateUpOptions"
|
||||
ng-model="row.admin_state_up"
|
||||
ng-disabled="row.allocatedMember"
|
||||
uib-btn-radio="option.value">{$ ::option.label $}</label>
|
||||
</div>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr table-status table="table" column-count="7"></tr>
|
||||
<tr table-status table="table" column-count="8"></tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<td colspan="6">
|
||||
<action-list class="pull-right">
|
||||
<action action-classes="'btn btn-sm btn-default'"
|
||||
callback="ctrl.allocateExternalMember">
|
||||
|
@ -139,7 +139,8 @@
|
||||
name: null,
|
||||
description: null,
|
||||
ip: null,
|
||||
subnet: null
|
||||
subnet: null,
|
||||
admin_state_up: true
|
||||
},
|
||||
listener: {
|
||||
id: null,
|
||||
@ -147,7 +148,8 @@
|
||||
description: null,
|
||||
protocol: null,
|
||||
port: null,
|
||||
connection_limit: -1
|
||||
connection_limit: -1,
|
||||
admin_state_up: true
|
||||
},
|
||||
pool: {
|
||||
id: null,
|
||||
@ -156,7 +158,8 @@
|
||||
protocol: null,
|
||||
method: null,
|
||||
type: null,
|
||||
cookie: null
|
||||
cookie: null,
|
||||
admin_state_up: true
|
||||
},
|
||||
monitor: {
|
||||
id: null,
|
||||
@ -167,7 +170,8 @@
|
||||
timeout: 5,
|
||||
method: 'GET',
|
||||
status: '200',
|
||||
path: '/'
|
||||
path: '/',
|
||||
admin_state_up: true
|
||||
},
|
||||
members: [],
|
||||
certificates: []
|
||||
@ -504,7 +508,8 @@
|
||||
name: server.name,
|
||||
weight: 1,
|
||||
monitor_address: null,
|
||||
monitor_port: null
|
||||
monitor_port: null,
|
||||
admin_state_up: true
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -623,6 +628,7 @@
|
||||
spec.description = loadbalancer.description;
|
||||
spec.ip = loadbalancer.vip_address;
|
||||
spec.subnet = loadbalancer.vip_subnet_id;
|
||||
spec.admin_state_up = loadbalancer.admin_state_up;
|
||||
}
|
||||
|
||||
function setListenerSpec(listener) {
|
||||
@ -633,6 +639,7 @@
|
||||
spec.protocol = listener.protocol;
|
||||
spec.port = listener.protocol_port;
|
||||
spec.connection_limit = listener.connection_limit;
|
||||
spec.admin_state_up = listener.admin_state_up;
|
||||
}
|
||||
|
||||
function setPoolSpec(pool) {
|
||||
@ -642,6 +649,7 @@
|
||||
spec.description = pool.description;
|
||||
spec.protocol = pool.protocol;
|
||||
spec.method = pool.lb_algorithm;
|
||||
spec.admin_state_up = pool.admin_state_up;
|
||||
if (angular.isObject(pool.session_persistence)) {
|
||||
var type = pool.session_persistence.type;
|
||||
var cookie = pool.session_persistence.cookie_name;
|
||||
@ -667,6 +675,7 @@
|
||||
weight: member.weight,
|
||||
monitor_address: member.monitor_address,
|
||||
monitor_port: member.monitor_port,
|
||||
admin_state_up: member.admin_state_up,
|
||||
allocatedMember: true
|
||||
});
|
||||
});
|
||||
@ -684,6 +693,7 @@
|
||||
spec.method = monitor.http_method;
|
||||
spec.status = monitor.expected_codes;
|
||||
spec.path = monitor.url_path;
|
||||
spec.admin_state_up = monitor.admin_state_up;
|
||||
}
|
||||
|
||||
function onGetHealthMonitor(response) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
beforeEach(function() {
|
||||
listenerResources = {
|
||||
listener: {
|
||||
admin_state_up: true,
|
||||
id: '1234',
|
||||
name: 'Listener 1',
|
||||
description: 'listener description',
|
||||
@ -36,6 +37,7 @@
|
||||
sni_container_refs: ['container2']
|
||||
},
|
||||
pool: {
|
||||
admin_state_up: true,
|
||||
id: '1234',
|
||||
name: 'Pool 1',
|
||||
protocol: 'HTTP',
|
||||
@ -63,6 +65,7 @@
|
||||
}
|
||||
],
|
||||
monitor: {
|
||||
admin_state_up: true,
|
||||
id: '1234',
|
||||
type: 'HTTP',
|
||||
delay: 1,
|
||||
@ -94,6 +97,7 @@
|
||||
},
|
||||
getLoadBalancer: function() {
|
||||
var loadbalancer = {
|
||||
admin_state_up: true,
|
||||
id: '1234',
|
||||
name: 'Load Balancer 1',
|
||||
vip_address: '1.2.3.4',
|
||||
@ -952,10 +956,10 @@
|
||||
// to implement tests for them.
|
||||
it('has the right number of properties', function() {
|
||||
expect(Object.keys(model.spec).length).toBe(8);
|
||||
expect(Object.keys(model.spec.loadbalancer).length).toBe(4);
|
||||
expect(Object.keys(model.spec.listener).length).toBe(6);
|
||||
expect(Object.keys(model.spec.pool).length).toBe(7);
|
||||
expect(Object.keys(model.spec.monitor).length).toBe(9);
|
||||
expect(Object.keys(model.spec.loadbalancer).length).toBe(5);
|
||||
expect(Object.keys(model.spec.listener).length).toBe(7);
|
||||
expect(Object.keys(model.spec.pool).length).toBe(8);
|
||||
expect(Object.keys(model.spec.monitor).length).toBe(10);
|
||||
expect(model.spec.members).toEqual([]);
|
||||
});
|
||||
|
||||
@ -1249,18 +1253,21 @@
|
||||
expect(finalSpec.loadbalancer.description).toBeUndefined();
|
||||
expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4');
|
||||
expect(finalSpec.loadbalancer.subnet).toBe(model.subnets[0].id);
|
||||
expect(finalSpec.loadbalancer.admin_state_up).toBe(true);
|
||||
|
||||
expect(finalSpec.listener.name).toBe('Listener 1');
|
||||
expect(finalSpec.listener.description).toBeUndefined();
|
||||
expect(finalSpec.listener.protocol).toBe('TCP');
|
||||
expect(finalSpec.listener.port).toBe(80);
|
||||
expect(finalSpec.listener.connection_limit).toBe(999);
|
||||
expect(finalSpec.listener.admin_state_up).toBe(true);
|
||||
|
||||
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.pool.type).toBe('SOURCE_IP');
|
||||
expect(finalSpec.pool.admin_state_up).toBe(true);
|
||||
|
||||
expect(finalSpec.members.length).toBe(3);
|
||||
expect(finalSpec.members[0].address).toBe('1.2.3.4');
|
||||
@ -1290,6 +1297,7 @@
|
||||
expect(finalSpec.monitor.retry_down).toBe(1);
|
||||
expect(finalSpec.monitor.timeout).toBe(1);
|
||||
expect(finalSpec.certificates).toBeUndefined();
|
||||
expect(finalSpec.monitor.admin_state_up).toBe(true);
|
||||
});
|
||||
|
||||
it('should set final spec certificates', function() {
|
||||
|
@ -40,6 +40,11 @@
|
||||
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.adminStateUpOptions = [
|
||||
{ label: gettext('Yes'), value: true },
|
||||
{ label: gettext('No'), value: false }
|
||||
];
|
||||
|
||||
// Error text for invalid fields
|
||||
/* eslint-disable max-len */
|
||||
ctrl.intervalError = gettext('The health check interval must be greater than or equal to the timeout.');
|
||||
|
@ -124,4 +124,23 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xs-12 col-sm-8 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label required" translate>Admin State Up</label>
|
||||
<div class="form-field">
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-default"
|
||||
ng-repeat="option in ctrl.adminStateUpOptions"
|
||||
ng-model="model.spec.monitor.admin_state_up"
|
||||
uib-btn-radio="option.value">{$ ::option.label $}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2017 Walmart.
|
||||
*
|
||||
* 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('PoolDetailsController', PoolDetailsController);
|
||||
|
||||
PoolDetailsController.$inject = [
|
||||
'horizon.dashboard.project.lbaasv2.patterns',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name PoolDetailsController
|
||||
* @description
|
||||
* The `PoolDetailsController` controller provides functions for
|
||||
* configuring the pool step of the LBaaS wizard.
|
||||
* @param patterns The LBaaS v2 patterns constant.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function PoolDetailsController(patterns, gettext) {
|
||||
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.adminStateUpOptions = [
|
||||
{ label: gettext('Yes'), value: true },
|
||||
{ label: gettext('No'), value: false }
|
||||
];
|
||||
|
||||
}
|
||||
})();
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2017 Walmart.
|
||||
*
|
||||
* 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('Pool Details Step', function() {
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
describe('PoolDetailsController', function() {
|
||||
var ctrl;
|
||||
|
||||
beforeEach(inject(function($controller) {
|
||||
ctrl = $controller('PoolDetailsController');
|
||||
}));
|
||||
|
||||
it('should define adminStateUpOptions', function() {
|
||||
expect(ctrl.adminStateUpOptions).toBeDefined();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
})();
|
@ -1,4 +1,4 @@
|
||||
<div>
|
||||
<div ng-controller="PoolDetailsController as ctrl">
|
||||
<p translate>Provide the details for the pool.</p>
|
||||
|
||||
<div class="row">
|
||||
@ -63,4 +63,23 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xs-12 col-sm-8 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label required" translate>Admin State Up</label>
|
||||
<div class="form-field">
|
||||
<div class="btn-group">
|
||||
<label class="btn btn-default"
|
||||
ng-repeat="option in ctrl.adminStateUpOptions"
|
||||
ng-model="model.spec.pool.admin_state_up"
|
||||
uib-btn-radio="option.value">{$ ::option.label $}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -62,37 +62,62 @@
|
||||
templateUrl: basePath + 'workflow/monitor/monitor.html',
|
||||
helpUrl: basePath + 'workflow/monitor/monitor.help.html',
|
||||
formName: 'monitorDetailsForm'
|
||||
},
|
||||
{
|
||||
id: 'certificates',
|
||||
title: gettext('SSL Certificates'),
|
||||
templateUrl: basePath + 'workflow/certificates/certificates.html',
|
||||
helpUrl: basePath + 'workflow/certificates/certificates.help.html',
|
||||
formName: 'certificateDetailsForm'
|
||||
}
|
||||
];
|
||||
|
||||
// This step is kept separate from the rest because it is only added to the workflow by
|
||||
// the Listener Details step if the TERMINATED_HTTPS protocol is selected.
|
||||
var certificatesStep = {
|
||||
id: 'certificates',
|
||||
title: gettext('SSL Certificates'),
|
||||
templateUrl: basePath + 'workflow/certificates/certificates.html',
|
||||
helpUrl: basePath + 'workflow/certificates/certificates.help.html',
|
||||
formName: 'certificateDetailsForm'
|
||||
};
|
||||
|
||||
return initWorkflow;
|
||||
|
||||
function initWorkflow(title, icon, steps, promise) {
|
||||
function initWorkflow(title, icon, steps) {
|
||||
|
||||
var filteredSteps = steps ? workflowSteps.filter(function(step) {
|
||||
return steps.indexOf(step.id) > -1;
|
||||
}) : workflowSteps;
|
||||
var filteredSteps = Array.isArray(steps) ? workflowSteps
|
||||
.filter(
|
||||
function(workflowStep) {
|
||||
return steps.some(function(step) {
|
||||
if (step.id) {
|
||||
return step.id === workflowStep.id;
|
||||
} else {
|
||||
return step === workflowStep.id;
|
||||
}
|
||||
});
|
||||
}
|
||||
) : workflowSteps;
|
||||
|
||||
// If a promise is provided then add a checkReadiness function to the first step so
|
||||
// that the workflow will not show until the promise is resolved. There must always
|
||||
// be at least one step in the workflow.
|
||||
if (promise) {
|
||||
filteredSteps[0] = angular.copy(filteredSteps[0]);
|
||||
filteredSteps[0].checkReadiness = function() {
|
||||
return promise;
|
||||
};
|
||||
if (filteredSteps.length === 0) {
|
||||
filteredSteps = workflowSteps;
|
||||
}
|
||||
|
||||
filteredSteps = filteredSteps.map(function(filteredStep) {
|
||||
filteredStep = angular.copy(filteredStep);
|
||||
if (!Array.isArray(steps)) {
|
||||
return filteredStep;
|
||||
}
|
||||
var step = steps.filter(function(step) {
|
||||
if (step.id) {
|
||||
return step.id === filteredStep.id;
|
||||
} else {
|
||||
return step === filteredStep.id;
|
||||
}
|
||||
})[0];
|
||||
var deferred;
|
||||
if (step) {
|
||||
deferred = step.deferred;
|
||||
}
|
||||
if (deferred) {
|
||||
var promise = deferred.promise;
|
||||
filteredStep.checkReadiness = function() {
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
return filteredStep;
|
||||
});
|
||||
|
||||
return dashboardWorkflow({
|
||||
title: title,
|
||||
btnText: {
|
||||
@ -101,9 +126,7 @@
|
||||
btnIcon: {
|
||||
finish: icon
|
||||
},
|
||||
steps: filteredSteps,
|
||||
allSteps: workflowSteps,
|
||||
certificatesStep: certificatesStep
|
||||
steps: filteredSteps
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Workflow Service', function() {
|
||||
var workflowService;
|
||||
var workflowService, $q;
|
||||
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
@ -29,6 +29,7 @@
|
||||
workflowService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.workflow.workflow'
|
||||
);
|
||||
$q = $injector.get('$q');
|
||||
}));
|
||||
|
||||
it('should be defined', function () {
|
||||
@ -43,25 +44,24 @@
|
||||
it('should have default steps defined', function () {
|
||||
var workflow = workflowService('My Workflow');
|
||||
expect(workflow.steps).toBeDefined();
|
||||
expect(workflow.steps.length).toBe(5);
|
||||
expect(workflow.steps.length).toBe(6);
|
||||
|
||||
var forms = [
|
||||
'loadBalancerDetailsForm',
|
||||
'listenerDetailsForm',
|
||||
'poolDetailsForm',
|
||||
'memberDetailsForm',
|
||||
'monitorDetailsForm'
|
||||
'monitorDetailsForm',
|
||||
'certificateDetailsForm'
|
||||
];
|
||||
|
||||
forms.forEach(function(expectedForm, idx) {
|
||||
expect(workflow.steps[idx].formName).toBe(expectedForm);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have a step for ssl certificates', function () {
|
||||
var workflow = workflowService('My Workflow');
|
||||
expect(workflow.certificatesStep).toBeDefined();
|
||||
expect(workflow.certificatesStep.title).toBe('SSL Certificates');
|
||||
workflow = workflowService('My Workflow', 'foo', []);
|
||||
forms.forEach(function(expectedForm, idx) {
|
||||
expect(workflow.steps[idx].formName).toBe(expectedForm);
|
||||
});
|
||||
});
|
||||
|
||||
it('can filter steps', function () {
|
||||
@ -81,10 +81,18 @@
|
||||
});
|
||||
|
||||
it('can wait for all steps to be ready', function () {
|
||||
var workflow = workflowService('My Workflow', 'foo', null, 'promise');
|
||||
var steps = ['listener', 'certificates'].map(function(step) {
|
||||
return {
|
||||
id: step,
|
||||
deferred: $q.defer()
|
||||
};
|
||||
});
|
||||
var workflow = workflowService('My Workflow', 'foo', steps);
|
||||
|
||||
expect(workflow.steps[0].checkReadiness).toBeDefined();
|
||||
expect(workflow.steps[0].checkReadiness()).toBe('promise');
|
||||
expect(workflow.steps[0].checkReadiness()).toBe(steps[0].deferred.promise);
|
||||
expect(workflow.steps[1].checkReadiness).toBeDefined();
|
||||
expect(workflow.steps[1].checkReadiness()).toBe(steps[1].deferred.promise);
|
||||
});
|
||||
|
||||
it('can be extended', function () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user