From 759df1f9be9afe1d9912f6db3eae75976b6bf27b Mon Sep 17 00:00:00 2001 From: Peter Piela Date: Mon, 9 Jan 2017 12:32:19 -0500 Subject: [PATCH] Refactor the edit-node/nodeUpdatePatch class The nodeUpdatePatch class has been refactored in to a separate updatePatch service that will be used to patch both nodes and ports. Change-Id: I725bfe92fb9f878db243dd987f07f1c8eb04440c --- .../ironic/edit-node/edit-node.controller.js | 6 +- .../ironic/edit-node/edit-node.service.js | 161 +-------------- .../admin/ironic/update-patch.service.js | 187 ++++++++++++++++++ 3 files changed, 194 insertions(+), 160 deletions(-) create mode 100644 ironic_ui/static/dashboard/admin/ironic/update-patch.service.js diff --git a/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.controller.js b/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.controller.js index 10370f7e..1b54a1bf 100644 --- a/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.controller.js +++ b/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.controller.js @@ -31,6 +31,7 @@ 'horizon.app.core.openstack-service-api.ironic', 'horizon.dashboard.admin.ironic.events', 'horizon.dashboard.admin.ironic.edit-node.service', + 'horizon.dashboard.admin.ironic.update-patch.service', '$log', 'node' ]; @@ -42,6 +43,7 @@ ironic, ironicEvents, editNodeService, + updatePatchService, $log, node) { var ctrl = this; @@ -109,7 +111,7 @@ * @return {object[]} Array of patch instructions */ function buildPatch(sourceNode, targetNode) { - var patcher = new editNodeService.NodeUpdatePatch(); + var patcher = new updatePatchService.UpdatePatch(); patcher.buildPatch(sourceNode.name, targetNode.name, "/name"); patcher.buildPatch(sourceNode.driver, targetNode.driver, "/driver"); @@ -152,7 +154,7 @@ var patch = buildPatch(ctrl.baseNode, ctrl.node); $log.info("patch = " + JSON.stringify(patch.patch)); - if (patch.status === editNodeService.NodeUpdatePatch.status.OK) { + if (patch.status === updatePatchService.UpdatePatch.status.OK) { ironic.updateNode(ctrl.baseNode.uuid, patch.patch).then(function() { $rootScope.$emit(ironicEvents.EDIT_NODE_SUCCESS); }); diff --git a/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.service.js b/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.service.js index 22471e85..18fc8ffc 100644 --- a/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.service.js +++ b/ironic_ui/static/dashboard/admin/ironic/edit-node/edit-node.service.js @@ -23,14 +23,12 @@ editNodeService.$inject = [ '$uibModal', - 'horizon.dashboard.admin.ironic.basePath', - '$log' + 'horizon.dashboard.admin.ironic.basePath' ]; - function editNodeService($uibModal, basePath, $log) { + function editNodeService($uibModal, basePath) { var service = { - modal: modal, - NodeUpdatePatch: NodeUpdatePatch + modal: modal }; function modal(node) { @@ -47,159 +45,6 @@ return $uibModal.open(options); } - /* - The NodeUpdatePatch class is used to construct a set of patch - instructions that transform a base node into a specified target. - This class supports the edit-node functionality. - */ - function NodeUpdatePatch() { - this.patch = []; - this.status = NodeUpdatePatch.status.OK; - } - - NodeUpdatePatch.status = { - OK: 0, - ERROR: 1, - UNKNOWN_TYPE: 2 - }; - - /** - * @description Update the status of the patch with a specified code - * - * @param {int} status - latest status code - * @return {void} - */ - NodeUpdatePatch.prototype._updateStatus = function(status) { - this.status = Math.max(this.status, status); - }; - - /** - * @description Check whether an item is a property - * - * @param {object} item - item to be tested - * @return {boolean} True if the item is a number, string, or date - */ - function isProperty(item) { - return item === null || - angular.isNumber(item) || - angular.isString(item) || - angular.isDate(item); - } - - /** - * @description Check whether an item is a collection - * - * @param {object} item - item to be tested - * @return {boolean} True if the item is an array or object - */ - function isCollection(item) { - return angular.isArray(item) || angular.isObject(item); - } - - /** - * @description Add instructions to the patch for processing a - * specified item - * - * @param {object} item - item to be added - * @param {string} path - Path to the item being added - * @param {string} op - add or remove - * @return {void} - */ - NodeUpdatePatch.prototype._processItem = function(item, path, op) { - $log.info("NodeUpdatePatch._processItem: " + path + " " + op); - if (isProperty(item)) { - this.patch.push({op: op, path: path, value: item}); - } else if (isCollection(item)) { - angular.forEach(item, function(partName, part) { - this._processItem(part, path + "/" + partName, op); - }); - } else { - this._updateStatus(NodeUpdatePatch.status.UNKNOWN_TYPE); - $log.error("Unable to process (" + op + ") item (" + path + "). " + - " " + typeof item + " " + JSON.stringify(item)); - } - }; - - /** - * @description Add instructions to the patch for adding a specified item - * - * @param {object} item - item to be added - * @param {string} path - Path to the item being removed - * @return {void} - */ - NodeUpdatePatch.prototype._addItem = function(item, path) { - this._processItem(item, path, "add"); - }; - - /** - * @description Add instructions to the patch for removing a specified item - * - * @param {object} item - item to be removed - * @param {string} path - Path to the item being removed - * @return {void} - */ - NodeUpdatePatch.prototype._removeItem = function(item, path) { - this._processItem(item, path, "remove"); - }; - - /** - * @description Determine the set of operations required to - * transform a source version of an object into a target version, - * and add them to a patch. - * - * @param {object} source - Source object - * @param {object} target - Target object - * @param {string} path - Pathname of the patched object - * @return {void} - */ - NodeUpdatePatch.prototype.buildPatch = function(source, target, path) { - $log.info("NodeUpdatePatch._buildPatch: " + path); - var patcher = this; - - if (isProperty(source) && isProperty(target)) { - if (source !== target) { - patcher.patch.push({op: "replace", path: path, value: target}); - } - } else if (isCollection(source) && isCollection(target)) { - angular.forEach(source, function(sourceItem, sourceItemName) { - if (angular.isDefined(target[sourceItemName])) { - patcher.buildPatch(sourceItem, - target[sourceItemName], - path + '/' + sourceItemName); - } else { - patcher._removeItem(sourceItem, path + '/' + sourceItemName); - } - }); - angular.forEach(target, function(targetItem, targetItemName) { - if (angular.isUndefined(source[targetItemName])) { - patcher._addItem(targetItem, path + '/' + targetItemName); - } - }); - } else if (isProperty(source) && isCollection(target) || - isCollection(source) && isProperty(target)) { - patcher._removeItem(source, path); - patcher._addItem(target, path); - } else { - patcher._updateStatus(NodeUpdatePatch.status.ERROR); - $log.error("Unable to patch " + path + " " + - "source = " + JSON.stringify(source) + ", " + - "target = " + JSON.stringify(target)); - } - }; - - /** - * @description Get the patch - * - * @return {object} An object with two properties: - * patch: Array of patch instructions compatible with the Ironic - * node update function - * status: Code indicating whether patch creation was successful - * - */ - NodeUpdatePatch.prototype.getPatch = function() { - return {patch: angular.copy(this.patch), status: this.status}; - }; - return service; } })(); diff --git a/ironic_ui/static/dashboard/admin/ironic/update-patch.service.js b/ironic_ui/static/dashboard/admin/ironic/update-patch.service.js new file mode 100644 index 00000000..d9c0f154 --- /dev/null +++ b/ironic_ui/static/dashboard/admin/ironic/update-patch.service.js @@ -0,0 +1,187 @@ +/* + * Copyright 2016 Cray Inc. + * + * 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.admin.ironic') + .factory('horizon.dashboard.admin.ironic.update-patch.service', + updatePatchService); + + updatePatchService.$inject = [ + '$log' + ]; + + function updatePatchService($log) { + var service = { + UpdatePatch: UpdatePatch + }; + + /* + The pdatePatch class is used to construct a set of patch + instructions that transform a base object into a specified target. + */ + function UpdatePatch() { + this.patch = []; + this.status = UpdatePatch.status.OK; + } + + UpdatePatch.status = { + OK: 0, + ERROR: 1, + UNKNOWN_TYPE: 2 + }; + + /** + * @description Update the status of the patch with a specified code + * + * @param {int} status - latest status code + * @return {void} + */ + UpdatePatch.prototype._updateStatus = function(status) { + this.status = Math.max(this.status, status); + }; + + /** + * @description Check whether an item is a property + * + * @param {object} item - item to be tested + * @return {boolean} True if the item is a number, string, or date + */ + function isProperty(item) { + return item === null || + angular.isNumber(item) || + angular.isString(item) || + angular.isDate(item); + } + + /** + * @description Check whether an item is a collection + * + * @param {object} item - item to be tested + * @return {boolean} True if the item is an array or object + */ + function isCollection(item) { + return angular.isArray(item) || angular.isObject(item); + } + + /** + * @description Add instructions to the patch for processing a + * specified item + * + * @param {object} item - item to be added + * @param {string} path - Path to the item being added + * @param {string} op - add or remove + * @return {void} + */ + UpdatePatch.prototype._processItem = function(item, path, op) { + $log.info("UpdatePatch._processItem: " + path + " " + op); + if (isProperty(item)) { + this.patch.push({op: op, path: path, value: item}); + } else if (isCollection(item)) { + angular.forEach(item, function(partName, part) { + this._processItem(part, path + "/" + partName, op); + }); + } else { + this._updateStatus(UpdatePatch.status.UNKNOWN_TYPE); + $log.error("Unable to process (" + op + ") item (" + path + "). " + + " " + typeof item + " " + JSON.stringify(item)); + } + }; + + /** + * @description Add instructions to the patch for adding a specified item + * + * @param {object} item - item to be added + * @param {string} path - Path to the item being removed + * @return {void} + */ + UpdatePatch.prototype._addItem = function(item, path) { + this._processItem(item, path, "add"); + }; + + /** + * @description Add instructions to the patch for removing a specified item + * + * @param {object} item - item to be removed + * @param {string} path - Path to the item being removed + * @return {void} + */ + UpdatePatch.prototype._removeItem = function(item, path) { + this._processItem(item, path, "remove"); + }; + + /** + * @description Determine the set of operations required to + * transform a source version of an object into a target version, + * and add them to a patch. + * + * @param {object} source - Source object + * @param {object} target - Target object + * @param {string} path - Pathname of the patched object + * @return {void} + */ + UpdatePatch.prototype.buildPatch = function(source, target, path) { + $log.info("UpdatePatch._buildPatch: " + path); + var patcher = this; + + if (isProperty(source) && isProperty(target)) { + if (source !== target) { + patcher.patch.push({op: "replace", path: path, value: target}); + } + } else if (isCollection(source) && isCollection(target)) { + angular.forEach(source, function(sourceItem, sourceItemName) { + if (angular.isDefined(target[sourceItemName])) { + patcher.buildPatch(sourceItem, + target[sourceItemName], + path + '/' + sourceItemName); + } else { + patcher._removeItem(sourceItem, path + '/' + sourceItemName); + } + }); + angular.forEach(target, function(targetItem, targetItemName) { + if (angular.isUndefined(source[targetItemName])) { + patcher._addItem(targetItem, path + '/' + targetItemName); + } + }); + } else if (isProperty(source) && isCollection(target) || + isCollection(source) && isProperty(target)) { + patcher._removeItem(source, path); + patcher._addItem(target, path); + } else { + patcher._updateStatus(UpdatePatch.status.ERROR); + $log.error("Unable to patch " + path + " " + + "source = " + JSON.stringify(source) + ", " + + "target = " + JSON.stringify(target)); + } + }; + + /** + * @description Get the patch + * + * @return {object} An object with two properties: + * patch: Array of patch instructions compatible with the Ironic + * node/port update commands + * status: Code indicating whether patch creation was successful + * + */ + UpdatePatch.prototype.getPatch = function() { + return {patch: angular.copy(this.patch), status: this.status}; + }; + + return service; + } +})();