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.
Files changed (149) hide show
  1. package/lib/__tests__/config-provider.js +75 -0
  2. package/lib/__tests__/config.js +130 -0
  3. package/lib/__tests__/driver-logging.js +148 -0
  4. package/lib/__tests__/driver.js +19 -0
  5. package/lib/__tests__/errors.js +49 -0
  6. package/lib/__tests__/http-proxy.js +214 -0
  7. package/lib/__tests__/index.js +25 -0
  8. package/lib/__tests__/service.js +16 -0
  9. package/lib/cli/__tests__/develop.js +239 -0
  10. package/lib/cli/__tests__/external-ip.js +68 -0
  11. package/lib/cli/__tests__/health.js +257 -0
  12. package/lib/cli/__tests__/https.js +210 -0
  13. package/lib/cli/__tests__/import.js +110 -0
  14. package/lib/cli/__tests__/index.js +118 -0
  15. package/lib/cli/__tests__/lan-ip.js +90 -0
  16. package/lib/cli/__tests__/launch.js +179 -0
  17. package/lib/cli/__tests__/live.js +155 -0
  18. package/lib/cli/__tests__/local-ip.js +72 -0
  19. package/lib/cli/__tests__/logs.js +52 -0
  20. package/lib/cli/__tests__/open.js +65 -0
  21. package/lib/cli/__tests__/program.js +472 -0
  22. package/lib/cli/__tests__/ps.js +345 -0
  23. package/lib/cli/__tests__/refresh-config.js +95 -0
  24. package/lib/cli/__tests__/run.js +54 -0
  25. package/lib/cli/__tests__/status.js +204 -0
  26. package/lib/cli/__tests__/updates.js +243 -0
  27. package/lib/cli/__tests__/wait-for-healthy.js +134 -0
  28. package/lib/cli/config/__tests__/index.js +275 -0
  29. package/lib/cli/config/__tests__/wrapper.js +53 -0
  30. package/lib/cli/config/index.js +19 -37
  31. package/lib/cli/config/wrapper.js +0 -6
  32. package/lib/cli/develop.js +7 -21
  33. package/lib/cli/doctor/__tests__/clean-compose-files.js +78 -0
  34. package/lib/cli/doctor/__tests__/index.js +67 -0
  35. package/lib/cli/doctor/__tests__/invalid-compose-config.js +103 -0
  36. package/lib/cli/doctor/__tests__/invalid-state.js +83 -0
  37. package/lib/cli/doctor/__tests__/util.js +91 -0
  38. package/lib/cli/doctor/clean-compose-files.js +5 -13
  39. package/lib/cli/doctor/index.js +0 -12
  40. package/lib/cli/doctor/invalid-compose-config.js +0 -4
  41. package/lib/cli/doctor/invalid-state.js +0 -6
  42. package/lib/cli/doctor/util.js +0 -10
  43. package/lib/cli/external-ip.js +0 -4
  44. package/lib/cli/health.js +0 -12
  45. package/lib/cli/https.js +9 -25
  46. package/lib/cli/import.js +0 -12
  47. package/lib/cli/index.js +0 -9
  48. package/lib/cli/lan-ip.js +2 -8
  49. package/lib/cli/launch.js +0 -9
  50. package/lib/cli/live.js +6 -16
  51. package/lib/cli/local-ip.js +2 -7
  52. package/lib/cli/logs.js +0 -3
  53. package/lib/cli/open.js +2 -7
  54. package/lib/cli/program.js +73 -101
  55. package/lib/cli/ps.js +1 -21
  56. package/lib/cli/refresh-config.js +0 -7
  57. package/lib/cli/run.js +0 -3
  58. package/lib/cli/status.js +0 -11
  59. package/lib/cli/updates.js +0 -22
  60. package/lib/cli/util/__tests__/get-or-initialise-navy.js +66 -0
  61. package/lib/cli/util/__tests__/import.js +123 -0
  62. package/lib/cli/util/__tests__/index.js +17 -0
  63. package/lib/cli/util/__tests__/merge-action-options.js +47 -0
  64. package/lib/cli/util/__tests__/reconfigure.js +78 -0
  65. package/lib/cli/util/get-or-initialise-navy.js +0 -7
  66. package/lib/cli/util/import.js +0 -9
  67. package/lib/cli/util/index.js +0 -2
  68. package/lib/cli/util/merge-action-options.js +20 -0
  69. package/lib/cli/util/reconfigure.js +0 -4
  70. package/lib/cli/wait-for-healthy.js +0 -21
  71. package/lib/client/registry/__tests__/get-credentials.js +62 -0
  72. package/lib/client/registry/__tests__/get-endpoint.js +124 -0
  73. package/lib/client/registry/__tests__/get-fat-manifest.js +67 -0
  74. package/lib/client/registry/__tests__/get-token.js +66 -0
  75. package/lib/client/registry/__tests__/helpers.js +26 -0
  76. package/lib/client/registry/get-credentials.js +3 -9
  77. package/lib/client/registry/get-endpoint.js +29 -63
  78. package/lib/client/registry/get-fat-manifest.js +2 -9
  79. package/lib/client/registry/get-token.js +2 -13
  80. package/lib/client/registry/helpers.js +0 -4
  81. package/lib/config-provider.js +0 -12
  82. package/lib/config-providers/filesystem/__tests__/index.js +176 -0
  83. package/lib/config-providers/filesystem/index.js +5 -23
  84. package/lib/config-providers/npm/__tests__/index.js +226 -0
  85. package/lib/config-providers/npm/__tests__/util.js +1 -2
  86. package/lib/config-providers/npm/index.js +12 -35
  87. package/lib/config-providers/npm/util.js +0 -3
  88. package/lib/config.js +4 -19
  89. package/lib/domain/__tests__/container-image.js +81 -0
  90. package/lib/domain/__tests__/oci-api-specification.js +23 -0
  91. package/lib/domain/container-image.js +8 -21
  92. package/lib/domain/oci-api-specification.js +3 -5
  93. package/lib/driver-logging.js +0 -19
  94. package/lib/driver.js +0 -4
  95. package/lib/drivers/docker-compose/__tests__/client.js +249 -0
  96. package/lib/drivers/docker-compose/__tests__/index.js +430 -0
  97. package/lib/drivers/docker-compose/client.js +0 -16
  98. package/lib/drivers/docker-compose/index.js +7 -49
  99. package/lib/errors.js +0 -10
  100. package/lib/http-proxy.js +28 -23
  101. package/lib/index.js +1 -9
  102. package/lib/middleware/__tests__/add-service-proxy-config.js +258 -0
  103. package/lib/middleware/__tests__/develop.js +120 -0
  104. package/lib/middleware/__tests__/helpers.js +154 -0
  105. package/lib/middleware/__tests__/port-override.js +125 -0
  106. package/lib/middleware/__tests__/set-env-vars.js +94 -0
  107. package/lib/middleware/__tests__/set-image.js +76 -0
  108. package/lib/middleware/__tests__/set-logging-driver.js +94 -0
  109. package/lib/middleware/__tests__/tag-override.js +92 -0
  110. package/lib/middleware/add-service-proxy-config.js +8 -16
  111. package/lib/middleware/develop.js +2 -5
  112. package/lib/middleware/helpers.js +6 -12
  113. package/lib/middleware/port-override.js +5 -8
  114. package/lib/middleware/set-env-vars.js +6 -6
  115. package/lib/middleware/set-image.js +4 -5
  116. package/lib/middleware/set-logging-driver.js +6 -6
  117. package/lib/middleware/tag-override.js +4 -6
  118. package/lib/navy/__tests__/default-middleware.js +40 -0
  119. package/lib/navy/__tests__/index.js +1612 -0
  120. package/lib/navy/__tests__/middleware.js +71 -0
  121. package/lib/navy/__tests__/plugin-interface.js +121 -0
  122. package/lib/navy/__tests__/state.js +103 -0
  123. package/lib/navy/__tests__/util.js +24 -0
  124. package/lib/navy/default-middleware.js +0 -10
  125. package/lib/navy/index.js +83 -138
  126. package/lib/navy/middleware.js +0 -6
  127. package/lib/navy/plugin-interface.js +2 -10
  128. package/lib/navy/state.js +12 -24
  129. package/lib/navy/util.js +0 -1
  130. package/lib/service.js +2 -3
  131. package/lib/util/__tests__/exec-async.js +83 -0
  132. package/lib/util/__tests__/external-ip.js +97 -2
  133. package/lib/util/__tests__/get-lan-ip.js +46 -0
  134. package/lib/util/__tests__/has-update.js +136 -0
  135. package/lib/util/__tests__/https.js +301 -0
  136. package/lib/util/__tests__/navyrc.js +45 -0
  137. package/lib/util/__tests__/service-host.js +63 -5
  138. package/lib/util/__tests__/table.js +44 -0
  139. package/lib/util/docker-client.js +2 -10
  140. package/lib/util/exec-async.js +0 -4
  141. package/lib/util/external-ip.js +8 -12
  142. package/lib/util/fs.js +1 -6
  143. package/lib/util/get-lan-ip.js +0 -5
  144. package/lib/util/has-update.js +2 -14
  145. package/lib/util/https.js +11 -55
  146. package/lib/util/navyrc.js +0 -5
  147. package/lib/util/service-host.js +0 -17
  148. package/lib/util/table.js +0 -6
  149. package/package.json +14 -13
