Add the angular LBaaS V2 health monitor detail page

This change implements the health monitor detail page that shows the details
for a specific health monitor that exists within a particular pool.

Partially-Implements: blueprint horizon-lbaas-v2-ui
Change-Id: I73aad299e22d352b20e74356db96ad7f49e709ca
This commit is contained in:
Lucas Palm 2016-01-06 16:03:53 -06:00
parent 7b90156da1
commit cbf51dff4e
11 changed files with 395 additions and 5 deletions

View File

@ -346,3 +346,19 @@ class Member(generic.View):
"""
lb = neutronclient(request).show_lbaas_member(member_id, pool_id)
return lb.get('member')
@urls.register
class HealthMonitor(generic.View):
"""API for retrieving a single health monitor.
"""
url_regex = r'lbaas/healthmonitors/(?P<healthmonitor_id>[^/]+)/$'
@rest_utils.ajax()
def get(self, request, healthmonitor_id):
"""Get a specific health monitor.
"""
lb = neutronclient(request).show_lbaas_healthmonitor(healthmonitor_id)
return lb.get('healthmonitor')

View File

@ -60,7 +60,9 @@ ADD_JS_FILES = [
'dashboard/project/lbaasv2/pools/detail.controller.js',
'dashboard/project/lbaasv2/members/members.module.js',
'dashboard/project/lbaasv2/members/detail.controller.js',
'dashboard/project/lbaasv2/members/table.controller.js'
'dashboard/project/lbaasv2/members/table.controller.js',
'dashboard/project/lbaasv2/healthmonitors/healthmonitors.module.js',
'dashboard/project/lbaasv2/healthmonitors/detail.controller.js'
]
ADD_JS_SPEC_FILES = [
@ -95,7 +97,9 @@ ADD_JS_SPEC_FILES = [
'dashboard/project/lbaasv2/pools/detail.controller.spec.js',
'dashboard/project/lbaasv2/members/members.module.spec.js',
'dashboard/project/lbaasv2/members/detail.controller.spec.js',
'dashboard/project/lbaasv2/members/table.controller.spec.js'
'dashboard/project/lbaasv2/members/table.controller.spec.js',
'dashboard/project/lbaasv2/healthmonitors/healthmonitors.module.spec.js',
'dashboard/project/lbaasv2/healthmonitors/detail.controller.spec.js'
]
ADD_SCSS_FILES = [

View File

@ -44,7 +44,8 @@
getListener: getListener,
getPool: getPool,
getMembers: getMembers,
getMember: getMember
getMember: getMember,
getHealthMonitor: getHealthMonitor
};
return service;
@ -208,5 +209,20 @@
});
}
/**
* @name horizon.app.core.openstack-service-api.lbaasv2.getHealthMonitor
* @description
* Get a single pool health monitor by ID.
* @param {string} monitorId
* Specifies the id of the health monitor.
*/
function getHealthMonitor(monitorId) {
return apiService.get('/api/lbaas/healthmonitors/' + monitorId)
.error(function () {
toastService.add('error', gettext('Unable to retrieve health monitor.'));
});
}
}
}());

View File

@ -109,6 +109,15 @@
'5678'
]
},
{
"func": "getHealthMonitor",
"method": "get",
"path": "/api/lbaas/healthmonitors/1234",
"error": "Unable to retrieve health monitor.",
"testInput": [
'1234'
]
},
{
"func": "createLoadBalancer",
"method": "post",

View File

@ -0,0 +1,102 @@
/*
* 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.healthmonitors')
.controller('HealthMonitorDetailController', HealthMonitorDetailController);
HealthMonitorDetailController.$inject = [
'horizon.app.core.openstack-service-api.lbaasv2',
'$routeParams'
];
/**
* @ngdoc controller
* @name HealthMonitorDetailController
*
* @description
* Controller for the LBaaS v2 health monitor detail page.
*
* @param api The LBaaS v2 API service.
* @param $routeParams The angular $routeParams service.
* @returns undefined
*/
function HealthMonitorDetailController(api, $routeParams) {
var ctrl = this;
ctrl.healthmonitor = {};
ctrl.pool = {};
ctrl.listener = {};
ctrl.loadbalancer = {};
var healthmonitorID = $routeParams.healthmonitorId;
init();
////////////////////////////////
function init() {
api.getHealthMonitor(healthmonitorID).success(healthMonitorSuccess);
}
function healthMonitorSuccess(response) {
ctrl.healthmonitor = response;
if (ctrl.healthmonitor.hasOwnProperty('pools') &&
ctrl.healthmonitor.pools.length > 0) {
getPoolDetails(ctrl.healthmonitor.pools[0].id);
}
}
function getPoolDetails(poolId) {
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,122 @@
/*
* 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 Healthmonitor Detail Controller', function() {
var controller, lbaasv2API, healthmonitor, pool, listener, loadbalancer;
function fakeHealthMonitorAPI() {
return {
success: function(callback) {
callback(healthmonitor);
}
};
}
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(inject(function($injector) {
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
controller = $injector.get('$controller');
spyOn(lbaasv2API, 'getHealthMonitor').and.callFake(fakeHealthMonitorAPI);
spyOn(lbaasv2API, 'getPool').and.callFake(fakePoolAPI);
spyOn(lbaasv2API, 'getListener').and.callFake(fakeListenerAPI);
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(fakeLoadBalancerAPI);
}));
function createController() {
return controller('HealthMonitorDetailController', {
api: lbaasv2API,
$routeParams: { healthmonitorId: 'healthmonitorId' }
});
}
it('should invoke lbaasv2 apis', function() {
healthmonitor = { id: 'healthmonitorId', pools: [{id: 'poolId'}] };
pool = { id: 'poolId', listeners: [{id: 'listenerId'}] };
listener = { id: 'listenerId', loadbalancers: [{id: 'loadbalancerId'}] };
loadbalancer = { id: 'loadbalancerId' };
createController();
expect(lbaasv2API.getHealthMonitor).toHaveBeenCalledWith('healthmonitorId');
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId');
});
it('should not invoke the getPool, getListener or getLoadBalancer lbaasv2 api', function() {
healthmonitor = { id: 'healthmonitorId', pools: [] };
createController();
expect(lbaasv2API.getHealthMonitor).toHaveBeenCalledWith('healthmonitorId');
expect(lbaasv2API.getPool).not.toHaveBeenCalled();
expect(lbaasv2API.getListener).not.toHaveBeenCalled();
expect(lbaasv2API.getLoadBalancer).not.toHaveBeenCalled();
});
it('should not invoke the getListener or getLoadBalancer lbaasv2 api', function() {
healthmonitor = { id: 'healthmonitorId', pools: [{id: 'poolId'}] };
pool = { id: 'poolId', listeners: [] };
createController();
expect(lbaasv2API.getHealthMonitor).toHaveBeenCalledWith('healthmonitorId');
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
expect(lbaasv2API.getListener).not.toHaveBeenCalled();
expect(lbaasv2API.getLoadBalancer).not.toHaveBeenCalled();
});
it('should not invoke getLoadBalancer lbaasv2 api', function() {
healthmonitor = { id: 'healthmonitorId', pools: [{id: 'poolId'}] };
pool = { id: 'poolId', listeners: [{id: 'listenerId'}] };
listener = { id: 'listenerId', loadbalancers: [] };
createController();
expect(lbaasv2API.getHealthMonitor).toHaveBeenCalledWith('healthmonitorId');
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
expect(lbaasv2API.getLoadBalancer).not.toHaveBeenCalled();
});
});
})();

View File

@ -0,0 +1,55 @@
<div class="content" ng-controller="HealthMonitorDetailController 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><a href="project/ngloadbalancersv2/pools/detail/{$ ::ctrl.pool.id $}">{$ ::(ctrl.pool.name || ctrl.pool.id) $}</a></li>
<li class="active">{$ ::(ctrl.healthmonitor.name || ctrl.healthmonitor.id) $}</li>
</ol>
</div>
<div class="detail-page">
<dl class="dl-horizontal">
<div>
<dt translate>Monitor ID</dt>
<dd>{$ ::ctrl.healthmonitor.id $}</dd>
</div>
<div>
<dt translate>Tenant ID</dt>
<dd>{$ ::ctrl.healthmonitor.tenant_id $}</dd>
</div>
<div>
<dt translate>Type</dt>
<dd>{$ ::ctrl.healthmonitor.type $}</dd>
</div>
<div>
<dt translate>HTTP Method</dt>
<dd>{$ ::ctrl.healthmonitor.http_method $}</dd>
</div>
<div>
<dt translate>Admin State Up</dt>
<dd>{$ ::ctrl.healthmonitor.admin_state | yesno $}</dd>
</div>
<div>
<dt translate>Expected Codes</dt>
<dd>{$ ::ctrl.healthmonitor.expected_codes $}</dd>
</div>
<div>
<dt translate>Max Retries</dt>
<dd>{$ ::ctrl.healthmonitor.max_retries $}</dd>
</div>
<div>
<dt translate>Timeout</dt>
<dd>{$ ::ctrl.healthmonitor.timeout $}</dd>
</div>
<div>
<dt translate>Delay</dt>
<dd>{$ ::ctrl.healthmonitor.delay $}</dd>
</div>
<div>
<dt translate>URL Path</dt>
<dd>{$ ::ctrl.healthmonitor.url_path $}</dd>
</div>
</dl>
</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.healthmonitors
*
* @description
* Provides the services and widgets required to support and display the project healthmonitors
* for the load balancers v2 panel.
*/
angular
.module('horizon.dashboard.project.lbaasv2.healthmonitors', []);
})();

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 Healthmonitors Module', function() {
it('should exist', function() {
expect(angular.module('horizon.dashboard.project.lbaasv2.healthmonitors')).toBeDefined();
});
});
})();

View File

@ -29,7 +29,8 @@
'horizon.dashboard.project.lbaasv2.loadbalancers',
'horizon.dashboard.project.lbaasv2.listeners',
'horizon.dashboard.project.lbaasv2.pools',
'horizon.dashboard.project.lbaasv2.members'
'horizon.dashboard.project.lbaasv2.members',
'horizon.dashboard.project.lbaasv2.healthmonitors'
])
.config(config)
.constant('horizon.dashboard.project.lbaasv2.patterns', {
@ -72,6 +73,9 @@
})
.when(href + 'pools/:poolId/members/detail/:memberId', {
templateUrl: basePath + 'members/detail.html'
})
.when(href + 'healthmonitors/detail/:healthmonitorId', {
templateUrl: basePath + 'healthmonitors/detail.html'
});
}

View File

@ -126,10 +126,16 @@
{
templateUrl: basePath + 'members/detail.html'
}
],
[
href + 'healthmonitors/detail/:healthmonitorId',
{
templateUrl: basePath + 'healthmonitors/detail.html'
}
]
];
expect($routeProvider.when.calls.count()).toBe(5);
expect($routeProvider.when.calls.count()).toBe(6);
angular.forEach($routeProvider.when.calls.all(), function(call, i) {
expect(call.args).toEqual(routes[i]);
});