navy 5.0.0 → 5.0.1-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,11 +51,11 @@ You can customise the functionality of Navy by writing Javascript plugins which
51
51
  $ npm install -g navy
52
52
  ```
53
53
 
54
- - [Read more of the documentation on the website](https://momentumft.github.io/navy/)
55
- - [GitHub page](https://github.com/momentumft/navy)
54
+ - [Read more of the documentation on the website](https://moneyhub.github.io/navy/)
55
+ - [GitHub page](https://github.com/moneyhub/navy)
56
56
 
57
57
  ## License
58
58
 
59
59
  Licensed under the MIT License.
60
60
 
61
- [View the full license here](https://raw.githubusercontent.com/momentumft/navy/master/LICENSE).
61
+ [View the full license here](https://raw.githubusercontent.com/moneyhub/navy/master/LICENSE).
@@ -43,7 +43,7 @@ async function _default() {
43
43
  console.log(_chalk.default.green(' ✔ Finished tests'));
44
44
  console.log();
45
45
  console.log(' Please try running Navy again if it wasn\'t working before.');
46
- console.log(' If you still have problems, please open an issue at https://github.com/momentumft/navy/issues/new');
46
+ console.log(' If you still have problems, please open an issue at https://github.com/moneyhub/navy/issues/new');
47
47
  console.log();
48
48
  }
49
49
 
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _ramda = require("ramda");
9
+
10
+ var _execAsync = require("../../util/exec-async");
11
+
12
+ var _containerImage = require("../../domain/container-image");
13
+
14
+ const getAuthenticationForRegistry = async registry => {
15
+ try {
16
+ const credentialStore = registry === _containerImage.DEFAULT_REGISTRY ? _containerImage.DEFAULT_REGISTRY_AUTH : registry;
17
+ const options = [credentialStore, '|', 'docker-credential-desktop', 'get'];
18
+ const stdout = await (0, _execAsync.execAsync)('echo', options, _ramda.always, {
19
+ cwd: process.cwd()
20
+ });
21
+ const credentials = JSON.parse(stdout);
22
+ return {
23
+ username: credentials['Username'],
24
+ password: credentials['Secret']
25
+ };
26
+ } catch (exception) {
27
+ return {
28
+ username: '',
29
+ password: ''
30
+ };
31
+ }
32
+ };
33
+
34
+ var _default = getAuthenticationForRegistry;
35
+ exports.default = _default;
36
+ module.exports = exports.default;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var R = _interopRequireWildcard(require("ramda"));
11
+
12
+ var _https = _interopRequireDefault(require("https"));
13
+
14
+ var _nodeFetch = _interopRequireDefault(require("node-fetch"));
15
+
16
+ var _getToken = _interopRequireDefault(require("./get-token"));
17
+
18
+ var _ociApiSpecification = require("../../domain/oci-api-specification");
19
+
20
+ var _getCredentials = _interopRequireDefault(require("./get-credentials"));
21
+
22
+ var _helpers = require("./helpers");
23
+
24
+ var _parsers = _interopRequireDefault(require("www-authenticate/lib/parsers"));
25
+
26
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
27
+
28
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
29
+
30
+ const handleUnauthorizedResponse = async ({
31
+ response,
32
+ context,
33
+ url
34
+ }) => {
35
+ const challenges = response.headers.get('WWW-Authenticate');
36
+ const {
37
+ scheme,
38
+ parms
39
+ } = new _parsers.default.WWW_Authenticate(challenges);
40
+
41
+ if (scheme === 'Basic') {
42
+ throw new Error('Invalid authentication');
43
+ }
44
+
45
+ if (scheme !== 'Bearer') {
46
+ throw new Error('Invalid authentication');
47
+ }
48
+
49
+ try {
50
+ const token = await (0, _getToken.default)(parms, context);
51
+ const options = R.mergeDeepRight(context, {
52
+ headers: {
53
+ 'Authorization': `Bearer ${token}`
54
+ }
55
+ });
56
+ const response = await (0, _nodeFetch.default)(url, options);
57
+
58
+ if (response.status === 401) {
59
+ throw new Error('Access denied');
60
+ }
61
+
62
+ return response;
63
+ } catch (exception) {
64
+ throw exception;
65
+ }
66
+ };
67
+
68
+ const get = async ({
69
+ allowUnauthorizedRequest = false,
70
+ endpoint,
71
+ registry,
72
+ options = {}
73
+ }) => {
74
+ const url = _ociApiSpecification.restSpecification.operation(registry, endpoint);
75
+
76
+ const credentials = await (0, _getCredentials.default)(registry);
77
+ const context = R.mergeDeepLeft(options, {
78
+ headers: R.reject(R.isNil, {
79
+ 'Authorization': (0, _helpers.basicAuthentication)(credentials)
80
+ }),
81
+ agent: new _https.default.Agent({
82
+ rejectUnauthorized: !allowUnauthorizedRequest
83
+ })
84
+ });
85
+
86
+ try {
87
+ const response = await (0, _nodeFetch.default)(url, context);
88
+
89
+ switch (response.status) {
90
+ case 401:
91
+ return handleUnauthorizedResponse({
92
+ response,
93
+ context,
94
+ url
95
+ });
96
+
97
+ case 404:
98
+ throw new Error('Operation not found', {
99
+ status: 404,
100
+ body: await response.json()
101
+ });
102
+
103
+ default:
104
+ return response;
105
+ }
106
+ } catch (exception) {
107
+ throw exception;
108
+ }
109
+ };
110
+
111
+ var _default = get;
112
+ exports.default = _default;
113
+ module.exports = exports.default;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _getEndpoint = _interopRequireDefault(require("./get-endpoint"));
11
+
12
+ var _ociApiSpecification = require("../../domain/oci-api-specification");
13
+
14
+ const getFatManifest = async ({
15
+ allowUnauthorizedRequest = false,
16
+ repository,
17
+ registry,
18
+ tag
19
+ }) => {
20
+ const endpoint = _ociApiSpecification.restSpecification.getManifest(repository, tag);
21
+
22
+ const options = {
23
+ headers: {
24
+ 'Accept': _ociApiSpecification.MEDIA_TYPES.FAT_MANIFEST
25
+ }
26
+ };
27
+ const response = await (0, _getEndpoint.default)({
28
+ allowUnauthorizedRequest,
29
+ endpoint,
30
+ registry,
31
+ options
32
+ });
33
+ return {
34
+ tag: response.headers.get('docker-content-digest'),
35
+ data: await response.json()
36
+ };
37
+ };
38
+
39
+ var _default = getFatManifest;
40
+ exports.default = _default;
41
+ module.exports = exports.default;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _nodeFetch = _interopRequireDefault(require("node-fetch"));
11
+
12
+ var R = _interopRequireWildcard(require("ramda"));
13
+
14
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
+
16
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
+
18
+ const getToken = async ({
19
+ realm,
20
+ service,
21
+ scope
22
+ }, {
23
+ headers,
24
+ agent
25
+ }) => {
26
+ const url = `${realm}?service=${service}&scope=${scope}`;
27
+ const options = {
28
+ headers: R.pick(['Authorization'], headers),
29
+ agent
30
+ };
31
+ const response = await (0, _nodeFetch.default)(url, options);
32
+
33
+ if (response.status === 401) {
34
+ throw new Error('Invalid authentication');
35
+ }
36
+
37
+ const {
38
+ token
39
+ } = await response.json();
40
+ return token;
41
+ };
42
+
43
+ var _default = getToken;
44
+ exports.default = _default;
45
+ module.exports = exports.default;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.basicAuthentication = void 0;
7
+
8
+ var _ramda = require("ramda");
9
+
10
+ const basicAuthentication = credentials => {
11
+ if ((0, _ramda.isEmpty)(credentials)) {
12
+ return null;
13
+ }
14
+
15
+ const parameters = Buffer.from(`${credentials.username}:${credentials.password}`).toString('base64');
16
+ return `Basic ${parameters}`;
17
+ };
18
+
19
+ exports.basicAuthentication = basicAuthentication;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DEFAULT_REGISTRY_AUTH = exports.DEFAULT_REGISTRY = void 0;
7
+ exports.getImageFromImageWithTag = getImageFromImageWithTag;
8
+ exports.getRegistryFromImage = getRegistryFromImage;
9
+ exports.getRepositoryFromImage = getRepositoryFromImage;
10
+ exports.getTagFromImageWithTag = getTagFromImageWithTag;
11
+ // docker v2 registry URL
12
+ const DEFAULT_REGISTRY = 'registry-1.docker.io'; // the url which docker stores in .docker/config.json for auth
13
+
14
+ exports.DEFAULT_REGISTRY = DEFAULT_REGISTRY;
15
+ const DEFAULT_REGISTRY_AUTH = 'https://index.docker.io/v1/'; // someregistry.com/some/image:latest -> someregistry.com/some/image
16
+
17
+ exports.DEFAULT_REGISTRY_AUTH = DEFAULT_REGISTRY_AUTH;
18
+
19
+ function getImageFromImageWithTag(imageWithTag) {
20
+ if (imageWithTag.lastIndexOf('/') !== -1) {
21
+ const lastSlash = imageWithTag.lastIndexOf('/');
22
+
23
+ if (imageWithTag.indexOf(':', lastSlash) !== -1) {
24
+ return imageWithTag.substring(0, imageWithTag.indexOf(':', lastSlash));
25
+ }
26
+
27
+ return imageWithTag;
28
+ }
29
+
30
+ if (imageWithTag.indexOf(':') !== -1) {
31
+ return imageWithTag.substring(0, imageWithTag.indexOf(':'));
32
+ }
33
+
34
+ return imageWithTag;
35
+ } // someregistry.com/some/image:latest -> latest
36
+
37
+
38
+ function getTagFromImageWithTag(imageWithTag) {
39
+ if (imageWithTag.lastIndexOf('/') !== -1) {
40
+ const lastSlash = imageWithTag.lastIndexOf('/');
41
+
42
+ if (imageWithTag.indexOf(':', lastSlash) !== -1) {
43
+ return imageWithTag.substring(imageWithTag.indexOf(':', lastSlash) + 1);
44
+ }
45
+
46
+ return 'latest';
47
+ }
48
+
49
+ if (imageWithTag.indexOf(':') !== -1) {
50
+ return imageWithTag.substring(imageWithTag.indexOf(':') + 1);
51
+ }
52
+
53
+ return 'latest';
54
+ }
55
+
56
+ function getRegistryFromImage(image) {
57
+ const parsedRegistry = image.match(/([a-zA-Z0-9-.:]+)\/[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+/);
58
+ const registry = parsedRegistry != null && parsedRegistry.length > 1 ? parsedRegistry[1] : DEFAULT_REGISTRY;
59
+ return registry;
60
+ } // someregistry.com/some/image -> some/image
61
+
62
+
63
+ function getRepositoryFromImage(image) {
64
+ if (image.lastIndexOf('/') === -1) {
65
+ return 'library/' + image;
66
+ }
67
+
68
+ if (image.split('/').length === 3) {
69
+ return image.substring(image.indexOf('/') + 1);
70
+ }
71
+
72
+ return image;
73
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.restSpecification = exports.MEDIA_TYPES = void 0;
7
+ const restSpecification = {
8
+ operation: (registry, endpoint) => `https://${registry}/v2/${endpoint}`,
9
+ getManifest: (repository, tag) => `${repository}/manifests/${tag}`
10
+ };
11
+ exports.restSpecification = restSpecification;
12
+ const MEDIA_TYPES = {
13
+ FAT_MANIFEST: 'application/vnd.docker.distribution.manifest.list.v2+json'
14
+ };
15
+ exports.MEDIA_TYPES = MEDIA_TYPES;
package/lib/index.d.ts CHANGED
@@ -63,4 +63,8 @@ declare module "navy" {
63
63
  }
