Skip to content

Commit

Permalink
chore: move environment code (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
fuxingloh authored Apr 20, 2024
1 parent ba59fdb commit 824061a
Show file tree
Hide file tree
Showing 13 changed files with 433 additions and 224 deletions.
1 change: 1 addition & 0 deletions .idea/dictionaries/fuxing.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
"name": "Bitcoin Regtest",
"environment": {
"RPC_USER": {
"type": "RandomBytes",
"length": 16,
"encoding": "hex"
"type": "Value",
"value": "karfia"
},
"RPC_PASSWORD": {
"type": "RandomBytes",
"length": 16,
"encoding": "hex"
"type": "Value",
"value": "karfia"
}
},
"containers": {
Expand Down
7 changes: 1 addition & 6 deletions packages/karfia-agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
"build:docker": "docker buildx build --progress=plain -t ghcr.io/fuxingloh/karfia-agent:$(node -p \"require('./package.json').version\") -f Dockerfile ../../",
"clean": "tsc --build --clean",
"lint": "eslint .",
"push:docker": "docker buildx build --progress=plain -t ghcr.io/fuxingloh/karfia-agent:$(node -p \"require('./package.json').version\") -f Dockerfile ../../ --output type=registry --platform linux/amd64,linux/arm64",
"test": "jest --passWithNoTests"
"push:docker": "docker buildx build --progress=plain -t ghcr.io/fuxingloh/karfia-agent:$(node -p \"require('./package.json').version\") -f Dockerfile ../../ --output type=registry --platform linux/amd64,linux/arm64"
},
"lint-staged": {
"*": [
Expand All @@ -23,9 +22,6 @@
"prettier --write"
]
},
"jest": {
"preset": "@workspace/jest-preset"
},
"dependencies": {
"@trpc/server": "^10.45.2",
"ajv": "^8.12.0",
Expand All @@ -35,7 +31,6 @@
"zod": "^3.22.5"
},
"devDependencies": {
"@workspace/jest-preset": "workspace:*",
"@workspace/tsconfig": "workspace:*"
}
}
98 changes: 98 additions & 0 deletions packages/karfia-definition/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { randomBytes } from 'node:crypto';

import { Environment } from './index';

// Dotenv Expansion Implementation
//
// Copyright (c) 2016, Scott Motte
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
const dotenv = {
INTERPOLATE_SUBSTITUTION_REGEX:
/(\\)?(\$)(?!\()(\{?)([\w.]+)(?::?-((?:\$\{(?:\$\{(?:\$\{[^}]*\}|[^}])*}|[^}])*}|[^}])+))?(\}?)/gi,
resolveEscapeSequences: (value: string): string => {
return value.replace(/\\\$/g, '$');
},
interpolate: (value: string, parsed: Record<string, string>): string => {
return value.replace(
dotenv.INTERPOLATE_SUBSTITUTION_REGEX,
(match, escaped, dollarSign, openBrace, key, defaultValue) => {
if (escaped === '\\') return match.slice(1);

if (parsed[key]) {
// avoid recursion from EXPAND_SELF=$EXPAND_SELF
if (parsed[key] === value) {
return parsed[key];
} else {
return dotenv.interpolate(parsed[key], parsed);
}
}

if (defaultValue) {
if (defaultValue.startsWith('$')) {
return dotenv.interpolate(defaultValue, parsed);
} else {
return defaultValue;
}
}

return '';
},
);
},
expand: (env: Record<string, string>): Record<string, string> => {
const copied = { ...env };

for (const key in copied) {
const value = dotenv.interpolate(copied[key], copied);
copied[key] = dotenv.resolveEscapeSequences(value);
}

return copied;
},
};

export function synthEnv(environment: Environment): Record<string, string> {
return dotenv.expand(
Object.entries(environment).reduce(
(env, [key, factory]) => {
if (factory.type === 'RandomBytes') {
env[key] = randomBytes(factory.length).toString(factory.encoding);
return env;
}
if (factory.type === 'Value') {
env[key] = factory.value;
return env;
}

// if (factory.type === 'Injection') {
// TODO: Prompt if CLI, inject if constructs.
// To allow for simple configuration, e.g. Masternode Keys.

// @ts-expect-error so that we error out if we forget to handle a new factory type
throw new Error(`Unsupported Environment Factory: ${factory.type}`);
},
{} as Record<string, string>,
),
);
}
34 changes: 34 additions & 0 deletions packages/karfia-definition/environment.unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { expect, it } from '@jest/globals';

import { Environment } from '.';
import { synthEnv } from './environment';

