diff --git a/octavia_dashboard/api/rest/lbaasv2.py b/octavia_dashboard/api/rest/lbaasv2.py index 303337e0..223cebec 100644 --- a/octavia_dashboard/api/rest/lbaasv2.py +++ b/octavia_dashboard/api/rest/lbaasv2.py @@ -204,6 +204,7 @@ def create_pool(request, **kwargs): lb_algorithm=data['pool']['method'], session_persistence=session_persistence, listener_id=kwargs['listener_id'], + loadbalancer_id=kwargs['loadbalancer_id'], name=data['pool'].get('name'), description=data['pool'].get('description'), admin_state_up=data['pool'].get('admin_state_up') diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.js b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.js index b3522cd1..fca82d61 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.js @@ -121,9 +121,15 @@ }); if (actionResult.result.failed.length === 0 && actionResult.result.deleted.length > 0) { - var path = 'project/load_balancer/' + loadbalancerId + - '/listeners/' + listenerId + - '/pools/' + poolId; + var path; + if (listenerId) { + path = 'project/load_balancer/' + loadbalancerId + + '/listeners/' + listenerId + + '/pools/' + poolId; + } else { + path = 'project/load_balancer/' + loadbalancerId + + '/pools/' + poolId; + } $location.path(path); } return actionResult.result; diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.spec.js index 1e2d3613..3e44c314 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/actions/delete/delete.action.service.spec.js @@ -64,7 +64,7 @@ }); }); - it('should handle the action result properly', function() { + it('should handle the action result properly with listener', function() { spyOn($location, 'path'); spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop}); spyOn(lbaasv2API, 'deleteHealthMonitor').and.callFake(angular.noop); @@ -91,6 +91,33 @@ expect(result.failed[0].id).toBe(1); }); + it('should handle the action result properly without listener', function() { + spyOn($location, 'path'); + spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop}); + spyOn(lbaasv2API, 'deleteHealthMonitor').and.callFake(angular.noop); + service.perform({loadbalancerId: 1, poolId: 3, id: 1, name: 'one'}); + var result = service.deleteResult({ + fail: [], + pass: [{ + context: { + id: 1 + } + }] + }); + var path = 'project/load_balancer/1/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'); diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.js b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.js index d0ecd718..fcfb27ee 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.js @@ -63,6 +63,13 @@ ctrl.provisioningStatus = loadBalancersService.provisioningStatus; ctrl.loadbalancer = loadbalancer; ctrl.listener = listener; + if (!angular.equals({}, ctrl.listener)) { + ctrl.withListenerStyle = {}; + ctrl.withoutListenerStyle = {display: 'none'}; + } else { + ctrl.withListenerStyle = {display: 'none'}; + ctrl.withoutListenerStyle = {}; + } ctrl.pool = pool; ctrl.healthmonitor = healthmonitor; ctrl.resourceType = typeRegistry.getResourceType(resourceType); diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.spec.js index 6c10c5b5..f9237fc1 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.controller.spec.js @@ -47,6 +47,19 @@ }; $timeout = _$timeout_; scope = $rootScope.$new(); + ctrl = $controller('HealthMonitorDetailController', { + $scope: scope, + loadbalancer: { id: '123' }, + listener: {}, + 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 + } + }); ctrl = $controller('HealthMonitorDetailController', { $scope: scope, loadbalancer: { id: '123' }, diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.html b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.html index 126018bd..cd741cab 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.html +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/healthmonitors/details/detail.html @@ -4,8 +4,9 @@ - - + + +
diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js b/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js index 83de477c..f1f8d482 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js @@ -68,9 +68,12 @@ 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 listenerPool = listener + '/pools/:poolId'; + var listenerPoolMember = listenerPool + '/members/:memberId'; + var listenerPoolHealthmonitor = listenerPool + '/healthmonitors/:healthmonitorId'; + var loadbalancerPool = loadbalancers + '/:loadbalancerId/pools/:poolId'; + var loadbalancerPoolMember = loadbalancerPool + '/members/:memberId'; + var loadbalancerPoolHealthmonitor = loadbalancerPool + '/healthmonitors/:healthmonitorId'; $routeProvider .when(loadbalancers, { @@ -126,7 +129,7 @@ controller: 'ListenerDetailController', controllerAs: 'ctrl' }) - .when(pool, { + .when(listenerPool, { templateUrl: basePath + 'pools/details/detail.html', resolve: { loadbalancer: [ @@ -169,7 +172,7 @@ controller: 'PoolDetailController', controllerAs: 'ctrl' }) - .when(member, { + .when(listenerPoolMember, { templateUrl: basePath + 'members/details/detail.html', resolve: { loadbalancer: [ @@ -225,7 +228,7 @@ controller: 'MemberDetailController', controllerAs: 'ctrl' }) - .when(healthmonitor, { + .when(listenerPoolHealthmonitor, { templateUrl: basePath + 'healthmonitors/details/detail.html', resolve: { loadbalancer: [ @@ -280,6 +283,137 @@ }, controller: 'HealthMonitorDetailController', controllerAs: 'ctrl' + }) + .when(loadbalancerPool, { + 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: function() { + return {}; + }, + 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(loadbalancerPoolMember, { + 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: function() { + return {}; + }, + 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(loadbalancerPoolHealthmonitor, { + 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: function() { + return {}; + }, + 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' }); } diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js index 86f8149a..174ec00c 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js @@ -182,7 +182,7 @@ }); })); - it('should route resolved pool detail', inject(function($injector) { + it('should route resolved listener pool detail', inject(function($injector) { function loadbalancerAPI() { var loadbalancer = { provisioning_status: 'ACTIVE' }; return { @@ -233,7 +233,7 @@ }); })); - it('should route resolved member detail', inject(function($injector) { + it('should route resolved listener pool member detail', inject(function($injector) { function loadbalancerAPI() { var loadbalancer = { provisioning_status: 'ACTIVE' }; return { @@ -297,7 +297,7 @@ }); })); - it('should route resolved health monitor detail', inject(function($injector) { + it('should route resolved listener pool health monitor detail', inject(function($injector) { function loadbalancerAPI() { var loadbalancer = { provisioning_status: 'ACTIVE' }; return { @@ -361,6 +361,146 @@ }); })); + it('should route resolved loadbalancer 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 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, '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/pools/3'); + $rootScope.$digest(); + expect($route.current).toBeDefined(); + }); + })); + + it('should route resolved loadbalancer pool 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 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, '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/pools/3/members/4'); + $rootScope.$digest(); + expect($route.current).toBeDefined(); + }); + })); + + it('should route resolved loadbalancer pool 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 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, '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/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(); diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/details/detail.html b/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/details/detail.html index ac48cfb6..41ed0001 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/details/detail.html +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/details/detail.html @@ -57,12 +57,10 @@ list-function-extra-params="ctrl.listFunctionExtraParams"> - diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.js b/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.js index a2ec60d6..54fdf3db 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.js @@ -104,10 +104,16 @@ } function getMemberDetailsPath(item) { - return 'project/load_balancer/' + item.loadbalancerId + - '/listeners/' + item.listenerId + - '/pools/' + item.poolId + - '/members/' + item.id; + if (item.listenerId) { + return 'project/load_balancer/' + item.loadbalancerId + + '/listeners/' + item.listenerId + + '/pools/' + item.poolId + + '/members/' + item.id; + } else { + return 'project/load_balancer/' + item.loadbalancerId + + '/pools/' + item.poolId + + '/members/' + item.id; + } } function getMembersPromise(params) { @@ -131,10 +137,16 @@ } function getHealthMonitorDetailsPath(item) { - return 'project/load_balancer/' + item.loadbalancerId + - '/listeners/' + item.listenerId + - '/pools/' + item.poolId + - '/healthmonitors/' + item.id; + if (item.listenerId) { + return 'project/load_balancer/' + item.loadbalancerId + + '/listeners/' + item.listenerId + + '/pools/' + item.poolId + + '/healthmonitors/' + item.id; + } else { + return 'project/load_balancer/' + item.loadbalancerId + + '/pools/' + item.poolId + + '/healthmonitors/' + item.id; + } } function getHealthMonitorsPromise(params) { @@ -177,9 +189,15 @@ } function getPoolDetailsPath(item) { - return 'project/load_balancer/' + - item.loadbalancerId + '/listeners/' + - item.listeners[0].id + '/pools/' + item.id; + if (item.listeners.length > 0) { + return 'project/load_balancer/' + + item.loadbalancerId + '/listeners/' + + item.listeners[0].id + '/pools/' + item.id; + } else { + return 'project/load_balancer/' + + item.loadbalancerId + + '/pools/' + item.id; + } } function getListenersPromise(params) { diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.spec.js index 1892d4e9..e5222821 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.service.spec.js @@ -95,6 +95,9 @@ var myItem = {loadbalancerId: '123', id: '789', listeners: [{id: '456'}]}; expect(service.getPoolDetailsPath(myItem)) .toBe('project/load_balancer/123/listeners/456/pools/789'); + myItem = {loadbalancerId: '123', id: '789', listeners: []}; + expect(service.getPoolDetailsPath(myItem)) + .toBe('project/load_balancer/123/pools/789'); }); it("getPoolsPromise provides a promise", inject(function($timeout) { @@ -127,6 +130,13 @@ }; expect(service.getMemberDetailsPath(myItem)) .toBe('project/load_balancer/1/listeners/2/pools/3/members/4'); + myItem = { + loadbalancerId: '1', + poolId: '3', + id: '4' + }; + expect(service.getMemberDetailsPath(myItem)) + .toBe('project/load_balancer/1/pools/3/members/4'); }); it("getMembersPromise provides a promise", inject(function($timeout) { @@ -165,6 +175,13 @@ }; expect(service.getHealthMonitorDetailsPath(myItem)) .toBe('project/load_balancer/1/listeners/2/pools/3/healthmonitors/4'); + myItem = { + loadbalancerId: '1', + poolId: '3', + id: '4' + }; + expect(service.getHealthMonitorDetailsPath(myItem)) + .toBe('project/load_balancer/1/pools/3/healthmonitors/4'); }); it("getHealthMonitorsPromise provides a promise", inject(function($timeout) { diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.js b/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.js index de0e4d34..3761b32c 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.js @@ -119,9 +119,15 @@ }); if (actionResult.result.failed.length === 0 && actionResult.result.deleted.length > 0) { - var path = 'project/load_balancer/' + loadbalancerId + - '/listeners/' + listenerId + - '/pools/' + poolId; + var path; + if (listenerId) { + path = 'project/load_balancer/' + loadbalancerId + + '/listeners/' + listenerId + + '/pools/' + poolId; + } else { + path = 'project/load_balancer/' + loadbalancerId + + '/pools/' + poolId; + } $location.path(path); } return actionResult.result; diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.spec.js index 2d59fc52..27c44421 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/members/actions/delete/delete.action.service.spec.js @@ -63,7 +63,7 @@ }); }); - it('should handle the action result properly', function() { + it('should handle the action result properly with listener', function() { spyOn($location, 'path'); spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop}); spyOn(lbaasv2API, 'deleteMember').and.callFake(angular.noop); @@ -90,6 +90,33 @@ expect(result.failed[0].id).toBe(1); }); + it('should handle the action result properly without listener', function() { + spyOn($location, 'path'); + spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop}); + spyOn(lbaasv2API, 'deleteMember').and.callFake(angular.noop); + service.perform({loadbalancerId: 1, poolId: 3, id: 1, name: 'one'}); + var result = service.deleteResult({ + fail: [], + pass: [{ + context: { + id: 1 + } + }] + }); + var path = 'project/load_balancer/1/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'); diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.js b/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.js index 23f28b60..cad2730a 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.js @@ -63,6 +63,13 @@ ctrl.provisioningStatus = loadBalancersService.provisioningStatus; ctrl.loadbalancer = loadbalancer; ctrl.listener = listener; + if (!angular.equals({}, ctrl.listener)) { + ctrl.withListenerStyle = {}; + ctrl.withoutListenerStyle = {display: 'none'}; + } else { + ctrl.withListenerStyle = {display: 'none'}; + ctrl.withoutListenerStyle = {}; + } ctrl.pool = pool; ctrl.member = member; ctrl.resourceType = typeRegistry.getResourceType(resourceType); diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.spec.js index 0853d83f..dee5d627 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.controller.spec.js @@ -47,6 +47,19 @@ }; $timeout = _$timeout_; scope = $rootScope.$new(); + ctrl = $controller('MemberDetailController', { + $scope: scope, + loadbalancer: { id: '123' }, + listener: {}, + 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 + } + }); ctrl = $controller('MemberDetailController', { $scope: scope, loadbalancer: { id: '123' }, diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.html b/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.html index c7f546b6..2acda866 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.html +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/members/details/detail.html @@ -4,8 +4,9 @@ - - + + +
diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.js b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.js index ba1b5eb9..9b2bb848 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/create.action.service.js @@ -27,9 +27,7 @@ '$q', 'horizon.dashboard.project.lbaasv2.workflow.modal', 'horizon.app.core.openstack-service-api.policy', - 'horizon.framework.util.i18n.gettext', - 'horizon.framework.util.q.extensions', - '$routeParams' + 'horizon.framework.util.i18n.gettext' ]; /** @@ -45,15 +43,13 @@ * @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. - * @param $routeParams The angular $routeParams service. * * @returns The pool create service. */ function createService( resourceType, actionResultService, - $q, workflowModal, policy, gettext, qExtensions, $routeParams + $q, workflowModal, policy, gettext ) { return workflowModal.init({ controller: 'CreatePoolWizardController', @@ -66,7 +62,6 @@ function allowed() { return $q.all([ - qExtensions.booleanAsPromise(!!$routeParams.listenerId), policy.ifAllowed({ rules: [['neutron', 'create_pool']] }) ]); } diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.js b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.js index 9d0006cf..239fb0d4 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.js @@ -40,6 +40,9 @@ 'fa fa-cloud-download', ['pool', 'members', 'monitor'] ); + if (!listenerId) { + listenerId = null; + } scope.model.initialize('pool', false, loadbalancerId, listenerId); } diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.spec.js index 88c89358..11751ff2 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/create/wizard.controller.spec.js @@ -40,6 +40,16 @@ beforeEach(inject(function ($controller) { spyOn(model, 'initialize'); ctrl = $controller('CreatePoolWizardController', { $scope: scope }); + ctrl = $controller( + 'CreatePoolWizardController', + { + $scope: scope, + $routeParams: { + loadBalancerId: '1', + listenerId: '2' + } + } + ); })); it('defines the controller', function() { diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.js b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.js index 34acc9d4..0f10683b 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.js @@ -121,8 +121,13 @@ }); if (actionResult.result.failed.length === 0 && actionResult.result.deleted.length > 0) { - var path = 'project/load_balancer/' + loadbalancerId + - '/listeners/' + listenerId; + var path; + if (listenerId) { + path = 'project/load_balancer/' + loadbalancerId + + '/listeners/' + listenerId; + } else { + path = 'project/load_balancer/' + loadbalancerId; + } $location.path(path); } return actionResult.result; diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.spec.js index 174a3a15..4d55a372 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/actions/delete/delete.action.service.spec.js @@ -64,7 +64,7 @@ }); }); - it('should handle the action result properly', function() { + it('should handle the action result properly with listener', function() { spyOn($location, 'path'); spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop}); spyOn(lbaasv2API, 'deletePool').and.callFake(angular.noop); @@ -91,6 +91,33 @@ expect(result.failed[0].id).toBe(1); }); + it('should handle the action result properly without listener', function() { + spyOn($location, 'path'); + spyOn(deleteModalService, 'open').and.returnValue({then: angular.noop}); + spyOn(lbaasv2API, 'deletePool').and.callFake(angular.noop); + service.perform({loadbalancerId: 1, id: 1, name: 'one'}); + var result = service.deleteResult({ + fail: [], + pass: [{ + context: { + id: 1 + } + }] + }); + var path = 'project/load_balancer/1'; + 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'); diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.js b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.js index b0845b85..b11bdb8d 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.js @@ -62,6 +62,11 @@ ctrl.loadBalancerAlgorithm = loadBalancersService.loadBalancerAlgorithm; ctrl.loadbalancer = loadbalancer; ctrl.listener = listener; + if (!angular.equals({}, ctrl.listener)) { + ctrl.withListenerStyle = {}; + } else { + ctrl.withListenerStyle = {display: 'none'}; + } ctrl.pool = pool; ctrl.listFunctionExtraParams = { loadbalancerId: ctrl.loadbalancer.id, diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.spec.js index 2bda4630..e2e4210f 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.controller.spec.js @@ -47,6 +47,18 @@ }; $timeout = _$timeout_; scope = $rootScope.$new(); + ctrl = $controller('PoolDetailController', { + $scope: scope, + loadbalancer: { id: '123' }, + listener: {}, + pool: { 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 + } + }); ctrl = $controller('PoolDetailController', { $scope: scope, loadbalancer: { id: '123' }, diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.html b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.html index 51778f85..cb18e180 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.html +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/pools/details/detail.html @@ -4,7 +4,7 @@ - +
diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.js b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.js index b902da01..eff26953 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.js @@ -86,6 +86,7 @@ subnets: [], members: [], listenerProtocols: ['HTTP', 'TCP', 'TERMINATED_HTTPS', 'HTTPS'], + poolProtocols: ['HTTP', 'HTTPS', 'PROXY', 'TCP'], methods: ['LEAST_CONNECTIONS', 'ROUND_ROBIN', 'SOURCE_IP'], types: ['SOURCE_IP', 'HTTP_COOKIE', 'APP_COOKIE'], monitorTypes: ['HTTP', 'PING', 'TCP'], @@ -243,12 +244,20 @@ model.context.submit = createPool; // We get the listener details here because we need to know the listener protocol // in order to default the new pool's protocol to match. - return $q.all([ - lbaasv2API.getListener(model.spec.parentResourceId).then(onGetListener), - neutronAPI.getSubnets().then(onGetSubnets), - neutronAPI.getPorts().then(onGetPorts), - novaAPI.getServers().then(onGetServers) - ]).then(initMemberAddresses); + if (model.spec.parentResourceId) { + return $q.all([ + lbaasv2API.getListener(model.spec.parentResourceId).then(onGetListener), + neutronAPI.getSubnets().then(onGetSubnets), + neutronAPI.getPorts().then(onGetPorts), + novaAPI.getServers().then(onGetServers) + ]).then(initMemberAddresses); + } else { + return $q.all([ + neutronAPI.getSubnets().then(onGetSubnets), + neutronAPI.getPorts().then(onGetPorts), + novaAPI.getServers().then(onGetServers) + ]).then(initMemberAddresses); + } } function initCreateMonitor() { diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.js b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.js index 5ab25445..b01ae577 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.js +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.js @@ -451,7 +451,7 @@ }); }); - describe('Post initialize model (create pool)', function() { + describe('Post initialize model (create pool with listener)', function() { beforeEach(function() { includeChildResources = false; @@ -489,6 +489,44 @@ }); }); + describe('Post initialize model (create pool without listener)', function() { + + beforeEach(function() { + includeChildResources = false; + model.initialize('pool', false, '1234'); + scope.$apply(); + }); + + it('should initialize model properties', function() { + expect(model.initializing).toBe(false); + expect(model.initialized).toBe(true); + expect(model.subnets.length).toBe(2); + expect(model.members.length).toBe(2); + expect(model.certificates.length).toBe(0); + expect(model.listenerPorts.length).toBe(0); + expect(model.spec).toBeDefined(); + expect(model.spec.loadbalancer_id).toBe('1234'); + expect(model.spec.parentResourceId).toBeUndefined(); + expect(model.spec.loadbalancer).toBeDefined(); + expect(model.spec.listener).toBeDefined(); + expect(model.spec.pool).toBeDefined(); + expect(model.spec.members.length).toBe(0); + expect(model.spec.certificates).toEqual([]); + expect(model.spec.monitor).toBeDefined(); + expect(model.certificatesError).toBe(false); + }); + + it('should initialize names', function() { + expect(model.spec.pool.name).toBe('Pool 1'); + }); + + it('should initialize context properties', function() { + expect(model.context.resource).toBe('pool'); + expect(model.context.id).toBeFalsy(); + expect(model.context.submit).toBeDefined(); + }); + }); + describe('Post initialize model (create health monitor)', function() { beforeEach(function() { diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.html b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.html index e2b9172d..4ac2f545 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.html +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.html @@ -19,6 +19,12 @@

+

+ Protocol: + + The protocol for which this pool and its members listen. A valid value is HTTP, HTTPS, PROXY, or TCP. + +

Session Persistence: diff --git a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.html b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.html index d2e7d4ac..35aaaba8 100644 --- a/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.html +++ b/octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.html @@ -21,6 +21,40 @@

+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
@@ -46,24 +80,6 @@
-
- -
-
- - -
-
- -
-
diff --git a/releasenotes/notes/list-pools-on-lb-details-page-eb0400bdb2b3650f.yaml b/releasenotes/notes/list-pools-on-lb-details-page-eb0400bdb2b3650f.yaml new file mode 100644 index 00000000..22e380f7 --- /dev/null +++ b/releasenotes/notes/list-pools-on-lb-details-page-eb0400bdb2b3650f.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Pools attached to a load balancer are now listed on the load balancer + details page.