64
64
 
65
65
  export function getNavy(name: string): Navy
66
+
67
+ export function getLaunchedNavies(): Promise<Array<Navy>>
68
+
69
+ export function getLaunchedNavyNames(): Promise<Array<string>>
66
70
  }
@@ -5,33 +5,44 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.default = hasUpdate;
8
+ exports.default = void 0;
9
9
 
10
- var _simpleDockerRegistryClient = require("simple-docker-registry-client");
11
-
12
- var _registryClient = require("./registry-client");
10
+ var R = _interopRequireWildcard(require("ramda"));
13
11
 
14
12
  var _dockerClient = _interopRequireDefault(require("./docker-client"));
15
13
 
16
- async function hasUpdate(imageWithTag, currentImageId, navyFile) {
17
- const imageConfig = await _dockerClient.default.getImage(currentImageId).inspect();
18
- const currentImageContainerId = imageConfig.ContainerConfig.Image;
19
- const image = (0, _simpleDockerRegistryClient.imageFromImageWithTag)(imageWithTag);
20
- const client = await (0, _registryClient.getRegistryClient)(image, navyFile);
21
- let manifest;
14
+ var _getFatManifest = _interopRequireDefault(require("../client/registry/get-fat-manifest"));
22
15
 
23
- try {
24
- manifest = await client.request((0, _simpleDockerRegistryClient.localImageFromImage)(image) + '/manifests/' + (0, _simpleDockerRegistryClient.tagFromImageWithTag)(imageWithTag));
25
- } catch (ex) {
26
- if (ex.body && ex.body.errors[0].code === 'MANIFEST_UNKNOWN') {
27
- return 'UNKNOWN_REMOTE';
28
- }
16
+ var _containerImage = require("../domain/container-image");
29
17
 
30
- return 'UNKNOWN_ERROR';
31
- }
18
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
+
20
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
32
21
 
33
- const lastLayer = JSON.parse(manifest.history[0].v1Compatibility);
34
- return lastLayer.container_config.Image !== currentImageContainerId;
35
- }
22
+ const hasUpdate = async (imageWithTag, currentImageId, navyFile) => {
23
+ const tag = (0, _containerImage.getTagFromImageWithTag)(imageWithTag);
24
+ const image = (0, _containerImage.getImageFromImageWithTag)(imageWithTag);
25
+ const registry = (0, _containerImage.getRegistryFromImage)(image);
26
+ const repository = (0, _containerImage.getRepositoryFromImage)(image);
27
+ const allowUnauthorizedRequest = R.includes(registry, R.path(['ignoreUnauthorizedRequestsForRegistries'], navyFile));
28
+
29
+ try {
30
+ const {
31
+ RepoDigests
32
+ } = await _dockerClient.default.getImage(currentImageId).inspect();
33
+ const manifest = await (0, _getFatManifest.default)({
34
+ allowUnauthorizedRequest,
35
+ repository,
36
+ registry,
37
+ tag
38
+ });
39
+ const remoteRepoDigest = `${image}@${manifest.tag}`;
40
+ return !R.includes(remoteRepoDigest, RepoDigests);
41
+ } catch {
42
+ return 'INVALID_REMOTE';
43
+ }
44
+ };
36
45
 
