@push.rocks/qenv 5.0.4 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/qenv.classes.qenv.d.ts +14 -27
- package/dist_ts/qenv.classes.qenv.js +86 -125
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/qenv.classes.qenv.ts +101 -152
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/qenv',
|
|
6
|
-
version: '
|
|
6
|
+
version: '6.0.0',
|
|
7
7
|
description: 'easy promised environments'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDRCQUE0QjtDQUMxQyxDQUFBIn0=
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import * as plugins from './qenv.plugins.js';
|
|
2
|
-
/**
|
|
3
|
-
* class Qenv
|
|
4
|
-
* allows to make assertions about the environments while being more flexibel in how to meet them
|
|
5
|
-
*/
|
|
6
2
|
export declare class Qenv {
|
|
7
3
|
requiredEnvVars: string[];
|
|
8
4
|
availableEnvVars: string[];
|
|
@@ -13,27 +9,18 @@ export declare class Qenv {
|
|
|
13
9
|
logger: plugins.smartlog.ConsoleLog;
|
|
14
10
|
qenvFilePathAbsolute: string;
|
|
15
11
|
envFilePathAbsolute: string;
|
|
16
|
-
constructor(qenvFileBasePathArg: string, envFileBasePathArg:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
private getRequiredEnvVars;
|
|
31
|
-
/**
|
|
32
|
-
* gets the available env vars
|
|
33
|
-
*/
|
|
34
|
-
private getAvailableEnvVars;
|
|
35
|
-
/**
|
|
36
|
-
* gets missing env vars
|
|
37
|
-
*/
|
|
38
|
-
private getMissingEnvVars;
|
|
12
|
+
constructor(qenvFileBasePathArg: string, envFileBasePathArg: string, failOnMissing?: boolean);
|
|
13
|
+
private initializeFilePaths;
|
|
14
|
+
private loadRequiredEnvVars;
|
|
15
|
+
private loadAvailableEnvVars;
|
|
16
|
+
private checkForMissingEnvVars;
|
|
17
|
+
getEnvVarOnDemand(envVarName: string): Promise<string | undefined>;
|
|
18
|
+
getEnvVarOnDemandSync(envVarName: string): Promise<string | undefined>;
|
|
19
|
+
getEnvVarOnDemandAsObject(envVarName: string): Promise<any>;
|
|
20
|
+
private getFromEnvironmentVariable;
|
|
21
|
+
private getFromEnvJsonFile;
|
|
22
|
+
private getFromDockerSecret;
|
|
23
|
+
private getFromDockerSecretJson;
|
|
24
|
+
private encodeBase64;
|
|
25
|
+
private decodeBase64;
|
|
39
26
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import * as plugins from './qenv.plugins.js';
|
|
2
|
-
/**
|
|
3
|
-
* class Qenv
|
|
4
|
-
* allows to make assertions about the environments while being more flexibel in how to meet them
|
|
5
|
-
*/
|
|
6
2
|
export class Qenv {
|
|
7
3
|
constructor(qenvFileBasePathArg = process.cwd(), envFileBasePathArg, failOnMissing = true) {
|
|
8
4
|
this.requiredEnvVars = [];
|
|
@@ -10,61 +6,42 @@ export class Qenv {
|
|
|
10
6
|
this.missingEnvVars = [];
|
|
11
7
|
this.keyValueObject = {};
|
|
12
8
|
this.logger = new plugins.smartlog.ConsoleLog();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
this.initializeFilePaths(qenvFileBasePathArg, envFileBasePathArg);
|
|
10
|
+
this.loadRequiredEnvVars();
|
|
11
|
+
this.loadAvailableEnvVars();
|
|
12
|
+
this.checkForMissingEnvVars(failOnMissing);
|
|
13
|
+
}
|
|
14
|
+
initializeFilePaths(qenvFileBasePathArg, envFileBasePathArg) {
|
|
15
|
+
this.qenvFilePathAbsolute = plugins.path.join(plugins.path.resolve(qenvFileBasePathArg), 'qenv.yml');
|
|
16
|
+
this.envFilePathAbsolute = plugins.path.join(plugins.path.resolve(envFileBasePathArg), 'env.json');
|
|
17
|
+
}
|
|
18
|
+
loadRequiredEnvVars() {
|
|
19
|
+
if (plugins.smartfile.fs.fileExistsSync(this.qenvFilePathAbsolute)) {
|
|
20
|
+
const qenvFile = plugins.smartfile.fs.toObjectSync(this.qenvFilePathAbsolute);
|
|
21
|
+
if (qenvFile?.required && Array.isArray(qenvFile.required)) {
|
|
22
|
+
this.requiredEnvVars.push(...qenvFile.required);
|
|
23
23
|
}
|
|
24
24
|
else {
|
|
25
|
-
|
|
26
|
-
this.requiredEnvVars.push(qenvFile.required[keyArg]);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
/**
|
|
31
|
-
* gets the available env vars
|
|
32
|
-
*/
|
|
33
|
-
this.getAvailableEnvVars = () => {
|
|
34
|
-
for (const requiredEnvVar of this.requiredEnvVars) {
|
|
35
|
-
const chosenVar = this.getEnvVarOnDemand(requiredEnvVar);
|
|
36
|
-
if (chosenVar) {
|
|
37
|
-
this.availableEnvVars.push(requiredEnvVar);
|
|
38
|
-
this.keyValueObject[requiredEnvVar] = chosenVar;
|
|
39
|
-
}
|
|
25
|
+
this.logger.log('warn', 'qenv.yml does not contain a "required" Array!');
|
|
40
26
|
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
missingEnvVars.push(envVar);
|
|
50
|
-
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
loadAvailableEnvVars() {
|
|
30
|
+
for (const envVar of this.requiredEnvVars) {
|
|
31
|
+
const value = this.getEnvVarOnDemand(envVar);
|
|
32
|
+
if (value) {
|
|
33
|
+
this.availableEnvVars.push(envVar);
|
|
34
|
+
this.keyValueObject[envVar] = value;
|
|
51
35
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.
|
|
56
|
-
this.envFilePathAbsolute = plugins.path.join(plugins.path.resolve(envFileBasePathArg), 'env.json');
|
|
57
|
-
this.getRequiredEnvVars();
|
|
58
|
-
this.getAvailableEnvVars();
|
|
59
|
-
this.missingEnvVars = this.getMissingEnvVars();
|
|
60
|
-
// handle missing variables
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
checkForMissingEnvVars(failOnMissing) {
|
|
39
|
+
this.missingEnvVars = this.requiredEnvVars.filter((envVar) => !this.availableEnvVars.includes(envVar));
|
|
61
40
|
if (this.missingEnvVars.length > 0) {
|
|
62
|
-
console.info('Required Env Vars are:');
|
|
63
|
-
console.
|
|
64
|
-
console.error('However some Env variables could not be resolved:');
|
|
65
|
-
console.log(this.missingEnvVars);
|
|
41
|
+
console.info('Required Env Vars are:', this.requiredEnvVars);
|
|
42
|
+
console.error('Missing Env Vars:', this.missingEnvVars);
|
|
66
43
|
if (failOnMissing) {
|
|
67
|
-
this.logger.log('error', 'Exiting!');
|
|
44
|
+
this.logger.log('error', 'Exiting due to missing env vars!');
|
|
68
45
|
process.exit(1);
|
|
69
46
|
}
|
|
70
47
|
else {
|
|
@@ -72,89 +49,73 @@ export class Qenv {
|
|
|
72
49
|
}
|
|
73
50
|
}
|
|
74
51
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
52
|
+
async getEnvVarOnDemand(envVarName) {
|
|
53
|
+
return (this.getFromEnvironmentVariable(envVarName) ||
|
|
54
|
+
this.getFromEnvJsonFile(envVarName) ||
|
|
55
|
+
this.getFromDockerSecret(envVarName) ||
|
|
56
|
+
this.getFromDockerSecretJson(envVarName));
|
|
57
|
+
}
|
|
58
|
+
async getEnvVarOnDemandSync(envVarName) {
|
|
59
|
+
console.warn('requesting env var sync leaves out potentially important async env sources.');
|
|
60
|
+
return (this.getFromEnvironmentVariable(envVarName) ||
|
|
61
|
+
this.getFromEnvJsonFile(envVarName) ||
|
|
62
|
+
this.getFromDockerSecret(envVarName) ||
|
|
63
|
+
this.getFromDockerSecretJson(envVarName));
|
|
81
64
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
let envVarFromEnvironmentVariable;
|
|
88
|
-
let envVarFromEnvJsonFile;
|
|
89
|
-
let envVarFromDockerSecret;
|
|
90
|
-
let dockerSecretJson;
|
|
91
|
-
// env var check
|
|
92
|
-
if (process.env[wantedEnvVar]) {
|
|
93
|
-
this.availableEnvVars.push(wantedEnvVar);
|
|
94
|
-
envVarFromEnvironmentVariable = process.env[wantedEnvVar];
|
|
65
|
+
async getEnvVarOnDemandAsObject(envVarName) {
|
|
66
|
+
const rawValue = await this.getEnvVarOnDemand(envVarName);
|
|
67
|
+
if (rawValue && rawValue.startsWith('base64Object:')) {
|
|
68
|
+
const base64Part = rawValue.split('base64Object:')[1];
|
|
69
|
+
return this.decodeBase64(base64Part);
|
|
95
70
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
71
|
+
return rawValue;
|
|
72
|
+
}
|
|
73
|
+
getFromEnvironmentVariable(envVarName) {
|
|
74
|
+
return process.env[envVarName];
|
|
75
|
+
}
|
|
76
|
+
getFromEnvJsonFile(envVarName) {
|
|
99
77
|
try {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
78
|
+
const envJson = plugins.smartfile.fs.toObjectSync(this.envFilePathAbsolute);
|
|
79
|
+
const value = envJson[envVarName];
|
|
80
|
+
if (typeof value === 'object') {
|
|
81
|
+
return 'base64Object:' + this.encodeBase64(value);
|
|
82
|
+
}
|
|
83
|
+
return value;
|
|
104
84
|
}
|
|
105
|
-
|
|
106
|
-
|
|
85
|
+
catch (error) {
|
|
86
|
+
return undefined;
|
|
107
87
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
88
|
+
}
|
|
89
|
+
getFromDockerSecret(envVarName) {
|
|
90
|
+
const secretPath = `/run/secrets/${envVarName}`;
|
|
91
|
+
if (plugins.smartfile.fs.fileExistsSync(secretPath)) {
|
|
92
|
+
return plugins.smartfile.fs.toStringSync(secretPath);
|
|
113
93
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
getFromDockerSecretJson(envVarName) {
|
|
97
|
+
if (plugins.smartfile.fs.isDirectory('/run/secrets')) {
|
|
117
98
|
const availableSecrets = plugins.smartfile.fs.listAllItemsSync('/run/secrets');
|
|
118
99
|
for (const secret of availableSecrets) {
|
|
119
|
-
if (secret.includes('secret.json')
|
|
100
|
+
if (secret.includes('secret.json')) {
|
|
120
101
|
const secretObject = plugins.smartfile.fs.toObjectSync(`/run/secrets/${secret}`);
|
|
121
|
-
|
|
102
|
+
const value = secretObject[envVarName];
|
|
103
|
+
if (typeof value === 'object') {
|
|
104
|
+
return 'base64Object:' + this.encodeBase64(value);
|
|
105
|
+
}
|
|
106
|
+
return value;
|
|
122
107
|
}
|
|
123
108
|
}
|
|
124
109
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
availableCcandidates.push(candidate);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
if (availableCcandidates.length > 1) {
|
|
138
|
-
this.logger.log('warn', `found multiple candidates for ${wantedEnvVar} Choosing in the order of envVar, envFileVar, dockerSecret, dockerSecretJson`);
|
|
139
|
-
console.log(availableCcandidates);
|
|
140
|
-
}
|
|
141
|
-
switch (true) {
|
|
142
|
-
case !!envVarFromEnvironmentVariable:
|
|
143
|
-
this.logger.log('ok', `found ${wantedEnvVar} as environment variable`);
|
|
144
|
-
return envVarFromEnvironmentVariable;
|
|
145
|
-
case !!envVarFromEnvJsonFile:
|
|
146
|
-
this.logger.log('ok', `found ${wantedEnvVar} as env.json variable`);
|
|
147
|
-
return envVarFromEnvJsonFile;
|
|
148
|
-
case !!envVarFromDockerSecret:
|
|
149
|
-
this.logger.log('ok', `found ${wantedEnvVar} as docker secret`);
|
|
150
|
-
return envVarFromDockerSecret;
|
|
151
|
-
case !!dockerSecretJson:
|
|
152
|
-
this.logger.log('ok', `found ${wantedEnvVar} as docker secret.json`);
|
|
153
|
-
return dockerSecretJson;
|
|
154
|
-
default:
|
|
155
|
-
this.logger.log('warn', `could not find the wanted environment variable ${wantedEnvVar} anywhere`);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
encodeBase64(data) {
|
|
113
|
+
const jsonString = JSON.stringify(data);
|
|
114
|
+
return Buffer.from(jsonString).toString('base64');
|
|
115
|
+
}
|
|
116
|
+
decodeBase64(encodedString) {
|
|
117
|
+
const decodedString = Buffer.from(encodedString, 'base64').toString('utf-8');
|
|
118
|
+
return JSON.parse(decodedString);
|
|
158
119
|
}
|
|
159
120
|
}
|
|
160
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
121
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicWVudi5jbGFzc2VzLnFlbnYuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9xZW52LmNsYXNzZXMucWVudi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLG1CQUFtQixDQUFDO0FBRTdDLE1BQU0sT0FBTyxJQUFJO0lBVWYsWUFDRSxzQkFBOEIsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUMzQyxrQkFBMEIsRUFDMUIsZ0JBQXlCLElBQUk7UUFaeEIsb0JBQWUsR0FBYSxFQUFFLENBQUM7UUFDL0IscUJBQWdCLEdBQWEsRUFBRSxDQUFDO1FBQ2hDLG1CQUFjLEdBQWEsRUFBRSxDQUFDO1FBQzlCLG1CQUFjLEdBQTJCLEVBQUUsQ0FBQztRQUM1QyxXQUFNLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBVWhELElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxtQkFBbUIsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRU8sbUJBQW1CLENBQUMsbUJBQTJCLEVBQUUsa0JBQTBCO1FBQ2pGLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3JHLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3JHLENBQUM7SUFFTyxtQkFBbUI7UUFDekIsSUFB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
|
package/package.json
CHANGED
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/qenv.classes.qenv.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import * as plugins from './qenv.plugins.js';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* class Qenv
|
|
5
|
-
* allows to make assertions about the environments while being more flexibel in how to meet them
|
|
6
|
-
*/
|
|
7
3
|
export class Qenv {
|
|
8
4
|
public requiredEnvVars: string[] = [];
|
|
9
5
|
public availableEnvVars: string[] = [];
|
|
@@ -11,34 +7,54 @@ export class Qenv {
|
|
|
11
7
|
public keyValueObject: { [key: string]: any } = {};
|
|
12
8
|
public logger = new plugins.smartlog.ConsoleLog();
|
|
13
9
|
|
|
14
|
-
// filePaths
|
|
15
10
|
public qenvFilePathAbsolute: string;
|
|
16
11
|
public envFilePathAbsolute: string;
|
|
17
12
|
|
|
18
|
-
constructor(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
constructor(
|
|
14
|
+
qenvFileBasePathArg: string = process.cwd(),
|
|
15
|
+
envFileBasePathArg: string,
|
|
16
|
+
failOnMissing: boolean = true
|
|
17
|
+
) {
|
|
18
|
+
this.initializeFilePaths(qenvFileBasePathArg, envFileBasePathArg);
|
|
19
|
+
this.loadRequiredEnvVars();
|
|
20
|
+
this.loadAvailableEnvVars();
|
|
21
|
+
this.checkForMissingEnvVars(failOnMissing);
|
|
22
|
+
}
|
|
28
23
|
|
|
29
|
-
|
|
30
|
-
this.
|
|
24
|
+
private initializeFilePaths(qenvFileBasePathArg: string, envFileBasePathArg: string) {
|
|
25
|
+
this.qenvFilePathAbsolute = plugins.path.join(plugins.path.resolve(qenvFileBasePathArg), 'qenv.yml');
|
|
26
|
+
this.envFilePathAbsolute = plugins.path.join(plugins.path.resolve(envFileBasePathArg), 'env.json');
|
|
27
|
+
}
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
private loadRequiredEnvVars() {
|
|
30
|
+
if (plugins.smartfile.fs.fileExistsSync(this.qenvFilePathAbsolute)) {
|
|
31
|
+
const qenvFile = plugins.smartfile.fs.toObjectSync(this.qenvFilePathAbsolute);
|
|
32
|
+
if (qenvFile?.required && Array.isArray(qenvFile.required)) {
|
|
33
|
+
this.requiredEnvVars.push(...qenvFile.required);
|
|
34
|
+
} else {
|
|
35
|
+
this.logger.log('warn', 'qenv.yml does not contain a "required" Array!');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private loadAvailableEnvVars() {
|
|
41
|
+
for (const envVar of this.requiredEnvVars) {
|
|
42
|
+
const value = this.getEnvVarOnDemand(envVar);
|
|
43
|
+
if (value) {
|
|
44
|
+
this.availableEnvVars.push(envVar);
|
|
45
|
+
this.keyValueObject[envVar] = value;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private checkForMissingEnvVars(failOnMissing: boolean) {
|
|
51
|
+
this.missingEnvVars = this.requiredEnvVars.filter((envVar) => !this.availableEnvVars.includes(envVar));
|
|
33
52
|
|
|
34
|
-
// handle missing variables
|
|
35
53
|
if (this.missingEnvVars.length > 0) {
|
|
36
|
-
console.info('Required Env Vars are:');
|
|
37
|
-
console.
|
|
38
|
-
console.error('However some Env variables could not be resolved:');
|
|
39
|
-
console.log(this.missingEnvVars);
|
|
54
|
+
console.info('Required Env Vars are:', this.requiredEnvVars);
|
|
55
|
+
console.error('Missing Env Vars:', this.missingEnvVars);
|
|
40
56
|
if (failOnMissing) {
|
|
41
|
-
this.logger.log('error', 'Exiting!');
|
|
57
|
+
this.logger.log('error', 'Exiting due to missing env vars!');
|
|
42
58
|
process.exit(1);
|
|
43
59
|
} else {
|
|
44
60
|
this.logger.log('warn', 'qenv is not set to fail on missing environment variables');
|
|
@@ -46,150 +62,83 @@ export class Qenv {
|
|
|
46
62
|
}
|
|
47
63
|
}
|
|
48
64
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
public async getEnvVarOnDemand(envVarName: string): Promise<string | undefined> {
|
|
66
|
+
return (
|
|
67
|
+
this.getFromEnvironmentVariable(envVarName) ||
|
|
68
|
+
this.getFromEnvJsonFile(envVarName) ||
|
|
69
|
+
this.getFromDockerSecret(envVarName) ||
|
|
70
|
+
this.getFromDockerSecretJson(envVarName)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public async getEnvVarOnDemandSync(envVarName: string): Promise<string | undefined> {
|
|
75
|
+
console.warn('requesting env var sync leaves out potentially important async env sources.');
|
|
76
|
+
return (
|
|
77
|
+
this.getFromEnvironmentVariable(envVarName) ||
|
|
78
|
+
this.getFromEnvJsonFile(envVarName) ||
|
|
79
|
+
this.getFromDockerSecret(envVarName) ||
|
|
80
|
+
this.getFromDockerSecretJson(envVarName)
|
|
81
|
+
);
|
|
55
82
|
}
|
|
56
83
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
let envVarFromEnvironmentVariable: string;
|
|
63
|
-
let envVarFromEnvJsonFile: string;
|
|
64
|
-
let envVarFromDockerSecret: string;
|
|
65
|
-
let dockerSecretJson: string;
|
|
66
|
-
|
|
67
|
-
// env var check
|
|
68
|
-
if (process.env[wantedEnvVar]) {
|
|
69
|
-
this.availableEnvVars.push(wantedEnvVar);
|
|
70
|
-
envVarFromEnvironmentVariable = process.env[wantedEnvVar];
|
|
84
|
+
public async getEnvVarOnDemandAsObject(envVarName: string): Promise<any> {
|
|
85
|
+
const rawValue = await this.getEnvVarOnDemand(envVarName);
|
|
86
|
+
if (rawValue && rawValue.startsWith('base64Object:')) {
|
|
87
|
+
const base64Part = rawValue.split('base64Object:')[1];
|
|
88
|
+
return this.decodeBase64(base64Part);
|
|
71
89
|
}
|
|
90
|
+
return rawValue;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private getFromEnvironmentVariable(envVarName: string): string | undefined {
|
|
94
|
+
return process.env[envVarName];
|
|
95
|
+
}
|
|
72
96
|
|
|
73
|
-
|
|
74
|
-
// lets determine the actual env yml
|
|
75
|
-
let envJsonFileAsObject;
|
|
97
|
+
private getFromEnvJsonFile(envVarName: string): string | undefined {
|
|
76
98
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
const envJson = plugins.smartfile.fs.toObjectSync(this.envFilePathAbsolute);
|
|
100
|
+
const value = envJson[envVarName];
|
|
101
|
+
if (typeof value === 'object') {
|
|
102
|
+
return 'base64Object:' + this.encodeBase64(value);
|
|
103
|
+
}
|
|
104
|
+
return value;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return undefined;
|
|
83
107
|
}
|
|
108
|
+
}
|
|
84
109
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
plugins.smartfile.fs.
|
|
89
|
-
plugins.smartfile.fs.fileExistsSync(`/run/secrets/${wantedEnvVar}`)
|
|
90
|
-
) {
|
|
91
|
-
envVarFromDockerSecret = plugins.smartfile.fs.toStringSync(`/run/secrets/${wantedEnvVar}`);
|
|
110
|
+
private getFromDockerSecret(envVarName: string): string | undefined {
|
|
111
|
+
const secretPath = `/run/secrets/${envVarName}`;
|
|
112
|
+
if (plugins.smartfile.fs.fileExistsSync(secretPath)) {
|
|
113
|
+
return plugins.smartfile.fs.toStringSync(secretPath);
|
|
92
114
|
}
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
93
117
|
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
plugins.smartfile.fs.isDirectory('/run') &&
|
|
97
|
-
plugins.smartfile.fs.isDirectory('/run/secrets')
|
|
98
|
-
) {
|
|
118
|
+
private getFromDockerSecretJson(envVarName: string): string | undefined {
|
|
119
|
+
if (plugins.smartfile.fs.isDirectory('/run/secrets')) {
|
|
99
120
|
const availableSecrets = plugins.smartfile.fs.listAllItemsSync('/run/secrets');
|
|
100
121
|
for (const secret of availableSecrets) {
|
|
101
|
-
if (secret.includes('secret.json')
|
|
122
|
+
if (secret.includes('secret.json')) {
|
|
102
123
|
const secretObject = plugins.smartfile.fs.toObjectSync(`/run/secrets/${secret}`);
|
|
103
|
-
|
|
124
|
+
const value = secretObject[envVarName];
|
|
125
|
+
if (typeof value === 'object') {
|
|
126
|
+
return 'base64Object:' + this.encodeBase64(value);
|
|
127
|
+
}
|
|
128
|
+
return value;
|
|
104
129
|
}
|
|
105
130
|
}
|
|
106
131
|
}
|
|
107
|
-
|
|
108
|
-
// warn if there is more than one candidate
|
|
109
|
-
const availableCcandidates: any[] = [];
|
|
110
|
-
[
|
|
111
|
-
envVarFromEnvironmentVariable,
|
|
112
|
-
envVarFromEnvJsonFile,
|
|
113
|
-
envVarFromDockerSecret,
|
|
114
|
-
dockerSecretJson,
|
|
115
|
-
].forEach((candidate) => {
|
|
116
|
-
if (candidate) {
|
|
117
|
-
availableCcandidates.push(candidate);
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
if (availableCcandidates.length > 1) {
|
|
121
|
-
this.logger.log(
|
|
122
|
-
'warn',
|
|
123
|
-
`found multiple candidates for ${wantedEnvVar} Choosing in the order of envVar, envFileVar, dockerSecret, dockerSecretJson`
|
|
124
|
-
);
|
|
125
|
-
console.log(availableCcandidates);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
switch (true) {
|
|
129
|
-
case !!envVarFromEnvironmentVariable:
|
|
130
|
-
this.logger.log('ok', `found ${wantedEnvVar} as environment variable`);
|
|
131
|
-
return envVarFromEnvironmentVariable;
|
|
132
|
-
case !!envVarFromEnvJsonFile:
|
|
133
|
-
this.logger.log('ok', `found ${wantedEnvVar} as env.json variable`);
|
|
134
|
-
return envVarFromEnvJsonFile;
|
|
135
|
-
case !!envVarFromDockerSecret:
|
|
136
|
-
this.logger.log('ok', `found ${wantedEnvVar} as docker secret`);
|
|
137
|
-
return envVarFromDockerSecret;
|
|
138
|
-
case !!dockerSecretJson:
|
|
139
|
-
this.logger.log('ok', `found ${wantedEnvVar} as docker secret.json`);
|
|
140
|
-
return dockerSecretJson;
|
|
141
|
-
default:
|
|
142
|
-
this.logger.log(
|
|
143
|
-
'warn',
|
|
144
|
-
`could not find the wanted environment variable ${wantedEnvVar} anywhere`
|
|
145
|
-
);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
132
|
+
return undefined;
|
|
148
133
|
}
|
|
149
134
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let qenvFile: any = {};
|
|
155
|
-
if (plugins.smartfile.fs.fileExistsSync(this.qenvFilePathAbsolute)) {
|
|
156
|
-
qenvFile = plugins.smartfile.fs.toObjectSync(this.qenvFilePathAbsolute);
|
|
157
|
-
}
|
|
158
|
-
if (!qenvFile || !qenvFile.required || !Array.isArray(qenvFile.required)) {
|
|
159
|
-
this.logger.log(
|
|
160
|
-
'warn',
|
|
161
|
-
`qenv (promised environment): ./qenv.yml File does not contain a 'required' Array! This might be ok though.`
|
|
162
|
-
);
|
|
163
|
-
} else {
|
|
164
|
-
for (const keyArg of Object.keys(qenvFile.required)) {
|
|
165
|
-
this.requiredEnvVars.push(qenvFile.required[keyArg]);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* gets the available env vars
|
|
172
|
-
*/
|
|
173
|
-
private getAvailableEnvVars = () => {
|
|
174
|
-
for (const requiredEnvVar of this.requiredEnvVars) {
|
|
175
|
-
const chosenVar = this.getEnvVarOnDemand(requiredEnvVar);
|
|
176
|
-
if (chosenVar) {
|
|
177
|
-
this.availableEnvVars.push(requiredEnvVar);
|
|
178
|
-
this.keyValueObject[requiredEnvVar] = chosenVar;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
};
|
|
135
|
+
private encodeBase64(data: any): string {
|
|
136
|
+
const jsonString = JSON.stringify(data);
|
|
137
|
+
return Buffer.from(jsonString).toString('base64');
|
|
138
|
+
}
|
|
182
139
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const missingEnvVars: string[] = [];
|
|
188
|
-
for (const envVar of this.requiredEnvVars) {
|
|
189
|
-
if (!this.availableEnvVars.includes(envVar)) {
|
|
190
|
-
missingEnvVars.push(envVar);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return missingEnvVars;
|
|
194
|
-
};
|
|
140
|
+
private decodeBase64(encodedString: string): any {
|
|
141
|
+
const decodedString = Buffer.from(encodedString, 'base64').toString('utf-8');
|
|
142
|
+
return JSON.parse(decodedString);
|
|
143
|
+
}
|
|
195
144
|
}
|