diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..feee5de0 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,55 @@ +# Set up globals +globals: + angular: false + +extends: openstack + +# Most environment options are not explicitly enabled or disabled, only +# included here for completeness' sake. They are commented out, because the +# global updates.py script would otherwise override them during a global +# requirements synchronization. +# +# Individual projects should choose which platforms they deploy to. + +env: + # browser global variables. + browser: true + + # Adds all of the Jasmine testing global variables for version 1.3 and 2.0. + jasmine: true + +# Enable eslint-plugin-angular +plugins: + - angular + +# Below we adjust rules specific to horizon's usage of openstack's linting +# rules, and its own plugin inclusions. +rules: + ############################################################################# + # Disabled Rules from eslint-config-openstack + ############################################################################# + valid-jsdoc: 1 + no-undefined: 1 + brace-style: 1 + strict: 1 + no-extra-parens: 1 + eqeqeq: 1 + consistent-return: 1 + callback-return: 1 + guard-for-in: 1 + block-scoped-var: 1 + semi-spacing: 1 + no-redeclare: 1 + no-new: 1 + + ############################################################################# + # Angular Plugin Customization + ############################################################################# + + angular/ng_controller_as_vm: + - 1 + - "ctrl" + + # Remove after migrating to angular 1.4 or later. + angular/ng_no_cookiestore: + - 1 diff --git a/neutron_lbaas_dashboard/api/rest/lbaasv2.py b/neutron_lbaas_dashboard/api/rest/lbaasv2.py index 75c53857..d9962944 100644 --- a/neutron_lbaas_dashboard/api/rest/lbaasv2.py +++ b/neutron_lbaas_dashboard/api/rest/lbaasv2.py @@ -40,6 +40,27 @@ class LoadBalancers(generic.View): result = neutronclient(request).list_loadbalancers(tenant_id=tenant_id) return {'items': result.get('loadbalancers')} + @rest_utils.ajax() + def post(self, request): + """Create a new load balancer. + + Creates a new load balancer as well as other optional resources such as + a listener, pool, monitor, etc. + """ + data = request.DATA + spec = { + 'vip_subnet_id': data['loadbalancer']['subnet'] + } + if data['loadbalancer'].get('name'): + spec['name'] = data['loadbalancer']['name'] + if data['loadbalancer'].get('description'): + spec['description'] = data['loadbalancer']['description'] + if data['loadbalancer'].get('ip'): + spec['vip_address'] = data['loadbalancer']['ip'] + loadbalancer = neutronclient(request).create_loadbalancer( + {'loadbalancer': spec}).get('loadbalancer') + return loadbalancer + @urls.register class LoadBalancer(generic.View): diff --git a/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/index.html b/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/index.html index bd0e5b3c..bed22e27 100644 --- a/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/index.html +++ b/neutron_lbaas_dashboard/dashboards/project/ngloadbalancersv2/templates/ngloadbalancersv2/index.html @@ -4,7 +4,7 @@ {% block page_header %}{% endblock %} {% block ng_route_base %} - + {% endblock %} {% block main %} diff --git a/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py b/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py index d042001f..5ac855b2 100644 --- a/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py +++ b/neutron_lbaas_dashboard/enabled/_1481_project_ng_loadbalancersv2_panel.py @@ -37,6 +37,15 @@ ADD_JS_FILES = [ 'dashboard/project/lbaasv2/loadbalancers/table.controller.js', 'dashboard/project/lbaasv2/loadbalancers/detail.controller.js', 'dashboard/project/lbaasv2/loadbalancers/filters.js', + 'dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.js', + 'dashboard/project/lbaasv2/loadbalancers/actions/create/modal.service.js', + 'dashboard/project/lbaasv2/loadbalancers/actions/create/model.service.js', + ('dashboard/project/lbaasv2/loadbalancers/actions/create/' + 'wizard.controller.js'), + ('dashboard/project/lbaasv2/loadbalancers/actions/create/' + 'workflow.service.js'), + ('dashboard/project/lbaasv2/loadbalancers/actions/create/details/' + 'details.controller.js'), ] ADD_JS_SPEC_FILES = [ @@ -46,6 +55,18 @@ ADD_JS_SPEC_FILES = [ 'dashboard/project/lbaasv2/loadbalancers/table.controller.spec.js', 'dashboard/project/lbaasv2/loadbalancers/detail.controller.spec.js', 'dashboard/project/lbaasv2/loadbalancers/filters.spec.js', + ('dashboard/project/lbaasv2/loadbalancers/actions/' + 'batch-actions.service.spec.js'), + ('dashboard/project/lbaasv2/loadbalancers/actions/create/' + 'modal.service.spec.js'), + ('dashboard/project/lbaasv2/loadbalancers/actions/create/' + 'model.service.spec.js'), + ('dashboard/project/lbaasv2/loadbalancers/actions/create/' + 'wizard.controller.spec.js'), + ('dashboard/project/lbaasv2/loadbalancers/actions/create/' + 'workflow.service.spec.js'), + ('dashboard/project/lbaasv2/loadbalancers/actions/create/details/' + 'details.controller.spec.js'), ] ADD_SCSS_FILES = [ diff --git a/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.js b/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.js index b73bbbdf..59dad1e9 100644 --- a/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.js +++ b/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.js @@ -29,11 +29,16 @@ * @ngdoc service * @name horizon.app.core.openstack-service-api.loadbalancers * @description Provides direct pass through to neutron LBaaS v2 with NO abstraction. + * @param apiService The horizon core API service. + * @param toastService The horizon toast service. + * @returns The LBaaS V2 service API. */ + function lbaasv2API(apiService, toastService) { var service = { getLoadBalancers: getLoadBalancers, - getLoadBalancer: getLoadBalancer + getLoadBalancer: getLoadBalancer, + createLoadBalancer: createLoadBalancer }; return service; @@ -50,6 +55,7 @@ * The listing result is an object with property "items". Each item is * a load balancer. */ + function getLoadBalancers() { return apiService.get('/api/lbaas/loadbalancers/') .error(function () { @@ -64,6 +70,7 @@ * @param {string} id * Specifies the id of the load balancer to request. */ + function getLoadBalancer(id) { return apiService.get('/api/lbaas/loadbalancers/' + id) .error(function () { @@ -71,5 +78,20 @@ }); } + /** + * @name horizon.app.core.openstack-service-api.lbaasv2.createLoadBalancer + * @description + * Create a new load balancer + * @param {object} spec + * Specifies the data used to create the new load balancer. + */ + + function createLoadBalancer(spec) { + return apiService.post('/api/lbaas/loadbalancers/', spec) + .error(function () { + toastService.add('error', gettext('Unable to create load balancer.')); + }); + } + } }()); diff --git a/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.spec.js b/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.spec.js index 0cd64c83..b917ed23 100644 --- a/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.spec.js +++ b/neutron_lbaas_dashboard/static/app/core/openstack-service-api/lbaasv2.service.spec.js @@ -50,6 +50,16 @@ "testInput": [ '1234' ] + }, + { + "func": "createLoadBalancer", + "method": "post", + "path": "/api/lbaas/loadbalancers/", + "error": "Unable to create load balancer.", + "data": { name: 'loadbalancer-1' }, + "testInput": [ + { name: 'loadbalancer-1' } + ] } ]; diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js index a928ac64..16a506dc 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.js @@ -20,38 +20,43 @@ * @ngdoc overview * @name horizon.dashboard.project.lbaasv2 * @description - * - * # horizon.dashboard.project.lbaasv2 - * * The LBaaS v2 dashboard's top level module. */ + angular .module('horizon.dashboard.project.lbaasv2', [ 'ngRoute', 'horizon.dashboard.project.lbaasv2.loadbalancers' ]) - .config(config); + .config(config) + /* eslint-disable max-len */ + .constant('horizon.dashboard.project.lbaasv2.patterns', { + ipv4: '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))$', + ipv6: '^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$' + }); + /* eslint-enable max-len */ config.$inject = [ + '$provide', '$windowProvider', '$routeProvider', '$locationProvider' ]; - function config($windowProvider, $routeProvider, $locationProvider) { - $locationProvider.html5Mode({ - enabled: true - }).hashPrefix('!'); + function config($provide, $windowProvider, $routeProvider, $locationProvider) { + $locationProvider.html5Mode(true).hashPrefix('!'); - var base = '/project/ngloadbalancersv2/'; - var path = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/'; + var href = '/project/ngloadbalancersv2/'; + var basePath = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/'; + $provide.constant('horizon.dashboard.project.lbaasv2.basePath', basePath); $routeProvider - .when(base, { - templateUrl: path + 'loadbalancers/table.html' - }) - .when(base + 'detail/:loadbalancerId', { - templateUrl: path + 'loadbalancers/detail.html' + .when(href, { + templateUrl: basePath + 'loadbalancers/table.html' }) + .when(href + 'detail/:loadbalancerId', { + templateUrl: basePath + 'loadbalancers/detail.html' + }); } + }()); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js index afd0115a..54800caf 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/lbaasv2.module.spec.js @@ -22,8 +22,27 @@ }); }); + describe('LBaaS v2 Module Base Path', function () { + var basePath, staticUrl; + + beforeEach(module('horizon.dashboard.project.lbaasv2')); + + beforeEach(inject(function ($injector) { + basePath = $injector.get('horizon.dashboard.project.lbaasv2.basePath'); + staticUrl = $injector.get('$window').STATIC_URL; + })); + + it('should be defined', function () { + expect(basePath).toBeDefined(); + }); + + it('should be correct', function () { + expect(basePath).toEqual(staticUrl + 'dashboard/project/lbaasv2/'); + }); + }); + describe('LBaaS v2 Module Config', function () { - var $routeProvider, $locationProvider, path; + var $routeProvider, $locationProvider, basePath; beforeEach(function() { // Create a dummy module so that we can test $routeProvider and $locationProvider calls @@ -32,33 +51,33 @@ .config(function(_$routeProvider_, _$locationProvider_, $windowProvider) { $routeProvider = _$routeProvider_; $locationProvider = _$locationProvider_; - path = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/'; + basePath = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/'; spyOn($routeProvider, 'when').and.callThrough(); spyOn($locationProvider, 'html5Mode').and.callThrough(); }); - module('ngRoute') + module('ngRoute'); module('configTest'); - module('horizon.dashboard.project.lbaasv2') + module('horizon.dashboard.project.lbaasv2'); inject(); }); it('should use html5 mode', function () { - expect($locationProvider.html5Mode).toHaveBeenCalledWith({enabled: true}); + expect($locationProvider.html5Mode).toHaveBeenCalledWith(true); }); it('should route URLs', function () { - var base = '/ngloadbalancersv2/'; + var href = '/project/ngloadbalancersv2/'; var routes = [ [ - base, + href, { - templateUrl: path + 'loadbalancers/table.html' + templateUrl: basePath + 'loadbalancers/table.html' } ], [ - base + 'detail/:loadbalancerId', + href + 'detail/:loadbalancerId', { - templateUrl: path + 'loadbalancers/detail.html' + templateUrl: basePath + 'loadbalancers/detail.html' } ] ]; diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.js new file mode 100644 index 00000000..b57e275e --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.js @@ -0,0 +1,64 @@ +/* + * 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') + .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions', + tableBatchActions); + + tableBatchActions.$inject = [ + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.modal', + 'horizon.dashboard.project.lbaasv2.basePath', + 'horizon.framework.util.i18n.gettext' + ]; + + /** + * @ngdoc service + * @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions + * + * @description + * Provides the service for the Load Balancers table batch actions. + * + * @param createModal The create action modal service. + * @param basePath The lbaasv2 module base path. + * @param gettext The horizon gettext function for translation. + * @returns Load balancers table batch actions service object. + */ + + function tableBatchActions(createModal, basePath, gettext) { + + var service = { + actions: actions + }; + + return service; + + /////////////// + + function actions() { + return [{ + service: createModal, + template: { + url: basePath + 'loadbalancers/actions/create/action.template.html', + text: gettext('Create Load Balancer') + } + }]; + } + } + +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.spec.js new file mode 100644 index 00000000..488a7aaf --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/batch-actions.service.spec.js @@ -0,0 +1,45 @@ +/* + * 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 batchActionsService, scope; + + beforeEach(module('horizon.framework.util')); + beforeEach(module('horizon.framework.conf')); + beforeEach(module('horizon.framework.widgets.toast')); + beforeEach(module('horizon.app.core.openstack-service-api')); + beforeEach(module('horizon.dashboard.project.lbaasv2')); + + beforeEach(module(function($provide) { + $provide.value('$modal', {}); + })); + + beforeEach(inject(function ($injector) { + scope = $injector.get('$rootScope').$new(); + batchActionsService = $injector.get( + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions'); + })); + + it('should define correct table batch actions', function() { + var actions = batchActionsService.actions(); + expect(actions.length).toBe(1); + expect(actions[0].template.text).toBe('Create Load Balancer'); + }); + + }); +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/action.template.html b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/action.template.html new file mode 100644 index 00000000..81f5dcd0 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/action.template.html @@ -0,0 +1,3 @@ + + $text$ + diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.controller.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.controller.js new file mode 100644 index 00000000..7412eb2b --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.controller.js @@ -0,0 +1,47 @@ +/* + * 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('CreateLoadBalancerDetailsController', CreateLoadBalancerDetailsController); + + CreateLoadBalancerDetailsController.$inject = [ + 'horizon.dashboard.project.lbaasv2.patterns' + ]; + + /** + * @ngdoc controller + * @name CreateLoadBalancerDetailsController + * @description + * The `CreateLoadBalancerDetailsController` controller provides functions for + * configuring the details step of the Create Load Balancer Wizard. + * @param patterns The LBaaS v2 patterns constant. + * @returns undefined + */ + + function CreateLoadBalancerDetailsController(patterns) { + + var ctrl = this; + + // Error text for invalid fields + ctrl.loadbalancerIPError = gettext('The IP address is not valid.'); + + // IP address validation pattern + ctrl.ipPattern = [patterns.ipv4, patterns.ipv6].join('|'); + } +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.controller.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.controller.spec.js new file mode 100644 index 00000000..6102bf1e --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.controller.spec.js @@ -0,0 +1,40 @@ +/* + * 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('Create Load Balancer Details Step', function() { + + beforeEach(module('horizon.dashboard.project.lbaasv2')); + + describe('CreateLoadBalancerDetailsController', function() { + var ctrl; + + beforeEach(inject(function($controller) { + ctrl = $controller('CreateLoadBalancerDetailsController'); + })); + + it('should define error messages for invalid fields', function() { + expect(ctrl.loadbalancerIPError).toBeDefined(); + }); + + it('should define patterns for field validation', function() { + expect(ctrl.ipPattern).toBeDefined(); + }); + + }); + }); +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.help.html b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.help.html new file mode 100644 index 00000000..30fd3e67 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.help.html @@ -0,0 +1,3 @@ +

