Add the angular LBaaS V2 pools detail page

This change implements the details page for the default pool
that is associated with a particular load balancer listener
resource.  It also adds the tab for the pool members table that
will be added in a later patch.

Partially-Implements: blueprint horizon-lbaas-v2-ui
Change-Id: I0c7ef2f5d37363f9753ffbd35deeaf1f2e19ed7d
This commit is contained in:
Lucas Palm 2015-12-14 15:56:07 -06:00
parent f544e0375a
commit 964d845e21
12 changed files with 379 additions and 7 deletions

View File

@ -293,3 +293,20 @@ class Listener(generic.View):
"""
lb = neutronclient(request).show_listener(listener_id)
return lb.get('listener')
@urls.register
class Pool(generic.View):
"""API for retrieving a single pool.
"""
url_regex = r'lbaas/pools/(?P<pool_id>[^/]+)/$'
@rest_utils.ajax()
def get(self, request, pool_id):
"""Get a specific pool.
http://localhost/api/lbaas/pools/cc758c90-3d98-4ea1-af44-aab405c9c915
"""
lb = neutronclient(request).show_lbaas_pool(pool_id)
return lb.get('pool')

View File

@ -55,7 +55,9 @@ ADD_JS_FILES = [
'dashboard/project/lbaasv2/listeners/listeners.module.js',
'dashboard/project/lbaasv2/listeners/table.controller.js',
'dashboard/project/lbaasv2/listeners/detail.controller.js',
'dashboard/project/lbaasv2/listeners/filters.js'
'dashboard/project/lbaasv2/listeners/filters.js',
'dashboard/project/lbaasv2/pools/pools.module.js',
'dashboard/project/lbaasv2/pools/detail.controller.js'
]
ADD_JS_SPEC_FILES = [
@ -85,7 +87,9 @@ ADD_JS_SPEC_FILES = [
'dashboard/project/lbaasv2/listeners/listeners.module.spec.js',
'dashboard/project/lbaasv2/listeners/table.controller.spec.js',
'dashboard/project/lbaasv2/listeners/detail.controller.spec.js',
'dashboard/project/lbaasv2/listeners/filters.spec.js'
'dashboard/project/lbassv2/listeners/filters.spec.js',
'dashboard/project/lbaasv2/pools/pools.module.spec.js',
'dashboard/project/lbaasv2/pools/detail.controller.spec.js'
]
ADD_SCSS_FILES = [

View File

@ -41,7 +41,8 @@
createLoadBalancer: createLoadBalancer,
editLoadBalancer: editLoadBalancer,
getListeners: getListeners,
getListener: getListener
getListener: getListener,
getPool: getPool
};
return service;
@ -151,5 +152,20 @@
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getPool
* @description
* Get a single Pool by ID.
* @param {string} id
* Specifies the id of the pool to request.
*/
function getPool(id) {
return apiService.get('/api/lbaas/pools/' + id)
.error(function () {
toastService.add('error', gettext('Unable to retrieve pool.'));
});
}
}
}());

View File

@ -81,6 +81,15 @@
'1234'
]
},
{
"func": "getPool",
"method": "get",
"path": "/api/lbaas/pools/1234",
"error": "Unable to retrieve pool.",
"testInput": [
'1234'
]
},
{
"func": "createLoadBalancer",
"method": "post",

View File

@ -27,7 +27,8 @@
.module('horizon.dashboard.project.lbaasv2', [
'ngRoute',
'horizon.dashboard.project.lbaasv2.loadbalancers',
'horizon.dashboard.project.lbaasv2.listeners'
'horizon.dashboard.project.lbaasv2.listeners',
'horizon.dashboard.project.lbaasv2.pools'
])
.config(config)
.constant('horizon.dashboard.project.lbaasv2.patterns', {
@ -64,6 +65,9 @@
})
.when(href + 'listeners/detail/:listenerId', {
templateUrl: basePath + 'listeners/detail.html'
})
.when(href + 'pools/detail/:poolId', {
templateUrl: basePath + 'pools/detail.html'
});
}

View File

@ -114,10 +114,16 @@
{
templateUrl: basePath + 'listeners/detail.html'
}
],
[
href + 'pools/detail/:poolId',
{
templateUrl: basePath + 'pools/detail.html'
}
]
];
expect($routeProvider.when.calls.count()).toBe(3);
expect($routeProvider.when.calls.count()).toBe(4);
angular.forEach($routeProvider.when.calls.all(), function(call, i) {
expect(call.args).toEqual(routes[i]);
});

View File

@ -36,10 +36,10 @@
<div>
<dt translate>Default Pool ID</dt>
<dd>
<div ng-if="ctrl.listener.default_pool_id !== null">
<div ng-if="ctrl.listener.default_pool_id">
<a ng-href="project/ngloadbalancersv2/pools/detail/{$ ::ctrl.listener.default_pool_id $}">{$ ::ctrl.listener.default_pool_id $}</a>
</div>
<div ng-if="ctrl.listener.default_pool_id === null">
<div ng-if="!ctrl.listener.default_pool_id">
{$ 'None' | translate $}
</div>
</dd>

View File

@ -0,0 +1,94 @@
/*
* 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.pools')
.controller('PoolDetailController', PoolDetailController);
PoolDetailController.$inject = [
'horizon.app.core.openstack-service-api.lbaasv2',
'$routeParams',
'horizon.framework.util.i18n.gettext'
];
/**
* @ngdoc controller
* @name PoolDetailController
*
* @description
* Controller for the LBaaS v2 pool detail page.
*
* @param api The LBaaS v2 API service.
* @param $routeParams The angular $routeParams service.
* @param gettext The horizon gettext function for translation.
* @returns undefined
*/
function PoolDetailController(api, $routeParams, gettext) {
var ctrl = this;
ctrl.pool = {};
ctrl.listener = {};
ctrl.loadbalancer = {};
ctrl.lb_algorithm_mappings = {
'ROUND_ROBIN': gettext('Round Robin'),
'LEAST_CONNECTIONS': gettext('Least Connections'),
'SOURCE_IP': gettext('Source IP')
};
var poolId = $routeParams.poolId;
init();
////////////////////////////////
function init() {
api.getPool(poolId).success(poolSuccess);
}
function poolSuccess(response) {
ctrl.pool = response;
if (ctrl.pool.hasOwnProperty('listeners') &&
ctrl.pool.listeners.length > 0) {
getListenerDetails(ctrl.pool.listeners[0].id);
}
}
function getListenerDetails(listenerId) {
api.getListener(listenerId).success(listenerSuccess);
}
function listenerSuccess(response) {
ctrl.listener = response;
if (ctrl.listener.hasOwnProperty('loadbalancers') &&
ctrl.listener.loadbalancers.length > 0) {
getLoadBalancerDetails(ctrl.listener.loadbalancers[0].id);
}
}
function getLoadBalancerDetails(loadbalancerId) {
api.getLoadBalancer(loadbalancerId).success(loadbalancerSuccess);
}
function loadbalancerSuccess(response) {
ctrl.loadbalancer = response;
}
}
})();

View File

@ -0,0 +1,101 @@
/*
* 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 Pool Detail Controller', function() {
var controller, lbaasv2API, gettextService, pool, listener, loadbalancer;
function fakePoolAPI() {
return {
success: function(callback) {
callback(pool);
}
};
}
function fakeListenerAPI() {
return {
success: function(callback) {
callback(listener);
}
};
}
function fakeLoadBalancerAPI() {
return {
success: function(callback) {
callback(loadbalancer);
}
};
}
///////////////////////
beforeEach(module('horizon.framework.util.http'));
beforeEach(module('horizon.framework.widgets.toast'));
beforeEach(module('horizon.framework.conf'));
beforeEach(module('horizon.app.core.openstack-service-api'));
beforeEach(module('horizon.dashboard.project.lbaasv2'));
beforeEach(module('horizon.framework.util.i18n'));
beforeEach(inject(function($injector) {
gettextService = $injector.get('horizon.framework.util.i18n.gettext');
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
controller = $injector.get('$controller');
spyOn(lbaasv2API, 'getPool').and.callFake(fakePoolAPI);
spyOn(lbaasv2API, 'getListener').and.callFake(fakeListenerAPI);
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(fakeLoadBalancerAPI);
}));
function createController() {
return controller('PoolDetailController', {
api: lbaasv2API,
$routeParams: { poolId: 'poolId' },
gettext: gettextService
});
}
it('should invoke lbaasv2 apis', function() {
pool = { id: 'poolId', listeners: [{id: 'listenerId'}] };
listener = { id: 'listenerId', loadbalancers: [{id: 'loadbalancerId'}] };
loadbalancer = { id: 'loadbalancerId' };
createController();
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId');
});
it('should not invoke the getListener or getLoadBalancer lbaasv2 api', function() {
pool = { id: 'poolId', listeners: [] };
createController();
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
expect(lbaasv2API.getListener).not.toHaveBeenCalled();
expect(lbaasv2API.getLoadBalancer).not.toHaveBeenCalled();
});
it('should not invoke getLoadBalancer lbaasv2 api', function() {
pool = { id: 'poolId', listeners: [{id: 'listenerId'}] };
listener = { id: 'listenerId', loadbalancers: [] };
createController();
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
expect(lbaasv2API.getLoadBalancer).not.toHaveBeenCalled();
});
});
})();

View File

@ -0,0 +1,65 @@
<div class="content" ng-controller="PoolDetailController as ctrl">
<div class='page-header'>
<ol class="breadcrumb">
<li><a href="project/ngloadbalancersv2/"><translate>Load Balancers</translate></a></li>
<li><a href="project/ngloadbalancersv2/detail/{$ ::ctrl.loadbalancer.id $}">{$ ::(ctrl.loadbalancer.name || ctrl.loadbalancer.id) $}</a></li>
<li><a href="project/ngloadbalancersv2/listeners/detail/{$ ::ctrl.listener.id $}">{$ ::(ctrl.listener.name || ctrl.listener.id) $}</a></li>
<li class="active">{$ ::(ctrl.pool.name || ctrl.pool.id) $}</li>
</ol>
<p ng-if="::ctrl.pool.description">{$ ::ctrl.pool.description $}</p>
</div>
<div class="detail-page">
<tabset>
<tab heading="{$ 'Overview' | translate $}">
<dl class="dl-horizontal">
<div>
<dt translate>Pool ID</dt>
<dd>{$ ::ctrl.pool.id $}</dd>
</div>
<div>
<dt translate>Admin State Up</dt>
<dd>{$ ::ctrl.pool.admin_state_up | yesno $}</dd>
</div>
<div>
<dt translate>Tenant ID</dt>
<dd>{$ ::ctrl.pool.tenant_id $}</dd>
</div>
<div>
<dt translate>Protocol</dt>
<dd>{$ ::ctrl.pool.protocol $}</dd>
</div>
<div>
<dt translate>Load Balancer Algorithm</dt>
<dd>{$ ctrl.pool.lb_algorithm | decode:ctrl.lb_algorithm_mappings $}</dd>
</div>
<div>
<dt translate>Session Persistence</dt>
<dd>
<div ng-if="ctrl.pool.session_persistence">
{$ ::ctrl.pool.session_persistence $}
</div>
<div ng-if="!ctrl.pool.session_persistence">
{$ 'None' | translate $}
</div>
</dd>
</div>
<div>
<dt translate>Health Monitor ID</dt>
<dd>
<div ng-if="ctrl.pool.healthmonitor_id">
<a ng-href="project/ngloadbalancersv2/healthmonitors/detail/{$ ::ctrl.pool.healthmonitor_id $}">{$ ::ctrl.pool.healthmonitor_id $}</a>
</div>
<div ng-if="!ctrl.pool.healthmonitor_id">
{$ 'None' | translate $}
</div>
</dd>
</div>
</dl>
</tab>
<tab heading="{$ 'Members' | translate $}">
<!--This should be uncommented in the members table patch work.-->
<!--<ng-include src="'static/dashboard/project/lbaasv2/members/table.html'"></ng-include>-->
</tab>
</tabset>
</div>
</div>

View File

@ -0,0 +1,31 @@
/*
* 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 overview
* @ngname horizon.dashboard.project.lbaasv2.pools
*
* @description
* Provides the services and widgets required to support and display the project pools
* for the load balancers v2 panel.
*/
angular
.module('horizon.dashboard.project.lbaasv2.pools', []);
})();

View File

@ -0,0 +1,25 @@
/*
* 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 Pools Module', function() {
it('should exist', function() {
expect(angular.module('horizon.dashboard.project.lbaasv2.pools')).toBeDefined();
});
});
})();