From 2f01c46a404da9060375091f5a1e2c29640ff190 Mon Sep 17 00:00:00 2001 From: Shu Muto Date: Thu, 19 Jan 2017 17:56:13 +0900 Subject: [PATCH] Add update action for cluster template This patch adds update action as item action into cluster template table and details view. To be available updating 'lables', needs to fix bug/1638863 Change-Id: Iee1eec7bc7d232e743d3420a98f7ee3128d3f7f1 Implements: blueprint baymodel-update --- magnum_ui/api/magnum.py | 76 +++++++-- magnum_ui/api/rest/magnum.py | 13 ++ .../cluster-templates/actions.module.js | 9 + .../cluster-templates.service.js | 4 +- .../create/create.service.js | 10 +- .../create/create.service.spec.js | 6 +- .../update/update.service.js | 156 ++++++++++++++++++ .../update/update.service.spec.js | 90 ++++++++++ .../{create => workflow}/info.help.html | 0 .../{create => workflow}/labels.help.html | 0 .../{create => workflow}/network.help.html | 0 .../{create => workflow}/spec.help.html | 0 .../workflow.service.js} | 35 ++-- .../workflow.service.spec.js} | 6 +- .../container-infra/magnum.service.js | 8 + 15 files changed, 370 insertions(+), 43 deletions(-) create mode 100644 magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.js create mode 100644 magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.spec.js rename magnum_ui/static/dashboard/container-infra/cluster-templates/{create => workflow}/info.help.html (100%) rename magnum_ui/static/dashboard/container-infra/cluster-templates/{create => workflow}/labels.help.html (100%) rename magnum_ui/static/dashboard/container-infra/cluster-templates/{create => workflow}/network.help.html (100%) rename magnum_ui/static/dashboard/container-infra/cluster-templates/{create => workflow}/spec.help.html (100%) rename magnum_ui/static/dashboard/container-infra/cluster-templates/{create/create-workflow.service.js => workflow/workflow.service.js} (95%) rename magnum_ui/static/dashboard/container-infra/cluster-templates/{create/create-workflow.service.spec.js => workflow/workflow.service.spec.js} (92%) diff --git a/magnum_ui/api/magnum.py b/magnum_ui/api/magnum.py index 7bdbaca3..20f3a510 100644 --- a/magnum_ui/api/magnum.py +++ b/magnum_ui/api/magnum.py @@ -43,6 +43,59 @@ CLUSTER_CREATE_ATTRS = ['name', 'cluster_template_id', 'node_count', CERTIFICATE_CREATE_ATTRS = ['cluster_uuid', 'csr'] +def _cleanup_params(attrs, check, **params): + args = {} + for (key, value) in params.items(): + if key in attrs: + if value is None: + value = '' + args[str(key)] = str(value) + elif check: + raise exceptions.BadRequest( + "Key must be in %s" % ",".join(attrs)) + if key == "labels": + if isinstance(value, str) or isinstance(value, unicode): + labels = {} + vals = value.split(",") + for v in vals: + kv = v.split("=", 1) + labels[kv[0]] = kv[1] + args["labels"] = labels + else: + args["labels"] = value + return args + + +def _create_patches(old, new): + """"Create patches for updating cluster template and cluster + + Returns patches include operations for each parameters to update values + """ + # old = {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D', 'e': 'E'} + # new = {'a': 'A', 'c': 'c', 'd': None, 'e': '', 'f': 'F'} + # patch = [ + # {'op': 'add', 'path': '/f', 'value': 'F'} + # {'op': 'remove', 'path': '/e'}, + # {'op': 'remove', 'path': '/d'}, + # {'op': 'replace', 'path': '/c', 'value': 'c'} + # ] + + patch = [] + + for key in new: + path = '/' + key + if key in old and old[key] != new[key]: + if new[key] is None or new[key] is '': + patch.append({'op': 'remove', 'path': path}) + else: + patch.append({'op': 'replace', 'path': path, + 'value': new[key]}) + elif key not in old: + patch.append({'op': 'add', 'path': path, 'value': new[key]}) + + return patch + + @memoized def magnumclient(request): magnum_url = "" @@ -69,23 +122,18 @@ def magnumclient(request): def cluster_template_create(request, **kwargs): - args = {} - for (key, value) in kwargs.items(): - if key in CLUSTER_TEMPLATE_CREATE_ATTRS: - args[str(key)] = str(value) - else: - raise exceptions.BadRequest( - "Key must be in %s" % ",".join(CLUSTER_TEMPLATE_CREATE_ATTRS)) - if key == "labels": - labels = {} - vals = value.split(",") - for v in vals: - kv = v.split("=", 1) - labels[kv[0]] = kv[1] - args["labels"] = labels + args = _cleanup_params(CLUSTER_TEMPLATE_CREATE_ATTRS, True, **kwargs) return magnumclient(request).cluster_templates.create(**args) +def cluster_template_update(request, id, **kwargs): + new = _cleanup_params(CLUSTER_TEMPLATE_CREATE_ATTRS, True, **kwargs) + old = magnumclient(request).cluster_templates.get(id).to_dict() + old = _cleanup_params(CLUSTER_TEMPLATE_CREATE_ATTRS, False, **old) + patch = _create_patches(old, new) + return magnumclient(request).cluster_templates.update(id, patch) + + def cluster_template_delete(request, id): return magnumclient(request).cluster_templates.delete(id) diff --git a/magnum_ui/api/rest/magnum.py b/magnum_ui/api/rest/magnum.py index d4a0ba00..19589099 100644 --- a/magnum_ui/api/rest/magnum.py +++ b/magnum_ui/api/rest/magnum.py @@ -41,6 +41,19 @@ class ClusterTemplate(generic.View): return change_to_id(magnum.cluster_template_show(request, template_id) .to_dict()) + @rest_utils.ajax(data_required=True) + def patch(self, request, template_id): + """Update a Cluster Template. + + Returns the Cluster Template object on success. + """ + params = request.DATA + updated_template = magnum.cluster_template_update( + request, template_id, **params) + return rest_utils.CreatedResponse( + '/api/container_infra/cluster_template/%s' % template_id, + updated_template.to_dict()) + @urls.register class ClusterTemplates(generic.View): diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/actions.module.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/actions.module.js index acd984c2..b2c4f73a 100644 --- a/magnum_ui/static/dashboard/container-infra/cluster-templates/actions.module.js +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/actions.module.js @@ -34,6 +34,7 @@ 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.container-infra.cluster-templates.create.service', 'horizon.dashboard.container-infra.cluster-templates.delete.service', + 'horizon.dashboard.container-infra.cluster-templates.update.service', 'horizon.dashboard.container-infra.clusters.create.service', 'horizon.dashboard.container-infra.cluster-templates.resourceType' ]; @@ -43,6 +44,7 @@ gettext, createClusterTemplateService, deleteClusterTemplateService, + updateClusterTemplateService, createClusterService, resourceType) { @@ -76,6 +78,13 @@ text: gettext('Create Cluster') } }) + .append({ + id: 'updateClusterTemplateAction', + service: updateClusterTemplateService, + template: { + text: gettext('Update Cluster Template') + } + }) .append({ id: 'deleteClusterTemplateAction', service: deleteClusterTemplateService, diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/cluster-templates.service.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/cluster-templates.service.js index b270ee65..ef2497af 100644 --- a/magnum_ui/static/dashboard/container-infra/cluster-templates/cluster-templates.service.js +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/cluster-templates.service.js @@ -47,7 +47,9 @@ return {data: {items: response.data.items.map(addTrackBy)}}; function addTrackBy(clusterTemplate) { - clusterTemplate.trackBy = clusterTemplate.id; + /* eslint-disable max-len */ + var timestamp = clusterTemplate.updated_at ? clusterTemplate.updated_at : clusterTemplate.created_at; + clusterTemplate.trackBy = clusterTemplate.id + timestamp; return clusterTemplate; } } diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.js index 957cedf8..c71c4df1 100644 --- a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.js +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.js @@ -32,16 +32,14 @@ 'horizon.framework.util.actions.action-result.service', 'horizon.framework.util.i18n.gettext', 'horizon.framework.util.q.extensions', - 'horizon.framework.widgets.modal.wizard-modal.service', + 'horizon.framework.widgets.form.ModalFormService', 'horizon.framework.widgets.toast.service', 'horizon.dashboard.container-infra.cluster-templates.resourceType', - 'horizon.dashboard.container-infra.cluster-templates.workflow', - 'horizon.framework.widgets.form.ModalFormService' + 'horizon.dashboard.container-infra.cluster-templates.workflow' ]; function createService( - magnum, policy, actionResult, gettext, $qExtensions, wizardModalService, - toast, resourceType, createWorkflow, modal + magnum, policy, actionResult, gettext, $qExtensions, modal, toast, resourceType, workflow ) { var config; @@ -59,7 +57,7 @@ ////////////// function perform() { - config = createWorkflow.init(); + config = workflow.init('create', gettext('Create Cluster Template')); return modal.open(config).then(submit); } diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.spec.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.spec.js index e1b6f8da..bac2b934 100644 --- a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.spec.js +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create.service.spec.js @@ -19,7 +19,7 @@ describe('horizon.dashboard.container-infra.cluster-templates.create.service', function() { - var service, $scope, $q, deferred, magnum, createWorkflow; + var service, $scope, $q, deferred, magnum, workflow; var model = { tabs: "", keypair_id: "", @@ -50,13 +50,13 @@ service = $injector.get( 'horizon.dashboard.container-infra.cluster-templates.create.service'); magnum = $injector.get('horizon.app.core.openstack-service-api.magnum'); - createWorkflow = $injector.get( + workflow = $injector.get( 'horizon.dashboard.container-infra.cluster-templates.workflow'); deferred = $q.defer(); deferred.resolve({data: {uuid: 1}}); spyOn(magnum, 'createClusterTemplate').and.returnValue(deferred.promise); spyOn(modal, 'open').and.callThrough(); - spyOn(createWorkflow, 'init').and.returnValue({model: model}); + spyOn(workflow, 'init').and.returnValue({model: model}); })); it('should check the policy if the user is allowed to create cluster template', function() { diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.js new file mode 100644 index 00000000..0fafb6c8 --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.js @@ -0,0 +1,156 @@ +/** + * Copyright 2017 NEC Corporation + * + * 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.cluster-templates.update.service + * @description Service for the container-infra cluster template update modal + */ + angular + .module('horizon.dashboard.container-infra.cluster-templates') + .factory('horizon.dashboard.container-infra.cluster-templates.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.cluster-templates.resourceType', + 'horizon.dashboard.container-infra.cluster-templates.workflow' + ]; + + function updateService( + magnum, policy, actionResult, gettext, $qExtensions, modal, toast, resourceType, workflow + ) { + + var config; + var message = { + success: gettext('Cluster template %s was successfully updated.') + }; + + var service = { + perform: perform, + allowed: allowed + }; + + return service; + + ////////////// + + function perform(selected) { + config = workflow.init('update', gettext('Update Cluster Template')); + config.model.id = selected.id; + + // load current data + magnum.getClusterTemplate(selected.id).then(onLoad); + function onLoad(response) { + config.model.name = response.data.name + ? response.data.name : ""; + config.model.coe = response.data.coe + ? response.data.coe : ""; + config.model.public = response.data.public + ? response.data.public : false; + config.model.registry_enabled = response.data.registry_enabled + ? response.data.registry_enabled : false; + config.model.tls_disabled = response.data.tls_disabled + ? response.data.tls_disabled : false; + config.model.image_id = response.data.image_id + ? response.data.image_id : ""; + config.model.flavor_id = response.data.flavor_id + ? response.data.flavor_id : ""; + config.model.master_flavor_id = response.data.master_flavor_id + ? response.data.master_flavor_id : ""; + config.model.docker_volume_size = response.data.docker_volume_size + ? response.data.docker_volume_size : ""; + config.model.docker_storage_driver = response.data.docker_storage_driver + ? response.data.docker_storage_driver : ""; + config.model.keypair_id = response.data.keypair_id + ? response.data.keypair_id : ""; + config.model.network_driver = response.data.network_driver + ? response.data.network_driver : ""; + config.model.volume_driver = response.data.volume_driver + ? response.data.volume_driver : ""; + config.model.http_proxy = response.data.http_proxy + ? response.data.http_proxy : ""; + config.model.https_proxy = response.data.https_proxy + ? response.data.https_proxy : ""; + config.model.no_proxy = response.data.no_proxy + ? response.data.no_proxy : ""; + config.model.external_network_id = response.data.external_network_id + ? response.data.external_network_id : ""; + config.model.fixed_network = response.data.fixed_network + ? response.data.fixed_network : ""; + config.model.fixed_subnet = response.data.fixed_subnet + ? response.data.fixed_subnet : ""; + config.model.dns_nameserver = response.data.dns_nameserver + ? response.data.dns_nameserver : ""; + config.model.master_lb_enabled = response.data.master_lb_enabled + ? response.data.master_lb_enabled : false; + config.model.floating_ip_enabled = response.data.floating_ip_enabled + ? response.data.floating_ip_enabled : false; + var labels = ""; + for (var key in response.data.labels) { + if (response.data.labels.hasOwnProperty(key)) { + if (labels !== "") { + labels += ","; + } + labels += key + "=" + response.data.labels[key]; + } + } + config.model.labels = labels; // + } + + return modal.open(config).then(submit); + } + + function allowed() { + return $qExtensions.booleanAsPromise(true); + } + + function submit(context) { + var id = context.model.id; + context.model = cleanNullProperties(context.model); + return magnum.updateClusterTemplate(id, context.model, true) + .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] === "" || + key === "tabs" || key === "id") { + delete model[key]; + } + } + return model; + } + + function success(response) { + response.data.id = response.data.uuid; + toast.add('success', interpolate(message.success, [response.data.id])); + return actionResult.getActionResult() + .updated(resourceType, response.data.id) + .result; + } + } +})(); diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.spec.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.spec.js new file mode 100644 index 00000000..8c1ef18d --- /dev/null +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/update/update.service.spec.js @@ -0,0 +1,90 @@ +/** + * Copyright 2017 NEC Corporation + * + * 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.cluster-templates.update.service', function() { + + var service, $scope, $q, deferred, magnum; + var selected = { + id: 1 + }; + var model = { + id: 1, + tabs: "", + keypair_id: "", + coe: null + }; + 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.cluster-templates')); + + beforeEach(module(function($provide) { + $provide.value('horizon.dashboard.container-infra.cluster-templates.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.cluster-templates.update.service'); + magnum = $injector.get('horizon.app.core.openstack-service-api.magnum'); + deferred = $q.defer(); + deferred.resolve({data: {uuid: 1, labels: "key1:val1,key2:val2"}}); + spyOn(magnum, 'getClusterTemplate').and.returnValue(deferred.promise); + spyOn(magnum, 'updateClusterTemplate').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 cluster template', 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.updateClusterTemplate).toHaveBeenCalled(); + })); + }); +})(); diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/info.help.html b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/info.help.html similarity index 100% rename from magnum_ui/static/dashboard/container-infra/cluster-templates/create/info.help.html rename to magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/info.help.html diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/labels.help.html b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/labels.help.html similarity index 100% rename from magnum_ui/static/dashboard/container-infra/cluster-templates/create/labels.help.html rename to magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/labels.help.html diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/network.help.html b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/network.help.html similarity index 100% rename from magnum_ui/static/dashboard/container-infra/cluster-templates/create/network.help.html rename to magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/network.help.html diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/spec.help.html b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/spec.help.html similarity index 100% rename from magnum_ui/static/dashboard/container-infra/cluster-templates/create/spec.help.html rename to magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/spec.help.html diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create-workflow.service.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/workflow.service.js similarity index 95% rename from magnum_ui/static/dashboard/container-infra/cluster-templates/create/create-workflow.service.js rename to magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/workflow.service.js index 37026d67..28d24e07 100644 --- a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create-workflow.service.js +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/workflow.service.js @@ -36,7 +36,7 @@ init: init }; - function init() { + function init(action, title) { var schema, form, model; var images = [{value:"", name: gettext("Choose an Image")}]; var nflavors = [{value:"", name: gettext("Choose a Flavor for the Node")}]; @@ -76,7 +76,7 @@ type: 'string', 'x-schema-form': { type: 'string', - placeholder: gettext('Name of the cluster template to create.') + placeholder: gettext('Name of the cluster template.') } }, 'coe': { @@ -206,8 +206,7 @@ placeholder: gettext('KEY1=VALUE1, KEY2=VALUE2...') } } - }, - required: ['coe', 'image_id', 'external_network_id'] + } }; // form @@ -217,7 +216,7 @@ tabs: [ { title: gettext('Info'), - help: basePath + 'cluster-templates/create/info.help.html', + help: basePath + 'cluster-templates/workflow/info.help.html', type: 'section', htmlClass: 'row', items: [ @@ -232,6 +231,7 @@ key: 'coe', type: 'select', titleMap: coes, + required: true, onChange: function() { if (model.coe) { form[0].tabs[2].items[0].items[0].items[0].titleMap = @@ -267,12 +267,11 @@ ] } ], - required: ['coe'] - + required: true }, { title: gettext('Node Spec'), - help: basePath + 'cluster-templates/create/spec.help.html', + help: basePath + 'cluster-templates/workflow/spec.help.html', type: 'section', htmlClass: 'row', items: [ @@ -287,7 +286,8 @@ { key: 'image_id', type: 'select', - titleMap: images + titleMap: images, + required: true }, { key: 'flavor_id', @@ -353,11 +353,11 @@ ] } ], - required: ['image_id'] + required: true }, { title: gettext('Network'), - help: basePath + 'cluster-templates/create/network.help.html', + help: basePath + 'cluster-templates/workflow/network.help.html', type: 'section', htmlClass: 'row', items: [ @@ -388,7 +388,8 @@ key: 'no_proxy' }, { - key: 'external_network_id' + key: 'external_network_id', + required: true }, { key: 'fixed_network' @@ -410,11 +411,11 @@ ] } ], - required: ['external_network_id'] + required: true }, { title: gettext('Labels'), - help: basePath + 'cluster-templates/create/labels.help.html', + help: basePath + 'cluster-templates/workflow/labels.help.html', type: 'section', htmlClass: 'row', items: [ @@ -427,7 +428,9 @@ htmlClass: 'col-xs-12', items: [ { - key: 'labels' + key: 'labels', + // fixme: to be available, needs to fix bug/1638863 + readonly: action === 'update' } ] } @@ -489,7 +492,7 @@ }; var config = { - title: gettext('Create Cluster Template'), + title: title, schema: schema, form: form, model: model diff --git a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create-workflow.service.spec.js b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/workflow.service.spec.js similarity index 92% rename from magnum_ui/static/dashboard/container-infra/cluster-templates/create/create-workflow.service.spec.js rename to magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/workflow.service.spec.js index 6872b256..df41319b 100644 --- a/magnum_ui/static/dashboard/container-infra/cluster-templates/create/create-workflow.service.spec.js +++ b/magnum_ui/static/dashboard/container-infra/cluster-templates/workflow/workflow.service.spec.js @@ -19,7 +19,7 @@ describe('horizon.dashboard.container-infra.cluster-templates.workflow', function() { - var createWorkflow, nova, glance, $q, deferred, keyDeferred; + var workflow, nova, glance, $q, deferred, keyDeferred; beforeEach(module('horizon.app.core')); beforeEach(module('horizon.framework')); @@ -27,7 +27,7 @@ beforeEach(inject(function($injector, _$q_) { $q = _$q_; - createWorkflow = $injector.get( + workflow = $injector.get( 'horizon.dashboard.container-infra.cluster-templates.workflow'); nova = $injector.get('horizon.app.core.openstack-service-api.nova'); glance = $injector.get('horizon.app.core.openstack-service-api.glance'); @@ -42,7 +42,7 @@ })); it('should be init', inject(function($timeout) { - var config = createWorkflow.init(); + var config = workflow.init('create', 'Create Cluster Template'); $timeout.flush(); expect(config.title).toBeDefined(); expect(config.schema).toBeDefined(); diff --git a/magnum_ui/static/dashboard/container-infra/magnum.service.js b/magnum_ui/static/dashboard/container-infra/magnum.service.js index 2acd1b46..f2584855 100644 --- a/magnum_ui/static/dashboard/container-infra/magnum.service.js +++ b/magnum_ui/static/dashboard/container-infra/magnum.service.js @@ -35,6 +35,7 @@ deleteCluster: deleteCluster, deleteClusters: deleteClusters, createClusterTemplate: createClusterTemplate, + updateClusterTemplate: updateClusterTemplate, getClusterTemplate: getClusterTemplate, getClusterTemplates: getClusterTemplates, deleteClusterTemplate: deleteClusterTemplate, @@ -98,6 +99,13 @@ }); } + function updateClusterTemplate(id, params) { + return apiService.patch('/api/container_infra/cluster_templates/' + id, params) + .error(function() { + toastService.add('error', gettext('Unable to update cluster template.')); + }); + } + function getClusterTemplate(id) { return apiService.get('/api/container_infra/cluster_templates/' + id) .error(function() {