From 05e5bb1b99a23a7242558b0c77f0e11574f913dc Mon Sep 17 00:00:00 2001 From: Shu Muto Date: Thu, 14 Jun 2018 17:57:22 +0900 Subject: [PATCH] Add create action for capsule This patch adds create action for capsule as global action. Change-Id: I9ffcc9bcc3118850a174eae0f8afc1dc34b40c34 Partial-Implements: blueprint capsule --- zun_ui/api/client.py | 8 ++ zun_ui/api/rest_api.py | 11 +++ .../container/capsules/actions.module.js | 13 ++- .../capsules/actions/create.service.js | 84 +++++++++++++++++ .../workflow/load-template.controller.js | 47 ++++++++++ .../actions/workflow/load-template.html | 9 ++ .../actions/workflow/workflow.service.js | 89 +++++++++++++++++++ .../static/dashboard/container/zun.service.js | 6 ++ 8 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 zun_ui/static/dashboard/container/capsules/actions/create.service.js create mode 100644 zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.controller.js create mode 100644 zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.html create mode 100644 zun_ui/static/dashboard/container/capsules/actions/workflow/workflow.service.js diff --git a/zun_ui/api/client.py b/zun_ui/api/client.py index 545c9ec..0e4a123 100644 --- a/zun_ui/api/client.py +++ b/zun_ui/api/client.py @@ -20,12 +20,14 @@ from openstack_dashboard.api import base from neutronclient.v2_0 import client as neutron_client from zunclient import api_versions +from zunclient.common import template_format from zunclient.common import utils from zunclient.v1 import client as zun_client LOG = logging.getLogger(__name__) CONTAINER_CREATE_ATTRS = zun_client.containers.CREATION_ATTRIBUTES +CAPSULE_CREATE_ATTRS = zun_client.capsules.CREATION_ATTRIBUTES IMAGE_PULL_ATTRS = zun_client.images.PULL_ATTRIBUTES API_VERSION = api_versions.APIVersion(api_versions.DEFAULT_API_VERSION) @@ -276,6 +278,12 @@ def capsule_show(request, id): return zunclient(request).capsules.get(id) +def capsule_create(request, **kwargs): + args, run = _cleanup_params(CAPSULE_CREATE_ATTRS, True, **kwargs) + args["template"] = template_format.parse(args["template"]) + return zunclient(request).capsules.create(**args) + + def image_list(request, limit=None, marker=None, sort_key=None, sort_dir=None, detail=False): # FIXME(shu-mutou): change "detail" param to True, if it enabled. diff --git a/zun_ui/api/rest_api.py b/zun_ui/api/rest_api.py index 1224ba4..53e3e45 100644 --- a/zun_ui/api/rest_api.py +++ b/zun_ui/api/rest_api.py @@ -178,6 +178,17 @@ class Capsules(generic.View): result = client.capsule_list(request) return {'items': [i.to_dict() for i in result]} + @rest_utils.ajax(data_required=True) + def post(self, request): + """Create a new Capsule. + + Returns the new Capsule object on success. + """ + new_capsule = client.capsule_create(request, **request.DATA) + return rest_utils.CreatedResponse( + '/api/zun/capsules/%s' % new_capsule.uuid, + new_capsule.to_dict()) + @urls.register class Capsule(generic.View): diff --git a/zun_ui/static/dashboard/container/capsules/actions.module.js b/zun_ui/static/dashboard/container/capsules/actions.module.js index db5d5c9..fe91688 100644 --- a/zun_ui/static/dashboard/container/capsules/actions.module.js +++ b/zun_ui/static/dashboard/container/capsules/actions.module.js @@ -32,6 +32,7 @@ registerCapsuleActions.$inject = [ 'horizon.framework.conf.resource-type-registry.service', 'horizon.framework.util.i18n.gettext', + 'horizon.dashboard.container.capsules.actions.create.service', 'horizon.dashboard.container.capsules.actions.refresh.service', 'horizon.dashboard.container.capsules.resourceType' ]; @@ -39,12 +40,22 @@ function registerCapsuleActions( registry, gettext, + createCapsuleService, refreshCapsuleService, resourceType ) { var capsulesResourceType = registry.getResourceType(resourceType); - // FIXME(shu-mutow): refresh action is dummy. remove it when add other action. + capsulesResourceType.globalActions + .append({ + id: 'createCapsuleAction', + service: createCapsuleService, + template: { + text: gettext('Create') + } + }); + + // FIXME(shu-mutow): refresh action is dummy. remove it when add other item action. capsulesResourceType.itemActions .append({ id: 'refreshCapsuleAction', diff --git a/zun_ui/static/dashboard/container/capsules/actions/create.service.js b/zun_ui/static/dashboard/container/capsules/actions/create.service.js new file mode 100644 index 0000000..9e6f51f --- /dev/null +++ b/zun_ui/static/dashboard/container/capsules/actions/create.service.js @@ -0,0 +1,84 @@ +/** + * 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 factory + * @name horizon.dashboard.container.capsules.actions.create.service + * @description + * Service for the create capsule modal + */ + angular + .module('horizon.dashboard.container.capsules.actions') + .factory('horizon.dashboard.container.capsules.actions.create.service', createCapsuleService); + + createCapsuleService.$inject = [ + 'horizon.app.core.openstack-service-api.policy', + 'horizon.app.core.openstack-service-api.zun', + 'horizon.dashboard.container.capsules.actions.workflow', + 'horizon.dashboard.container.capsules.resourceType', + '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' + ]; + + function createCapsuleService( + policy, zun, workflow, resourceType, + actionResult, gettext, $qExtensions, modal, toast + ) { + + var message = { + success: gettext('Request to create capsule %s has been accepted.') + }; + + var service = { + initAction: initAction, + perform: perform, + allowed: allowed + }; + + return service; + + ////////////// + + function initAction() { + } + + function perform() { + var title, submitText; + title = gettext('Create Capsule'); + submitText = gettext('Create'); + var config = workflow.init('create', title, submitText); + return modal.open(config).then(submit); + } + + function allowed() { + return policy.ifAllowed({ rules: [['capsule', 'create_capsule']] }); + } + + function submit(context) { + return zun.createCapsule(context.model, true).then(success, true); + } + + function success(response) { + toast.add('success', interpolate(message.success, [response.data.id])); + var result = actionResult.getActionResult().created(resourceType, response.data.name); + return result.result; + } + } +})(); diff --git a/zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.controller.js b/zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.controller.js new file mode 100644 index 0000000..ef65b02 --- /dev/null +++ b/zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.controller.js @@ -0,0 +1,47 @@ +/** + * 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 controller + * @name horizon.dashboard.container.capsules.actions.workflow.loadTemplateController + * @ngController + * + * @description + * Controller for the loading template file + */ + angular + .module('horizon.dashboard.container.capsules.actions') + .controller('horizon.dashboard.container.capsules.actions.workflow.loadTemplateController', + loadTemplateController); + + loadTemplateController.$inject = [ + '$scope' + ]; + + function loadTemplateController($scope) { + var ctrl = this; + ctrl.title = $scope.schema.properties.template.title; + ctrl.template = ""; + ctrl.onTemplateChange = onTemplateChange; + + //// + + function onTemplateChange(template) { + $scope.model.template = template; + } + } +})(); diff --git a/zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.html b/zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.html new file mode 100644 index 0000000..21100ff --- /dev/null +++ b/zun_ui/static/dashboard/container/capsules/actions/workflow/load-template.html @@ -0,0 +1,9 @@ +
+ + +
diff --git a/zun_ui/static/dashboard/container/capsules/actions/workflow/workflow.service.js b/zun_ui/static/dashboard/container/capsules/actions/workflow/workflow.service.js new file mode 100644 index 0000000..db2ad9c --- /dev/null +++ b/zun_ui/static/dashboard/container/capsules/actions/workflow/workflow.service.js @@ -0,0 +1,89 @@ +/** + * 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 factory + * @name horizon.dashboard.container.capsules.actions.workflow + * @description + * Workflow for creating capsule + */ + angular + .module('horizon.dashboard.container.capsules.actions') + .factory('horizon.dashboard.container.capsules.actions.workflow', workflow); + + workflow.$inject = [ + 'horizon.dashboard.container.capsules.basePath', + 'horizon.framework.util.i18n.gettext' + ]; + + function workflow(basePath, gettext) { + var workflow = { + init: init + }; + + function init(actionType, title, submitText) { + var schema, form, model; + + // schema + schema = { + type: 'object', + properties: { + template: { + title: gettext('Template'), + type: 'string' + } + } + }; + + // form + form = [ + { + type: 'section', + htmlClass: 'row', + items: [ + { + type: 'section', + htmlClass: 'col-sm-12', + items: [ + { + type: 'template', + templateUrl: basePath + 'actions/workflow/load-template.html', + } + ] + } + ] + } + ]; // form + + model = { + template: '' + }; + + var config = { + title: title, + submitText: submitText, + schema: schema, + form: form, + model: model + }; + + return config; + } + + return workflow; + } +})(); diff --git a/zun_ui/static/dashboard/container/zun.service.js b/zun_ui/static/dashboard/container/zun.service.js index 7385648..5a179af 100644 --- a/zun_ui/static/dashboard/container/zun.service.js +++ b/zun_ui/static/dashboard/container/zun.service.js @@ -55,6 +55,7 @@ getZunAvailabilityZones: getZunAvailabilityZones, getCapsules: getCapsules, getCapsule: getCapsule, + createCapsule: createCapsule, pullImage: pullImage, getImages: getImages, deleteImage: deleteImage, @@ -214,6 +215,11 @@ return apiService.get(capsulesPath + id).error(error(msg)); } + function createCapsule(params) { + var msg = gettext('Unable to create Capsule.'); + return apiService.post(capsulesPath, params).error(error(msg)); + } + //////////// // Images // ////////////