@@ -0,0 +1,53 @@
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/config/wrapper', function () {
10
+ let sandbox;
11
+ let execSyncStub;
12
+ let originalArgv;
13
+ let wrapperCli;
14
+ beforeEach(function () {
15
+ sandbox = _sinon.default.createSandbox();
16
+ execSyncStub = sandbox.stub();
17
+ originalArgv = process.argv;
18
+ wrapperCli = _proxyquire.default.noCallThru()('../wrapper', {
19
+ child_process: {
20
+ execSync: execSyncStub
21
+ }
22
+ });
23
+ });
24
+ afterEach(function () {
25
+ process.argv = originalArgv;
26
+ sandbox.restore();
27
+ });
28
+ describe('default export', function () {
29
+ it('should invoke navy-config.js via execSync with stdio inherit', async function () {
30
+ process.argv = ['node', 'navy', 'config'];
31
+ await wrapperCli('env-1');
32
+ (0, _chai.expect)(execSyncStub.calledOnce).to.equal(true);
33
+ const command = execSyncStub.firstCall.args[0];
34
+ (0, _chai.expect)(command).to.contain('navy-config.js');
35
+ const opts = execSyncStub.firstCall.args[1];
36
+ (0, _chai.expect)(opts).to.eql({
37
+ stdio: 'inherit'
38
+ });
39
+ });
40
+ it('should pass through any extra command-line args from process.argv', async function () {
41
+ process.argv = ['node', 'navy', 'config', 'set', 'default-navy', 'dev'];
42
+ await wrapperCli('env-1');
43
+ const command = execSyncStub.firstCall.args[0];
44
+ (0, _chai.expect)(command).to.contain('set default-navy dev');
45
+ });
46
+ it('should invoke with no extra args when only the wrapper command is supplied', async function () {
47
+ process.argv = ['node', 'navy', 'config'];
48
+ await wrapperCli('env-1');
49
+ const command = execSyncStub.firstCall.args[0];
50
+ (0, _chai.expect)(command.endsWith('navy-config.js ')).to.equal(true);
51
+ });
52
+ });
53
+ });
@@ -1,80 +1,64 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
3
  Object.defineProperty(exports, "__esModule", {
6
4
  value: true
7
5
  });
