From e40c9e1f6de73332a6b1be8a0f0d3c2b16ab3137 Mon Sep 17 00:00:00 2001 From: Charles Thomas Date: Thu, 23 Jun 2022 15:49:28 -0400 Subject: [PATCH] feat: add `MockController`, `MockKubeResourceMeta` - these will enable simpler testing here - it should also enable simpler testing of the `mustachetemplate` controller - this is also ground work for a PR to `mustachetemplate` to add a new script it its `bin/` that can render MTPs from files on disk, instead of only k8s resources in a live environment, to enable better testing of MTPs generally --- index.js | 8 +- lib/BaseTemplateController.js | 11 ++- lib/MockController.js | 17 ++++ lib/MockKubeResourceMeta.js | 60 ++++++++++++++ test/fetchEnvs-tests.js | 146 +++++++++------------------------- 5 files changed, 128 insertions(+), 114 deletions(-) create mode 100644 lib/MockController.js create mode 100644 lib/MockKubeResourceMeta.js diff --git a/index.js b/index.js index 0d7c748..bb106e6 100644 --- a/index.js +++ b/index.js @@ -24,10 +24,16 @@ const CompositeController = require('./lib/CompositeController'); const FetchEnvs = require('./lib/FetchEnvs'); +const MockController = require('./lib/MockController'); + +const MockKubeResourceMeta = require('./lib/MockKubeResourceMeta'); + module.exports = { BaseController, BaseDownloadController, BaseTemplateController, CompositeController, - FetchEnvs + FetchEnvs, + MockController, + MockKubeResourceMeta }; diff --git a/lib/BaseTemplateController.js b/lib/BaseTemplateController.js index e30a9a2..3edbb27 100644 --- a/lib/BaseTemplateController.js +++ b/lib/BaseTemplateController.js @@ -25,14 +25,19 @@ module.exports = class BaseTemplateController extends CompositeController { super(params); } - async added() { - let fetchEnvs = new FetchEnvs(this); - let env = await fetchEnvs.get('spec'); + concatTemplates() { let objTemplates = objectPath.get(this.data, ['object', 'spec', 'templates'], []); if (!Array.isArray(objTemplates)) objTemplates = [objTemplates]; let strTemplates = objectPath.get(this.data, ['object', 'spec', 'strTemplates'], []); if (!Array.isArray(strTemplates)) strTemplates = [strTemplates]; let templates = objTemplates.concat(strTemplates); + return templates; + } + + async added() { + let fetchEnvs = new FetchEnvs(this); + let env = await fetchEnvs.get('spec'); + let templates = this.concatTemplates(); templates = await this.processTemplate(templates, env); if (!Array.isArray(templates) || templates.length == 0) { this.updateRazeeLogs('warn', { controller: 'BaseTemplate', message: 'No templates found to apply' }); diff --git a/lib/MockController.js b/lib/MockController.js new file mode 100644 index 0000000..a374eb0 --- /dev/null +++ b/lib/MockController.js @@ -0,0 +1,17 @@ +const MockKubeResourceMeta = require('../lib/MockKubeResourceMeta'); + +module.exports = class MockController { + constructor(eventData, kubeData) { + this.data = eventData; + this.kubeResourceMeta = new MockKubeResourceMeta( + this.data.object.apiVersion, + this.data.object.kind, + kubeData + ); + this.kubeClass = { + getKubeResourceMeta: (apiVersion, kind) => { + return new MockKubeResourceMeta(apiVersion, kind, kubeData); + } + }; + } +}; diff --git a/lib/MockKubeResourceMeta.js b/lib/MockKubeResourceMeta.js new file mode 100644 index 0000000..b99ed2c --- /dev/null +++ b/lib/MockKubeResourceMeta.js @@ -0,0 +1,60 @@ +module.exports = class MockKubeResourceMeta { + constructor(apiVersion, kind, kubeData) { + this._apiVersion = ((apiVersion === undefined || apiVersion === '') ? 'deploy.razee.io/v1alpha2' : apiVersion); + this._kind = ((kind === undefined || kind === '') ? 'MustacheTemplate' : kind); + this.kubeData = kubeData; + } + + async request(reqOpt) { + const ref = { + apiVersion: reqOpt.uri.apiVersion, + kind: reqOpt.uri.kind, + name: reqOpt.uri.name, + namespace: reqOpt.uri.namespace, + labelSelector: reqOpt?.qs?.labelSelector + }; + + const res = await this.kubeGetResource(ref); + return res; + } + + async get(name, namespace) { + const ref = this.uri({ name, namespace }); + return await this.kubeGetResource(ref); + } + + uri(options) { + return { ...options, apiVersion: this._apiVersion, kind: this._kind, }; + } + + async kubeGetResource(ref) { + const { + name, + labelSelector, + namespace, + kind, + apiVersion + } = ref; + if (!this.kubeData[kind]) { + return; + } + + let fn = labelSelector ? 'filter' : 'find'; + let lookup = this.kubeData[kind][fn](obj => { + let match = true; + match = (obj.apiVersion === apiVersion && match) ? true : false; + match = (obj.kind === kind && match) ? true : false; + match = ((obj.metadata.name === name || labelSelector !== undefined) && match) ? true : false; + match = (obj.metadata.namespace === namespace && match) ? true : false; + if (labelSelector) { + const objLabels = obj.metadata.labels ?? {}; + labelSelector.split(',').forEach(label => { + let [key, value] = label.split('='); + match = (objLabels[key] === value && match) ? true : false; + }); + } + return match; + }); + return labelSelector ? { items: lookup } : lookup; + } +}; diff --git a/test/fetchEnvs-tests.js b/test/fetchEnvs-tests.js index d6f7880..aec9c0c 100644 --- a/test/fetchEnvs-tests.js +++ b/test/fetchEnvs-tests.js @@ -17,124 +17,50 @@ const assert = require('chai').assert; const FetchEnvs = require('../lib/FetchEnvs'); const fs = require('fs-extra'); - - -const krm = { - _apiVersion: 'deploy.razee.io/v1alpha2', - _kind: 'MustacheTemplate', - async request(reqOpt) { - const ref = { - apiVersion: reqOpt.uri.apiVersion, - kind: reqOpt.uri.kind, - name: reqOpt.uri.name, - namespace: reqOpt.uri.namespace, - labelSelector: reqOpt?.qs?.labelSelector - }; - - const res = await kubeGetResource(ref); - return res; - }, - async get(name, namespace) { - const ref = this.uri({ name, namespace }); - - return await kubeGetResource(ref); - }, - uri(options) { - return { ...options, apiVersion: this._apiVersion, kind: this._kind, }; +const MockController = require('../lib/MockController'); + +const envData = fs.readJsonSync(`${__dirname}/fetchEnvs-test-scenarios/sampleData.json`); + +const controllerData = { + type: 'ADDED', + object: { + apiVersion: 'deploy.razee.io/v1alpha2', + kind: 'MustacheTemplate', + metadata: { + name: 'rd-test', + namespace: 'razeedeploy', + }, + spec: { + clusterAuth: { impersonateUser: 'razeedeploy' }, + templateEngine: 'handlebars', + envFrom: [], + env: [], + tempates: [], + strTemplates: [], + } } }; -const controllerObject = { - data: { - type: 'ADDED', - object: { - apiVersion: 'deploy.razee.io/v1alpha2', - kind: 'MustacheTemplate', - metadata: { - name: 'rd-test', - namespace: 'razeedeploy', - }, - spec: { - clusterAuth: { impersonateUser: 'razeedeploy' }, - templateEngine: 'handlebars', +const altPathControllerData = { + type: 'ADDED', + object: { + apiVersion: 'deploy.razee.io/v1alpha2', + kind: 'FeatureFlagSetLD', + metadata: { + name: 'rd-test', + namespace: 'razeedeploy', + }, + spec: { + identityRef: { envFrom: [], - env: [], - tempates: [], - strTemplates: [], - } - } - }, - kubeResourceMeta: krm, - kubeClass: { - getKubeResourceMeta: (apiVersion, kind) => { - const newKRM = { ...krm }; - newKRM._apiVersion = apiVersion; - newKRM._kind = kind; - return newKRM; - } - }, -}; - -const altPathControllerObject = { - data: { - type: 'ADDED', - object: { - apiVersion: 'deploy.razee.io/v1alpha2', - kind: 'FeatureFlagSetLD', - metadata: { - name: 'rd-test', - namespace: 'razeedeploy', - }, - spec: { - identityRef: { - envFrom: [], - env: [] - } + env: [] } } - }, - kubeResourceMeta: krm, - kubeClass: { - getKubeResourceMeta: (apiVersion, kind) => { - const newKRM = { ...krm }; - newKRM._apiVersion = apiVersion; - newKRM._kind = kind; - return newKRM; - } - }, -}; - -async function kubeGetResource(ref) { - const kubeData = await fs.readJSON(`${__dirname}/fetchEnvs-test-scenarios/sampleData.json`); - const { - name, - labelSelector, - namespace, - kind, - apiVersion - } = ref; - if (!kubeData[kind]) { - return; } +}; - let fn = labelSelector ? 'filter' : 'find'; - let lookup = kubeData[kind][fn](obj => { - let match = true; - match = (obj.apiVersion === apiVersion && match) ? true : false; - match = (obj.kind === kind && match) ? true : false; - match = ((obj.metadata.name === name || labelSelector !== undefined) && match) ? true : false; - match = (obj.metadata.namespace === namespace && match) ? true : false; - if (labelSelector) { - const objLabels = obj.metadata.labels ?? {}; - labelSelector.split(',').forEach(label => { - let [key, value] = label.split('='); - match = (objLabels[key] === value && match) ? true : false; - }); - } - return match; - }); - return labelSelector ? { items: lookup } : lookup; -} +const controllerObject = new MockController(controllerData, envData); +const altPathControllerObject = new MockController(altPathControllerData, envData); describe('fetchEnvs', function () { afterEach(function () {