it('should expand environment', async () => {
const environment: Environment = {
USER: {
type: 'RandomBytes',
length: 8,
encoding: 'hex',
},
PASS: {
type: 'RandomBytes',
length: 16,
encoding: 'hex',
},
URL: {
type: 'Value',
value: `http://$USER:$PASS@localhost:3000000`,
},
DEBUG: {
type: 'Value',
value: 'karfia:*',
},
};

expect(synthEnv(environment)).toStrictEqual({
USER: expect.stringMatching(/[0-9a-f]{16}/),
PASS: expect.stringMatching(/[0-9a-f]{32}/),
URL: expect.stringMatching(/http:\/\/[0-9a-f]{16}:[0-9a-f]{32}@localhost:3000000/),
DEBUG: 'karfia:*',
});
});
2 changes: 1 addition & 1 deletion packages/karfia-definition/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@
]
},
"body": {
"$ref": "http://json-schema.org/draft-07/schema"
"$ref": "http://json-schema.org/draft-07/schema#"
}
},
"required": ["status"]
Expand Down
14 changes: 11 additions & 3 deletions packages/karfia-definition/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@
"index.d.ts",
"schema.js",
"schema.d.ts",
"schema.d.ts.map"
"schema.d.ts.map",
"environment.js",
"environment.d.ts",
"environment.d.ts.map"
],
"scripts": {
"build": "json2ts index.json > index.d.ts && tsc --project tsconfig.build.json",
"clean": "rm -f index.d.ts && tsc --build --clean",
"lint": "eslint ."
"lint": "eslint .",
"test": "jest"
},
"lint-staged": {
"*": [
Expand All @@ -30,12 +34,16 @@
"prettier --write"
]
},
"jest": {
"preset": "@workspace/jest-preset"
},
"dependencies": {
"ajv": "^8.12.0",
"ajv-formats": "^3.0.1"
},
"devDependencies": {
"@workspace/jest-preset": "workspace:*",
"@workspace/tsconfig": "workspace:*",
"json-schema-to-typescript": "^13.1.2"
"json-schema-to-typescript": "^14.0.0"
}
}
66 changes: 0 additions & 66 deletions packages/karfia-docker-compose/environment.ts

This file was deleted.

29 changes: 4 additions & 25 deletions packages/karfia-docker-compose/synthesizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { randomBytes } from 'node:crypto';

import yaml from 'js-yaml';
import { Container, KarfiaDefinition } from 'karfia-definition';
import { synthEnv } from 'karfia-definition/environment';
import { validate } from 'karfia-definition/schema';

import { expand } from './environment';
import { version } from './package.json';

/**
Expand All @@ -23,31 +23,10 @@ export class Synthesizer {
}

public synthEnv(): string {
const env = expand({
return Object.entries({
...synthEnv(this.definition.environment ?? {}),
KARFIA_DEPLOYMENT_ID: this.deploymentId,
...Object.entries(this.definition.environment ?? {}).reduce(
(env, [key, factory]) => {
if (factory.type === 'RandomBytes') {
env[key] = randomBytes(factory.length).toString(factory.encoding);
return env;
}
if (factory.type === 'Value') {
env[key] = factory.value;
return env;
}

// if (factory.type === 'Injection') {
// TODO: Prompt if CLI, inject if constructs.
// To allow for simple configuration, e.g. Masternode Keys.

// @ts-expect-error so that we error if we forget to handle a new factory type
throw new Error(`Unsupported Environment Factory: ${factory.type}`);
},
{} as Record<string, string>,
),
});

return Object.entries(env ?? {})
})
.map(([key, value]) => `${key}=${value}`)
.join('\n');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/karfia-docker-compose/synthesizer.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ it('should synthesize with valid definition', async () => {
const synthesizer = new Synthesizer(definition);
expect(synthesizer.synthCompose()).toMatchSnapshot();
expect(synthesizer.synthEnv().split('\n')).toStrictEqual([
expect.stringMatching(/^KARFIA_DEPLOYMENT_ID=[0-9a-f]{16}$/),
expect.stringMatching(/^RPC_USER=[0-9a-f]{32}$/),
expect.stringMatching(/^RPC_PASSWORD=[0-9a-f]{32}$/),
expect.stringMatching(/^URL=http:\/\/[0-9a-f]{32}:[0-9a-f]{32}@ganache:8554$/),
expect.stringMatching(/^KARFIA_DEPLOYMENT_ID=[0-9a-f]{16}$/),
]);
});

Expand Down
4 changes: 4 additions & 0 deletions packages/karfia-testcontainers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export class KarfiaTestcontainers {
return this.deploymentId;
}

getEnvironment(): Record<string, string> {
return this.environment;
}

getContainer(name: string): KarfiaContainer {
const containerDef = this.definition.containers[name];
if (containerDef === undefined) {
Expand Down
Loading

0 comments on commit 824061a

Please sign in to comment.