@jcoreio/aws-ecr-utils 1.0.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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016-present Andy Edwards
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # @jcoreio/aws-ecr-utils
2
+
3
+ [![CircleCI](https://circleci.com/gh/jcoreio/aws-ecr-utils.svg?style=svg)](https://circleci.com/gh/jcoreio/aws-ecr-utils)
4
+ [![Coverage Status](https://codecov.io/gh/jcoreio/aws-ecr-utils/branch/master/graph/badge.svg)](https://codecov.io/gh/jcoreio/aws-ecr-utils)
5
+ [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
6
+ [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
7
+ [![npm version](https://badge.fury.io/js/%40jcoreio%2Faws-ecr-utils.svg)](https://badge.fury.io/js/%40jcoreio%2Faws-ecr-utils)
8
+
9
+ # Table of Contents
10
+
11
+ - [@jcoreio/aws-ecr-utils](#jcoreioaws-ecr-utils)
12
+ - [Table of Contents](#table-of-contents)
13
+ - [`copyECRImage(options)`](#copyecrimageoptions)
14
+ - [Options](#options)
15
+ - [`options.from.imageUri`, `options.to.imageUri` (`string`, **required**)](#optionsfromimageuri-optionstoimageuri-string-required)
16
+ - [`options.from.ecr`, `options.to.ecr` (`AWS.ECR`, _optional_)](#optionsfromecr-optionstoecr-awsecr-optional)
17
+ - [`options.from.awsConfig`, `options.to.awsConfig` (`AWS.ConfigurationOptions`, _optional_)](#optionsfromawsconfig-optionstoawsconfig-awsconfigurationoptions-optional)
18
+ - [Returns (`Promise<void>`)](#returns-promisevoid)
19
+ - [`ecrImageExists(options)`](#ecrimageexistsoptions)
20
+ - [Options](#options-1)
21
+ - [`options.ecr` (`AWS.ECR`, _optional_)](#optionsecr-awsecr-optional)
22
+ - [`options.awsConfig` (`AWS.ConfigurationOptions`, _optional_)](#optionsawsconfig-awsconfigurationoptions-optional)
23
+ - [`options.imageUri` (`string`, _optional_)](#optionsimageuri-string-optional)
24
+ - [`options.registryId` (`string`, _optional_)](#optionsregistryid-string-optional)
25
+ - [`options.repositoryName` (`string`, _optional_)](#optionsrepositoryname-string-optional)
26
+ - [`options.imageTag` (`string`, _optional_)](#optionsimagetag-string-optional)
27
+ - [Returns (`Promise<boolean>`)](#returns-promiseboolean)
28
+ - [`loginToECR(options)`](#logintoecroptions)
29
+ - [Options](#options-2)
30
+ - [`options.ecr` (`AWS.ECR`, _optional_)](#optionsecr-awsecr-optional-1)
31
+ - [`options.awsConfig` (`AWS.ConfigurationOptions`, _optional_)](#optionsawsconfig-awsconfigurationoptions-optional-1)
32
+ - [Returns (`Promise<void>`)](#returns-promisevoid-1)
33
+ - [`parseECRImageUri(imageUri)`](#parseecrimageuriimageuri)
34
+ - [Options](#options-3)
35
+ - [`imageUri` (`string`, **required**)](#imageuri-string-required)
36
+ - [Returns (`object`)](#returns-object)
37
+ - [`tagECRImage(options)`](#tagecrimageoptions)
38
+ - [Options](#options-4)
39
+ - [`options.ecr` (`AWS.ECR`, _optional_)](#optionsecr-awsecr-optional-2)
40
+ - [`options.awsConfig` (`AWS.ConfigurationOptions`, _optional_)](#optionsawsconfig-awsconfigurationoptions-optional-2)
41
+ - [`options.imageUri` (`string`, **required**)](#optionsimageuri-string-required)
42
+ - [`options.tags` (`string[]`, **required**)](#optionstags-string-required)
43
+ - [Returns (`Promise<void>`)](#returns-promisevoid-2)
44
+
45
+ ## `copyECRImage(options)`
46
+
47
+ Copies an image between ECRs (potentially between accounts). Requires Docker to be installed and the `docker` command to be on your path.
48
+
49
+ ### Options
50
+
51
+ #### `options.from.imageUri`, `options.to.imageUri` (`string`, **required**)
52
+
53
+ The URIs of the source and destination ECR images
54
+
55
+ #### `options.from.ecr`, `options.to.ecr` (`AWS.ECR`, _optional_)
56
+
57
+ The ECR clients to use for the source and destination images
58
+
59
+ #### `options.from.awsConfig`, `options.to.awsConfig` (`AWS.ConfigurationOptions`, _optional_)
60
+
61
+ The AWS service options to use if `options.from.ecr` and `options.to.ecr` aren't provided
62
+
63
+ ### Returns (`Promise<void>`)
64
+
65
+ A promise that will resolve once the image has been pulled from the source repository and pushed to the destination repository.
66
+
67
+ ## `ecrImageExists(options)`
68
+
69
+ Determines if an ECR image exists.
70
+
71
+ ### Options
72
+
73
+ #### `options.ecr` (`AWS.ECR`, _optional_)
74
+
75
+ The ECR client to use
76
+
77
+ #### `options.awsConfig` (`AWS.ConfigurationOptions`, _optional_)
78
+
79
+ The AWS service options to use if `options.ecr` isn't provided
80
+
81
+ #### `options.imageUri` (`string`, _optional_)
82
+
83
+ The URI of the image to look for. You must provide either this or `options.registryId`,
84
+ `options.repositoryName`, or `imageTag`.
85
+
86
+ #### `options.registryId` (`string`, _optional_)
87
+
88
+ The ID of the ECR (same as your AWS account number?)
89
+
90
+ #### `options.repositoryName` (`string`, _optional_)
91
+
92
+ The name of the ECR repository
93
+
94
+ #### `options.imageTag` (`string`, _optional_)
95
+
96
+ The ECR image tag
97
+
98
+ ### Returns (`Promise<boolean>`)
99
+
100
+ A promise that will resolve to true if the image exists and false otherwise.
101
+
102
+ ## `loginToECR(options)`
103
+
104
+ Logs the local Docker client into the given ECR. Requires Docker to be installed and the `docker` command to be on your path.
105
+
106
+ ### Options
107
+
108
+ #### `options.ecr` (`AWS.ECR`, _optional_)
109
+
110
+ The ECR client to use
111
+
112
+ #### `options.awsConfig` (`AWS.ConfigurationOptions`, _optional_)
113
+
114
+ The AWS service options to use if `options.ecr` isn't provided
115
+
116
+ ### Returns (`Promise<void>`)
117
+
118
+ A promise that will resolve once logged in.
119
+
120
+ ## `parseECRImageUri(imageUri)`
121
+
122
+ Parses the given ECR image URI.
123
+
124
+ ### Options
125
+
126
+ #### `imageUri` (`string`, **required**)
127
+
128
+ The URI of the ECR image to parse.
129
+
130
+ ### Returns (`object`)
131
+
132
+ An object with the following properties:
133
+
134
+ ```ts
135
+ {
136
+ registryId: string
137
+ region: string
138
+ repositoryName: string
139
+ imageTag: string
140
+ }
141
+ ```
142
+
143
+ ## `tagECRImage(options)`
144
+
145
+ Adds additional tags to an existing ECR image.
146
+
147
+ ### Options
148
+
149
+ #### `options.ecr` (`AWS.ECR`, _optional_)
150
+
151
+ The ECR client to use
152
+
153
+ #### `options.awsConfig` (`AWS.ConfigurationOptions`, _optional_)
154
+
155
+ The AWS service options to use if `options.ecr` isn't provided
156
+
157
+ #### `options.imageUri` (`string`, **required**)
158
+
159
+ The URI of the ECR image to add tags to
160
+
161
+ #### `options.tags` (`string[]`, **required**)
162
+
163
+ The tags to add to the ECR image
164
+
165
+ ### Returns (`Promise<void>`)
166
+
167
+ A promise that will resolve once the tags have been added.
@@ -0,0 +1,13 @@
1
+ import AWS from 'aws-sdk';
2
+ export default function copyECRImage({ from, to, }: {
3
+ from: {
4
+ imageUri: string;
5
+ ecr?: AWS.ECR;
6
+ awsConfig?: AWS.ConfigurationOptions;
7
+ };
8
+ to: {
9
+ imageUri: string;
10
+ ecr?: AWS.ECR;
11
+ awsConfig?: AWS.ConfigurationOptions;
12
+ };
13
+ }): Promise<void>;
@@ -0,0 +1,127 @@
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"] = copyECRImage;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+
14
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
15
+
16
+ var _promisifyChildProcess = require("promisify-child-process");
17
+
18
+ var _loginToECR = _interopRequireDefault(require("./loginToECR"));
19
+
20
+ var _ecrImageExists = _interopRequireDefault(require("./ecrImageExists"));
21
+
22
+ var _parseECRImageUri3 = _interopRequireDefault(require("./parseECRImageUri"));
23
+
24
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
25
+
26
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
27
+
28
+ function copyECRImage(_x) {
29
+ return _copyECRImage.apply(this, arguments);
30
+ }
31
+
32
+ function _copyECRImage() {
33
+ _copyECRImage = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(_ref) {
34
+ var from, to, srcRepositoryUri, repositoryUri, _parseECRImageUri, fromRegion, _parseECRImageUri2, toRegion, repositoryName, imageTag;
35
+
36
+ return _regenerator["default"].wrap(function _callee$(_context) {
37
+ while (1) {
38
+ switch (_context.prev = _context.next) {
39
+ case 0:
40
+ from = _ref.from, to = _ref.to;
41
+
42
+ if (!(from.imageUri === to.imageUri)) {
43
+ _context.next = 3;
44
+ break;
45
+ }
46
+
47
+ return _context.abrupt("return");
48
+
49
+ case 3:
50
+ srcRepositoryUri = from.imageUri.replace(/:.+/, '');
51
+ repositoryUri = to.imageUri.replace(/:.+/, '');
52
+ _parseECRImageUri = (0, _parseECRImageUri3["default"])(from.imageUri), fromRegion = _parseECRImageUri.region;
53
+ _parseECRImageUri2 = (0, _parseECRImageUri3["default"])(to.imageUri), toRegion = _parseECRImageUri2.region, repositoryName = _parseECRImageUri2.repositoryName, imageTag = _parseECRImageUri2.imageTag;
54
+ _context.next = 9;
55
+ return (0, _ecrImageExists["default"])({
56
+ awsConfig: _objectSpread(_objectSpread({}, to.awsConfig), {}, {
57
+ region: toRegion
58
+ }),
59
+ ecr: to.ecr,
60
+ repositoryName: repositoryName,
61
+ imageTag: imageTag
62
+ });
63
+
64
+ case 9:
65
+ if (!_context.sent) {
66
+ _context.next = 13;
67
+ break;
68
+ }
69
+
70
+ // eslint-disable-next-line no-console
71
+ console.error("Clarity image already exists in your ECR: ".concat(repositoryName, ":").concat(imageTag));
72
+ _context.next = 27;
73
+ break;
74
+
75
+ case 13:
76
+ // eslint-disable-next-line no-console
77
+ console.error("Logging into source ECR: ".concat(srcRepositoryUri.replace(/\/.*/, ''), "..."));
78
+ _context.next = 16;
79
+ return (0, _loginToECR["default"])({
80
+ ecr: from.ecr,
81
+ awsConfig: _objectSpread(_objectSpread({}, from.awsConfig), {}, {
82
+ region: fromRegion
83
+ })
84
+ });
85
+
86
+ case 16:
87
+ // eslint-disable-next-line no-console
88
+ console.error("Pulling ".concat(from.imageUri, "..."));
89
+ _context.next = 19;
90
+ return (0, _promisifyChildProcess.spawn)('docker', ['pull', from.imageUri], {
91
+ stdio: 'inherit'
92
+ });
93
+
94
+ case 19:
95
+ // eslint-disable-next-line no-console
96
+ console.error("Logging into dest ECR: ".concat(repositoryUri.replace(/\/.*/, ''), "..."));
97
+ _context.next = 22;
98
+ return (0, _loginToECR["default"])({
99
+ ecr: to.ecr,
100
+ awsConfig: _objectSpread(_objectSpread({}, to.awsConfig), {}, {
101
+ region: toRegion
102
+ })
103
+ });
104
+
105
+ case 22:
106
+ // eslint-disable-next-line no-console
107
+ console.error("Pushing ".concat(to.imageUri, "..."));
108
+ _context.next = 25;
109
+ return (0, _promisifyChildProcess.spawn)('docker', ['tag', from.imageUri, to.imageUri], {
110
+ stdio: 'inherit'
111
+ });
112
+
113
+ case 25:
114
+ _context.next = 27;
115
+ return (0, _promisifyChildProcess.spawn)('docker', ['push', to.imageUri], {
116
+ stdio: 'inherit'
117
+ });
118
+
119
+ case 27:
120
+ case "end":
121
+ return _context.stop();
122
+ }
123
+ }
124
+ }, _callee);
125
+ }));
126
+ return _copyECRImage.apply(this, arguments);
127
+ }
@@ -0,0 +1,14 @@
1
+ // @flow
2
+
3
+ declare export default function copyECRImage(options: {|
4
+ from: {
5
+ imageUri: string,
6
+ ecr: any,
7
+ awsConfig: { ... },
8
+ },
9
+ to: {
10
+ imageUri: string,
11
+ ecr: any,
12
+ awsConfig: { ... },
13
+ },
14
+ |}): Promise<void>
@@ -0,0 +1,9 @@
1
+ import AWS from 'aws-sdk';
2
+ export default function ecrImageExists({ ecr, awsConfig, imageUri, registryId, repositoryName, imageTag, }: {
3
+ ecr?: AWS.ECR;
4
+ awsConfig?: AWS.ConfigurationOptions;
5
+ imageUri?: string;
6
+ registryId?: string;
7
+ repositoryName?: string;
8
+ imageTag?: string;
9
+ }): Promise<boolean>;
@@ -0,0 +1,97 @@
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"] = ecrImageExists;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+
16
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
17
+
18
+ var _awsSdk = _interopRequireDefault(require("aws-sdk"));
19
+
20
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
21
+
22
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
23
+
24
+ function ecrImageExists(_x) {
25
+ return _ecrImageExists.apply(this, arguments);
26
+ }
27
+
28
+ function _ecrImageExists() {
29
+ _ecrImageExists = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(_ref) {
30
+ var ecr, awsConfig, imageUri, registryId, repositoryName, imageTag, region, match, _match;
31
+
32
+ return _regenerator["default"].wrap(function _callee$(_context) {
33
+ while (1) {
34
+ switch (_context.prev = _context.next) {
35
+ case 0:
36
+ ecr = _ref.ecr, awsConfig = _ref.awsConfig, imageUri = _ref.imageUri, registryId = _ref.registryId, repositoryName = _ref.repositoryName, imageTag = _ref.imageTag;
37
+
38
+ if (!imageUri) {
39
+ _context.next = 10;
40
+ break;
41
+ }
42
+
43
+ match = /(\d+)\.dkr\.ecr\.(.+?)\.amazonaws\.com\/(.+?):(.+)/.exec(imageUri);
44
+
45
+ if (match) {
46
+ _context.next = 5;
47
+ break;
48
+ }
49
+
50
+ throw new Error("failed to parse imageUri: ".concat(imageUri));
51
+
52
+ case 5:
53
+ _match = (0, _slicedToArray2["default"])(match, 5);
54
+ registryId = _match[1];
55
+ region = _match[2];
56
+ repositoryName = _match[3];
57
+ imageTag = _match[4];
58
+
59
+ case 10:
60
+ if (!region) region = awsConfig === null || awsConfig === void 0 ? void 0 : awsConfig.region;
61
+ if (!ecr) ecr = new _awsSdk["default"].ECR(_objectSpread(_objectSpread({}, awsConfig), {}, {
62
+ region: region
63
+ }));
64
+
65
+ if (!(!repositoryName || !imageTag)) {
66
+ _context.next = 14;
67
+ break;
68
+ }
69
+
70
+ throw new Error("missing repositoryName/imageTag or imageUri");
71
+
72
+ case 14:
73
+ _context.next = 16;
74
+ return ecr.describeImages({
75
+ registryId: registryId,
76
+ repositoryName: repositoryName,
77
+ imageIds: [{
78
+ imageTag: imageTag
79
+ }]
80
+ }).promise().then(function () {
81
+ return true;
82
+ }, function () {
83
+ return false;
84
+ });
85
+
86
+ case 16:
87
+ return _context.abrupt("return", _context.sent);
88
+
89
+ case 17:
90
+ case "end":
91
+ return _context.stop();
92
+ }
93
+ }
94
+ }, _callee);
95
+ }));
96
+ return _ecrImageExists.apply(this, arguments);
97
+ }
@@ -0,0 +1,10 @@
1
+ // @flow
2
+
3
+ declare export default function ecrImageExists(options: {|
4
+ ecr?: any,
5
+ awsConfig?: { ... },
6
+ imageUri?: string,
7
+ registryId?: string,
8
+ repositoryName?: string,
9
+ imageTag?: string,
10
+ |}): Promise<boolean>
@@ -0,0 +1,13 @@
1
+ import AWS from 'aws-sdk';
2
+ export default function copyECRImage({ from, to, }: {
3
+ from: {
4
+ imageUri: string;
5
+ ecr?: AWS.ECR;
6
+ awsConfig?: AWS.ConfigurationOptions;
7
+ };
8
+ to: {
9
+ imageUri: string;
10
+ ecr?: AWS.ECR;
11
+ awsConfig?: AWS.ConfigurationOptions;
12
+ };
13
+ }): Promise<void>;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = copyECRImage;
7
+
8
+ var _promisifyChildProcess = require("promisify-child-process");
9
+
10
+ var _loginToECR = _interopRequireDefault(require("./loginToECR"));
11
+
12
+ var _ecrImageExists = _interopRequireDefault(require("./ecrImageExists"));
13
+
14
+ var _parseECRImageUri = _interopRequireDefault(require("./parseECRImageUri"));
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ async function copyECRImage({
19
+ from,
20
+ to
21
+ }) {
22
+ if (from.imageUri === to.imageUri) return;
23
+ const srcRepositoryUri = from.imageUri.replace(/:.+/, '');
24
+ const repositoryUri = to.imageUri.replace(/:.+/, '');
25
+ const {
26
+ region: fromRegion
27
+ } = (0, _parseECRImageUri.default)(from.imageUri);
28
+ const {
29
+ region: toRegion,
30
+ repositoryName,
31
+ imageTag
32
+ } = (0, _parseECRImageUri.default)(to.imageUri);
33
+
34
+ if (await (0, _ecrImageExists.default)({
35
+ awsConfig: { ...to.awsConfig,
36
+ region: toRegion
37
+ },
38
+ ecr: to.ecr,
39
+ repositoryName,
40
+ imageTag
41
+ })) {
42
+ // eslint-disable-next-line no-console
43
+ console.error(`Clarity image already exists in your ECR: ${repositoryName}:${imageTag}`);
44
+ } else {
45
+ // eslint-disable-next-line no-console
46
+ console.error(`Logging into source ECR: ${srcRepositoryUri.replace(/\/.*/, '')}...`);
47
+ await (0, _loginToECR.default)({
48
+ ecr: from.ecr,
49
+ awsConfig: { ...from.awsConfig,
50
+ region: fromRegion
51
+ }
52
+ }); // eslint-disable-next-line no-console
53
+
54
+ console.error(`Pulling ${from.imageUri}...`);
55
+ await (0, _promisifyChildProcess.spawn)('docker', ['pull', from.imageUri], {
56
+ stdio: 'inherit'
57
+ }); // eslint-disable-next-line no-console
58
+
59
+ console.error(`Logging into dest ECR: ${repositoryUri.replace(/\/.*/, '')}...`);
60
+ await (0, _loginToECR.default)({
61
+ ecr: to.ecr,
62
+ awsConfig: { ...to.awsConfig,
63
+ region: toRegion
64
+ }
65
+ }); // eslint-disable-next-line no-console
66
+
67
+ console.error(`Pushing ${to.imageUri}...`);
68
+ await (0, _promisifyChildProcess.spawn)('docker', ['tag', from.imageUri, to.imageUri], {
69
+ stdio: 'inherit'
70
+ });
71
+ await (0, _promisifyChildProcess.spawn)('docker', ['push', to.imageUri], {
72
+ stdio: 'inherit'
73
+ });
74
+ }
75
+ }
76
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb3B5RUNSSW1hZ2UudHMiXSwibmFtZXMiOlsiY29weUVDUkltYWdlIiwiZnJvbSIsInRvIiwiaW1hZ2VVcmkiLCJzcmNSZXBvc2l0b3J5VXJpIiwicmVwbGFjZSIsInJlcG9zaXRvcnlVcmkiLCJyZWdpb24iLCJmcm9tUmVnaW9uIiwidG9SZWdpb24iLCJyZXBvc2l0b3J5TmFtZSIsImltYWdlVGFnIiwiYXdzQ29uZmlnIiwiZWNyIiwiY29uc29sZSIsImVycm9yIiwic3RkaW8iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVlLGVBQWVBLFlBQWYsQ0FBNEI7QUFDekNDLEVBQUFBLElBRHlDO0FBRXpDQyxFQUFBQTtBQUZ5QyxDQUE1QixFQWNHO0FBQ2hCLE1BQUlELElBQUksQ0FBQ0UsUUFBTCxLQUFrQkQsRUFBRSxDQUFDQyxRQUF6QixFQUFtQztBQUNuQyxRQUFNQyxnQkFBZ0IsR0FBR0gsSUFBSSxDQUFDRSxRQUFMLENBQWNFLE9BQWQsQ0FBc0IsS0FBdEIsRUFBNkIsRUFBN0IsQ0FBekI7QUFDQSxRQUFNQyxhQUFhLEdBQUdKLEVBQUUsQ0FBQ0MsUUFBSCxDQUFZRSxPQUFaLENBQW9CLEtBQXBCLEVBQTJCLEVBQTNCLENBQXRCO0FBRUEsUUFBTTtBQUFFRSxJQUFBQSxNQUFNLEVBQUVDO0FBQVYsTUFBeUIsK0JBQWlCUCxJQUFJLENBQUNFLFFBQXRCLENBQS9CO0FBQ0EsUUFBTTtBQUNKSSxJQUFBQSxNQUFNLEVBQUVFLFFBREo7QUFFSkMsSUFBQUEsY0FGSTtBQUdKQyxJQUFBQTtBQUhJLE1BSUYsK0JBQWlCVCxFQUFFLENBQUNDLFFBQXBCLENBSko7O0FBTUEsTUFDRSxNQUFNLDZCQUFlO0FBQ25CUyxJQUFBQSxTQUFTLEVBQUUsRUFBRSxHQUFHVixFQUFFLENBQUNVLFNBQVI7QUFBbUJMLE1BQUFBLE1BQU0sRUFBRUU7QUFBM0IsS0FEUTtBQUVuQkksSUFBQUEsR0FBRyxFQUFFWCxFQUFFLENBQUNXLEdBRlc7QUFHbkJILElBQUFBLGNBSG1CO0FBSW5CQyxJQUFBQTtBQUptQixHQUFmLENBRFIsRUFPRTtBQUNBO0FBQ0FHLElBQUFBLE9BQU8sQ0FBQ0MsS0FBUixDQUNHLDZDQUE0Q0wsY0FBZSxJQUFHQyxRQUFTLEVBRDFFO0FBR0QsR0FaRCxNQVlPO0FBQ0w7QUFDQUcsSUFBQUEsT0FBTyxDQUFDQyxLQUFSLENBQ0csNEJBQTJCWCxnQkFBZ0IsQ0FBQ0MsT0FBakIsQ0FBeUIsTUFBekIsRUFBaUMsRUFBakMsQ0FBcUMsS0FEbkU7QUFJQSxVQUFNLHlCQUFXO0FBQ2ZRLE1BQUFBLEdBQUcsRUFBRVosSUFBSSxDQUFDWSxHQURLO0FBRWZELE1BQUFBLFNBQVMsRUFBRSxFQUFFLEdBQUdYLElBQUksQ0FBQ1csU0FBVjtBQUFxQkwsUUFBQUEsTUFBTSxFQUFFQztBQUE3QjtBQUZJLEtBQVgsQ0FBTixDQU5LLENBV0w7O0FBQ0FNLElBQUFBLE9BQU8sQ0FBQ0MsS0FBUixDQUFlLFdBQVVkLElBQUksQ0FBQ0UsUUFBUyxLQUF2QztBQUNBLFVBQU0sa0NBQU0sUUFBTixFQUFnQixDQUFDLE1BQUQsRUFBU0YsSUFBSSxDQUFDRSxRQUFkLENBQWhCLEVBQXlDO0FBQUVhLE1BQUFBLEtBQUssRUFBRTtBQUFULEtBQXpDLENBQU4sQ0FiSyxDQWVMOztBQUNBRixJQUFBQSxPQUFPLENBQUNDLEtBQVIsQ0FDRywwQkFBeUJULGFBQWEsQ0FBQ0QsT0FBZCxDQUFzQixNQUF0QixFQUE4QixFQUE5QixDQUFrQyxLQUQ5RDtBQUdBLFVBQU0seUJBQVc7QUFDZlEsTUFBQUEsR0FBRyxFQUFFWCxFQUFFLENBQUNXLEdBRE87QUFFZkQsTUFBQUEsU0FBUyxFQUFFLEVBQUUsR0FBR1YsRUFBRSxDQUFDVSxTQUFSO0FBQW1CTCxRQUFBQSxNQUFNLEVBQUVFO0FBQTNCO0FBRkksS0FBWCxDQUFOLENBbkJLLENBd0JMOztBQUNBSyxJQUFBQSxPQUFPLENBQUNDLEtBQVIsQ0FBZSxXQUFVYixFQUFFLENBQUNDLFFBQVMsS0FBckM7QUFDQSxVQUFNLGtDQUFNLFFBQU4sRUFBZ0IsQ0FBQyxLQUFELEVBQVFGLElBQUksQ0FBQ0UsUUFBYixFQUF1QkQsRUFBRSxDQUFDQyxRQUExQixDQUFoQixFQUFxRDtBQUN6RGEsTUFBQUEsS0FBSyxFQUFFO0FBRGtELEtBQXJELENBQU47QUFHQSxVQUFNLGtDQUFNLFFBQU4sRUFBZ0IsQ0FBQyxNQUFELEVBQVNkLEVBQUUsQ0FBQ0MsUUFBWixDQUFoQixFQUF1QztBQUFFYSxNQUFBQSxLQUFLLEVBQUU7QUFBVCxLQUF2QyxDQUFOO0FBQ0Q7QUFDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBBV1MgZnJvbSAnYXdzLXNkaydcbmltcG9ydCB7IHNwYXduIH0gZnJvbSAncHJvbWlzaWZ5LWNoaWxkLXByb2Nlc3MnXG5pbXBvcnQgbG9naW5Ub0VDUiBmcm9tICcuL2xvZ2luVG9FQ1InXG5pbXBvcnQgZWNySW1hZ2VFeGlzdHMgZnJvbSAnLi9lY3JJbWFnZUV4aXN0cydcbmltcG9ydCBwYXJzZUVDUkltYWdlVXJpIGZyb20gJy4vcGFyc2VFQ1JJbWFnZVVyaSdcblxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gY29weUVDUkltYWdlKHtcbiAgZnJvbSxcbiAgdG8sXG59OiB7XG4gIGZyb206IHtcbiAgICBpbWFnZVVyaTogc3RyaW5nXG4gICAgZWNyPzogQVdTLkVDUlxuICAgIGF3c0NvbmZpZz86IEFXUy5Db25maWd1cmF0aW9uT3B0aW9uc1xuICB9XG4gIHRvOiB7XG4gICAgaW1hZ2VVcmk6IHN0cmluZ1xuICAgIGVjcj86IEFXUy5FQ1JcbiAgICBhd3NDb25maWc/OiBBV1MuQ29uZmlndXJhdGlvbk9wdGlvbnNcbiAgfVxufSk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoZnJvbS5pbWFnZVVyaSA9PT0gdG8uaW1hZ2VVcmkpIHJldHVyblxuICBjb25zdCBzcmNSZXBvc2l0b3J5VXJpID0gZnJvbS5pbWFnZVVyaS5yZXBsYWNlKC86LisvLCAnJylcbiAgY29uc3QgcmVwb3NpdG9yeVVyaSA9IHRvLmltYWdlVXJpLnJlcGxhY2UoLzouKy8sICcnKVxuXG4gIGNvbnN0IHsgcmVnaW9uOiBmcm9tUmVnaW9uIH0gPSBwYXJzZUVDUkltYWdlVXJpKGZyb20uaW1hZ2VVcmkpXG4gIGNvbnN0IHtcbiAgICByZWdpb246IHRvUmVnaW9uLFxuICAgIHJlcG9zaXRvcnlOYW1lLFxuICAgIGltYWdlVGFnLFxuICB9ID0gcGFyc2VFQ1JJbWFnZVVyaSh0by5pbWFnZVVyaSlcblxuICBpZiAoXG4gICAgYXdhaXQgZWNySW1hZ2VFeGlzdHMoe1xuICAgICAgYXdzQ29uZmlnOiB7IC4uLnRvLmF3c0NvbmZpZywgcmVnaW9uOiB0b1JlZ2lvbiB9LFxuICAgICAgZWNyOiB0by5lY3IsXG4gICAgICByZXBvc2l0b3J5TmFtZSxcbiAgICAgIGltYWdlVGFnLFxuICAgIH0pXG4gICkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgIGBDbGFyaXR5IGltYWdlIGFscmVhZHkgZXhpc3RzIGluIHlvdXIgRUNSOiAke3JlcG9zaXRvcnlOYW1lfToke2ltYWdlVGFnfWBcbiAgICApXG4gIH0gZWxzZSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgYExvZ2dpbmcgaW50byBzb3VyY2UgRUNSOiAke3NyY1JlcG9zaXRvcnlVcmkucmVwbGFjZSgvXFwvLiovLCAnJyl9Li4uYFxuICAgIClcblxuICAgIGF3YWl0IGxvZ2luVG9FQ1Ioe1xuICAgICAgZWNyOiBmcm9tLmVjcixcbiAgICAgIGF3c0NvbmZpZzogeyAuLi5mcm9tLmF3c0NvbmZpZywgcmVnaW9uOiBmcm9tUmVnaW9uIH0sXG4gICAgfSlcblxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS5lcnJvcihgUHVsbGluZyAke2Zyb20uaW1hZ2VVcml9Li4uYClcbiAgICBhd2FpdCBzcGF3bignZG9ja2VyJywgWydwdWxsJywgZnJvbS5pbWFnZVVyaV0sIHsgc3RkaW86ICdpbmhlcml0JyB9KVxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmVycm9yKFxuICAgICAgYExvZ2dpbmcgaW50byBkZXN0IEVDUjogJHtyZXBvc2l0b3J5VXJpLnJlcGxhY2UoL1xcLy4qLywgJycpfS4uLmBcbiAgICApXG4gICAgYXdhaXQgbG9naW5Ub0VDUih7XG4gICAgICBlY3I6IHRvLmVjcixcbiAgICAgIGF3c0NvbmZpZzogeyAuLi50by5hd3NDb25maWcsIHJlZ2lvbjogdG9SZWdpb24gfSxcbiAgICB9KVxuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmVycm9yKGBQdXNoaW5nICR7dG8uaW1hZ2VVcml9Li4uYClcbiAgICBhd2FpdCBzcGF3bignZG9ja2VyJywgWyd0YWcnLCBmcm9tLmltYWdlVXJpLCB0by5pbWFnZVVyaV0sIHtcbiAgICAgIHN0ZGlvOiAnaW5oZXJpdCcsXG4gICAgfSlcbiAgICBhd2FpdCBzcGF3bignZG9ja2VyJywgWydwdXNoJywgdG8uaW1hZ2VVcmldLCB7IHN0ZGlvOiAnaW5oZXJpdCcgfSlcbiAgfVxufVxuIl19
@@ -0,0 +1,14 @@
1
+ // @flow
2
+
3
+ declare export default function copyECRImage(options: {|
4
+ from: {
5
+ imageUri: string,
6
+ ecr: any,
7
+ awsConfig: { ... },
8
+ },
9
+ to: {
10
+ imageUri: string,
11
+ ecr: any,
12
+ awsConfig: { ... },
13
+ },
14
+ |}): Promise<void>
@@ -0,0 +1,9 @@
1
+ import AWS from 'aws-sdk';
2
+ export default function ecrImageExists({ ecr, awsConfig, imageUri, registryId, repositoryName, imageTag, }: {
3
+ ecr?: AWS.ECR;
4
+ awsConfig?: AWS.ConfigurationOptions;
5
+ imageUri?: string;
6
+ registryId?: string;
7
+ repositoryName?: string;
8
+ imageTag?: string;
9
+ }): Promise<boolean>;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = ecrImageExists;
7
+
8
+ var _awsSdk = _interopRequireDefault(require("aws-sdk"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ async function ecrImageExists({
13
+ ecr,
14
+ awsConfig,
15
+ imageUri,
16
+ registryId,
17
+ repositoryName,
18
+ imageTag
19
+ }) {
20
+ let region;
21
+
22
+ if (imageUri) {
23
+ const match = /(\d+)\.dkr\.ecr\.(.+?)\.amazonaws\.com\/(.+?):(.+)/.exec(imageUri);
24
+ if (!match) throw new Error(`failed to parse imageUri: ${imageUri}`);
25
+ [, registryId, region, repositoryName, imageTag] = match;
26
+ }
27
+
28
+ if (!region) region = awsConfig === null || awsConfig === void 0 ? void 0 : awsConfig.region;
29
+ if (!ecr) ecr = new _awsSdk.default.ECR({ ...awsConfig,
30
+ region
31
+ });
32
+
33
+ if (!repositoryName || !imageTag) {
34
+ throw new Error(`missing repositoryName/imageTag or imageUri`);
35
+ }
36
+
37
+ return await ecr.describeImages({
38
+ registryId,
39
+ repositoryName,
40
+ imageIds: [{
41
+ imageTag
42
+ }]
43
+ }).promise().then(() => true, () => false);
44
+ }
45
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9lY3JJbWFnZUV4aXN0cy50cyJdLCJuYW1lcyI6WyJlY3JJbWFnZUV4aXN0cyIsImVjciIsImF3c0NvbmZpZyIsImltYWdlVXJpIiwicmVnaXN0cnlJZCIsInJlcG9zaXRvcnlOYW1lIiwiaW1hZ2VUYWciLCJyZWdpb24iLCJtYXRjaCIsImV4ZWMiLCJFcnJvciIsIkFXUyIsIkVDUiIsImRlc2NyaWJlSW1hZ2VzIiwiaW1hZ2VJZHMiLCJwcm9taXNlIiwidGhlbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBOzs7O0FBRWUsZUFBZUEsY0FBZixDQUE4QjtBQUMzQ0MsRUFBQUEsR0FEMkM7QUFFM0NDLEVBQUFBLFNBRjJDO0FBRzNDQyxFQUFBQSxRQUgyQztBQUkzQ0MsRUFBQUEsVUFKMkM7QUFLM0NDLEVBQUFBLGNBTDJDO0FBTTNDQyxFQUFBQTtBQU4yQyxDQUE5QixFQWNNO0FBQ25CLE1BQUlDLE1BQUo7O0FBQ0EsTUFBSUosUUFBSixFQUFjO0FBQ1osVUFBTUssS0FBSyxHQUFHLHFEQUFxREMsSUFBckQsQ0FDWk4sUUFEWSxDQUFkO0FBR0EsUUFBSSxDQUFDSyxLQUFMLEVBQVksTUFBTSxJQUFJRSxLQUFKLENBQVcsNkJBQTRCUCxRQUFTLEVBQWhELENBQU47QUFDWCxPQUFHQyxVQUFILEVBQWVHLE1BQWYsRUFBdUJGLGNBQXZCLEVBQXVDQyxRQUF2QyxJQUFtREUsS0FBbkQ7QUFDRjs7QUFDRCxNQUFJLENBQUNELE1BQUwsRUFBYUEsTUFBTSxHQUFHTCxTQUFILGFBQUdBLFNBQUgsdUJBQUdBLFNBQVMsQ0FBRUssTUFBcEI7QUFDYixNQUFJLENBQUNOLEdBQUwsRUFBVUEsR0FBRyxHQUFHLElBQUlVLGdCQUFJQyxHQUFSLENBQVksRUFBRSxHQUFHVixTQUFMO0FBQWdCSyxJQUFBQTtBQUFoQixHQUFaLENBQU47O0FBRVYsTUFBSSxDQUFDRixjQUFELElBQW1CLENBQUNDLFFBQXhCLEVBQWtDO0FBQ2hDLFVBQU0sSUFBSUksS0FBSixDQUFXLDZDQUFYLENBQU47QUFDRDs7QUFDRCxTQUFPLE1BQU1ULEdBQUcsQ0FDYlksY0FEVSxDQUNLO0FBQ2RULElBQUFBLFVBRGM7QUFFZEMsSUFBQUEsY0FGYztBQUdkUyxJQUFBQSxRQUFRLEVBQUUsQ0FBQztBQUFFUixNQUFBQTtBQUFGLEtBQUQ7QUFISSxHQURMLEVBTVZTLE9BTlUsR0FPVkMsSUFQVSxDQVFULE1BQU0sSUFSRyxFQVNULE1BQU0sS0FURyxDQUFiO0FBV0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQVdTIGZyb20gJ2F3cy1zZGsnXG5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGVjckltYWdlRXhpc3RzKHtcbiAgZWNyLFxuICBhd3NDb25maWcsXG4gIGltYWdlVXJpLFxuICByZWdpc3RyeUlkLFxuICByZXBvc2l0b3J5TmFtZSxcbiAgaW1hZ2VUYWcsXG59OiB7XG4gIGVjcj86IEFXUy5FQ1JcbiAgYXdzQ29uZmlnPzogQVdTLkNvbmZpZ3VyYXRpb25PcHRpb25zXG4gIGltYWdlVXJpPzogc3RyaW5nXG4gIHJlZ2lzdHJ5SWQ/OiBzdHJpbmdcbiAgcmVwb3NpdG9yeU5hbWU/OiBzdHJpbmdcbiAgaW1hZ2VUYWc/OiBzdHJpbmdcbn0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgbGV0IHJlZ2lvblxuICBpZiAoaW1hZ2VVcmkpIHtcbiAgICBjb25zdCBtYXRjaCA9IC8oXFxkKylcXC5ka3JcXC5lY3JcXC4oLis/KVxcLmFtYXpvbmF3c1xcLmNvbVxcLyguKz8pOiguKykvLmV4ZWMoXG4gICAgICBpbWFnZVVyaVxuICAgIClcbiAgICBpZiAoIW1hdGNoKSB0aHJvdyBuZXcgRXJyb3IoYGZhaWxlZCB0byBwYXJzZSBpbWFnZVVyaTogJHtpbWFnZVVyaX1gKVxuICAgIDtbLCByZWdpc3RyeUlkLCByZWdpb24sIHJlcG9zaXRvcnlOYW1lLCBpbWFnZVRhZ10gPSBtYXRjaFxuICB9XG4gIGlmICghcmVnaW9uKSByZWdpb24gPSBhd3NDb25maWc/LnJlZ2lvblxuICBpZiAoIWVjcikgZWNyID0gbmV3IEFXUy5FQ1IoeyAuLi5hd3NDb25maWcsIHJlZ2lvbiB9KVxuXG4gIGlmICghcmVwb3NpdG9yeU5hbWUgfHwgIWltYWdlVGFnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBtaXNzaW5nIHJlcG9zaXRvcnlOYW1lL2ltYWdlVGFnIG9yIGltYWdlVXJpYClcbiAgfVxuICByZXR1cm4gYXdhaXQgZWNyXG4gICAgLmRlc2NyaWJlSW1hZ2VzKHtcbiAgICAgIHJlZ2lzdHJ5SWQsXG4gICAgICByZXBvc2l0b3J5TmFtZSxcbiAgICAgIGltYWdlSWRzOiBbeyBpbWFnZVRhZyB9XSxcbiAgICB9KVxuICAgIC5wcm9taXNlKClcbiAgICAudGhlbihcbiAgICAgICgpID0+IHRydWUsXG4gICAgICAoKSA9PiBmYWxzZVxuICAgIClcbn1cbiJdfQ==
@@ -0,0 +1,10 @@
1
+ // @flow
2
+
3
+ declare export default function ecrImageExists(options: {|
4
+ ecr?: any,
5
+ awsConfig?: { ... },
6
+ imageUri?: string,
7
+ registryId?: string,
8
+ repositoryName?: string,
9
+ imageTag?: string,
10
+ |}): Promise<boolean>
package/es/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { default as copyECRImage } from './copyECRImage';
2
+ export { default as ecrImageExists } from './ecrImageExists';
3
+ export { default as loginToECR } from './loginToECR';
4
+ export { default as tagECRImage } from './tagECRImage';
5
+ export { default as parseECRImageUri } from './parseECRImageUri';