qenv/ts/qenv.classes.qenv.ts

204 lines
6.2 KiB
TypeScript
Raw Normal View History

import * as plugins from './qenv.plugins';
2019-01-13 21:04:20 +00:00
plugins.smartlog.defaultLogger.enableConsole();
2017-05-12 16:17:22 +00:00
2019-01-12 23:00:32 +00:00
/**
* class Qenv
* allows to make assertions about the environments while being more flexibel in how to meet them
*/
2017-05-12 16:17:22 +00:00
export class Qenv {
2019-01-06 00:30:07 +00:00
public requiredEnvVars: string[] = [];
public availableEnvVars: string[] = [];
public missingEnvVars: string[] = [];
2019-08-06 15:37:07 +00:00
public keyValueObject: { [key: string]: any } = {};
2019-01-06 00:30:07 +00:00
public logger: plugins.smartlog.Smartlog;
// filePaths
public qenvFilePathAbsolute: string;
public envFilePathAbsolute: string;
constructor(
qenvFileBasePathArg = process.cwd(),
envFileBasePathArg,
failOnMissing = true,
loggerArg: plugins.smartlog.Smartlog = plugins.smartlog.defaultLogger
) {
this.logger = loggerArg;
// lets make sure paths are absolute
2019-01-12 23:00:32 +00:00
this.qenvFilePathAbsolute = plugins.path.join(
plugins.path.resolve(qenvFileBasePathArg),
'qenv.yml'
);
this.envFilePathAbsolute = plugins.path.join(
plugins.path.resolve(envFileBasePathArg),
2019-08-06 15:41:45 +00:00
'env.json'
2019-01-12 23:00:32 +00:00
);
2019-01-06 00:30:07 +00:00
this.getRequiredEnvVars();
this.getAvailableEnvVars();
this.missingEnvVars = this.getMissingEnvVars();
2017-05-12 16:17:22 +00:00
// handle missing variables
if (this.missingEnvVars.length > 0) {
console.info('Required Env Vars are:');
console.log(this.requiredEnvVars);
console.error('However some Env variables could not be resolved:');
console.log(this.missingEnvVars);
2017-05-12 16:17:22 +00:00
if (failOnMissing) {
2019-08-29 12:29:16 +00:00
this.logger.log('error', 'Exiting!');
process.exit(1);
2019-08-29 12:19:15 +00:00
} else {
2019-08-29 12:29:16 +00:00
this.logger.log('warn', 'qenv is not set to fail on missing environment variables');
2017-05-12 16:17:22 +00:00
}
}
}
2019-01-12 23:00:32 +00:00
/**
* only gets an environment variable if it is required within a read qenv.yml file
* @param envVarName
*/
public getEnvVarRequired(envVarName): string {
return this.keyValueObject[envVarName];
2017-05-12 16:17:22 +00:00
}
2019-01-06 00:30:07 +00:00
2019-01-12 23:00:32 +00:00
/**
* tries to get any env var even if it is not required
2019-09-13 09:20:47 +00:00
* @param wantedEnvVar
2019-01-12 23:00:32 +00:00
*/
2019-09-13 09:20:47 +00:00
public getEnvVarOnDemand(wantedEnvVar: string): string {
let envVarFromEnvironmentVariable: string;
let envVarFromEnvJsonFile: string;
let envVarFromDockerSecret: string;
2019-01-12 23:00:32 +00:00
let dockerSecretJson: string;
// env var check
2019-09-13 09:20:47 +00:00
if (process.env[wantedEnvVar]) {
this.availableEnvVars.push(wantedEnvVar);
envVarFromEnvironmentVariable = process.env[wantedEnvVar];
2019-01-12 23:00:32 +00:00
}
2019-01-06 00:30:07 +00:00
2019-01-12 23:00:32 +00:00
// env file check
2019-09-13 09:20:47 +00:00
// lets determine the actual env yml
let envJsonFileAsObject;
try {
envJsonFileAsObject = plugins.smartfile.fs.toObjectSync(this.envFilePathAbsolute);
} catch (err) {
envJsonFileAsObject = {};
}
if (envJsonFileAsObject.hasOwnProperty(wantedEnvVar)) {
envVarFromEnvJsonFile = envJsonFileAsObject[wantedEnvVar];
2019-01-12 23:00:32 +00:00
}
2019-01-06 00:30:07 +00:00
2019-01-12 23:00:32 +00:00
// docker secret check
if (
plugins.smartfile.fs.isDirectory('/run') &&
plugins.smartfile.fs.isDirectory('/run/secrets') &&
2019-09-13 09:20:47 +00:00
plugins.smartfile.fs.fileExistsSync(`/run/secrets/${wantedEnvVar}`)
2019-01-12 23:00:32 +00:00
) {
2019-09-13 09:20:47 +00:00
envVarFromDockerSecret = plugins.smartfile.fs.toStringSync(`/run/secrets/${wantedEnvVar}`);
2019-01-12 23:00:32 +00:00
}
2019-01-06 00:30:07 +00:00
2019-01-12 23:00:32 +00:00
// docker secret.json
if (
plugins.smartfile.fs.isDirectory('/run') &&
plugins.smartfile.fs.isDirectory('/run/secrets')
2019-01-12 23:00:32 +00:00
) {
const availableSecrets = plugins.smartfile.fs.listAllItemsSync('/run/secrets');
for (const secret of availableSecrets) {
2019-09-13 09:20:47 +00:00
if (secret.includes('secret.json') && !envVarFromDockerSecret) {
2019-01-14 21:42:24 +00:00
const secretObject = plugins.smartfile.fs.toObjectSync(`/run/secrets/${secret}`);
2019-09-13 09:20:47 +00:00
envVarFromDockerSecret = secretObject[wantedEnvVar];
}
}
2019-01-12 23:00:32 +00:00
}
2019-01-06 00:30:07 +00:00
2019-01-12 23:00:32 +00:00
// warn if there is more than one candidate
2019-09-13 09:20:47 +00:00
const availableCcandidates: any[] = [];
[
envVarFromEnvironmentVariable,
envVarFromEnvJsonFile,
envVarFromDockerSecret,
dockerSecretJson
].forEach(candidate => {
2019-01-12 23:00:32 +00:00
if (candidate) {
2019-09-13 09:20:47 +00:00
availableCcandidates.push(candidate);
2019-01-06 00:30:07 +00:00
}
2019-01-12 23:00:32 +00:00
});
2019-09-13 09:20:47 +00:00
if (availableCcandidates.length > 1) {
2019-01-12 23:00:32 +00:00
this.logger.log(
'warn',
2019-09-13 09:20:47 +00:00
`found multiple candidates for ${wantedEnvVar} Choosing in the order of envVar, envFileVar, dockerSecret, dockerSecretJson`
2019-01-12 23:00:32 +00:00
);
2019-09-13 09:20:47 +00:00
console.log(availableCcandidates);
2019-01-12 23:00:32 +00:00
}
2019-09-13 09:20:47 +00:00
switch (true) {
case !!envVarFromEnvironmentVariable:
this.logger.log('ok', `found ${wantedEnvVar} as environment variable`);
return envVarFromEnvironmentVariable;
case !!envVarFromEnvJsonFile:
this.logger.log('ok', `found ${wantedEnvVar} as env.json variable`);
return envVarFromEnvJsonFile;
case !!envVarFromDockerSecret:
this.logger.log('ok', `found ${wantedEnvVar} as docker secret`);
return envVarFromDockerSecret;
case !!dockerSecretJson:
this.logger.log('ok', `found ${wantedEnvVar} as docker secret.json`);
return dockerSecretJson;
default:
this.logger.log(
'warn',
`could not find the wanted environment variable ${wantedEnvVar} anywhere`
);
return;
2019-01-12 23:00:32 +00:00
}
2019-01-06 00:30:07 +00:00
}
/**
* gets the required env values
*/
private getRequiredEnvVars = () => {
2019-01-12 23:00:32 +00:00
let qenvFile: any = {};
if (plugins.smartfile.fs.fileExistsSync(this.qenvFilePathAbsolute)) {
2019-01-06 02:36:40 +00:00
qenvFile = plugins.smartfile.fs.toObjectSync(this.qenvFilePathAbsolute);
2019-01-06 00:30:07 +00:00
}
2019-01-06 02:36:40 +00:00
if (!qenvFile || !qenvFile.required || !Array.isArray(qenvFile.required)) {
2019-09-13 09:20:47 +00:00
this.logger.log(
'warn',
`qenv (promised environment): ./env.yml File does not contain a 'required' Array!`
);
2019-01-06 02:36:40 +00:00
} else {
for (const keyArg of Object.keys(qenvFile.required)) {
this.requiredEnvVars.push(qenvFile.required[keyArg]);
}
2019-01-06 00:30:07 +00:00
}
2019-09-13 09:20:47 +00:00
};
2019-01-06 00:30:07 +00:00
/**
* gets the available env vars
*/
private getAvailableEnvVars = () => {
for (const requiredEnvVar of this.requiredEnvVars) {
const chosenVar = this.getEnvVarOnDemand(requiredEnvVar);
if (chosenVar) {
this.availableEnvVars.push(requiredEnvVar);
this.keyValueObject[requiredEnvVar] = chosenVar;
2019-01-06 00:30:07 +00:00
}
}
2019-08-06 15:37:07 +00:00
};
2019-01-06 00:30:07 +00:00
/**
* gets missing env vars
*/
private getMissingEnvVars = (): string[] => {
const missingEnvVars: string[] = [];
for (const envVar of this.requiredEnvVars) {
if (!this.availableEnvVars.includes(envVar)) {
missingEnvVars.push(envVar);
}
}
return missingEnvVars;
};
2017-05-12 16:17:22 +00:00
}