diff --git a/magnum_ui/api/magnum.py b/magnum_ui/api/magnum.py index 3784e408..9bdd5e32 100644 --- a/magnum_ui/api/magnum.py +++ b/magnum_ui/api/magnum.py @@ -223,11 +223,7 @@ def quotas_create(request, **kwargs): def quotas_update(request, project_id, resource, **kwargs): - new = _cleanup_params(QUOTA_CREATION_ATTRIBUTES, True, **kwargs) - old = magnumclient(request).quotas.get(project_id, resource).to_dict() - old = _cleanup_params(QUOTA_CREATION_ATTRIBUTES, False, **old) - patch = _create_patches(old, new) - return magnumclient(request).quotas.update(project_id, resource, patch) + return magnumclient(request).quotas.update(project_id, resource, kwargs) def quotas_delete(request, project_id, resource): diff --git a/magnum_ui/api/rest/magnum.py b/magnum_ui/api/rest/magnum.py index 477cca95..5e6af047 100644 --- a/magnum_ui/api/rest/magnum.py +++ b/magnum_ui/api/rest/magnum.py @@ -227,9 +227,9 @@ class Quota(generic.View): """ params = request.DATA updated = magnum.quotas_update( - request, project_id, resource, **params) + request, **params) return rest_utils.CreatedResponse( - ('/api/container_infra/quotas/%s/%s' % project_id, resource), + ('/api/container_infra/quotas/%s/%s' % (project_id, resource)), updated.to_dict()) @rest_utils.ajax(data_required=True) diff --git a/magnum_ui/static/dashboard/container-infra/quotas/actions.module.js b/magnum_ui/static/dashboard/container-infra/quotas/actions.module.js index 8ba4f946..bb8fa41f 100644 --- a/magnum_ui/static/dashboard/container-infra/quotas/actions.module.js +++ b/magnum_ui/static/dashboard/container-infra/quotas/actions.module.js @@ -33,6 +33,7 @@ 'horizon.framework.conf.resource-type-registry.service', 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.container-infra.quotas.create.service', + 'horizon.dashboard.container-infra.quotas.update.service', 'horizon.dashboard.container-infra.quotas.delete.service', 'horizon.dashboard.container-infra.quotas.resourceType' ]; @@ -41,6 +42,7 @@ registry, gettext, createQuotaService, + updateQuotaService, deleteQuotaService, resourceType) { @@ -66,6 +68,13 @@ }); quotaResourceType.itemActions + .append({ + id: 'updateQuotaService', + service: updateQuotaService, + template: { + text: gettext('Update Quota') + } + }) .append({ id: 'deleteQuotaService', service: deleteQuotaService, diff --git a/magnum_ui/static/dashboard/container-infra/quotas/update/update.service.js b/magnum_ui/static/dashboard/container-infra/quotas/update/update.service.js new file mode 100644 index 00000000..d6c4539b --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/quotas/update/update.service.js @@ -0,0 +1,106 @@ +/** + * 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.update.service + * @description Service for the container-infra quotas update modal + */ + angular + .module('horizon.dashboard.container-infra.quotas') + .factory('horizon.dashboard.container-infra.quotas.update.service', updateService); + + updateService.$inject = [ + 'horizon.app.core.openstack-service-api.magnum', + 'horizon.app.core.openstack-service-api.policy', + 'horizon.framework.util.actions.action-result.service', + 'horizon.framework.util.i18n.gettext', + 'horizon.framework.util.q.extensions', + 'horizon.framework.widgets.form.ModalFormService', + 'horizon.framework.widgets.toast.service', + 'horizon.dashboard.container-infra.quotas.resourceType', + 'horizon.dashboard.container-infra.quotas.workflow' + ]; + + function updateService( + magnum, policy, actionResult, gettext, $qExtensions, modal, toast, resourceType, workflow + ) { + + var config; + var message = { + success: gettext('Quota %s/%s was successfully updated.') + }; + + var service = { + perform: perform, + allowed: allowed + }; + + return service; + + ////////////// + + function perform(selected, $scope) { + config = workflow.init('update', gettext('Update Quota'), $scope); + config.model.id = selected.id; + + // load current data + magnum.getQuota(selected.project_id, selected.resource).then(onLoad); + function onLoad(response) { + config.model.id = response.data.id + ? response.data.id : ""; + config.model.project_id = response.data.project_id + ? response.data.project_id : ""; + config.model.resource = response.data.resource + ? response.data.resource : "Cluster"; + config.model.hard_limit = response.data.hard_limit + ? response.data.hard_limit : null; + } + + return modal.open(config).then(submit); + } + + function allowed() { + return $qExtensions.booleanAsPromise(true); + } + + function submit(context) { + context.model = cleanNullProperties(context.model); + return magnum.updateQuota(context.model.project_id, context.model.resource, context.model) + .then(success, true); + } + + function cleanNullProperties(model) { + // Initially clean fields that don't have any value. + // Not only "null", blank too. + for (var key in model) { + if (model.hasOwnProperty(key) && model[key] === null || model[key] === "") { + delete model[key]; + } + } + return model; + } + + function success(response) { + toast.add('success', interpolate(message.success, [ + response.data.project_id, response.data.resource])); + return actionResult.getActionResult() + .updated(resourceType, response.data.id) + .result; + } + } +})(); diff --git a/magnum_ui/static/dashboard/container-infra/quotas/update/update.service.spec.js b/magnum_ui/static/dashboard/container-infra/quotas/update/update.service.spec.js new file mode 100644 index 00000000..16e71d6f --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/quotas/update/update.service.spec.js @@ -0,0 +1,88 @@ +/** + * 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.update.service', function() { + + var service, $scope, $q, deferred, magnum; + var selected = { + id: 1 + }; + var model = { + id: 1, + project_id: "p1", + resource: "Cluster", + hard_limit: 1 + }; + var modal = { + open: function(config) { + config.model = model; + deferred = $q.defer(); + deferred.resolve(config); + return deferred.promise; + } + }; + var workflow = { + init: function (action, title) { + action = title; + return {model: model}; + } + }; + + /////////////////// + + beforeEach(module('horizon.app.core')); + beforeEach(module('horizon.framework')); + beforeEach(module('horizon.dashboard.container-infra.quotas')); + + beforeEach(module(function($provide) { + $provide.value('horizon.dashboard.container-infra.quotas.workflow', workflow); + $provide.value('horizon.framework.widgets.form.ModalFormService', modal); + })); + + beforeEach(inject(function($injector, _$rootScope_, _$q_) { + $q = _$q_; + $scope = _$rootScope_.$new(); + service = $injector.get( + 'horizon.dashboard.container-infra.quotas.update.service'); + magnum = $injector.get('horizon.app.core.openstack-service-api.magnum'); + deferred = $q.defer(); + deferred.resolve({data: {id: 1, project_id: "p1", resource: "Cluster", hard_limit: 1}}); + spyOn(magnum, 'getQuota').and.returnValue(deferred.promise); + spyOn(magnum, 'updateQuota').and.returnValue(deferred.promise); + spyOn(workflow, 'init').and.returnValue({model: model}); + spyOn(modal, 'open').and.callThrough(); + })); + + it('should check the policy if the user is allowed to update quota', function() { + var allowed = service.allowed(); + expect(allowed).toBeTruthy(); + }); + + it('open the modal', inject(function($timeout) { + service.perform(selected, $scope); + + expect(workflow.init).toHaveBeenCalled(); + + expect(modal.open).toHaveBeenCalledWith({model: model}); + + $timeout.flush(); + $scope.$apply(); + + expect(magnum.updateQuota).toHaveBeenCalled(); + })); + }); +})();