Skip to content

Commit

Permalink
feat: enable rendering MTPs to disk, from disk
Browse files Browse the repository at this point in the history
- `bin/renderlocal` can take an `--mtp`, and any number of `--env`s
  (greater than 0) and render resources, writing them to `--out`
- create a `LocalMustacheTemplateController` that resembles the mocked
  one used in tests
  - update tests to use `LocalMustacheTemplateController`
- depends on proposed changes to `razeedeploy-core`
  • Loading branch information
charlesthomas committed Jun 24, 2022
1 parent 94fd798 commit dccfcd7
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 20 deletions.
56 changes: 56 additions & 0 deletions bin/renderlocal
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env node

const nopt = require('nopt');
const path = require('path');

const { FetchEnvs, MockController } = require('@razee/razeedeploy-core');
const IOUtils = require('../src/IOUtils');
const LocalMustacheTemplateController = require('../src/LocalMustacheTemplateController');

const args = nopt(
{
mtp: path,
out: path,
env: [path, Array]
},
{}, process.argv, 2
);

if (args.mtp === undefined) {
console.error("exactly one --mtp is required!");
process.exit(1);
}

if (args.env === undefined || args.env.length < 1) {
console.error("at least one --env is required!");
process.exit(1);
}

async function renderLocal() {
const mtp = await IOUtils.readYamlFile(args.mtp);
const kubeData = await IOUtils.kubeDataFromYamlFiles(...args.env);

const eventData = {
type: 'ADDED',
object: mtp[0]
}

const fetchEnvs = new FetchEnvs(new MockController(eventData, kubeData));
const view = await fetchEnvs.get('spec');

const mtpController = new LocalMustacheTemplateController({eventData: eventData, kubeData: kubeData});
let templates = mtpController.concatTemplates();
await mtpController.processTemplate(templates, view);

if (templates.length > 1) {
throw Error("can only handle one template!");
}

if (args.out === undefined) {
await IOUtils.printYaml(templates[0]);
} else {
await IOUtils.writeYamlFile(templates[0], args.out)
}
};

renderLocal();
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"version": "0.0.0-dev",
"description": "Razee: component to use the Mustache template processor on kubernetes resource configurations.",
"main": "./src/index.js",
"bin": "./bin/mustachetemplate",
"bin": {
"mustachetemplate": "./bin/mustachetemplate",
"renderlocal": "./bin/renderlocal"
},
"keywords": [
"kubernetes",
"razee",
Expand Down Expand Up @@ -45,6 +48,7 @@
"handlebars": "^4.7.7",
"js-yaml": "^4.1.0",
"mustache": "^4.2.0",
"nopt": "^5.0.0",
"object-path": "^0.11.8",
"pino": "^7.11.0"
},
Expand Down
52 changes: 52 additions & 0 deletions src/IOUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const fs = require('fs');
const yaml = require('js-yaml');

async function kubeDataFromYamlFiles(...filePaths) {
let kubeData = {};
for (const filePath of filePaths) {
let data = await readYamlFile(filePath);
for (const element of data) {
const kind = element.kind;
if (!(kind in kubeData)) {
kubeData[kind] = [];
}
kubeData[kind].push(element);
}
}
return kubeData;
}

async function objToYaml(asObj) {
return await yaml.dump(asObj);
}

async function printYaml(asObj) {
process.stdout.write(await objToYaml(asObj));
}

async function readFile(filePath) {
return await fs.promises.readFile(filePath);
}

async function readYamlFile(filePath) {
return await yamlToObj(await readFile(filePath));
}

async function writeFile(contents, filePath) {
fs.writeFile(filePath, contents, (err) => { console.error(err); });
}

async function writeYamlFile(asObj, filePath) {
await writeFile(await objToYaml(asObj), filePath);
}

async function yamlToObj(asYaml) {
return await yaml.loadAll(asYaml);
}

