From 444c4faf9014637d85d79d6f1d69b13a35d4014b Mon Sep 17 00:00:00 2001 From: Shu Muto Date: Wed, 13 Jun 2018 11:24:21 +0900 Subject: [PATCH] Add delete action for images This patch adds delete action for images panel. Delete action needs to specify "host" parameter, so this action is implemeted as item action. Change-Id: I722d2859785ead7175a63d72ab42e1a9e33197ed Implements: blueprint add-image-delete --- zun_ui/api/client.py | 4 + zun_ui/api/rest_api.py | 11 ++ .../container/images/actions.module.js | 11 ++ .../images/actions/delete.service.js | 142 ++++++++++++++++++ .../static/dashboard/container/zun.service.js | 6 + 5 files changed, 174 insertions(+) create mode 100644 zun_ui/static/dashboard/container/images/actions/delete.service.js diff --git a/zun_ui/api/client.py b/zun_ui/api/client.py index f783fe7..b5c272e 100644 --- a/zun_ui/api/client.py +++ b/zun_ui/api/client.py @@ -278,6 +278,10 @@ def image_create(request, **kwargs): return zunclient(request).images.create(**args) +def image_delete(request, id, **kwargs): + return zunclient(request).images.delete(id, **kwargs) + + def host_list(request, limit=None, marker=None, sort_key=None, sort_dir=None, detail=False): return zunclient(request).hosts.list(limit, marker, sort_key, diff --git a/zun_ui/api/rest_api.py b/zun_ui/api/rest_api.py index 3311f1a..3d4cd76 100644 --- a/zun_ui/api/rest_api.py +++ b/zun_ui/api/rest_api.py @@ -190,6 +190,17 @@ class Images(generic.View): new_image.to_dict()) +@urls.register +class Image(generic.View): + """API for operate a single image""" + url_regex = r'zun/images/(?P[^/]+)$' + + @rest_utils.ajax(data_required=True) + def delete(self, request, id): + """Delete a specific image""" + client.image_delete(request, id, **request.DATA) + + @urls.register class Hosts(generic.View): """API for Zun Hosts""" diff --git a/zun_ui/static/dashboard/container/images/actions.module.js b/zun_ui/static/dashboard/container/images/actions.module.js index 061c23f..0bba984 100644 --- a/zun_ui/static/dashboard/container/images/actions.module.js +++ b/zun_ui/static/dashboard/container/images/actions.module.js @@ -33,6 +33,7 @@ 'horizon.framework.conf.resource-type-registry.service', 'horizon.framework.util.i18n.gettext', 'horizon.dashboard.container.images.actions.create.service', + 'horizon.dashboard.container.images.actions.delete.service', 'horizon.dashboard.container.images.resourceType' ]; @@ -40,6 +41,7 @@ registry, gettext, createImageService, + deleteImageService, resourceType ) { var imagesResourceType = registry.getResourceType(resourceType); @@ -53,6 +55,15 @@ text: gettext('Pull Image') } }); + + imagesResourceType.itemActions + .append({ + id: 'deleteImageAction', + service: deleteImageService, + template: { + text: gettext('Delete Image') + } + }); } })(); diff --git a/zun_ui/static/dashboard/container/images/actions/delete.service.js b/zun_ui/static/dashboard/container/images/actions/delete.service.js new file mode 100644 index 0000000..1782030 --- /dev/null +++ b/zun_ui/static/dashboard/container/images/actions/delete.service.js @@ -0,0 +1,142 @@ +/** + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use self 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.images.actions.delete.service + * @Description + * restart container. + */ + angular + .module('horizon.dashboard.container.images.actions') + .factory('horizon.dashboard.container.images.actions.delete.service', deleteService); + + deleteService.$inject = [ + 'horizon.app.core.openstack-service-api.zun', + 'horizon.dashboard.container.images.basePath', + 'horizon.dashboard.container.images.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 deleteService( + zun, basePath, resourceType, actionResult, gettext, $qExtensions, modal, toast + ) { + var push = Array.prototype.push; + var hosts = [{value: "", name: gettext("Select host to remove the image from.")}]; + // schema + var schema = { + type: "object", + properties: { + host: { + title: gettext("Host"), + type: "string" + } + } + }; + + // form + var form = [ + { + type: 'section', + htmlClass: 'row', + items: [ + { + type: 'section', + htmlClass: 'col-sm-12', + items: [ + { + key: 'host', + type: "select", + titleMap: hosts, + required: true + } + ] + } + ] + } + ]; + + // model + var model; + + // get hosts for zun + zun.getHosts().then(onGetZunHosts); + function onGetZunHosts(response) { + var hs = []; + response.data.items.forEach(function (host) { + hs.push({value: host.id, name: host.hostname}); + }); + push.apply(hosts, hs); + } + + var message = { + success: gettext('Container %s was successfully restarted.') + }; + + var service = { + initAction: initAction, + allowed: allowed, + perform: perform + }; + + return service; + + ////////////// + + // include this function in your service + // if you plan to emit events to the parent controller + function initAction() { + } + + function allowed() { + return $qExtensions.booleanAsPromise(true); + } + + function perform(selected) { + model = { + id: selected.id, + repo: selected.repo, + host: "" + }; + + // modal config + var config = { + "title": interpolate(gettext('Delete Image %s'), [model.repo]), + "submitText": gettext('Delete'), + "schema": schema, + "form": form, + "model": model + }; + return modal.open(config).then(submit); + + function submit(context) { + var id = context.model.id; + var repo = context.model.repo; + var host = context.model.host; + return zun.deleteImage(id, host).then(function() { + toast.add('success', interpolate(message.success, [repo])); + var result = actionResult.getActionResult().updated(resourceType, id); + return result.result; + }); + } + } + } +})(); diff --git a/zun_ui/static/dashboard/container/zun.service.js b/zun_ui/static/dashboard/container/zun.service.js index 799d968..a8084f0 100644 --- a/zun_ui/static/dashboard/container/zun.service.js +++ b/zun_ui/static/dashboard/container/zun.service.js @@ -54,6 +54,7 @@ getZunAvailabilityZones: getZunAvailabilityZones, pullImage: pullImage, getImages: getImages, + deleteImage: deleteImage, getHosts: getHosts }; @@ -210,6 +211,11 @@ return apiService.get(imagesPath).error(error(msg)); } + function deleteImage(id, host) { + var msg = gettext('Unable to delete the Image.'); + return apiService.delete(imagesPath + id, {host: host}).error(error(msg)); + } + /////////// // Hosts // ///////////