1
+ const chalk = require('chalk');
1
2
const childProcess = require('child_process');
2
3
const { localConfig } = require("../config");
3
4
const path = require('path');
4
5
const fs = require('fs');
5
- const { log,success } = require("../parser");
6
+ const { log, success, hint } = require("../parser");
6
7
const { openRuntimesVersion, systemTools } = require("./utils");
7
- const ID = require("../id");
8
-
9
- const activeDockerIds = {};
10
8
11
9
async function dockerStop(id) {
12
- delete activeDockerIds[id];
13
10
const stopProcess = childProcess.spawn('docker', ['rm', '--force', id], {
14
11
stdio: 'pipe',
15
12
});
@@ -18,20 +15,42 @@ async function dockerStop(id) {
18
15
}
19
16
20
17
async function dockerPull(func) {
21
- log('Pulling Docker image of function runtime ...');
22
-
23
18
const runtimeChunks = func.runtime.split("-");
24
19
const runtimeVersion = runtimeChunks.pop();
25
20
const runtimeName = runtimeChunks.join("-");
26
21
const imageName = `openruntimes/${runtimeName}:${openRuntimesVersion}-${runtimeVersion}`;
27
22
28
- const pullProcess = childProcess.spawn('docker', ['pull ', imageName], {
23
+ const checkProcess = childProcess.spawn('docker', ['images', '--format', 'json ', imageName], {
29
24
stdio: 'pipe',
30
25
pwd: path.join(process.cwd(), func.path)
31
26
});
32
27
33
- pullProcess.stderr.on('data', (data) => {
34
- process.stderr.write(`\n${data}$ `);
28
+ let hasImage = false;
29
+
30
+ checkProcess.stdout.on('data', (data) => {
31
+ if(data) {
32
+ hasImage = false;
33
+ }
34
+ });
35
+
36
+ checkProcess.stderr.on('data', (data) => {
37
+ if(data) {
38
+ hasImage = false;
39
+ }
40
+ });
41
+
42
+ await new Promise((res) => { checkProcess.on('close', res) });
43
+
44
+ if(hasImage) {
45
+ return;
46
+ }
47
+
48
+ log('Pulling Docker image ...');
49
+ hint('This may take a few minutes, but we only need to do this once.');
50
+
51
+ const pullProcess = childProcess.spawn('docker', ['pull', imageName], {
52
+ stdio: 'pipe',
53
+ pwd: path.join(process.cwd(), func.path)
35
54
});
36
55
37
56
await new Promise((res) => { pullProcess.on('close', res) });
@@ -47,14 +66,15 @@ async function dockerBuild(func, variables) {
47
66
48
67
const functionDir = path.join(process.cwd(), func.path);
49
68
50
- const id = ID.unique() ;
69
+ const id = func.$id ;
51
70
52
71
const params = [ 'run' ];
53
72
params.push('--name', id);
54
73
params.push('-v', `${functionDir}/:/mnt/code:rw`);
55
74
params.push('-e', 'APPWRITE_ENV=development');
56
75
params.push('-e', 'OPEN_RUNTIMES_ENV=development');
57
76
params.push('-e', 'OPEN_RUNTIMES_SECRET=');
77
+ params.push('-l', 'appwrite-env=dev');
58
78
params.push('-e', `OPEN_RUNTIMES_ENTRYPOINT=${func.entrypoint}`);
59
79
60
80
for(const k of Object.keys(variables)) {
@@ -69,11 +89,11 @@ async function dockerBuild(func, variables) {
69
89
});
70
90
71
91
buildProcess.stdout.on('data', (data) => {
72
- process.stdout.write(`\n ${data}` );
92
+ process.stdout.write(chalk.white.dim(` ${data}\n`) );
73
93
});
74
94
75
95
buildProcess.stderr.on('data', (data) => {
76
- process.stderr.write(`\n ${data}` );
96
+ process.stderr.write(chalk.white.dim(` ${data}\n`) );
77
97
});
78
98
79
99
await new Promise((res) => { buildProcess.on('close', res) });
@@ -91,14 +111,7 @@ async function dockerBuild(func, variables) {
91
111
92
112
await new Promise((res) => { copyProcess.on('close', res) });
93
113
94
- const cleanupProcess = childProcess.spawn('docker', ['rm', '--force', id], {
95
- stdio: 'pipe',
96
- pwd: functionDir
97
- });
98
-
99
- await new Promise((res) => { cleanupProcess.on('close', res) });
100
-
101
- delete activeDockerIds[id];
114
+ await dockerStop(id);
102
115
103
116
const tempPath = path.join(process.cwd(), func.path, 'code.tar.gz');
104
117
if (fs.existsSync(tempPath)) {
@@ -107,15 +120,6 @@ async function dockerBuild(func, variables) {
107
120
}
108
121
109
122
async function dockerStart(func, variables, port) {
110
- log('Starting function using Docker ...');
111
-
112
- log("Permissions, events, CRON and timeouts dont apply when running locally.");
113
-
114
- log('💡 Hint: Function automatically restarts when you edit your code.');
115
-
116
- success(`Visit http://localhost:${port}/ to execute your function.`);
117
-
118
-
119
123
const runtimeChunks = func.runtime.split("-");
120
124
const runtimeVersion = runtimeChunks.pop();
121
125
const runtimeName = runtimeChunks.join("-");
@@ -125,13 +129,14 @@ async function dockerStart(func, variables, port) {
125
129
126
130
const functionDir = path.join(process.cwd(), func.path);
127
131
128
- const id = ID.unique() ;
132
+ const id = func.$id ;
129
133
130
134
const params = [ 'run' ];
131
135
params.push('--rm');
132
136
params.push('-d');
133
137
params.push('--name', id);
134
138
params.push('-p', `${port}:3000`);
139
+ params.push('-l', 'appwrite-env=dev');
135
140
params.push('-e', 'APPWRITE_ENV=development');
136
141
params.push('-e', 'OPEN_RUNTIMES_ENV=development');
137
142
params.push('-e', 'OPEN_RUNTIMES_SECRET=');
@@ -150,11 +155,11 @@ async function dockerStart(func, variables, port) {
150
155
pwd: functionDir
151
156
});
152
157
153
- activeDockerIds[id] = true ;
158
+ success(`Visit http://localhost:${port}/ to execute your function.`) ;
154
159
}
155
160
156
161
async function dockerCleanup() {
157
- await dockerStop ();
162
+ await dockerStopActive ();
158
163
159
164
const functions = localConfig.getFunctions();
160
165
for(const func of functions) {
@@ -171,17 +176,40 @@ async function dockerCleanup() {
171
176
}
172
177
173
178
async function dockerStopActive() {
174
- const ids = Object.keys(activeDockerIds);
175
- for await (const id of ids) {
179
+ const listProcess = childProcess.spawn('docker', ['ps', '-a', '-q', '--filter', 'label=appwrite-env=dev'], {
180
+ stdio: 'pipe',
181
+ });
182
+
183
+ const ids = [];
184
+ function handleOutput(data) {
185
+ const list = data.toString().split('\n');
186
+ for(const id of list) {
187
+ if(id && !id.includes(' ')) {
188
+ ids.push(id);
189
+ }
190
+ }
191
+ }
192
+
193
+ listProcess.stdout.on('data', (data) => {
194
+ handleOutput(data);
195
+ });
196
+
197
+ listProcess.stderr.on('data', (data) => {
198
+ handleOutput(data);
199
+ });
200
+
201
+ await new Promise((res) => { listProcess.on('close', res) });
202
+
203
+ for(const id of ids) {
176
204
await dockerStop(id);
177
205
}
178
206
}
179
207
180
208
module.exports = {
181
- dockerStop,
182
209
dockerPull,
183
210
dockerBuild,
184
211
dockerStart,
185
212
dockerCleanup,
186
213
dockerStopActive,
214
+ dockerStop,
187
215
}
0 commit comments