module.exports = {
kubeDataFromYamlFiles,
printYaml,
readYamlFile,
writeYamlFile
};
19 changes: 19 additions & 0 deletions src/LocalMustacheTemplateController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { MockKubeResourceMeta } = require('@razee/razeedeploy-core');
const MustacheTemplateController = require('../src/MustacheTemplateController');

module.exports = class LocalMustacheTemplateController extends MustacheTemplateController {
constructor(params) {
let kubeData = {};
if (params.kubeData !== undefined) {
kubeData = params.kubeData;
delete params.kubeData;
}
params.kubeResourceMeta = new MockKubeResourceMeta(
'deploy.razee.io/v1alpha2', 'MustacheTemplate', kubeData
);
params.logger = {
info: () => {}
};
super(params);
}
};
31 changes: 12 additions & 19 deletions test/mustache-template-tests.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var assert = require('chai').assert;
var Controller = require('../src/MustacheTemplateController');
var Controller = require('../src/LocalMustacheTemplateController');

describe('#processTemplates', async function () {
const eventData = {
Expand All @@ -26,57 +26,50 @@ describe('#processTemplates', async function () {
}
}
};
const noop = () => {};
const kubeResourceMeta = {
uri: noop,
};
const logger = {
info: noop,
};
it('should evaulate a mustache template correctly', async function () {
const controller = new Controller({eventData, kubeResourceMeta, logger});
const controller = new Controller({eventData});
const res = await controller.processTemplate(eventData.object.spec.strTemplates, { CRN_REGION: 'us-east'});
assert.deepEqual(res[0].data, {'us-east': 'true'});
});

it('should evaulate a handlebars template correctly', async function () {
eventData.object.spec['templateEngine'] = 'handlebars';
eventData.object.spec.strTemplates = [
eventData.object.spec.strTemplates = [
'apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: seed-config\ndata:\n {{#if CRN_REGION}}\n "region": {{ CRN_REGION }}\n {{/if}}'
];
const controller = new Controller({eventData, kubeResourceMeta, logger});
const controller = new Controller({eventData});
const res = await controller.processTemplate(eventData.object.spec.strTemplates, { CRN_REGION: 'us-east'});
assert.equal(res[0].data.region, 'us-east');
});

it('should evaulate a handlebars template correctly with an equality register helper', async function () {
eventData.object.spec['templateEngine'] = 'handlebars';
eventData.object.spec.strTemplates = [
eventData.object.spec.strTemplates = [
'apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: seed-config\ndata:\n {{#if (eq CRN_REGION "us-west") }}\n "region": {{ CRN_REGION }}\n {{/if}}'
];
const controller = new Controller({eventData, kubeResourceMeta, logger});
const controller = new Controller({eventData});

const res = await controller.processTemplate(eventData.object.spec.strTemplates, { CRN_REGION: 'us-west'});
assert.equal(res[0].data.region, 'us-west');
});

it('should be able to assign a var in handlebars with the "assign" helper', async function () {
eventData.object.spec['templateEngine'] = 'handlebars';
eventData.object.spec.strTemplates = [
eventData.object.spec.strTemplates = [
'apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: seed-config\ndata:\n {{ assign "GEO" "us-west" }}\n "region": {{ GEO }}'
];
const controller = new Controller({eventData, kubeResourceMeta, logger});
const controller = new Controller({eventData});

const res = await controller.processTemplate(eventData.object.spec.strTemplates, { CRN_REGION: 'us-west'});
assert.equal(res[0].data.region, 'us-west');
});

it('should throw succeed without any view data', async function () {
eventData.object.spec['templateEngine'] = 'handlebars';
eventData.object.spec.strTemplates = [
eventData.object.spec.strTemplates = [
'apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: seed-config\ndata:\n {{ assign "GEO" "us-west" }}\n "region": {{ GEO }}'
];
const controller = new Controller({eventData, kubeResourceMeta, logger});
const controller = new Controller({eventData});
const res = await controller.processTemplate(eventData.object.spec.strTemplates, {});
assert.equal(res[0].data.region, 'us-west');
});
Expand Down

0 comments on commit dccfcd7

Please sign in to comment.