8
6
  exports.reconfigureIfNecessary = reconfigureIfNecessary;
9
-
10
- var _commander = _interopRequireDefault(require("commander"));
11
-
7
+ var _commander = require("commander");
12
8
  var _config = require("../../config");
13
-
14
9
  var _errors = require("../../errors");
15
-
16
10
  var _reconfigure = require("../util/reconfigure");
17
-
18
11
  const NAME_MAP = {
19
12
  'default-navy': 'defaultNavy',
20
13
  'external-ip': 'externalIP',
21
14
  'tlsCa-dir': 'tlsRootCaDir'
22
15
  };
23
16
  const configWhichNeedsReconfigure = ['externalIP'];
24
-
25
17
  async function reconfigureIfNecessary(configProp) {
26
18
  if (configWhichNeedsReconfigure.indexOf(configProp) === -1) {
27
19
  return;
28
20
  }
29
-
30
21
  await (0, _reconfigure.reconfigureAllNavies)();
31
22
  }
32
-
33
- _commander.default.command('set <key> <value>').description('Sets the given config key').action(async (key, value) => {
23
+ _commander.program.command('set <key> <value>').description('Sets the given config key').action(async (key, value) => {
34
24
  const configProp = NAME_MAP[key];
35
-
36
25
  if (!configProp) {
37
26
  throw new _errors.NavyError('Invalid config key: ' + key);
38
27
  }
39
-
40
- await (0, _config.setConfig)({ ...(await (0, _config.getConfig)()),
41
- [configProp]: value
42
- });
28
+ const updated = {
29
+ ...(await (0, _config.getConfig)())
30
+ };
31
+ updated[configProp] = value;
32
+ await (0, _config.setConfig)(updated);
43
33
  await reconfigureIfNecessary(configProp);
44
34
  });
45
-
46
- _commander.default.command('get <key>').description('Gets the given config by key').action(async key => {
35
+ _commander.program.command('get <key>').description('Gets the given config by key').action(async key => {
47
36
  if (!NAME_MAP[key]) {
48
37
  throw new _errors.NavyError('Invalid config key: ' + key);
49
38
  }
50
-
51
39
  const config = await (0, _config.getConfig)();
52
40
  console.log(config[NAME_MAP[key]]);
53
41
  });
54
-
55
- _commander.default.command('rm <key>').description('Removes the current config value').action(async key => {
42
+ _commander.program.command('rm <key>').description('Removes the current config value').action(async key => {
56
43
  const configProp = NAME_MAP[key];
57
-
58
44
  if (!configProp) {
59
45
  throw new _errors.NavyError('Invalid config key: ' + key);
60
46
  }
61
-
62
- await (0, _config.setConfig)({ ...(await (0, _config.getConfig)()),
63
- [configProp]: null
64
- });
47
+ const updated = {
48
+ ...(await (0, _config.getConfig)())
49
+ };
50
+ updated[configProp] = null;
51
+ await (0, _config.setConfig)(updated);
65
52
  await reconfigureIfNecessary(configProp);
66
53
  });
67
-
68
- _commander.default.command('ls').description('Lists all of the Navy config keys and values that have been set').action(async () => {
54
+ _commander.program.command('ls').description('Lists all of the Navy config keys and values that have been set').action(async () => {
69
55
  const configKeys = Object.keys(NAME_MAP);
70
56
  const config = await (0, _config.getConfig)();
71
57
  console.log(configKeys.map(key => `${key}=${config[NAME_MAP[key]] != null ? config[NAME_MAP[key]] : 'null'}`).join('\n'));
72
58
  });
73
-
74
- _commander.default.command('json').description('Dumps out all Navy config as JSON').action(async () => {
59
+ _commander.program.command('json').description('Dumps out all Navy config as JSON').action(async () => {
75
60
  console.log(JSON.stringify(await (0, _config.getConfig)(), null, 2));
76
61
  });
77
-
78
62
  process.on('unhandledRejection', err => {
79
63
  if (err instanceof _errors.NavyError) {
80
64
  err.prettyPrint();
@@ -82,9 +66,7 @@ process.on('unhandledRejection', err => {
82
66
  console.error(err.stack);
83
67
  }
84
68
  });
85
-
86
- _commander.default.parse(process.argv);
87
-
88
- if (_commander.default.args.length === 0) {
89
- _commander.default.help();
69
+ _commander.program.parse(process.argv);
70
+ if (_commander.program.args.length === 0) {
71
+ _commander.program.help();
90
72
  }
@@ -1,21 +1,15 @@
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
  });
8
7
  exports.default = _default;
9
-
10
8
  var _child_process = require("child_process");
11
-
12
9
  var _path = _interopRequireDefault(require("path"));
13
-
14
10
  async function _default(navy) {
15
- // $FlowIgnore flow bug with execSync
16
11
  (0, _child_process.execSync)(_path.default.join(__dirname, '../../../bin/navy-config.js') + ' ' + process.argv.slice(3).join(' '), {
17
12
  stdio: 'inherit'
18
13
  });
19
14
  }
20
-
21
15
  module.exports = exports.default;
@@ -1,55 +1,44 @@
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
  });
8
7
  exports.default = _default;
9
-
10
8
  var _path = _interopRequireDefault(require("path"));
11
-
12
9
  var _chalk = _interopRequireDefault(require("chalk"));
13
-
14
10
  var _invariant = _interopRequireDefault(require("invariant"));
15
-
16
11
  var _ = require("../");
17
-
18
12
  var _errors = require("../errors");
19
-
20
13
  var _dockerClient = _interopRequireDefault(require("../util/docker-client"));
21
-
22
14
  var _navyrc = _interopRequireDefault(require("../util/navyrc"));
23
-
24
15
  async function _default(service, opts) {
25
16
  const navy = (0, _.getNavy)(opts.navy);
26
17
  const cwd = process.cwd();
27
18
  const navyRc = await (0, _navyrc.default)(cwd);
28
-
29
19
  if (!navyRc || !navyRc.services) {
30
20
  throw new _errors.NavyError(`No valid .navyrc file was found in "${cwd}"`);
31
21
  }
32
-
33
22
  if (!navyRc.develop) {
34
23
  throw new _errors.NavyError('No develop mounts found in .navyrc');
35
24
  }
36
-
37
25
  if (navyRc.services.length > 1 && !service) {
38
26
  throw new _errors.NavyError('Multiple service mappings are defined in .navyrc, you need to explicitly specify what service to develop');
39
27
  }
40
-
41
28
  if (!service) service = navyRc.services[0];
42
-
43
29
  if (navyRc.services.indexOf(service) === -1) {
44
30
  throw new _errors.NavyError(`Service "${service}" is not a valid development target`);
45
31
  }
46
-
47
32
  const mounts = {};
48
33
  Object.keys(navyRc.develop.mounts).forEach(localPath => mounts[_path.default.resolve(localPath)] = navyRc.develop.mounts[localPath]);
49
34
  const state = (await navy.getState()) || {};
50
- await navy.saveState({ ...state,
51
- services: { ...state.services,
52
- [service]: { ...(state.services || {})[service],
35
+ const stateServices = state.services || {};
36
+ await navy.saveState({
37
+ ...state,
38
+ services: {
39
+ ...stateServices,
40
+ [service]: {
41
+ ...stateServices[service],
53
42
  _develop: {
54
43
  mounts,
55
44
  command: navyRc.develop.command
@@ -68,9 +57,7 @@ async function _default(service, opts) {
68
57
  const container = (await navy.ps()).filter(_service => _service.name === service)[0];
69
58
  (0, _invariant.default)(container, "DEVELOP_NO_CONTAINER_ID: Could not determine container ID for log attachment");
70
59
  const containerId = container.id;
71
-
72
60
  const containerObj = _dockerClient.default.getContainer(containerId);
73
-
74
61
  containerObj.attach({
75
62
  stream: true,
76
63
  stdout: true,
@@ -81,5 +68,4 @@ async function _default(service, opts) {
81
68
  console.log();
82
69
  });
83
70
  }
84
-
85
71
  module.exports = exports.default;
@@ -0,0 +1,78 @@
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/doctor/clean-compose-files', function () {
10
+ let sandbox;
11
+ let getLaunchedNavyNamesStub;
12
+ let startStub;
13
+ let pathToNavyStub;
14
+ let normaliseNavyNameStub;
15
+ let rmStub;
16
+ let cleanComposeFiles;
17
+ beforeEach(function () {
18
+ sandbox = _sinon.default.createSandbox();
19
+ getLaunchedNavyNamesStub = sandbox.stub().resolves([]);
20
+ startStub = sandbox.stub();
21
+ pathToNavyStub = sandbox.stub().callsFake(name => `/state/${name}`);
22
+ normaliseNavyNameStub = sandbox.stub().callsFake(name => name.toLowerCase());
23
+ rmStub = sandbox.stub().resolves();
24
+ cleanComposeFiles = _proxyquire.default.noCallThru()('../clean-compose-files', {
25
+ '../../': {
26
+ getLaunchedNavyNames: getLaunchedNavyNamesStub
27
+ },
28
+ './util': {
29
+ start: startStub
30
+ },
31
+ '../../navy/state': {
32
+ pathToNavy: pathToNavyStub
33
+ },
34
+ '../../navy/util': {
35
+ normaliseNavyName: normaliseNavyNameStub
36
+ },
37
+ fs: {
38
+ promises: {
39
+ rm: rmStub
40
+ }
41
+ }
42
+ });
43
+ });
44
+ afterEach(function () {
45
+ sandbox.restore();
46
+ });
47
+ describe('default export', function () {
48
+ it('should print a starting message', async function () {
49
+ await cleanComposeFiles();
50
+ (0, _chai.expect)(startStub.calledOnce).to.equal(true);
51
+ (0, _chai.expect)(startStub.firstCall.args[0]).to.contain('Cleaning');
52
+ });
53
+ it('should not call rm when there are no launched navies', async function () {
54
+ getLaunchedNavyNamesStub.resolves([]);
55
+ await cleanComposeFiles();
56
+ (0, _chai.expect)(rmStub.called).to.equal(false);
57
+ });
58
+ it('should remove docker-compose.tmp.yml from each launched navy path', async function () {
59
+ getLaunchedNavyNamesStub.resolves(['env-1', 'Dev']);
60
+ await cleanComposeFiles();
61
+ (0, _chai.expect)(rmStub.callCount).to.equal(2);
62
+ const paths = rmStub.getCalls().map(c => c.args[0]);
63
+ (0, _chai.expect)(paths).to.include('/state/env-1/docker-compose.tmp.yml');
64
+ (0, _chai.expect)(paths).to.include('/state/dev/docker-compose.tmp.yml');
65
+ rmStub.getCalls().forEach(call => {
66
+ (0, _chai.expect)(call.args[1]).to.eql({
67
+ recursive: true,
68
+ force: true
69
+ });
70
+ });
71
+ });
72
+ it('should normalise navy names when resolving paths', async function () {
73
+ getLaunchedNavyNamesStub.resolves(['MyEnv']);
74
+ await cleanComposeFiles();
75
+ (0, _chai.expect)(normaliseNavyNameStub.calledWith('MyEnv')).to.equal(true);
76
+ });
77
+ });
78
+ });
@@ -0,0 +1,67 @@
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/doctor/index', function () {
10
+ let sandbox;
11
+ let cleanComposeStub;
12
+ let invalidStateStub;
13
+ let invalidComposeConfigStub;
14
+ let consoleLogStub;
15
+ let doctorCli;
16
+ function loadModule() {
17
+ doctorCli = _proxyquire.default.noCallThru()('../index', {
18
+ './clean-compose-files': cleanComposeStub,
19
+ './invalid-state': invalidStateStub,
20
+ './invalid-compose-config': invalidComposeConfigStub
21
+ });
22
+ }
23
+ beforeEach(function () {
24
+ sandbox = _sinon.default.createSandbox();
25
+ cleanComposeStub = sandbox.stub().resolves();
26
+ invalidStateStub = sandbox.stub().resolves();
27
+ invalidComposeConfigStub = sandbox.stub().resolves();
28
+ consoleLogStub = sandbox.stub(console, 'log');
29
+ loadModule();
30
+ });
31
+ afterEach(function () {
32
+ sandbox.restore();
33
+ });
34
+ describe('default export', function () {
35
+ it('should run all checks in order', async function () {
36
+ await doctorCli();
37
+ (0, _chai.expect)(cleanComposeStub.calledOnce).to.equal(true);
38
+ (0, _chai.expect)(invalidStateStub.calledOnce).to.equal(true);
39
+ (0, _chai.expect)(invalidComposeConfigStub.calledOnce).to.equal(true);
40
+ (0, _chai.expect)(cleanComposeStub.calledBefore(invalidStateStub)).to.equal(true);
41
+ (0, _chai.expect)(invalidStateStub.calledBefore(invalidComposeConfigStub)).to.equal(true);
42
+ });
43
+ it('should print a success message when all checks pass', async function () {
44
+ await doctorCli();
45
+ const printed = consoleLogStub.getCalls().map(c => c.args[0] || '').join('\n');
46
+ (0, _chai.expect)(printed).to.contain('Finished tests');
47
+ });
48
+ it('should print error stacks and a warning when checks fail', async function () {
49
+ const error1 = new Error('boom1');
50
+ const error2 = new Error('boom2');
51
+ cleanComposeStub.rejects(error1);
52
+ invalidStateStub.rejects(error2);
53
+ await doctorCli();
54
+ const printedArgs = consoleLogStub.getCalls().map(c => c.args[0] || '');
55
+ const all = printedArgs.join('\n');
56
+ (0, _chai.expect)(all).to.contain('There were some issues');
57
+ (0, _chai.expect)(printedArgs.some(arg => typeof arg === 'string' && arg.includes(error1.stack))).to.equal(true);
58
+ (0, _chai.expect)(printedArgs.some(arg => typeof arg === 'string' && arg.includes(error2.stack))).to.equal(true);
59
+ });
60
+ it('should run all checks even when an early one throws', async function () {
61
+ cleanComposeStub.rejects(new Error('boom'));
62
+ await doctorCli();
63
+ (0, _chai.expect)(invalidStateStub.calledOnce).to.equal(true);
64
+ (0, _chai.expect)(invalidComposeConfigStub.calledOnce).to.equal(true);
65
+ });
66
+ });
67
+ });
@@ -0,0 +1,103 @@
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/doctor/invalid-compose-config', function () {
10
+ let sandbox;
11
+ let getLaunchedNaviesStub;
12
+ let startStub;
13
+ let fixStub;
14
+ let catchInvariantStub;
15
+ let invalidComposeConfig;
16
+ beforeEach(function () {
17
+ sandbox = _sinon.default.createSandbox();
18
+ getLaunchedNaviesStub = sandbox.stub().resolves([]);
19
+ startStub = sandbox.stub();
20
+ fixStub = sandbox.stub().callsFake(async (msg, name, callback) => callback());
21
+ catchInvariantStub = sandbox.stub().callsFake(async (code, fn, catchCallback) => {
22
+ try {
23
+ await fn();
24
+ } catch (err) {
25
+ if (err.name === 'Invariant Violation' && err.message.indexOf(code) === 0) {
26
+ await catchCallback();
27
+ }
28
+ }
29
+ });
30
+ invalidComposeConfig = _proxyquire.default.noCallThru()('../invalid-compose-config', {
31
+ '../../': {
32
+ getLaunchedNavies: getLaunchedNaviesStub
33
+ },
34
+ './util': {
35
+ start: startStub,
36
+ fix: fixStub,
37
+ catchInvariant: catchInvariantStub
38
+ }
39
+ });
40
+ });
41
+ afterEach(function () {
42
+ sandbox.restore();
43
+ });
44
+ describe('default export', function () {
45
+ it('should log a starting message', async function () {
46
+ await invalidComposeConfig();
47
+ (0, _chai.expect)(startStub.calledOnce).to.equal(true);
48
+ (0, _chai.expect)(startStub.firstCall.args[0]).to.contain('compose');
49
+ });
50
+ it('should do nothing further when there are no launched navies', async function () {
51
+ getLaunchedNaviesStub.resolves([]);
52
+ await invalidComposeConfig();
53
+ (0, _chai.expect)(catchInvariantStub.called).to.equal(false);
54
+ (0, _chai.expect)(fixStub.called).to.equal(false);
55
+ });
56
+ it('should call safeGetDriver().getConfig() for each navy', async function () {
57
+ const driver = {
58
+ getConfig: sandbox.stub().resolves({})
59
+ };
60
+ const navy = {
61
+ name: 'env-1',
62
+ safeGetDriver: sandbox.stub().resolves(driver),
63
+ delete: sandbox.stub().resolves()
64
+ };
65
+ getLaunchedNaviesStub.resolves([navy]);
66
+ await invalidComposeConfig();
67
+ (0, _chai.expect)(navy.safeGetDriver.calledOnce).to.equal(true);
68
+ (0, _chai.expect)(driver.getConfig.calledOnce).to.equal(true);
69
+ });
70
+ it('should remove a navy whose driver throws NO_DOCKER_COMPOSE_FILE invariant', async function () {
71
+ const err = new Error('NO_DOCKER_COMPOSE_FILE: not found');
72
+ err.name = 'Invariant Violation';
73
+ const driver = {
74
+ getConfig: sandbox.stub().rejects(err)
75
+ };
76
+ const navy = {
77
+ name: 'env-1',
78
+ safeGetDriver: sandbox.stub().resolves(driver),
79
+ delete: sandbox.stub().resolves()
80
+ };
81
+ getLaunchedNaviesStub.resolves([navy]);
82
+ await invalidComposeConfig();
83
+ (0, _chai.expect)(fixStub.calledOnce).to.equal(true);
84
+ (0, _chai.expect)(navy.delete.calledOnce).to.equal(true);
85
+ });
86
+ it('should not call delete when the driver throws a different invariant', async function () {
87
+ const err = new Error('SOMETHING_ELSE: nope');
88
+ err.name = 'Invariant Violation';
89
+ const driver = {
90
+ getConfig: sandbox.stub().rejects(err)
91
+ };
92
+ const navy = {
93
+ name: 'env-1',
94
+ safeGetDriver: sandbox.stub().resolves(driver),
95
+ delete: sandbox.stub().resolves()
96
+ };
97
+ getLaunchedNaviesStub.resolves([navy]);
98
+ await invalidComposeConfig();
99
+ (0, _chai.expect)(fixStub.called).to.equal(false);
100
+ (0, _chai.expect)(navy.delete.called).to.equal(false);
101
+ });
102
+ });
103
+ });
@@ -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 _proxyquire = _interopRequireDefault(require("proxyquire"));
7
+ /* eslint-env mocha */
8
+
9
+ describe('cli/doctor/invalid-state', function () {
10
+ let sandbox;
11
+ let getLaunchedNaviesStub;
12
+ let startStub;
13
+ let fixStub;
14
+ let invalidState;
15
+ beforeEach(function () {
16
+ sandbox = _sinon.default.createSandbox();
17
+ getLaunchedNaviesStub = sandbox.stub().resolves([]);
18
+ startStub = sandbox.stub();
19
+ fixStub = sandbox.stub().callsFake(async (msg, name, callback) => callback());
20
+ invalidState = _proxyquire.default.noCallThru()('../invalid-state', {
21
+ '../../': {
22
+ getLaunchedNavies: getLaunchedNaviesStub
23
+ },
24
+ './util': {
25
+ start: startStub,
26
+ fix: fixStub
27
+ }
28
+ });
29
+ });
30
+ afterEach(function () {
31
+ sandbox.restore();
32
+ });
33
+ describe('default export', function () {
34
+ it('should log a starting message', async function () {
35
+ await invalidState();
36
+ (0, _chai.expect)(startStub.calledOnce).to.equal(true);
37
+ (0, _chai.expect)(startStub.firstCall.args[0]).to.contain('dangling');
38
+ });
39
+ it('should remove a navy that has no config provider', async function () {
40
+ const navy = {
41
+ name: 'env-1',
42
+ getConfigProvider: sandbox.stub().resolves(null),
43
+ delete: sandbox.stub().resolves()
44
+ };
45
+ getLaunchedNaviesStub.resolves([navy]);
46
+ await invalidState();
47
+ (0, _chai.expect)(fixStub.calledOnce).to.equal(true);
48
+ (0, _chai.expect)(fixStub.firstCall.args[0]).to.contain('without config provider');
49
+ (0, _chai.expect)(navy.delete.calledOnce).to.equal(true);
50
+ });
51
+ it('should destroy a dangling navy whose config is invalid', async function () {
52
+ const configProvider = {
53
+ isDangling: sandbox.stub().resolves(true)
54
+ };
55
+ const navy = {
56
+ name: 'env-1',
57
+ getConfigProvider: sandbox.stub().resolves(configProvider),
58
+ destroy: sandbox.stub().resolves()
59
+ };
60
+ getLaunchedNaviesStub.resolves([navy]);
61
+ await invalidState();
62
+ (0, _chai.expect)(fixStub.calledOnce).to.equal(true);
63
+ (0, _chai.expect)(fixStub.firstCall.args[0]).to.contain('dangling Navy');
64
+ (0, _chai.expect)(navy.destroy.calledOnce).to.equal(true);
65
+ });
66
+ it('should leave alone a navy whose config provider exists and is not dangling', async function () {
67
+ const configProvider = {
68
+ isDangling: sandbox.stub().resolves(false)
69
+ };
70
+ const navy = {
71
+ name: 'env-1',
72
+ getConfigProvider: sandbox.stub().resolves(configProvider),
73
+ destroy: sandbox.stub().resolves(),
74
+ delete: sandbox.stub().resolves()
75
+ };
76
+ getLaunchedNaviesStub.resolves([navy]);
77
+ await invalidState();
78
+ (0, _chai.expect)(fixStub.called).to.equal(false);
79
+ (0, _chai.expect)(navy.destroy.called).to.equal(false);
80
+ (0, _chai.expect)(navy.delete.called).to.equal(false);
81
+ });
82
+ });
83
+ });