Load Balancer Details Help

+ +

Provide the details for the new load balancer. A subnet is required. The subnet is the network on which to allocate the load balancer's IP address. If an IP address is provided it must be a well-formed IPv4 or IPv6 address. The system will attempt to assign the provided IP address to the load balancer.

diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.html b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.html new file mode 100644 index 00000000..1365ae0f --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/details/details.html @@ -0,0 +1,61 @@ +
+

Load Balancer Details

+ + +
+
Provide the details for the new load balancer.
+ +
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+ +
+
+
+ + + +
+
+ +
+
+ + +
+
+ +
+ +
+ +
diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/modal.service.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/modal.service.js new file mode 100644 index 00000000..b5937206 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/modal.service.js @@ -0,0 +1,85 @@ +/* + * 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') + .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.modal', + modalService); + + modalService.$inject = [ + '$modal', + '$location', + '$window', + 'horizon.framework.widgets.toast.service', + 'horizon.framework.util.i18n.gettext', + 'horizon.app.core.openstack-service-api.policy' + ]; + + /** + * @ngdoc service + * @ngname horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.modal + * + * @description + * Provides the service for opening the create load balancer modal. + * + * @param $modal The angular bootstrap $modal service. + * @param $location The angular $location service. + * @param $window The angular reference to the browser window object. + * @param toastService The horizon toast service. + * @param gettext The horizon gettext function for translation. + * @param policy The horizon policy service. + * @returns The modal service for the create load balancer workflow. + */ + + function modalService($modal, $location, $window, toastService, gettext, policy) { + + var service = { + allowed: allowed, + perform: perform + }; + + return service; + + ////////////// + + 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 perform() { + var spec = { + backdrop: 'static', + controller: 'ModalContainerController', + template: '', + windowClass: 'modal-dialog-wizard', + // ModalContainerController requires a launchContext parameter... + resolve: { + launchContext: null + } + }; + var modal = $modal.open(spec); + modal.result.then(function(response) { + toastService.add('success', gettext('A new load balancer is being created.')); + $location.path($window.WEBROOT + 'project/ngloadbalancersv2/detail/' + response.data.id); + }); + } + + } +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/modal.service.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/modal.service.spec.js new file mode 100644 index 00000000..c78f8323 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/modal.service.spec.js @@ -0,0 +1,107 @@ +/* + * 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 Create Action Modal Service', function() { + var modalService, modal; + + beforeEach(module('horizon.framework.util')); + beforeEach(module('horizon.framework.conf')); + beforeEach(module('horizon.framework.widgets.toast')); + beforeEach(module('horizon.app.core.openstack-service-api')); + beforeEach(module('horizon.dashboard.project.lbaasv2')); + + beforeEach(module(function($provide) { + var response = { + data: { + id: '1' + } + }; + modal = { + open: function() { + return { + result: { + then: function(func) { + func(response); + } + } + }; + } + }; + + var policyAPI = { + ifAllowed: function() { + return true; + } + }; + + $provide.value('$modal', modal); + $provide.value('horizon.app.core.openstack-service-api.policy', policyAPI); + })); + + beforeEach(inject(function ($injector) { + modalService = $injector.get( + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.modal'); + })); + + it('should define function for opening a modal', function() { + expect(modalService.perform).toBeDefined(); + }); + + it('should be allowed based on policy', function() { + expect(modalService.allowed()).toBe(true); + }); + + describe('modalService "perform" function tests', function() { + var toastService, $location; + + beforeEach(inject(function ($injector) { + toastService = $injector.get('horizon.framework.widgets.toast.service'); + $location = $injector.get('$location'); + })); + + it('calls modal.open', function() { + spyOn(modal, 'open').and.callThrough(); + modalService.perform(); + + expect(modal.open).toHaveBeenCalled(); + }); + + it('calls modal.open with expected values', function() { + spyOn(modal, 'open').and.callThrough(); + modalService.perform(); + + var args = modal.open.calls.argsFor(0)[0]; + expect(args.backdrop).toBe('static'); + expect(args.controller).toBeDefined(); + expect(args.resolve).toBeDefined(); + expect(args.resolve.launchContext).toBeNull(); + }); + + it('redirects upon success', function() { + spyOn(toastService, 'add').and.callThrough(); + spyOn($location, 'path').and.callThrough(); + modalService.perform(); + + expect(toastService.add).toHaveBeenCalledWith('success', jasmine.any(String)); + expect($location.path).toHaveBeenCalledWith('/project/ngloadbalancersv2/detail/1'); + }); + + }); + + }); +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/model.service.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/model.service.js new file mode 100644 index 00000000..b2e92999 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/model.service.js @@ -0,0 +1,181 @@ +/* + * 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') + .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.model', + createLoadBalancerModel); + + createLoadBalancerModel.$inject = [ + '$q', + 'horizon.app.core.openstack-service-api.neutron', + 'horizon.app.core.openstack-service-api.lbaasv2' + ]; + + /** + * @ngdoc service + * @name horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.model + * + * @description + * This is the M part of the MVC design pattern for the create load balancer wizard workflow. It + * is responsible for providing data to the view of each step in the workflow and collecting the + * user's input from the view for creation of the new load balancer. It is also the center point + * of communication between the UI and services API. + * + * @param $q The angular service for promises. + * @param neutronAPI The neutron service API. + * @param lbaasv2API The LBaaS V2 service API. + * @returns The model service for the create load balancer workflow. + */ + + function createLoadBalancerModel($q, neutronAPI, lbaasv2API) { + var initPromise; + + /** + * @ngdoc model api object + */ + + var model = { + + initializing: false, + initialized: false, + + /** + * @name spec + * + * @description + * A dictionary like object containing specification collected from user + * input. Required properties include: + * + * @property {String} name: The new load balancer name. + * @property {String} subnet: The subnet for the load balancer. + */ + + spec: null, + + subnets: [], + + /** + * api methods for UI controllers + */ + + initialize: initialize, + createLoadBalancer: createLoadBalancer + }; + + /** + * @ngdoc method + * @name createLoadBalancerModel.initialize + * @returns {promise} + * + * @description + * Send request to get all data to initialize the model. + */ + + function initialize() { + var promise; + + model.spec = { + loadbalancer: { + name: null, + description: null, + ip: null, + subnet: null + } + }; + + if (model.initializing) { + promise = initPromise; + } else { + model.initializing = true; + + promise = $q.all([ + lbaasv2API.getLoadBalancers().then(onGetLoadBalancers), + neutronAPI.getSubnets().then(onGetSubnets) + ]); + + promise.then(onInitSuccess, onInitFail); + } + + return promise; + } + + function onInitSuccess() { + model.initializing = false; + model.initialized = true; + } + + function onInitFail() { + model.initializing = false; + model.initialized = false; + } + + /** + * @ngdoc method + * @name createLoadBalancerModel.createLoadBalancer + * @returns {promise} + * + * @description + * Send request for creating the load balancer. + * + * @returns Response from the LBaaS V2 API for creating a load balancer. + */ + + function createLoadBalancer() { + var finalSpec = angular.copy(model.spec); + + // Delete null properties + angular.forEach(finalSpec, function(group, groupName) { + angular.forEach(group, function(value, key) { + if (value === null) { + delete finalSpec[groupName][key]; + } + }); + }); + + finalSpec.loadbalancer.subnet = finalSpec.loadbalancer.subnet.id; + + return lbaasv2API.createLoadBalancer(finalSpec); + } + + function onGetLoadBalancers(response) { + var existingNames = {}; + angular.forEach(response.data.items, function(lb) { + existingNames[lb.name] = 1; + }); + var name; + var index = 0; + var prefix = 'Load Balancer '; + do { + index += 1; + name = prefix + index; + } while (name in existingNames); + model.spec.loadbalancer.name = name; + } + + function onGetSubnets(response) { + model.subnets = []; + angular.forEach(response.data.items, function(subnet) { + model.subnets.push(subnet); + }); + } + + return model; + } + +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/model.service.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/model.service.spec.js new file mode 100644 index 00000000..8f10e545 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/model.service.spec.js @@ -0,0 +1,184 @@ +/* + * 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 Create Load Balancer Workflow Model Service', function() { + var model, $q, scope; + + beforeEach(module('horizon.dashboard.project.lbaasv2')); + + beforeEach(module(function($provide) { + $provide.value('horizon.app.core.openstack-service-api.lbaasv2', { + getLoadBalancers: function() { + var loadbalancers = [ { name: 'Load Balancer 1' }, { name: 'Load Balancer 2' } ]; + + var deferred = $q.defer(); + deferred.resolve({ data: { items: loadbalancers } }); + + return deferred.promise; + }, + createLoadBalancer: function(spec) { + return spec; + } + }); + + $provide.value('horizon.app.core.openstack-service-api.neutron', { + getSubnets: function() { + var subnets = [ { id: 'subnet-1', name: 'subnet-1' }, + { id: 'subnet-2', name: 'subnet-2' } ]; + + var deferred = $q.defer(); + deferred.resolve({ data: { items: subnets } }); + + return deferred.promise; + } + }); + })); + + beforeEach(inject(function ($injector) { + model = $injector.get( + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.model' + ); + $q = $injector.get('$q'); + scope = $injector.get('$rootScope').$new(); + })); + + describe('Initial object (pre-initialize)', function() { + + it('is defined', function() { + expect(model).toBeDefined(); + }); + + it('has initialization status parameters', function() { + expect(model.initializing).toBeDefined(); + expect(model.initialized).toBeDefined(); + }); + + it('does not yet have a spec', function() { + expect(model.spec).toBeNull(); + }); + + it('has empty subnets array', function() { + expect(model.subnets).toEqual([]); + }); + + it('has an "initialize" function', function() { + expect(model.initialize).toBeDefined(); + }); + + it('has a "createLoadBalancer" function', function() { + expect(model.createLoadBalancer).toBeDefined(); + }); + }); + + describe('Post initialize model', function() { + + beforeEach(function() { + model.initialize(); + 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.spec).toBeDefined(); + expect(model.spec.loadbalancer).toBeDefined(); + }); + + it('should initialize names', function() { + expect(model.spec.loadbalancer.name).toBe('Load Balancer 3'); + }); + }); + + describe('Initialization failure', function() { + + beforeEach(inject(function ($injector) { + var neutronAPI = $injector.get('horizon.app.core.openstack-service-api.neutron'); + neutronAPI.getSubnets = function() { + var deferred = $q.defer(); + deferred.reject('Error'); + return deferred.promise; + }; + })); + + beforeEach(function() { + model.initialize(); + scope.$apply(); + }); + + it('should fail to be initialized on subnets error', function() { + expect(model.initializing).toBe(false); + expect(model.initialized).toBe(false); + expect(model.spec.loadbalancer.name).toBe('Load Balancer 3'); + expect(model.subnets).toEqual([]); + }); + }); + + describe('Post initialize model - Initializing', function() { + + beforeEach(function() { + model.initializing = true; + model.initialize(); + scope.$apply(); + }); + + // This is here to ensure that as people add/change spec properties, they don't forget + // to implement tests for them. + it('has the right number of properties', function() { + expect(Object.keys(model.spec).length).toBe(1); + expect(Object.keys(model.spec.loadbalancer).length).toBe(4); + }); + + it('sets load balancer name to null', function() { + expect(model.spec.loadbalancer.name).toBeNull(); + }); + + it('sets load balancer description to null', function() { + expect(model.spec.loadbalancer.description).toBeNull(); + }); + + it('sets load balancer ip address to null', function() { + expect(model.spec.loadbalancer.ip).toBeNull(); + }); + + it('sets load balancer subnet to null', function() { + expect(model.spec.loadbalancer.subnet).toBeNull(); + }); + }); + + describe('Create Load Balancer', function() { + + beforeEach(function() { + model.initialize(); + scope.$apply(); + }); + + it('should set final spec properties', function() { + model.spec.loadbalancer.ip = '1.2.3.4'; + model.spec.loadbalancer.subnet = model.subnets[0]; + var finalSpec = model.createLoadBalancer(); + + expect(finalSpec.loadbalancer.name).toBe('Load Balancer 3'); + expect(finalSpec.loadbalancer.description).toBeUndefined(); + expect(finalSpec.loadbalancer.ip).toBe('1.2.3.4'); + expect(finalSpec.loadbalancer.subnet).toBe(model.subnets[0].id); + }); + }); + + }); +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.js new file mode 100644 index 00000000..f7386b36 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.js @@ -0,0 +1,42 @@ +/* + * 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('CreateLoadBalancerWizardController', CreateLoadBalancerWizardController); + + CreateLoadBalancerWizardController.$inject = [ + '$scope', + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.model', + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.workflow' + ]; + + function CreateLoadBalancerWizardController( + $scope, + createLoadBalancerModel, + createLoadBalancerWorkflow + ) { + // Note: we set these attributes on the $scope so that the scope inheritance used all + // through the wizard continues to work. + $scope.workflow = createLoadBalancerWorkflow; // eslint-disable-line angular/ng_controller_as + $scope.model = createLoadBalancerModel; // eslint-disable-line angular/ng_controller_as + $scope.model.initialize(); + $scope.submit = $scope.model.createLoadBalancer; // eslint-disable-line angular/ng_controller_as + } + +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.spec.js new file mode 100644 index 00000000..fb7c9155 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/wizard.controller.spec.js @@ -0,0 +1,63 @@ +/* + * 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 Create Load Balancer Wizard Controller', function() { + var ctrl; + var model = { + createLoadBalancer: function() { + return 'created'; + }, + initialize: angular.noop + }; + var scope = {}; + + beforeEach(module('horizon.app.core')); + beforeEach(module('horizon.framework.util')); + beforeEach(module('horizon.framework.conf')); + beforeEach(module('horizon.framework.widgets.toast')); + beforeEach(module('horizon.dashboard.project.lbaasv2')); + beforeEach(module(function ($provide) { + $provide.value('horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.model', + model); + $provide.value('horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.workflow', + { thing: true }); + })); + beforeEach(inject(function ($controller) { + spyOn(model, 'initialize'); + ctrl = $controller('CreateLoadBalancerWizardController', { $scope: scope }); + })); + + it('defines the controller', function() { + expect(ctrl).toBeDefined(); + }); + + it('calls initialize on the given model', function() { + expect(model.initialize).toHaveBeenCalled(); + }); + + it('sets scope.workflow to the given workflow', function() { + expect(scope.workflow).toEqual({ thing: true }); + }); + + it('defines scope.submit', function() { + expect(scope.submit).toBeDefined(); + expect(scope.submit()).toBe('created'); + }); + }); + +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/workflow.service.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/workflow.service.js new file mode 100644 index 00000000..2e91801b --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/workflow.service.js @@ -0,0 +1,53 @@ +/* + * 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') + .factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.workflow', + createLoadBalancerWorkflow); + + createLoadBalancerWorkflow.$inject = [ + 'horizon.dashboard.project.lbaasv2.basePath', + 'horizon.app.core.workflow.factory' + ]; + + function createLoadBalancerWorkflow(basePath, dashboardWorkflow) { + return dashboardWorkflow({ + title: gettext('Create Load Balancer'), + + steps: [ + { + id: 'loadbalancer', + title: gettext('Load Balancer Details'), + templateUrl: basePath + 'loadbalancers/actions/create/details/details.html', + helpUrl: basePath + 'loadbalancers/actions/create/details/details.help.html', + formName: 'createLoadBalancerDetailsForm' + } + ], + + btnText: { + finish: gettext('Create Load Balancer') + }, + + btnIcon: { + finish: 'fa fa-cloud-download' + } + }); + } + +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/workflow.service.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/workflow.service.spec.js new file mode 100644 index 00000000..3165eb07 --- /dev/null +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/actions/create/workflow.service.spec.js @@ -0,0 +1,65 @@ +/* + * 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 Create Load Balancer Workflow Service', function() { + var createLoadBalancerWorkflow; + + beforeEach(module('horizon.app.core')); + beforeEach(module('horizon.framework.util')); + beforeEach(module('horizon.framework.conf')); + beforeEach(module('horizon.framework.widgets.toast')); + beforeEach(module('horizon.dashboard.project.lbaasv2')); + + beforeEach(inject(function ($injector) { + createLoadBalancerWorkflow = $injector.get( + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.create.workflow' + ); + })); + + it('should be defined', function () { + expect(createLoadBalancerWorkflow).toBeDefined(); + }); + + it('should have a title property', function () { + expect(createLoadBalancerWorkflow.title).toBeDefined(); + }); + + it('should have steps defined', function () { + expect(createLoadBalancerWorkflow.steps).toBeDefined(); + expect(createLoadBalancerWorkflow.steps.length).toBe(1); + + var forms = [ + 'createLoadBalancerDetailsForm' + ]; + + forms.forEach(function(expectedForm, idx) { + expect(createLoadBalancerWorkflow.steps[idx].formName).toBe(expectedForm); + }); + }); + + it('can be extended', function () { + expect(createLoadBalancerWorkflow.append).toBeDefined(); + expect(createLoadBalancerWorkflow.prepend).toBeDefined(); + expect(createLoadBalancerWorkflow.after).toBeDefined(); + expect(createLoadBalancerWorkflow.replace).toBeDefined(); + expect(createLoadBalancerWorkflow.remove).toBeDefined(); + expect(createLoadBalancerWorkflow.addController).toBeDefined(); + }); + + }); +})(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.js index eee777ad..a207b5ad 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.js @@ -21,9 +21,9 @@ .controller('LoadBalancerDetailController', LoadBalancerDetailController); LoadBalancerDetailController.$inject = [ - 'horizon.dashboard.project.lbaasv2.loadbalancers.basePath', 'horizon.app.core.openstack-service-api.lbaasv2', - '$routeParams' + '$routeParams', + '$window' ]; /** @@ -32,12 +32,18 @@ * * @description * Controller for the LBaaS v2 load balancers detail page. + * + * @param api The LBaaS v2 API service. + * @param $routeParams The angular $routeParams service. + * @param $window The angular reference to the browser window object. + * @returns undefined */ - function LoadBalancerDetailController(basepath, api, $routeParams) { + + function LoadBalancerDetailController(api, $routeParams, $window) { var ctrl = this; ctrl.loadbalancer = {}; - ctrl.path = basepath; + ctrl.webroot = $window.webroot; var loadbalancerId = $routeParams.loadbalancerId; diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.spec.js index 7797e81a..d3676191 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.spec.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.controller.spec.js @@ -31,8 +31,9 @@ beforeEach(module('horizon.framework.util.http')); beforeEach(module('horizon.framework.widgets.toast')); + beforeEach(module('horizon.framework.conf')); beforeEach(module('horizon.app.core.openstack-service-api')); - beforeEach(module('horizon.dashboard.project.lbaasv2.loadbalancers')); + beforeEach(module('horizon.dashboard.project.lbaasv2')); beforeEach(inject(function($injector) { loadbalancer = { id: '1234' }; @@ -49,11 +50,6 @@ }); } - it('should set path properly', function() { - var path = staticUrl + 'dashboard/project/lbaasv2/loadbalancers/'; - expect(createController().path).toEqual(path); - }); - it('should invoke lbaasv2 apis', function() { createController(); expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('1234'); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.html b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.html index f5305160..39c2052c 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.html +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/detail.html @@ -36,22 +36,19 @@
Subnet ID
- {$ ::ctrl.loadbalancer.vip_subnet_id $} + {$ ::ctrl.loadbalancer.vip_subnet_id $}
Port ID
- {$ ::ctrl.loadbalancer.vip_port_id $} + {$ ::ctrl.loadbalancer.vip_port_id $}
- - - - - + + diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/filters.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/filters.js index fe353036..1dd11346 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/filters.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/filters.js @@ -34,7 +34,10 @@ * @name operatingStatusFilter * @description * Takes raw load balancer operating status from the API and returns the user friendly status. + * @param gettext The horizon gettext function for translation. + * @returns The function for filtering the load balancer operating status. */ + function operatingStatusFilter(gettext) { var statuses = { 'ONLINE': gettext('Online'), @@ -54,7 +57,10 @@ * @name provisioningStatusFilter * @description * Takes raw load balancer provisioning status from the API and returns the user friendly status. + * @param gettext The horizon gettext function for translation. + * @returns The function for filtering the load balancer provisioning status. */ + function provisioningStatusFilter(gettext) { var statuses = { 'ACTIVE': gettext('Active'), diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.js index e93cbbe8..ee5fd195 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.js @@ -24,18 +24,8 @@ * Provides the services and widgets required to support and display the project load * balancers v2 panel. */ + angular - .module('horizon.dashboard.project.lbaasv2.loadbalancers', []) - .config(config); - - config.$inject = [ - '$provide', - '$windowProvider' - ]; - - function config($provide, $windowProvider) { - var path = $windowProvider.$get().STATIC_URL + 'dashboard/project/lbaasv2/loadbalancers/'; - $provide.constant('horizon.dashboard.project.lbaasv2.loadbalancers.basePath', path); - } + .module('horizon.dashboard.project.lbaasv2.loadbalancers', []); })(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.spec.js index ced3746b..e48dc891 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.spec.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/loadbalancers.module.spec.js @@ -22,22 +22,4 @@ }); }); - describe('LBaaS v2 Load Balancers Module Base Path', function () { - var basePath, staticUrl; - - beforeEach(module('horizon.dashboard.project.lbaasv2.loadbalancers')); - beforeEach(inject(function ($injector) { - basePath = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.basePath'); - staticUrl = $injector.get('$window').STATIC_URL; - })); - - it('should be defined', function () { - expect(basePath).toBeDefined(); - }); - - it('should be correct', function () { - expect(basePath).toEqual(staticUrl + 'dashboard/project/lbaasv2/loadbalancers/'); - }); - }); - })(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.js index 40007e87..3dbde29b 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.js @@ -18,11 +18,13 @@ angular .module('horizon.dashboard.project.lbaasv2.loadbalancers') - .controller('loadBalancersTableController', LoadBalancersTableController); + .controller('LoadBalancersTableController', LoadBalancersTableController); LoadBalancersTableController.$inject = [ - 'horizon.dashboard.project.lbaasv2.loadbalancers.basePath', - 'horizon.app.core.openstack-service-api.lbaasv2' + '$scope', + '$window', + 'horizon.app.core.openstack-service-api.lbaasv2', + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions' ]; /** @@ -30,16 +32,23 @@ * @name LoadBalancersTableController * * @description - * Controller for the LBaaS v2 load balancers table. - * Serves as the focal point for table actions. + * Controller for the LBaaS v2 load balancers table. Serves as the focal point for table actions. + * + * @param $scope The angular $scope object. + * @param $window The angular reference to the browser window object. + * @param api The LBaaS V2 service API. + * @param batchActions The load balancer batch actions service. + * @returns undefined */ - function LoadBalancersTableController(basepath, api) { + + function LoadBalancersTableController($scope, $window, api, batchActions) { var ctrl = this; ctrl.items = []; ctrl.src = []; ctrl.checked = {}; - ctrl.path = basepath; + ctrl.webroot = $window.webroot; + ctrl.batchActions = batchActions; init(); diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.spec.js b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.spec.js index 1d30f0e9..d80e5d62 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.spec.js +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.controller.spec.js @@ -17,7 +17,8 @@ 'use strict'; describe('LBaaS v2 Load Balancers Table Controller', function() { - var controller, lbaasv2API, staticUrl, items = []; + var controller, lbaasv2API, staticUrl, scope, batchActionsService; + var items = []; function fakeAPI() { return { @@ -29,22 +30,29 @@ /////////////////////// - beforeEach(module('horizon.framework.util.http')); 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.loadbalancers')); + beforeEach(module('horizon.dashboard.project.lbaasv2')); + + beforeEach(module(function($provide) { + $provide.value('$modal', {}); + })); beforeEach(inject(function($injector) { lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2'); + batchActionsService = $injector.get( + 'horizon.dashboard.project.lbaasv2.loadbalancers.actions.batchActions'); controller = $injector.get('$controller'); staticUrl = $injector.get('$window').STATIC_URL; + scope = $injector.get('$rootScope').$new(); + scope.lbaasv2API = lbaasv2API; spyOn(lbaasv2API, 'getLoadBalancers').and.callFake(fakeAPI); })); function createController() { - return controller('loadBalancersTableController', { - lbaasv2API: lbaasv2API - }); + return controller('LoadBalancersTableController', { $scope: scope }); } it('should initialize correctly', function() { @@ -52,11 +60,7 @@ expect(ctrl.items).toEqual([]); expect(ctrl.src).toEqual(items); expect(ctrl.checked).toEqual({}); - }); - - it('should set path properly', function() { - var path = staticUrl + 'dashboard/project/lbaasv2/loadbalancers/'; - expect(createController().path).toEqual(path); + expect(ctrl.batchActions).toBeDefined(); }); it('should invoke lbaasv2 apis', function() { diff --git a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.html b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.html index e893b58f..8b31a92b 100644 --- a/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.html +++ b/neutron_lbaas_dashboard/static/dashboard/project/lbaasv2/loadbalancers/table.html @@ -1,6 +1,6 @@ - @@ -70,7 +71,7 @@ duration="200"> - +
+
{$ item.name $}{$ item.name $} {$ item.description | noValue $} {$ item.operating_status | operatingStatus $} {$ item.provisioning_status | provisioningStatus $}