@codiac.io/codiac-cli 1.3.139 → 1.3.141
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/README.md +1 -1
- package/dist/bootstrapper-for-enterprise-commands.js +4 -1
- package/dist/bootstrapper-for-enterprise-commands.js.map +1 -1
- package/dist/command-base-enterprise.js +6 -3
- package/dist/command-base-enterprise.js.map +1 -1
- package/dist/commands/asset/deploy.js +38 -1
- package/dist/commands/asset/deploy.js.map +1 -1
- package/dist/relay/relay-container.d.ts +33 -46
- package/dist/relay/relay-container.js +317 -533
- package/dist/relay/relay-container.js.map +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -1,604 +1,388 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DEFAULT_IMAGE_TAG = exports.RelayContainer = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const rxjs_1 = require("rxjs");
|
|
6
6
|
const operators_1 = require("rxjs/operators");
|
|
7
7
|
const reqp = require("request-promise");
|
|
8
8
|
const os = require("os");
|
|
9
|
-
const fs = require("fs");
|
|
9
|
+
const fs = require("fs/promises");
|
|
10
10
|
const path = require("path");
|
|
11
|
-
const
|
|
11
|
+
const Nats = require("@nats-io/nats-core");
|
|
12
|
+
const Transport = require("@nats-io/transport-node");
|
|
12
13
|
const inversify_1 = require("inversify");
|
|
13
|
-
const codiac_error_1 = require("@codiac.io/codiac-common/contracts/codiac-error");
|
|
14
|
-
const codiac_common_1 = require("@codiac.io/codiac-common");
|
|
15
|
-
const IBetterLogger_1 = require("@codiac.io/codiac-common/IBetterLogger");
|
|
16
|
-
const cli_tools_1 = require("@codiac.io/cli-tools");
|
|
17
|
-
const INTERFACES_CLI_1 = require("../ops/INTERFACES_CLI");
|
|
18
14
|
const Docker = require("dockerode");
|
|
15
|
+
const codiac_common_1 = require("@codiac.io/codiac-common");
|
|
16
|
+
const ops_1 = require("../ops");
|
|
19
17
|
const entities_1 = require("../ops/entities");
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
// Configuration defaults
|
|
19
|
+
const DEFAULT_CONFIG = {
|
|
20
|
+
IMAGE_NAME: "codiacimages/codiac-relay",
|
|
21
|
+
IMAGE_TAG: "1.6.59",
|
|
22
|
+
CONTAINER_NAME: "codiac-relay",
|
|
23
|
+
HEALTH_CHECK_URL: "http://localhost:5799/heartbeat-json",
|
|
24
|
+
RETRY_TIMEOUT_MINUTES: 1,
|
|
25
|
+
MAX_HEALTH_CHECK_RETRIES: 40,
|
|
26
|
+
HEALTH_CHECK_INTERVAL_MS: 3000,
|
|
27
|
+
EXPOSED_PORTS: {
|
|
28
|
+
"5799/tcp": {},
|
|
29
|
+
"5798/tcp": {},
|
|
30
|
+
"4222/tcp": {},
|
|
31
|
+
"9222/tcp": {},
|
|
32
|
+
},
|
|
33
|
+
PORT_BINDINGS: {
|
|
34
|
+
"5799/tcp": [{ HostPort: "5799" }],
|
|
35
|
+
"5798/tcp": [{ HostPort: "5798" }],
|
|
36
|
+
"4222/tcp": [{ HostPort: "4222" }],
|
|
37
|
+
"9222/tcp": [{ HostPort: "9222" }],
|
|
38
|
+
},
|
|
39
|
+
VOLUMES: { "/root/.codiac": {} },
|
|
40
|
+
BINDS: [`${os.homedir()}/.codiac:/root/.codiac`],
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Manages a single version of a Codiac Relay Docker container, ensuring only the specified version runs.
|
|
44
|
+
*/
|
|
25
45
|
let RelayContainer = class RelayContainer {
|
|
26
46
|
get userMessages() {
|
|
27
|
-
return this.
|
|
28
|
-
}
|
|
29
|
-
get dockerFailed$() {
|
|
30
|
-
return this.dockerFailedSubj.asObservable();
|
|
31
|
-
}
|
|
32
|
-
get docker$() {
|
|
33
|
-
return this.dockerSubj.asObservable();
|
|
34
|
-
}
|
|
35
|
-
get startFailed$() {
|
|
36
|
-
return this.startFailedSubj.asObservable();
|
|
47
|
+
return this.userMessagesSubj.asObservable();
|
|
37
48
|
}
|
|
38
49
|
get ready$() {
|
|
39
50
|
return this.readySubj.pipe((0, operators_1.distinctUntilChanged)());
|
|
40
51
|
}
|
|
41
|
-
constructor(styler, cliEnviro, logger, healthCheckUrl =
|
|
52
|
+
constructor(styler, cliEnviro, logger, healthCheckUrl = DEFAULT_CONFIG.HEALTH_CHECK_URL, retryTimeOut = DEFAULT_CONFIG.RETRY_TIMEOUT_MINUTES, projectRoot, localEntities = false) {
|
|
42
53
|
this.styler = styler;
|
|
43
54
|
this.cliEnviro = cliEnviro;
|
|
44
55
|
this.logger = logger;
|
|
45
|
-
this.healthCheckUrl = healthCheckUrl;
|
|
46
|
-
this.retryTimeOut = retryTimeOut;
|
|
47
56
|
this.projectRoot = projectRoot;
|
|
48
57
|
this.localEntities = localEntities;
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
58
|
+
this.natsClient = new rxjs_1.BehaviorSubject(null);
|
|
59
|
+
this.destroySubj = new rxjs_1.Subject();
|
|
60
|
+
this.userMessagesSubj = new rxjs_1.BehaviorSubject(undefined);
|
|
61
|
+
this.readySubj = new rxjs_1.ReplaySubject(1);
|
|
62
|
+
this.readyFailedSubj = new rxjs_1.Subject();
|
|
63
|
+
this.connectionRefusedCount = new rxjs_1.BehaviorSubject(0);
|
|
52
64
|
this.silent = false;
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
56
|
-
this.MAXTRIESBEFORECONTAINERRESTART = 40; // Equivalent to over 40 seconds for the container to get healthy
|
|
57
|
-
this.isWin = process.platform === "win32";
|
|
58
|
-
// https://github.com/apocas/dockerode/issues/290
|
|
59
|
-
this.socketPath = this.isWin
|
|
60
|
-
? "//./pipe/docker_engine"
|
|
61
|
-
: undefined;
|
|
62
|
-
this._userMessages = new rxjs_1.BehaviorSubject(undefined);
|
|
63
|
-
// private startSubj: Subject<string> = new Subject<string>();
|
|
64
|
-
// private get start$(): Observable<string> {
|
|
65
|
-
// return this.startSubj.asObservable();
|
|
66
|
-
// }
|
|
67
|
-
this.dockerFailedSubj = new rxjs_1.Subject();
|
|
68
|
-
this.dockerSubj = new rxjs_1.Subject();
|
|
69
|
-
// started is based on the container we're trying to start
|
|
70
|
-
this.startFailedSubj = new rxjs_1.Subject();
|
|
71
|
-
this.readySubj = new rxjs_1.ReplaySubject();
|
|
72
|
-
this.promisifyStream = (stream) => new Promise((resolve, reject) => {
|
|
73
|
-
stream.on('data', (d) => this.logger.write(d.toString()));
|
|
74
|
-
stream.on('end', resolve);
|
|
75
|
-
stream.on('error', reject);
|
|
76
|
-
});
|
|
77
|
-
this._cliExec = new cli_tools_1.CliExec(logger);
|
|
78
|
-
this.docker = new Docker();
|
|
79
|
-
this.init();
|
|
65
|
+
this.config = Object.assign(Object.assign({}, DEFAULT_CONFIG), { HEALTH_CHECK_URL: healthCheckUrl, RETRY_TIMEOUT_MINUTES: retryTimeOut });
|
|
66
|
+
this.docker = this.instantiateDocker();
|
|
67
|
+
this.checkDockerAvailability();
|
|
80
68
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
* Does not throw: Logs any encountered errors and continues.
|
|
84
|
-
*/
|
|
85
|
-
createLocalDataFolders() {
|
|
86
|
-
var _a;
|
|
87
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
88
|
-
const folders = [
|
|
89
|
-
"cluster-images",
|
|
90
|
-
"templates",
|
|
91
|
-
"data/db",
|
|
92
|
-
"data/logs"
|
|
93
|
-
];
|
|
94
|
-
for (let folder of folders) {
|
|
95
|
-
try {
|
|
96
|
-
const fqn = path.posix.join(this.cliEnviro.localProgramFolder, folder);
|
|
97
|
-
if (!fs.existsSync(fqn)) {
|
|
98
|
-
yield fs.promises.mkdir(fqn, { recursive: true });
|
|
99
|
-
this.logger.debug("Created local data folder ".concat("[", fqn, "]."));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
this.logger.error("Error creating local data folder ".concat("[", folder, "]: ", (_a = err.message) !== null && _a !== void 0 ? _a : "(no message available)"));
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return;
|
|
107
|
-
});
|
|
69
|
+
instantiateDocker() {
|
|
70
|
+
return new Docker(process.platform === "win32" ? { socketPath: "//./pipe/docker_engine" } : {});
|
|
108
71
|
}
|
|
109
72
|
init() {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// This should hit anytime the image tag changes, which triggers the workflow to rip and replace if its not the same versions
|
|
113
|
-
(0, rxjs_1.of)(this.imageTag)
|
|
114
|
-
.pipe((0, operators_1.distinctUntilChanged)()) // i think to be able to change image dynamiclly
|
|
115
|
-
.pipe((0, operators_1.concatMap)(_ => this.versionMismatch())) //check the version mismatch or no version do some work
|
|
116
|
-
.pipe((0, operators_1.concatMap)(versionMismatch => {
|
|
117
|
-
if (versionMismatch) {
|
|
118
|
-
this._userMessages.next(`Version mismatch of the Relay container found. Updating to ${this.imageTag}`);
|
|
119
|
-
return this.stop()
|
|
120
|
-
.pipe((0, operators_1.concatMap)(_ => this.remove()))
|
|
121
|
-
.pipe((0, operators_1.concatMap)(_ => this.deleteRelayImage()))
|
|
122
|
-
.pipe((0, operators_1.concatMap)(_ => this.pullImage()));
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
// The api's may already be running. Let's see.
|
|
126
|
-
return (0, rxjs_1.of)("no work was done");
|
|
127
|
-
}
|
|
128
|
-
}))
|
|
129
|
-
.subscribe(_ => this.healthCheck());
|
|
130
|
-
// If we find docker is not started, we put ourselves into a loop, asking the user to kick it on
|
|
131
|
-
this.dockerFailed$
|
|
132
|
-
.pipe((0, operators_1.delay)(10000))
|
|
133
|
-
.pipe((0, operators_1.tap)(_ => {
|
|
134
|
-
this.logger.debug("Attempting to get service again");
|
|
135
|
-
this.getDocker();
|
|
136
|
-
}))
|
|
137
|
-
.subscribe();
|
|
138
|
-
// If docker is running but the api's are not, let's try to start the container optimistically
|
|
139
|
-
(0, rxjs_1.combineLatest)([this.docker$, this.readyFailed$])
|
|
140
|
-
.pipe((0, operators_1.tap)(docker => {
|
|
141
|
-
this.execStart();
|
|
142
|
-
}))
|
|
143
|
-
.pipe((0, operators_1.takeUntil)(this.ready$))
|
|
73
|
+
(0, rxjs_1.of)(`${this.config.IMAGE_NAME}:${this.config.IMAGE_TAG}`)
|
|
74
|
+
.pipe((0, operators_1.distinctUntilChanged)(), (0, operators_1.concatMap)(() => this.handleVersionMismatch()), (0, operators_1.takeUntil)(this.destroySubj))
|
|
144
75
|
.subscribe();
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
.pipe((0, operators_1.
|
|
148
|
-
this.createContainer();
|
|
149
|
-
}))
|
|
150
|
-
.pipe((0, operators_1.takeUntil)(this.ready$))
|
|
76
|
+
this.readyFailedSubj
|
|
77
|
+
.pipe((0, operators_1.tap)(() => this.logNotice(this.styler.hilite("Starting Services..."))), (0, operators_1.concatMap)(() => (0, rxjs_1.interval)(this.config.HEALTH_CHECK_INTERVAL_MS)
|
|
78
|
+
.pipe((0, operators_1.timeout)(this.config.RETRY_TIMEOUT_MINUTES * 60000), (0, operators_1.take)(this.config.MAX_HEALTH_CHECK_RETRIES), (0, operators_1.takeUntil)(this.ready$), (0, operators_1.takeUntil)(this.destroySubj), (0, operators_1.concatMap)(() => this.performHealthCheck()))))
|
|
151
79
|
.subscribe();
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
80
|
+
}
|
|
81
|
+
logDebug(message) {
|
|
82
|
+
this.logger.debug(message);
|
|
83
|
+
}
|
|
84
|
+
logNotice(message) {
|
|
85
|
+
this.logger.notice(message);
|
|
86
|
+
}
|
|
87
|
+
createLocalDataFolders() {
|
|
88
|
+
if (!this.localEntities)
|
|
89
|
+
return (0, rxjs_1.of)(true);
|
|
90
|
+
const folders = ["cluster-images", "templates", "data/db", "data/logs"];
|
|
91
|
+
return (0, rxjs_1.from)(Promise.all(folders.map((folder) => fs.mkdir(path.posix.join(this.cliEnviro.localProgramFolder, folder), { recursive: true })
|
|
92
|
+
.then(() => this.logDebug(`Created local data folder [${folder}]`))
|
|
93
|
+
.catch((err) => {
|
|
94
|
+
this.logger.error(`Error creating local data folder [${folder}]: ${err.message}`);
|
|
95
|
+
throw err;
|
|
96
|
+
})))).pipe((0, operators_1.map)(() => true), (0, operators_1.catchError)(() => (0, rxjs_1.of)(false)));
|
|
97
|
+
}
|
|
98
|
+
checkDockerAvailability() {
|
|
99
|
+
(0, rxjs_1.from)(this.docker.info())
|
|
158
100
|
.pipe((0, operators_1.tap)(() => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
101
|
+
this.logDebug("Docker daemon is available");
|
|
102
|
+
this.init();
|
|
103
|
+
}), (0, operators_1.catchError)((err) => {
|
|
104
|
+
const msg = "Can you start Docker for me?";
|
|
105
|
+
this.logger.error(msg, err);
|
|
106
|
+
this.userMessagesSubj.next(msg);
|
|
107
|
+
return (0, rxjs_1.of)(null).pipe((0, operators_1.delay)(6000), (0, operators_1.tap)(() => {
|
|
108
|
+
this.docker = this.instantiateDocker();
|
|
109
|
+
this.checkDockerAvailability();
|
|
110
|
+
}));
|
|
111
|
+
}), (0, operators_1.takeUntil)(this.destroySubj))
|
|
166
112
|
.subscribe();
|
|
167
113
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
if (stdout == undefined && stdout == "")
|
|
177
|
-
output.next(undefined);
|
|
178
|
-
else {
|
|
179
|
-
const listedContainers = stdout.split("\n");
|
|
180
|
-
let containerIds = [];
|
|
181
|
-
listedContainers.forEach(r => {
|
|
182
|
-
if (r.split(" ")[1].includes(this.imageName))
|
|
183
|
-
containerIds.push(r.split(" ")[0]);
|
|
184
|
-
});
|
|
185
|
-
output.next(containerIds);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
catch (parseError) {
|
|
189
|
-
this.logger.error(`getRelayImageFromDockerPS - Error parsing Docker output: ${parseError}`);
|
|
190
|
-
return parseError;
|
|
191
|
-
}
|
|
192
|
-
})
|
|
193
|
-
.catch(error => {
|
|
194
|
-
this.logger.debug(`getRelayImageFromDockerPS - Command failed: docker ps -a | grep -v ID`);
|
|
195
|
-
output.next(undefined);
|
|
196
|
-
});
|
|
197
|
-
return output.asObservable();
|
|
114
|
+
getRunningContainers() {
|
|
115
|
+
return (0, rxjs_1.from)(this.docker.listContainers({ all: true })).pipe((0, operators_1.map)((containers) => containers.filter((c) => c.Image.includes(this.config.IMAGE_NAME) && c.State === "running")), (0, operators_1.concatMap)((matching) => matching.length === 0
|
|
116
|
+
? (0, rxjs_1.of)([])
|
|
117
|
+
: (0, rxjs_1.from)(Promise.all(matching.map((c) => this.docker.getContainer(c.Id).inspect())))), (0, operators_1.catchError)((err) => {
|
|
118
|
+
this.logger.error(`Failed to list containers: ${err.message}`);
|
|
119
|
+
return (0, rxjs_1.of)([]);
|
|
120
|
+
}));
|
|
198
121
|
}
|
|
199
|
-
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// Split the output into lines and parse each line as JSON
|
|
206
|
-
try {
|
|
207
|
-
if (stdout == undefined && stdout == "")
|
|
208
|
-
output.next(undefined);
|
|
209
|
-
else {
|
|
210
|
-
const listedContainers = stdout.split("\n");
|
|
211
|
-
const relayImangeName = listedContainers.find(r => {
|
|
212
|
-
const name = r.split(" ")[1].includes(this.imageName);
|
|
213
|
-
if (name)
|
|
214
|
-
return name;
|
|
215
|
-
});
|
|
216
|
-
if (relayImangeName != undefined && relayImangeName != "") {
|
|
217
|
-
output.next(relayImangeName.split(" ")[1]);
|
|
218
|
-
}
|
|
219
|
-
else
|
|
220
|
-
output.next(undefined);
|
|
221
|
-
}
|
|
122
|
+
handleVersionMismatch() {
|
|
123
|
+
const imageRef = `${this.config.IMAGE_NAME}:${this.config.IMAGE_TAG}`;
|
|
124
|
+
return this.getRunningContainers().pipe((0, operators_1.concatMap)((containers) => {
|
|
125
|
+
if (containers.length === 0) {
|
|
126
|
+
this.logDebug("No running containers found");
|
|
127
|
+
return this.startContainer();
|
|
222
128
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
129
|
+
const mismatchChecks = containers.map((c) => {
|
|
130
|
+
const imageName = c.Image;
|
|
131
|
+
if (imageName.startsWith("sha256:")) {
|
|
132
|
+
return (0, rxjs_1.from)(this.docker.getImage(imageName).inspect()).pipe((0, operators_1.map)((info) => !(info.RepoTags || []).includes(imageRef)), (0, operators_1.catchError)((err) => {
|
|
133
|
+
this.logger.error(`Failed to inspect image ${imageName}: ${err.message}`);
|
|
134
|
+
return (0, rxjs_1.of)(true);
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
return (0, rxjs_1.of)(!imageName.includes(this.config.IMAGE_TAG));
|
|
138
|
+
});
|
|
139
|
+
return (0, rxjs_1.forkJoin)(mismatchChecks).pipe((0, operators_1.map)((results) => results.some((hasMismatch) => hasMismatch)), (0, operators_1.concatMap)((hasMismatch) => {
|
|
140
|
+
if (!hasMismatch) {
|
|
141
|
+
this.logDebug(`Container version matches ${imageRef}`);
|
|
142
|
+
return this.performHealthCheck();
|
|
143
|
+
}
|
|
144
|
+
this.userMessagesSubj.next(`Version mismatch detected. Updating to ${imageRef}`);
|
|
145
|
+
return this.stopAndRemoveContainers().pipe((0, operators_1.concatMap)(() => this.deleteMismatchedImages()), (0, operators_1.concatMap)(() => this.pullImage()), (0, operators_1.concatMap)(() => this.startContainer()));
|
|
146
|
+
}));
|
|
147
|
+
}));
|
|
233
148
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const command = `docker inspect ${running}`;
|
|
240
|
-
this._cliExec.execAsyncStdOut(command, { cwd: this.projectRoot }, IBetterLogger_1.LogLevel.debug, true)
|
|
241
|
-
.then((stdout) => {
|
|
242
|
-
// Split the output into lines and parse each line as JSON
|
|
243
|
-
try {
|
|
244
|
-
if (stdout != undefined && stdout != "") {
|
|
245
|
-
const images = JSON.parse(stdout);
|
|
246
|
-
output.next(images);
|
|
247
|
-
}
|
|
248
|
-
else
|
|
249
|
-
output.next(undefined);
|
|
250
|
-
}
|
|
251
|
-
catch (parseError) {
|
|
252
|
-
this.logger.error(`Error getting running containers: ${parseError}`);
|
|
253
|
-
output.next(undefined);
|
|
254
|
-
}
|
|
255
|
-
})
|
|
256
|
-
.catch(error => {
|
|
257
|
-
this.logger.debug(`getRunningContainers - ${error.message}`);
|
|
258
|
-
output.next(undefined);
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
this.logger.debug(`getRunningContainers - No running containers found.`);
|
|
263
|
-
return (0, rxjs_1.of)(undefined);
|
|
149
|
+
stopAndRemoveContainers() {
|
|
150
|
+
return this.getRunningContainers().pipe((0, operators_1.concatMap)((containers) => {
|
|
151
|
+
if (containers.length === 0) {
|
|
152
|
+
this.logDebug("No containers to stop or remove");
|
|
153
|
+
return (0, rxjs_1.of)(false);
|
|
264
154
|
}
|
|
265
|
-
return
|
|
155
|
+
return (0, rxjs_1.from)(Promise.all(containers.map((c) => this.docker.getContainer(c.Id).stop().catch((err) => {
|
|
156
|
+
if (err.statusCode !== 404)
|
|
157
|
+
throw err;
|
|
158
|
+
})))).pipe((0, operators_1.concatMap)(() => (0, rxjs_1.from)(Promise.all(containers.map((c) => this.docker.getContainer(c.Id).remove({ force: true }).catch((err) => {
|
|
159
|
+
if (err.statusCode !== 404)
|
|
160
|
+
throw err;
|
|
161
|
+
}))))), (0, operators_1.tap)(() => this.logDebug("All containers stopped and removed")), (0, operators_1.map)(() => true), (0, operators_1.catchError)((err) => {
|
|
162
|
+
this.logger.error(`Failed to stop/remove containers: ${err.message}`);
|
|
163
|
+
return (0, rxjs_1.of)(false);
|
|
164
|
+
}));
|
|
266
165
|
}));
|
|
267
166
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
return this.
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
167
|
+
deleteMismatchedImages() {
|
|
168
|
+
const imageRef = `${this.config.IMAGE_NAME}:${this.config.IMAGE_TAG}`;
|
|
169
|
+
return (0, rxjs_1.from)(this.docker.listImages()).pipe((0, operators_1.map)((images) => images
|
|
170
|
+
.filter((img) => img.RepoTags &&
|
|
171
|
+
img.RepoTags.some((tag) => tag.includes(this.config.IMAGE_NAME) && tag !== imageRef))
|
|
172
|
+
.map((img) => img.RepoTags[0])), (0, operators_1.concatMap)((imagesToRemove) => {
|
|
173
|
+
if (imagesToRemove.length === 0) {
|
|
174
|
+
this.logDebug("No mismatched images to delete");
|
|
175
|
+
return (0, rxjs_1.of)(false);
|
|
275
176
|
}
|
|
276
|
-
|
|
277
|
-
|
|
177
|
+
return (0, rxjs_1.from)(Promise.all(imagesToRemove.map((tag) => this.docker.getImage(tag).remove()))).pipe((0, operators_1.tap)(() => {
|
|
178
|
+
this.userMessagesSubj.next("Removing extra images complete");
|
|
179
|
+
imagesToRemove.forEach((tag) => this.logDebug(`Removed image ${tag}`));
|
|
180
|
+
}), (0, operators_1.map)(() => true), (0, operators_1.catchError)((err) => {
|
|
181
|
+
this.logger.error(`Failed to delete images: ${err.message}`);
|
|
182
|
+
return (0, rxjs_1.of)(false);
|
|
183
|
+
}));
|
|
278
184
|
}));
|
|
279
185
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
this.
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
.then((fullfulled) => {
|
|
291
|
-
this.logger.debug('pull response', fullfulled);
|
|
292
|
-
this.createContainer();
|
|
293
|
-
output.next('Remove Image complete');
|
|
294
|
-
this._userMessages.next(`Removing extra image(s) complete`);
|
|
295
|
-
})
|
|
296
|
-
.catch(error => {
|
|
297
|
-
this.logger.debug(`Removing Relay image failed.`);
|
|
298
|
-
});
|
|
299
|
-
});
|
|
186
|
+
pullImage() {
|
|
187
|
+
const imageRef = `${this.config.IMAGE_NAME}:${this.config.IMAGE_TAG}`;
|
|
188
|
+
return (0, rxjs_1.from)(this.docker.getImage(imageRef).inspect()).pipe((0, operators_1.tap)(() => {
|
|
189
|
+
this.logDebug(`Image ${imageRef} already exists`);
|
|
190
|
+
this.userMessagesSubj.next(`Image ${imageRef} already exists`);
|
|
191
|
+
}), (0, operators_1.map)(() => true), (0, operators_1.catchError)((err) => {
|
|
192
|
+
if (err.statusCode !== 404) {
|
|
193
|
+
this.logger.error(`Error inspecting image ${imageRef}: ${err.message}`);
|
|
194
|
+
this.userMessagesSubj.next(`Error inspecting image: ${err.message}`);
|
|
195
|
+
return (0, rxjs_1.of)(false);
|
|
300
196
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
197
|
+
this.logNotice(`Fetching image ${imageRef}. This may take a few minutes...`);
|
|
198
|
+
this.userMessagesSubj.next(`Fetching image ${imageRef}...`);
|
|
199
|
+
return (0, rxjs_1.from)(this.docker.pull(imageRef, {})).pipe((0, operators_1.concatMap)((stream) => new rxjs_1.Observable((observer) => {
|
|
200
|
+
this.docker.modem.followProgress(stream, (err) => {
|
|
201
|
+
if (err) {
|
|
202
|
+
this.logger.error(`Failed to pull image ${imageRef}: ${err.message}`);
|
|
203
|
+
this.userMessagesSubj.next(`Fetching failed: ${err.message}`);
|
|
204
|
+
observer.error(err);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
this.logDebug(`Image ${imageRef} pulled successfully`);
|
|
208
|
+
this.userMessagesSubj.next("Relay fetch complete");
|
|
209
|
+
observer.next(true);
|
|
210
|
+
observer.complete();
|
|
211
|
+
}, (progress) => { var _a; return this.userMessagesSubj.next(`Pulling ${(_a = progress.id) !== null && _a !== void 0 ? _a : imageRef} : Layer ${progress.status}`); });
|
|
212
|
+
})), (0, operators_1.catchError)((err) => {
|
|
213
|
+
this.logger.error(`Failed to pull image ${imageRef}: ${err.message}`);
|
|
214
|
+
this.userMessagesSubj.next(`Fetching failed: ${err.message}`);
|
|
215
|
+
return (0, rxjs_1.of)(false);
|
|
216
|
+
}));
|
|
305
217
|
}));
|
|
306
218
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
.
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
219
|
+
performHealthCheck() {
|
|
220
|
+
this.logDebug(`Checking ${this.config.CONTAINER_NAME} health...`);
|
|
221
|
+
return this.config.HEALTH_CHECK_URL.startsWith("http")
|
|
222
|
+
? this.performHttpHealthCheck()
|
|
223
|
+
: this.performNatsHealthCheck();
|
|
224
|
+
}
|
|
225
|
+
performHttpHealthCheck() {
|
|
226
|
+
return (0, rxjs_1.from)(reqp.get(this.config.HEALTH_CHECK_URL)).pipe((0, operators_1.map)(() => {
|
|
227
|
+
this.logger.trace(`${this.config.CONTAINER_NAME} is healthy`);
|
|
228
|
+
this.readySubj.next(true);
|
|
229
|
+
this.connectionRefusedCount.next(0);
|
|
230
|
+
return true;
|
|
231
|
+
}), (0, operators_1.catchError)((err) => {
|
|
232
|
+
var _a;
|
|
233
|
+
if (((_a = err.error) === null || _a === void 0 ? void 0 : _a.code) === "ECONNREFUSED") {
|
|
234
|
+
this.connectionRefusedCount.next(this.connectionRefusedCount.value + 1);
|
|
235
|
+
if (this.connectionRefusedCount.value >= this.config.MAX_HEALTH_CHECK_RETRIES) {
|
|
236
|
+
this.logDebug("Max retries reached, restarting container");
|
|
237
|
+
this.startContainer().pipe((0, operators_1.take)(1)).subscribe();
|
|
238
|
+
this.connectionRefusedCount.next(0);
|
|
318
239
|
}
|
|
319
|
-
else
|
|
320
|
-
output.next(undefined);
|
|
321
|
-
}
|
|
322
|
-
catch (parseError) {
|
|
323
|
-
this.logger.error(`Error getting relay image: ${parseError}`);
|
|
324
|
-
return parseError;
|
|
325
240
|
}
|
|
326
|
-
|
|
327
|
-
.
|
|
328
|
-
|
|
329
|
-
});
|
|
330
|
-
return output.asObservable();
|
|
241
|
+
this.logDebug(`Health check failed: ${err.message}`);
|
|
242
|
+
this.readyFailedSubj.next();
|
|
243
|
+
return (0, rxjs_1.of)(false);
|
|
244
|
+
}));
|
|
331
245
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
.then((stdout) => {
|
|
337
|
-
// Split the output into lines and parse each line as JSON
|
|
338
|
-
try {
|
|
339
|
-
output.next(undefined);
|
|
246
|
+
performNatsHealthCheck() {
|
|
247
|
+
return (0, rxjs_1.from)((() => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
248
|
+
if (!this.natsClient.value || this.natsClient.value.isClosed()) {
|
|
249
|
+
this.natsClient.next(yield Transport.connect({ servers: this.config.HEALTH_CHECK_URL }));
|
|
340
250
|
}
|
|
341
|
-
|
|
342
|
-
|
|
251
|
+
return this.natsClient.value.request("dmz.get.heartbeat-json", Nats.Empty, { timeout: 2000 });
|
|
252
|
+
}))()).pipe((0, operators_1.map)(() => {
|
|
253
|
+
this.logger.trace(`${this.config.CONTAINER_NAME} NATS heartbeat received`);
|
|
254
|
+
this.readySubj.next(true);
|
|
255
|
+
this.connectionRefusedCount.next(0);
|
|
256
|
+
return true;
|
|
257
|
+
}), (0, operators_1.catchError)((err) => {
|
|
258
|
+
this.connectionRefusedCount.next(this.connectionRefusedCount.value + 1);
|
|
259
|
+
if (this.connectionRefusedCount.value >= this.config.MAX_HEALTH_CHECK_RETRIES) {
|
|
260
|
+
this.logDebug("Max retries reached, restarting container");
|
|
261
|
+
this.startContainer().pipe((0, operators_1.take)(1)).subscribe();
|
|
262
|
+
this.connectionRefusedCount.next(0);
|
|
343
263
|
}
|
|
344
|
-
|
|
345
|
-
.
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
var _a, _b;
|
|
353
|
-
try {
|
|
354
|
-
this.logger.debug(`healthCheck - Checking ${this.containerName} health now...`);
|
|
355
|
-
reqp.get(this.healthCheckUrl)
|
|
356
|
-
.then(response => {
|
|
357
|
-
this.logger.trace(`healthCheck - ...${this.containerName} ready.`);
|
|
358
|
-
// this.watchLogs();
|
|
359
|
-
this.readySubj.next(true);
|
|
360
|
-
})
|
|
361
|
-
.catch(error => {
|
|
362
|
-
var _a, _b;
|
|
363
|
-
// Sometimes the relay container hangs and the heartbeat is never reachable.
|
|
364
|
-
// Since we're pinging it every second, let's simply give up and restart the container after bunch of tries
|
|
365
|
-
if (error.error.code == "ECONNREFUSED") {
|
|
366
|
-
this.connectionRefusedCount = this.connectionRefusedCount + 1;
|
|
367
|
-
if (this.connectionRefusedCount > this.MAXTRIESBEFORECONTAINERRESTART) {
|
|
368
|
-
this.createContainer().pipe((0, operators_1.take)(1)).subscribe();
|
|
369
|
-
this.connectionRefusedCount = 0;
|
|
370
|
-
}
|
|
264
|
+
this.logDebug(`NATS health check failed: ${err.message}`);
|
|
265
|
+
this.readyFailedSubj.next();
|
|
266
|
+
return (0, rxjs_1.of)(false);
|
|
267
|
+
}), (0, operators_1.tap)({
|
|
268
|
+
complete: () => {
|
|
269
|
+
if (this.natsClient.value && !this.natsClient.value.isClosed()) {
|
|
270
|
+
this.natsClient.value.close().catch((err) => this.logger.error(`Failed to close NATS client: ${err.message}`));
|
|
271
|
+
this.natsClient.next(null);
|
|
371
272
|
}
|
|
372
|
-
this.logger.debug(`healthCheck - ...${this.containerName} failed to respond (${(_a = error.name) !== null && _a !== void 0 ? _a : ""} ${(_b = error.message) !== null && _b !== void 0 ? _b : ""})`);
|
|
373
|
-
this.readyFailed$.next();
|
|
374
|
-
// this.startSubj.next(this.containerName);
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
catch (error) {
|
|
378
|
-
this.logger.debug(`healthCheck failed (${(_a = error.name) !== null && _a !== void 0 ? _a : ""} ${(_b = error.message) !== null && _b !== void 0 ? _b : ""})`, JSON.stringify(error, null, 2));
|
|
379
|
-
this.readyFailed$.next();
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
stop() {
|
|
383
|
-
// fire off this command in a separate cli window
|
|
384
|
-
let cmdStop = `docker stop ${this.containerName}`;
|
|
385
|
-
let result$ = new rxjs_1.Subject();
|
|
386
|
-
result$.subscribe();
|
|
387
|
-
let options = {
|
|
388
|
-
cwd: this.projectRoot,
|
|
389
|
-
// stdio: "inherit",
|
|
390
|
-
// stdio: [process.stdin, process.stdout, process.stderr, process.st], // TODO: Capture stderr instead
|
|
391
|
-
shell: true
|
|
392
|
-
};
|
|
393
|
-
const ls = (0, child_process_1.spawn)(cmdStop, options);
|
|
394
|
-
// ls.stdout?.on('data', (data: any) => {
|
|
395
|
-
// result$.next(true);
|
|
396
|
-
// });
|
|
397
|
-
// ls.stdout?.on('error', (data: any) => {
|
|
398
|
-
// result$.next(false);
|
|
399
|
-
// });
|
|
400
|
-
// ls.on('error', (data: any) => {
|
|
401
|
-
// result$.next(false);
|
|
402
|
-
// });
|
|
403
|
-
ls.on('close', (data) => {
|
|
404
|
-
result$.next(false);
|
|
405
|
-
});
|
|
406
|
-
return result$.asObservable();
|
|
407
|
-
}
|
|
408
|
-
remove() {
|
|
409
|
-
// fire off this command in a separate cli window
|
|
410
|
-
this.getAllContainersOfRelayImage().pipe((0, operators_1.map)(response => {
|
|
411
|
-
if (response && response.length > 0) {
|
|
412
|
-
response.forEach(containerId => {
|
|
413
|
-
let cmdStop = `docker rm ${containerId} -f`;
|
|
414
|
-
let options = {
|
|
415
|
-
cwd: this.projectRoot,
|
|
416
|
-
shell: true
|
|
417
|
-
};
|
|
418
|
-
const ls = (0, child_process_1.spawn)(cmdStop, options);
|
|
419
|
-
ls.on('close', (data) => {
|
|
420
|
-
result$.next(false);
|
|
421
|
-
});
|
|
422
|
-
});
|
|
423
273
|
}
|
|
424
|
-
}))
|
|
425
|
-
.subscribe();
|
|
426
|
-
let result$ = new rxjs_1.Subject();
|
|
427
|
-
result$.subscribe();
|
|
428
|
-
return result$.asObservable();
|
|
274
|
+
}));
|
|
429
275
|
}
|
|
430
|
-
|
|
431
|
-
|
|
276
|
+
startContainer() {
|
|
277
|
+
return this.createLocalDataFolders().pipe((0, operators_1.concatMap)(() => this.pullImage()), (0, operators_1.concatMap)(() => this.createContainer()), (0, operators_1.concatMap)(() => this.startContainerInternal()), (0, operators_1.catchError)((err) => {
|
|
278
|
+
this.logger.error(`Failed to start container: ${err.message}`);
|
|
279
|
+
this.userMessagesSubj.next(`Failed to start container: ${err.message}`);
|
|
280
|
+
return (0, rxjs_1.of)(false);
|
|
281
|
+
}));
|
|
432
282
|
}
|
|
433
283
|
createContainer() {
|
|
434
|
-
var _a
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
ExposedPorts: {
|
|
441
|
-
"5799/tcp": {},
|
|
442
|
-
"5798/tcp": {},
|
|
443
|
-
"4222/tcp": {},
|
|
444
|
-
"9222/tcp": {}
|
|
445
|
-
},
|
|
284
|
+
var _a;
|
|
285
|
+
const containerConfig = {
|
|
286
|
+
Image: `${this.config.IMAGE_NAME}:${this.config.IMAGE_TAG}`,
|
|
287
|
+
name: this.config.CONTAINER_NAME,
|
|
288
|
+
Hostname: this.config.CONTAINER_NAME,
|
|
289
|
+
ExposedPorts: Object.assign({}, DEFAULT_CONFIG.EXPOSED_PORTS),
|
|
446
290
|
HostConfig: {
|
|
447
|
-
Binds: [
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
// `${os.homedir}/.azure:/root/.azure`
|
|
451
|
-
],
|
|
452
|
-
PortBindings: {
|
|
453
|
-
"5799/tcp": [
|
|
454
|
-
{
|
|
455
|
-
HostPort: "5799"
|
|
456
|
-
}
|
|
457
|
-
],
|
|
458
|
-
"5798/tcp": [
|
|
459
|
-
{
|
|
460
|
-
HostPort: "5798"
|
|
461
|
-
}
|
|
462
|
-
],
|
|
463
|
-
"4222/tcp": [
|
|
464
|
-
{
|
|
465
|
-
HostPort: "4222"
|
|
466
|
-
}
|
|
467
|
-
],
|
|
468
|
-
"9222/tcp": [
|
|
469
|
-
{
|
|
470
|
-
HostPort: "9222"
|
|
471
|
-
}
|
|
472
|
-
]
|
|
473
|
-
},
|
|
474
|
-
RestartPolicy: {
|
|
475
|
-
Name: "unless-stopped"
|
|
476
|
-
}
|
|
291
|
+
Binds: [...DEFAULT_CONFIG.BINDS],
|
|
292
|
+
PortBindings: Object.assign({}, DEFAULT_CONFIG.PORT_BINDINGS),
|
|
293
|
+
RestartPolicy: { Name: "unless-stopped" },
|
|
477
294
|
},
|
|
478
|
-
Volumes: {
|
|
479
|
-
|
|
480
|
-
// "/root/.kube": {},
|
|
481
|
-
// "/root/.azure": {}
|
|
482
|
-
},
|
|
483
|
-
Env: [
|
|
484
|
-
"HOST_PLATFORM=".concat(process.platform)
|
|
485
|
-
]
|
|
295
|
+
Volumes: Object.assign({}, DEFAULT_CONFIG.VOLUMES),
|
|
296
|
+
Env: [`HOST_PLATFORM=${process.platform}`],
|
|
486
297
|
};
|
|
487
|
-
if (this.localEntities
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
(_a =
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
container.Entrypoint = ["./start-relay-w-nats-and-local-entities.sh"];
|
|
298
|
+
if (this.localEntities) {
|
|
299
|
+
containerConfig.ExposedPorts["27017/tcp"] = {};
|
|
300
|
+
containerConfig.HostConfig.PortBindings["27017/tcp"] = [{ HostPort: "27017" }];
|
|
301
|
+
(_a = containerConfig.HostConfig.Binds) === null || _a === void 0 ? void 0 : _a.push(`${os.homedir()}/.codiac/data/db:/data/db`, `${os.homedir()}/.codiac/data/logs:/data/logs`);
|
|
302
|
+
containerConfig.Volumes["/data/db"] = {};
|
|
303
|
+
containerConfig.Volumes["/data/logs"] = {};
|
|
304
|
+
containerConfig.Entrypoint = ["./start-relay-w-nats-and-local-entities.sh"];
|
|
495
305
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
this.logger.trace(`createContainer - Created ${this.containerName}`);
|
|
501
|
-
this.execStart();
|
|
502
|
-
})
|
|
503
|
-
.catch(error => {
|
|
504
|
-
if (error.statusCode == 409)
|
|
505
|
-
this.execStart(); //Already in use
|
|
506
|
-
else {
|
|
507
|
-
this.logger.debug(`createContainer - Failed to create ${this.containerName}`, JSON.stringify(error, null, 2));
|
|
508
|
-
this.pullImage();
|
|
306
|
+
return (0, rxjs_1.from)(this.docker.createContainer(containerConfig)).pipe((0, operators_1.tap)(() => this.logDebug(`Created container ${this.config.CONTAINER_NAME}`)), (0, operators_1.map)(() => true), (0, operators_1.catchError)((err) => {
|
|
307
|
+
if (err.statusCode === 409) {
|
|
308
|
+
this.logDebug(`Container ${this.config.CONTAINER_NAME} already exists`);
|
|
309
|
+
return (0, rxjs_1.of)(true);
|
|
509
310
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
return output.asObservable();
|
|
311
|
+
this.logger.error(`Failed to create container: ${err.message}`);
|
|
312
|
+
return this.pullImage();
|
|
313
|
+
}));
|
|
514
314
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
this.
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
315
|
+
startContainerInternal() {
|
|
316
|
+
return (0, rxjs_1.from)(this.docker.getContainer(this.config.CONTAINER_NAME).inspect()).pipe((0, operators_1.concatMap)((info) => {
|
|
317
|
+
if (info.State.Running) {
|
|
318
|
+
this.logDebug(`Container ${this.config.CONTAINER_NAME} is already running`);
|
|
319
|
+
return this.performHealthCheck();
|
|
320
|
+
}
|
|
321
|
+
return (0, rxjs_1.from)(this.docker.getContainer(this.config.CONTAINER_NAME).start()).pipe((0, operators_1.tap)(() => {
|
|
322
|
+
this.logDebug(`Started container ${this.config.CONTAINER_NAME}`);
|
|
323
|
+
this.userMessagesSubj.next("Starting Relay...");
|
|
324
|
+
this.performHealthCheck().subscribe();
|
|
325
|
+
}), (0, operators_1.map)(() => true));
|
|
326
|
+
}), (0, operators_1.catchError)((err) => {
|
|
327
|
+
if (err.statusCode === 404) {
|
|
328
|
+
this.logDebug(`Container ${this.config.CONTAINER_NAME} not found, creating...`);
|
|
329
|
+
return this.createContainer();
|
|
330
|
+
}
|
|
331
|
+
this.logger.error(`Failed to start container: ${err.message}`);
|
|
332
|
+
return (0, rxjs_1.of)(false);
|
|
333
|
+
}));
|
|
533
334
|
}
|
|
534
|
-
|
|
535
|
-
(0, rxjs_1.
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
this.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
// Hard stop on 20 tries, reboot it
|
|
550
|
-
if (this.serverErrorCount == 20) {
|
|
551
|
-
this.stop()
|
|
552
|
-
.pipe((0, operators_1.map)(x => this.startFailedSubj.next(this.containerName)))
|
|
553
|
-
.pipe((0, operators_1.take)(1))
|
|
554
|
-
.subscribe();
|
|
555
|
-
this.serverErrorCount = 0;
|
|
556
|
-
}
|
|
557
|
-
});
|
|
558
|
-
}))
|
|
559
|
-
.subscribe();
|
|
335
|
+
stop() {
|
|
336
|
+
return (0, rxjs_1.from)(this.docker.getContainer(this.config.CONTAINER_NAME).inspect()).pipe((0, operators_1.concatMap)((info) => {
|
|
337
|
+
if (!info.State.Running) {
|
|
338
|
+
this.logDebug(`Container ${this.config.CONTAINER_NAME} is not running`);
|
|
339
|
+
return (0, rxjs_1.of)(false);
|
|
340
|
+
}
|
|
341
|
+
return (0, rxjs_1.from)(this.docker.getContainer(this.config.CONTAINER_NAME).stop()).pipe((0, operators_1.tap)(() => this.logDebug(`Stopped container ${this.config.CONTAINER_NAME}`)), (0, operators_1.map)(() => true));
|
|
342
|
+
}), (0, operators_1.catchError)((err) => {
|
|
343
|
+
if (err.statusCode === 404) {
|
|
344
|
+
this.logDebug(`Container ${this.config.CONTAINER_NAME} does not exist`);
|
|
345
|
+
return (0, rxjs_1.of)(false);
|
|
346
|
+
}
|
|
347
|
+
this.logger.error(`Failed to stop container: ${err.message}`);
|
|
348
|
+
return (0, rxjs_1.of)(false);
|
|
349
|
+
}));
|
|
560
350
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
.
|
|
569
|
-
|
|
570
|
-
});
|
|
351
|
+
remove() {
|
|
352
|
+
return this.stop().pipe((0, operators_1.concatMap)(() => (0, rxjs_1.from)(this.docker.getContainer(this.config.CONTAINER_NAME).remove({ force: true })).pipe((0, operators_1.tap)(() => this.logDebug(`Removed container ${this.config.CONTAINER_NAME}`)), (0, operators_1.map)(() => true), (0, operators_1.catchError)((err) => {
|
|
353
|
+
if (err.statusCode === 404) {
|
|
354
|
+
this.logDebug(`Container ${this.config.CONTAINER_NAME} does not exist`);
|
|
355
|
+
return (0, rxjs_1.of)(false);
|
|
356
|
+
}
|
|
357
|
+
this.logger.error(`Failed to remove container: ${err.message}`);
|
|
358
|
+
return (0, rxjs_1.of)(false);
|
|
359
|
+
}))));
|
|
571
360
|
}
|
|
572
|
-
|
|
573
|
-
this.
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
this.
|
|
581
|
-
this.
|
|
582
|
-
this.
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
this._userMessages.next(msg);
|
|
590
|
-
this.dockerFailedSubj.next();
|
|
591
|
-
return (0, rxjs_1.of)(this.docker);
|
|
592
|
-
}))
|
|
593
|
-
.pipe((0, operators_1.take)(1))
|
|
594
|
-
.subscribe();
|
|
361
|
+
destroy() {
|
|
362
|
+
return this.stop().pipe((0, operators_1.concatMap)(() => this.remove()), (0, operators_1.tap)(() => {
|
|
363
|
+
if (this.natsClient.value && !this.natsClient.value.isClosed()) {
|
|
364
|
+
this.natsClient.value.close().catch((err) => this.logger.error(`Failed to close NATS client: ${err.message}`));
|
|
365
|
+
this.natsClient.next(null);
|
|
366
|
+
}
|
|
367
|
+
this.destroySubj.next();
|
|
368
|
+
this.destroySubj.complete();
|
|
369
|
+
this.readySubj.complete();
|
|
370
|
+
this.readyFailedSubj.complete();
|
|
371
|
+
this.userMessagesSubj.complete();
|
|
372
|
+
this.connectionRefusedCount.complete();
|
|
373
|
+
this.logDebug("RelayContainer destroyed");
|
|
374
|
+
}), (0, operators_1.map)(() => true), (0, operators_1.catchError)((err) => {
|
|
375
|
+
this.logger.error(`Failed to destroy RelayContainer: ${err.message}`);
|
|
376
|
+
return (0, rxjs_1.of)(false);
|
|
377
|
+
}));
|
|
595
378
|
}
|
|
596
379
|
};
|
|
597
380
|
RelayContainer = tslib_1.__decorate([
|
|
598
|
-
tslib_1.__param(0, (0, inversify_1.inject)(
|
|
381
|
+
tslib_1.__param(0, (0, inversify_1.inject)(ops_1.INTERFACES_CLI.IOutputStyler)),
|
|
599
382
|
tslib_1.__param(1, (0, inversify_1.inject)(entities_1.CliEnviro)),
|
|
600
383
|
tslib_1.__param(2, (0, inversify_1.inject)(codiac_common_1.INTERFACES.IBetterLogger)),
|
|
601
384
|
tslib_1.__metadata("design:paramtypes", [Object, entities_1.CliEnviro, Object, String, Number, String, Boolean])
|
|
602
385
|
], RelayContainer);
|
|
603
386
|
exports.RelayContainer = RelayContainer;
|
|
387
|
+
exports.DEFAULT_IMAGE_TAG = DEFAULT_CONFIG.IMAGE_TAG;
|
|
604
388
|
//# sourceMappingURL=relay-container.js.map
|