46
+ var _default = hasUpdate;
47
+ exports.default = _default;
37
48
  module.exports = exports.default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "navy",
3
- "version": "5.0.0",
3
+ "version": "5.0.1-rc.0",
4
4
  "description": "Quick and powerful development environments using Docker and Docker Compose",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -12,18 +12,18 @@
12
12
  },
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "git+https://github.com/momentumft/navy.git"
15
+ "url": "git+https://github.com/moneyhub/navy.git"
16
16
  },
17
17
  "keywords": [
18
18
  "docker",
19
19
  "environment"
20
20
  ],
21
- "author": "Momentum Financial Technology Ltd",
21
+ "author": "Moneyhub Financial Technology Ltd",
22
22
  "license": "MIT",
23
23
  "bugs": {
24
- "url": "https://github.com/momentumft/navy/issues"
24
+ "url": "https://github.com/moneyhub/navy/issues"
25
25
  },
26
- "homepage": "https://github.com/momentumft/navy#readme",
26
+ "homepage": "https://github.com/moneyhub/navy#readme",
27
27
  "dependencies": {
28
28
  "@babel/runtime": "^7",
29
29
  "bluebird": "^3.7.2",
@@ -38,13 +38,14 @@
38
38
  "js-yaml": "^3.14.1",
39
39
  "lodash": "^4.17.21",
40
40
  "mkdirp": "^0.5.5",
41
- "node-forge": "^0.10.0",
41
+ "node-forge": "^1.3.0",
42
42
  "opn": "^5.5.0",
43
43
  "pad": "^3.2.0",
44
44
  "promise-retry": "^1.1.1",
45
+ "ramda": "^0.28.0",
45
46
  "resolve": "^1.20.0",
46
47
  "rimraf": "^2.7.1",
47
- "simple-docker-registry-client": "^1.1.2",
48
- "strip-ansi": "^3.0.1"
48
+ "strip-ansi": "^3.0.1",
49
+ "www-authenticate": "^0.6.3"
49
50
  }
