@kapeta/local-cluster-service 0.12.0 → 0.13.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/CHANGELOG.md +14 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/src/assetManager.d.ts +3 -1
- package/dist/cjs/src/assetManager.js +20 -4
- package/dist/cjs/src/assets/routes.js +22 -1
- package/dist/cjs/src/containerManager.d.ts +1 -1
- package/dist/cjs/src/containerManager.js +132 -122
- package/dist/cjs/src/instanceManager.d.ts +4 -3
- package/dist/cjs/src/instanceManager.js +87 -60
- package/dist/cjs/src/instances/routes.js +21 -11
- package/dist/cjs/src/operatorManager.d.ts +5 -3
- package/dist/cjs/src/operatorManager.js +34 -22
- package/dist/cjs/src/providerManager.js +1 -1
- package/dist/cjs/src/repositoryManager.d.ts +2 -4
- package/dist/cjs/src/repositoryManager.js +51 -66
- package/dist/cjs/src/socketManager.js +1 -1
- package/dist/cjs/src/taskManager.d.ts +64 -0
- package/dist/cjs/src/taskManager.js +163 -0
- package/dist/cjs/src/tasks/routes.d.ts +3 -0
- package/dist/cjs/src/tasks/routes.js +35 -0
- package/dist/cjs/src/utils/BlockInstanceRunner.js +0 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/src/assetManager.d.ts +3 -1
- package/dist/esm/src/assetManager.js +20 -4
- package/dist/esm/src/assets/routes.js +22 -1
- package/dist/esm/src/containerManager.d.ts +1 -1
- package/dist/esm/src/containerManager.js +132 -122
- package/dist/esm/src/instanceManager.d.ts +4 -3
- package/dist/esm/src/instanceManager.js +87 -60
- package/dist/esm/src/instances/routes.js +21 -11
- package/dist/esm/src/operatorManager.d.ts +5 -3
- package/dist/esm/src/operatorManager.js +34 -22
- package/dist/esm/src/providerManager.js +1 -1
- package/dist/esm/src/repositoryManager.d.ts +2 -4
- package/dist/esm/src/repositoryManager.js +51 -66
- package/dist/esm/src/socketManager.js +1 -1
- package/dist/esm/src/taskManager.d.ts +64 -0
- package/dist/esm/src/taskManager.js +159 -0
- package/dist/esm/src/tasks/routes.d.ts +3 -0
- package/dist/esm/src/tasks/routes.js +30 -0
- package/dist/esm/src/utils/BlockInstanceRunner.js +0 -1
- package/index.ts +2 -0
- package/package.json +1 -1
- package/src/assetManager.ts +28 -4
- package/src/assets/routes.ts +23 -1
- package/src/containerManager.ts +153 -142
- package/src/instanceManager.ts +116 -70
- package/src/instances/routes.ts +20 -12
- package/src/operatorManager.ts +46 -26
- package/src/providerManager.ts +1 -1
- package/src/repositoryManager.ts +65 -63
- package/src/socketManager.ts +1 -1
- package/src/taskManager.ts +225 -0
- package/src/tasks/routes.ts +38 -0
- package/src/utils/BlockInstanceRunner.ts +0 -4
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
# [0.13.0](https://github.com/kapetacom/local-cluster-service/compare/v0.12.1...v0.13.0) (2023-08-03)
|
2
|
+
|
3
|
+
|
4
|
+
### Features
|
5
|
+
|
6
|
+
* Adds background task concept ([#55](https://github.com/kapetacom/local-cluster-service/issues/55)) ([71cc63c](https://github.com/kapetacom/local-cluster-service/commit/71cc63c9c3eb8bec1dec8b31d3340694e93bd3e5))
|
7
|
+
|
8
|
+
## [0.12.1](https://github.com/kapetacom/local-cluster-service/compare/v0.12.0...v0.12.1) (2023-08-02)
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* Adjustments to make starting plans locally smoother ([fc353ad](https://github.com/kapetacom/local-cluster-service/commit/fc353adde350b7e9d4c7eb9347c4cfa0c3a6aa58))
|
14
|
+
|
1
15
|
# [0.12.0](https://github.com/kapetacom/local-cluster-service/compare/v0.11.1...v0.12.0) (2023-07-31)
|
2
16
|
|
3
17
|
|
package/dist/cjs/index.js
CHANGED
@@ -20,6 +20,7 @@ const routes_6 = __importDefault(require("./src/filesystem/routes"));
|
|
20
20
|
const routes_7 = __importDefault(require("./src/assets/routes"));
|
21
21
|
const routes_8 = __importDefault(require("./src/providers/routes"));
|
22
22
|
const routes_9 = __importDefault(require("./src/attachments/routes"));
|
23
|
+
const routes_10 = __importDefault(require("./src/tasks/routes"));
|
23
24
|
const utils_1 = require("./src/utils/utils");
|
24
25
|
const request_1 = __importDefault(require("request"));
|
25
26
|
let currentServer = null;
|
@@ -34,6 +35,7 @@ function createServer() {
|
|
34
35
|
app.use('/assets', routes_7.default);
|
35
36
|
app.use('/providers', routes_8.default);
|
36
37
|
app.use('/attachments', routes_9.default);
|
38
|
+
app.use('/tasks', routes_10.default);
|
37
39
|
app.get('/status', async (req, res) => {
|
38
40
|
res.send({
|
39
41
|
ok: true,
|
@@ -13,6 +13,7 @@ export interface EnrichedAsset {
|
|
13
13
|
declare class AssetManager {
|
14
14
|
private cache;
|
15
15
|
constructor();
|
16
|
+
clearCache(): void;
|
16
17
|
/**
|
17
18
|
*
|
18
19
|
* @param {string[]} [assetKinds]
|
@@ -21,11 +22,12 @@ declare class AssetManager {
|
|
21
22
|
getAssets(assetKinds?: string[]): EnrichedAsset[];
|
22
23
|
getPlans(): EnrichedAsset[];
|
23
24
|
getPlan(ref: string, noCache?: boolean): Promise<Definition>;
|
24
|
-
getAsset(ref: string, noCache?: boolean): Promise<EnrichedAsset | undefined>;
|
25
|
+
getAsset(ref: string, noCache?: boolean, autoFetch?: boolean): Promise<EnrichedAsset | undefined>;
|
25
26
|
createAsset(path: string, yaml: BlockDefinition): Promise<EnrichedAsset[]>;
|
26
27
|
updateAsset(ref: string, yaml: BlockDefinition): Promise<void>;
|
27
28
|
importFile(filePath: string): Promise<EnrichedAsset[]>;
|
28
29
|
unregisterAsset(ref: string): Promise<void>;
|
30
|
+
installAsset(ref: string): Promise<import("./taskManager").Task<void>[] | undefined>;
|
29
31
|
}
|
30
32
|
export declare const assetManager: AssetManager;
|
31
33
|
export {};
|
@@ -47,6 +47,9 @@ class AssetManager {
|
|
47
47
|
stdTTL: 60 * 60, // 1 hour
|
48
48
|
});
|
49
49
|
}
|
50
|
+
clearCache() {
|
51
|
+
this.cache.flushAll();
|
52
|
+
}
|
50
53
|
/**
|
51
54
|
*
|
52
55
|
* @param {string[]} [assetKinds]
|
@@ -76,22 +79,26 @@ class AssetManager {
|
|
76
79
|
}
|
77
80
|
return asset.data;
|
78
81
|
}
|
79
|
-
async getAsset(ref, noCache = false) {
|
82
|
+
async getAsset(ref, noCache = false, autoFetch = true) {
|
80
83
|
ref = (0, utils_1.normalizeKapetaUri)(ref);
|
81
84
|
const cacheKey = `getAsset:${ref}`;
|
82
85
|
if (!noCache && this.cache.has(cacheKey)) {
|
83
86
|
return this.cache.get(cacheKey);
|
84
87
|
}
|
85
88
|
const uri = (0, nodejs_utils_1.parseKapetaUri)(ref);
|
86
|
-
|
89
|
+
if (autoFetch) {
|
90
|
+
await repositoryManager_1.repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, true);
|
91
|
+
}
|
87
92
|
let asset = definitionsManager_1.definitionsManager
|
88
93
|
.getDefinitions()
|
89
94
|
.map(enrichAsset)
|
90
95
|
.find((a) => (0, nodejs_utils_1.parseKapetaUri)(a.ref).equals(uri));
|
91
|
-
if (!asset) {
|
96
|
+
if (autoFetch && !asset) {
|
92
97
|
throw new Error('Asset not found: ' + ref);
|
93
98
|
}
|
94
|
-
|
99
|
+
if (asset) {
|
100
|
+
this.cache.set(cacheKey, asset);
|
101
|
+
}
|
95
102
|
return asset;
|
96
103
|
}
|
97
104
|
async createAsset(path, yaml) {
|
@@ -152,5 +159,14 @@ class AssetManager {
|
|
152
159
|
this.cache.flushAll();
|
153
160
|
await nodejs_registry_utils_1.Actions.uninstall(progressListener_1.progressListener, [asset.ref]);
|
154
161
|
}
|
162
|
+
async installAsset(ref) {
|
163
|
+
const asset = await this.getAsset(ref, true, false);
|
164
|
+
if (asset) {
|
165
|
+
throw new Error('Asset already installed: ' + ref);
|
166
|
+
}
|
167
|
+
const uri = (0, nodejs_utils_1.parseKapetaUri)(ref);
|
168
|
+
console.log('Installing %s', ref);
|
169
|
+
return await repositoryManager_1.repositoryManager.ensureAsset(uri.handle, uri.name, uri.version, false);
|
170
|
+
}
|
155
171
|
}
|
156
172
|
exports.assetManager = new AssetManager();
|
@@ -39,8 +39,15 @@ router.get('/read', async (req, res) => {
|
|
39
39
|
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
40
40
|
return;
|
41
41
|
}
|
42
|
+
const ensure = req.query.ensure !== 'false';
|
42
43
|
try {
|
43
|
-
|
44
|
+
const asset = await assetManager_1.assetManager.getAsset(req.query.ref, true, ensure);
|
45
|
+
if (asset) {
|
46
|
+
res.send(asset);
|
47
|
+
}
|
48
|
+
else {
|
49
|
+
res.status(404).send({ error: 'Asset not found' });
|
50
|
+
}
|
44
51
|
}
|
45
52
|
catch (err) {
|
46
53
|
res.status(400).send({ error: err.message });
|
@@ -114,4 +121,18 @@ router.put('/import', async (req, res) => {
|
|
114
121
|
res.status(400).send({ error: err.message });
|
115
122
|
}
|
116
123
|
});
|
124
|
+
router.put('/install', async (req, res) => {
|
125
|
+
if (!req.query.ref) {
|
126
|
+
res.status(400).send({ error: 'Query parameter "ref" is missing' });
|
127
|
+
return;
|
128
|
+
}
|
129
|
+
try {
|
130
|
+
const tasks = await assetManager_1.assetManager.installAsset(req.query.ref);
|
131
|
+
const taskIds = tasks?.map((t) => t.id) ?? [];
|
132
|
+
res.status(200).send(taskIds);
|
133
|
+
}
|
134
|
+
catch (err) {
|
135
|
+
res.status(400).send({ error: err.message });
|
136
|
+
}
|
137
|
+
});
|
117
138
|
exports.default = router;
|
@@ -59,7 +59,7 @@ declare class ContainerManager {
|
|
59
59
|
ping(): Promise<void>;
|
60
60
|
docker(): Docker;
|
61
61
|
getContainerByName(containerName: string): Promise<ContainerInfo | undefined>;
|
62
|
-
pull(image: string
|
62
|
+
pull(image: string): Promise<boolean>;
|
63
63
|
toDockerMounts(mounts: StringMap): DockerMounts[];
|
64
64
|
toDockerHealth(health: Health): {
|
65
65
|
Test: string[];
|
@@ -15,15 +15,13 @@ const local_cluster_config_1 = __importDefault(require("@kapeta/local-cluster-co
|
|
15
15
|
const node_uuid_1 = __importDefault(require("node-uuid"));
|
16
16
|
const md5_1 = __importDefault(require("md5"));
|
17
17
|
const utils_1 = require("./utils/utils");
|
18
|
-
const socketManager_1 = require("./socketManager");
|
19
18
|
const nodejs_api_client_1 = require("@kapeta/nodejs-api-client");
|
19
|
+
const taskManager_1 = require("./taskManager");
|
20
20
|
const EVENT_IMAGE_PULL = 'docker-image-pull';
|
21
21
|
exports.CONTAINER_LABEL_PORT_PREFIX = 'kapeta_port-';
|
22
22
|
const NANO_SECOND = 1000000;
|
23
23
|
const HEALTH_CHECK_INTERVAL = 3000;
|
24
24
|
const HEALTH_CHECK_MAX = 20;
|
25
|
-
const IMAGE_PULL_CACHE_TTL = 30 * 60 * 1000;
|
26
|
-
const IMAGE_PULL_CACHE = {};
|
27
25
|
exports.HEALTH_CHECK_TIMEOUT = HEALTH_CHECK_INTERVAL * HEALTH_CHECK_MAX * 2;
|
28
26
|
const promisifyStream = (stream, handler) => new Promise((resolve, reject) => {
|
29
27
|
stream.on('data', handler);
|
@@ -151,17 +149,11 @@ class ContainerManager {
|
|
151
149
|
}
|
152
150
|
return undefined;
|
153
151
|
}
|
154
|
-
async pull(image
|
152
|
+
async pull(image) {
|
155
153
|
let [imageName, tag] = image.split(/:/);
|
156
154
|
if (!tag) {
|
157
155
|
tag = 'latest';
|
158
156
|
}
|
159
|
-
if (IMAGE_PULL_CACHE[image]) {
|
160
|
-
const timeSince = Date.now() - IMAGE_PULL_CACHE[image];
|
161
|
-
if (timeSince < cacheForMS) {
|
162
|
-
return false;
|
163
|
-
}
|
164
|
-
}
|
165
157
|
const imageTagList = (await this.docker().image.list())
|
166
158
|
.map((image) => image.data)
|
167
159
|
.filter((imageData) => !!imageData.RepoTags)
|
@@ -170,121 +162,141 @@ class ContainerManager {
|
|
170
162
|
console.log('Image found: %s', image);
|
171
163
|
return false;
|
172
164
|
}
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
let lastEmitted = Date.now();
|
190
|
-
await promisifyStream(stream, (rawData) => {
|
191
|
-
const lines = rawData.toString().trim().split('\n');
|
192
|
-
lines.forEach((line) => {
|
193
|
-
const data = JSON.parse(line);
|
194
|
-
if (![
|
195
|
-
'Waiting',
|
196
|
-
'Downloading',
|
197
|
-
'Extracting',
|
198
|
-
'Download complete',
|
199
|
-
'Pull complete',
|
200
|
-
'Already exists',
|
201
|
-
].includes(data.status)) {
|
202
|
-
return;
|
203
|
-
}
|
204
|
-
if (!chunks[data.id]) {
|
205
|
-
chunks[data.id] = {
|
206
|
-
downloading: {
|
207
|
-
total: 0,
|
208
|
-
current: 0,
|
209
|
-
},
|
210
|
-
extracting: {
|
211
|
-
total: 0,
|
212
|
-
current: 0,
|
213
|
-
},
|
214
|
-
done: false,
|
215
|
-
};
|
216
|
-
}
|
217
|
-
const chunk = chunks[data.id];
|
218
|
-
switch (data.status) {
|
219
|
-
case 'Downloading':
|
220
|
-
chunk.downloading = data.progressDetail;
|
221
|
-
break;
|
222
|
-
case 'Extracting':
|
223
|
-
chunk.extracting = data.progressDetail;
|
224
|
-
break;
|
225
|
-
case 'Download complete':
|
226
|
-
chunk.downloading.current = chunks[data.id].downloading.total;
|
227
|
-
break;
|
228
|
-
case 'Pull complete':
|
229
|
-
chunk.extracting.current = chunks[data.id].extracting.total;
|
230
|
-
chunk.done = true;
|
231
|
-
break;
|
232
|
-
case 'Already exists':
|
233
|
-
// Force layer to be done
|
234
|
-
chunk.downloading.current = 1;
|
235
|
-
chunk.downloading.total = 1;
|
236
|
-
chunk.extracting.current = 1;
|
237
|
-
chunk.extracting.total = 1;
|
238
|
-
chunk.done = true;
|
239
|
-
break;
|
240
|
-
}
|
241
|
-
});
|
242
|
-
if (Date.now() - lastEmitted < 1000) {
|
243
|
-
return;
|
244
|
-
}
|
245
|
-
const chunkList = Object.values(chunks);
|
246
|
-
let totals = {
|
247
|
-
downloading: {
|
248
|
-
total: 0,
|
249
|
-
current: 0,
|
250
|
-
},
|
251
|
-
extracting: {
|
252
|
-
total: 0,
|
253
|
-
current: 0,
|
254
|
-
},
|
255
|
-
total: chunkList.length,
|
256
|
-
done: 0,
|
257
|
-
};
|
258
|
-
chunkList.forEach((chunk) => {
|
259
|
-
if (chunk.downloading.current > 0) {
|
260
|
-
totals.downloading.current += chunk.downloading.current;
|
261
|
-
}
|
262
|
-
if (chunk.downloading.total > 0) {
|
263
|
-
totals.downloading.total += chunk.downloading.total;
|
165
|
+
let friendlyImageName = image;
|
166
|
+
const imageParts = imageName.split('/');
|
167
|
+
if (imageParts.length > 2) {
|
168
|
+
//Strip the registry to make the name shorter
|
169
|
+
friendlyImageName = `${imageParts.slice(1).join('/')}:${tag}`;
|
170
|
+
}
|
171
|
+
const taskName = `Pulling image ${friendlyImageName}`;
|
172
|
+
const processor = async (task) => {
|
173
|
+
const timeStarted = Date.now();
|
174
|
+
const api = new nodejs_api_client_1.KapetaAPI();
|
175
|
+
const accessToken = await api.getAccessToken();
|
176
|
+
const auth = image.startsWith('docker.kapeta.com/')
|
177
|
+
? {
|
178
|
+
username: 'kapeta',
|
179
|
+
password: accessToken,
|
180
|
+
serveraddress: 'docker.kapeta.com',
|
264
181
|
}
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
182
|
+
: {};
|
183
|
+
const stream = (await this.docker().image.create(auth, {
|
184
|
+
fromImage: imageName,
|
185
|
+
tag: tag,
|
186
|
+
}));
|
187
|
+
const chunks = {};
|
188
|
+
let lastEmitted = Date.now();
|
189
|
+
await promisifyStream(stream, (rawData) => {
|
190
|
+
const lines = rawData.toString().trim().split('\n');
|
191
|
+
lines.forEach((line) => {
|
192
|
+
const data = JSON.parse(line);
|
193
|
+
if (![
|
194
|
+
'Waiting',
|
195
|
+
'Downloading',
|
196
|
+
'Extracting',
|
197
|
+
'Download complete',
|
198
|
+
'Pull complete',
|
199
|
+
'Already exists',
|
200
|
+
].includes(data.status)) {
|
201
|
+
return;
|
202
|
+
}
|
203
|
+
if (!chunks[data.id]) {
|
204
|
+
chunks[data.id] = {
|
205
|
+
downloading: {
|
206
|
+
total: 0,
|
207
|
+
current: 0,
|
208
|
+
},
|
209
|
+
extracting: {
|
210
|
+
total: 0,
|
211
|
+
current: 0,
|
212
|
+
},
|
213
|
+
done: false,
|
214
|
+
};
|
215
|
+
}
|
216
|
+
const chunk = chunks[data.id];
|
217
|
+
switch (data.status) {
|
218
|
+
case 'Downloading':
|
219
|
+
chunk.downloading = data.progressDetail;
|
220
|
+
break;
|
221
|
+
case 'Extracting':
|
222
|
+
chunk.extracting = data.progressDetail;
|
223
|
+
break;
|
224
|
+
case 'Download complete':
|
225
|
+
chunk.downloading.current = chunks[data.id].downloading.total;
|
226
|
+
break;
|
227
|
+
case 'Pull complete':
|
228
|
+
chunk.extracting.current = chunks[data.id].extracting.total;
|
229
|
+
chunk.done = true;
|
230
|
+
break;
|
231
|
+
case 'Already exists':
|
232
|
+
// Force layer to be done
|
233
|
+
chunk.downloading.current = 1;
|
234
|
+
chunk.downloading.total = 1;
|
235
|
+
chunk.extracting.current = 1;
|
236
|
+
chunk.extracting.total = 1;
|
237
|
+
chunk.done = true;
|
238
|
+
break;
|
239
|
+
}
|
240
|
+
});
|
241
|
+
if (Date.now() - lastEmitted < 1000) {
|
242
|
+
return;
|
273
243
|
}
|
244
|
+
const chunkList = Object.values(chunks);
|
245
|
+
let totals = {
|
246
|
+
downloading: {
|
247
|
+
total: 0,
|
248
|
+
current: 0,
|
249
|
+
},
|
250
|
+
extracting: {
|
251
|
+
total: 0,
|
252
|
+
current: 0,
|
253
|
+
},
|
254
|
+
total: chunkList.length,
|
255
|
+
done: 0,
|
256
|
+
};
|
257
|
+
chunkList.forEach((chunk) => {
|
258
|
+
if (chunk.downloading.current > 0) {
|
259
|
+
totals.downloading.current += chunk.downloading.current;
|
260
|
+
}
|
261
|
+
if (chunk.downloading.total > 0) {
|
262
|
+
totals.downloading.total += chunk.downloading.total;
|
263
|
+
}
|
264
|
+
if (chunk.extracting.current > 0) {
|
265
|
+
totals.extracting.current += chunk.extracting.current;
|
266
|
+
}
|
267
|
+
if (chunk.extracting.total > 0) {
|
268
|
+
totals.extracting.total += chunk.extracting.total;
|
269
|
+
}
|
270
|
+
if (chunk.done) {
|
271
|
+
totals.done++;
|
272
|
+
}
|
273
|
+
});
|
274
|
+
const progress = totals.total > 0 ? (totals.done / totals.total) * 100 : 0;
|
275
|
+
task.metadata = {
|
276
|
+
...task.metadata,
|
277
|
+
image,
|
278
|
+
progress,
|
279
|
+
status: totals,
|
280
|
+
timeTaken: Date.now() - timeStarted,
|
281
|
+
};
|
282
|
+
task.emitUpdate();
|
283
|
+
lastEmitted = Date.now();
|
284
|
+
//console.log('Pulling image %s: %s % [done: %s, total: %s]', image, Math.round(percent), totals.done, totals.total);
|
274
285
|
});
|
275
|
-
|
276
|
-
|
277
|
-
socketManager_1.socketManager.emitGlobal(EVENT_IMAGE_PULL, {
|
286
|
+
task.metadata = {
|
287
|
+
...task.metadata,
|
278
288
|
image,
|
279
|
-
|
280
|
-
status: totals,
|
289
|
+
progress: 100,
|
281
290
|
timeTaken: Date.now() - timeStarted,
|
282
|
-
}
|
283
|
-
|
284
|
-
|
291
|
+
};
|
292
|
+
task.emitUpdate();
|
293
|
+
};
|
294
|
+
const task = taskManager_1.taskManager.add(`docker:image:pull:${image}`, processor, {
|
295
|
+
name: taskName,
|
296
|
+
image,
|
297
|
+
progress: -1,
|
285
298
|
});
|
286
|
-
|
287
|
-
socketManager_1.socketManager.emitGlobal(EVENT_IMAGE_PULL, { image, percent: 100, timeTaken: Date.now() - timeStarted });
|
299
|
+
await task.wait();
|
288
300
|
return true;
|
289
301
|
}
|
290
302
|
toDockerMounts(mounts) {
|
@@ -319,9 +331,7 @@ class ContainerManager {
|
|
319
331
|
dockerOpts.Labels.HASH = hash;
|
320
332
|
}
|
321
333
|
async ensureContainer(opts) {
|
322
|
-
|
323
|
-
await this.waitForReady(container);
|
324
|
-
return container;
|
334
|
+
return await this.createOrUpdateContainer(opts);
|
325
335
|
}
|
326
336
|
async createOrUpdateContainer(opts) {
|
327
337
|
let imagePulled = await this.pull(opts.Image);
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { InstanceInfo, LogEntry } from './types';
|
2
|
+
import { Task } from './taskManager';
|
2
3
|
export declare class InstanceManager {
|
3
4
|
private _interval;
|
4
5
|
private readonly _instances;
|
@@ -18,11 +19,11 @@ export declare class InstanceManager {
|
|
18
19
|
registerInstanceFromSDK(systemId: string, instanceId: string, info: Omit<InstanceInfo, 'systemId' | 'instanceId'>): Promise<InstanceInfo | undefined>;
|
19
20
|
private getHealthUrl;
|
20
21
|
markAsStopped(systemId: string, instanceId: string): Promise<void>;
|
21
|
-
startAllForPlan(systemId: string): Promise<InstanceInfo[]
|
22
|
+
startAllForPlan(systemId: string): Promise<Task<InstanceInfo[]>>;
|
22
23
|
stop(systemId: string, instanceId: string): Promise<void>;
|
23
24
|
private stopInner;
|
24
|
-
stopAllForPlan(systemId: string):
|
25
|
-
start(systemId: string, instanceId: string): Promise<InstanceInfo
|
25
|
+
stopAllForPlan(systemId: string): Task<void>;
|
26
|
+
start(systemId: string, instanceId: string): Promise<InstanceInfo | Task<InstanceInfo>>;
|
26
27
|
/**
|
27
28
|
* Stops an instance but does not remove it from the list of active instances
|
28
29
|
*
|