diff --git a/magnum_ui/api/rest/magnum.py b/magnum_ui/api/rest/magnum.py index e2450861..c5bbcc6a 100644 --- a/magnum_ui/api/rest/magnum.py +++ b/magnum_ui/api/rest/magnum.py @@ -254,7 +254,7 @@ class Quotas(generic.View): item under this is a Quota. """ result = magnum.quotas_list(request) - return {'items': [change_to_id(n.to_dict()) for n in result]} + return {'items': [n.to_dict() for n in result]} @rest_utils.ajax(data_required=True) def post(self, request): @@ -264,7 +264,7 @@ class Quotas(generic.View): """ created = magnum.quotas_create(request, **request.DATA) return rest_utils.CreatedResponse( - ('/api/container_infra/quotas/%s/%s' % created.uuid, + ('/api/container_infra/quotas/%s/%s' % created.id, created.resource), created.to_dict()) diff --git a/magnum_ui/content/container_infra/__init__.py b/magnum_ui/content/container_infra/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/magnum_ui/content/container_infra/quotas/__init__.py b/magnum_ui/content/container_infra/quotas/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/magnum_ui/content/container_infra/quotas/panel.py b/magnum_ui/content/container_infra/quotas/panel.py new file mode 100644 index 00000000..d2f17e22 --- /dev/null +++ b/magnum_ui/content/container_infra/quotas/panel.py @@ -0,0 +1,20 @@ +# 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. + +from django.utils.translation import ugettext_lazy as _ + +import horizon + + +class Quotas(horizon.Panel): + name = _("Quotas") + slug = "container_infra.quotas" diff --git a/magnum_ui/content/container_infra/quotas/urls.py b/magnum_ui/content/container_infra/quotas/urls.py new file mode 100644 index 00000000..1a6afd02 --- /dev/null +++ b/magnum_ui/content/container_infra/quotas/urls.py @@ -0,0 +1,26 @@ +# 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. + +from django.conf.urls import url +from django.utils.translation import ugettext_lazy as _ + +from horizon.browsers import views + +from magnum_ui.content.container_infra.quotas import panel + +title = _("Container Infra - Quotas") +page_title = panel.Quotas.name +urlpatterns = [ + url(r'^$', + views.AngularIndexView.as_view(title=title, page_title=page_title), + name='index'), +] diff --git a/magnum_ui/enabled/_2370_admin_container_infra_panel_group.py b/magnum_ui/enabled/_2370_admin_container_infra_panel_group.py new file mode 100644 index 00000000..52a084ff --- /dev/null +++ b/magnum_ui/enabled/_2370_admin_container_infra_panel_group.py @@ -0,0 +1,19 @@ +# 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. +from django.utils.translation import ugettext_lazy as _ + +# The slug of the panel group to be added to HORIZON_CONFIG. Required. +PANEL_GROUP = 'container_infra' +# The display name of the PANEL_GROUP. Required. +PANEL_GROUP_NAME = _('Container Infra') +# The slug of the dashboard the PANEL_GROUP associated with. Required. +PANEL_GROUP_DASHBOARD = 'admin' diff --git a/magnum_ui/enabled/_2371_admin_container_infra_quotas_panel.py b/magnum_ui/enabled/_2371_admin_container_infra_quotas_panel.py new file mode 100644 index 00000000..68441545 --- /dev/null +++ b/magnum_ui/enabled/_2371_admin_container_infra_quotas_panel.py @@ -0,0 +1,21 @@ +# 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. + +# The slug of the panel to be added to HORIZON_CONFIG. Required. +PANEL = 'container_infra.quotas' +# The slug of the panel group the PANEL is associated with. +PANEL_GROUP = 'container_infra' +# The slug of the dashboard the PANEL associated with. Required. +PANEL_DASHBOARD = 'admin' + +# Python panel class of the PANEL to be added. +ADD_PANEL = 'magnum_ui.content.container_infra.quotas.panel.Quotas' diff --git a/magnum_ui/static/dashboard/container-infra/container-infra.module.js b/magnum_ui/static/dashboard/container-infra/container-infra.module.js index 5fb5bdf9..2ed1f8af 100644 --- a/magnum_ui/static/dashboard/container-infra/container-infra.module.js +++ b/magnum_ui/static/dashboard/container-infra/container-infra.module.js @@ -28,6 +28,7 @@ .module('horizon.dashboard.container-infra', [ 'horizon.dashboard.container-infra.clusters', 'horizon.dashboard.container-infra.cluster-templates', + 'horizon.dashboard.container-infra.quotas', 'ngRoute' ]) .config(config); diff --git a/magnum_ui/static/dashboard/container-infra/quotas/panel.html b/magnum_ui/static/dashboard/container-infra/quotas/panel.html new file mode 100644 index 00000000..1b083dbd --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/quotas/panel.html @@ -0,0 +1,4 @@ + + + diff --git a/magnum_ui/static/dashboard/container-infra/quotas/quotas.module.js b/magnum_ui/static/dashboard/container-infra/quotas/quotas.module.js new file mode 100644 index 00000000..37383aca --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/quotas/quotas.module.js @@ -0,0 +1,149 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function() { + 'use strict'; + + /** + * @ngdoc overview + * @name horizon.dashboard.container-infra.quotas + * @ngModule + * @description + * Provides all the services and widgets require to display the quotas template + * panel + */ + angular + .module('horizon.dashboard.container-infra.quotas', + [ + 'ngRoute' + ]) + .constant('horizon.dashboard.container-infra.quotas.events', events()) + .constant( + 'horizon.dashboard.container-infra.quotas.resourceType', + 'OS::Magnum::Quota') + .run(run) + .config(config); + + /** + * @ngdoc constant + * @name events + * @returns {Object} The event object + * @description A list of events for quotas + */ + function events() { + return { + CREATE_SUCCESS: 'horizon.dashboard.container-infra.quotas.CREATE_SUCCESS', + UPDATE_SUCCESS: 'horizon.dashboard.container-infra.quotas.UPDATE_SUCCESS', + DELETE_SUCCESS: 'horizon.dashboard.container-infra.quotas.DELETE_SUCCESS' + }; + } + + run.$inject = [ + 'horizon.framework.conf.resource-type-registry.service', + 'horizon.dashboard.container-infra.quotas.service', + 'horizon.dashboard.container-infra.quotas.basePath', + 'horizon.dashboard.container-infra.quotas.resourceType' + ]; + + function run(registry, quotasService, basePath, resourceType) { + registry.getResourceType(resourceType) + .setNames(gettext('Quota'), gettext('Quotas')) + // for table row items. + .setProperty('id', { + label: gettext('ID') + }) + .setProperty('project_id', { + label: gettext('Project ID') + }) + .setProperty('resource', { + label: gettext('Resource') + }) + .setProperty('hard_limit', { + label: gettext('Hard Limit') + }) + .setProperty('created_at', { + label: gettext('Created At') + }) + .setProperty('updated_at', { + label: gettext('Updated At') + }) + .setListFunction(quotasService.getQuotasPromise) + .tableColumns + .append({ + id: 'id', + priority: 1 + }) + .append({ + id: 'project_id', + priority: 1 + }) + .append({ + id: 'resource', + priority: 1 + }) + .append({ + id: 'hard_limit', + priority: 1 + }) + .append({ + id: 'created_at', + priority: 2, + filters: ['simpleDate'] + }) + .append({ + id: 'updated_at', + priority: 2, + filters: ['simpleDate'] + }); + + // for magic-search + registry.getResourceType(resourceType).filterFacets + .append({ + 'label': gettext('Project ID'), + 'name': 'project_id', + 'singleton': true + }) + .append({ + 'label': gettext('Resource'), + 'name': 'resource', + 'singleton': true + }) + .append({ + 'label': gettext('Hard Limit'), + 'name': 'hard_limit', + 'singleton': true + }); + } + + config.$inject = [ + '$provide', + '$windowProvider', + '$routeProvider' + ]; + + /** + * @name config + * @param {Object} $provide + * @param {Object} $windowProvider + * @param {Object} $routeProvider + * @returns {undefined} Returns nothing + * @description Routes used by this module. + */ + function config($provide, $windowProvider, $routeProvider) { + var path = $windowProvider.$get().STATIC_URL + 'dashboard/container-infra/quotas/'; + $provide.constant('horizon.dashboard.container-infra.quotas.basePath', path); + $routeProvider.when('/admin/container_infra/quotas', { + templateUrl: path + 'panel.html' + }); + } +})(); diff --git a/magnum_ui/static/dashboard/container-infra/quotas/quotas.module.spec.js b/magnum_ui/static/dashboard/container-infra/quotas/quotas.module.spec.js new file mode 100644 index 00000000..9621c26a --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/quotas/quotas.module.spec.js @@ -0,0 +1,23 @@ +/** + * 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('horizon.dashboard.container-infra.quotas', function() { + it('should exist', function() { + expect(angular.module('horizon.dashboard.container-infra.quotas')).toBeDefined(); + }); + }); + +})(); diff --git a/magnum_ui/static/dashboard/container-infra/quotas/quotas.service.js b/magnum_ui/static/dashboard/container-infra/quotas/quotas.service.js new file mode 100644 index 00000000..f3397d90 --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/quotas/quotas.service.js @@ -0,0 +1,55 @@ +/** + * 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.container-infra.quotas') + .factory('horizon.dashboard.container-infra.quotas.service', + quotasService); + + quotasService.$inject = [ + '$filter', + 'horizon.app.core.openstack-service-api.magnum' + ]; + + /* + * @ngdoc factory + * @name horizon.dashboard.container-infra.quotas.service + * + * @description + * This service provides functions that are used through the Quotas + * features. These are primarily used in the module registrations + * but do not need to be restricted to such use. Each exposed function + * is documented below. + */ + function quotasService($filter, magnum) { + return { + getQuotasPromise: getQuotasPromise + }; + + function getQuotasPromise(params) { + return magnum.getQuotas(params).then(modifyResponse); + + function modifyResponse(response) { + return {data: {items: response.data.items.map(addTrackBy)}}; + + function addTrackBy(quota) { + quota.trackBy = quota.id + quota.resource; + return quota; + } + } + } + } +})(); diff --git a/magnum_ui/static/dashboard/container-infra/quotas/quotas.service.spec.js b/magnum_ui/static/dashboard/container-infra/quotas/quotas.service.spec.js new file mode 100644 index 00000000..58123fd3 --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/quotas/quotas.service.spec.js @@ -0,0 +1,43 @@ +/** + * 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('quotas service', function() { + var magnum, service; + beforeEach(module('horizon.framework')); + beforeEach(module('horizon.app.core.openstack-service-api')); + beforeEach(module('horizon.dashboard.container-infra.quotas')); + beforeEach(inject(function($injector) { + magnum = $injector.get('horizon.app.core.openstack-service-api.magnum'); + service = $injector.get('horizon.dashboard.container-infra.quotas.service'); + })); + + describe('getQuotasPromise', function() { + it("provides a promise", inject(function($q, $timeout) { + var deferred = $q.defer(); + spyOn(magnum, 'getQuotas').and.returnValue(deferred.promise); + var result = service.getQuotasPromise({}); + deferred.resolve({ + data:{ + items: [{id: '123', resource: 'Cluster', hard_limit: 5}] + } + }); + $timeout.flush(); + expect(magnum.getQuotas).toHaveBeenCalled(); + expect(result.$$state.value.data.items[0].id).toBe('123'); + })); + }); + }); +})();