navy 6.0.0 → 7.0.0-alpha.2
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 +472 -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 +73 -101
- 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__/merge-action-options.js +47 -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/merge-action-options.js +20 -0
- 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 +14 -13
package/lib/navy/state.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
-
|
|
5
4
|
Object.defineProperty(exports, "__esModule", {
|
|
6
5
|
value: true
|
|
7
6
|
});
|
|
@@ -12,64 +11,53 @@ exports.pathToNavyRoot = pathToNavyRoot;
|
|
|
12
11
|
exports.pathToNavys = pathToNavys;
|
|
13
12
|
exports.pathToState = pathToState;
|
|
14
13
|
exports.saveState = saveState;
|
|
15
|
-
|
|
16
14
|
var _path = _interopRequireDefault(require("path"));
|
|
17
|
-
|
|
18
15
|
var _invariant = _interopRequireDefault(require("invariant"));
|
|
19
|
-
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
var _fs = _interopRequireDefault(require("../util/fs"));
|
|
23
|
-
|
|
16
|
+
var _fs = require("fs");
|
|
17
|
+
var _fs2 = _interopRequireDefault(require("../util/fs"));
|
|
24
18
|
const debug = require('debug')('navy:state');
|
|
25
|
-
|
|
26
|
-
const mkdirp = _bluebird.default.promisify(require('mkdirp'));
|
|
27
|
-
|
|
28
|
-
const rimraf = _bluebird.default.promisify(require('rimraf'));
|
|
29
|
-
|
|
30
19
|
function pathToNavyRoot() {
|
|
31
20
|
const home = process.env.HOME;
|
|
32
21
|
(0, _invariant.default)(home, "NO_HOME_DIRECTORY: No home directory available");
|
|
33
22
|
return _path.default.join(home, '.navy');
|
|
34
23
|
}
|
|
35
|
-
|
|
36
24
|
function pathToNavys() {
|
|
37
25
|
return _path.default.join(pathToNavyRoot(), 'navies');
|
|
38
26
|
}
|
|
39
|
-
|
|
40
27
|
function pathToNavy(normalisedEnvName) {
|
|
41
28
|
return _path.default.join(pathToNavys(), normalisedEnvName);
|
|
42
29
|
}
|
|
43
|
-
|
|
44
30
|
function pathToState(normalisedEnvName) {
|
|
45
31
|
return _path.default.join(pathToNavy(normalisedEnvName), 'state.json');
|
|
46
32
|
}
|
|
47
33
|
/* eslint-disable no-use-before-define */
|
|
48
|
-
|
|
49
|
-
|
|
50
34
|
async function getState(normalisedEnvName) {
|
|
51
35
|
/* eslint-enable no-use-before-define */
|
|
52
36
|
try {
|
|
53
37
|
const statePath = pathToState(normalisedEnvName);
|
|
54
|
-
const file = (await
|
|
38
|
+
const file = (await _fs2.default.readFileAsync(statePath)).toString();
|
|
55
39
|
debug('Got raw state for env ' + normalisedEnvName, statePath, file);
|
|
56
40
|
return JSON.parse(file);
|
|
57
41
|
} catch (ex) {
|
|
58
42
|
return null;
|
|
59
43
|
}
|
|
60
44
|
}
|
|
61
|
-
|
|
62
45
|
async function saveState(normalisedEnvName, state) {
|
|
63
46
|
const statePath = pathToState(normalisedEnvName);
|
|
64
|
-
await
|
|
47
|
+
await _fs.promises.mkdir(_path.default.dirname(statePath), {
|
|
48
|
+
recursive: true
|
|
49
|
+
});
|
|
65
50
|
debug('Writing state for env ' + normalisedEnvName, statePath, state);
|
|
66
|
-
await
|
|
51
|
+
await _fs2.default.writeFileAsync(statePath, JSON.stringify(state, null, 2));
|
|
67
52
|
}
|
|
68
|
-
|
|
69
53
|
async function deleteState(normalisedEnvName) {
|
|
70
54
|
debug('Deleting state for env ' + normalisedEnvName);
|
|
71
|
-
await
|
|
55
|
+
await _fs.promises.rm(_path.default.dirname(pathToState(normalisedEnvName)), {
|
|
56
|
+
recursive: true,
|
|
57
|
+
force: true
|
|
58
|
+
});
|
|
72
59
|
}
|
|
60
|
+
|
|
73
61
|
/**
|
|
74
62
|
* A "state" object of the current services, and other internal Navy state.
|
|
75
63
|
* This can be used to hang "state" off services which can then be used by middleware at runtime to modify the
|
package/lib/navy/util.js
CHANGED
package/lib/service.js
CHANGED
|
@@ -0,0 +1,83 @@
|
|
|
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 _events = require("events");
|
|
7
|
+
var _child_process = _interopRequireDefault(require("child_process"));
|
|
8
|
+
var _execAsync = require("../exec-async");
|
|
9
|
+
/* eslint-env mocha */
|
|
10
|
+
|
|
11
|
+
function createFakeChild() {
|
|
12
|
+
const child = new _events.EventEmitter();
|
|
13
|
+
child.stdout = new _events.EventEmitter();
|
|
14
|
+
child.stderr = new _events.EventEmitter();
|
|
15
|
+
return child;
|
|
16
|
+
}
|
|
17
|
+
describe('exec-async', function () {
|
|
18
|
+
describe('execAsync', function () {
|
|
19
|
+
let sandbox;
|
|
20
|
+
let execStub;
|
|
21
|
+
let fakeChild;
|
|
22
|
+
beforeEach(function () {
|
|
23
|
+
sandbox = _sinon.default.createSandbox();
|
|
24
|
+
fakeChild = createFakeChild();
|
|
25
|
+
execStub = sandbox.stub(_child_process.default, 'exec').callsFake((cmd, opts, cb) => {
|
|
26
|
+
process.nextTick(() => {
|
|
27
|
+
fakeChild.stdout.emit('data', Buffer.from('hello'));
|
|
28
|
+
fakeChild.stderr.emit('data', Buffer.from('warn'));
|
|
29
|
+
cb(null, 'hello world', '');
|
|
30
|
+
});
|
|
31
|
+
return fakeChild;
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
afterEach(function () {
|
|
35
|
+
sandbox.restore();
|
|
36
|
+
});
|
|
37
|
+
it('should resolve with stdout when the command succeeds', async function () {
|
|
38
|
+
const result = await (0, _execAsync.execAsync)('echo', ['hello', 'world']);
|
|
39
|
+
(0, _chai.expect)(result).to.equal('hello world');
|
|
40
|
+
(0, _chai.expect)(execStub.calledOnce).to.equal(true);
|
|
41
|
+
(0, _chai.expect)(execStub.firstCall.args[0]).to.equal('echo hello world');
|
|
42
|
+
});
|
|
43
|
+
it('should default args to an empty array when not provided', async function () {
|
|
44
|
+
const result = await (0, _execAsync.execAsync)('echo');
|
|
45
|
+
(0, _chai.expect)(result).to.equal('hello world');
|
|
46
|
+
(0, _chai.expect)(execStub.firstCall.args[0]).to.equal('echo ');
|
|
47
|
+
});
|
|
48
|
+
it('should pass opts through to child_process.exec', async function () {
|
|
49
|
+
const opts = {
|
|
50
|
+
cwd: '/tmp',
|
|
51
|
+
env: {
|
|
52
|
+
FOO: 'bar'
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
await (0, _execAsync.execAsync)('ls', ['-la'], null, opts);
|
|
56
|
+
(0, _chai.expect)(execStub.firstCall.args[1]).to.equal(opts);
|
|
57
|
+
});
|
|
58
|
+
it('should invoke the callback with the spawned child process', async function () {
|
|
59
|
+
const callback = _sinon.default.spy();
|
|
60
|
+
await (0, _execAsync.execAsync)('echo', ['hi'], callback);
|
|
61
|
+
(0, _chai.expect)(callback.calledOnce).to.equal(true);
|
|
62
|
+
(0, _chai.expect)(callback.firstCall.args[0]).to.equal(fakeChild);
|
|
63
|
+
});
|
|
64
|
+
it('should not invoke the callback when none is supplied', async function () {
|
|
65
|
+
await (0, _execAsync.execAsync)('echo', ['hi']);
|
|
66
|
+
});
|
|
67
|
+
it('should reject when the command fails', async function () {
|
|
68
|
+
execStub.restore();
|
|
69
|
+
const failure = new Error('boom');
|
|
70
|
+
execStub = sandbox.stub(_child_process.default, 'exec').callsFake((cmd, opts, cb) => {
|
|
71
|
+
process.nextTick(() => cb(failure));
|
|
72
|
+
return fakeChild;
|
|
73
|
+
});
|
|
74
|
+
let caught;
|
|
75
|
+
try {
|
|
76
|
+
await (0, _execAsync.execAsync)('false');
|
|
77
|
+
} catch (err) {
|
|
78
|
+
caught = err;
|
|
79
|
+
}
|
|
80
|
+
(0, _chai.expect)(caught).to.equal(failure);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
var _chai = require("chai");
|
|
4
|
-
|
|
5
|
+
var _sinon = _interopRequireDefault(require("sinon"));
|
|
6
|
+
var _dns = _interopRequireDefault(require("dns"));
|
|
5
7
|
var _externalIp = require("../external-ip");
|
|
6
|
-
|
|
7
8
|
/* eslint-env mocha */
|
|
9
|
+
|
|
8
10
|
describe('getExternalIP', function () {
|
|
9
11
|
it('should return NAVY_EXTERNAL_IP if set', async function () {
|
|
10
12
|
process.env.NAVY_EXTERNAL_IP = '192.168.1.10';
|
|
@@ -23,4 +25,97 @@ describe('getExternalIP', function () {
|
|
|
23
25
|
(0, _chai.expect)(await (0, _externalIp.getExternalIP)()).to.equal('192.168.1.13');
|
|
24
26
|
delete process.env.DOCKER_HOST;
|
|
25
27
|
});
|
|
28
|
+
});
|
|
29
|
+
describe('external-ip (mocked)', function () {
|
|
30
|
+
let sandbox;
|
|
31
|
+
let originalEnv;
|
|
32
|
+
beforeEach(function () {
|
|
33
|
+
sandbox = _sinon.default.createSandbox();
|
|
34
|
+
originalEnv = {
|
|
35
|
+
DOCKER_HOST: process.env.DOCKER_HOST,
|
|
36
|
+
NAVY_HOST: process.env.NAVY_HOST,
|
|
37
|
+
NAVY_EXTERNAL_IP: process.env.NAVY_EXTERNAL_IP
|
|
38
|
+
};
|
|
39
|
+
delete process.env.DOCKER_HOST;
|
|
40
|
+
delete process.env.NAVY_HOST;
|
|
41
|
+
delete process.env.NAVY_EXTERNAL_IP;
|
|
42
|
+
});
|
|
43
|
+
afterEach(function () {
|
|
44
|
+
sandbox.restore();
|
|
45
|
+
for (const [name, value] of Object.entries(originalEnv)) {
|
|
46
|
+
if (value === undefined) {
|
|
47
|
+
delete process.env[name];
|
|
48
|
+
} else {
|
|
49
|
+
process.env[name] = value;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
describe('dnsLookup', function () {
|
|
54
|
+
it('should resolve with the IPv4 address when dns returns family 4', async function () {
|
|
55
|
+
sandbox.stub(_dns.default, 'lookup').callsFake((hostname, opts, cb) => {
|
|
56
|
+
cb(null, '10.20.30.40', 4);
|
|
57
|
+
});
|
|
58
|
+
const ip = await (0, _externalIp.dnsLookup)('example.com');
|
|
59
|
+
(0, _chai.expect)(ip).to.equal('10.20.30.40');
|
|
60
|
+
});
|
|
61
|
+
it('should reject when dns.lookup returns an error', async function () {
|
|
62
|
+
sandbox.stub(_dns.default, 'lookup').callsFake((hostname, opts, cb) => {
|
|
63
|
+
cb(new Error('ENOTFOUND'));
|
|
64
|
+
});
|
|
65
|
+
let caught;
|
|
66
|
+
try {
|
|
67
|
+
await (0, _externalIp.dnsLookup)('does-not-exist');
|
|
68
|
+
} catch (err) {
|
|
69
|
+
caught = err;
|
|
70
|
+
}
|
|
71
|
+
(0, _chai.expect)(caught).to.be.an('error');
|
|
72
|
+
(0, _chai.expect)(caught.message).to.equal('Failed to lookup hostname "does-not-exist"');
|
|
73
|
+
});
|
|
74
|
+
it('should reject when dns.lookup returns a non-ipv4 family', async function () {
|
|
75
|
+
sandbox.stub(_dns.default, 'lookup').callsFake((hostname, opts, cb) => {
|
|
76
|
+
cb(null, '::1', 6);
|
|
77
|
+
});
|
|
78
|
+
let caught;
|
|
79
|
+
try {
|
|
80
|
+
await (0, _externalIp.dnsLookup)('ipv6-only.example');
|
|
81
|
+
} catch (err) {
|
|
82
|
+
caught = err;
|
|
83
|
+
}
|
|
84
|
+
(0, _chai.expect)(caught).to.be.an('error');
|
|
85
|
+
(0, _chai.expect)(caught.message).to.equal('Failed to lookup hostname "ipv6-only.example"');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('getExternalIP (additional branches)', function () {
|
|
89
|
+
it('should return NAVY_HOST (deprecated) when set', async function () {
|
|
90
|
+
process.env.NAVY_HOST = 'legacy.host';
|
|
91
|
+
(0, _chai.expect)(await (0, _externalIp.getExternalIP)()).to.equal('legacy.host');
|
|
92
|
+
});
|
|
93
|
+
it('should give NAVY_HOST precedence over NAVY_EXTERNAL_IP', async function () {
|
|
94
|
+
process.env.NAVY_HOST = 'legacy.host';
|
|
95
|
+
process.env.NAVY_EXTERNAL_IP = '1.2.3.4';
|
|
96
|
+
(0, _chai.expect)(await (0, _externalIp.getExternalIP)()).to.equal('legacy.host');
|
|
97
|
+
});
|
|
98
|
+
it('should DNS-resolve ipInConfig when provided', async function () {
|
|
99
|
+
sandbox.stub(_dns.default, 'lookup').callsFake((hostname, opts, cb) => {
|
|
100
|
+
(0, _chai.expect)(hostname).to.equal('docker.internal');
|
|
101
|
+
cb(null, '172.16.0.5', 4);
|
|
102
|
+
});
|
|
103
|
+
(0, _chai.expect)(await (0, _externalIp.getExternalIP)('docker.internal')).to.equal('172.16.0.5');
|
|
104
|
+
});
|
|
105
|
+
it('should resolve a hostname embedded in DOCKER_HOST tcp:// using DNS', async function () {
|
|
106
|
+
process.env.DOCKER_HOST = 'tcp://my-docker-host.example:2375';
|
|
107
|
+
sandbox.stub(_dns.default, 'lookup').callsFake((hostname, opts, cb) => {
|
|
108
|
+
(0, _chai.expect)(hostname).to.equal('my-docker-host.example');
|
|
109
|
+
cb(null, '203.0.113.7', 4);
|
|
110
|
+
});
|
|
111
|
+
(0, _chai.expect)(await (0, _externalIp.getExternalIP)()).to.equal('203.0.113.7');
|
|
112
|
+
});
|
|
113
|
+
it('should fall back to 127.0.0.1 when no env vars or config are set', async function () {
|
|
114
|
+
(0, _chai.expect)(await (0, _externalIp.getExternalIP)()).to.equal('127.0.0.1');
|
|
115
|
+
});
|
|
116
|
+
it('should fall back to 127.0.0.1 when DOCKER_HOST is set without tcp://', async function () {
|
|
117
|
+
process.env.DOCKER_HOST = 'unix:///var/run/docker.sock';
|
|
118
|
+
(0, _chai.expect)(await (0, _externalIp.getExternalIP)()).to.equal('127.0.0.1');
|
|
119
|
+
});
|
|
120
|
+
});
|
|
26
121
|
});
|
|
@@ -0,0 +1,46 @@
|
|
|
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 _dns = _interopRequireDefault(require("dns"));
|
|
7
|
+
var _os = _interopRequireDefault(require("os"));
|
|
8
|
+
var _getLanIp = require("../get-lan-ip");
|
|
9
|
+
/* eslint-env mocha */
|
|
10
|
+
|
|
11
|
+
describe('get-lan-ip', function () {
|
|
12
|
+
describe('getLANIP', function () {
|
|
13
|
+
let sandbox;
|
|
14
|
+
beforeEach(function () {
|
|
15
|
+
sandbox = _sinon.default.createSandbox();
|
|
16
|
+
});
|
|
17
|
+
afterEach(function () {
|
|
18
|
+
sandbox.restore();
|
|
19
|
+
});
|
|
20
|
+
it('should resolve with the looked-up address for the host name', async function () {
|
|
21
|
+
sandbox.stub(_os.default, 'hostname').returns('my-laptop.local');
|
|
22
|
+
const dnsStub = sandbox.stub(_dns.default, 'lookup').callsFake((host, opts, cb) => {
|
|
23
|
+
cb(null, '10.0.0.42');
|
|
24
|
+
});
|
|
25
|
+
const result = await (0, _getLanIp.getLANIP)();
|
|
26
|
+
(0, _chai.expect)(result).to.equal('10.0.0.42');
|
|
27
|
+
(0, _chai.expect)(dnsStub.calledOnce).to.equal(true);
|
|
28
|
+
(0, _chai.expect)(dnsStub.firstCall.args[0]).to.equal('my-laptop.local');
|
|
29
|
+
(0, _chai.expect)(dnsStub.firstCall.args[1]).to.equal(null);
|
|
30
|
+
});
|
|
31
|
+
it('should reject if dns.lookup fails', async function () {
|
|
32
|
+
sandbox.stub(_os.default, 'hostname').returns('unknown.local');
|
|
33
|
+
const lookupError = new Error('lookup failed');
|
|
34
|
+
sandbox.stub(_dns.default, 'lookup').callsFake((host, opts, cb) => {
|
|
35
|
+
cb(lookupError);
|
|
36
|
+
});
|
|
37
|
+
let caught;
|
|
38
|
+
try {
|
|
39
|
+
await (0, _getLanIp.getLANIP)();
|
|
40
|
+
} catch (err) {
|
|
41
|
+
caught = err;
|
|
42
|
+
}
|
|
43
|
+
(0, _chai.expect)(caught).to.equal(lookupError);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
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
|
+
// NOTE: hasUpdate has a defect at line 17 in `../has-update`: when the
|
|
10
|
+
// supplied navyFile is null/undefined or has no
|
|
11
|
+
// `ignoreUnauthorizedRequestsForRegistries` array, `R.includes(registry,
|
|
12
|
+
// undefined)` throws (in current ramda). The tests below provide a valid
|
|
13
|
+
// navyFile shape to exercise the supported call patterns.
|
|
14
|
+
function withMocks({
|
|
15
|
+
inspect,
|
|
16
|
+
getFatManifest = _sinon.default.stub()
|
|
17
|
+
}) {
|
|
18
|
+
const docker = {
|
|
19
|
+
getImage: _sinon.default.stub().returns({
|
|
20
|
+
inspect
|
|
21
|
+
})
|
|
22
|
+
};
|
|
23
|
+
const stubs = {
|
|
24
|
+
'./docker-client': docker,
|
|
25
|
+
'../client/registry/get-fat-manifest': getFatManifest
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
docker,
|
|
29
|
+
getFatManifest,
|
|
30
|
+
hasUpdate: _proxyquire.default.noCallThru()('../has-update', stubs)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
describe('has-update', function () {
|
|
34
|
+
it('should return false when the remote digest matches one of the local RepoDigests', async function () {
|
|
35
|
+
const inspect = _sinon.default.stub().resolves({
|
|
36
|
+
RepoDigests: ['library/node@sha256:abc', 'library/node@sha256:other']
|
|
37
|
+
});
|
|
38
|
+
const {
|
|
39
|
+
hasUpdate
|
|
40
|
+
} = withMocks({
|
|
41
|
+
inspect,
|
|
42
|
+
getFatManifest: _sinon.default.stub().resolves({
|
|
43
|
+
tag: 'sha256:abc'
|
|
44
|
+
})
|
|
45
|
+
});
|
|
46
|
+
const result = await hasUpdate('library/node:lts', 'image-id', {
|
|
47
|
+
ignoreUnauthorizedRequestsForRegistries: []
|
|
48
|
+
});
|
|
49
|
+
(0, _chai.expect)(result).to.equal(false);
|
|
50
|
+
});
|
|
51
|
+
it('should return true when the remote digest is not in the local RepoDigests', async function () {
|
|
52
|
+
const inspect = _sinon.default.stub().resolves({
|
|
53
|
+
RepoDigests: ['library/node@sha256:old']
|
|
54
|
+
});
|
|
55
|
+
const {
|
|
56
|
+
hasUpdate
|
|
57
|
+
} = withMocks({
|
|
58
|
+
inspect,
|
|
59
|
+
getFatManifest: _sinon.default.stub().resolves({
|
|
60
|
+
tag: 'sha256:new'
|
|
61
|
+
})
|
|
62
|
+
});
|
|
63
|
+
const result = await hasUpdate('library/node:lts', 'image-id', {
|
|
64
|
+
ignoreUnauthorizedRequestsForRegistries: []
|
|
65
|
+
});
|
|
66
|
+
(0, _chai.expect)(result).to.equal(true);
|
|
67
|
+
});
|
|
68
|
+
it('should return "INVALID_REMOTE" when getFatManifest fails', async function () {
|
|
69
|
+
const inspect = _sinon.default.stub().resolves({
|
|
70
|
+
RepoDigests: []
|
|
71
|
+
});
|
|
72
|
+
const {
|
|
73
|
+
hasUpdate
|
|
74
|
+
} = withMocks({
|
|
75
|
+
inspect,
|
|
76
|
+
getFatManifest: _sinon.default.stub().rejects(new Error('boom'))
|
|
77
|
+
});
|
|
78
|
+
const result = await hasUpdate('library/node:lts', 'image-id', {
|
|
79
|
+
ignoreUnauthorizedRequestsForRegistries: []
|
|
80
|
+
});
|
|
81
|
+
(0, _chai.expect)(result).to.equal('INVALID_REMOTE');
|
|
82
|
+
});
|
|
83
|
+
it('should return "INVALID_REMOTE" when docker.getImage().inspect() fails', async function () {
|
|
84
|
+
const inspect = _sinon.default.stub().rejects(new Error('no such image'));
|
|
85
|
+
const {
|
|
86
|
+
hasUpdate
|
|
87
|
+
} = withMocks({
|
|
88
|
+
inspect
|
|
89
|
+
});
|
|
90
|
+
const result = await hasUpdate('library/node:lts', 'image-id', {
|
|
91
|
+
ignoreUnauthorizedRequestsForRegistries: []
|
|
92
|
+
});
|
|
93
|
+
(0, _chai.expect)(result).to.equal('INVALID_REMOTE');
|
|
94
|
+
});
|
|
95
|
+
it('should pass allowUnauthorizedRequest=true when navyFile lists the registry as ignored', async function () {
|
|
96
|
+
const inspect = _sinon.default.stub().resolves({
|
|
97
|
+
RepoDigests: ['someregistry.com/some/image@sha256:abc']
|
|
98
|
+
});
|
|
99
|
+
const getFatManifest = _sinon.default.stub().resolves({
|
|
100
|
+
tag: 'sha256:abc'
|
|
101
|
+
});
|
|
102
|
+
const {
|
|
103
|
+
hasUpdate
|
|
104
|
+
} = withMocks({
|
|
105
|
+
inspect,
|
|
106
|
+
getFatManifest
|
|
107
|
+
});
|
|
108
|
+
await hasUpdate('someregistry.com/some/image:1', 'image-id', {
|
|
109
|
+
ignoreUnauthorizedRequestsForRegistries: ['someregistry.com']
|
|
110
|
+
});
|
|
111
|
+
(0, _chai.expect)(getFatManifest.firstCall.args[0]).to.eql({
|
|
112
|
+
allowUnauthorizedRequest: true,
|
|
113
|
+
registry: 'someregistry.com',
|
|
114
|
+
repository: 'some/image',
|
|
115
|
+
tag: '1'
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
it('should pass allowUnauthorizedRequest=false when registry is not in the ignore list', async function () {
|
|
119
|
+
const inspect = _sinon.default.stub().resolves({
|
|
120
|
+
RepoDigests: []
|
|
121
|
+
});
|
|
122
|
+
const getFatManifest = _sinon.default.stub().resolves({
|
|
123
|
+
tag: 'sha256:abc'
|
|
124
|
+
});
|
|
125
|
+
const {
|
|
126
|
+
hasUpdate
|
|
127
|
+
} = withMocks({
|
|
128
|
+
inspect,
|
|
129
|
+
getFatManifest
|
|
130
|
+
});
|
|
131
|
+
await hasUpdate('someregistry.com/some/image:1', 'image-id', {
|
|
132
|
+
ignoreUnauthorizedRequestsForRegistries: ['otherregistry.com']
|
|
133
|
+
});
|
|
134
|
+
(0, _chai.expect)(getFatManifest.firstCall.args[0].allowUnauthorizedRequest).to.equal(false);
|
|
135
|
+
});
|
|
136
|
+
});
|