Catch up with horizon framework
* Use resource registry to reduce boilerplate * Resolve resources before routing * Better organization of the page structure Change-Id: I9fdf0d1bc3389cac0f4cd955dcd76920b7c0f90b Story: 1713855 Task: 5449 Story: 1713854 Task: 5219 Story: 1713853 Task: 5366
This commit is contained in:
parent
8788fcbf55
commit
3594784322
@ -661,6 +661,24 @@ class Pools(generic.View):
|
||||
"""
|
||||
url_regex = r'lbaas/pools/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request):
|
||||
"""List of pools for the current project.
|
||||
|
||||
The listing result is an object with property "items".
|
||||
"""
|
||||
loadbalancer_id = request.GET.get('loadbalancerId')
|
||||
listener_id = request.GET.get('listenerId')
|
||||
conn = _get_sdk_connection(request)
|
||||
pool_list = _sdk_object_to_list(conn.load_balancer.pools(
|
||||
project_id=request.user.project_id))
|
||||
|
||||
if loadbalancer_id or listener_id:
|
||||
pool_list = self._filter_pools(pool_list,
|
||||
loadbalancer_id,
|
||||
listener_id)
|
||||
return {'items': pool_list}
|
||||
|
||||
@rest_utils.ajax()
|
||||
def post(self, request):
|
||||
"""Create a new pool.
|
||||
@ -672,6 +690,24 @@ class Pools(generic.View):
|
||||
'listener_id': request.DATA.get('parentResourceId')}
|
||||
return create_pool(request, **kwargs)
|
||||
|
||||
def _filter_pools(self, pool_list, loadbalancer_id, listener_id):
|
||||
filtered_pools = []
|
||||
|
||||
for pool in pool_list:
|
||||
if loadbalancer_id:
|
||||
if pool['loadbalancers'][0]['id'] == loadbalancer_id:
|
||||
if listener_id:
|
||||
if (pool['listeners'] and
|
||||
pool['listeners'][0]['id'] == listener_id):
|
||||
filtered_pools.append(pool)
|
||||
else:
|
||||
filtered_pools.append(pool)
|
||||
elif (pool['listeners'] and
|
||||
pool['listeners'][0]['id'] == listener_id):
|
||||
filtered_pools.append(pool)
|
||||
|
||||
return filtered_pools
|
||||
|
||||
|
||||
@urls.register
|
||||
class Pool(generic.View):
|
||||
@ -819,6 +855,26 @@ class HealthMonitors(generic.View):
|
||||
"""
|
||||
url_regex = r'lbaas/healthmonitors/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request):
|
||||
"""List of health monitors for the current project.
|
||||
|
||||
The listing result is an object with property "items".
|
||||
"""
|
||||
pool_id = request.GET.get('poolId')
|
||||
conn = _get_sdk_connection(request)
|
||||
health_monitor_list = _sdk_object_to_list(
|
||||
conn.load_balancer.health_monitors(
|
||||
project_id=request.user.project_id
|
||||
)
|
||||
)
|
||||
|
||||
if pool_id:
|
||||
health_monitor_list = self._filter_health_monitors(
|
||||
health_monitor_list,
|
||||
pool_id)
|
||||
return {'items': health_monitor_list}
|
||||
|
||||
@rest_utils.ajax()
|
||||
def post(self, request):
|
||||
"""Create a new health monitor.
|
||||
@ -828,6 +884,15 @@ class HealthMonitors(generic.View):
|
||||
'pool_id': request.DATA.get('parentResourceId')}
|
||||
return create_health_monitor(request, **kwargs)
|
||||
|
||||
def _filter_health_monitors(self, health_monitor_list, pool_id):
|
||||
filtered_health_monitors = []
|
||||
|
||||
for health_monitor in health_monitor_list:
|
||||
if health_monitor['pools'][0]['id'] == pool_id:
|
||||
filtered_health_monitors.append(health_monitor)
|
||||
|
||||
return filtered_health_monitors
|
||||
|
||||
|
||||
@urls.register
|
||||
class HealthMonitor(generic.View):
|
||||
|
@ -46,6 +46,7 @@
|
||||
createListener: createListener,
|
||||
editListener: editListener,
|
||||
deleteListener: deleteListener,
|
||||
getPools: getPools,
|
||||
getPool: getPool,
|
||||
createPool: createPool,
|
||||
editPool: editPool,
|
||||
@ -54,6 +55,7 @@
|
||||
getMember: getMember,
|
||||
deleteMember: deleteMember,
|
||||
editMember: editMember,
|
||||
getHealthMonitors: getHealthMonitors,
|
||||
getHealthMonitor: getHealthMonitor,
|
||||
deleteHealthMonitor: deleteHealthMonitor,
|
||||
createHealthMonitor: createHealthMonitor,
|
||||
@ -242,6 +244,38 @@
|
||||
|
||||
// Pools
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.lbaasv2.getPools
|
||||
* @description
|
||||
* Get the list of pools.
|
||||
* If a loadbalancer ID is passed as a parameter, the returning list of
|
||||
* pools will be filtered to include only those pools under the
|
||||
* specified loadbalancer.
|
||||
* @param {string} loadbalancerId
|
||||
* Specifies the id of the loadbalancer to request pools for.
|
||||
* @param {string} listenerId
|
||||
* Specifies the id of the listener to request pools for.
|
||||
*
|
||||
* The listing result is an object with property "items". Each item is
|
||||
* a pool.
|
||||
*/
|
||||
|
||||
function getPools(loadbalancerId, listenerId) {
|
||||
var params = $.extend({},
|
||||
{
|
||||
loadbalancerId: loadbalancerId,
|
||||
listenerId: listenerId
|
||||
}
|
||||
);
|
||||
if (!$.isEmptyObject(params)) {
|
||||
params = { params: params };
|
||||
}
|
||||
return apiService.get('/api/lbaas/pools/', params)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve pools.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.lbaasv2.getPool
|
||||
* @description
|
||||
@ -408,6 +442,28 @@
|
||||
* Specifies the id of the health monitor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.lbaasv2.getHealthMonitors
|
||||
* @description
|
||||
* Get the list of healthmonitors.
|
||||
* If a pool ID is passed as a parameter, the returning list of
|
||||
* healthmonitors will be filtered to include only those healthmonitors under the
|
||||
* specified pool.
|
||||
* @param {string} id
|
||||
* Specifies the id of the pool to request healthmonitors for.
|
||||
*
|
||||
* The listing result is an object with property "items". Each item is
|
||||
* a healthmonitor.
|
||||
*/
|
||||
|
||||
function getHealthMonitors(id) {
|
||||
var params = id ? {params: {poolId: id}} : {};
|
||||
return apiService.get('/api/lbaas/healthmonitors/', params)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve health monitors.'));
|
||||
});
|
||||
}
|
||||
|
||||
function getHealthMonitor(monitorId) {
|
||||
return apiService.get('/api/lbaas/healthmonitors/' + monitorId + '/')
|
||||
.error(function () {
|
||||
|
@ -90,6 +90,37 @@
|
||||
error: 'Unable to retrieve listener.',
|
||||
testInput: [ '1234', false ]
|
||||
},
|
||||
{
|
||||
func: 'getPools',
|
||||
method: 'get',
|
||||
path: '/api/lbaas/pools/',
|
||||
error: 'Unable to retrieve pools.',
|
||||
testInput: [ '1234' ],
|
||||
data: { params: { loadbalancerId: '1234' } }
|
||||
},
|
||||
{
|
||||
func: 'getPools',
|
||||
method: 'get',
|
||||
path: '/api/lbaas/pools/',
|
||||
error: 'Unable to retrieve pools.',
|
||||
testInput: [ '1234', '5678' ],
|
||||
data: { params: { loadbalancerId: '1234', listenerId: '5678' } }
|
||||
},
|
||||
{
|
||||
func: 'getPools',
|
||||
method: 'get',
|
||||
path: '/api/lbaas/pools/',
|
||||
error: 'Unable to retrieve pools.',
|
||||
testInput: [ undefined, '5678' ],
|
||||
data: { params: { listenerId: '5678' } }
|
||||
},
|
||||
{
|
||||
func: 'getPools',
|
||||
method: 'get',
|
||||
path: '/api/lbaas/pools/',
|
||||
data: {},
|
||||
error: 'Unable to retrieve pools.'
|
||||
},
|
||||
{
|
||||
func: 'getPool',
|
||||
method: 'get',
|
||||
@ -142,6 +173,21 @@
|
||||
data: { weight: 2 },
|
||||
testInput: [ '1234', '5678', { weight: 2 } ]
|
||||
},
|
||||
{
|
||||
func: 'getHealthMonitors',
|
||||
method: 'get',
|
||||
path: '/api/lbaas/healthmonitors/',
|
||||
error: 'Unable to retrieve health monitors.',
|
||||
testInput: [ '1234' ],
|
||||
data: { params: { poolId: '1234' } }
|
||||
},
|
||||
{
|
||||
func: 'getHealthMonitors',
|
||||
method: 'get',
|
||||
path: '/api/lbaas/healthmonitors/',
|
||||
data: {},
|
||||
error: 'Unable to retrieve health monitors.'
|
||||
},
|
||||
{
|
||||
func: 'getHealthMonitor',
|
||||
method: 'get',
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -21,68 +22,46 @@
|
||||
.factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.create', createService);
|
||||
|
||||
createService.$inject = [
|
||||
'$q',
|
||||
'$location',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.util.q.extensions'
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.healthmonitors.actions.createService
|
||||
*
|
||||
* @description
|
||||
* Provides the service for creating a health monitor resource.
|
||||
* @param $q The angular service for promises.
|
||||
* @param $location The angular $location service.
|
||||
*
|
||||
* @param resourceType The health monitor resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
*
|
||||
* @returns The health monitor create service.
|
||||
*/
|
||||
|
||||
function createService($q, $location, workflowModal, policy, gettext, qExtensions) {
|
||||
var loadbalancerId, listenerId, poolId, statePromise;
|
||||
|
||||
var create = workflowModal.init({
|
||||
function createService(resourceType, actionResultService, workflowModal, policy, gettext) {
|
||||
return workflowModal.init({
|
||||
controller: 'CreateHealthMonitorWizardController',
|
||||
message: gettext('A new health monitor is being created.'),
|
||||
handle: onCreate,
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
var service = {
|
||||
init: init,
|
||||
create: create
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function init(_loadbalancerId_, _listenerId_, _statePromise_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
listenerId = _listenerId_;
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
function allowed() {
|
||||
return policy.ifAllowed({ rules: [['neutron', 'create_health_monitor']] });
|
||||
}
|
||||
|
||||
function allowed(pool) {
|
||||
poolId = pool.id;
|
||||
return $q.all([
|
||||
statePromise,
|
||||
qExtensions.booleanAsPromise(!pool.health_monitor_id),
|
||||
policy.ifAllowed({ rules: [['neutron', 'create_health_monitor']] })
|
||||
]);
|
||||
function handle(response) {
|
||||
var newHealthMonitor = response.data;
|
||||
return actionResultService.getActionResult()
|
||||
.created(resourceType, newHealthMonitor.id)
|
||||
.result;
|
||||
}
|
||||
|
||||
function onCreate(response) {
|
||||
var healthMonitorId = response.data.id;
|
||||
$location.path('project/load_balancer/' + loadbalancerId + '/listeners/' +
|
||||
listenerId + '/pools/' + poolId + '/healthmonitors/' + healthMonitorId);
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -17,89 +18,25 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Create Health Monitor Action Service', function() {
|
||||
var scope, $q, $location, policy, init, service, loadBalancerState;
|
||||
var policy, service;
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = service.create.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith(
|
||||
{rules: [['neutron', 'create_health_monitor']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func({ data: { id: 'healthmonitor1' } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
$q = $injector.get('$q');
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
$location = $injector.get('$location');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.actions.create');
|
||||
init = service.init;
|
||||
loadBalancerState = $q.defer();
|
||||
}));
|
||||
|
||||
it('should define the correct service properties', function() {
|
||||
expect(service.init).toBeDefined();
|
||||
expect(service.create).toBeDefined();
|
||||
it('should check policy to allow creating a health monitor', function() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
expect(service.allowed()).toBe(true);
|
||||
expect(policy.ifAllowed)
|
||||
.toHaveBeenCalledWith({rules: [['neutron', 'create_health_monitor']]});
|
||||
});
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
expect(service.create.allowed).toBeDefined();
|
||||
expect(service.create.perform).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow creating a health monitor under an ACTIVE load balancer', function() {
|
||||
loadBalancerState.resolve();
|
||||
init('active', '1', loadBalancerState.promise);
|
||||
expect(allowed({})).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow creating a health monitor under a NON-ACTIVE load balancer', function() {
|
||||
loadBalancerState.reject();
|
||||
init('non-active', '1', loadBalancerState.promise);
|
||||
expect(allowed({})).toBe(false);
|
||||
});
|
||||
|
||||
it('should not allow creating a health monitor if one already exists', function() {
|
||||
loadBalancerState.resolve();
|
||||
init('active', '1', loadBalancerState.promise);
|
||||
expect(allowed({ health_monitor_id: '1234' })).toBe(false);
|
||||
});
|
||||
|
||||
it('should redirect after create', function() {
|
||||
loadBalancerState.resolve();
|
||||
spyOn($location, 'path').and.callThrough();
|
||||
init('loadbalancer1', 'listener1', loadBalancerState.promise).create.allowed({id: 'pool1'});
|
||||
service.create.perform();
|
||||
expect($location.path).toHaveBeenCalledWith(
|
||||
'project/load_balancer/loadbalancer1/listeners/listener1/pools/pool1/' +
|
||||
'healthmonitors/healthmonitor1');
|
||||
it('should handle the action result properly', function() {
|
||||
var result = service.handle({data: {id: 1}});
|
||||
expect(result.created[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -32,6 +32,7 @@
|
||||
$scope, $routeParams, model, workflowService, gettext
|
||||
) {
|
||||
var loadbalancerId = $routeParams.loadbalancerId;
|
||||
var poolId = $routeParams.poolId;
|
||||
var scope = $scope;
|
||||
scope.model = model;
|
||||
scope.submit = scope.model.submit;
|
||||
@ -40,7 +41,7 @@
|
||||
'fa fa-cloud-download',
|
||||
['monitor']
|
||||
);
|
||||
scope.model.initialize('monitor', false, loadbalancerId, scope.launchContext.id);
|
||||
scope.model.initialize('monitor', false, loadbalancerId, poolId);
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -21,9 +22,9 @@
|
||||
.factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete', deleteService);
|
||||
|
||||
deleteService.$inject = [
|
||||
'$q',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'$location',
|
||||
'$route',
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
@ -33,24 +34,27 @@
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.healthmonitors.actions.deleteService
|
||||
*
|
||||
* @description
|
||||
* Brings up the delete health monitor confirmation modal dialog.
|
||||
* On submit, deletes selected health monitor.
|
||||
* On cancel, does nothing.
|
||||
* @param $q The angular service for promises.
|
||||
*
|
||||
* @param resourceType The health monitor resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param $location The angular $location service.
|
||||
* @param $route The angular $route service.
|
||||
* @param deleteModal The horizon delete modal service.
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns The health monitor delete service.
|
||||
*/
|
||||
|
||||
function deleteService(
|
||||
$q, $location, $route, deleteModal, api, policy, gettext
|
||||
resourceType, actionResultService, $location, deleteModal, api, policy, gettext
|
||||
) {
|
||||
var loadbalancerId, listenerId, poolId, statePromise;
|
||||
var loadbalancerId, listenerId, poolId;
|
||||
var context = {
|
||||
labels: {
|
||||
title: gettext('Confirm Delete Health Monitor'),
|
||||
@ -68,50 +72,51 @@
|
||||
var service = {
|
||||
perform: perform,
|
||||
allowed: allowed,
|
||||
init: init
|
||||
deleteResult: deleteResult // exposed just for testing
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function init(_loadbalancerId_, _listenerId_, _poolId_, _statePromise_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
listenerId = _listenerId_;
|
||||
poolId = _poolId_;
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
}
|
||||
|
||||
function perform(item) {
|
||||
deleteModal.open({ $emit: actionComplete }, [item], context);
|
||||
}
|
||||
|
||||
function allowed(/*item*/) {
|
||||
return $q.all([
|
||||
statePromise,
|
||||
// This rule is made up and should therefore always pass. I assume at some point there
|
||||
// will be a valid rule similar to this that we will want to use.
|
||||
policy.ifAllowed({ rules: [['neutron', 'delete_health_monitor']] })
|
||||
]);
|
||||
// This rule is made up and should therefore always pass. I assume at some point there
|
||||
// will be a valid rule similar to this that we will want to use.
|
||||
return policy.ifAllowed({ rules: [['neutron', 'delete_health_monitor']] });
|
||||
}
|
||||
|
||||
function deleteItem(id) {
|
||||
return api.deleteHealthMonitor(id, true);
|
||||
function perform(items, scope) {
|
||||
var healthMonitors = angular.isArray(items) ? items : [items];
|
||||
healthMonitors.map(function(item) {
|
||||
loadbalancerId = item.loadbalancerId;
|
||||
listenerId = item.listenerId;
|
||||
poolId = item.poolId;
|
||||
});
|
||||
return deleteModal.open(scope, healthMonitors, context).then(deleteResult);
|
||||
}
|
||||
|
||||
function actionComplete(eventType) {
|
||||
if (eventType === context.failedEvent) {
|
||||
// Error, reload page
|
||||
$route.reload();
|
||||
} else {
|
||||
// Success, go back to pool details page
|
||||
function deleteResult(deleteModalResult) {
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
var actionResult = actionResultService.getActionResult();
|
||||
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||
actionResult.deleted(resourceType, item.context.id);
|
||||
});
|
||||
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||
actionResult.failed(resourceType, item.context.id);
|
||||
});
|
||||
|
||||
if (actionResult.result.failed.length === 0 && actionResult.result.deleted.length > 0) {
|
||||
var path = 'project/load_balancer/' + loadbalancerId +
|
||||
'/listeners/' + listenerId +
|
||||
'/pools/' + poolId;
|
||||
$location.path(path);
|
||||
}
|
||||
return actionResult.result;
|
||||
}
|
||||
|
||||
function deleteItem(id) {
|
||||
return api.deleteHealthMonitor(id, true);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -17,140 +18,87 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Health Monitor Delete Service', function() {
|
||||
var service, policy, modal, lbaasv2Api, $scope, $location, $q, toast, monitor;
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(makePromise());
|
||||
var promise = service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
$scope.$apply();
|
||||
expect(policy.ifAllowed)
|
||||
.toHaveBeenCalledWith({rules: [['neutron', 'delete_health_monitor']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
function makePromise(reject) {
|
||||
var def = $q.defer();
|
||||
def[reject ? 'reject' : 'resolve']();
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
function isActionable(id) {
|
||||
if (id === 'active') {
|
||||
return $q.when();
|
||||
} else {
|
||||
return $q.reject();
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
beforeEach(module('horizon.framework'));
|
||||
|
||||
beforeEach(function() {
|
||||
monitor = { id: '1', name: 'HealthMonitor1' };
|
||||
});
|
||||
var deleteModalService, service, lbaasv2API, policyAPI, $location;
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: makePromise()
|
||||
};
|
||||
}
|
||||
});
|
||||
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
|
||||
deleteHealthMonitor: function() {
|
||||
return makePromise();
|
||||
}
|
||||
});
|
||||
$provide.value('$location', {
|
||||
path: function() {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
modal = $injector.get('horizon.framework.widgets.modal.deleteModalService');
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$location = $injector.get('$location');
|
||||
$q = $injector.get('$q');
|
||||
toast = $injector.get('horizon.framework.widgets.toast.service');
|
||||
beforeEach(inject(function($injector) {
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete');
|
||||
service.init('1', '2', '3', isActionable('active'));
|
||||
$scope.$apply();
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
deleteModalService = $injector.get('horizon.framework.widgets.modal.deleteModalService');
|
||||
policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
$location = $injector.get('$location');
|
||||
}));
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
expect(service.allowed).toBeDefined();
|
||||
expect(service.perform).toBeDefined();
|
||||
describe('perform method', function() {
|
||||
beforeEach(function () {
|
||||
// just need for this to return something that looks like a promise but does nothing
|
||||
spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop});
|
||||
});
|
||||
|
||||
it('should open the modal with correct label', function () {
|
||||
service.perform({name: 'spam'});
|
||||
var labels = deleteModalService.open.calls.argsFor(0)[2].labels;
|
||||
expect(deleteModalService.open).toHaveBeenCalled();
|
||||
angular.forEach(labels, function eachLabel(label) {
|
||||
expect(label.toLowerCase()).toContain('health monitor');
|
||||
});
|
||||
});
|
||||
|
||||
it('should open the delete modal with correct entities', function () {
|
||||
service.perform([{name: 'one'}, {name: 'two'}]);
|
||||
var entities = deleteModalService.open.calls.argsFor(0)[1];
|
||||
expect(deleteModalService.open).toHaveBeenCalled();
|
||||
expect(entities.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should pass in a function that deletes a health monitor', function () {
|
||||
spyOn(lbaasv2API, 'deleteHealthMonitor').and.callFake(angular.noop);
|
||||
service.perform({id: 1, name: 'one'});
|
||||
var contextArg = deleteModalService.open.calls.argsFor(0)[2];
|
||||
var deleteFunction = contextArg.deleteEntity;
|
||||
deleteFunction(1);
|
||||
expect(lbaasv2API.deleteHealthMonitor).toHaveBeenCalledWith(1, true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow deleting health monitor from load balancer in ACTIVE state', function() {
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow deleting health monitor from load balancer in PENDING state', function() {
|
||||
service.init('1', '2', '3', isActionable('pending'));
|
||||
expect(allowed()).toBe(false);
|
||||
});
|
||||
|
||||
it('should open the delete modal', function() {
|
||||
spyOn(modal, 'open');
|
||||
service.perform(monitor);
|
||||
$scope.$apply();
|
||||
expect(modal.open.calls.count()).toBe(1);
|
||||
var args = modal.open.calls.argsFor(0);
|
||||
expect(args.length).toBe(3);
|
||||
expect(args[0]).toEqual({ $emit: jasmine.any(Function) });
|
||||
expect(args[1]).toEqual([monitor]);
|
||||
expect(args[2]).toEqual(jasmine.objectContaining({
|
||||
labels: jasmine.any(Object),
|
||||
deleteEntity: jasmine.any(Function)
|
||||
}));
|
||||
expect(args[2].labels.title).toBe('Confirm Delete Health Monitor');
|
||||
});
|
||||
|
||||
it('should pass function to modal that deletes the health monitor', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteHealthMonitor').and.callThrough();
|
||||
service.perform(monitor);
|
||||
$scope.$apply();
|
||||
expect(lbaasv2Api.deleteHealthMonitor.calls.count()).toBe(1);
|
||||
expect(lbaasv2Api.deleteHealthMonitor).toHaveBeenCalledWith('1', true);
|
||||
});
|
||||
|
||||
it('should show message if any items fail to be deleted', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteHealthMonitor').and.returnValue(makePromise(true));
|
||||
spyOn(toast, 'add');
|
||||
service.perform(monitor);
|
||||
$scope.$apply();
|
||||
expect(modal.open).toHaveBeenCalled();
|
||||
expect(lbaasv2Api.deleteHealthMonitor.calls.count()).toBe(1);
|
||||
expect(toast.add).toHaveBeenCalledWith('error', 'The following health monitor could not ' +
|
||||
'be deleted: HealthMonitor1.');
|
||||
});
|
||||
|
||||
it('should return to pool details after delete', function() {
|
||||
var path = 'project/load_balancer/1/listeners/2/pools/3';
|
||||
it('should handle the action result properly', function() {
|
||||
spyOn($location, 'path');
|
||||
spyOn(toast, 'add');
|
||||
service.perform(monitor);
|
||||
$scope.$apply();
|
||||
spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop});
|
||||
spyOn(lbaasv2API, 'deleteHealthMonitor').and.callFake(angular.noop);
|
||||
service.perform({loadbalancerId: 1, listenerId: 2, poolId: 3, id: 1, name: 'one'});
|
||||
var result = service.deleteResult({
|
||||
fail: [],
|
||||
pass: [{
|
||||
context: {
|
||||
id: 1
|
||||
}
|
||||
}]
|
||||
});
|
||||
var path = 'project/load_balancer/1/listeners/2/pools/3';
|
||||
expect($location.path).toHaveBeenCalledWith(path);
|
||||
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted health monitor: HealthMonitor1.');
|
||||
expect(result.deleted[0].id).toBe(1);
|
||||
result = service.deleteResult({
|
||||
pass: [],
|
||||
fail: [{
|
||||
context: {
|
||||
id: 1
|
||||
}
|
||||
}]
|
||||
});
|
||||
expect(result.failed[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
describe('allow method', function() {
|
||||
it('should use default policy if batch action', function () {
|
||||
spyOn(policyAPI, 'ifAllowed');
|
||||
service.allowed();
|
||||
expect(policyAPI.ifAllowed).toHaveBeenCalled();
|
||||
});
|
||||
}); // end of allowed
|
||||
|
||||
}); // end of delete
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -21,8 +22,8 @@
|
||||
.factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit', editService);
|
||||
|
||||
editService.$inject = [
|
||||
'$q',
|
||||
'$route',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
@ -31,50 +32,36 @@
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.healthmonitors.actions.editService
|
||||
*
|
||||
* @description
|
||||
* Provides the service for editing a health monitor resource.
|
||||
* @param $q The angular service for promises.
|
||||
* @param $route The angular $route service.
|
||||
*
|
||||
* @param resourceType The health monitor resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns The health monitor edit service.
|
||||
*/
|
||||
|
||||
function editService($q, $route, workflowModal, policy, gettext) {
|
||||
var statePromise;
|
||||
function editService(resourceType, actionResultService, workflowModal, policy, gettext) {
|
||||
|
||||
var edit = workflowModal.init({
|
||||
return workflowModal.init({
|
||||
controller: 'EditHealthMonitorWizardController',
|
||||
message: gettext('The health monitor has been updated.'),
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
var service = {
|
||||
init: init,
|
||||
edit: edit
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function init(_statePromise_) {
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
}
|
||||
|
||||
function allowed(/*healthmonitor*/) {
|
||||
return $q.all([
|
||||
statePromise,
|
||||
policy.ifAllowed({ rules: [['neutron', 'update_health_monitor']] })
|
||||
]);
|
||||
return policy.ifAllowed({ rules: [['neutron', 'update_health_monitor']] });
|
||||
}
|
||||
|
||||
function handle(/*response*/) {
|
||||
$route.reload();
|
||||
function handle(response) {
|
||||
return actionResultService.getActionResult()
|
||||
.updated(resourceType, response.config.data.monitor.id)
|
||||
.result;
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -17,81 +18,25 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Edit Health Monitor Action Service', function() {
|
||||
var scope, $q, $route, policy, init, service, loadBalancerState;
|
||||
var policy, service;
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = service.edit.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith(
|
||||
{rules: [['neutron', 'update_health_monitor']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func({ data: { id: 'healthmonitor1' } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
$q = $injector.get('$q');
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
$route = $injector.get('$route');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit');
|
||||
init = service.init;
|
||||
loadBalancerState = $q.defer();
|
||||
}));
|
||||
|
||||
it('should define the correct service properties', function() {
|
||||
expect(service.init).toBeDefined();
|
||||
expect(service.edit).toBeDefined();
|
||||
it('should check policy to allow editing a health monitor', function() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
expect(service.allowed()).toBe(true);
|
||||
expect(policy.ifAllowed)
|
||||
.toHaveBeenCalledWith({rules: [['neutron', 'update_health_monitor']]});
|
||||
});
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
expect(service.edit.allowed).toBeDefined();
|
||||
expect(service.edit.perform).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow edit a health monitor under an ACTIVE load balancer', function() {
|
||||
loadBalancerState.resolve();
|
||||
init(loadBalancerState.promise);
|
||||
expect(allowed({})).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow editing a health monitor under a NON-ACTIVE load balancer', function() {
|
||||
loadBalancerState.reject();
|
||||
init(loadBalancerState.promise);
|
||||
expect(allowed({})).toBe(false);
|
||||
});
|
||||
|
||||
it('should reload page after edit', function() {
|
||||
loadBalancerState.resolve();
|
||||
spyOn($route, 'reload');
|
||||
init(loadBalancerState.promise).edit.allowed({});
|
||||
service.edit.perform();
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
it('should handle the action result properly', function() {
|
||||
var result = service.handle({config: {data: {monitor: {id: 1}}}});
|
||||
expect(result.updated[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,81 +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.healthmonitors')
|
||||
.factory('horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions',
|
||||
rowActions);
|
||||
|
||||
rowActions.$inject = [
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the health monitor row actions.
|
||||
*
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param editService The LBaaS v2 health monitor edit service.
|
||||
* @param deleteService The LBaaS v2 health monitor delete service.
|
||||
* @returns Health monitor row actions service object.
|
||||
*/
|
||||
|
||||
function rowActions(gettext, loadBalancersService, editService, deleteService) {
|
||||
var loadBalancerIsActionable, loadbalancerId, listenerId, poolId;
|
||||
|
||||
var service = {
|
||||
actions: actions,
|
||||
init: init
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function init(_loadbalancerId_, _listenerId_, _poolId_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
listenerId = _listenerId_;
|
||||
poolId = _poolId_;
|
||||
loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId);
|
||||
return service;
|
||||
}
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: editService.init(loadBalancerIsActionable).edit,
|
||||
template: {
|
||||
text: gettext('Edit')
|
||||
}
|
||||
},{
|
||||
service: deleteService.init(loadbalancerId, listenerId, poolId, loadBalancerIsActionable),
|
||||
template: {
|
||||
text: gettext('Delete Health Monitor'),
|
||||
type: 'delete'
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -1,51 +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('LBaaS v2 Health Monitor Row Actions Service', function() {
|
||||
var actions;
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
var rowActionsService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions');
|
||||
actions = rowActionsService.init('1', '2', '3').actions();
|
||||
var loadbalancerService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service');
|
||||
spyOn(loadbalancerService, 'isActionable').and.returnValue(true);
|
||||
}));
|
||||
|
||||
it('should define correct table row actions', function() {
|
||||
expect(actions.length).toBe(2);
|
||||
expect(actions[0].template.text).toBe('Edit');
|
||||
expect(actions[1].template.text).toBe('Delete Health Monitor');
|
||||
});
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
actions.forEach(function(action) {
|
||||
expect(action.service.allowed).toBeDefined();
|
||||
expect(action.service.perform).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,100 +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.healthmonitors')
|
||||
.controller('HealthMonitorDetailController', HealthMonitorDetailController);
|
||||
|
||||
HealthMonitorDetailController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.rowActions',
|
||||
'$routeParams',
|
||||
'$q'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name HealthMonitorDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 health monitor detail page.
|
||||
*
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param rowActions The LBaaS v2 health monitor row actions service.
|
||||
* @param $routeParams The angular $routeParams service.
|
||||
* @param $q The angular service for promises.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function HealthMonitorDetailController(api, rowActions, $routeParams, $q) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
ctrl.actions = rowActions.init($routeParams.loadbalancerId,
|
||||
$routeParams.listenerId,
|
||||
$routeParams.poolId).actions;
|
||||
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
ctrl.healthmonitor = null;
|
||||
ctrl.pool = null;
|
||||
ctrl.listener = null;
|
||||
ctrl.loadbalancer = null;
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
$q.all([
|
||||
api.getHealthMonitor($routeParams.healthmonitorId)
|
||||
.then(success('healthmonitor'), fail('healthmonitor')),
|
||||
api.getPool($routeParams.poolId)
|
||||
.then(success('pool'), fail('pool')),
|
||||
api.getListener($routeParams.listenerId)
|
||||
.then(success('listener'), fail('listener')),
|
||||
api.getLoadBalancer($routeParams.loadbalancerId)
|
||||
.then(success('loadbalancer'), fail('loadbalancer'))
|
||||
]).then(postInit, initError);
|
||||
}
|
||||
|
||||
function success(property) {
|
||||
return angular.bind(null, function setProp(property, response) {
|
||||
ctrl[property] = response.data;
|
||||
}, property);
|
||||
}
|
||||
|
||||
function fail(property) {
|
||||
return angular.bind(null, function setProp(property, error) {
|
||||
ctrl[property] = null;
|
||||
throw error;
|
||||
}, property);
|
||||
}
|
||||
|
||||
function postInit() {
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
function initError() {
|
||||
ctrl.loading = false;
|
||||
ctrl.error = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -1,111 +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('LBaaS v2 Healthmonitor Detail Controller', function() {
|
||||
var lbaasv2API, $controller, apiFail, qAllFail;
|
||||
|
||||
function fakePromise(data, reject) {
|
||||
return {
|
||||
then: function(success, fail) {
|
||||
if (reject) {
|
||||
fail();
|
||||
} else {
|
||||
success({ data: data });
|
||||
}
|
||||
return fakePromise();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fakeAPI() {
|
||||
return fakePromise('foo', apiFail);
|
||||
}
|
||||
|
||||
function loadbalancerAPI() {
|
||||
return fakePromise({ provisioning_status: 'ACTIVE' });
|
||||
}
|
||||
|
||||
function qAll() {
|
||||
return fakePromise(null, qAllFail);
|
||||
}
|
||||
|
||||
function createController() {
|
||||
return $controller('HealthMonitorDetailController', {
|
||||
$routeParams: {
|
||||
loadbalancerId: 'loadbalancerId',
|
||||
listenerId: 'listenerId',
|
||||
poolId: 'poolId',
|
||||
healthmonitorId: 'healthmonitorId'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
apiFail = false;
|
||||
qAllFail = false;
|
||||
|
||||
$provide.value('$q', { all: qAll });
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getHealthMonitor').and.callFake(fakeAPI);
|
||||
spyOn(lbaasv2API, 'getPool').and.callFake(fakeAPI);
|
||||
spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI);
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
$controller = $injector.get('$controller');
|
||||
}));
|
||||
|
||||
it('should invoke lbaasv2 apis', function() {
|
||||
var ctrl = createController();
|
||||
expect(lbaasv2API.getHealthMonitor).toHaveBeenCalledWith('healthmonitorId');
|
||||
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
|
||||
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
|
||||
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId');
|
||||
expect(ctrl.loadbalancer).toEqual({ provisioning_status: 'ACTIVE' });
|
||||
expect(ctrl.listener).toBe('foo');
|
||||
expect(ctrl.pool).toBe('foo');
|
||||
expect(ctrl.healthmonitor).toBe('foo');
|
||||
});
|
||||
|
||||
it('should throw error on API fail', function() {
|
||||
apiFail = true;
|
||||
var init = function() {
|
||||
createController();
|
||||
};
|
||||
expect(init).toThrow();
|
||||
});
|
||||
|
||||
it('should set error state if any APIs fail', function() {
|
||||
qAllFail = true;
|
||||
var ctrl = createController();
|
||||
expect(ctrl.loading).toBe(false);
|
||||
expect(ctrl.error).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -1,48 +0,0 @@
|
||||
<div ng-controller="HealthMonitorDetailController as ctrl">
|
||||
<detail-status loading="ctrl.loading" error="ctrl.error"></detail-status>
|
||||
<div ng-if="!ctrl.loading && !ctrl.error">
|
||||
<div class="page-header">
|
||||
<actions allowed="ctrl.actions" type="row" item="ctrl.healthmonitor"
|
||||
ng-if="ctrl.healthmonitor" class="actions_column pull-right"></actions>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}">{$ ::(ctrl.loadbalancer.name || ctrl.loadbalancer.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}">{$ ::(ctrl.listener.name || ctrl.listener.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}/pools/{$ ::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="row">
|
||||
<div class="col-md-6 detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt translate>Type</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.type $}</dd>
|
||||
<dt translate>Delay</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.delay $}</dd>
|
||||
<dt translate>Max Retries</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.max_retries $}</dd>
|
||||
<dt translate>Max Retries Down</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.max_retries_down $}</dd>
|
||||
<dt translate>Timeout</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.timeout $}</dd>
|
||||
<dt translate ng-if="::ctrl.healthmonitor.http_method">HTTP Method</dt>
|
||||
<dd ng-if="::ctrl.healthmonitor.http_method">{$ ::ctrl.healthmonitor.http_method $}</dd>
|
||||
<dt translate ng-if="::ctrl.healthmonitor.expected_codes">Expected Codes</dt>
|
||||
<dd ng-if="::ctrl.healthmonitor.expected_codes">{$ ::ctrl.healthmonitor.expected_codes $}</dd>
|
||||
<dt translate ng-if="::ctrl.healthmonitor.url_path">URL Path</dt>
|
||||
<dd ng-if="::ctrl.healthmonitor.url_path">{$ ::ctrl.healthmonitor.url_path $}</dd>
|
||||
<dt translate>Admin State Up</dt>
|
||||
<dd>{$ ctrl.healthmonitor.admin_state_up | yesno $}</dd>
|
||||
<dt translate>Monitor ID</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.id $}</dd>
|
||||
<dt translate>Project ID</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.project_id $}</dd>
|
||||
<dt translate>Created At</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.created_at $}</dd>
|
||||
<dt translate>Updated At</dt>
|
||||
<dd>{$ ::ctrl.healthmonitor.updated_at $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.healthmonitors')
|
||||
.controller('HealthMonitorDetailController', HealthMonitorDetailController);
|
||||
|
||||
HealthMonitorDetailController.$inject = [
|
||||
'loadbalancer',
|
||||
'listener',
|
||||
'pool',
|
||||
'healthmonitor',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.resourceType',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service',
|
||||
'$q'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name HealthMonitorDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 health monitor detail page.
|
||||
*
|
||||
* @param loadbalancer The loadbalancer object.
|
||||
* @param listener The listener object.
|
||||
* @param pool The pool object.
|
||||
* @param healthmonitor The health monitor object.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param resourceType The health monitor resource type.
|
||||
* @param typeRegistry The horizon resource type registry service.
|
||||
* @param spinnerService The horizon modal wait spinner service.
|
||||
* @param $q The angular service for promises.
|
||||
*
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function HealthMonitorDetailController(
|
||||
loadbalancer, listener, pool, healthmonitor, loadBalancersService,
|
||||
resourceType, typeRegistry, spinnerService, $q
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
ctrl.loadbalancer = loadbalancer;
|
||||
ctrl.listener = listener;
|
||||
ctrl.pool = pool;
|
||||
ctrl.healthmonitor = healthmonitor;
|
||||
ctrl.resourceType = typeRegistry.getResourceType(resourceType);
|
||||
ctrl.context = {};
|
||||
ctrl.context.identifier = ctrl.resourceType.parsePath(ctrl.healthmonitor.id);
|
||||
|
||||
ctrl.resultHandler = actionResultHandler;
|
||||
|
||||
function actionResultHandler(returnValue) {
|
||||
return $q.when(returnValue, actionSuccessHandler);
|
||||
}
|
||||
|
||||
function loadData(response) {
|
||||
spinnerService.hideModalSpinner();
|
||||
ctrl.showDetails = true;
|
||||
ctrl.resourceType.initActions();
|
||||
ctrl.healthmonitor = response.data;
|
||||
ctrl.healthmonitor.loadbalancerId = ctrl.loadbalancer.id;
|
||||
ctrl.healthmonitor.listenerId = ctrl.listener.id;
|
||||
ctrl.healthmonitor.poolId = ctrl.pool.id;
|
||||
}
|
||||
|
||||
function actionSuccessHandler(result) {
|
||||
// The action has completed (for whatever "complete" means to that
|
||||
// action. Notice the view doesn't really need to know the semantics of the
|
||||
// particular action because the actions return data in a standard form.
|
||||
// That return includes the id and type of each created, updated, deleted
|
||||
// and failed item.
|
||||
// Currently just refreshes the display each time.
|
||||
if (result) {
|
||||
spinnerService.showModalSpinner(gettext('Please Wait'));
|
||||
ctrl.showDetails = false;
|
||||
ctrl.context.loadPromise = ctrl.resourceType.load(ctrl.context.identifier);
|
||||
ctrl.context.loadPromise.then(loadData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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('LBaaS v2 HealthMonitor Detail Controller', function() {
|
||||
var deferred, service, ctrl, scope, $timeout, $q, actionResultService;
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($controller, $rootScope, _$q_, _$timeout_) {
|
||||
$q = _$q_;
|
||||
deferred = $q.defer();
|
||||
service = {
|
||||
getResourceType: function() {
|
||||
return {
|
||||
load: function() { return deferred.promise; },
|
||||
parsePath: function() { return 'my-context'; },
|
||||
itemName: function() { return 'A name'; },
|
||||
initActions: angular.noop
|
||||
};
|
||||
},
|
||||
getDefaultDetailsTemplateUrl: angular.noop
|
||||
};
|
||||
actionResultService = {
|
||||
getIdsOfType: function() { return []; }
|
||||
};
|
||||
$timeout = _$timeout_;
|
||||
scope = $rootScope.$new();
|
||||
ctrl = $controller('HealthMonitorDetailController', {
|
||||
$scope: scope,
|
||||
loadbalancer: { id: '123' },
|
||||
listener: { id: '123' },
|
||||
pool: { id: '123' },
|
||||
healthmonitor: { id: '123' },
|
||||
'horizon.framework.conf.resource-type-registry.service': service,
|
||||
'horizon.framework.util.actions.action-result.service': actionResultService,
|
||||
'horizon.framework.widgets.modal-wait-spinner.service': {
|
||||
showModalSpinner: angular.noop,
|
||||
hideModalSpinner: angular.noop
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
it('should create a controller', function() {
|
||||
expect(ctrl).toBeDefined();
|
||||
expect(ctrl.loadbalancer).toBeDefined();
|
||||
expect(ctrl.listener).toBeDefined();
|
||||
expect(ctrl.pool).toBeDefined();
|
||||
expect(ctrl.healthmonitor).toBeDefined();
|
||||
});
|
||||
|
||||
describe('resultHandler', function() {
|
||||
|
||||
it('handles empty results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve({});
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles falsy results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve(false);
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles matched results', function() {
|
||||
spyOn(actionResultService, 'getIdsOfType').and.returnValue([1, 2, 3]);
|
||||
var result = $q.defer();
|
||||
result.resolve({some: 'thing'});
|
||||
ctrl.resultHandler(result.promise);
|
||||
deferred.resolve({data: {some: 'data'}});
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
})();
|
@ -0,0 +1,53 @@
|
||||
<div class="page-header">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}">{$ ::(ctrl.loadbalancer.name || ctrl.loadbalancer.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}">{$ ::(ctrl.listener.name || ctrl.listener.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}/pools/{$ ::ctrl.pool.id $}">{$ ::(ctrl.pool.name || ctrl.pool.id) $}</a></li>
|
||||
<li class="active">{$ ::(ctrl.healthmonitor.name || ctrl.healthmonitor.id) $}</li>
|
||||
</ol>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-9 text-left">
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<strong translate>Type</strong>
|
||||
{$ ::ctrl.healthmonitor.type $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Operating Status</strong>
|
||||
{$ ctrl.healthmonitor.operating_status | decode:ctrl.operatingStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Provisioning Status</strong>
|
||||
{$ ctrl.healthmonitor.provisioning_status | decode:ctrl.provisioningStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Admin State Up</strong>
|
||||
{$ ctrl.healthmonitor.admin_state_up | yesno $}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-3 text-right details-item-actions">
|
||||
<actions allowed="ctrl.resourceType.itemActions"
|
||||
type="row"
|
||||
item="ctrl.healthmonitor"
|
||||
ng-if="ctrl.healthmonitor"
|
||||
class="actions_column pull-right"
|
||||
result-handler="ctrl.resultHandler"></actions>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::HealthMonitor"
|
||||
cls="dl-horizontal"
|
||||
item="ctrl.healthmonitor"
|
||||
property-groups="[[
|
||||
'id', 'name', 'project_id', 'created_at', 'updated_at',
|
||||
'delay', 'timeout', 'max_retries', 'max_retries_down',
|
||||
'http_method', 'url_path', 'expected_codes']]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,10 @@
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::HealthMonitor"
|
||||
item="item"
|
||||
property-groups="[
|
||||
['name', 'id', 'project_id'],
|
||||
['created_at', 'updated_at'],
|
||||
['type', 'delay', 'timeout'],
|
||||
['max_retries', 'max_retries_down'],
|
||||
['http_method', 'url_path', 'expected_codes']]">
|
||||
</hz-resource-property-list>
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -26,6 +27,138 @@
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.healthmonitors', []);
|
||||
.module('horizon.dashboard.project.lbaasv2.healthmonitors', [])
|
||||
.constant('horizon.dashboard.project.lbaasv2.healthmonitors.resourceType',
|
||||
'OS::Octavia::HealthMonitor')
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.dashboard.project.lbaasv2.basePath',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.create',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.edit',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.actions.delete',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors.resourceType'
|
||||
];
|
||||
|
||||
function run(
|
||||
registry,
|
||||
basePath,
|
||||
loadBalancerService,
|
||||
createService,
|
||||
editService,
|
||||
deleteService,
|
||||
resourceType
|
||||
) {
|
||||
var healthMonitorResourceType = registry.getResourceType(resourceType);
|
||||
|
||||
healthMonitorResourceType
|
||||
.setNames(gettext('Health Monitor'), gettext('Health Monitors'))
|
||||
.setSummaryTemplateUrl(basePath + 'healthmonitors/details/drawer.html')
|
||||
.setProperties(healthMonitorProperties(loadBalancerService))
|
||||
.setListFunction(loadBalancerService.getHealthMonitorsPromise)
|
||||
.setLoadFunction(loadBalancerService.getHealthMonitorPromise)
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
urlFunction: loadBalancerService.getHealthMonitorDetailsPath
|
||||
})
|
||||
.append({
|
||||
id: 'type',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'operating_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'provisioning_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'admin_state_up',
|
||||
priority: 1
|
||||
});
|
||||
|
||||
healthMonitorResourceType.itemActions
|
||||
.append({
|
||||
id: 'healthMonitorEdit',
|
||||
service: editService,
|
||||
template: {
|
||||
text: gettext('Edit Health Monitor')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'healthMonitorDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Health Monitor'),
|
||||
type: 'delete'
|
||||
}
|
||||
});
|
||||
|
||||
healthMonitorResourceType.globalActions
|
||||
.append({
|
||||
id: 'healthMonitorCreate',
|
||||
service: createService,
|
||||
template: {
|
||||
type: 'create',
|
||||
text: gettext('Create Health Monitor')
|
||||
}
|
||||
});
|
||||
|
||||
healthMonitorResourceType.batchActions
|
||||
.append({
|
||||
id: 'healthMonitorBatchDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Health Monitors'),
|
||||
type: 'delete-selected'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function healthMonitorProperties(loadBalancerService) {
|
||||
return {
|
||||
id: gettext('ID'),
|
||||
name: {
|
||||
label: gettext('Name'),
|
||||
filters: ['noName']
|
||||
},
|
||||
provisioning_status: {
|
||||
label: gettext('Provisioning Status'),
|
||||
values: loadBalancerService.provisioningStatus
|
||||
},
|
||||
operating_status: {
|
||||
label: gettext('Operating Status'),
|
||||
values: loadBalancerService.operatingStatus
|
||||
},
|
||||
admin_state_up: {
|
||||
label: gettext('Admin State Up'),
|
||||
filters: ['yesno']
|
||||
},
|
||||
type: gettext('Type'),
|
||||
delay: gettext('Delay'),
|
||||
timeout: gettext('Timeout'),
|
||||
max_retries: gettext('Max Retries'),
|
||||
max_retries_down: gettext('Max Retries Down'),
|
||||
http_method: gettext('HTTP Method'),
|
||||
url_path: gettext('URL Path'),
|
||||
expected_codes: gettext('Expected Codes'),
|
||||
project_id: gettext('Project ID'),
|
||||
created_at: {
|
||||
label: gettext('Created At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
updated_at: {
|
||||
label: gettext('Updated At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
pools: gettext('Pools')
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -22,4 +23,46 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('LBaaS v2 Healthmonitors Registry', function () {
|
||||
var registry, resourceType;
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
resourceType = $injector.get('horizon.dashboard.project.lbaasv2.healthmonitors.resourceType');
|
||||
registry = $injector.get('horizon.framework.conf.resource-type-registry.service');
|
||||
}));
|
||||
|
||||
it('should define resourceType', function () {
|
||||
expect(resourceType).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register item actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).itemActions;
|
||||
expect(actionHasId(actions, 'healthMonitorEdit')).toBe(true);
|
||||
expect(actionHasId(actions, 'healthMonitorDelete')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register global actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).globalActions;
|
||||
expect(actionHasId(actions, 'healthMonitorCreate')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register batch actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).batchActions;
|
||||
expect(actionHasId(actions, 'healthMonitorBatchDelete')).toBe(true);
|
||||
});
|
||||
|
||||
function actionHasId(list, value) {
|
||||
return list.filter(matchesId).length === 1;
|
||||
|
||||
function matchesId(action) {
|
||||
if (action.id === value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@ -25,12 +26,15 @@
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2', [
|
||||
'ngRoute',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers',
|
||||
'horizon.dashboard.project.lbaasv2.listeners',
|
||||
'horizon.dashboard.project.lbaasv2.pools',
|
||||
'horizon.dashboard.project.lbaasv2.members',
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors'
|
||||
'horizon.dashboard.project.lbaasv2.healthmonitors',
|
||||
'horizon.framework.conf',
|
||||
'horizon.framework.widgets',
|
||||
'horizon.framework.util',
|
||||
'horizon.app.core'
|
||||
])
|
||||
.config(config)
|
||||
.constant('horizon.dashboard.project.lbaasv2.patterns', {
|
||||
@ -45,7 +49,12 @@
|
||||
})
|
||||
.constant('horizon.dashboard.project.lbaasv2.popovers', {
|
||||
ipAddresses: '<ul><li ng-repeat="addr in member.addresses">{$ addr.ip $}</li></ul>'
|
||||
});
|
||||
})
|
||||
.run(['$rootScope', '$location', function ($rootScope, $location) {
|
||||
$rootScope.$on('$routeChangeError', function() {
|
||||
$location.path('project/load_balancer');
|
||||
});
|
||||
}]);
|
||||
|
||||
config.$inject = [
|
||||
'$provide',
|
||||
@ -65,22 +74,212 @@
|
||||
|
||||
$routeProvider
|
||||
.when(loadbalancers, {
|
||||
templateUrl: basePath + 'loadbalancers/table.html'
|
||||
templateUrl: basePath + 'loadbalancers/panel.html'
|
||||
})
|
||||
.when(loadbalancers + '/:loadbalancerId', {
|
||||
templateUrl: basePath + 'loadbalancers/detail.html'
|
||||
templateUrl: basePath + 'loadbalancers/details/detail.html',
|
||||
resolve: {
|
||||
loadbalancer: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getLoadBalancer($route.current.params.loadbalancerId, true).then(
|
||||
function success(response) {
|
||||
response.data.floating_ip_address = response.data.floating_ip.ip;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
]
|
||||
},
|
||||
controller: 'LoadBalancerDetailController',
|
||||
controllerAs: 'ctrl'
|
||||
})
|
||||
.when(listener, {
|
||||
templateUrl: basePath + 'listeners/detail.html'
|
||||
templateUrl: basePath + 'listeners/details/detail.html',
|
||||
resolve: {
|
||||
loadbalancer: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getLoadBalancer($route.current.params.loadbalancerId, true).then(
|
||||
function success(response) {
|
||||
response.data.floating_ip_address = response.data.floating_ip.ip;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
listener: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getListener($route.current.params.listenerId).then(
|
||||
function success(response) {
|
||||
response.data.loadbalancerId = $route.current.params.loadbalancerId;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
]
|
||||
},
|
||||
controller: 'ListenerDetailController',
|
||||
controllerAs: 'ctrl'
|
||||
})
|
||||
.when(pool, {
|
||||
templateUrl: basePath + 'pools/detail.html'
|
||||
templateUrl: basePath + 'pools/details/detail.html',
|
||||
resolve: {
|
||||
loadbalancer: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getLoadBalancer($route.current.params.loadbalancerId, true).then(
|
||||
function success(response) {
|
||||
response.data.floating_ip_address = response.data.floating_ip.ip;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
listener: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getListener($route.current.params.listenerId).then(
|
||||
function success(response) {
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
pool: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getPool($route.current.params.poolId).then(
|
||||
function success(response) {
|
||||
response.data.loadbalancerId = $route.current.params.loadbalancerId;
|
||||
response.data.listenerId = $route.current.params.listenerId;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
]
|
||||
},
|
||||
controller: 'PoolDetailController',
|
||||
controllerAs: 'ctrl'
|
||||
})
|
||||
.when(member, {
|
||||
templateUrl: basePath + 'members/detail.html'
|
||||
templateUrl: basePath + 'members/details/detail.html',
|
||||
resolve: {
|
||||
loadbalancer: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getLoadBalancer($route.current.params.loadbalancerId, true).then(
|
||||
function success(response) {
|
||||
response.data.floating_ip_address = response.data.floating_ip.ip;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
listener: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getListener($route.current.params.listenerId).then(
|
||||
function success(response) {
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
pool: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getPool($route.current.params.poolId).then(
|
||||
function success(response) {
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
member: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getMember($route.current.params.poolId,
|
||||
$route.current.params.memberId).then(
|
||||
function success(response) {
|
||||
response.data.loadbalancerId = $route.current.params.loadbalancerId;
|
||||
response.data.listenerId = $route.current.params.listenerId;
|
||||
response.data.poolId = $route.current.params.poolId;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
]
|
||||
},
|
||||
controller: 'MemberDetailController',
|
||||
controllerAs: 'ctrl'
|
||||
})
|
||||
.when(healthmonitor, {
|
||||
templateUrl: basePath + 'healthmonitors/detail.html'
|
||||
templateUrl: basePath + 'healthmonitors/details/detail.html',
|
||||
resolve: {
|
||||
loadbalancer: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getLoadBalancer($route.current.params.loadbalancerId, true).then(
|
||||
function success(response) {
|
||||
response.data.floating_ip_address = response.data.floating_ip.ip;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
listener: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getListener($route.current.params.listenerId).then(
|
||||
function success(response) {
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
pool: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getPool($route.current.params.poolId).then(
|
||||
function success(response) {
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
healthmonitor: [
|
||||
'$route',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
function($route, api) {
|
||||
return api.getHealthMonitor(
|
||||
$route.current.params.healthmonitorId).then(
|
||||
function success(response) {
|
||||
response.data.loadbalancerId = $route.current.params.loadbalancerId;
|
||||
response.data.listenerId = $route.current.params.listenerId;
|
||||
response.data.poolId = $route.current.params.poolId;
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
]
|
||||
},
|
||||
controller: 'HealthMonitorDetailController',
|
||||
controllerAs: 'ctrl'
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@ -104,43 +105,270 @@
|
||||
inject();
|
||||
});
|
||||
|
||||
it('should route URLs', function () {
|
||||
it('should route to loadbalancer panel', function () {
|
||||
var loadbalancers = '/project/load_balancer';
|
||||
var listener = loadbalancers + '/:loadbalancerId/listeners/:listenerId';
|
||||
var pool = listener + '/pools/:poolId';
|
||||
var member = pool + '/members/:memberId';
|
||||
var healthmonitor = pool + '/healthmonitors/:healthmonitorId';
|
||||
var routes = [[
|
||||
loadbalancers, {
|
||||
templateUrl: basePath + 'loadbalancers/table.html'
|
||||
}
|
||||
], [
|
||||
loadbalancers + '/:loadbalancerId', {
|
||||
templateUrl: basePath + 'loadbalancers/detail.html'
|
||||
}
|
||||
], [
|
||||
listener, {
|
||||
templateUrl: basePath + 'listeners/detail.html'
|
||||
}
|
||||
], [
|
||||
pool, {
|
||||
templateUrl: basePath + 'pools/detail.html'
|
||||
}
|
||||
], [
|
||||
member, {
|
||||
templateUrl: basePath + 'members/detail.html'
|
||||
}
|
||||
], [
|
||||
healthmonitor, {
|
||||
templateUrl: basePath + 'healthmonitors/detail.html'
|
||||
templateUrl: basePath + 'loadbalancers/panel.html'
|
||||
}
|
||||
]];
|
||||
|
||||
expect($routeProvider.when.calls.count()).toBe(6);
|
||||
angular.forEach($routeProvider.when.calls.all(), function(call, i) {
|
||||
expect(call.args).toEqual(routes[i]);
|
||||
routes.forEach(function(route) {
|
||||
expect($routeProvider.when).toHaveBeenCalledWith(route[0], route[1]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should route resolved loadbalancer detail', inject(function($injector) {
|
||||
function loadbalancerAPI() {
|
||||
var loadbalancer = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(loadbalancer);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1, floating_ip: {}}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
inject(function($route, $location, $rootScope, $httpBackend) {
|
||||
$httpBackend.expectGET(
|
||||
'/static/dashboard/project/lbaasv2/loadbalancers/details/detail.html'
|
||||
).respond({});
|
||||
$location.path('/project/load_balancer/1');
|
||||
$rootScope.$digest();
|
||||
expect($route.current).toBeDefined();
|
||||
|
||||
});
|
||||
}));
|
||||
|
||||
it('should route resolved listener detail', inject(function($injector) {
|
||||
function loadbalancerAPI() {
|
||||
var loadbalancer = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(loadbalancer);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1, floating_ip: {}}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function listenerAPI() {
|
||||
var listener = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(listener);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
spyOn(lbaasv2API, 'getListener').and.callFake(listenerAPI);
|
||||
inject(function($route, $location, $rootScope, $httpBackend) {
|
||||
$httpBackend.expectGET(
|
||||
'/static/dashboard/project/lbaasv2/listeners/details/detail.html'
|
||||
).respond({});
|
||||
$location.path('/project/load_balancer/1/listeners/2');
|
||||
$rootScope.$digest();
|
||||
expect($route.current).toBeDefined();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should route resolved pool detail', inject(function($injector) {
|
||||
function loadbalancerAPI() {
|
||||
var loadbalancer = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(loadbalancer);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1, floating_ip: {}}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function listenerAPI() {
|
||||
var listener = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(listener);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function poolAPI() {
|
||||
var pool = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(pool);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
spyOn(lbaasv2API, 'getListener').and.callFake(listenerAPI);
|
||||
spyOn(lbaasv2API, 'getPool').and.callFake(poolAPI);
|
||||
inject(function($route, $location, $rootScope, $httpBackend) {
|
||||
$httpBackend.expectGET(
|
||||
'/static/dashboard/project/lbaasv2/pools/details/detail.html'
|
||||
).respond({});
|
||||
$location.path('/project/load_balancer/1/listeners/2/pools/3');
|
||||
$rootScope.$digest();
|
||||
expect($route.current).toBeDefined();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should route resolved member detail', inject(function($injector) {
|
||||
function loadbalancerAPI() {
|
||||
var loadbalancer = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(loadbalancer);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1, floating_ip: {}}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function listenerAPI() {
|
||||
var listener = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(listener);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function poolAPI() {
|
||||
var pool = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(pool);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function memberAPI() {
|
||||
var member = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(member);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
spyOn(lbaasv2API, 'getListener').and.callFake(listenerAPI);
|
||||
spyOn(lbaasv2API, 'getPool').and.callFake(poolAPI);
|
||||
spyOn(lbaasv2API, 'getMember').and.callFake(memberAPI);
|
||||
inject(function($route, $location, $rootScope, $httpBackend) {
|
||||
$httpBackend.expectGET(
|
||||
'/static/dashboard/project/lbaasv2/members/details/detail.html'
|
||||
).respond({});
|
||||
$location.path('/project/load_balancer/1/listeners/2/pools/3/members/4');
|
||||
$rootScope.$digest();
|
||||
expect($route.current).toBeDefined();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should route resolved health monitor detail', inject(function($injector) {
|
||||
function loadbalancerAPI() {
|
||||
var loadbalancer = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(loadbalancer);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1, floating_ip: {}}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function listenerAPI() {
|
||||
var listener = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(listener);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function poolAPI() {
|
||||
var pool = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(pool);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function healthmonitorAPI() {
|
||||
var healthmonitor = { provisioning_status: 'ACTIVE' };
|
||||
return {
|
||||
success: function(callback) {
|
||||
callback(healthmonitor);
|
||||
},
|
||||
then: function(callback) {
|
||||
callback({ data: { id: 1}});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
spyOn(lbaasv2API, 'getListener').and.callFake(listenerAPI);
|
||||
spyOn(lbaasv2API, 'getPool').and.callFake(poolAPI);
|
||||
spyOn(lbaasv2API, 'getHealthMonitor').and.callFake(healthmonitorAPI);
|
||||
inject(function($route, $location, $rootScope, $httpBackend) {
|
||||
$httpBackend.expectGET(
|
||||
'/static/dashboard/project/lbaasv2/healthmonitors/details/detail.html'
|
||||
).respond({});
|
||||
$location.path('/project/load_balancer/1/listeners/2/pools/3/healthmonitors/4');
|
||||
$rootScope.$digest();
|
||||
expect($route.current).toBeDefined();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should redirect to project home on route change error',
|
||||
inject(function($location, $rootScope) {
|
||||
spyOn($location, 'path').and.callThrough();
|
||||
$rootScope.$emit('$routeChangeError', null, null, null, 'routeChangeError');
|
||||
expect($location.path).toHaveBeenCalledWith('project/load_balancer');
|
||||
})
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@ -74,9 +75,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Progress indicator while data is loading */
|
||||
[table-status],
|
||||
detail-status {
|
||||
/* Progress indicator in the table while items are loading */
|
||||
[table-status] {
|
||||
.progress {
|
||||
margin: 0px auto;
|
||||
width: 25%;
|
||||
@ -86,12 +86,9 @@ detail-status {
|
||||
}
|
||||
}
|
||||
}
|
||||
detail-status {
|
||||
.progress {
|
||||
margin-top: 25vh;
|
||||
}
|
||||
.error-actions {
|
||||
text-align: center;
|
||||
|
||||
.octavia-tabset {
|
||||
.tab-content {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
@ -1,107 +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.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',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.delete'
|
||||
];
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @param deleteService The LBaaS v2 listeners delete service.
|
||||
* @returns Listeners table batch actions service object.
|
||||
*/
|
||||
|
||||
function tableBatchActions(
|
||||
$q, $location, workflowModal, policy, gettext, loadBalancersService, deleteService
|
||||
) {
|
||||
var loadBalancerIsActionable, 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_;
|
||||
loadBalancerIsActionable = loadBalancersService.isActionable(loadBalancerId);
|
||||
return service;
|
||||
}
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: create,
|
||||
template: {
|
||||
type: 'create',
|
||||
text: gettext('Create Listener')
|
||||
}
|
||||
},{
|
||||
service: deleteService.init(loadBalancerId, loadBalancerIsActionable),
|
||||
template: {
|
||||
text: gettext('Delete Listeners'),
|
||||
type: 'delete-selected'
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
function canCreate() {
|
||||
return $q.all([
|
||||
loadBalancerIsActionable,
|
||||
policy.ifAllowed({ rules: [['neutron', 'create_listener']] })
|
||||
]);
|
||||
}
|
||||
|
||||
function onCreate(response) {
|
||||
var id = response.data.id;
|
||||
$location.path('project/load_balancer/' + loadBalancerId + '/listeners/' + id);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -1,105 +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('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'));
|
||||
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('$uibModal', modal);
|
||||
$provide.value('horizon.dashboard.project.lbaasv2.loadbalancers.service', {
|
||||
isActionable: 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(2);
|
||||
expect(actions[0].template.text).toBe('Create Listener');
|
||||
expect(actions[1].template.text).toBe('Delete Listeners');
|
||||
});
|
||||
|
||||
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/load_balancer/1234/listeners/5678');
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.listeners')
|
||||
.factory('horizon.dashboard.project.lbaasv2.listeners.actions.create',
|
||||
createService);
|
||||
|
||||
createService.$inject = [
|
||||
'horizon.dashboard.project.lbaasv2.listeners.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.listeners.actions.batchActions
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Listeners creation.
|
||||
*
|
||||
* @param resourceType The listener resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns Listeners create service object.
|
||||
*/
|
||||
|
||||
function createService(
|
||||
resourceType, actionResultService, workflowModal, policy, gettext
|
||||
) {
|
||||
return workflowModal.init({
|
||||
controller: 'CreateListenerWizardController',
|
||||
message: gettext('A new listener is being created.'),
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
function allowed() {
|
||||
return policy.ifAllowed({ rules: [['neutron', 'create_listener']] });
|
||||
}
|
||||
|
||||
function handle(response) {
|
||||
return actionResultService.getActionResult()
|
||||
.created(resourceType, response.data.id)
|
||||
.result;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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('LBaaS v2 Create Listener Action Service', function() {
|
||||
var policy, service;
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$modal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func({ data: { id: 'listener1' } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.listeners.actions.create');
|
||||
}));
|
||||
|
||||
it('should check policy to allow creating a listener', function() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
expect(service.allowed()).toBe(true);
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'create_listener']]});
|
||||
});
|
||||
|
||||
it('should handle the action result properly', function() {
|
||||
var result = service.handle({data: {id: 1}});
|
||||
expect(result.created[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -21,9 +22,10 @@
|
||||
.factory('horizon.dashboard.project.lbaasv2.listeners.actions.delete', deleteService);
|
||||
|
||||
deleteService.$inject = [
|
||||
'horizon.dashboard.project.lbaasv2.listeners.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'$q',
|
||||
'$location',
|
||||
'$route',
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
@ -35,26 +37,31 @@
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.listeners.actions.deleteService
|
||||
*
|
||||
* @description
|
||||
* Brings up the delete listeners confirmation modal dialog.
|
||||
* On submit, deletes selected listeners.
|
||||
* On cancel, does nothing.
|
||||
*
|
||||
* @param resourceType The listener resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param $q The angular service for promises.
|
||||
* @param $location The angular $location service.
|
||||
* @param $route The angular $route service.
|
||||
* @param deleteModal The horizon delete modal service.
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param toast The horizon message service.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns The listeners table delete service.
|
||||
*
|
||||
* @returns The listeners delete service.
|
||||
*/
|
||||
|
||||
function deleteService(
|
||||
$q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext
|
||||
resourceType, actionResultService, $q, $location,
|
||||
deleteModal, api, policy, toast, qExtensions, gettext
|
||||
) {
|
||||
var loadbalancerId, statePromise;
|
||||
var loadbalancerId, scope;
|
||||
var notAllowedMessage = gettext('The following listeners will not be deleted ' +
|
||||
'due to existing pools: %s.');
|
||||
var context = {
|
||||
@ -74,54 +81,38 @@
|
||||
|
||||
var service = {
|
||||
perform: perform,
|
||||
allowed: allowed,
|
||||
init: init
|
||||
allowed: allowed
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function init(_loadbalancerId_, _statePromise_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
function perform(items, _scope_) {
|
||||
scope = _scope_;
|
||||
var listeners = angular.isArray(items) ? items : [items];
|
||||
listeners.map(function(item) {
|
||||
loadbalancerId = item.loadbalancerId;
|
||||
});
|
||||
return qExtensions.allSettled(listeners.map(checkPermission)).then(afterCheck);
|
||||
}
|
||||
|
||||
function perform(items) {
|
||||
if (angular.isArray(items)) {
|
||||
qExtensions.allSettled(items.map(checkPermission)).then(afterCheck);
|
||||
} else {
|
||||
deleteModal.open({ $emit: actionComplete }, [items], context);
|
||||
}
|
||||
}
|
||||
|
||||
function allowed(item) {
|
||||
var promises = [policy.ifAllowed({ rules: [['neutron', 'delete_listener']] }), statePromise];
|
||||
if (item) {
|
||||
promises.push(qExtensions.booleanAsPromise(!item.default_pool_id));
|
||||
}
|
||||
return $q.all(promises);
|
||||
}
|
||||
|
||||
function deleteItem(id) {
|
||||
return api.deleteListener(id, true);
|
||||
}
|
||||
|
||||
function actionComplete(eventType) {
|
||||
if (eventType === context.failedEvent) {
|
||||
// Action failed, reload the page
|
||||
$route.reload();
|
||||
} else {
|
||||
// If the user is on the listeners table then just reload the page, otherwise they
|
||||
// are on the details page and we return to the table.
|
||||
var regex = new RegExp('project\/load_balancer\/' + loadbalancerId + '(\/)?$');
|
||||
if (regex.test($location.path())) {
|
||||
$route.reload();
|
||||
} else {
|
||||
$location.path('project/load_balancer/' + loadbalancerId);
|
||||
}
|
||||
function deleteResult(deleteModalResult) {
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
var actionResult = actionResultService.getActionResult();
|
||||
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||
actionResult.deleted(resourceType, item.context.id);
|
||||
});
|
||||
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||
actionResult.failed(resourceType, item.context.id);
|
||||
});
|
||||
|
||||
if (actionResult.result.failed.length === 0 && actionResult.result.deleted.length > 0) {
|
||||
var path = 'project/load_balancer/' + loadbalancerId;
|
||||
$location.path(path);
|
||||
}
|
||||
return actionResult.result;
|
||||
}
|
||||
|
||||
function checkPermission(item) {
|
||||
@ -133,7 +124,7 @@
|
||||
toast.add('error', getMessage(notAllowedMessage, result.fail));
|
||||
}
|
||||
if (result.pass.length > 0) {
|
||||
deleteModal.open({ $emit: actionComplete }, result.pass.map(getEntity), context);
|
||||
return deleteModal.open(scope, result.pass.map(getEntity), context).then(deleteResult);
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,5 +144,12 @@
|
||||
return result.context;
|
||||
}
|
||||
|
||||
function allowed() {
|
||||
return policy.ifAllowed({ rules: [['neutron', 'delete_listener']] });
|
||||
}
|
||||
|
||||
function deleteItem(id) {
|
||||
return api.deleteListener(id, true);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -17,17 +18,11 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Listeners Delete Service', function() {
|
||||
var service, policy, modal, lbaasv2Api, $scope, $route, $location, $q, toast, items, path;
|
||||
var service, policy, modal, lbaasv2Api, $scope, $location, $q, toast, items, path;
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(makePromise());
|
||||
var promise = service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var allowed = service.allowed(item);
|
||||
$scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'delete_listener']]});
|
||||
return allowed;
|
||||
@ -46,15 +41,19 @@
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(function() {
|
||||
items = [{ id: '1', name: 'First' },
|
||||
{ id: '2', name: 'Second' }];
|
||||
items = [{ id: '1', name: 'First', loadbalancerId: 1 },
|
||||
{ id: '2', name: 'Second', loadbalancerId: 1 }];
|
||||
});
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: makePromise()
|
||||
result: {
|
||||
then: function(func) {
|
||||
return func({ data: { id: 'listener1' } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -75,12 +74,10 @@
|
||||
lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
modal = $injector.get('horizon.framework.widgets.modal.deleteModalService');
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$route = $injector.get('$route');
|
||||
$location = $injector.get('$location');
|
||||
$q = $injector.get('$q');
|
||||
toast = $injector.get('horizon.framework.widgets.toast.service');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.listeners.actions.delete');
|
||||
service.init('1', makePromise());
|
||||
}));
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
@ -96,23 +93,14 @@
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow deleting a listener from load balancer in a PENDING state', function() {
|
||||
service.init('1', makePromise(true));
|
||||
expect(allowed()).toBe(false);
|
||||
});
|
||||
|
||||
it('should not allow deleting a listener that has a default pool', function() {
|
||||
expect(allowed({default_pool_id: 'pool1'})).toBe(false);
|
||||
});
|
||||
|
||||
it('should open the delete modal', function() {
|
||||
spyOn(modal, 'open');
|
||||
service.perform(items[0]);
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
service.perform(items[0], $scope);
|
||||
$scope.$apply();
|
||||
expect(modal.open.calls.count()).toBe(1);
|
||||
var args = modal.open.calls.argsFor(0);
|
||||
expect(args.length).toBe(3);
|
||||
expect(args[0]).toEqual({ $emit: jasmine.any(Function) });
|
||||
expect(args[0]).toEqual($scope);
|
||||
expect(args[1]).toEqual([jasmine.objectContaining({ id: '1' })]);
|
||||
expect(args[2]).toEqual(jasmine.objectContaining({
|
||||
labels: jasmine.any(Object),
|
||||
@ -124,7 +112,7 @@
|
||||
it('should pass function to modal that deletes listeners', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteListener').and.callThrough();
|
||||
service.perform(items[0]);
|
||||
service.perform(items[0], $scope);
|
||||
$scope.$apply();
|
||||
expect(lbaasv2Api.deleteListener.calls.count()).toBe(1);
|
||||
expect(lbaasv2Api.deleteListener).toHaveBeenCalledWith('1', true);
|
||||
@ -135,7 +123,7 @@
|
||||
spyOn(lbaasv2Api, 'deleteListener').and.returnValue(makePromise(true));
|
||||
spyOn(toast, 'add');
|
||||
items.splice(1, 1);
|
||||
service.perform(items);
|
||||
service.perform(items, $scope);
|
||||
$scope.$apply();
|
||||
expect(modal.open).toHaveBeenCalled();
|
||||
expect(lbaasv2Api.deleteListener.calls.count()).toBe(1);
|
||||
@ -143,19 +131,11 @@
|
||||
'be deleted, possibly due to existing pools: First.');
|
||||
});
|
||||
|
||||
it('should reload table after delete', function() {
|
||||
path = 'project/load_balancer/1';
|
||||
spyOn($route, 'reload');
|
||||
service.perform(items);
|
||||
$scope.$apply();
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return to table after delete if on detail page', function() {
|
||||
path = 'project/load_balancer/1/listeners/2';
|
||||
spyOn($location, 'path');
|
||||
spyOn(toast, 'add');
|
||||
service.perform(items[0]);
|
||||
service.perform(items[0], $scope);
|
||||
$scope.$apply();
|
||||
expect($location.path).toHaveBeenCalledWith('project/load_balancer/1');
|
||||
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted listeners: First.');
|
||||
@ -166,7 +146,7 @@
|
||||
spyOn(toast, 'add');
|
||||
items[0].default_pool_id = 'pool1';
|
||||
items[1].default_pool_id = 'pool2';
|
||||
service.perform(items);
|
||||
service.perform(items, $scope);
|
||||
$scope.$apply();
|
||||
expect(modal.open).not.toHaveBeenCalled();
|
||||
expect(toast.add).toHaveBeenCalledWith('error',
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.listeners')
|
||||
.factory('horizon.dashboard.project.lbaasv2.listeners.actions.edit',
|
||||
editService);
|
||||
|
||||
editService.$inject = [
|
||||
'horizon.dashboard.project.lbaasv2.listeners.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.listeners.actions.edit
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Listener edit action.
|
||||
*
|
||||
* @param resourceType The listener resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns Listeners edit action service object.
|
||||
*/
|
||||
|
||||
function editService(
|
||||
resourceType, actionResultService, workflowModal, policy, gettext
|
||||
) {
|
||||
return workflowModal.init({
|
||||
controller: 'EditListenerWizardController',
|
||||
message: gettext('The listener has been updated.'),
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
function allowed(/*item*/) {
|
||||
return policy.ifAllowed({ rules: [['neutron', 'update_listener']] });
|
||||
}
|
||||
|
||||
function handle(response) {
|
||||
return actionResultService.getActionResult()
|
||||
.updated(resourceType, response.config.data.listener.id)
|
||||
.result;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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('LBaaS v2 Edit Listener Action Service', function() {
|
||||
var policy, service;
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$modal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func({ data: { id: 'listener1' } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.listeners.actions.edit');
|
||||
}));
|
||||
|
||||
it('should check policy to allow editing a listener', function() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
expect(service.allowed()).toBe(true);
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_listener']]});
|
||||
});
|
||||
|
||||
it('should handle the action result properly', function() {
|
||||
var result = service.handle({config: {data: {listener: {id: 1}}}});
|
||||
expect(result.updated[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,113 +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.listeners')
|
||||
.factory('horizon.dashboard.project.lbaasv2.listeners.actions.rowActions',
|
||||
tableRowActions);
|
||||
|
||||
tableRowActions.$inject = [
|
||||
'$q',
|
||||
'$route',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.delete',
|
||||
'horizon.dashboard.project.lbaasv2.pools.actions.create'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.listeners.actions.rowActions
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Listener table row actions.
|
||||
*
|
||||
* @param $q The angular service for promises.
|
||||
* @param $route The angular $route 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.
|
||||
* @param deleteService The LBaaS v2 listeners delete service.
|
||||
* @param createPoolService The LBaaS v2 pools create service.
|
||||
* @returns Listeners row actions service object.
|
||||
*/
|
||||
|
||||
function tableRowActions(
|
||||
$q, $route, workflowModal, policy, gettext, loadBalancersService, deleteService,
|
||||
createPoolService
|
||||
) {
|
||||
var loadbalancerId, loadBalancerIsActionable;
|
||||
|
||||
var edit = workflowModal.init({
|
||||
controller: 'EditListenerWizardController',
|
||||
message: gettext('The listener has been updated.'),
|
||||
handle: onEdit,
|
||||
allowed: canEdit
|
||||
});
|
||||
|
||||
var service = {
|
||||
actions: actions,
|
||||
init: init
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function init(_loadbalancerId_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId);
|
||||
return service;
|
||||
}
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: edit,
|
||||
template: {
|
||||
text: gettext('Edit')
|
||||
}
|
||||
},{
|
||||
service: createPoolService.init(loadbalancerId, loadBalancerIsActionable).create,
|
||||
template: {
|
||||
text: gettext('Create Pool')
|
||||
}
|
||||
},{
|
||||
service: deleteService.init(loadbalancerId, loadBalancerIsActionable),
|
||||
template: {
|
||||
text: gettext('Delete Listener'),
|
||||
type: 'delete'
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
function canEdit(/*item*/) {
|
||||
return $q.all([
|
||||
loadBalancerIsActionable,
|
||||
policy.ifAllowed({ rules: [['neutron', 'update_listener']] })
|
||||
]);
|
||||
}
|
||||
|
||||
function onEdit(/*response*/) {
|
||||
$route.reload();
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -1,115 +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('LBaaS v2 Listeners Table Row Actions Service', function() {
|
||||
var scope, $route, $q, actions, policy, init;
|
||||
|
||||
function canEdit(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = actions[0].service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_listener']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
function isActionableMock(id) {
|
||||
if (id === 'active') {
|
||||
return $q.when();
|
||||
} else {
|
||||
return $q.reject();
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
var response = {
|
||||
data: {
|
||||
id: '1'
|
||||
}
|
||||
};
|
||||
var modal = {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
$provide.value('$uibModal', modal);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
$q = $injector.get('$q');
|
||||
$route = $injector.get('$route');
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
var rowActionsService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions');
|
||||
actions = rowActionsService.actions();
|
||||
init = rowActionsService.init;
|
||||
var loadbalancerService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service');
|
||||
spyOn(loadbalancerService, 'isActionable').and.callFake(isActionableMock);
|
||||
}));
|
||||
|
||||
it('should define correct table row actions', function() {
|
||||
expect(actions.length).toBe(3);
|
||||
expect(actions[0].template.text).toBe('Edit');
|
||||
expect(actions[1].template.text).toBe('Create Pool');
|
||||
expect(actions[2].template.text).toBe('Delete Listener');
|
||||
});
|
||||
|
||||
it('should allow editing a listener of an ACTIVE load balancer', function() {
|
||||
init('active');
|
||||
expect(canEdit({listenerId: '1234'})).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow editing a listener of a non-ACTIVE load balancer', function() {
|
||||
init('non-active');
|
||||
expect(canEdit({listenerId: '1234'})).toBe(false);
|
||||
});
|
||||
|
||||
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 reload table after edit', function() {
|
||||
spyOn($route, 'reload').and.callThrough();
|
||||
actions[0].service.perform();
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,92 +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.listeners')
|
||||
.controller('ListenerDetailController', ListenerDetailController);
|
||||
|
||||
ListenerDetailController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions',
|
||||
'$routeParams',
|
||||
'$q'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name ListenerDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 listener detail page.
|
||||
*
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param rowActions The listener row actions service.
|
||||
* @param $routeParams The angular $routeParams service.
|
||||
* @param $q The angular service for promises.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function ListenerDetailController(api, rowActions, $routeParams, $q) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
ctrl.actions = rowActions.init($routeParams.loadbalancerId).actions;
|
||||
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
ctrl.listener = null;
|
||||
ctrl.loadbalancer = null;
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
$q.all([
|
||||
api.getListener($routeParams.listenerId)
|
||||
.then(success('listener'), fail('listener')),
|
||||
api.getLoadBalancer($routeParams.loadbalancerId)
|
||||
.then(success('loadbalancer'), fail('loadbalancer'))
|
||||
]).then(postInit, initError);
|
||||
}
|
||||
|
||||
function success(property) {
|
||||
return angular.bind(null, function setProp(property, response) {
|
||||
ctrl[property] = response.data;
|
||||
}, property);
|
||||
}
|
||||
|
||||
function fail(property) {
|
||||
return angular.bind(null, function setProp(property, error) {
|
||||
ctrl[property] = null;
|
||||
throw error;
|
||||
}, property);
|
||||
}
|
||||
|
||||
function postInit() {
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
function initError() {
|
||||
ctrl.loading = false;
|
||||
ctrl.error = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -1,104 +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('LBaaS v2 Listener Detail Controller', function() {
|
||||
var lbaasv2API, $controller, apiFail, qAllFail;
|
||||
|
||||
function fakePromise(data, reject) {
|
||||
return {
|
||||
then: function(success, fail) {
|
||||
if (reject) {
|
||||
fail();
|
||||
} else {
|
||||
success({ data: data });
|
||||
}
|
||||
return fakePromise();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fakeAPI() {
|
||||
return fakePromise('foo', apiFail);
|
||||
}
|
||||
|
||||
function loadbalancerAPI() {
|
||||
return fakePromise({ provisioning_status: 'ACTIVE' });
|
||||
}
|
||||
|
||||
function qAll() {
|
||||
return fakePromise(null, qAllFail);
|
||||
}
|
||||
|
||||
function createController() {
|
||||
return $controller('ListenerDetailController', {
|
||||
$routeParams: {
|
||||
loadbalancerId: 'loadbalancerId',
|
||||
listenerId: 'listenerId'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
apiFail = false;
|
||||
qAllFail = false;
|
||||
|
||||
$provide.value('$q', { all: qAll });
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI);
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
$controller = $injector.get('$controller');
|
||||
}));
|
||||
|
||||
it('should invoke lbaasv2 apis', function() {
|
||||
var ctrl = createController();
|
||||
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
|
||||
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId');
|
||||
expect(ctrl.loadbalancer).toEqual({ provisioning_status: 'ACTIVE' });
|
||||
expect(ctrl.listener).toBe('foo');
|
||||
});
|
||||
|
||||
it('should throw error on API fail', function() {
|
||||
apiFail = true;
|
||||
var init = function() {
|
||||
createController();
|
||||
};
|
||||
expect(init).toThrow();
|
||||
});
|
||||
|
||||
it('should set error state if any APIs fail', function() {
|
||||
qAllFail = true;
|
||||
var ctrl = createController();
|
||||
expect(ctrl.loading).toBe(false);
|
||||
expect(ctrl.error).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -1,46 +0,0 @@
|
||||
<div ng-controller="ListenerDetailController as ctrl">
|
||||
<detail-status loading="ctrl.loading" error="ctrl.error"></detail-status>
|
||||
<div ng-if="!ctrl.loading && !ctrl.error">
|
||||
<div class="page-header">
|
||||
<actions allowed="ctrl.actions" type="row" item="ctrl.listener" ng-if="ctrl.listener"
|
||||
class="actions_column pull-right"></actions>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}">{$ ::(ctrl.loadbalancer.name || ctrl.loadbalancer.id) $}</a></li>
|
||||
<li class="active">{$ ::(ctrl.listener.name || ctrl.listener.id) $}</li>
|
||||
</ol>
|
||||
<p ng-if="::ctrl.listener.description">{$ ::ctrl.listener.description $}</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt translate>Protocol</dt>
|
||||
<dd>{$ ::ctrl.listener.protocol $}</dd>
|
||||
<dt translate>Protocol Port</dt>
|
||||
<dd>{$ ::ctrl.listener.protocol_port $}</dd>
|
||||
<dt translate>Connection Limit</dt>
|
||||
<dd>{$ ctrl.listener.connection_limit | limit $}</dd>
|
||||
<dt translate>Admin State Up</dt>
|
||||
<dd>{$ ctrl.listener.admin_state_up | yesno $}</dd>
|
||||
<dt translate>Default Pool ID</dt>
|
||||
<dd>
|
||||
<a ng-href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}/pools/{$ ::ctrl.listener.default_pool_id $}" ng-if="ctrl.listener.default_pool_id">
|
||||
{$ ::ctrl.listener.default_pool_id $}
|
||||
</a>
|
||||
<span ng-if="!ctrl.listener.default_pool_id">
|
||||
{$ 'None' | translate $}
|
||||
</span>
|
||||
</dd>
|
||||
<dt translate>Listener ID</dt>
|
||||
<dd>{$ ::ctrl.listener.id $}</dd>
|
||||
<dt translate>Project ID</dt>
|
||||
<dd>{$ ::ctrl.listener.project_id $}</dd>
|
||||
<dt translate>Created At</dt>
|
||||
<dd>{$ ::ctrl.listener.created_at $}</dd>
|
||||
<dt translate>Updated At</dt>
|
||||
<dd>{$ ::ctrl.listener.updated_at $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.listeners')
|
||||
.controller('ListenerDetailController', ListenerDetailController);
|
||||
|
||||
ListenerDetailController.$inject = [
|
||||
'loadbalancer',
|
||||
'listener',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.resourceType',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service',
|
||||
'$q'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name ListenerDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 listener detail page.
|
||||
*
|
||||
* @param loadbalancer The loadbalancer object.
|
||||
* @param listener The listener object.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param resourceType The listenr resource type.
|
||||
* @param typeRegistry The horizon resource type registry service.
|
||||
* @param spinnerService The horizon modal wait spinner service.
|
||||
* @param $q The angular service for promises.
|
||||
*
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function ListenerDetailController(
|
||||
loadbalancer, listener, loadBalancersService, resourceType, typeRegistry,
|
||||
spinnerService, $q
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
ctrl.loadbalancer = loadbalancer;
|
||||
ctrl.listener = listener;
|
||||
ctrl.listFunctionExtraParams = {
|
||||
loadbalancerId: ctrl.loadbalancer.id,
|
||||
listenerId: ctrl.listener.id
|
||||
};
|
||||
ctrl.resourceType = typeRegistry.getResourceType(resourceType);
|
||||
ctrl.context = {};
|
||||
ctrl.context.identifier = listener.id;
|
||||
|
||||
ctrl.resultHandler = actionResultHandler;
|
||||
|
||||
function actionResultHandler(returnValue) {
|
||||
return $q.when(returnValue, actionSuccessHandler);
|
||||
}
|
||||
|
||||
function loadData(response) {
|
||||
spinnerService.hideModalSpinner();
|
||||
ctrl.showDetails = true;
|
||||
ctrl.resourceType.initActions();
|
||||
ctrl.listener = response.data;
|
||||
ctrl.listener.loadbalancerId = ctrl.loadbalancer.id;
|
||||
}
|
||||
|
||||
function actionSuccessHandler(result) {
|
||||
// The action has completed (for whatever "complete" means to that
|
||||
// action. Notice the view doesn't really need to know the semantics of the
|
||||
// particular action because the actions return data in a standard form.
|
||||
// That return includes the id and type of each created, updated, deleted
|
||||
// and failed item.
|
||||
// Currently just refreshes the display each time.
|
||||
if (result) {
|
||||
spinnerService.showModalSpinner(gettext('Please Wait'));
|
||||
ctrl.showDetails = false;
|
||||
ctrl.context.loadPromise = ctrl.resourceType.load(ctrl.context.identifier);
|
||||
ctrl.context.loadPromise.then(loadData);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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('LBaaS v2 Listener Detail Controller', function() {
|
||||
var deferred, service, ctrl, scope, $timeout, $q, actionResultService;
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($controller, $rootScope, _$q_, _$timeout_) {
|
||||
$q = _$q_;
|
||||
deferred = $q.defer();
|
||||
service = {
|
||||
getResourceType: function() {
|
||||
return {
|
||||
load: function() { return deferred.promise; },
|
||||
parsePath: function() { return 'my-context'; },
|
||||
itemName: function() { return 'A name'; },
|
||||
initActions: angular.noop
|
||||
};
|
||||
},
|
||||
getDefaultDetailsTemplateUrl: angular.noop
|
||||
};
|
||||
actionResultService = {
|
||||
getIdsOfType: function() { return []; }
|
||||
};
|
||||
$timeout = _$timeout_;
|
||||
scope = $rootScope.$new();
|
||||
ctrl = $controller('ListenerDetailController', {
|
||||
$scope: scope,
|
||||
loadbalancer: { id: '123' },
|
||||
listener: { id: '123' },
|
||||
'horizon.framework.conf.resource-type-registry.service': service,
|
||||
'horizon.framework.util.actions.action-result.service': actionResultService,
|
||||
'horizon.framework.widgets.modal-wait-spinner.service': {
|
||||
showModalSpinner: angular.noop,
|
||||
hideModalSpinner: angular.noop
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
it('should create a controller', function() {
|
||||
expect(ctrl).toBeDefined();
|
||||
expect(ctrl.loadbalancer).toBeDefined();
|
||||
expect(ctrl.listener).toBeDefined();
|
||||
});
|
||||
|
||||
describe('resultHandler', function() {
|
||||
|
||||
it('handles empty results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve({});
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles falsy results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve(false);
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles matched results', function() {
|
||||
spyOn(actionResultService, 'getIdsOfType').and.returnValue([1, 2, 3]);
|
||||
var result = $q.defer();
|
||||
result.resolve({some: 'thing'});
|
||||
ctrl.resultHandler(result.promise);
|
||||
deferred.resolve({data: {some: 'data'}});
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -0,0 +1,62 @@
|
||||
<div class="page-header">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}">{$ ::(ctrl.loadbalancer.name || ctrl.loadbalancer.id) $}</a></li>
|
||||
<li class="active">{$ ::(ctrl.listener.name || ctrl.listener.id) $}</li>
|
||||
</ol>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-9 text-left">
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<strong translate>Protocol</strong>
|
||||
{$ ::ctrl.listener.protocol $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Port</strong>
|
||||
{$ ::ctrl.listener.protocol_port $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Operating Status</strong>
|
||||
{$ ctrl.listener.operating_status | decode:ctrl.operatingStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Provisioning Status</strong>
|
||||
{$ ctrl.listener.provisioning_status | decode:ctrl.provisioningStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Admin State Up</strong>
|
||||
{$ ctrl.listener.admin_state_up | yesno $}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-3 text-right details-item-actions">
|
||||
<actions allowed="ctrl.resourceType.itemActions"
|
||||
type="row"
|
||||
item="ctrl.listener"
|
||||
ng-if="ctrl.listener"
|
||||
class="actions_column pull-right"
|
||||
result-handler="ctrl.resultHandler"></actions>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<uib-tabset class="octavia-tabset">
|
||||
<uib-tab heading="{$ 'Overview' | translate $}">
|
||||
<div class="col-md-6 detail">
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::Listener"
|
||||
cls="dl-horizontal"
|
||||
item="ctrl.listener"
|
||||
property-groups="[[
|
||||
'id', 'name', 'description', 'project_id', 'created_at', 'updated_at',
|
||||
'connection_limit', 'default_pool_id']]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</uib-tab>
|
||||
<uib-tab heading="{$ 'Pools' | translate $}">
|
||||
<hz-resource-table resource-type-name="OS::Octavia::Pool"
|
||||
track-by="trackBy"
|
||||
list-function-extra-params="ctrl.listFunctionExtraParams">
|
||||
</hz-resource-table>
|
||||
</uib-tab>
|
||||
</uib-tabset>
|
@ -0,0 +1,9 @@
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::Listener"
|
||||
item="item"
|
||||
property-groups="[
|
||||
['name', 'id', 'project_id'],
|
||||
['created_at', 'updated_at', 'description'],
|
||||
['protocol', 'protocol_port', 'connection_limit'],
|
||||
['default_pool_id']]">
|
||||
</hz-resource-property-list>
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -26,6 +27,152 @@
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.listeners', []);
|
||||
.module('horizon.dashboard.project.lbaasv2.listeners', [])
|
||||
.constant('horizon.dashboard.project.lbaasv2.listeners.resourceType',
|
||||
'OS::Octavia::Listener')
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.dashboard.project.lbaasv2.basePath',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.create',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.edit',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.delete',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.resourceType'
|
||||
];
|
||||
|
||||
function run(
|
||||
registry,
|
||||
basePath,
|
||||
loadBalancerService,
|
||||
createService,
|
||||
editService,
|
||||
deleteService,
|
||||
resourceType
|
||||
) {
|
||||
var listenerResourceType = registry.getResourceType(resourceType);
|
||||
|
||||
listenerResourceType
|
||||
.setNames(gettext('Listener'), gettext('Listeners'))
|
||||
.setSummaryTemplateUrl(basePath + 'listeners/details/drawer.html')
|
||||
.setProperties(listenerProperties(loadBalancerService))
|
||||
.setListFunction(loadBalancerService.getListenersPromise)
|
||||
.setLoadFunction(loadBalancerService.getListenerPromise)
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
urlFunction: loadBalancerService.getListenerDetailsPath
|
||||
})
|
||||
.append({
|
||||
id: 'protocol',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'protocol_port',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'operating_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'provisioning_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'admin_state_up',
|
||||
priority: 1
|
||||
});
|
||||
|
||||
listenerResourceType.itemActions
|
||||
.append({
|
||||
id: 'listenerEdit',
|
||||
service: editService,
|
||||
template: {
|
||||
text: gettext('Edit Listener')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'listenerDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Listener'),
|
||||
type: 'delete'
|
||||
}
|
||||
});
|
||||
|
||||
listenerResourceType.globalActions
|
||||
.append({
|
||||
id: 'listenerCreate',
|
||||
service: createService,
|
||||
template: {
|
||||
type: 'create',
|
||||
text: gettext('Create Listener')
|
||||
}
|
||||
});
|
||||
|
||||
listenerResourceType.batchActions
|
||||
.append({
|
||||
id: 'listenerBatchDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Listeners'),
|
||||
type: 'delete-selected'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function listenerProperties(loadBalancerService) {
|
||||
return {
|
||||
id: gettext('ID'),
|
||||
name: {
|
||||
label: gettext('Name'),
|
||||
filters: ['noName']
|
||||
},
|
||||
description: {
|
||||
label: gettext('Description'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
provisioning_status: {
|
||||
label: gettext('Provisioning Status'),
|
||||
values: loadBalancerService.provisioningStatus
|
||||
},
|
||||
operating_status: {
|
||||
label: gettext('Operating Status'),
|
||||
values: loadBalancerService.operatingStatus
|
||||
},
|
||||
admin_state_up: {
|
||||
label: gettext('Admin State Up'),
|
||||
filters: ['yesno']
|
||||
},
|
||||
protocol: gettext('Protocol'),
|
||||
protocol_port: gettext('Port'),
|
||||
project_id: gettext('Project ID'),
|
||||
created_at: {
|
||||
label: gettext('Created At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
updated_at: {
|
||||
label: gettext('Updated At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
connection_limit: {
|
||||
label: gettext('Connection Limit'),
|
||||
filters: ['limit']
|
||||
},
|
||||
default_tls_container_ref: gettext('Default TLS Container Ref'),
|
||||
sni_container_refs: gettext('SNI Container Refs'),
|
||||
default_pool_id: {
|
||||
label: gettext('Default Pool ID'),
|
||||
filters: ['noName']
|
||||
},
|
||||
l7_policies: gettext('L7 Policies'),
|
||||
insert_headers: gettext('Insert Headers'),
|
||||
load_balancers: gettext('Load Balancers')
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -22,4 +23,46 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('LBaaS v2 Listeners Registry', function () {
|
||||
var registry, resourceType;
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
resourceType = $injector.get('horizon.dashboard.project.lbaasv2.listeners.resourceType');
|
||||
registry = $injector.get('horizon.framework.conf.resource-type-registry.service');
|
||||
}));
|
||||
|
||||
it('should define resourceType', function () {
|
||||
expect(resourceType).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register item actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).itemActions;
|
||||
expect(actionHasId(actions, 'listenerEdit')).toBe(true);
|
||||
expect(actionHasId(actions, 'listenerDelete')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register global actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).globalActions;
|
||||
expect(actionHasId(actions, 'listenerCreate')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register batch actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).batchActions;
|
||||
expect(actionHasId(actions, 'listenerBatchDelete')).toBe(true);
|
||||
});
|
||||
|
||||
function actionHasId(list, value) {
|
||||
return list.filter(matchesId).length === 1;
|
||||
|
||||
function matchesId(action) {
|
||||
if (action.id === value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -1,80 +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.listeners')
|
||||
.controller('ListenersTableController', ListenersTableController);
|
||||
|
||||
ListenersTableController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'$routeParams',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.rowActions',
|
||||
'horizon.dashboard.project.lbaasv2.listeners.actions.batchActions'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name ListenersTableController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 listeners table. Serves as the focal point for table actions.
|
||||
*
|
||||
* @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, batchActions) {
|
||||
|
||||
var ctrl = this;
|
||||
ctrl.items = [];
|
||||
ctrl.src = [];
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
ctrl.checked = {};
|
||||
ctrl.loadbalancerId = $routeParams.loadbalancerId;
|
||||
ctrl.batchActions = batchActions.init(ctrl.loadbalancerId);
|
||||
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId);
|
||||
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
ctrl.src = [];
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
api.getListeners(ctrl.loadbalancerId).then(success, fail);
|
||||
}
|
||||
|
||||
function success(response) {
|
||||
ctrl.src = response.data.items;
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
function fail(/*response*/) {
|
||||
ctrl.src = [];
|
||||
ctrl.loading = false;
|
||||
ctrl.error = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -1,97 +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('LBaaS v2 Listeners Table Controller', function() {
|
||||
var controller, lbaasv2API, rowActions, batchActions;
|
||||
var items = [{ foo: 'bar' }];
|
||||
var apiFail = false;
|
||||
|
||||
function fakeAPI() {
|
||||
return {
|
||||
then: function(success, fail) {
|
||||
if (apiFail && fail) {
|
||||
fail();
|
||||
} else {
|
||||
success({ data: { items: items } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function initMock() {
|
||||
return rowActions;
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
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);
|
||||
}));
|
||||
|
||||
function createController() {
|
||||
return controller('ListenersTableController', {
|
||||
$routeParams: { loadbalancerId: '1234' }
|
||||
});
|
||||
}
|
||||
|
||||
it('should initialize correctly', function() {
|
||||
var ctrl = createController();
|
||||
expect(ctrl.items).toEqual([]);
|
||||
expect(ctrl.src).toEqual(items);
|
||||
expect(ctrl.loading).toBe(false);
|
||||
expect(ctrl.error).toBe(false);
|
||||
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() {
|
||||
var ctrl = createController();
|
||||
expect(lbaasv2API.getListeners).toHaveBeenCalled();
|
||||
expect(ctrl.src.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should show error if loading fails', function() {
|
||||
apiFail = true;
|
||||
var ctrl = createController();
|
||||
expect(ctrl.src.length).toBe(0);
|
||||
expect(ctrl.error).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,124 +0,0 @@
|
||||
<table ng-controller="ListenersTableController as table"
|
||||
hz-table ng-cloak
|
||||
st-table="table.items"
|
||||
st-safe-src="table.src"
|
||||
default-sort="name"
|
||||
default-sort-reverse="false"
|
||||
class="table table-striped table-rsp table-detail">
|
||||
<!--
|
||||
TODO(jpomero): This table pattern does not allow for extensibility and should be revisited
|
||||
once horizon implements a better one.
|
||||
-->
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<!--
|
||||
Table-batch-actions:
|
||||
This is where batch actions like searching, creating, and deleting.
|
||||
-->
|
||||
<th colspan="7" class="search-header">
|
||||
<hz-search-bar icon-classes="fa-search">
|
||||
<actions allowed="table.batchActions.actions" type="batch"></actions>
|
||||
</hz-search-bar>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<!--
|
||||
Table-column-headers:
|
||||
This is where we declaratively define the table column headers.
|
||||
Include select-col if you want to select all.
|
||||
Include expander if you want to inline details.
|
||||
Include action-col if you want to perform actions.
|
||||
-->
|
||||
<th class="multi_select_column">
|
||||
<input type="checkbox" hz-select-all="table.items">
|
||||
</th>
|
||||
|
||||
<th class="expander"></th>
|
||||
|
||||
<th class="rsp-p1" st-sort="name" st-sort-default="name" translate>Name</th>
|
||||
<th class="rsp-p1" st-sort="description" translate>Description</th>
|
||||
<th class="rsp-p1" st-sort="protocol" translate>Protocol</th>
|
||||
<th class="rsp-p1" st-sort="port" translate>Port</th>
|
||||
<th class="actions_column" translate>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<!--
|
||||
Table-rows:
|
||||
This is where we declaratively define the table columns.
|
||||
Include select-col if you want to select all.
|
||||
Include expander if you want to inline details.
|
||||
Include action-col if you want to perform actions.
|
||||
rsp-p1 rsp-p2 are responsive priority as user resizes window.
|
||||
-->
|
||||
<tr ng-repeat-start="item in table.items track by item.id"
|
||||
ng-class="{'st-selected': checked[item.id]}">
|
||||
|
||||
<td class="multi_select_column">
|
||||
<input type="checkbox"
|
||||
ng-model="tCtrl.selections[item.id].checked"
|
||||
hz-select="item">
|
||||
</td>
|
||||
<td class="expander">
|
||||
<span class="fa fa-chevron-right"
|
||||
hz-expand-detail
|
||||
duration="200">
|
||||
</span>
|
||||
</td>
|
||||
<td class="rsp-p1"><a ng-href="project/load_balancer/{$ ::table.loadbalancerId $}/listeners/{$ ::item.id $}">{$ ::(item.name || item.id) $}</a></td>
|
||||
<td class="rsp-p1">{$ ::item.description | noValue $}</td>
|
||||
<td class="rsp-p1">{$ ::item.protocol$}</td>
|
||||
<td class="rsp-p1">{$ ::item.protocol_port$}</td>
|
||||
<td class="actions_column">
|
||||
<!--
|
||||
Table-row-action-column:
|
||||
Actions taken here apply to a single item/row.
|
||||
-->
|
||||
<actions allowed="table.rowActions.actions" type="row" item="item"></actions>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr ng-repeat-end class="detail-row">
|
||||
<!--
|
||||
Detail-row:
|
||||
Contains detailed information on this item.
|
||||
Can be toggled using the chevron button.
|
||||
Ensure colspan is greater or equal to number of column-headers.
|
||||
-->
|
||||
<td class="detail" colspan="7">
|
||||
|
||||
<div class="row">
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>ID</dt>
|
||||
<dd>{$ ::item.id $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Admin State Up</dt>
|
||||
<dd>{$ ::item.admin_state_up | yesno $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Connection Limit</dt>
|
||||
<dd>{$ ::item.connection_limit | limit $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Default Pool ID</dt>
|
||||
<dd>{$ ::item.default_pool_id | noValue $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr table-status table="table" column-count="7"></tr>
|
||||
|
||||
</tbody>
|
||||
<!--
|
||||
Table-footer:
|
||||
This is where we display number of items and pagination controls.
|
||||
-->
|
||||
<tfoot hz-table-footer items="table.items"></tfoot>
|
||||
|
||||
</table>
|
@ -20,7 +20,6 @@
|
||||
var ctrl, network, floatingIps, floatingIpPools, $controller, $uibModalInstance;
|
||||
var associateFail = false;
|
||||
|
||||
beforeEach(module('horizon.framework.util.i18n'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(function() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -18,7 +19,7 @@
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.loadbalancers')
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service',
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip',
|
||||
modalService);
|
||||
|
||||
modalService.$inject = [
|
||||
@ -35,7 +36,7 @@
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Load Balancer Associate Floating IP action.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -34,10 +35,6 @@
|
||||
return allowed;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(function() {
|
||||
@ -76,7 +73,7 @@
|
||||
$route = $injector.get('$route');
|
||||
$uibModal = $injector.get('$uibModal');
|
||||
service = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service');
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip');
|
||||
}));
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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 Load Balancers Table Batch Actions Service', function() {
|
||||
var $location, actions, policy;
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
var response = {
|
||||
data: {
|
||||
id: '1'
|
||||
}
|
||||
};
|
||||
var modal = {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
$provide.value('$uibModal', modal);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
$location = $injector.get('$location');
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
var batchActionsService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions');
|
||||
actions = batchActionsService.actions();
|
||||
}));
|
||||
|
||||
it('should define correct table batch actions', function() {
|
||||
expect(actions.length).toBe(2);
|
||||
expect(actions[0].template.text).toBe('Create Load Balancer');
|
||||
expect(actions[1].template.text).toBe('Delete Load Balancers');
|
||||
});
|
||||
|
||||
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 load balancer', function() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var allowed = actions[0].service.allowed();
|
||||
expect(allowed).toBe(true);
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'create_loadbalancer']]});
|
||||
});
|
||||
|
||||
it('should redirect after create', function() {
|
||||
spyOn($location, 'path').and.callThrough();
|
||||
actions[0].service.perform();
|
||||
expect($location.path).toHaveBeenCalledWith('project/load_balancer/1');
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -18,76 +19,55 @@
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.loadbalancers')
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions',
|
||||
tableBatchActions);
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.create', createService);
|
||||
|
||||
tableBatchActions.$inject = [
|
||||
'$location',
|
||||
createService.$inject = [
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.dashboard.project.lbaasv2.basePath',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions
|
||||
* @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.create
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Load Balancers table batch actions.
|
||||
* Provides the service for the create load balancer action.
|
||||
*
|
||||
* @param $location The angular $location service.
|
||||
* @param resourceType The loadbalancer resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param basePath The lbaasv2 module base path.
|
||||
* @param deleteService The load balancer delete service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns Load balancers table batch actions service object.
|
||||
*
|
||||
* @returns Create load balancer action service.
|
||||
*/
|
||||
|
||||
function tableBatchActions($location, workflowModal, basePath, deleteService, policy, gettext) {
|
||||
function createService(
|
||||
resourceType, actionResultService, workflowModal, policy, gettext
|
||||
) {
|
||||
|
||||
var create = workflowModal.init({
|
||||
return workflowModal.init({
|
||||
controller: 'CreateLoadBalancerWizardController',
|
||||
message: gettext('A new load balancer is being created.'),
|
||||
handle: onCreate,
|
||||
allowed: canCreate
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
var service = {
|
||||
actions: actions
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: create,
|
||||
template: {
|
||||
type: 'create',
|
||||
text: gettext('Create Load Balancer')
|
||||
}
|
||||
}, {
|
||||
service: deleteService,
|
||||
template: {
|
||||
type: 'delete-selected',
|
||||
text: gettext('Delete Load Balancers')
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
function canCreate() {
|
||||
function allowed() {
|
||||
// This rule is made up and should therefore always pass. I assume at some point there
|
||||
// will be a valid rule similar to this that we will want to use.
|
||||
return policy.ifAllowed({ rules: [['neutron', 'create_loadbalancer']] });
|
||||
}
|
||||
|
||||
function onCreate(response) {
|
||||
$location.path('project/load_balancer/' + response.data.id);
|
||||
function handle(response) {
|
||||
return actionResultService.getActionResult()
|
||||
.created(resourceType, response.data.id)
|
||||
.result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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('LBaaS v2 Create Load Balancer Action Service', function() {
|
||||
var policy, service;
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$modal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func({ data: { id: 'loadbalancer1' } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.actions.create');
|
||||
}));
|
||||
|
||||
it('should check policy to allow creating a load balancer', function() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
expect(service.allowed()).toBe(true);
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'create_loadbalancer']]});
|
||||
});
|
||||
|
||||
it('should handle the action result properly', function() {
|
||||
var result = service.handle({data: {id: 1}});
|
||||
expect(result.created[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -29,7 +29,6 @@
|
||||
};
|
||||
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);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -21,9 +22,9 @@
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete', deleteService);
|
||||
|
||||
deleteService.$inject = [
|
||||
'$q',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'$location',
|
||||
'$route',
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
@ -36,24 +37,31 @@
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.loadbalancers.actions.deleteService
|
||||
* @description
|
||||
*
|
||||
* Brings up the delete load balancers confirmation modal dialog.
|
||||
* On submit, deletes selected load balancers.
|
||||
* On cancel, does nothing.
|
||||
* @param $q The angular service for promises.
|
||||
*
|
||||
* @param resourceType The loadbalancer resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param $location The angular $location service.
|
||||
* @param $route The angular $route service.
|
||||
* @param deleteModal The horizon delete modal service.
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param toast The horizon message service.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns The load balancers table delete service.
|
||||
*
|
||||
* @returns The load balancers delete service.
|
||||
*/
|
||||
|
||||
function deleteService(
|
||||
$q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext
|
||||
resourceType, actionResultService, $location, deleteModal, api,
|
||||
policy, toast, qExtensions, gettext
|
||||
) {
|
||||
|
||||
var scope;
|
||||
|
||||
// If a batch delete, then this message is displayed for any selected load balancers not in
|
||||
// ACTIVE or ERROR state.
|
||||
var notAllowedMessage = gettext('The following load balancers are pending and cannot be ' +
|
||||
@ -82,23 +90,34 @@
|
||||
|
||||
//////////////
|
||||
|
||||
function perform(items) {
|
||||
if (angular.isArray(items)) {
|
||||
qExtensions.allSettled(items.map(checkPermission)).then(afterCheck);
|
||||
} else {
|
||||
deleteModal.open({ $emit: actionComplete }, [items], context);
|
||||
}
|
||||
function perform(items, _scope_) {
|
||||
scope = _scope_;
|
||||
var loadbalancers = angular.isArray(items) ? items : [items];
|
||||
return qExtensions.allSettled(loadbalancers.map(checkPermission)).then(afterCheck);
|
||||
}
|
||||
|
||||
function allowed(item) {
|
||||
function deleteResult(deleteModalResult) {
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
var actionResult = actionResultService.getActionResult();
|
||||
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||
actionResult.deleted(resourceType, item.context.id);
|
||||
});
|
||||
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||
actionResult.failed(resourceType, item.context.id);
|
||||
});
|
||||
|
||||
if (actionResult.result.failed.length === 0 && actionResult.result.deleted.length > 0) {
|
||||
var path = 'project/load_balancer';
|
||||
$location.path(path);
|
||||
}
|
||||
return actionResult.result;
|
||||
}
|
||||
|
||||
function allowed() {
|
||||
// This rule is made up and should therefore always pass. I assume at some point there
|
||||
// will be a valid rule similar to this that we will want to use.
|
||||
var promises = [policy.ifAllowed({ rules: [['neutron', 'delete_loadbalancer']] })];
|
||||
if (item) {
|
||||
var status = item.provisioning_status;
|
||||
promises.push(qExtensions.booleanAsPromise(status === 'ACTIVE' || status === 'ERROR'));
|
||||
}
|
||||
return $q.all(promises);
|
||||
return policy.ifAllowed({ rules: [['neutron', 'delete_loadbalancer']] });
|
||||
}
|
||||
|
||||
function canBeDeleted(item) {
|
||||
@ -115,7 +134,7 @@
|
||||
toast.add('error', getMessage(notAllowedMessage, result.fail));
|
||||
}
|
||||
if (result.pass.length > 0) {
|
||||
deleteModal.open({ $emit: actionComplete }, result.pass.map(getEntity), context);
|
||||
return deleteModal.open(scope, result.pass.map(getEntity), context).then(deleteResult);
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,20 +154,5 @@
|
||||
return result.context;
|
||||
}
|
||||
|
||||
function actionComplete(eventType) {
|
||||
if (eventType === context.failedEvent) {
|
||||
// Action failed, reload the page
|
||||
$route.reload();
|
||||
} else {
|
||||
// If the user is on the load balancers table then just reload the page, otherwise they
|
||||
// are on the details page and we return to the table.
|
||||
if (/\/load_balancer(\/)?$/.test($location.path())) {
|
||||
$route.reload();
|
||||
} else {
|
||||
$location.path('project/load_balancer');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -17,17 +18,11 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Load Balancers Table Row Delete Service', function() {
|
||||
var service, policy, modal, lbaasv2Api, $scope, $route, $location, $q, toast, items, path;
|
||||
var service, policy, modal, lbaasv2Api, $scope, $location, $q, toast, items, path;
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
var allowed = service.allowed(item);
|
||||
$scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'delete_loadbalancer']]});
|
||||
return allowed;
|
||||
@ -39,10 +34,6 @@
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(function() {
|
||||
@ -75,7 +66,6 @@
|
||||
lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
modal = $injector.get('horizon.framework.widgets.modal.deleteModalService');
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$route = $injector.get('$route');
|
||||
$location = $injector.get('$location');
|
||||
$q = $injector.get('$q');
|
||||
toast = $injector.get('horizon.framework.widgets.toast.service');
|
||||
@ -95,24 +85,14 @@
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow deleting load balancers if state check fails (single)', function() {
|
||||
items[0].provisioning_status = 'PENDING_UPDATE';
|
||||
expect(allowed(items[0])).toBe(false);
|
||||
});
|
||||
|
||||
it('should allow batch delete even if state check fails (batch)', function() {
|
||||
items[0].provisioning_status = 'PENDING_UPDATE';
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should open the delete modal', function() {
|
||||
spyOn(modal, 'open');
|
||||
service.perform(items[0]);
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
service.perform(items[0], $scope);
|
||||
$scope.$apply();
|
||||
expect(modal.open.calls.count()).toBe(1);
|
||||
var args = modal.open.calls.argsFor(0);
|
||||
expect(args.length).toBe(3);
|
||||
expect(args[0]).toEqual({ $emit: jasmine.any(Function) });
|
||||
expect(args[0]).toEqual($scope);
|
||||
expect(args[1]).toEqual([jasmine.objectContaining({ id: '1' })]);
|
||||
expect(args[2]).toEqual(jasmine.objectContaining({
|
||||
labels: jasmine.any(Object),
|
||||
@ -124,7 +104,7 @@
|
||||
it('should pass function to modal that deletes load balancers', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteLoadBalancer').and.callThrough();
|
||||
service.perform(items[0]);
|
||||
service.perform(items[0], $scope);
|
||||
$scope.$apply();
|
||||
expect(lbaasv2Api.deleteLoadBalancer.calls.count()).toBe(1);
|
||||
expect(lbaasv2Api.deleteLoadBalancer).toHaveBeenCalledWith('1', true);
|
||||
@ -135,7 +115,7 @@
|
||||
spyOn(toast, 'add');
|
||||
items[0].provisioning_status = 'PENDING_UPDATE';
|
||||
items[1].provisioning_status = 'PENDING_DELETE';
|
||||
service.perform(items);
|
||||
service.perform(items, $scope);
|
||||
$scope.$apply();
|
||||
expect(modal.open).not.toHaveBeenCalled();
|
||||
expect(toast.add).toHaveBeenCalledWith('error',
|
||||
@ -147,7 +127,7 @@
|
||||
spyOn(lbaasv2Api, 'deleteLoadBalancer').and.returnValue(makePromise(true));
|
||||
spyOn(toast, 'add');
|
||||
items.splice(1, 1);
|
||||
service.perform(items);
|
||||
service.perform(items, $scope);
|
||||
$scope.$apply();
|
||||
expect(modal.open).toHaveBeenCalled();
|
||||
expect(lbaasv2Api.deleteLoadBalancer.calls.count()).toBe(1);
|
||||
@ -155,19 +135,11 @@
|
||||
'be deleted, possibly due to existing listeners: First.');
|
||||
});
|
||||
|
||||
it('should reload table after delete', function() {
|
||||
path = 'project/load_balancer';
|
||||
spyOn($route, 'reload');
|
||||
service.perform(items);
|
||||
$scope.$apply();
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return to table after delete if on detail page', function() {
|
||||
it('should return to panel after delete if on detail page', function() {
|
||||
path = 'project/load_balancer/1';
|
||||
spyOn($location, 'path');
|
||||
spyOn(toast, 'add');
|
||||
service.perform(items[0]);
|
||||
service.perform(items[0], $scope);
|
||||
$scope.$apply();
|
||||
expect($location.path).toHaveBeenCalledWith('project/load_balancer');
|
||||
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted load balancers: First.');
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -19,7 +20,7 @@
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.loadbalancers')
|
||||
.factory(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip',
|
||||
modalService);
|
||||
|
||||
modalService.$inject = [
|
||||
@ -34,11 +35,13 @@
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service
|
||||
* @name horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip
|
||||
*
|
||||
* @description
|
||||
* Brings up the disassociate floating IP confirmation modal dialog.
|
||||
* On submit, dsiassociates the floating IP address from the load balancer.
|
||||
* On cancel, does nothing.
|
||||
*
|
||||
* @param $q The angular service for promises.
|
||||
* @param $route The angular $route service.
|
||||
* @param deleteModal The horizon delete modal service.
|
||||
@ -46,7 +49,8 @@
|
||||
* @param policy The horizon policy service.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns The load balancers table row delete service.
|
||||
*
|
||||
* @returns The Disassociate Floating IP modal service.
|
||||
*/
|
||||
|
||||
function modalService($q, $route, deleteModal, network, policy, qExtensions, gettext) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -34,10 +35,6 @@
|
||||
return allowed;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(function() {
|
||||
@ -71,7 +68,7 @@
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$route = $injector.get('$route');
|
||||
service = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service');
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip');
|
||||
}));
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.loadbalancers')
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.edit', editService);
|
||||
|
||||
editService.$inject = [
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.edit
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the edit load balancer action.
|
||||
*
|
||||
* @param resourceType The loadbalancer resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns Edit load balancer action service.
|
||||
*/
|
||||
|
||||
function editService(
|
||||
resourceType, actionResultService, workflowModal, policy,
|
||||
qExtensions, gettext
|
||||
) {
|
||||
|
||||
return workflowModal.init({
|
||||
controller: 'EditLoadBalancerWizardController',
|
||||
message: gettext('The load balancer has been updated.'),
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
///////////////
|
||||
|
||||
function allowed() {
|
||||
// This rule is made up and should therefore always pass. At some point there will
|
||||
// likely be a valid rule similar to this that we will want to use.
|
||||
return policy.ifAllowed({ rules: [['neutron', 'update_loadbalancer']] });
|
||||
}
|
||||
|
||||
function handle(response) {
|
||||
return actionResultService.getActionResult()
|
||||
.updated(resourceType, response.config.data.loadbalancer.id)
|
||||
.result;
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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('LBaaS v2 Edit Load Balancer Action Service', function() {
|
||||
var service, scope, policy;
|
||||
|
||||
function canEdit(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var allowed = service.allowed(item);
|
||||
scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_loadbalancer']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$modal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.actions.edit');
|
||||
}));
|
||||
|
||||
it('should allow editing an load balancer', function() {
|
||||
expect(canEdit({provisioning_status: 'ACTIVE'})).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle the action result properly', function() {
|
||||
var result = service.handle({config: {data: {loadbalancer: {id: 1}}}});
|
||||
expect(result.updated[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -29,7 +29,6 @@
|
||||
launchContext: { id: '1' }
|
||||
};
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
beforeEach(module(function ($provide) {
|
||||
workflowSpy = jasmine.createSpy('workflow').and.returnValue(workflow);
|
||||
|
@ -1,123 +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.loadbalancers')
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions',
|
||||
tableRowActions);
|
||||
|
||||
tableRowActions.$inject = [
|
||||
'$q',
|
||||
'$route',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip.modal.service',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip.modal.service',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.network',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Load Balancers table row actions.
|
||||
*
|
||||
* @param $q The angular service for promises.
|
||||
* @param $route The angular $route service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param deleteService The load balancer delete service.
|
||||
* @param associateIp The associate floating IP modal service.
|
||||
* @param disassociateIp The disassociate floating IP modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param network The horizon network API service.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns Load balancers table row actions service object.
|
||||
*/
|
||||
|
||||
function tableRowActions(
|
||||
$q,
|
||||
$route,
|
||||
workflowModal,
|
||||
deleteService,
|
||||
associateIp,
|
||||
disassociateIp,
|
||||
policy,
|
||||
network,
|
||||
qExtensions,
|
||||
gettext
|
||||
) {
|
||||
var edit = workflowModal.init({
|
||||
controller: 'EditLoadBalancerWizardController',
|
||||
message: gettext('The load balancer has been updated.'),
|
||||
handle: onEdit,
|
||||
allowed: canEdit
|
||||
});
|
||||
|
||||
var service = {
|
||||
actions: actions
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: edit,
|
||||
template: {
|
||||
text: gettext('Edit')
|
||||
}
|
||||
},{
|
||||
service: associateIp,
|
||||
template: {
|
||||
text: gettext('Associate Floating IP')
|
||||
}
|
||||
},{
|
||||
service: disassociateIp,
|
||||
template: {
|
||||
text: gettext('Disassociate Floating IP')
|
||||
}
|
||||
},{
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Load Balancer'),
|
||||
type: 'delete'
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
function canEdit(item) {
|
||||
return $q.all([
|
||||
qExtensions.booleanAsPromise(item.provisioning_status === 'ACTIVE'),
|
||||
// This rule is made up and should therefore always pass. At some point there will
|
||||
// likely be a valid rule similar to this that we will want to use.
|
||||
policy.ifAllowed({ rules: [['neutron', 'update_loadbalancer']] })
|
||||
]);
|
||||
}
|
||||
|
||||
function onEdit(/*response*/) {
|
||||
$route.reload();
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -1,101 +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('LBaaS v2 Load Balancers Table Row Actions Service', function() {
|
||||
var rowActionsService, scope, $route, actions, policy;
|
||||
|
||||
function canEdit(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = actions[0].service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_loadbalancer']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
var response = {
|
||||
data: {
|
||||
id: '1'
|
||||
}
|
||||
};
|
||||
var modal = {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
$provide.value('$uibModal', modal);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
$route = $injector.get('$route');
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
rowActionsService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions');
|
||||
actions = rowActionsService.actions();
|
||||
}));
|
||||
|
||||
it('should define correct table row actions', function() {
|
||||
expect(actions.length).toBe(4);
|
||||
expect(actions[0].template.text).toBe('Edit');
|
||||
expect(actions[1].template.text).toBe('Associate Floating IP');
|
||||
expect(actions[2].template.text).toBe('Disassociate Floating IP');
|
||||
expect(actions[3].template.text).toBe('Delete Load Balancer');
|
||||
});
|
||||
|
||||
it('should allow editing an ACTIVE load balancer', function() {
|
||||
expect(canEdit({provisioning_status: 'ACTIVE'})).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow editing a non-ACTIVE load balancer', function() {
|
||||
expect(canEdit({provisioning_status: 'PENDING_UPDATE'})).toBe(false);
|
||||
});
|
||||
|
||||
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 reload table after edit', function() {
|
||||
spyOn($route, 'reload').and.callThrough();
|
||||
actions[0].service.perform();
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.loadbalancers')
|
||||
.controller('LoadBalancerDetailController', LoadBalancerDetailController);
|
||||
|
||||
LoadBalancerDetailController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'$routeParams',
|
||||
'$window',
|
||||
'$scope'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name LoadBalancerDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 load balancers detail page.
|
||||
*
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param rowActions The load balancer row actions service.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param $routeParams The angular $routeParams service.
|
||||
* @param $window Angular's reference to the browser window object.
|
||||
* @param $scope The angular scope object.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function LoadBalancerDetailController(
|
||||
api, rowActions, loadBalancersService, $routeParams, $window, $scope
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
ctrl.actions = rowActions.actions;
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
ctrl.listenersTabActive = $window.listenersTabActive;
|
||||
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
ctrl.loadbalancer = null;
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
api.getLoadBalancer($routeParams.loadbalancerId, true).then(success, fail);
|
||||
}
|
||||
|
||||
function success(response) {
|
||||
ctrl.loadbalancer = response.data;
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
function fail(/*response*/) {
|
||||
ctrl.loadbalancer = null;
|
||||
ctrl.loading = false;
|
||||
ctrl.error = true;
|
||||
}
|
||||
|
||||
// Save the active state of the listeners tab in the global window object so it can stay
|
||||
// active after reloading the route following an action.
|
||||
$scope.$watch(function() {
|
||||
return ctrl.listenersTabActive;
|
||||
}, function(active) {
|
||||
$window.listenersTabActive = active;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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 Load Balancer Detail Controller', function() {
|
||||
var lbaasv2API, $scope, $window, $controller, apiFail;
|
||||
|
||||
function fakeAPI() {
|
||||
return {
|
||||
then: function(success, fail) {
|
||||
if (apiFail && fail) {
|
||||
fail();
|
||||
} else {
|
||||
success({ id: '1234' });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function createController() {
|
||||
return $controller('LoadBalancerDetailController', {
|
||||
$scope: $scope,
|
||||
$window: $window,
|
||||
$routeParams: { loadbalancerId: '1234' }
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
apiFail = false;
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(fakeAPI);
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$window = {};
|
||||
$controller = $injector.get('$controller');
|
||||
}));
|
||||
|
||||
it('should invoke lbaasv2 apis', function() {
|
||||
createController();
|
||||
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('1234', true);
|
||||
});
|
||||
|
||||
it('should save changes to listeners tab active state', function() {
|
||||
var ctrl = createController();
|
||||
expect($window.listenersTabActive).toBeUndefined();
|
||||
expect(ctrl.listenersTabActive).toBeUndefined();
|
||||
ctrl.listenersTabActive = true;
|
||||
$scope.$apply();
|
||||
expect($window.listenersTabActive).toBe(true);
|
||||
ctrl.listenersTabActive = false;
|
||||
$scope.$apply();
|
||||
expect($window.listenersTabActive).toBe(false);
|
||||
});
|
||||
|
||||
it('should set error state', function() {
|
||||
apiFail = true;
|
||||
var ctrl = createController();
|
||||
expect(ctrl.loading).toBe(false);
|
||||
expect(ctrl.error).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -1,61 +0,0 @@
|
||||
<div ng-controller="LoadBalancerDetailController as ctrl">
|
||||
<detail-status loading="ctrl.loading" error="ctrl.error"></detail-status>
|
||||
<div ng-if="!ctrl.loading && !ctrl.error">
|
||||
<div class="page-header">
|
||||
<actions allowed="ctrl.actions" type="row" item="ctrl.loadbalancer"
|
||||
ng-if="ctrl.loadbalancer" class="actions_column pull-right"></actions>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li class="active">{$ ctrl.loadbalancer.name || ctrl.loadbalancer.id $}</li>
|
||||
</ol>
|
||||
<p ng-if="::ctrl.loadbalancer.description">{$ ::ctrl.loadbalancer.description $}</p>
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<strong translate>IP Address</strong>
|
||||
{$ ::ctrl.loadbalancer.vip_address $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Operating Status</strong>
|
||||
{$ ctrl.loadbalancer.operating_status | decode:ctrl.operatingStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Provisioning Status</strong>
|
||||
{$ ctrl.loadbalancer.provisioning_status | decode:ctrl.provisioningStatus $}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<tabset>
|
||||
<tab heading="{$ 'Overview' | translate $}">
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt translate>Provider</dt>
|
||||
<dd>{$ ::ctrl.loadbalancer.provider $}</dd>
|
||||
<dt translate>Admin State Up</dt>
|
||||
<dd>{$ ctrl.loadbalancer.admin_state_up | yesno $}</dd>
|
||||
<dt translate ng-if="ctrl.loadbalancer.floating_ip !== undefined">Floating IP Address</dt>
|
||||
<dd ng-if="ctrl.loadbalancer.floating_ip !== undefined">{$ ctrl.loadbalancer.floating_ip.ip | noValue:('None' | translate) $}</dd>
|
||||
<dt translate>Load Balancer ID</dt>
|
||||
<dd>{$ ::ctrl.loadbalancer.id $}</dd>
|
||||
<dt translate>Subnet ID</dt>
|
||||
<dd>
|
||||
<a target="_self" ng-href="project/networks/subnets/{$ ::ctrl.loadbalancer.vip_subnet_id $}/detail">{$ ::ctrl.loadbalancer.vip_subnet_id $}</a>
|
||||
</dd>
|
||||
<dt translate>Port ID</dt>
|
||||
<dd>
|
||||
<a target="_self" ng-href="project/networks/ports/{$ ::ctrl.loadbalancer.vip_port_id $}/detail">{$ ::ctrl.loadbalancer.vip_port_id $}</a>
|
||||
</dd>
|
||||
<dt translate>Created At</dt>
|
||||
<dd>{$ ::ctrl.loadbalancer.created_at $}</dd>
|
||||
<dt translate>Updated At</dt>
|
||||
<dd>{$ ::ctrl.loadbalancer.updated_at $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</tab>
|
||||
<tab heading="{$ 'Listeners' | translate $}" active="ctrl.listenersTabActive">
|
||||
<ng-include src="'static/dashboard/project/lbaasv2/listeners/table.html'"></ng-include>
|
||||
</tab>
|
||||
</tabset>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.loadbalancers')
|
||||
.controller('LoadBalancerDetailController', LoadBalancerDetailController);
|
||||
|
||||
LoadBalancerDetailController.$inject = [
|
||||
'loadbalancer',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.resourceType',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service',
|
||||
'$q'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name LoadBalancerDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 load balancers detail page.
|
||||
*
|
||||
* @param loadbalancer The loadbalancer object.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param resourceType The load balancer resource type.
|
||||
* @param typeRegistry The horizon type registry service.
|
||||
* @param spinnerService The horizon modal wait spinner service.
|
||||
* @param $q The angular service for promises.
|
||||
*
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function LoadBalancerDetailController(
|
||||
loadbalancer, loadBalancersService, resourceType, typeRegistry,
|
||||
spinnerService, $q
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
ctrl.loadbalancer = loadbalancer;
|
||||
ctrl.listFunctionExtraParams = {
|
||||
loadbalancerId: ctrl.loadbalancer.id
|
||||
};
|
||||
ctrl.resourceType = typeRegistry.getResourceType(resourceType);
|
||||
ctrl.context = {};
|
||||
ctrl.context.identifier = loadbalancer.id;
|
||||
|
||||
ctrl.resultHandler = actionResultHandler;
|
||||
|
||||
function actionResultHandler(returnValue) {
|
||||
return $q.when(returnValue, actionSuccessHandler);
|
||||
}
|
||||
|
||||
function loadData(response) {
|
||||
spinnerService.hideModalSpinner();
|
||||
ctrl.showDetails = true;
|
||||
ctrl.resourceType.initActions();
|
||||
ctrl.loadbalancer = response.data;
|
||||
ctrl.loadbalancer.floating_ip_address = response.data.floating_ip.ip;
|
||||
}
|
||||
|
||||
function actionSuccessHandler(result) {
|
||||
// The action has completed (for whatever "complete" means to that
|
||||
// action. Notice the view doesn't really need to know the semantics of the
|
||||
// particular action because the actions return data in a standard form.
|
||||
// That return includes the id and type of each created, updated, deleted
|
||||
// and failed item.
|
||||
// Currently just refreshes the display each time.
|
||||
if (result) {
|
||||
spinnerService.showModalSpinner(gettext('Please Wait'));
|
||||
ctrl.showDetails = false;
|
||||
ctrl.context.loadPromise = ctrl.resourceType.load(ctrl.context.identifier);
|
||||
ctrl.context.loadPromise.then(loadData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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('LBaaS v2 Load Balancer Detail Controller', function() {
|
||||
var deferred, service, ctrl, scope, $timeout, $q, actionResultService;
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($controller, $rootScope, _$q_, _$timeout_) {
|
||||
$q = _$q_;
|
||||
deferred = $q.defer();
|
||||
service = {
|
||||
getResourceType: function() {
|
||||
return {
|
||||
load: function() { return deferred.promise; },
|
||||
parsePath: function() { return 'my-context'; },
|
||||
itemName: function() { return 'A name'; },
|
||||
initActions: angular.noop
|
||||
};
|
||||
},
|
||||
getDefaultDetailsTemplateUrl: angular.noop
|
||||
};
|
||||
actionResultService = {
|
||||
getIdsOfType: function() { return []; }
|
||||
};
|
||||
$timeout = _$timeout_;
|
||||
scope = $rootScope.$new();
|
||||
ctrl = $controller('LoadBalancerDetailController', {
|
||||
$scope: scope,
|
||||
loadbalancer: { id: '123' },
|
||||
'horizon.framework.conf.resource-type-registry.service': service,
|
||||
'horizon.framework.util.actions.action-result.service': actionResultService,
|
||||
'horizon.framework.widgets.modal-wait-spinner.service': {
|
||||
showModalSpinner: angular.noop,
|
||||
hideModalSpinner: angular.noop
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
it('should create a controller', function() {
|
||||
expect(ctrl).toBeDefined();
|
||||
expect(ctrl.loadbalancer).toBeDefined();
|
||||
});
|
||||
|
||||
describe('resultHandler', function() {
|
||||
|
||||
it('handles empty results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve({});
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles falsy results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve(false);
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles matched results', function() {
|
||||
spyOn(actionResultService, 'getIdsOfType').and.returnValue([1, 2, 3]);
|
||||
var result = $q.defer();
|
||||
result.resolve({some: 'thing'});
|
||||
ctrl.resultHandler(result.promise);
|
||||
deferred.resolve({data: {some: 'data', floating_ip: {}}});
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -0,0 +1,66 @@
|
||||
<div class="page-header">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li class="active">{$ ctrl.loadbalancer.name || ctrl.loadbalancer.id $}</li>
|
||||
</ol>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-9 text-left">
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<strong translate>IP Address</strong>
|
||||
{$ ::ctrl.loadbalancer.vip_address $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Operating Status</strong>
|
||||
{$ ctrl.loadbalancer.operating_status | decode:ctrl.operatingStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Provisioning Status</strong>
|
||||
{$ ctrl.loadbalancer.provisioning_status | decode:ctrl.provisioningStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Admin State Up</strong>
|
||||
{$ ctrl.loadbalancer.admin_state_up | yesno $}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-3 text-right details-item-actions">
|
||||
<actions allowed="ctrl.resourceType.itemActions"
|
||||
type="row"
|
||||
item="ctrl.loadbalancer"
|
||||
ng-if="ctrl.loadbalancer"
|
||||
class="actions_column pull-right"
|
||||
result-handler="ctrl.resultHandler"></actions>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<uib-tabset class="octavia-tabset">
|
||||
<uib-tab heading="{$ 'Overview' | translate $}">
|
||||
<div class="col-md-6 detail">
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::LoadBalancer"
|
||||
cls="dl-horizontal"
|
||||
item="ctrl.loadbalancer"
|
||||
property-groups="[[
|
||||
'id', 'name', 'description', 'project_id', 'created_at', 'updated_at',
|
||||
'vip_port_id', 'vip_subnet_id', 'vip_network_id', 'provider', 'flavor',
|
||||
'floating_ip_address']]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</uib-tab>
|
||||
<uib-tab heading="{$ 'Listeners' | translate $}">
|
||||
<hz-resource-table resource-type-name="OS::Octavia::Listener"
|
||||
track-by="trackBy"
|
||||
list-function-extra-params="ctrl.listFunctionExtraParams">
|
||||
</hz-resource-table>
|
||||
</uib-tab>
|
||||
<!--
|
||||
<uib-tab heading="{$ 'Pools' | translate $}">
|
||||
<hz-resource-table resource-type-name="OS::Octavia::Pool"
|
||||
track-by="trackBy"
|
||||
list-function-extra-params="ctrl.listFunctionExtraParams">
|
||||
</hz-resource-table>
|
||||
</uib-tab>
|
||||
-->
|
||||
</uib-tabset>
|
@ -0,0 +1,9 @@
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::LoadBalancer"
|
||||
item="item"
|
||||
property-groups="[
|
||||
['name', 'id', 'project_id'],
|
||||
['created_at', 'updated_at', 'description'],
|
||||
['vip_network_id', 'vip_subnet_id', 'vip_port_id'],
|
||||
['provider', 'floating_ip_address']]">
|
||||
</hz-resource-property-list>
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@ -26,6 +27,166 @@
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.loadbalancers', []);
|
||||
.module('horizon.dashboard.project.lbaasv2.loadbalancers', [])
|
||||
.constant('horizon.dashboard.project.lbaasv2.loadbalancers.resourceType',
|
||||
'OS::Octavia::LoadBalancer')
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.dashboard.project.lbaasv2.basePath',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.create',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.edit',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.associate-ip',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.disassociate-ip',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.resourceType'
|
||||
];
|
||||
|
||||
function run(
|
||||
registry,
|
||||
basePath,
|
||||
loadBalancerService,
|
||||
createService,
|
||||
editService,
|
||||
associateIpService,
|
||||
disassociateIpService,
|
||||
deleteService,
|
||||
resourceType
|
||||
) {
|
||||
var loadBalancerResourceType = registry.getResourceType(resourceType);
|
||||
|
||||
loadBalancerResourceType
|
||||
.setNames(gettext('Load Balancer'), gettext('Load Balancers'))
|
||||
.setSummaryTemplateUrl(basePath + 'loadbalancers/details/drawer.html')
|
||||
.setProperties(loadBalancerProperties(loadBalancerService))
|
||||
.setListFunction(loadBalancerService.getLoadBalancersPromise)
|
||||
.setLoadFunction(loadBalancerService.getLoadBalancerPromise)
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
urlFunction: loadBalancerService.getDetailsPath
|
||||
})
|
||||
.append({
|
||||
id: 'vip_address',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'operating_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'provisioning_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'admin_state_up',
|
||||
priority: 1
|
||||
});
|
||||
|
||||
loadBalancerResourceType.itemActions
|
||||
.append({
|
||||
id: 'loadBalancerEdit',
|
||||
service: editService,
|
||||
template: {
|
||||
text: gettext('Edit Load Balancer')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'loadBalancerAssociateFloatingIp',
|
||||
service: associateIpService,
|
||||
template: {
|
||||
text: gettext('Associate Floating IP')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'loadBalancerDisassociateFloatingIp',
|
||||
service: disassociateIpService,
|
||||
template: {
|
||||
text: gettext('Disassociate Floating IP')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'loadBalancerDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Load Balancer'),
|
||||
type: 'delete'
|
||||
}
|
||||
});
|
||||
|
||||
loadBalancerResourceType.globalActions
|
||||
.append({
|
||||
id: 'loadBalancerCreate',
|
||||
service: createService,
|
||||
template: {
|
||||
type: 'create',
|
||||
text: gettext('Create Load Balancer')
|
||||
}
|
||||
});
|
||||
|
||||
loadBalancerResourceType.batchActions
|
||||
.append({
|
||||
id: 'loadBalancerBatchDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Load Balancers'),
|
||||
type: 'delete-selected'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadBalancerProperties(loadBalancerService) {
|
||||
return {
|
||||
id: gettext('ID'),
|
||||
name: {
|
||||
label: gettext('Name'),
|
||||
filters: ['noName']
|
||||
},
|
||||
description: {
|
||||
label: gettext('Description'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
provisioning_status: {
|
||||
label: gettext('Provisioning Status'),
|
||||
values: loadBalancerService.provisioningStatus
|
||||
},
|
||||
operating_status: {
|
||||
label: gettext('Operating Status'),
|
||||
values: loadBalancerService.operatingStatus
|
||||
},
|
||||
admin_state_up: {
|
||||
label: gettext('Admin State Up'),
|
||||
filters: ['yesno']
|
||||
},
|
||||
project_id: gettext('Project ID'),
|
||||
created_at: {
|
||||
label: gettext('Created At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
updated_at: {
|
||||
label: gettext('Updated At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
vip_address: gettext('IP Address'),
|
||||
vip_port_id: gettext('Port ID'),
|
||||
vip_subnet_id: gettext('Subnet ID'),
|
||||
vip_network_id: gettext('Network ID'),
|
||||
listeners: gettext('Listeners'),
|
||||
pools: gettext('Pools'),
|
||||
provider: gettext('Provider'),
|
||||
flavor: {
|
||||
label: gettext('Flavor'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
floating_ip_address: {
|
||||
label: gettext('Floating IP'),
|
||||
filters: ['noName']
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@ -22,4 +23,48 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('LBaaS v2 Load Balancers Registry', function () {
|
||||
var registry, resourceType;
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
resourceType = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.resourceType');
|
||||
registry = $injector.get('horizon.framework.conf.resource-type-registry.service');
|
||||
}));
|
||||
|
||||
it('should define resourceType', function () {
|
||||
expect(resourceType).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register item actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).itemActions;
|
||||
expect(actionHasId(actions, 'loadBalancerEdit')).toBe(true);
|
||||
expect(actionHasId(actions, 'loadBalancerAssociateFloatingIp')).toBe(true);
|
||||
expect(actionHasId(actions, 'loadBalancerDisassociateFloatingIp')).toBe(true);
|
||||
expect(actionHasId(actions, 'loadBalancerDelete')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register global actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).globalActions;
|
||||
expect(actionHasId(actions, 'loadBalancerCreate')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register batch actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).batchActions;
|
||||
expect(actionHasId(actions, 'loadBalancerBatchDelete')).toBe(true);
|
||||
});
|
||||
|
||||
function actionHasId(list, value) {
|
||||
return list.filter(matchesId).length === 1;
|
||||
|
||||
function matchesId(action) {
|
||||
if (action.id === value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -29,10 +30,13 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name horizon.dashboard.project.lbaasv2.loadbalancers.service
|
||||
*
|
||||
* @description General service for LBaaS v2 load balancers.
|
||||
*
|
||||
* @param $q The angular service for promises.
|
||||
* @param api The LBaaS V2 service API.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns The load balancers service.
|
||||
*/
|
||||
|
||||
@ -41,7 +45,8 @@
|
||||
ONLINE: gettext('Online'),
|
||||
OFFLINE: gettext('Offline'),
|
||||
DEGRADED: gettext('Degraded'),
|
||||
ERROR: gettext('Error')
|
||||
ERROR: gettext('Error'),
|
||||
NO_MONITOR: gettext('No Monitor')
|
||||
};
|
||||
|
||||
var provisioningStatus = {
|
||||
@ -53,9 +58,37 @@
|
||||
ERROR: gettext('Error')
|
||||
};
|
||||
|
||||
var loadBalancerAlgorithm = {
|
||||
ROUND_ROBIN: gettext('Round Robin'),
|
||||
LEAST_CONNECTIONS: gettext('Least Connections'),
|
||||
SOURCE_IP: gettext('Source IP')
|
||||
};
|
||||
|
||||
var none = {
|
||||
null: gettext('None')
|
||||
};
|
||||
|
||||
var service = {
|
||||
operatingStatus: operatingStatus,
|
||||
provisioningStatus: provisioningStatus,
|
||||
loadBalancerAlgorithm: loadBalancerAlgorithm,
|
||||
none: none,
|
||||
nullFilter: nullFilter,
|
||||
getLoadBalancersPromise: getLoadBalancersPromise,
|
||||
getLoadBalancerPromise: getLoadBalancerPromise,
|
||||
getDetailsPath: getDetailsPath,
|
||||
getListenersPromise: getListenersPromise,
|
||||
getListenerPromise: getListenerPromise,
|
||||
getListenerDetailsPath: getListenerDetailsPath,
|
||||
getPoolsPromise: getPoolsPromise,
|
||||
getPoolPromise: getPoolPromise,
|
||||
getPoolDetailsPath: getPoolDetailsPath,
|
||||
getMembersPromise: getMembersPromise,
|
||||
getMemberPromise: getMemberPromise,
|
||||
getMemberDetailsPath: getMemberDetailsPath,
|
||||
getHealthMonitorPromise: getHealthMonitorPromise,
|
||||
getHealthMonitorsPromise: getHealthMonitorsPromise,
|
||||
getHealthMonitorDetailsPath: getHealthMonitorDetailsPath,
|
||||
isActionable: isActionable
|
||||
};
|
||||
|
||||
@ -63,6 +96,136 @@
|
||||
|
||||
////////////
|
||||
|
||||
function nullFilter(input) {
|
||||
if (none.hasOwnProperty(input)) {
|
||||
return none[input];
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
function getMemberDetailsPath(item) {
|
||||
return 'project/load_balancer/' + item.loadbalancerId +
|
||||
'/listeners/' + item.listenerId +
|
||||
'/pools/' + item.poolId +
|
||||
'/members/' + item.id;
|
||||
}
|
||||
|
||||
function getMembersPromise(params) {
|
||||
return api.getMembers(params.poolId).then(modifyResponse);
|
||||
|
||||
function modifyResponse(response) {
|
||||
return {data: {items: response.data.items.map(modifyItem)}};
|
||||
|
||||
function modifyItem(item) {
|
||||
item.trackBy = item.id + item.updated_at;
|
||||
item.loadbalancerId = params.loadbalancerId;
|
||||
item.listenerId = params.listenerId;
|
||||
item.poolId = params.poolId;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMemberPromise(poolId, memberId) {
|
||||
return api.getMember(poolId, memberId);
|
||||
}
|
||||
|
||||
function getHealthMonitorDetailsPath(item) {
|
||||
return 'project/load_balancer/' + item.loadbalancerId +
|
||||
'/listeners/' + item.listenerId +
|
||||
'/pools/' + item.poolId +
|
||||
'/healthmonitors/' + item.id;
|
||||
}
|
||||
|
||||
function getHealthMonitorsPromise(params) {
|
||||
return api.getHealthMonitors(params.poolId).then(modifyResponse);
|
||||
|
||||
function modifyResponse(response) {
|
||||
return {data: {items: response.data.items.map(modifyItem)}};
|
||||
|
||||
function modifyItem(item) {
|
||||
item.trackBy = item.id + item.updated_at;
|
||||
item.loadbalancerId = params.loadbalancerId;
|
||||
item.listenerId = params.listenerId;
|
||||
item.poolId = params.poolId;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getHealthMonitorPromise(identifier) {
|
||||
return api.getHealthMonitor(identifier);
|
||||
}
|
||||
|
||||
function getPoolsPromise(params) {
|
||||
return api.getPools(params.loadbalancerId, params.listenerId).then(modifyResponse);
|
||||
|
||||
function modifyResponse(response) {
|
||||
return {data: {items: response.data.items.map(modifyItem)}};
|
||||
|
||||
function modifyItem(item) {
|
||||
item.trackBy = item.id + item.updated_at;
|
||||
item.loadbalancerId = params.loadbalancerId;
|
||||
item.listenerId = params.listenerId;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getPoolPromise(identifier) {
|
||||
return api.getPool(identifier);
|
||||
}
|
||||
|
||||
function getPoolDetailsPath(item) {
|
||||
return 'project/load_balancer/' +
|
||||
item.loadbalancerId + '/listeners/' +
|
||||
item.listeners[0].id + '/pools/' + item.id;
|
||||
}
|
||||
|
||||
function getListenersPromise(params) {
|
||||
return api.getListeners(params.loadbalancerId).then(modifyResponse);
|
||||
|
||||
function modifyResponse(response) {
|
||||
return {data: {items: response.data.items.map(modifyItem)}};
|
||||
|
||||
function modifyItem(item) {
|
||||
item.trackBy = item.id + item.updated_at;
|
||||
item.loadbalancerId = params.loadbalancerId;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getListenerPromise(identifier) {
|
||||
return api.getListener(identifier);
|
||||
}
|
||||
|
||||
function getListenerDetailsPath(item) {
|
||||
return 'project/load_balancer/' + item.loadbalancerId + '/listeners/' + item.id;
|
||||
}
|
||||
|
||||
function getLoadBalancersPromise() {
|
||||
return api.getLoadBalancers(true).then(modifyResponse);
|
||||
|
||||
function modifyResponse(response) {
|
||||
return {data: {items: response.data.items.map(modifyItem)}};
|
||||
|
||||
function modifyItem(item) {
|
||||
item.trackBy = item.id + item.updated_at;
|
||||
item.floating_ip_address = item.floating_ip.ip;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getLoadBalancerPromise(identifier) {
|
||||
return api.getLoadBalancer(identifier, true);
|
||||
}
|
||||
|
||||
function getDetailsPath(item) {
|
||||
return 'project/load_balancer/' + item.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name horizon.dashboard.project.lbaasv2.loadbalancers.service.isActionable
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -17,32 +18,15 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Load Balancers Service', function() {
|
||||
var service, $q, $scope;
|
||||
var service, $q, $scope, api;
|
||||
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
|
||||
getLoadBalancer: function(index) {
|
||||
var loadbalancers = [{ provisioning_status: 'ACTIVE' },
|
||||
{ provisioning_status: 'PENDING_UPDATE' }];
|
||||
|
||||
var deferred = $q.defer();
|
||||
deferred.resolve({ data: loadbalancers[index] });
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
$q = $injector.get('$q');
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.service');
|
||||
api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
}));
|
||||
|
||||
it('should define value mappings', function() {
|
||||
@ -50,16 +34,184 @@
|
||||
expect(service.provisioningStatus).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow checking status of load balancer', function() {
|
||||
it('should filter null property', function() {
|
||||
expect(service.nullFilter('null')).toBe(gettext('None'));
|
||||
expect(service.nullFilter('something else')).toBe('something else');
|
||||
});
|
||||
|
||||
it('getDetailsPath creates urls using the item\'s ID', function() {
|
||||
var myItem = {id: '1234'};
|
||||
expect(service.getDetailsPath(myItem)).toBe('project/load_balancer/1234');
|
||||
});
|
||||
|
||||
it("getLoadBalancersPromise provides a promise", inject(function($timeout) {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getLoadBalancers').and.returnValue(deferred.promise);
|
||||
var result = service.getLoadBalancersPromise({});
|
||||
deferred.resolve({data: {items: [{id: 1, updated_at: 'feb8', floating_ip: {}}]}});
|
||||
$timeout.flush();
|
||||
expect(result.$$state.value.data.items[0].id).toBe(1);
|
||||
expect(result.$$state.value.data.items[0].updated_at).toBe('feb8');
|
||||
expect(result.$$state.value.data.items[0].trackBy).toBe('1feb8');
|
||||
}));
|
||||
|
||||
it("getLoadBalancerPromise provides a promise", inject(function() {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getLoadBalancer').and.returnValue(deferred.promise);
|
||||
var result = service.getLoadBalancerPromise({});
|
||||
deferred.resolve({data: {id: 1, updated_at: 'feb8', floating_ip: {}}});
|
||||
expect(result.$$state.value.data.id).toBe(1);
|
||||
expect(result.$$state.value.data.updated_at).toBe('feb8');
|
||||
}));
|
||||
|
||||
it('getListenerDetailsPath creates urls using the item\'s ID', function() {
|
||||
var myItem = {loadbalancerId: '123', id: '456'};
|
||||
expect(service.getListenerDetailsPath(myItem))
|
||||
.toBe('project/load_balancer/123/listeners/456');
|
||||
});
|
||||
|
||||
it("getListenersPromise provides a promise", inject(function($timeout) {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getListeners').and.returnValue(deferred.promise);
|
||||
var result = service.getListenersPromise({loadbalancerId: 3});
|
||||
deferred.resolve({data: {items: [{id: 1, updated_at: 'feb8'}]}});
|
||||
$timeout.flush();
|
||||
expect(result.$$state.value.data.items[0].id).toBe(1);
|
||||
expect(result.$$state.value.data.items[0].updated_at).toBe('feb8');
|
||||
expect(result.$$state.value.data.items[0].trackBy).toBe('1feb8');
|
||||
expect(result.$$state.value.data.items[0].loadbalancerId).toBe(3);
|
||||
}));
|
||||
|
||||
it("getListenerPromise provides a promise", inject(function() {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getListener').and.returnValue(deferred.promise);
|
||||
var result = service.getListenerPromise({loadbalancerId: 3});
|
||||
deferred.resolve({data: {id: 1, updated_at: 'feb8', floating_ip: {}}});
|
||||
expect(result.$$state.value.data.id).toBe(1);
|
||||
expect(result.$$state.value.data.updated_at).toBe('feb8');
|
||||
}));
|
||||
|
||||
it('getPoolDetailsPath creates urls using the item\'s ID', function() {
|
||||
var myItem = {loadbalancerId: '123', id: '789', listeners: [{id: '456'}]};
|
||||
expect(service.getPoolDetailsPath(myItem))
|
||||
.toBe('project/load_balancer/123/listeners/456/pools/789');
|
||||
});
|
||||
|
||||
it("getPoolsPromise provides a promise", inject(function($timeout) {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getPools').and.returnValue(deferred.promise);
|
||||
var result = service.getPoolsPromise({loadbalancerId: 3});
|
||||
deferred.resolve({data: {items: [{id: 1, updated_at: 'feb8'}]}});
|
||||
$timeout.flush();
|
||||
expect(result.$$state.value.data.items[0].id).toBe(1);
|
||||
expect(result.$$state.value.data.items[0].updated_at).toBe('feb8');
|
||||
expect(result.$$state.value.data.items[0].trackBy).toBe('1feb8');
|
||||
expect(result.$$state.value.data.items[0].loadbalancerId).toBe(3);
|
||||
}));
|
||||
|
||||
it("getPoolPromise provides a promise", inject(function() {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getPool').and.returnValue(deferred.promise);
|
||||
var result = service.getPoolPromise({loadbalancerId: 3});
|
||||
deferred.resolve({data: {id: 1, updated_at: 'feb8'}});
|
||||
expect(result.$$state.value.data.id).toBe(1);
|
||||
expect(result.$$state.value.data.updated_at).toBe('feb8');
|
||||
}));
|
||||
|
||||
it('getMemberDetailsPath creates urls using the item\'s ID', function() {
|
||||
var myItem = {
|
||||
loadbalancerId: '1',
|
||||
listenerId: '2',
|
||||
poolId: '3',
|
||||
id: '4'
|
||||
};
|
||||
expect(service.getMemberDetailsPath(myItem))
|
||||
.toBe('project/load_balancer/1/listeners/2/pools/3/members/4');
|
||||
});
|
||||
|
||||
it("getMembersPromise provides a promise", inject(function($timeout) {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getMembers').and.returnValue(deferred.promise);
|
||||
var result = service.getMembersPromise({
|
||||
loadbalancerId: 1,
|
||||
listenerId: 2,
|
||||
poolId: 3
|
||||
});
|
||||
deferred.resolve({data: {items: [{id: 4, updated_at: 'feb8'}]}});
|
||||
$timeout.flush();
|
||||
expect(result.$$state.value.data.items[0].id).toBe(4);
|
||||
expect(result.$$state.value.data.items[0].updated_at).toBe('feb8');
|
||||
expect(result.$$state.value.data.items[0].trackBy).toBe('4feb8');
|
||||
expect(result.$$state.value.data.items[0].loadbalancerId).toBe(1);
|
||||
expect(result.$$state.value.data.items[0].listenerId).toBe(2);
|
||||
expect(result.$$state.value.data.items[0].poolId).toBe(3);
|
||||
}));
|
||||
|
||||
it("getMemberPromise provides a promise", inject(function() {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getMember').and.returnValue(deferred.promise);
|
||||
var result = service.getMemberPromise(2, 1);
|
||||
deferred.resolve({data: {id: 1, updated_at: 'feb8'}});
|
||||
expect(result.$$state.value.data.id).toBe(1);
|
||||
expect(result.$$state.value.data.updated_at).toBe('feb8');
|
||||
}));
|
||||
|
||||
it('getHealthMonitorDetailsPath creates urls using the item\'s ID', function() {
|
||||
var myItem = {
|
||||
loadbalancerId: '1',
|
||||
listenerId: '2',
|
||||
poolId: '3',
|
||||
id: '4'
|
||||
};
|
||||
expect(service.getHealthMonitorDetailsPath(myItem))
|
||||
.toBe('project/load_balancer/1/listeners/2/pools/3/healthmonitors/4');
|
||||
});
|
||||
|
||||
it("getHealthMonitorsPromise provides a promise", inject(function($timeout) {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getHealthMonitors').and.returnValue(deferred.promise);
|
||||
var result = service.getHealthMonitorsPromise({
|
||||
loadbalancerId: 1,
|
||||
listenerId: 2,
|
||||
poolId: 3
|
||||
});
|
||||
deferred.resolve({data: {items: [{id: 4, updated_at: 'feb8'}]}});
|
||||
$timeout.flush();
|
||||
expect(result.$$state.value.data.items[0].id).toBe(4);
|
||||
expect(result.$$state.value.data.items[0].updated_at).toBe('feb8');
|
||||
expect(result.$$state.value.data.items[0].trackBy).toBe('4feb8');
|
||||
expect(result.$$state.value.data.items[0].loadbalancerId).toBe(1);
|
||||
expect(result.$$state.value.data.items[0].listenerId).toBe(2);
|
||||
expect(result.$$state.value.data.items[0].poolId).toBe(3);
|
||||
}));
|
||||
|
||||
it("getHealthMonitorPromise provides a promise", inject(function() {
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getHealthMonitor').and.returnValue(deferred.promise);
|
||||
var result = service.getHealthMonitorPromise(1);
|
||||
deferred.resolve({data: {id: 1, updated_at: 'feb8'}});
|
||||
expect(result.$$state.value.data.id).toBe(1);
|
||||
expect(result.$$state.value.data.updated_at).toBe('feb8');
|
||||
}));
|
||||
|
||||
it('should allow checking active status of load balancer', function() {
|
||||
var active = null;
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getLoadBalancer').and.returnValue(deferred.promise);
|
||||
deferred.resolve({data: { provisioning_status: 'ACTIVE'}});
|
||||
service.isActionable(0).then(function() {
|
||||
active = true;
|
||||
});
|
||||
$scope.$apply();
|
||||
expect(active).toBe(true);
|
||||
});
|
||||
|
||||
active = null;
|
||||
service.isActionable(1).then(angular.noop, function() {
|
||||
it('should allow checking transitional status of load balancer', function() {
|
||||
var active = null;
|
||||
var deferred = $q.defer();
|
||||
spyOn(api, 'getLoadBalancer').and.returnValue(deferred.promise);
|
||||
deferred.resolve({data: { provisioning_status: 'PENDING_UPDATE'}});
|
||||
service.isActionable(0).then(angular.noop, function() {
|
||||
active = false;
|
||||
});
|
||||
$scope.$apply();
|
||||
|
@ -0,0 +1,4 @@
|
||||
<hz-resource-panel resource-type-name="OS::Octavia::LoadBalancer">
|
||||
<hz-resource-table resource-type-name="OS::Octavia::LoadBalancer"
|
||||
track-by="trackBy"></hz-resource-table>
|
||||
</hz-resource-panel>
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.loadbalancers')
|
||||
.controller('LoadBalancersTableController', LoadBalancersTableController);
|
||||
|
||||
LoadBalancersTableController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name LoadBalancersTableController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 load balancers table. Serves as the focal point for table actions.
|
||||
*
|
||||
* @param api The LBaaS V2 service API.
|
||||
* @param batchActions The load balancer batch actions service.
|
||||
* @param rowActions The load balancer row actions service.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function LoadBalancersTableController(api, batchActions, rowActions, loadBalancersService) {
|
||||
|
||||
var ctrl = this;
|
||||
ctrl.items = [];
|
||||
ctrl.src = [];
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
ctrl.checked = {};
|
||||
ctrl.batchActions = batchActions;
|
||||
ctrl.rowActions = rowActions;
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
ctrl.src = [];
|
||||
ctrl.loading = true;
|
||||
api.getLoadBalancers(true).then(success, fail);
|
||||
}
|
||||
|
||||
function success(response) {
|
||||
ctrl.src = response.data.items;
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
function fail(/*response*/) {
|
||||
ctrl.src = [];
|
||||
ctrl.error = true;
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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 Load Balancers Table Controller', function() {
|
||||
var controller, lbaasv2API, scope;
|
||||
var items = [{ foo: 'bar' }];
|
||||
var apiFail = false;
|
||||
|
||||
function fakeAPI() {
|
||||
return {
|
||||
then: function(success, fail) {
|
||||
if (apiFail && fail) {
|
||||
fail();
|
||||
} else {
|
||||
success({ data: { items: items } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
controller = $injector.get('$controller');
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
spyOn(lbaasv2API, 'getLoadBalancers').and.callFake(fakeAPI);
|
||||
}));
|
||||
|
||||
function createController() {
|
||||
return controller('LoadBalancersTableController', { $scope: scope });
|
||||
}
|
||||
|
||||
it('should initialize correctly', function() {
|
||||
var ctrl = createController();
|
||||
expect(ctrl.items).toEqual([]);
|
||||
expect(ctrl.src).toEqual(items);
|
||||
expect(ctrl.loading).toBe(false);
|
||||
expect(ctrl.error).toBe(false);
|
||||
expect(ctrl.checked).toEqual({});
|
||||
expect(ctrl.batchActions).toBeDefined();
|
||||
expect(ctrl.rowActions).toBeDefined();
|
||||
expect(ctrl.operatingStatus).toBeDefined();
|
||||
expect(ctrl.provisioningStatus).toBeDefined();
|
||||
});
|
||||
|
||||
it('should invoke lbaasv2 apis', function() {
|
||||
var ctrl = createController();
|
||||
expect(lbaasv2API.getLoadBalancers).toHaveBeenCalled();
|
||||
expect(ctrl.src.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should show error if loading fails', function() {
|
||||
apiFail = true;
|
||||
var ctrl = createController();
|
||||
expect(ctrl.src.length).toBe(0);
|
||||
expect(ctrl.error).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,155 +0,0 @@
|
||||
<hz-page-header header="{$ 'Load Balancers' | translate $}"></hz-page-header>
|
||||
|
||||
<table ng-controller="LoadBalancersTableController as table"
|
||||
hz-table ng-cloak
|
||||
st-table="table.items"
|
||||
st-safe-src="table.src"
|
||||
default-sort="name"
|
||||
default-sort-reverse="false"
|
||||
class="table table-striped table-rsp table-detail">
|
||||
<!--
|
||||
TODO(jpomero): This table pattern does not allow for extensibility and should be revisited
|
||||
once horizon implements a better one.
|
||||
-->
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<!--
|
||||
Table-batch-actions:
|
||||
This is where batch actions like searching, creating, and deleting.
|
||||
-->
|
||||
<th colspan="9" class="search-header">
|
||||
<hz-search-bar icon-classes="fa-search">
|
||||
<actions allowed="table.batchActions.actions" type="batch"></actions>
|
||||
</hz-search-bar>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<!--
|
||||
Table-column-headers:
|
||||
This is where we declaratively define the table column headers.
|
||||
Include select-col if you want to select all.
|
||||
Include expander if you want to inline details.
|
||||
Include action-col if you want to perform actions.
|
||||
-->
|
||||
<th class="multi_select_column">
|
||||
<input type="checkbox" hz-select-all="table.items">
|
||||
</th>
|
||||
|
||||
<th class="expander"></th>
|
||||
|
||||
<th class="rsp-p1" st-sort="name" st-sort-default="name" translate>Name</th>
|
||||
<th class="rsp-p1" st-sort="description" translate>Description</th>
|
||||
<th class="rsp-p1" st-sort="operating_status" translate>Operating Status</th>
|
||||
<th class="rsp-p1" st-sort="provisioning_status" translate>Provisioning Status</th>
|
||||
<th class="rsp-p2" st-sort="vip_address" translate>IP Address</th>
|
||||
<th class="rsp-p2" st-sort="listeners.length" translate>Listeners</th>
|
||||
<th class="actions_column" translate>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<!--
|
||||
Table-rows:
|
||||
This is where we declaratively define the table columns.
|
||||
Include select-col if you want to select all.
|
||||
Include expander if you want to inline details.
|
||||
Include action-col if you want to perform actions.
|
||||
rsp-p1 rsp-p2 are responsive priority as user resizes window.
|
||||
-->
|
||||
<tr ng-repeat-start="item in table.items track by item.id"
|
||||
ng-class="{'st-selected': checked[item.id]}">
|
||||
|
||||
<td class="multi_select_column">
|
||||
<input type="checkbox"
|
||||
ng-model="tCtrl.selections[item.id].checked"
|
||||
hz-select="item">
|
||||
</td>
|
||||
<td class="expander">
|
||||
<span class="fa fa-chevron-right"
|
||||
hz-expand-detail
|
||||
duration="200">
|
||||
</span>
|
||||
</td>
|
||||
<td class="rsp-p1"><a ng-href="project/load_balancer/{$ ::item.id $}">{$ ::(item.name || item.id) $}</a></td>
|
||||
<td class="rsp-p1">{$ ::item.description | noValue $}</td>
|
||||
<td class="rsp-p1">{$ ::item.operating_status | decode:table.operatingStatus $}</td>
|
||||
<td class="rsp-p1">{$ ::item.provisioning_status | decode:table.provisioningStatus $}</td>
|
||||
<td class="rsp-p2">{$ ::item.vip_address $}</td>
|
||||
<td class="rsp-p2">{$ item.listeners.length $}</td>
|
||||
<td class="actions_column">
|
||||
<!--
|
||||
Table-row-action-column:
|
||||
Actions taken here apply to a single item/row.
|
||||
-->
|
||||
<actions allowed="table.rowActions.actions" type="row" item="item"></actions>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr ng-repeat-end class="detail-row">
|
||||
<!--
|
||||
Detail-row:
|
||||
Contains detailed information on this item.
|
||||
Can be toggled using the chevron button.
|
||||
Ensure colspan is greater or equal to number of column-headers.
|
||||
-->
|
||||
<td class="detail" colspan="9">
|
||||
<!--
|
||||
The responsive columns that disappear typically should reappear here
|
||||
with the same responsive priority that they disappear.
|
||||
E.g. table header with rsp-p2 should be here with rsp-alt-p2
|
||||
-->
|
||||
<div class="row">
|
||||
<span class="rsp-alt-p2">
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>IP Address</dt>
|
||||
<dd>{$ ::item.vip_address $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Listeners</dt>
|
||||
<dd>{$ item.listeners.length $}</dd>
|
||||
</dl>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Provider</dt>
|
||||
<dd>{$ ::item.provider $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2" ng-if="item.floating_ip !== undefined">
|
||||
<dt translate>Floating IP Address</dt>
|
||||
<dd>{$ item.floating_ip.ip || 'None' | translate $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Admin State Up</dt>
|
||||
<dd>{$ ::item.admin_state_up | yesno $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>ID</dt>
|
||||
<dd>{$ ::item.id $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Subnet ID</dt>
|
||||
<dd><a target="_self" ng-href="project/networks/subnets/{$ ::item.vip_subnet_id $}/detail">{$ ::item.vip_subnet_id $}</a></dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Port ID</dt>
|
||||
<dd><a target="_self" ng-href="project/networks/ports/{$ ::item.vip_port_id $}/detail">{$ ::item.vip_port_id $}</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr table-status table="table" column-count="9"></tr>
|
||||
|
||||
</tbody>
|
||||
<!--
|
||||
Table-footer:
|
||||
This is where we display number of items and pagination controls.
|
||||
-->
|
||||
<tfoot hz-table-footer items="table.items"></tfoot>
|
||||
|
||||
</table>
|
@ -1,73 +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.members')
|
||||
.factory('horizon.dashboard.project.lbaasv2.members.actions.batchActions',
|
||||
tableBatchActions);
|
||||
|
||||
tableBatchActions.$inject = [
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.pools.actions.batchActions
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the Members table batch actions.
|
||||
*
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param updateMemberListService The LBaaS v2 update member list service.
|
||||
* @returns Members table batch actions service object.
|
||||
*/
|
||||
|
||||
function tableBatchActions(
|
||||
gettext, loadBalancersService, updateMemberListService
|
||||
) {
|
||||
var loadBalancerIsActionable, loadBalancerId;
|
||||
|
||||
var service = {
|
||||
actions: actions,
|
||||
init: init
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function init(_loadBalancerId_) {
|
||||
loadBalancerId = _loadBalancerId_;
|
||||
loadBalancerIsActionable = loadBalancersService.isActionable(loadBalancerId);
|
||||
return service;
|
||||
}
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: updateMemberListService.init(loadBalancerIsActionable).update,
|
||||
template: {
|
||||
text: gettext('Add/Remove Pool Members')
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -1,67 +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('LBaaS v2 Members Table Batch Actions Service', function() {
|
||||
var actions;
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
var response = {
|
||||
data: {
|
||||
id: '1'
|
||||
}
|
||||
};
|
||||
var modal = {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func(response);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
$provide.value('$uibModal', modal);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
var batchActionsService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.batchActions');
|
||||
actions = batchActionsService.actions();
|
||||
}));
|
||||
|
||||
it('should define correct table batch actions', function() {
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions[0].template.text).toBe('Add/Remove Pool Members');
|
||||
});
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
actions.forEach(function(action) {
|
||||
expect(action.service.allowed).toBeDefined();
|
||||
expect(action.service.perform).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -21,9 +21,9 @@
|
||||
.factory('horizon.dashboard.project.lbaasv2.members.actions.delete', deleteService);
|
||||
|
||||
deleteService.$inject = [
|
||||
'$q',
|
||||
'horizon.dashboard.project.lbaasv2.members.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'$location',
|
||||
'$route',
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
@ -33,22 +33,26 @@
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.members.actions.deleteService
|
||||
*
|
||||
* @description
|
||||
* Brings up the delete member confirmation modal dialog.
|
||||
* On submit, deletes selected member.
|
||||
* On cancel, does nothing.
|
||||
* @param $q The angular service for promises.
|
||||
*
|
||||
* @param resourceType The member resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param $location The angular $location service.
|
||||
* @param $route The angular $route service.
|
||||
* @param deleteModal The horizon delete modal service.
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns The load balancers table delete service.
|
||||
*/
|
||||
|
||||
function deleteService($q, $location, $route, deleteModal, api, policy, gettext) {
|
||||
var loadbalancerId, listenerId, poolId, statePromise;
|
||||
function deleteService(resourceType, actionResultService,
|
||||
$location, deleteModal, api, policy, gettext) {
|
||||
var loadbalancerId, listenerId, poolId;
|
||||
var context = {
|
||||
labels: {
|
||||
title: gettext('Confirm Delete Member'),
|
||||
@ -66,46 +70,51 @@
|
||||
var service = {
|
||||
perform: perform,
|
||||
allowed: allowed,
|
||||
init: init
|
||||
deleteResult: deleteResult // exposed just for testing
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function init(_loadbalancerId_, _listenerId_, _poolId_, _statePromise_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
listenerId = _listenerId_;
|
||||
poolId = _poolId_;
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
}
|
||||
|
||||
function perform(item) {
|
||||
deleteModal.open({ $emit: actionComplete }, [item], context);
|
||||
}
|
||||
|
||||
function allowed(/*item*/) {
|
||||
return $q.all([
|
||||
statePromise,
|
||||
// This rule is made up and should therefore always pass. I assume at some point there
|
||||
// will be a valid rule similar to this that we will want to use.
|
||||
policy.ifAllowed({ rules: [['neutron', 'pool_member_delete']] })
|
||||
]);
|
||||
// This rule is made up and should therefore always pass. I assume at some point there
|
||||
// will be a valid rule similar to this that we will want to use.
|
||||
return policy.ifAllowed({ rules: [['neutron', 'pool_member_delete']] });
|
||||
}
|
||||
|
||||
function perform(items, scope) {
|
||||
var members = angular.isArray(items) ? items : [items];
|
||||
members.map(function(item) {
|
||||
loadbalancerId = item.loadbalancerId;
|
||||
listenerId = item.listenerId;
|
||||
poolId = item.poolId;
|
||||
});
|
||||
return deleteModal.open(scope, members, context).then(deleteResult);
|
||||
}
|
||||
|
||||
function deleteResult(deleteModalResult) {
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
var actionResult = actionResultService.getActionResult();
|
||||
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||
actionResult.deleted(resourceType, item.context.id);
|
||||
});
|
||||
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||
actionResult.failed(resourceType, item.context.id);
|
||||
});
|
||||
|
||||
if (actionResult.result.failed.length === 0 && actionResult.result.deleted.length > 0) {
|
||||
var path = 'project/load_balancer/' + loadbalancerId +
|
||||
'/listeners/' + listenerId +
|
||||
'/pools/' + poolId;
|
||||
$location.path(path);
|
||||
}
|
||||
return actionResult.result;
|
||||
}
|
||||
|
||||
function deleteItem(id) {
|
||||
return api.deleteMember(poolId, id);
|
||||
}
|
||||
|
||||
function actionComplete(eventType) {
|
||||
if (eventType === context.successEvent) {
|
||||
// Success, go back to pool details page
|
||||
var path = 'project/load_balancer/' +
|
||||
loadbalancerId + '/listeners/' + listenerId + '/pools/' + poolId;
|
||||
$location.path(path);
|
||||
}
|
||||
$route.reload();
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -17,138 +17,87 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Member Delete Service', function() {
|
||||
var service, policy, modal, lbaasv2Api, $scope, $location, $q, toast, member;
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(makePromise());
|
||||
var promise = service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
$scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'pool_member_delete']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
function makePromise(reject) {
|
||||
var def = $q.defer();
|
||||
def[reject ? 'reject' : 'resolve']();
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
function isActionable(id) {
|
||||
if (id === 'active') {
|
||||
return $q.when();
|
||||
} else {
|
||||
return $q.reject();
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
beforeEach(module('horizon.framework'));
|
||||
|
||||
beforeEach(function() {
|
||||
member = { id: '1', name: 'Member1' };
|
||||
});
|
||||
var deleteModalService, service, lbaasv2API, policyAPI, $location;
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: makePromise()
|
||||
};
|
||||
}
|
||||
});
|
||||
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
|
||||
deleteMember: function() {
|
||||
return makePromise();
|
||||
}
|
||||
});
|
||||
$provide.value('$location', {
|
||||
path: function() {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
modal = $injector.get('horizon.framework.widgets.modal.deleteModalService');
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$location = $injector.get('$location');
|
||||
$q = $injector.get('$q');
|
||||
toast = $injector.get('horizon.framework.widgets.toast.service');
|
||||
beforeEach(inject(function($injector) {
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.members.actions.delete');
|
||||
service.init('1', '2', '3', isActionable('active'));
|
||||
$scope.$apply();
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
deleteModalService = $injector.get('horizon.framework.widgets.modal.deleteModalService');
|
||||
policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
$location = $injector.get('$location');
|
||||
}));
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
expect(service.allowed).toBeDefined();
|
||||
expect(service.perform).toBeDefined();
|
||||
describe('perform method', function() {
|
||||
beforeEach(function () {
|
||||
// just need for this to return something that looks like a promise but does nothing
|
||||
spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop});
|
||||
});
|
||||
|
||||
it('should open the modal with correct label', function () {
|
||||
service.perform({name: 'spam'});
|
||||
var labels = deleteModalService.open.calls.argsFor(0)[2].labels;
|
||||
expect(deleteModalService.open).toHaveBeenCalled();
|
||||
angular.forEach(labels, function eachLabel(label) {
|
||||
expect(label.toLowerCase()).toContain('member');
|
||||
});
|
||||
});
|
||||
|
||||
it('should open the delete modal with correct entities', function () {
|
||||
service.perform([{name: 'one'}, {name: 'two'}]);
|
||||
var entities = deleteModalService.open.calls.argsFor(0)[1];
|
||||
expect(deleteModalService.open).toHaveBeenCalled();
|
||||
expect(entities.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should pass in a function that deletes an member', function () {
|
||||
spyOn(lbaasv2API, 'deleteMember').and.callFake(angular.noop);
|
||||
service.perform({poolId: 2, id: 1, name: 'one'});
|
||||
var contextArg = deleteModalService.open.calls.argsFor(0)[2];
|
||||
var deleteFunction = contextArg.deleteEntity;
|
||||
deleteFunction(1);
|
||||
expect(lbaasv2API.deleteMember).toHaveBeenCalledWith(2, 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow deleting member from load balancer in ACTIVE state', function() {
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow deleting member from load balancer in a PENDING state', function() {
|
||||
service.init('1', '2', '3', isActionable('pending'));
|
||||
expect(allowed()).toBe(false);
|
||||
});
|
||||
|
||||
it('should open the delete modal', function() {
|
||||
spyOn(modal, 'open');
|
||||
service.perform(member);
|
||||
$scope.$apply();
|
||||
expect(modal.open.calls.count()).toBe(1);
|
||||
var args = modal.open.calls.argsFor(0);
|
||||
expect(args.length).toBe(3);
|
||||
expect(args[0]).toEqual({ $emit: jasmine.any(Function) });
|
||||
expect(args[1]).toEqual([member]);
|
||||
expect(args[2]).toEqual(jasmine.objectContaining({
|
||||
labels: jasmine.any(Object),
|
||||
deleteEntity: jasmine.any(Function)
|
||||
}));
|
||||
expect(args[2].labels.title).toBe('Confirm Delete Member');
|
||||
});
|
||||
|
||||
it('should pass function to modal that deletes the member', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteMember').and.callThrough();
|
||||
service.perform(member);
|
||||
$scope.$apply();
|
||||
expect(lbaasv2Api.deleteMember.calls.count()).toBe(1);
|
||||
expect(lbaasv2Api.deleteMember).toHaveBeenCalledWith('3', '1');
|
||||
});
|
||||
|
||||
it('should show message if any items fail to be deleted', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteMember').and.returnValue(makePromise(true));
|
||||
spyOn(toast, 'add');
|
||||
service.perform(member);
|
||||
$scope.$apply();
|
||||
expect(modal.open).toHaveBeenCalled();
|
||||
expect(lbaasv2Api.deleteMember.calls.count()).toBe(1);
|
||||
expect(toast.add).toHaveBeenCalledWith('error', 'The following member could not ' +
|
||||
'be deleted: Member1.');
|
||||
});
|
||||
|
||||
it('should return to listener details after delete', function() {
|
||||
it('should handle the action result properly', function() {
|
||||
spyOn($location, 'path');
|
||||
spyOn(toast, 'add');
|
||||
service.perform(member);
|
||||
$scope.$apply();
|
||||
expect($location.path).toHaveBeenCalledWith('project/load_balancer/1/listeners/2/pools/3');
|
||||
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted member: Member1.');
|
||||
spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop});
|
||||
spyOn(lbaasv2API, 'deleteMember').and.callFake(angular.noop);
|
||||
service.perform({loadbalancerId: 1, listenerId: 2, poolId: 3, id: 1, name: 'one'});
|
||||
var result = service.deleteResult({
|
||||
fail: [],
|
||||
pass: [{
|
||||
context: {
|
||||
id: 1
|
||||
}
|
||||
}]
|
||||
});
|
||||
var path = 'project/load_balancer/1/listeners/2/pools/3';
|
||||
expect($location.path).toHaveBeenCalledWith(path);
|
||||
expect(result.deleted[0].id).toBe(1);
|
||||
result = service.deleteResult({
|
||||
pass: [],
|
||||
fail: [{
|
||||
context: {
|
||||
id: 1
|
||||
}
|
||||
}]
|
||||
});
|
||||
expect(result.failed[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
describe('allow method', function() {
|
||||
it('should use default policy if batch action', function () {
|
||||
spyOn(policyAPI, 'ifAllowed');
|
||||
service.allowed();
|
||||
expect(policyAPI.ifAllowed).toHaveBeenCalled();
|
||||
});
|
||||
}); // end of allowed
|
||||
|
||||
}); // end of delete
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -18,13 +19,13 @@
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.members')
|
||||
.factory('horizon.dashboard.project.lbaasv2.members.actions.edit-member.modal.service',
|
||||
.factory('horizon.dashboard.project.lbaasv2.members.actions.edit-member',
|
||||
modalService);
|
||||
|
||||
modalService.$inject = [
|
||||
'$q',
|
||||
'horizon.dashboard.project.lbaasv2.members.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'$uibModal',
|
||||
'$route',
|
||||
'horizon.dashboard.project.lbaasv2.basePath',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
@ -38,9 +39,9 @@
|
||||
* @description
|
||||
* Provides the service for the pool member Edit Member action.
|
||||
*
|
||||
* @param $q The angular service for promises.
|
||||
* @param resourceType The member resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param $uibModal The angular bootstrap $uibModal service.
|
||||
* @param $route The angular $route service.
|
||||
* @param basePath The LBaaS v2 module base path.
|
||||
* @param policy The horizon policy service.
|
||||
* @param toastService The horizon toast service.
|
||||
@ -50,39 +51,29 @@
|
||||
*/
|
||||
|
||||
function modalService(
|
||||
$q,
|
||||
resourceType,
|
||||
actionResultService,
|
||||
$uibModal,
|
||||
$route,
|
||||
basePath,
|
||||
policy,
|
||||
toastService,
|
||||
gettext
|
||||
) {
|
||||
var poolId, statePromise;
|
||||
var member;
|
||||
|
||||
var service = {
|
||||
perform: open,
|
||||
allowed: allowed,
|
||||
init: init
|
||||
allowed: allowed
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
////////////
|
||||
|
||||
function init(_poolId_, _statePromise_) {
|
||||
poolId = _poolId_;
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
}
|
||||
|
||||
function allowed(/*item*/) {
|
||||
return $q.all([
|
||||
statePromise,
|
||||
// This rule is made up and should therefore always pass. At some point there will
|
||||
// likely be a valid rule similar to this that we will want to use.
|
||||
policy.ifAllowed({ rules: [['neutron', 'pool_member_update']] })
|
||||
]);
|
||||
// This rule is made up and should therefore always pass. At some point there will
|
||||
// likely be a valid rule similar to this that we will want to use.
|
||||
return policy.ifAllowed({ rules: [['neutron', 'pool_member_update']] });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -97,13 +88,14 @@
|
||||
*/
|
||||
|
||||
function open(item) {
|
||||
member = item;
|
||||
var spec = {
|
||||
backdrop: 'static',
|
||||
controller: 'EditMemberModalController as modal',
|
||||
templateUrl: basePath + 'members/actions/edit-member/modal.html',
|
||||
resolve: {
|
||||
poolId: function() {
|
||||
return poolId;
|
||||
return item.poolId;
|
||||
},
|
||||
member: function() {
|
||||
return item;
|
||||
@ -115,8 +107,9 @@
|
||||
|
||||
function onModalClose() {
|
||||
toastService.add('success', gettext('Pool member has been updated.'));
|
||||
$route.reload();
|
||||
return actionResultService.getActionResult()
|
||||
.updated(resourceType, member.id)
|
||||
.result;
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -18,7 +19,7 @@
|
||||
|
||||
describe('LBaaS v2 Member Edit Service', function() {
|
||||
var service, policy, $scope, $route, $uibModal, toast;
|
||||
var member = { id: 'member1' };
|
||||
var member = { poolId:'pool1', id: 'member1' };
|
||||
|
||||
var fakePromise = function(response) {
|
||||
return {
|
||||
@ -30,14 +31,7 @@
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
$scope.$apply();
|
||||
var allowed = service.allowed(item);
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'pool_member_update']]});
|
||||
return allowed;
|
||||
}
|
||||
@ -52,7 +46,7 @@
|
||||
$provide.value('$uibModal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: fakePromise()
|
||||
result: fakePromise({config: {data: {member: {id: 1}}}})
|
||||
};
|
||||
}
|
||||
});
|
||||
@ -65,8 +59,7 @@
|
||||
$route = $injector.get('$route');
|
||||
$uibModal = $injector.get('$uibModal');
|
||||
service = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.edit-member.modal.service');
|
||||
service.init('pool1', fakePromise());
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.edit-member');
|
||||
}));
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
@ -96,13 +89,11 @@
|
||||
expect(resolve.member()).toBe(member);
|
||||
});
|
||||
|
||||
it('should show message and reload page upon closing modal', function() {
|
||||
it('should show message upon closing modal', function() {
|
||||
spyOn(toast, 'add');
|
||||
spyOn($route, 'reload');
|
||||
service.perform(member);
|
||||
$scope.$apply();
|
||||
expect(toast.add).toHaveBeenCalledWith('success', 'Pool member has been updated.');
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,79 +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.members')
|
||||
.factory('horizon.dashboard.project.lbaasv2.members.actions.rowActions', rowActions);
|
||||
|
||||
rowActions.$inject = [
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.delete',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.edit-member.modal.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @ngname horizon.dashboard.project.lbaasv2.members.actions.rowActions
|
||||
*
|
||||
* @description
|
||||
* Provides the service for the pool members row actions.
|
||||
*
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param editMember The LBaaS v2 pool member edit service.
|
||||
* @returns Members row actions service object.
|
||||
*/
|
||||
|
||||
function rowActions(gettext, loadBalancersService, deleteService, editMember) {
|
||||
var loadBalancerIsActionable, loadbalancerId, listenerId, poolId;
|
||||
|
||||
var service = {
|
||||
actions: actions,
|
||||
init: init
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
///////////////
|
||||
|
||||
function init(_loadbalancerId_, _listenerId_, _poolId_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
listenerId = _listenerId_;
|
||||
poolId = _poolId_;
|
||||
loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId);
|
||||
return service;
|
||||
}
|
||||
|
||||
function actions() {
|
||||
return [{
|
||||
service: editMember.init(poolId, loadBalancerIsActionable),
|
||||
template: {
|
||||
text: gettext('Edit')
|
||||
}
|
||||
},{
|
||||
service: deleteService.init(loadbalancerId, listenerId, poolId, loadBalancerIsActionable),
|
||||
template: {
|
||||
text: gettext('Delete Member'),
|
||||
type: 'delete'
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -1,51 +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('LBaaS v2 Members Row Actions Service', function() {
|
||||
var actions;
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
var rowActionsService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.rowActions');
|
||||
actions = rowActionsService.init('1', '2', '3').actions();
|
||||
var loadbalancerService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service');
|
||||
spyOn(loadbalancerService, 'isActionable').and.returnValue(true);
|
||||
}));
|
||||
|
||||
it('should define correct table row actions', function() {
|
||||
expect(actions.length).toBe(2);
|
||||
expect(actions[0].template.text).toBe('Edit');
|
||||
expect(actions[1].template.text).toBe('Delete Member');
|
||||
});
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
actions.forEach(function(action) {
|
||||
expect(action.service.allowed).toBeDefined();
|
||||
expect(action.service.perform).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -22,8 +23,8 @@
|
||||
updateMemberListService);
|
||||
|
||||
updateMemberListService.$inject = [
|
||||
'$q',
|
||||
'$route',
|
||||
'horizon.dashboard.project.lbaasv2.members.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
@ -31,53 +32,38 @@
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.listeners.actions.updateMemberListService
|
||||
* @name horizon.dashboard.project.lbaasv2.members.actions.updateMemberListService
|
||||
*
|
||||
* @description
|
||||
* Provides the service for updating the list of pool members.
|
||||
* @param $q The angular service for promises.
|
||||
* @param $route The angular $route service.
|
||||
*
|
||||
* @param resourceType The member resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
*
|
||||
* @returns The load balancers members update member list service.
|
||||
*/
|
||||
|
||||
function updateMemberListService(
|
||||
$q, $route, workflowModal, policy, gettext
|
||||
resourceType, actionResultService, workflowModal, policy, gettext
|
||||
) {
|
||||
var statePromise;
|
||||
|
||||
var updateList = workflowModal.init({
|
||||
return workflowModal.init({
|
||||
controller: 'UpdateMemberListWizardController',
|
||||
message: gettext('The pool members have been updated.'),
|
||||
handle: onUpdate,
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
var service = {
|
||||
init: init,
|
||||
update: updateList
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function init(_statePromise_) {
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
}
|
||||
|
||||
function allowed(/*item*/) {
|
||||
return $q.all([
|
||||
statePromise,
|
||||
policy.ifAllowed({ rules: [['neutron', 'update_member_list']] })
|
||||
]);
|
||||
return policy.ifAllowed({ rules: [['neutron', 'update_member_list']] });
|
||||
}
|
||||
|
||||
function onUpdate(/*response*/) {
|
||||
$route.reload();
|
||||
function handle(response) {
|
||||
return actionResultService.getActionResult()
|
||||
.created(resourceType, response.data.id)
|
||||
.result;
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -17,85 +18,40 @@
|
||||
'use strict';
|
||||
|
||||
describe('LBaaS v2 Update Member List Action Service', function() {
|
||||
var scope, $q, $route, policy, init, updateMemberListService, defer;
|
||||
var policy, service;
|
||||
|
||||
function allowed() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = updateMemberListService.update.allowed();
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_member_list']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
var response = {
|
||||
data: {
|
||||
id: '9012'
|
||||
}
|
||||
};
|
||||
var modal = {
|
||||
$provide.value('$modal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: {
|
||||
then: function(func) {
|
||||
func(response);
|
||||
func({ data: { id: 'listener1' } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
$provide.value('$uibModal', modal);
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
scope = $injector.get('$rootScope').$new();
|
||||
$q = $injector.get('$q');
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
$route = $injector.get('$route');
|
||||
updateMemberListService = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list');
|
||||
init = updateMemberListService.init;
|
||||
defer = $q.defer();
|
||||
service = $injector.get(
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list'
|
||||
);
|
||||
}));
|
||||
|
||||
it('should define the correct service properties', function() {
|
||||
expect(updateMemberListService.init).toBeDefined();
|
||||
expect(updateMemberListService.update).toBeDefined();
|
||||
it('should check policy to allow updating member list', function() {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
expect(service.allowed()).toBe(true);
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'update_member_list']]});
|
||||
});
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
expect(updateMemberListService.update.allowed).toBeDefined();
|
||||
expect(updateMemberListService.update.perform).toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow editing a pool under an ACTIVE load balancer', function() {
|
||||
defer.resolve();
|
||||
init(defer.promise);
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow editing a pool under an NON-ACTIVE load balancer', function() {
|
||||
defer.reject();
|
||||
init(defer.promise);
|
||||
expect(allowed()).toBe(false);
|
||||
});
|
||||
|
||||
it('should redirect after edit', function() {
|
||||
spyOn($route, 'reload').and.callThrough();
|
||||
updateMemberListService.update.perform();
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
it('should handle the action result properly', function() {
|
||||
var result = service.handle({data: {id: 1}});
|
||||
expect(result.created[0].id).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,108 +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.members')
|
||||
.controller('MemberDetailController', MemberDetailController);
|
||||
|
||||
MemberDetailController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.rowActions',
|
||||
'$routeParams',
|
||||
'$q',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name MemberDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 member detail page.
|
||||
*
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param rowActions The pool members row actions service.
|
||||
* @param $routeParams The angular $routeParams service.
|
||||
* @param $q The angular service for promises.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function MemberDetailController(
|
||||
api, rowActions, $routeParams, $q, loadBalancersService
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
ctrl.actions = rowActions.init($routeParams.loadbalancerId,
|
||||
$routeParams.listenerId, $routeParams.poolId).actions;
|
||||
ctrl.loadbalancerId = $routeParams.loadbalancerId;
|
||||
ctrl.listenerId = $routeParams.listenerId;
|
||||
ctrl.poolId = $routeParams.poolId;
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
ctrl.member = null;
|
||||
ctrl.pool = null;
|
||||
ctrl.listener = null;
|
||||
ctrl.loadbalancer = null;
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
$q.all([
|
||||
api.getMember($routeParams.poolId, $routeParams.memberId)
|
||||
.then(success('member'), fail('member')),
|
||||
api.getPool($routeParams.poolId)
|
||||
.then(success('pool'), fail('pool')),
|
||||
api.getListener($routeParams.listenerId)
|
||||
.then(success('listener'), fail('listener')),
|
||||
api.getLoadBalancer($routeParams.loadbalancerId)
|
||||
.then(success('loadbalancer'), fail('loadbalancer'))
|
||||
]).then(postInit, initError);
|
||||
}
|
||||
|
||||
function success(property) {
|
||||
return angular.bind(null, function setProp(property, response) {
|
||||
ctrl[property] = response.data;
|
||||
}, property);
|
||||
}
|
||||
|
||||
function fail(property) {
|
||||
return angular.bind(null, function setProp(property, error) {
|
||||
ctrl[property] = null;
|
||||
throw error;
|
||||
}, property);
|
||||
}
|
||||
|
||||
function postInit() {
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
function initError() {
|
||||
ctrl.loading = false;
|
||||
ctrl.error = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -1,124 +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('LBaaS v2 Member Detail Controller', function() {
|
||||
var $controller, lbaasv2API, apiFail, qAllFail, actions;
|
||||
|
||||
function fakePromise(data, reject) {
|
||||
return {
|
||||
then: function(success, fail) {
|
||||
if (reject) {
|
||||
fail();
|
||||
} else {
|
||||
success({ data: data });
|
||||
}
|
||||
return fakePromise();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fakeAPI() {
|
||||
return fakePromise('foo', apiFail);
|
||||
}
|
||||
|
||||
function loadbalancerAPI() {
|
||||
return fakePromise({ provisioning_status: 'ACTIVE' });
|
||||
}
|
||||
|
||||
function qAll() {
|
||||
return fakePromise(null, qAllFail);
|
||||
}
|
||||
|
||||
function createController() {
|
||||
return $controller('MemberDetailController', {
|
||||
$routeParams: {
|
||||
loadbalancerId: 'loadbalancerId',
|
||||
listenerId: 'listenerId',
|
||||
poolId: 'poolId',
|
||||
memberId: 'memberId'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
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(function($provide) {
|
||||
apiFail = false;
|
||||
qAllFail = false;
|
||||
|
||||
$provide.value('$q', { all: qAll });
|
||||
$provide.value('$uibModal', {});
|
||||
$provide.value('horizon.dashboard.project.lbaasv2.members.actions.rowActions', {
|
||||
init: function() {
|
||||
return {
|
||||
actions: 'member-actions'
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
actions = $injector.get('horizon.dashboard.project.lbaasv2.members.actions.rowActions');
|
||||
spyOn(lbaasv2API, 'getMember').and.callFake(fakeAPI);
|
||||
spyOn(lbaasv2API, 'getPool').and.callFake(fakeAPI);
|
||||
spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI);
|
||||
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
|
||||
spyOn(actions, 'init').and.callThrough();
|
||||
$controller = $injector.get('$controller');
|
||||
}));
|
||||
|
||||
it('should invoke lbaasv2 apis', function() {
|
||||
var ctrl = createController();
|
||||
expect(lbaasv2API.getMember).toHaveBeenCalledWith('poolId','memberId');
|
||||
expect(lbaasv2API.getPool).toHaveBeenCalledWith('poolId');
|
||||
expect(lbaasv2API.getListener).toHaveBeenCalledWith('listenerId');
|
||||
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('loadbalancerId');
|
||||
expect(ctrl.loadbalancerId).toBeDefined();
|
||||
expect(ctrl.listenerId).toBeDefined();
|
||||
expect(ctrl.poolId).toBeDefined();
|
||||
expect(ctrl.operatingStatus).toBeDefined();
|
||||
expect(ctrl.provisioningStatus).toBeDefined();
|
||||
expect(ctrl.actions).toBe('member-actions');
|
||||
expect(actions.init).toHaveBeenCalledWith('loadbalancerId', 'listenerId', 'poolId');
|
||||
});
|
||||
|
||||
it('should throw error on API fail', function() {
|
||||
apiFail = true;
|
||||
var init = function() {
|
||||
createController();
|
||||
};
|
||||
expect(init).toThrow();
|
||||
});
|
||||
|
||||
it('should set error state if any APIs fail', function() {
|
||||
qAllFail = true;
|
||||
var ctrl = createController();
|
||||
expect(ctrl.loading).toBe(false);
|
||||
expect(ctrl.error).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -1,48 +0,0 @@
|
||||
<div ng-controller="MemberDetailController as ctrl">
|
||||
<detail-status loading="ctrl.loading" error="ctrl.error"></detail-status>
|
||||
<div ng-if="!ctrl.loading && !ctrl.error">
|
||||
<div class="page-header">
|
||||
<actions allowed="ctrl.actions" type="row" item="ctrl.member"
|
||||
ng-if="ctrl.member" class="actions_column pull-right"></actions>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}">{$ ::(ctrl.loadbalancer.name || ctrl.loadbalancer.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}">{$ ::(ctrl.listener.name || ctrl.listener.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}/pools/{$ ::ctrl.pool.id $}">{$ ::(ctrl.pool.name || ctrl.pool.id) $}</a></li>
|
||||
<li class="active">{$ ::(ctrl.member.name || ctrl.member.id) $}</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<dl class="dl-horizontal">
|
||||
<dt translate>Address</dt>
|
||||
<dd>{$ ::ctrl.member.address $}</dd>
|
||||
<dt translate>Admin State Up</dt>
|
||||
<dd>{$ ctrl.member.admin_state_up | yesno $}</dd>
|
||||
<dt translate>Member ID</dt>
|
||||
<dd>{$ ::ctrl.member.id $}</dd>
|
||||
<dt translate>Operating Status</dt>
|
||||
<dd>{$ ctrl.member.operating_status | decode:ctrl.operatingStatus $}</dd>
|
||||
<dt translate>Project ID</dt>
|
||||
<dd>{$ ::ctrl.member.project_id $}</dd>
|
||||
<dt translate>Protocol Port</dt>
|
||||
<dd>{$ ::ctrl.member.protocol_port $}</dd>
|
||||
<dt translate>Provisioning Status</dt>
|
||||
<dd>{$ ctrl.member.provisioning_status | decode:ctrl.provisioningStatus $}</dd>
|
||||
<dt translate>Subnet ID</dt>
|
||||
<dd>{$ ctrl.member.subnet_id $}</dd>
|
||||
<dt translate>Weight</dt>
|
||||
<dd>{$ ctrl.member.weight $}</dd>
|
||||
<dt translate>Monitor Address</dt>
|
||||
<dd>{$ ::ctrl.member.monitor_address | noValue:('None' | translate) $}</dd>
|
||||
<dt translate>Monitor Port</dt>
|
||||
<dd>{$ ::ctrl.member.monitor_port | noValue:('None' | translate) $}</dd>
|
||||
<dt translate>Created At</dt>
|
||||
<dd>{$ ::ctrl.member.created_at $}</dd>
|
||||
<dt translate>Updated At</dt>
|
||||
<dd>{$ ::ctrl.member.updated_at $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.members')
|
||||
.controller('MemberDetailController', MemberDetailController);
|
||||
|
||||
MemberDetailController.$inject = [
|
||||
'loadbalancer',
|
||||
'listener',
|
||||
'pool',
|
||||
'member',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.members.resourceType',
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.framework.widgets.modal-wait-spinner.service',
|
||||
'$q'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name MemberDetailController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 member detail page.
|
||||
*
|
||||
* @param loadbalancer The loadbalancer object.
|
||||
* @param listener The listener object.
|
||||
* @param pool The pool object.
|
||||
* @param member The member object.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @param resourceType The member resource type.
|
||||
* @param typeRegistry The horizon resource type registry service.
|
||||
* @param spinnerService The horizon modal wait spinner service.
|
||||
* @param $q The angular service for promises.
|
||||
*
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function MemberDetailController(
|
||||
loadbalancer, listener, pool, member, loadBalancersService,
|
||||
resourceType, typeRegistry, spinnerService, $q
|
||||
) {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
ctrl.loadbalancer = loadbalancer;
|
||||
ctrl.listener = listener;
|
||||
ctrl.pool = pool;
|
||||
ctrl.member = member;
|
||||
ctrl.resourceType = typeRegistry.getResourceType(resourceType);
|
||||
ctrl.context = {};
|
||||
ctrl.context.memberId = member.id;
|
||||
ctrl.context.poolId = pool.id;
|
||||
|
||||
ctrl.resultHandler = actionResultHandler;
|
||||
|
||||
function actionResultHandler(returnValue) {
|
||||
return $q.when(returnValue, actionSuccessHandler);
|
||||
}
|
||||
|
||||
function loadData(response) {
|
||||
spinnerService.hideModalSpinner();
|
||||
ctrl.showDetails = true;
|
||||
ctrl.resourceType.initActions();
|
||||
ctrl.member = response.data;
|
||||
ctrl.member.loadbalancerId = ctrl.loadbalancer.id;
|
||||
ctrl.member.listenerId = ctrl.listener.id;
|
||||
ctrl.member.poolId = ctrl.pool.id;
|
||||
}
|
||||
|
||||
function actionSuccessHandler(result) {
|
||||
// The action has completed (for whatever "complete" means to that
|
||||
// action. Notice the view doesn't really need to know the semantics of the
|
||||
// particular action because the actions return data in a standard form.
|
||||
// That return includes the id and type of each created, updated, deleted
|
||||
// and failed item.
|
||||
// Currently just refreshes the display each time.
|
||||
if (result) {
|
||||
spinnerService.showModalSpinner(gettext('Please Wait'));
|
||||
ctrl.showDetails = false;
|
||||
ctrl.context.loadPromise = ctrl.resourceType.load(
|
||||
ctrl.context.poolId,
|
||||
ctrl.context.memberId
|
||||
);
|
||||
ctrl.context.loadPromise.then(loadData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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('LBaaS v2 Member Detail Controller', function() {
|
||||
var deferred, service, ctrl, scope, $timeout, $q, actionResultService;
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($controller, $rootScope, _$q_, _$timeout_) {
|
||||
$q = _$q_;
|
||||
deferred = $q.defer();
|
||||
service = {
|
||||
getResourceType: function() {
|
||||
return {
|
||||
load: function() { return deferred.promise; },
|
||||
parsePath: function() { return 'my-context'; },
|
||||
itemName: function() { return 'A name'; },
|
||||
initActions: angular.noop
|
||||
};
|
||||
},
|
||||
getDefaultDetailsTemplateUrl: angular.noop
|
||||
};
|
||||
actionResultService = {
|
||||
getIdsOfType: function() { return []; }
|
||||
};
|
||||
$timeout = _$timeout_;
|
||||
scope = $rootScope.$new();
|
||||
ctrl = $controller('MemberDetailController', {
|
||||
$scope: scope,
|
||||
loadbalancer: { id: '123' },
|
||||
listener: { id: '123' },
|
||||
pool: { id: '123' },
|
||||
member: { id: '123' },
|
||||
'horizon.framework.conf.resource-type-registry.service': service,
|
||||
'horizon.framework.util.actions.action-result.service': actionResultService,
|
||||
'horizon.framework.widgets.modal-wait-spinner.service': {
|
||||
showModalSpinner: angular.noop,
|
||||
hideModalSpinner: angular.noop
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
it('should create a controller', function() {
|
||||
expect(ctrl).toBeDefined();
|
||||
expect(ctrl.loadbalancer).toBeDefined();
|
||||
expect(ctrl.listener).toBeDefined();
|
||||
expect(ctrl.pool).toBeDefined();
|
||||
expect(ctrl.member).toBeDefined();
|
||||
});
|
||||
|
||||
describe('resultHandler', function() {
|
||||
|
||||
it('handles empty results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve({});
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles falsy results', function() {
|
||||
var result = $q.defer();
|
||||
result.resolve(false);
|
||||
ctrl.resultHandler(result.promise);
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).not.toBe(true);
|
||||
});
|
||||
|
||||
it('handles matched results', function() {
|
||||
spyOn(actionResultService, 'getIdsOfType').and.returnValue([1, 2, 3]);
|
||||
var result = $q.defer();
|
||||
result.resolve({some: 'thing'});
|
||||
ctrl.resultHandler(result.promise);
|
||||
deferred.resolve({data: {some: 'data'}});
|
||||
$timeout.flush();
|
||||
expect(ctrl.showDetails).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -0,0 +1,55 @@
|
||||
<div class="page-header">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="project/load_balancer/"><translate>Load Balancers</translate></a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}">{$ ::(ctrl.loadbalancer.name || ctrl.loadbalancer.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}">{$ ::(ctrl.listener.name || ctrl.listener.id) $}</a></li>
|
||||
<li><a href="project/load_balancer/{$ ::ctrl.loadbalancer.id $}/listeners/{$ ::ctrl.listener.id $}/pools/{$ ::ctrl.pool.id $}">{$ ::(ctrl.pool.name || ctrl.pool.id) $}</a></li>
|
||||
<li class="active">{$ ::(ctrl.member.name || ctrl.member.id) $}</li>
|
||||
</ol>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-9 text-left">
|
||||
<ul class="list-inline">
|
||||
<li>
|
||||
<strong translate>IP Address</strong>
|
||||
{$ ::ctrl.member.address $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Port</strong>
|
||||
{$ ::ctrl.member.protocol_port $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Operating Status</strong>
|
||||
{$ ctrl.member.operating_status | decode:ctrl.operatingStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Provisioning Status</strong>
|
||||
{$ ctrl.member.provisioning_status | decode:ctrl.provisioningStatus $}
|
||||
</li>
|
||||
<li>
|
||||
<strong translate>Admin State Up</strong>
|
||||
{$ ctrl.member.admin_state_up | yesno $}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-3 text-right details-item-actions">
|
||||
<actions allowed="ctrl.resourceType.itemActions"
|
||||
type="row"
|
||||
item="ctrl.member"
|
||||
class="actions_column pull-right"
|
||||
result-handler="ctrl.resultHandler"></actions>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 detail">
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::Member"
|
||||
cls="dl-horizontal"
|
||||
item="ctrl.member"
|
||||
property-groups="[[
|
||||
'id', 'name', 'project_id', 'created_at', 'updated_at',
|
||||
'weight', 'monitor_address', 'monitor_port']]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,9 @@
|
||||
<hz-resource-property-list
|
||||
resource-type-name="OS::Octavia::Member"
|
||||
item="item"
|
||||
property-groups="[
|
||||
['name', 'id', 'project_id'],
|
||||
['created_at', 'updated_at'],
|
||||
['address', 'protocol_port', 'weight'],
|
||||
['subnet_id', 'monitor_address', 'monitor_port']]">
|
||||
</hz-resource-property-list>
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -26,6 +27,149 @@
|
||||
*/
|
||||
|
||||
angular
|
||||
.module('horizon.dashboard.project.lbaasv2.members', []);
|
||||
.module('horizon.dashboard.project.lbaasv2.members', [])
|
||||
.constant('horizon.dashboard.project.lbaasv2.members.resourceType',
|
||||
'OS::Octavia::Member')
|
||||
.run(run);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.dashboard.project.lbaasv2.basePath',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.update-member-list',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.edit-member',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.delete',
|
||||
'horizon.dashboard.project.lbaasv2.members.resourceType'
|
||||
];
|
||||
|
||||
function run(
|
||||
registry,
|
||||
basePath,
|
||||
loadBalancerService,
|
||||
createService,
|
||||
editService,
|
||||
deleteService,
|
||||
resourceType
|
||||
) {
|
||||
var memberResourceType = registry.getResourceType(resourceType);
|
||||
|
||||
memberResourceType
|
||||
.setNames(gettext('Member'), gettext('Members'))
|
||||
.setSummaryTemplateUrl(basePath + 'members/details/drawer.html')
|
||||
.setProperties(memberProperties(loadBalancerService))
|
||||
.setListFunction(loadBalancerService.getMembersPromise)
|
||||
.setLoadFunction(loadBalancerService.getMemberPromise)
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true,
|
||||
urlFunction: loadBalancerService.getMemberDetailsPath
|
||||
})
|
||||
.append({
|
||||
id: 'address',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'protocol_port',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'weight',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'operating_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'provisioning_status',
|
||||
priority: 1
|
||||
})
|
||||
.append({
|
||||
id: 'admin_state_up',
|
||||
priority: 1
|
||||
});
|
||||
|
||||
memberResourceType.itemActions
|
||||
.append({
|
||||
id: 'memberEdit',
|
||||
service: editService,
|
||||
template: {
|
||||
text: gettext('Edit Member')
|
||||
}
|
||||
})
|
||||
.append({
|
||||
id: 'memberDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Member'),
|
||||
type: 'delete'
|
||||
}
|
||||
});
|
||||
|
||||
memberResourceType.globalActions
|
||||
.append({
|
||||
id: 'memberCreate',
|
||||
service: createService,
|
||||
template: {
|
||||
type: 'create',
|
||||
text: gettext('Add/Remove Members')
|
||||
}
|
||||
});
|
||||
|
||||
memberResourceType.batchActions
|
||||
.append({
|
||||
id: 'memberBatchDelete',
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Members'),
|
||||
type: 'delete-selected'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function memberProperties(loadBalancerService) {
|
||||
return {
|
||||
id: gettext('ID'),
|
||||
name: {
|
||||
label: gettext('Name'),
|
||||
filters: ['noName']
|
||||
},
|
||||
provisioning_status: {
|
||||
label: gettext('Provisioning Status'),
|
||||
values: loadBalancerService.provisioningStatus
|
||||
},
|
||||
operating_status: {
|
||||
label: gettext('Operating Status'),
|
||||
values: loadBalancerService.operatingStatus
|
||||
},
|
||||
admin_state_up: {
|
||||
label: gettext('Admin State Up'),
|
||||
filters: ['yesno']
|
||||
},
|
||||
address: gettext('IP Address'),
|
||||
protocol_port: gettext('Port'),
|
||||
weight: gettext('Weight'),
|
||||
subnet_id: gettext('Subnet ID'),
|
||||
project_id: gettext('Project ID'),
|
||||
created_at: {
|
||||
label: gettext('Created At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
updated_at: {
|
||||
label: gettext('Updated At'),
|
||||
filters: ['noValue']
|
||||
},
|
||||
monitor_address: {
|
||||
label: gettext('Monitor Address'),
|
||||
filters: ['noName']
|
||||
},
|
||||
monitor_port: {
|
||||
label: gettext('Monitor Port'),
|
||||
filters: ['noName']
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -22,4 +23,46 @@
|
||||
});
|
||||
});
|
||||
|
||||
describe('LBaaS v2 Members Registry', function () {
|
||||
var registry, resourceType;
|
||||
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
resourceType = $injector.get('horizon.dashboard.project.lbaasv2.members.resourceType');
|
||||
registry = $injector.get('horizon.framework.conf.resource-type-registry.service');
|
||||
}));
|
||||
|
||||
it('should define resourceType', function () {
|
||||
expect(resourceType).toBeDefined();
|
||||
});
|
||||
|
||||
it('should register item actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).itemActions;
|
||||
expect(actionHasId(actions, 'memberEdit')).toBe(true);
|
||||
expect(actionHasId(actions, 'memberDelete')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register global actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).globalActions;
|
||||
expect(actionHasId(actions, 'memberCreate')).toBe(true);
|
||||
});
|
||||
|
||||
it('should register batch actions', function () {
|
||||
var actions = registry.getResourceType(resourceType).batchActions;
|
||||
expect(actionHasId(actions, 'memberBatchDelete')).toBe(true);
|
||||
});
|
||||
|
||||
function actionHasId(list, value) {
|
||||
return list.filter(matchesId).length === 1;
|
||||
|
||||
function matchesId(action) {
|
||||
if (action.id === value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -1,87 +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.members')
|
||||
.controller('MembersTableController', MembersTableController);
|
||||
|
||||
MembersTableController.$inject = [
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.rowActions',
|
||||
'horizon.dashboard.project.lbaasv2.members.actions.batchActions',
|
||||
'$routeParams',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.service'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name MembersTableController
|
||||
*
|
||||
* @description
|
||||
* Controller for the LBaaS v2 members table. Serves as the focal point for table actions.
|
||||
*
|
||||
* @param api The LBaaS V2 service API.
|
||||
* @param rowActions The pool members row actions service.
|
||||
* @param batchActions The members batch actions service.
|
||||
* @param $routeParams The angular $routeParams service.
|
||||
* @param loadBalancersService The LBaaS v2 load balancers service.
|
||||
* @returns undefined
|
||||
*/
|
||||
|
||||
function MembersTableController(
|
||||
api, rowActions, batchActions, $routeParams, loadBalancersService
|
||||
) {
|
||||
var ctrl = this;
|
||||
ctrl.items = [];
|
||||
ctrl.src = [];
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
ctrl.checked = {};
|
||||
ctrl.loadbalancerId = $routeParams.loadbalancerId;
|
||||
ctrl.listenerId = $routeParams.listenerId;
|
||||
ctrl.poolId = $routeParams.poolId;
|
||||
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId, ctrl.listenerId, ctrl.poolId);
|
||||
ctrl.batchActions = batchActions.init(ctrl.loadbalancerId);
|
||||
ctrl.operatingStatus = loadBalancersService.operatingStatus;
|
||||
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
|
||||
|
||||
init();
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
function init() {
|
||||
ctrl.src = [];
|
||||
ctrl.loading = true;
|
||||
ctrl.error = false;
|
||||
api.getMembers(ctrl.poolId).then(success, fail);
|
||||
}
|
||||
|
||||
function success(response) {
|
||||
ctrl.src = response.data.items;
|
||||
ctrl.loading = false;
|
||||
}
|
||||
|
||||
function fail(/*response*/) {
|
||||
ctrl.src = [];
|
||||
ctrl.loading = false;
|
||||
ctrl.error = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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('LBaaS v2 Members Table Controller', function() {
|
||||
var controller, lbaasv2API, scope, actions;
|
||||
var items = [{ foo: 'bar' }];
|
||||
var apiFail = false;
|
||||
|
||||
function fakeAPI() {
|
||||
return {
|
||||
then: function(success, fail) {
|
||||
if (apiFail && fail) {
|
||||
fail();
|
||||
} else {
|
||||
success({ data: { items: items } });
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$uibModal', {});
|
||||
$provide.value('horizon.dashboard.project.lbaasv2.members.actions.rowActions', {
|
||||
init: function() {
|
||||
return {
|
||||
actions: 'member-actions'
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
actions = $injector.get('horizon.dashboard.project.lbaasv2.members.actions.rowActions');
|
||||
controller = $injector.get('$controller');
|
||||
spyOn(lbaasv2API, 'getMembers').and.callFake(fakeAPI);
|
||||
spyOn(actions, 'init').and.callThrough();
|
||||
}));
|
||||
|
||||
function createController() {
|
||||
return controller('MembersTableController', {
|
||||
$scope: scope,
|
||||
$routeParams: {
|
||||
loadbalancerId: 'loadbalancerId',
|
||||
listenerId: 'listenerId',
|
||||
poolId: 'poolId'
|
||||
}});
|
||||
}
|
||||
|
||||
it('should initialize the controller properties correctly', function() {
|
||||
var ctrl = createController();
|
||||
expect(ctrl.items).toEqual([]);
|
||||
expect(ctrl.src).toEqual(items);
|
||||
expect(ctrl.loading).toBe(false);
|
||||
expect(ctrl.error).toBe(false);
|
||||
expect(ctrl.checked).toEqual({});
|
||||
expect(ctrl.loadbalancerId).toBeDefined();
|
||||
expect(ctrl.listenerId).toBeDefined();
|
||||
expect(ctrl.poolId).toBeDefined();
|
||||
expect(ctrl.rowActions).toBeDefined();
|
||||
expect(ctrl.batchActions).toBeDefined();
|
||||
expect(ctrl.operatingStatus).toBeDefined();
|
||||
expect(ctrl.provisioningStatus).toBeDefined();
|
||||
});
|
||||
|
||||
it('should invoke lbaasv2 apis', function() {
|
||||
var ctrl = createController();
|
||||
expect(lbaasv2API.getMembers).toHaveBeenCalled();
|
||||
expect(ctrl.src.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should show error if loading fails', function() {
|
||||
apiFail = true;
|
||||
var ctrl = createController();
|
||||
expect(ctrl.src.length).toBe(0);
|
||||
expect(ctrl.error).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -1,120 +0,0 @@
|
||||
<table ng-controller="MembersTableController as table"
|
||||
hz-table ng-cloak
|
||||
st-table="table.items"
|
||||
st-safe-src="table.src"
|
||||
default-sort="id"
|
||||
default-sort-reverse="false"
|
||||
class="table table-striped table-rsp table-detail">
|
||||
<!--
|
||||
TODO(jpomero): This table pattern does not allow for extensibility and should be revisited
|
||||
once horizon implements a better one.
|
||||
-->
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<!--
|
||||
Table-batch-actions:
|
||||
This is where batch actions like searching, creating, and deleting.
|
||||
-->
|
||||
<th colspan="6" class="search-header">
|
||||
<hz-search-bar icon-classes="fa-search">
|
||||
<actions allowed="table.batchActions.actions" type="batch"></actions>
|
||||
</hz-search-bar>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<!--
|
||||
Table-column-headers:
|
||||
This is where we declaratively define the table column headers.
|
||||
Include select-col if you want to select all.
|
||||
Include expander if you want to inline details.
|
||||
Include action-col if you want to perform actions.
|
||||
-->
|
||||
<th class="multi_select_column">
|
||||
<input type="checkbox" hz-select-all="table.items">
|
||||
</th>
|
||||
|
||||
<th class="expander"></th>
|
||||
|
||||
<th class="rsp-p1" st-sort="id" st-sort-default="id" translate>ID</th>
|
||||
<th class="rsp-p1" st-sort="address" translate>IP Address</th>
|
||||
<th class="rsp-p1" st-sort="protocol_port" translate>Protocol Port</th>
|
||||
<th class="rsp-p1" st-sort="protocol_port" translate>Operating Status</th>
|
||||
<th class="rsp-p1" st-sort="protocol_port" translate>Provisioning Status</th>
|
||||
<th class="rsp-p1" st-sort="weight" translate>Weight</th>
|
||||
<th class="actions_column" translate>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<!--
|
||||
Table-rows:
|
||||
This is where we declaratively define the table columns.
|
||||
Include select-col if you want to select all.
|
||||
Include expander if you want to inline details.
|
||||
Include action-col if you want to perform actions.
|
||||
rsp-p1 rsp-p2 are responsive priority as user resizes window.
|
||||
-->
|
||||
<tr ng-repeat-start="item in table.items track by item.id"
|
||||
ng-class="{'st-selected': checked[item.id]}">
|
||||
|
||||
<td class="multi_select_column">
|
||||
<input type="checkbox"
|
||||
ng-model="tCtrl.selections[item.id].checked"
|
||||
hz-select="item">
|
||||
</td>
|
||||
<td class="expander">
|
||||
<span class="fa fa-chevron-right"
|
||||
hz-expand-detail
|
||||
duration="200">
|
||||
</span>
|
||||
</td>
|
||||
<td class="rsp-p1"><a ng-href="project/load_balancer/{$ ::table.loadbalancerId $}/listeners/{$ ::table.listenerId $}/pools/{$ ::table.poolId $}/members/{$ ::item.id $}">{$ ::item.id $}</a></td>
|
||||
<td class="rsp-p1">{$ ::item.address $}</td>
|
||||
<td class="rsp-p1">{$ ::item.protocol_port $}</td>
|
||||
<td class="rsp-p1">{$ ::item.operating_status | decode:table.operatingStatus $}</td>
|
||||
<td class="rsp-p1">{$ ::item.provisioning_status | decode:table.provisioningStatus $}</td>
|
||||
<td class="rsp-p1">{$ item.weight $}</td>
|
||||
<td class="actions_column">
|
||||
<!--
|
||||
Table-row-action-column:
|
||||
Actions taken here apply to a single item/row.
|
||||
-->
|
||||
<actions allowed="table.rowActions.actions" type="row" item="item"></actions>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr ng-repeat-end class="detail-row">
|
||||
<!--
|
||||
Detail-row:
|
||||
Contains detailed information on this item.
|
||||
Can be toggled using the chevron button.
|
||||
Ensure colspan is greater or equal to number of column-headers.
|
||||
-->
|
||||
<td class="detail" colspan="9">
|
||||
|
||||
<div class="row">
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Monitor Address</dt>
|
||||
<dd>{$ ::item.monitor_address | noValue:('None' | translate) $}</dd>
|
||||
</dl>
|
||||
<dl class="col-sm-2">
|
||||
<dt translate>Monitor Port</dt>
|
||||
<dd>{$ ::item.monitor_port | noValue:('None' | translate) $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr table-status table="table" column-count="9"></tr>
|
||||
|
||||
</tbody>
|
||||
<!--
|
||||
Table-footer:
|
||||
This is where we display number of items and pagination controls.
|
||||
-->
|
||||
<tfoot hz-table-footer items="table.items"></tfoot>
|
||||
|
||||
</table>
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
* 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.
|
||||
@ -21,69 +22,59 @@
|
||||
.factory('horizon.dashboard.project.lbaasv2.pools.actions.create', createService);
|
||||
|
||||
createService.$inject = [
|
||||
'horizon.dashboard.project.lbaasv2.pools.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'$q',
|
||||
'$location',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
'$routeParams'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.listeners.actions.createService
|
||||
* @name horizon.dashboard.project.lbaasv2.pools.actions.createService
|
||||
*
|
||||
* @description
|
||||
* Provides the service for creating a pool resource.
|
||||
*
|
||||
* @param resourceType The pool resource type.
|
||||
* @param actionResultService The horizon action result service.
|
||||
* @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 qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns The load balancers pool create service.
|
||||
* @param qExtensions horizon extensions to the $q service.
|
||||
* @param $routeParams The angular $routeParams service.
|
||||
*
|
||||
* @returns The pool create service.
|
||||
*/
|
||||
|
||||
function createService(
|
||||
$q, $location, workflowModal, policy, qExtensions, gettext
|
||||
resourceType, actionResultService,
|
||||
$q, workflowModal, policy, gettext, qExtensions, $routeParams
|
||||
) {
|
||||
var loadbalancerId, listenerId, statePromise;
|
||||
|
||||
var create = workflowModal.init({
|
||||
return workflowModal.init({
|
||||
controller: 'CreatePoolWizardController',
|
||||
message: gettext('A new pool is being created.'),
|
||||
handle: onCreate,
|
||||
handle: handle,
|
||||
allowed: allowed
|
||||
});
|
||||
|
||||
var service = {
|
||||
init: init,
|
||||
create: create
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function init(_loadbalancerId_, _statePromise_) {
|
||||
loadbalancerId = _loadbalancerId_;
|
||||
statePromise = _statePromise_;
|
||||
return service;
|
||||
}
|
||||
|
||||
function allowed(item) {
|
||||
listenerId = item.id;
|
||||
function allowed() {
|
||||
return $q.all([
|
||||
statePromise,
|
||||
qExtensions.booleanAsPromise(!item.default_pool_id),
|
||||
qExtensions.booleanAsPromise(!!$routeParams.listenerId),
|
||||
policy.ifAllowed({ rules: [['neutron', 'create_pool']] })
|
||||
]);
|
||||
}
|
||||
|
||||
function onCreate(response) {
|
||||
var poolId = response.data.id;
|
||||
$location.path('project/load_balancer/' + loadbalancerId + '/listeners/' +
|
||||
listenerId + '/pools/' + poolId);
|
||||
function handle(response) {
|
||||
return actionResultService.getActionResult()
|
||||
.created(resourceType, response.data.id)
|
||||
.result;
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user