50
51
  }
@@ -1,82 +0,0 @@
1
- "use strict";
2
-
3
- var _chai = require("chai");
4
-
5
- var _registryClient = require("../registry-client");
6
-
7
- /* eslint-env mocha */
8
-
9
- /* eslint-disable no-unused-expressions */
10
-
11
- /* eslint-enable chai-friendly/no-unused-expressions */
12
- describe('docker registry client', function () {
13
- describe('getAuthForRegistry', function () {
14
- beforeEach(function () {
15
- this.config = {
16
- auths: {
17
- 'quay.io': {
18
- auth: 'pretend-base64-of-username-and-password',
19
- email: 'test@navy.rocks'
20
- },
21
- 'https://index.docker.io/v1/': {
22
- auth: 'pretend-base64-of-username-and-password',
23
- email: 'test@navy.rocks'
24
- }
25
- }
26
- };
27
- });
28
- it('should return the auth config for the given registry', function () {
29
- (0, _chai.expect)((0, _registryClient.getAuthForRegistry)('quay.io', this.config)).to.eql({
30
- auth: 'pretend-base64-of-username-and-password',
31
- email: 'test@navy.rocks'
32
- });
33
- });
34
- it('should return the auth config for Docker Hub if given', function () {
35
- (0, _chai.expect)((0, _registryClient.getAuthForRegistry)('registry-1.docker.io', this.config)).to.eql({
36
- auth: 'pretend-base64-of-username-and-password',
37
- email: 'test@navy.rocks'
38
- });
39
- });
40
- it('should return null if there is no authentication for the given registry', function () {
41
- (0, _chai.expect)((0, _registryClient.getAuthForRegistry)('foo.bar', this.config)).to.be.null;
42
- });
43
- it('should return null if there is no docker config', function () {
44
- (0, _chai.expect)((0, _registryClient.getAuthForRegistry)('foo.bar', null)).to.be.null;
45
- });
46
- });
47
- describe('credentialsFromAuth', function () {
48
- it('should return the username and password from base64 encoded auth', function () {
49
- (0, _chai.expect)((0, _registryClient.credentialsFromAuth)({
50
- auth: 'YmFyOnBhc3N3b3Jk'
51
- })).to.eql({
52
- username: 'bar',
53
- password: 'password'
54
- });
55
- });
56
- it('should throw invariant violation when auth is invalid base64', function () {
57
- (0, _chai.expect)(() => (0, _registryClient.credentialsFromAuth)({
58
- auth: 'zjasj'
59
- })).to.throw('Invalid base64 string in docker/config.json for registry authentication');
60
- });
61
- });
62
- describe('registryFromImage', function () {
63
- it('should return the correct registry domain from the given image', function () {
64
- (0, _chai.expect)((0, _registryClient.registryFromImage)('quay.io/someorg/someimage')).to.equal('quay.io');
65
- });
66
- it('should return the correct registry domain from the given image with tag', function () {
67
- (0, _chai.expect)((0, _registryClient.registryFromImage)('quay.io/someorg/someimage:some-tag')).to.equal('quay.io');
68
- });
69
- it('should return the correct registry domain from the given image from docker hub', function () {
70
- (0, _chai.expect)((0, _registryClient.registryFromImage)('someuser/someimage')).to.equal('registry-1.docker.io');
71
- });
72
- it('should return the correct registry domain from the given image with tag from docker hub', function () {
73
- (0, _chai.expect)((0, _registryClient.registryFromImage)('someuser/someimage:some-tag')).to.equal('registry-1.docker.io');
74
- });
75
- it('should return the correct registry domain from the given library image from docker hub', function () {
76
- (0, _chai.expect)((0, _registryClient.registryFromImage)('someimage')).to.equal('registry-1.docker.io');
77
- });
78
- it('should return the correct registry domain from the given library image with tag from docker hub', function () {
79
- (0, _chai.expect)((0, _registryClient.registryFromImage)('someimage:some-tag')).to.equal('registry-1.docker.io');
80
- });
81
- });
82
- });
@@ -1,81 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
-
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- exports.credentialsFromAuth = credentialsFromAuth;
9
- exports.getAuthForRegistry = getAuthForRegistry;
10
- exports.getRegistryClient = getRegistryClient;
11
- exports.registryFromImage = registryFromImage;
12
-
13
- var _path = _interopRequireDefault(require("path"));
14
-
15
- var _invariant = _interopRequireDefault(require("invariant"));
16
-
17
- var _simpleDockerRegistryClient = require("simple-docker-registry-client");
18
-
19
- var _fs = _interopRequireDefault(require("./fs"));
20
-
21
- const DEFAULT_REGISTRY = 'registry-1.docker.io'; // docker v2 registry URL
22
-
23
- const DEFAULT_REGISTRY_AUTH = 'https://index.docker.io/v1/'; // the url which docker stores in .docker/config.json for auth
24
-
25
- async function getDockerUserConfig() {
26
- (0, _invariant.default)(process.env.HOME, "NO_HOME_DIRECTORY: No home directory available");
27
-
28
- try {
29
- const rawConfig = await _fs.default.readFileAsync(_path.default.join(process.env.HOME, '.docker', 'config.json'));
30
- const config = JSON.parse(rawConfig);
31
- return config;
32
- } catch (ex) {
33
- return null;
34
- }
35
- }
36
-
37
- function getAuthForRegistry(registry, dockerUserConfig) {
38
- if (registry === DEFAULT_REGISTRY) {
39
- registry = DEFAULT_REGISTRY_AUTH;
40
- }
41
-
42
- if (dockerUserConfig && dockerUserConfig.auths && dockerUserConfig.auths[registry]) {
43
- return dockerUserConfig.auths[registry];
44
- }
45
-
46
- return null;
47
- }
48
-
49
- function registryFromImage(image) {
50
- const parsedRegistry = image.match(/([a-zA-Z0-9-.:]+)\/[a-zA-Z0-9-]+\/[a-zA-Z0-9-]+/);
51
- const registry = parsedRegistry != null && parsedRegistry.length > 1 ? parsedRegistry[1] : DEFAULT_REGISTRY;
52
- return registry;
53
- }
54
-
55
- function credentialsFromAuth(auth) {
56
- if (auth && auth.auth) {
57
- (0, _invariant.default)(auth.auth.match(/^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/) != null, "DOCKER_CONFIG_INVALID_AUTH_BASE64: Invalid base64 string in docker/config.json for registry authentication");
58
- const decoded = Buffer.from(auth.auth, 'base64').toString();
59
- const parts = decoded.split(':');
60
- return {
61
- username: parts[0],
62
- password: parts[1]
63
- };
64
- }
65
-
66
- return null;
67
- }
68
-
69
- async function getRegistryClient(image, navyFile) {
70
- const registry = registryFromImage(image);
71
- const opts = {
72
- registry: `https://${registry}`,
73
- allowUnauthorized: navyFile && navyFile.ignoreUnauthorizedRequestsForRegistries && navyFile.ignoreUnauthorizedRequestsForRegistries.indexOf(registry) !== -1
74
- }; // try and work out auth
75
-
76
- const auth = getAuthForRegistry(registry, await getDockerUserConfig());
77
- opts.credentials = credentialsFromAuth(auth);
78
- return {
79
- request: url => (0, _simpleDockerRegistryClient.registryRequest)(url, opts)
80
- };
81
- }