From a09b2395ffd75104b6a708b99aefdee5aee2503b Mon Sep 17 00:00:00 2001 From: Eric Satterwhite Date: Tue, 1 Nov 2022 13:45:53 -0500 Subject: [PATCH] feat(base): allow default reconcile behavior to be configured (#349) Base cnntroller accepts a `reconcileByDefault` option which controls the default value for the reconciler behavior when `deploy.razee.io/Reconcile` is not specified. By default it is true. It must be a boolean looking value. 1, or 0 are not valid --- lib/BaseController.js | 22 ++++- test/basecontroller-tests.js | 165 +++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 test/basecontroller-tests.js diff --git a/lib/BaseController.js b/lib/BaseController.js index 4b85064..6dcf09f 100644 --- a/lib/BaseController.js +++ b/lib/BaseController.js @@ -24,11 +24,26 @@ const clone = require('clone'); const merge = require('deepmerge'); const fs = require('fs-extra'); const hash = require('object-hash'); - +const BOOL_EXPR = /^(true|false)$/; module.exports = class BaseController { constructor(params) { + let reconcileByDefault = 'true'; + const options = params.options || {}; + + if (options.reconcileByDefault != null) { + const valid = BOOL_EXPR.test(options.reconcileByDefault); + if (!valid) { + throw new TypeError( + `BaseController.options.reconcileByDefault must be a boolean value. Got: ${options.reconcileByDefault}` + ); + } + + reconcileByDefault = String(options.reconcileByDefault); + } + + this._finalizerString = params.finalizerString; this._logger = params.logger; @@ -38,6 +53,7 @@ module.exports = class BaseController { this._data = params.eventData; this._name = objectPath.get(this._data, 'object.metadata.name'); this._namespace = objectPath.get(this._data, 'object.metadata.namespace'); + this._reconcileString = objectPath.get(this._data, ['object', 'metadata', 'labels', 'deploy.razee.io/Reconcile'], reconcileByDefault); this._selfLink = this._kubeResourceMeta.uri({ name: this._name, namespace: this._namespace @@ -77,9 +93,7 @@ module.exports = class BaseController { return this._namespace; } get reconcileDefault() { - let result; - result = objectPath.get(this._data, ['object', 'metadata', 'labels', 'deploy.razee.io/Reconcile'], 'true'); - return result; + return this._reconcileString; } // Start processesing the data diff --git a/test/basecontroller-tests.js b/test/basecontroller-tests.js new file mode 100644 index 0000000..61d0f0c --- /dev/null +++ b/test/basecontroller-tests.js @@ -0,0 +1,165 @@ +'use strict'; +/* + * Copyright 2022 IBM Corp. All Rights Reserved. + * + * 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. + */ + +const assert = require('chai').assert; +const BaseController = require('../lib/BaseController'); +const MockKubeResourceMeta = require('../lib/MockKubeResourceMeta'); +const reconcileTrue = { + object: { + apiVersion: 'deploy.razee.io/v1alpha2', + kind: 'MustacheTemplate', + metadata: { + name: 'rd-test', + namespace: 'razeedeploy', + labels: { + 'deploy.razee.io/Reconcile': 'true' + } + }, + spec: { + clusterAuth: { impersonateUser: 'razeedeploy' }, + templateEngine: 'handlebars', + envFrom: [], + env: [], + tempates: [], + strTemplates: [], + } + } +}; + +const reconcileFalse = { + object: { + apiVersion: 'deploy.razee.io/v1alpha2', + kind: 'MustacheTemplate', + metadata: { + name: 'rd-test', + namespace: 'razeedeploy', + labels: { + 'deploy.razee.io/Reconcile': 'false' + } + }, + spec: { + clusterAuth: { impersonateUser: 'razeedeploy' }, + templateEngine: 'handlebars', + envFrom: [], + env: [], + tempates: [], + strTemplates: [], + } + } +}; + +const reconcileDefault = { + object: { + apiVersion: 'deploy.razee.io/v1alpha2', + kind: 'MustacheTemplate', + metadata: { + name: 'rd-test', + namespace: 'razeedeploy', + }, + spec: { + clusterAuth: { impersonateUser: 'razeedeploy' }, + templateEngine: 'handlebars', + envFrom: [], + env: [], + tempates: [], + strTemplates: [], + } + } +}; + +describe('BaseController', function () { + after(function () { + delete require.cache[require.resolve('../lib/BaseController')]; + }); + + describe('.reconcileDefault', function (){ + it('should return true by default', function () { + const controller = new BaseController({ + eventData: reconcileDefault, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + assert.equal(controller.reconcileDefault, 'true'); + }); + + it('should return true when deploy.razee.io/Reconcile=true', function () { + const controller = new BaseController({ + eventData: reconcileTrue, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + assert.equal(controller.reconcileDefault, 'true'); + }); + + it('should return false when deploy.razee.io/Reconcile=false', function () { + const controller = new BaseController({ + eventData: reconcileFalse, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + assert.equal(controller.reconcileDefault, 'false'); + }); + + it('should return true when reconcileByDefault=true', function () { + const controller = new BaseController({ + eventData: reconcileDefault, + options: {reconcileByDefault: true}, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + assert.equal(controller.reconcileDefault, 'true'); + }); + + it('should return false when reconcileByDefault=false', function () { + const controller = new BaseController({ + eventData: reconcileDefault, + options: {reconcileByDefault: false}, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + assert.equal(controller.reconcileDefault, 'false'); + }); + + + it('should return true when deploy.razee.io/Reconcile=true, reconcileByDefault=false', function () { + const controller = new BaseController({ + eventData: reconcileTrue, + options: {reconcileByDefault: 'false'}, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + assert.equal(controller.reconcileDefault, 'true'); + }); + + it('should return true when deploy.razee.io/Reconcile=false, reconcileByDefault=true', function () { + const controller = new BaseController({ + eventData: reconcileFalse, + options: {reconcileByDefault: 'true'}, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + assert.equal(controller.reconcileDefault, 'false'); + }); + + + it('should throw when reconcileByDefault is given a non boolean value', function () { + assert.throws(() => { + return new BaseController({ + eventData: reconcileDefault, + options: {reconcileByDefault: 1}, + kubeResourceMeta: new MockKubeResourceMeta('v1', 'MustacheTemplate', {}) + }); + }, TypeError, /reconcileByDefault must be a boolean value/g); + }); + }); + +}); + +