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 @@
-
-
-
-
-
+
+
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 $} |