This repository was archived by the owner on Nov 23, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathindex.js
More file actions
136 lines (118 loc) · 4.43 KB
/
index.js
File metadata and controls
136 lines (118 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// npm modules
const _ = require('lodash');
const fs = require('fs');
const path = require('path');
const {spawn} = require('child_process');
const tar = require('tar-fs');
const rimraf = require('rimraf');
const uuid = require('uuid');
const {getSecretsCollection} = require('../db');
// our modules
const {tempDockerDir: tempDir} = require('../config');
// try to find secret with current value name and return secret value if present
const valueOrSecret = (value, secrets) => {
const secret = secrets.find(s => `@${s.name}` === value);
if (secret) {
return secret.value;
}
return value;
};
// cleanup temp folder
exports.cleanTemp = folder => new Promise(resolve => rimraf(path.join(tempDir, folder), resolve));
// unpack function for incoming project files
exports.unpack = ({tarStream, folder}) =>
new Promise((resolve, reject) => {
// create whatever writestream you want
const s = tarStream.pipe(tar.extract(path.join(tempDir, folder)));
s.on('finish', () => resolve());
s.on('error', e => reject(e));
});
exports.getProjectConfig = folder => {
const projectConfigString = fs.readFileSync(path.join(tempDir, folder, 'exoframe.json'));
const config = JSON.parse(projectConfigString);
return config;
};
exports.tagFromConfig = ({username, config}) => `exo-${_.kebabCase(username)}-${_.kebabCase(config.name)}:latest`;
exports.baseNameFromImage = image =>
image
.split(':')
.shift()
.replace(/[^a-zA-Z0-9_-]/g, '');
exports.nameFromImage = image => {
const baseName = exports.baseNameFromImage(image);
const uid = uuid.v1();
return `${baseName}-${uid.split('-').shift()}`;
};
exports.projectFromConfig = ({username, config}) => {
const image = exports.tagFromConfig({username, config});
const baseName = exports.baseNameFromImage(image);
return config.project || baseName;
};
exports.sleep = time => new Promise(r => setTimeout(r, time));
exports.writeStatus = (stream, data) => stream.write(`${JSON.stringify(data)}\n`);
exports.runYarn = ({args, cwd}) =>
new Promise(resolve => {
const yarn = spawn('yarn', args, {cwd});
const log = [];
yarn.stdout.on('data', data => {
const message = data.toString().replace(/\n$/, '');
const hasError = message.toLowerCase().includes('error');
log.push({message, level: hasError ? 'error' : 'info'});
});
yarn.stderr.on('data', data => {
const message = data.toString().replace(/\n$/, '');
const hasError = message.toLowerCase().includes('error');
log.push({message, level: hasError ? 'error' : 'info'});
});
yarn.on('exit', code => {
log.push({message: `yarn exited with code ${code.toString()}`, level: 'info'});
resolve(log);
});
});
exports.compareNames = (nameOne = '', nameTwo = '') => {
const nameOneParts = nameOne.split('-');
const nameOneClean = nameOneParts.slice(0, nameOneParts.length - 2).join('-');
const nameTwoParts = nameTwo.split('-');
const nameTwoClean = nameTwoParts.slice(0, nameTwoParts.length - 2).join('-');
return nameOneClean === nameTwoClean;
};
exports.getHost = ({serverConfig, name, config}) => {
// construct base domain from config, prepend with "." if it's not there
const baseDomain = serverConfig.baseDomain ? serverConfig.baseDomain.replace(/^(\.?)/, '.') : undefined;
// construct default domain using given base domain
const defaultDomain = baseDomain ? `${name}${baseDomain}` : undefined;
// construct host
const host = config.domain === undefined ? defaultDomain : config.domain;
return host;
};
exports.getEnv = ({username, config, name, host, project = config.project || name}) => {
// replace env vars values with secrets if needed
const secrets = getSecretsCollection().find({user: username});
// generate env vars (with secrets)
const userEnv = config.env
? Object.entries(config.env).map(([key, value]) => [key, valueOrSecret(value, secrets)])
: [];
return [
...userEnv,
['EXOFRAME_DEPLOYMENT', name],
['EXOFRAME_USER', username],
['EXOFRAME_PROJECT', project],
['EXOFRAME_HOST', host],
];
};
exports.functionToContainerFormat = ({config, route, type = 'http'}) => ({
Name: `/${config.name}`,
Config: {
Labels: {
[`traefik.http.routers.${config.name}.rule`]: type === 'http' ? route || `/${config.name}` : 'Non-HTTP',
'exoframe.project': config.name,
'exoframe.type': `Function (${type})`,
},
},
NetworkSettings: {
Networks: {},
},
State: {
Status: 'running',
},
});