navy 6.0.0 → 7.0.0-alpha.1
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/lib/__tests__/config-provider.js +75 -0
- package/lib/__tests__/config.js +130 -0
- package/lib/__tests__/driver-logging.js +148 -0
- package/lib/__tests__/driver.js +19 -0
- package/lib/__tests__/errors.js +49 -0
- package/lib/__tests__/http-proxy.js +214 -0
- package/lib/__tests__/index.js +25 -0
- package/lib/__tests__/service.js +16 -0
- package/lib/cli/__tests__/develop.js +239 -0
- package/lib/cli/__tests__/external-ip.js +68 -0
- package/lib/cli/__tests__/health.js +257 -0
- package/lib/cli/__tests__/https.js +210 -0
- package/lib/cli/__tests__/import.js +110 -0
- package/lib/cli/__tests__/index.js +118 -0
- package/lib/cli/__tests__/lan-ip.js +90 -0
- package/lib/cli/__tests__/launch.js +179 -0
- package/lib/cli/__tests__/live.js +155 -0
- package/lib/cli/__tests__/local-ip.js +72 -0
- package/lib/cli/__tests__/logs.js +52 -0
- package/lib/cli/__tests__/open.js +65 -0
- package/lib/cli/__tests__/program.js +454 -0
- package/lib/cli/__tests__/ps.js +345 -0
- package/lib/cli/__tests__/refresh-config.js +95 -0
- package/lib/cli/__tests__/run.js +54 -0
- package/lib/cli/__tests__/status.js +204 -0
- package/lib/cli/__tests__/updates.js +243 -0
- package/lib/cli/__tests__/wait-for-healthy.js +134 -0
- package/lib/cli/config/__tests__/index.js +275 -0
- package/lib/cli/config/__tests__/wrapper.js +53 -0
- package/lib/cli/config/index.js +19 -37
- package/lib/cli/config/wrapper.js +0 -6
- package/lib/cli/develop.js +7 -21
- package/lib/cli/doctor/__tests__/clean-compose-files.js +78 -0
- package/lib/cli/doctor/__tests__/index.js +67 -0
- package/lib/cli/doctor/__tests__/invalid-compose-config.js +103 -0
- package/lib/cli/doctor/__tests__/invalid-state.js +83 -0
- package/lib/cli/doctor/__tests__/util.js +91 -0
- package/lib/cli/doctor/clean-compose-files.js +5 -13
- package/lib/cli/doctor/index.js +0 -12
- package/lib/cli/doctor/invalid-compose-config.js +0 -4
- package/lib/cli/doctor/invalid-state.js +0 -6
- package/lib/cli/doctor/util.js +0 -10
- package/lib/cli/external-ip.js +0 -4
- package/lib/cli/health.js +0 -12
- package/lib/cli/https.js +9 -25
- package/lib/cli/import.js +0 -12
- package/lib/cli/index.js +0 -9
- package/lib/cli/lan-ip.js +2 -8
- package/lib/cli/launch.js +0 -9
- package/lib/cli/live.js +6 -16
- package/lib/cli/local-ip.js +2 -7
- package/lib/cli/logs.js +0 -3
- package/lib/cli/open.js +2 -7
- package/lib/cli/program.js +41 -99
- package/lib/cli/ps.js +1 -21
- package/lib/cli/refresh-config.js +0 -7
- package/lib/cli/run.js +0 -3
- package/lib/cli/status.js +0 -11
- package/lib/cli/updates.js +0 -22
- package/lib/cli/util/__tests__/get-or-initialise-navy.js +66 -0
- package/lib/cli/util/__tests__/import.js +123 -0
- package/lib/cli/util/__tests__/index.js +17 -0
- package/lib/cli/util/__tests__/reconfigure.js +78 -0
- package/lib/cli/util/get-or-initialise-navy.js +0 -7
- package/lib/cli/util/import.js +0 -9
- package/lib/cli/util/index.js +0 -2
- package/lib/cli/util/reconfigure.js +0 -4
- package/lib/cli/wait-for-healthy.js +0 -21
- package/lib/client/registry/__tests__/get-credentials.js +62 -0
- package/lib/client/registry/__tests__/get-endpoint.js +124 -0
- package/lib/client/registry/__tests__/get-fat-manifest.js +67 -0
- package/lib/client/registry/__tests__/get-token.js +66 -0
- package/lib/client/registry/__tests__/helpers.js +26 -0
- package/lib/client/registry/get-credentials.js +3 -9
- package/lib/client/registry/get-endpoint.js +29 -63
- package/lib/client/registry/get-fat-manifest.js +2 -9
- package/lib/client/registry/get-token.js +2 -13
- package/lib/client/registry/helpers.js +0 -4
- package/lib/config-provider.js +0 -12
- package/lib/config-providers/filesystem/__tests__/index.js +176 -0
- package/lib/config-providers/filesystem/index.js +5 -23
- package/lib/config-providers/npm/__tests__/index.js +226 -0
- package/lib/config-providers/npm/__tests__/util.js +1 -2
- package/lib/config-providers/npm/index.js +12 -35
- package/lib/config-providers/npm/util.js +0 -3
- package/lib/config.js +4 -19
- package/lib/domain/__tests__/container-image.js +81 -0
- package/lib/domain/__tests__/oci-api-specification.js +23 -0
- package/lib/domain/container-image.js +8 -21
- package/lib/domain/oci-api-specification.js +3 -5
- package/lib/driver-logging.js +0 -19
- package/lib/driver.js +0 -4
- package/lib/drivers/docker-compose/__tests__/client.js +249 -0
- package/lib/drivers/docker-compose/__tests__/index.js +430 -0
- package/lib/drivers/docker-compose/client.js +0 -16
- package/lib/drivers/docker-compose/index.js +7 -49
- package/lib/errors.js +0 -10
- package/lib/http-proxy.js +28 -23
- package/lib/index.js +1 -9
- package/lib/middleware/__tests__/add-service-proxy-config.js +258 -0
- package/lib/middleware/__tests__/develop.js +120 -0
- package/lib/middleware/__tests__/helpers.js +154 -0
- package/lib/middleware/__tests__/port-override.js +125 -0
- package/lib/middleware/__tests__/set-env-vars.js +94 -0
- package/lib/middleware/__tests__/set-image.js +76 -0
- package/lib/middleware/__tests__/set-logging-driver.js +94 -0
- package/lib/middleware/__tests__/tag-override.js +92 -0
- package/lib/middleware/add-service-proxy-config.js +8 -16
- package/lib/middleware/develop.js +2 -5
- package/lib/middleware/helpers.js +6 -12
- package/lib/middleware/port-override.js +5 -8
- package/lib/middleware/set-env-vars.js +6 -6
- package/lib/middleware/set-image.js +4 -5
- package/lib/middleware/set-logging-driver.js +6 -6
- package/lib/middleware/tag-override.js +4 -6
- package/lib/navy/__tests__/default-middleware.js +40 -0
- package/lib/navy/__tests__/index.js +1612 -0
- package/lib/navy/__tests__/middleware.js +71 -0
- package/lib/navy/__tests__/plugin-interface.js +121 -0
- package/lib/navy/__tests__/state.js +103 -0
- package/lib/navy/__tests__/util.js +24 -0
- package/lib/navy/default-middleware.js +0 -10
- package/lib/navy/index.js +83 -138
- package/lib/navy/middleware.js +0 -6
- package/lib/navy/plugin-interface.js +2 -10
- package/lib/navy/state.js +12 -24
- package/lib/navy/util.js +0 -1
- package/lib/service.js +2 -3
- package/lib/util/__tests__/exec-async.js +83 -0
- package/lib/util/__tests__/external-ip.js +97 -2
- package/lib/util/__tests__/get-lan-ip.js +46 -0
- package/lib/util/__tests__/has-update.js +136 -0
- package/lib/util/__tests__/https.js +301 -0
- package/lib/util/__tests__/navyrc.js +45 -0
- package/lib/util/__tests__/service-host.js +63 -5
- package/lib/util/__tests__/table.js +44 -0
- package/lib/util/docker-client.js +2 -10
- package/lib/util/exec-async.js +0 -4
- package/lib/util/external-ip.js +8 -12
- package/lib/util/fs.js +1 -6
- package/lib/util/get-lan-ip.js +0 -5
- package/lib/util/has-update.js +2 -14
- package/lib/util/https.js +11 -55
- package/lib/util/navyrc.js +0 -5
- package/lib/util/service-host.js +0 -17
- package/lib/util/table.js +0 -6
- package/package.json +16 -14
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _chai = require("chai");
|
|
4
|
+
var _service = require("../service");
|
|
5
|
+
/* eslint-env mocha */
|
|
6
|
+
|
|
7
|
+
describe('service', function () {
|
|
8
|
+
describe('Status', function () {
|
|
9
|
+
it('should expose RUNNING and EXITED string constants', function () {
|
|
10
|
+
(0, _chai.expect)(_service.Status).to.eql({
|
|
11
|
+
RUNNING: 'running',
|
|
12
|
+
EXITED: 'exited'
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _chai = require("chai");
|
|
5
|
+
var _sinon = _interopRequireDefault(require("sinon"));
|
|
6
|
+
var _proxyquire = _interopRequireDefault(require("proxyquire"));
|
|
7
|
+
var _errors = require("../../errors");
|
|
8
|
+
/* eslint-env mocha */
|
|
9
|
+
|
|
10
|
+
describe('cli/develop', function () {
|
|
11
|
+
let sandbox;
|
|
12
|
+
let getNavyStub;
|
|
13
|
+
let navyStub;
|
|
14
|
+
let getNavyRcStub;
|
|
15
|
+
let dockerStub;
|
|
16
|
+
let containerObj;
|
|
17
|
+
let consoleLogStub;
|
|
18
|
+
let originalCwd;
|
|
19
|
+
let developCli;
|
|
20
|
+
beforeEach(function () {
|
|
21
|
+
sandbox = _sinon.default.createSandbox();
|
|
22
|
+
navyStub = {
|
|
23
|
+
name: 'env-1',
|
|
24
|
+
getState: sandbox.stub().resolves({}),
|
|
25
|
+
saveState: sandbox.stub().resolves(),
|
|
26
|
+
emitAsync: sandbox.stub().resolves(),
|
|
27
|
+
kill: sandbox.stub().resolves(),
|
|
28
|
+
launch: sandbox.stub().resolves(),
|
|
29
|
+
ps: sandbox.stub().resolves([{
|
|
30
|
+
name: 'web',
|
|
31
|
+
id: 'abc123'
|
|
32
|
+
}])
|
|
33
|
+
};
|
|
34
|
+
getNavyStub = sandbox.stub().returns(navyStub);
|
|
35
|
+
getNavyRcStub = sandbox.stub().resolves({
|
|
36
|
+
services: ['web'],
|
|
37
|
+
develop: {
|
|
38
|
+
mounts: {
|
|
39
|
+
'./src': '/app/src'
|
|
40
|
+
},
|
|
41
|
+
command: 'npm start'
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
containerObj = {
|
|
45
|
+
attach: sandbox.stub().resolves('stream'),
|
|
46
|
+
modem: {
|
|
47
|
+
demuxStream: sandbox.stub()
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
dockerStub = {
|
|
51
|
+
getContainer: sandbox.stub().returns(containerObj)
|
|
52
|
+
};
|
|
53
|
+
consoleLogStub = sandbox.stub(console, 'log');
|
|
54
|
+
originalCwd = process.cwd;
|
|
55
|
+
sandbox.stub(process, 'cwd').returns('/work');
|
|
56
|
+
developCli = _proxyquire.default.noCallThru()('../develop', {
|
|
57
|
+
'../': {
|
|
58
|
+
getNavy: getNavyStub
|
|
59
|
+
},
|
|
60
|
+
'../errors': {
|
|
61
|
+
NavyError: _errors.NavyError
|
|
62
|
+
},
|
|
63
|
+
'../util/docker-client': dockerStub,
|
|
64
|
+
'../util/navyrc': getNavyRcStub
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
afterEach(function () {
|
|
68
|
+
process.cwd = originalCwd;
|
|
69
|
+
sandbox.restore();
|
|
70
|
+
});
|
|
71
|
+
describe('default export', function () {
|
|
72
|
+
it('should throw a NavyError when navyrc is null', async function () {
|
|
73
|
+
getNavyRcStub.resolves(null);
|
|
74
|
+
let caught;
|
|
75
|
+
try {
|
|
76
|
+
await developCli('web', {
|
|
77
|
+
navy: 'env-1'
|
|
78
|
+
});
|
|
79
|
+
} catch (err) {
|
|
80
|
+
caught = err;
|
|
81
|
+
}
|
|
82
|
+
(0, _chai.expect)(caught).to.be.instanceof(_errors.NavyError);
|
|
83
|
+
(0, _chai.expect)(caught.message).to.contain('No valid .navyrc');
|
|
84
|
+
});
|
|
85
|
+
it('should throw a NavyError when navyrc has no services', async function () {
|
|
86
|
+
getNavyRcStub.resolves({
|
|
87
|
+
services: undefined
|
|
88
|
+
});
|
|
89
|
+
let caught;
|
|
90
|
+
try {
|
|
91
|
+
await developCli('web', {
|
|
92
|
+
navy: 'env-1'
|
|
93
|
+
});
|
|
94
|
+
} catch (err) {
|
|
95
|
+
caught = err;
|
|
96
|
+
}
|
|
97
|
+
(0, _chai.expect)(caught).to.be.instanceof(_errors.NavyError);
|
|
98
|
+
});
|
|
99
|
+
it('should throw a NavyError when develop key is missing', async function () {
|
|
100
|
+
getNavyRcStub.resolves({
|
|
101
|
+
services: ['web']
|
|
102
|
+
});
|
|
103
|
+
let caught;
|
|
104
|
+
try {
|
|
105
|
+
await developCli('web', {
|
|
106
|
+
navy: 'env-1'
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
caught = err;
|
|
110
|
+
}
|
|
111
|
+
(0, _chai.expect)(caught).to.be.instanceof(_errors.NavyError);
|
|
112
|
+
(0, _chai.expect)(caught.message).to.contain('No develop mounts');
|
|
113
|
+
});
|
|
114
|
+
it('should throw when multiple services are listed and none specified', async function () {
|
|
115
|
+
getNavyRcStub.resolves({
|
|
116
|
+
services: ['web', 'api'],
|
|
117
|
+
develop: {
|
|
118
|
+
mounts: {},
|
|
119
|
+
command: 'x'
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
let caught;
|
|
123
|
+
try {
|
|
124
|
+
await developCli(undefined, {
|
|
125
|
+
navy: 'env-1'
|
|
126
|
+
});
|
|
127
|
+
} catch (err) {
|
|
128
|
+
caught = err;
|
|
129
|
+
}
|
|
130
|
+
(0, _chai.expect)(caught).to.be.instanceof(_errors.NavyError);
|
|
131
|
+
(0, _chai.expect)(caught.message).to.contain('Multiple service mappings');
|
|
132
|
+
});
|
|
133
|
+
it('should infer the only service when one is listed', async function () {
|
|
134
|
+
await developCli(undefined, {
|
|
135
|
+
navy: 'env-1'
|
|
136
|
+
});
|
|
137
|
+
(0, _chai.expect)(navyStub.kill.calledWith(['web'])).to.equal(true);
|
|
138
|
+
});
|
|
139
|
+
it('should throw when the service is not in the navyrc list', async function () {
|
|
140
|
+
let caught;
|
|
141
|
+
try {
|
|
142
|
+
await developCli('unknown', {
|
|
143
|
+
navy: 'env-1'
|
|
144
|
+
});
|
|
145
|
+
} catch (err) {
|
|
146
|
+
caught = err;
|
|
147
|
+
}
|
|
148
|
+
(0, _chai.expect)(caught).to.be.instanceof(_errors.NavyError);
|
|
149
|
+
(0, _chai.expect)(caught.message).to.contain('not a valid development target');
|
|
150
|
+
});
|
|
151
|
+
it('should resolve mount keys to absolute paths and persist them in state', async function () {
|
|
152
|
+
await developCli('web', {
|
|
153
|
+
navy: 'env-1'
|
|
154
|
+
});
|
|
155
|
+
(0, _chai.expect)(navyStub.saveState.calledOnce).to.equal(true);
|
|
156
|
+
const newState = navyStub.saveState.firstCall.args[0];
|
|
157
|
+
const mountKeys = Object.keys(newState.services.web._develop.mounts);
|
|
158
|
+
(0, _chai.expect)(mountKeys[0].endsWith('src')).to.equal(true);
|
|
159
|
+
(0, _chai.expect)(newState.services.web._develop.command).to.equal('npm start');
|
|
160
|
+
});
|
|
161
|
+
it('should preserve existing state.services entries on save', async function () {
|
|
162
|
+
navyStub.getState.resolves({
|
|
163
|
+
services: {
|
|
164
|
+
api: {
|
|
165
|
+
_tag: 'v1'
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
await developCli('web', {
|
|
170
|
+
navy: 'env-1'
|
|
171
|
+
});
|
|
172
|
+
const newState = navyStub.saveState.firstCall.args[0];
|
|
173
|
+
(0, _chai.expect)(newState.services.api).to.eql({
|
|
174
|
+
_tag: 'v1'
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
it('should default to {} when navy.getState returns null', async function () {
|
|
178
|
+
navyStub.getState.resolves(null);
|
|
179
|
+
await developCli('web', {
|
|
180
|
+
navy: 'env-1'
|
|
181
|
+
});
|
|
182
|
+
const newState = navyStub.saveState.firstCall.args[0];
|
|
183
|
+
// eslint-disable-next-line no-unused-expressions
|
|
184
|
+
(0, _chai.expect)(newState.services.web._develop).to.exist;
|
|
185
|
+
});
|
|
186
|
+
it('should kill, then launch the service in develop mode', async function () {
|
|
187
|
+
await developCli('web', {
|
|
188
|
+
navy: 'env-1'
|
|
189
|
+
});
|
|
190
|
+
(0, _chai.expect)(navyStub.emitAsync.calledWith('cli.develop.beforeLaunch')).to.equal(true);
|
|
191
|
+
(0, _chai.expect)(navyStub.kill.calledOnce).to.equal(true);
|
|
192
|
+
(0, _chai.expect)(navyStub.launch.calledOnce).to.equal(true);
|
|
193
|
+
(0, _chai.expect)(navyStub.launch.firstCall.args[0]).to.eql(['web']);
|
|
194
|
+
(0, _chai.expect)(navyStub.launch.firstCall.args[1]).to.eql({
|
|
195
|
+
noDeps: true
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
it('should attach to the container and demux the stream', async function () {
|
|
199
|
+
await developCli('web', {
|
|
200
|
+
navy: 'env-1'
|
|
201
|
+
});
|
|
202
|
+
(0, _chai.expect)(dockerStub.getContainer.calledWith('abc123')).to.equal(true);
|
|
203
|
+
(0, _chai.expect)(containerObj.attach.calledOnce).to.equal(true);
|
|
204
|
+
|
|
205
|
+
// Wait for the .then callback to fire on the attach promise
|
|
206
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
207
|
+
(0, _chai.expect)(containerObj.modem.demuxStream.calledOnce).to.equal(true);
|
|
208
|
+
(0, _chai.expect)(containerObj.modem.demuxStream.firstCall.args[0]).to.equal('stream');
|
|
209
|
+
});
|
|
210
|
+
it('should log a graceful exit message when attach rejects', async function () {
|
|
211
|
+
containerObj.attach.rejects(new Error('attach failed'));
|
|
212
|
+
await developCli('web', {
|
|
213
|
+
navy: 'env-1'
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Wait microtask flush
|
|
217
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
218
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
219
|
+
const printed = consoleLogStub.getCalls().map(c => c.args[0] || '').join('\n');
|
|
220
|
+
(0, _chai.expect)(printed).to.contain('exited');
|
|
221
|
+
});
|
|
222
|
+
it('should throw an invariant violation when no container is found for the service', async function () {
|
|
223
|
+
navyStub.ps.resolves([{
|
|
224
|
+
name: 'other',
|
|
225
|
+
id: 'xyz'
|
|
226
|
+
}]);
|
|
227
|
+
let caught;
|
|
228
|
+
try {
|
|
229
|
+
await developCli('web', {
|
|
230
|
+
navy: 'env-1'
|
|
231
|
+
});
|
|
232
|
+
} catch (err) {
|
|
233
|
+
caught = err;
|
|
234
|
+
}
|
|
235
|
+
(0, _chai.expect)(caught).to.be.an('error');
|
|
236
|
+
(0, _chai.expect)(caught.message).to.contain('DEVELOP_NO_CONTAINER_ID');
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _chai = require("chai");
|
|
5
|
+
var _sinon = _interopRequireDefault(require("sinon"));
|
|
6
|
+
var _proxyquire = _interopRequireDefault(require("proxyquire"));
|
|
7
|
+
/* eslint-env mocha */
|
|
8
|
+
|
|
9
|
+
describe('cli/external-ip', function () {
|
|
10
|
+
let sandbox;
|
|
11
|
+
let getConfigStub;
|
|
12
|
+
let getExternalIPStub;
|
|
13
|
+
let consoleLogStub;
|
|
14
|
+
let externalIpCli;
|
|
15
|
+
beforeEach(function () {
|
|
16
|
+
sandbox = _sinon.default.createSandbox();
|
|
17
|
+
getConfigStub = sandbox.stub();
|
|
18
|
+
getExternalIPStub = sandbox.stub();
|
|
19
|
+
consoleLogStub = sandbox.stub(console, 'log');
|
|
20
|
+
externalIpCli = _proxyquire.default.noCallThru()('../external-ip', {
|
|
21
|
+
'../config': {
|
|
22
|
+
getConfig: getConfigStub
|
|
23
|
+
},
|
|
24
|
+
'../util/external-ip': {
|
|
25
|
+
getExternalIP: getExternalIPStub
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
afterEach(function () {
|
|
30
|
+
sandbox.restore();
|
|
31
|
+
});
|
|
32
|
+
describe('default export', function () {
|
|
33
|
+
it('should pass the externalIP value from config to getExternalIP', async function () {
|
|
34
|
+
getConfigStub.returns({
|
|
35
|
+
externalIP: 'configured.host'
|
|
36
|
+
});
|
|
37
|
+
getExternalIPStub.resolves('1.2.3.4');
|
|
38
|
+
await externalIpCli();
|
|
39
|
+
(0, _chai.expect)(getConfigStub.calledOnce).to.equal(true);
|
|
40
|
+
(0, _chai.expect)(getExternalIPStub.calledOnce).to.equal(true);
|
|
41
|
+
(0, _chai.expect)(getExternalIPStub.firstCall.args[0]).to.equal('configured.host');
|
|
42
|
+
});
|
|
43
|
+
it('should log the resolved external IP', async function () {
|
|
44
|
+
getConfigStub.returns({
|
|
45
|
+
externalIP: null
|
|
46
|
+
});
|
|
47
|
+
getExternalIPStub.resolves('5.6.7.8');
|
|
48
|
+
await externalIpCli();
|
|
49
|
+
(0, _chai.expect)(consoleLogStub.calledOnce).to.equal(true);
|
|
50
|
+
(0, _chai.expect)(consoleLogStub.firstCall.args[0]).to.equal('5.6.7.8');
|
|
51
|
+
});
|
|
52
|
+
it('should pass undefined when config has no externalIP key', async function () {
|
|
53
|
+
getConfigStub.returns({});
|
|
54
|
+
getExternalIPStub.resolves('127.0.0.1');
|
|
55
|
+
await externalIpCli();
|
|
56
|
+
(0, _chai.expect)(getExternalIPStub.firstCall.args[0]).to.equal(undefined);
|
|
57
|
+
});
|
|
58
|
+
it('should support an asynchronous getConfig implementation', async function () {
|
|
59
|
+
getConfigStub.resolves({
|
|
60
|
+
externalIP: 'async.host'
|
|
61
|
+
});
|
|
62
|
+
getExternalIPStub.resolves('9.9.9.9');
|
|
63
|
+
await externalIpCli();
|
|
64
|
+
(0, _chai.expect)(getExternalIPStub.firstCall.args[0]).to.equal('async.host');
|
|
65
|
+
(0, _chai.expect)(consoleLogStub.firstCall.args[0]).to.equal('9.9.9.9');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _chai = require("chai");
|
|
5
|
+
var _sinon = _interopRequireDefault(require("sinon"));
|
|
6
|
+
var _proxyquire = _interopRequireDefault(require("proxyquire"));
|
|
7
|
+
var _stripAnsi = _interopRequireDefault(require("strip-ansi"));
|
|
8
|
+
/* eslint-env mocha */
|
|
9
|
+
|
|
10
|
+
// NOTE (potential source bugs in health.js, not locked in by these tests):
|
|
11
|
+
// 1. `getStatus` and `getHistory` both compute `service.raw && service.raw.State.Health`.
|
|
12
|
+
// If `service.raw` is truthy but `service.raw.State` is undefined, this throws a
|
|
13
|
+
// TypeError reading 'Health' of undefined. The guard chain is incomplete; it
|
|
14
|
+
// should be `service.raw && service.raw.State && service.raw.State.Health`.
|
|
15
|
+
// 2. Both helpers accept a `state` parameter that is never used (dead parameter).
|
|
16
|
+
|
|
17
|
+
describe('cli/health', function () {
|
|
18
|
+
let sandbox;
|
|
19
|
+
let getNavyStub;
|
|
20
|
+
let navyStub;
|
|
21
|
+
let consoleLogStub;
|
|
22
|
+
let healthCli;
|
|
23
|
+
function makeService(overrides = {}) {
|
|
24
|
+
return {
|
|
25
|
+
id: 'svc-1',
|
|
26
|
+
name: 'api',
|
|
27
|
+
raw: undefined,
|
|
28
|
+
...overrides
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
beforeEach(function () {
|
|
32
|
+
sandbox = _sinon.default.createSandbox();
|
|
33
|
+
navyStub = {
|
|
34
|
+
ps: sandbox.stub().resolves([]),
|
|
35
|
+
getState: sandbox.stub().resolves(null)
|
|
36
|
+
};
|
|
37
|
+
getNavyStub = sandbox.stub().returns(navyStub);
|
|
38
|
+
consoleLogStub = sandbox.stub(console, 'log');
|
|
39
|
+
healthCli = _proxyquire.default.noCallThru()('../health', {
|
|
40
|
+
'../': {
|
|
41
|
+
getNavy: getNavyStub
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
afterEach(function () {
|
|
46
|
+
sandbox.restore();
|
|
47
|
+
});
|
|
48
|
+
function lastLoggedString() {
|
|
49
|
+
const last = consoleLogStub.lastCall;
|
|
50
|
+
return last ? String(last.args[0]) : '';
|
|
51
|
+
}
|
|
52
|
+
describe('default export', function () {
|
|
53
|
+
it('should resolve the navy instance using opts.navy', async function () {
|
|
54
|
+
await healthCli({
|
|
55
|
+
navy: 'env-1'
|
|
56
|
+
});
|
|
57
|
+
(0, _chai.expect)(getNavyStub.calledOnce).to.equal(true);
|
|
58
|
+
(0, _chai.expect)(getNavyStub.firstCall.args[0]).to.equal('env-1');
|
|
59
|
+
});
|
|
60
|
+
it('should print the table headers even when there are no services', async function () {
|
|
61
|
+
navyStub.ps.resolves([]);
|
|
62
|
+
await healthCli({
|
|
63
|
+
navy: 'env-1'
|
|
64
|
+
});
|
|
65
|
+
(0, _chai.expect)(consoleLogStub.calledOnce).to.equal(true);
|
|
66
|
+
const text = (0, _stripAnsi.default)(consoleLogStub.firstCall.args[0]);
|
|
67
|
+
(0, _chai.expect)(text).to.contain('NAME');
|
|
68
|
+
(0, _chai.expect)(text).to.contain('STATUS');
|
|
69
|
+
(0, _chai.expect)(text).to.contain('HISTORY');
|
|
70
|
+
});
|
|
71
|
+
it('should call ps and getState exactly once each', async function () {
|
|
72
|
+
navyStub.ps.resolves([makeService()]);
|
|
73
|
+
await healthCli({
|
|
74
|
+
navy: 'env-1'
|
|
75
|
+
});
|
|
76
|
+
(0, _chai.expect)(navyStub.ps.calledOnce).to.equal(true);
|
|
77
|
+
(0, _chai.expect)(navyStub.getState.calledOnce).to.equal(true);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('getStatus (via default export)', function () {
|
|
81
|
+
it('should render - when the service has no raw container info', async function () {
|
|
82
|
+
navyStub.ps.resolves([makeService({
|
|
83
|
+
name: 'api',
|
|
84
|
+
raw: undefined
|
|
85
|
+
})]);
|
|
86
|
+
await healthCli({
|
|
87
|
+
navy: 'env-1'
|
|
88
|
+
});
|
|
89
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
90
|
+
(0, _chai.expect)(text).to.contain('api');
|
|
91
|
+
(0, _chai.expect)(text).to.contain('-');
|
|
92
|
+
});
|
|
93
|
+
it('should render - when the service has raw but no Health record', async function () {
|
|
94
|
+
navyStub.ps.resolves([makeService({
|
|
95
|
+
name: 'api',
|
|
96
|
+
raw: {
|
|
97
|
+
State: {
|
|
98
|
+
Health: null
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
})]);
|
|
102
|
+
await healthCli({
|
|
103
|
+
navy: 'env-1'
|
|
104
|
+
});
|
|
105
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
106
|
+
(0, _chai.expect)(text).to.contain('api');
|
|
107
|
+
(0, _chai.expect)(text).to.contain('-');
|
|
108
|
+
});
|
|
109
|
+
it('should render Healthy when health status is "healthy"', async function () {
|
|
110
|
+
navyStub.ps.resolves([makeService({
|
|
111
|
+
raw: {
|
|
112
|
+
State: {
|
|
113
|
+
Health: {
|
|
114
|
+
Status: 'healthy',
|
|
115
|
+
Log: []
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
})]);
|
|
120
|
+
await healthCli({
|
|
121
|
+
navy: 'env-1'
|
|
122
|
+
});
|
|
123
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
124
|
+
(0, _chai.expect)(text).to.contain('Healthy');
|
|
125
|
+
});
|
|
126
|
+
it('should render Unhealthy when health status is anything other than healthy', async function () {
|
|
127
|
+
navyStub.ps.resolves([makeService({
|
|
128
|
+
raw: {
|
|
129
|
+
State: {
|
|
130
|
+
Health: {
|
|
131
|
+
Status: 'starting',
|
|
132
|
+
Log: []
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
})]);
|
|
137
|
+
await healthCli({
|
|
138
|
+
navy: 'env-1'
|
|
139
|
+
});
|
|
140
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
141
|
+
(0, _chai.expect)(text).to.contain('Unhealthy');
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
describe('getHistory (via default export)', function () {
|
|
145
|
+
it('should render - when the service has no raw container info', async function () {
|
|
146
|
+
navyStub.ps.resolves([makeService({
|
|
147
|
+
name: 'api',
|
|
148
|
+
raw: undefined
|
|
149
|
+
})]);
|
|
150
|
+
await healthCli({
|
|
151
|
+
navy: 'env-1'
|
|
152
|
+
});
|
|
153
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
154
|
+
(0, _chai.expect)(text).to.contain('-');
|
|
155
|
+
});
|
|
156
|
+
it('should render - when the service has raw but no Health record', async function () {
|
|
157
|
+
navyStub.ps.resolves([makeService({
|
|
158
|
+
raw: {
|
|
159
|
+
State: {
|
|
160
|
+
Health: null
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
})]);
|
|
164
|
+
await healthCli({
|
|
165
|
+
navy: 'env-1'
|
|
166
|
+
});
|
|
167
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
168
|
+
(0, _chai.expect)(text).to.contain('-');
|
|
169
|
+
});
|
|
170
|
+
it('should render only success markers when every entry has ExitCode 0', async function () {
|
|
171
|
+
navyStub.ps.resolves([makeService({
|
|
172
|
+
raw: {
|
|
173
|
+
State: {
|
|
174
|
+
Health: {
|
|
175
|
+
Status: 'healthy',
|
|
176
|
+
Log: [{
|
|
177
|
+
ExitCode: 0
|
|
178
|
+
}, {
|
|
179
|
+
ExitCode: 0
|
|
180
|
+
}]
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
})]);
|
|
185
|
+
await healthCli({
|
|
186
|
+
navy: 'env-1'
|
|
187
|
+
});
|
|
188
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
189
|
+
(0, _chai.expect)(text).to.contain('█ █');
|
|
190
|
+
(0, _chai.expect)(text).not.to.contain('x');
|
|
191
|
+
});
|
|
192
|
+
it('should render only failure markers when every entry has a non-zero ExitCode', async function () {
|
|
193
|
+
navyStub.ps.resolves([makeService({
|
|
194
|
+
raw: {
|
|
195
|
+
State: {
|
|
196
|
+
Health: {
|
|
197
|
+
Status: 'unhealthy',
|
|
198
|
+
Log: [{
|
|
199
|
+
ExitCode: 1
|
|
200
|
+
}, {
|
|
201
|
+
ExitCode: 2
|
|
202
|
+
}]
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
})]);
|
|
207
|
+
await healthCli({
|
|
208
|
+
navy: 'env-1'
|
|
209
|
+
});
|
|
210
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
211
|
+
(0, _chai.expect)(text).to.contain('x x');
|
|
212
|
+
(0, _chai.expect)(text).not.to.contain('█');
|
|
213
|
+
});
|
|
214
|
+
it('should render mixed success and failure markers based on each entry ExitCode', async function () {
|
|
215
|
+
navyStub.ps.resolves([makeService({
|
|
216
|
+
raw: {
|
|
217
|
+
State: {
|
|
218
|
+
Health: {
|
|
219
|
+
Status: 'healthy',
|
|
220
|
+
Log: [{
|
|
221
|
+
ExitCode: 0
|
|
222
|
+
}, {
|
|
223
|
+
ExitCode: 1
|
|
224
|
+
}, {
|
|
225
|
+
ExitCode: 0
|
|
226
|
+
}]
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
})]);
|
|
231
|
+
await healthCli({
|
|
232
|
+
navy: 'env-1'
|
|
233
|
+
});
|
|
234
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
235
|
+
(0, _chai.expect)(text).to.contain('█ x █');
|
|
236
|
+
});
|
|
237
|
+
it('should render an empty history string when Log is an empty array', async function () {
|
|
238
|
+
navyStub.ps.resolves([makeService({
|
|
239
|
+
raw: {
|
|
240
|
+
State: {
|
|
241
|
+
Health: {
|
|
242
|
+
Status: 'healthy',
|
|
243
|
+
Log: []
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
})]);
|
|
248
|
+
await healthCli({
|
|
249
|
+
navy: 'env-1'
|
|
250
|
+
});
|
|
251
|
+
const text = (0, _stripAnsi.default)(lastLoggedString());
|
|
252
|
+
(0, _chai.expect)(text).to.contain('Healthy');
|
|
253
|
+
(0, _chai.expect)(text).not.to.contain('█');
|
|
254
|
+
(0, _chai.expect)(text).not.to.contain('x');
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|