@jcoreio/aws-ecr-utils 1.3.1 → 2.1.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/ImageManifestSchema.d.mts +59 -0
- package/ImageManifestSchema.d.mts.map +1 -0
- package/ImageManifestSchema.d.ts +50 -49
- package/ImageManifestSchema.d.ts.map +1 -0
- package/ImageManifestSchema.js +2 -1
- package/ImageManifestSchema.js.map +1 -0
- package/ImageManifestSchema.mjs +2 -1
- package/ImageManifestSchema.mjs.map +1 -0
- package/checkECRImageAccess.d.mts +25 -0
- package/checkECRImageAccess.d.mts.map +1 -0
- package/checkECRImageAccess.d.ts +25 -17
- package/checkECRImageAccess.d.ts.map +1 -0
- package/checkECRImageAccess.js +65 -65
- package/checkECRImageAccess.js.map +1 -0
- package/checkECRImageAccess.mjs +22 -19
- package/checkECRImageAccess.mjs.map +1 -0
- package/checkECRRepositoryPolicy.d.mts +28 -0
- package/checkECRRepositoryPolicy.d.mts.map +1 -0
- package/checkECRRepositoryPolicy.d.ts +21 -12
- package/checkECRRepositoryPolicy.d.ts.map +1 -0
- package/checkECRRepositoryPolicy.js +27 -26
- package/checkECRRepositoryPolicy.js.map +1 -0
- package/checkECRRepositoryPolicy.mjs +11 -9
- package/checkECRRepositoryPolicy.mjs.map +1 -0
- package/copyECRImage.d.mts +17 -0
- package/copyECRImage.d.mts.map +1 -0
- package/copyECRImage.d.ts +17 -12
- package/copyECRImage.d.ts.map +1 -0
- package/copyECRImage.js +21 -20
- package/copyECRImage.js.map +1 -0
- package/copyECRImage.mjs +2 -1
- package/copyECRImage.mjs.map +1 -0
- package/ecrImageExists.d.mts +17 -0
- package/ecrImageExists.d.mts.map +1 -0
- package/ecrImageExists.d.ts +17 -8
- package/ecrImageExists.d.ts.map +1 -0
- package/ecrImageExists.js +17 -16
- package/ecrImageExists.js.map +1 -0
- package/ecrImageExists.mjs +6 -5
- package/ecrImageExists.mjs.map +1 -0
- package/formatECRImageUri.d.mts +12 -0
- package/formatECRImageUri.d.mts.map +1 -0
- package/formatECRImageUri.d.ts +12 -5
- package/formatECRImageUri.d.ts.map +1 -0
- package/formatECRImageUri.js +2 -1
- package/formatECRImageUri.js.map +1 -0
- package/formatECRImageUri.mjs +2 -1
- package/formatECRImageUri.mjs.map +1 -0
- package/formatECRRepositoryHostname.d.mts +10 -0
- package/formatECRRepositoryHostname.d.mts.map +1 -0
- package/formatECRRepositoryHostname.d.ts +10 -4
- package/formatECRRepositoryHostname.d.ts.map +1 -0
- package/formatECRRepositoryHostname.js +2 -1
- package/formatECRRepositoryHostname.js.map +1 -0
- package/formatECRRepositoryHostname.mjs +2 -1
- package/formatECRRepositoryHostname.mjs.map +1 -0
- package/index.d.mts +12 -0
- package/index.d.mts.map +1 -0
- package/index.d.ts +12 -11
- package/index.d.ts.map +1 -0
- package/index.js +2 -1
- package/index.js.map +1 -0
- package/index.mjs +2 -1
- package/index.mjs.map +1 -0
- package/loginToECR.d.mts +11 -0
- package/loginToECR.d.mts.map +1 -0
- package/loginToECR.d.ts +11 -7
- package/loginToECR.d.ts.map +1 -0
- package/loginToECR.js +96 -28
- package/loginToECR.js.map +1 -0
- package/loginToECR.mjs +46 -8
- package/loginToECR.mjs.map +1 -0
- package/package.json +17 -6
- package/parseECRImageUri.d.mts +7 -0
- package/parseECRImageUri.d.mts.map +1 -0
- package/parseECRImageUri.d.ts +7 -6
- package/parseECRImageUri.d.ts.map +1 -0
- package/parseECRImageUri.js +2 -1
- package/parseECRImageUri.js.map +1 -0
- package/parseECRImageUri.mjs +2 -1
- package/parseECRImageUri.mjs.map +1 -0
- package/parseECRRepositoryHostname.d.mts +6 -0
- package/parseECRRepositoryHostname.d.mts.map +1 -0
- package/parseECRRepositoryHostname.d.ts +6 -5
- package/parseECRRepositoryHostname.d.ts.map +1 -0
- package/parseECRRepositoryHostname.js +2 -1
- package/parseECRRepositoryHostname.js.map +1 -0
- package/parseECRRepositoryHostname.mjs +2 -1
- package/parseECRRepositoryHostname.mjs.map +1 -0
- package/src/ImageManifestSchema.ts +19 -0
- package/src/checkECRImageAccess.ts +193 -0
- package/src/checkECRRepositoryPolicy.ts +153 -0
- package/src/copyECRImage.ts +76 -0
- package/src/ecrImageExists.ts +48 -0
- package/src/formatECRImageUri.ts +19 -0
- package/src/formatECRRepositoryHostname.ts +11 -0
- package/src/index.ts +11 -0
- package/src/loginToECR.ts +96 -0
- package/src/parseECRImageUri.ts +13 -0
- package/src/parseECRRepositoryHostname.ts +12 -0
- package/src/tagECRImage.ts +57 -0
- package/src/upsertECRRepository.ts +40 -0
- package/tagECRImage.d.mts +16 -0
- package/tagECRImage.d.mts.map +1 -0
- package/tagECRImage.d.ts +13 -6
- package/tagECRImage.d.ts.map +1 -0
- package/tagECRImage.js +46 -45
- package/tagECRImage.js.map +1 -0
- package/tagECRImage.mjs +9 -9
- package/tagECRImage.mjs.map +1 -0
- package/upsertECRRepository.d.mts +11 -0
- package/upsertECRRepository.d.mts.map +1 -0
- package/upsertECRRepository.d.ts +12 -6
- package/upsertECRRepository.d.ts.map +1 -0
- package/upsertECRRepository.js +34 -31
- package/upsertECRRepository.js.map +1 -0
- package/upsertECRRepository.mjs +11 -8
- package/upsertECRRepository.mjs.map +1 -0
- package/copyECRImage.js.flow +0 -14
- package/copyECRImage.mjs.flow +0 -14
- package/ecrImageExists.js.flow +0 -10
- package/ecrImageExists.mjs.flow +0 -10
- package/index.js.flow +0 -8
- package/index.mjs.flow +0 -8
- package/loginToECR.js.flow +0 -6
- package/loginToECR.mjs.flow +0 -6
- package/parseECRImageUri.js.flow +0 -8
- package/parseECRImageUri.mjs.flow +0 -8
- package/tagECRImage.js.flow +0 -8
- package/tagECRImage.mjs.flow +0 -8
- package/upsertECRRepository.js.flow +0 -7
- package/upsertECRRepository.mjs.flow +0 -7
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { spawn } from 'promisify-child-process'
|
|
2
|
+
import loginToECR from './loginToECR'
|
|
3
|
+
import ecrImageExists from './ecrImageExists'
|
|
4
|
+
import parseECRImageUri from './parseECRImageUri'
|
|
5
|
+
import { ECRClient, ECRClientConfig } from '@aws-sdk/client-ecr'
|
|
6
|
+
|
|
7
|
+
export default async function copyECRImage({
|
|
8
|
+
from,
|
|
9
|
+
to,
|
|
10
|
+
}: {
|
|
11
|
+
from: {
|
|
12
|
+
imageUri: string
|
|
13
|
+
ecr?: ECRClient
|
|
14
|
+
awsConfig?: ECRClientConfig
|
|
15
|
+
}
|
|
16
|
+
to: {
|
|
17
|
+
imageUri: string
|
|
18
|
+
ecr?: ECRClient
|
|
19
|
+
awsConfig?: ECRClientConfig
|
|
20
|
+
}
|
|
21
|
+
}): Promise<void> {
|
|
22
|
+
if (from.imageUri === to.imageUri) return
|
|
23
|
+
const srcRepositoryUri = from.imageUri.replace(/:.+/, '')
|
|
24
|
+
const repositoryUri = to.imageUri.replace(/:.+/, '')
|
|
25
|
+
|
|
26
|
+
const { region: fromRegion } = parseECRImageUri(from.imageUri)
|
|
27
|
+
const {
|
|
28
|
+
region: toRegion,
|
|
29
|
+
repositoryName,
|
|
30
|
+
imageTag,
|
|
31
|
+
} = parseECRImageUri(to.imageUri)
|
|
32
|
+
|
|
33
|
+
if (
|
|
34
|
+
await ecrImageExists({
|
|
35
|
+
awsConfig: { ...to.awsConfig, region: toRegion },
|
|
36
|
+
ecr: to.ecr,
|
|
37
|
+
repositoryName,
|
|
38
|
+
imageTag,
|
|
39
|
+
})
|
|
40
|
+
) {
|
|
41
|
+
// eslint-disable-next-line no-console
|
|
42
|
+
console.error(
|
|
43
|
+
`Clarity image already exists in your ECR: ${repositoryName}:${imageTag}`
|
|
44
|
+
)
|
|
45
|
+
} else {
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
47
|
+
console.error(
|
|
48
|
+
`Logging into source ECR: ${srcRepositoryUri.replace(/\/.*/, '')}...`
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
await loginToECR({
|
|
52
|
+
ecr: from.ecr,
|
|
53
|
+
awsConfig: { ...from.awsConfig, region: fromRegion },
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// eslint-disable-next-line no-console
|
|
57
|
+
console.error(`Pulling ${from.imageUri}...`)
|
|
58
|
+
await spawn('docker', ['pull', from.imageUri], { stdio: 'inherit' })
|
|
59
|
+
|
|
60
|
+
// eslint-disable-next-line no-console
|
|
61
|
+
console.error(
|
|
62
|
+
`Logging into dest ECR: ${repositoryUri.replace(/\/.*/, '')}...`
|
|
63
|
+
)
|
|
64
|
+
await loginToECR({
|
|
65
|
+
ecr: to.ecr,
|
|
66
|
+
awsConfig: { ...to.awsConfig, region: toRegion },
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// eslint-disable-next-line no-console
|
|
70
|
+
console.error(`Pushing ${to.imageUri}...`)
|
|
71
|
+
await spawn('docker', ['tag', from.imageUri, to.imageUri], {
|
|
72
|
+
stdio: 'inherit',
|
|
73
|
+
})
|
|
74
|
+
await spawn('docker', ['push', to.imageUri], { stdio: 'inherit' })
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DescribeImagesCommand,
|
|
3
|
+
ECRClient,
|
|
4
|
+
ECRClientConfig,
|
|
5
|
+
} from '@aws-sdk/client-ecr'
|
|
6
|
+
|
|
7
|
+
export default async function ecrImageExists({
|
|
8
|
+
ecr,
|
|
9
|
+
awsConfig,
|
|
10
|
+
imageUri,
|
|
11
|
+
registryId,
|
|
12
|
+
repositoryName,
|
|
13
|
+
imageTag,
|
|
14
|
+
}: {
|
|
15
|
+
ecr?: ECRClient
|
|
16
|
+
awsConfig?: ECRClientConfig
|
|
17
|
+
imageUri?: string
|
|
18
|
+
registryId?: string
|
|
19
|
+
repositoryName?: string
|
|
20
|
+
imageTag?: string
|
|
21
|
+
}): Promise<boolean> {
|
|
22
|
+
let region
|
|
23
|
+
if (imageUri) {
|
|
24
|
+
const match = /(\d+)\.dkr\.ecr\.(.+?)\.amazonaws\.com\/(.+?):(.+)/.exec(
|
|
25
|
+
imageUri
|
|
26
|
+
)
|
|
27
|
+
if (!match) throw new Error(`failed to parse imageUri: ${imageUri}`)
|
|
28
|
+
;[, registryId, region, repositoryName, imageTag] = match
|
|
29
|
+
}
|
|
30
|
+
if (!region) region = awsConfig?.region
|
|
31
|
+
if (!ecr) ecr = new ECRClient({ ...awsConfig, region })
|
|
32
|
+
|
|
33
|
+
if (!repositoryName || !imageTag) {
|
|
34
|
+
throw new Error(`missing repositoryName/imageTag or imageUri`)
|
|
35
|
+
}
|
|
36
|
+
return await ecr
|
|
37
|
+
.send(
|
|
38
|
+
new DescribeImagesCommand({
|
|
39
|
+
registryId,
|
|
40
|
+
repositoryName,
|
|
41
|
+
imageIds: [{ imageTag }],
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
.then(
|
|
45
|
+
() => true,
|
|
46
|
+
() => false
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import formatECRRepositoryHostname from './formatECRRepositoryHostname'
|
|
2
|
+
|
|
3
|
+
export default function formatECRImageUri({
|
|
4
|
+
registryId,
|
|
5
|
+
region,
|
|
6
|
+
repositoryName,
|
|
7
|
+
imageTag,
|
|
8
|
+
}: {
|
|
9
|
+
registryId: string
|
|
10
|
+
region: string
|
|
11
|
+
repositoryName: string
|
|
12
|
+
imageTag: string
|
|
13
|
+
}): string {
|
|
14
|
+
return `${formatECRRepositoryHostname({
|
|
15
|
+
registryId,
|
|
16
|
+
region,
|
|
17
|
+
repositoryName,
|
|
18
|
+
})}:${imageTag}`
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default function formatECRRepositoryHostname({
|
|
2
|
+
registryId,
|
|
3
|
+
region,
|
|
4
|
+
repositoryName,
|
|
5
|
+
}: {
|
|
6
|
+
registryId: string
|
|
7
|
+
region: string
|
|
8
|
+
repositoryName: string
|
|
9
|
+
}): string {
|
|
10
|
+
return `${registryId}.dkr.ecr.${region}.amazonaws.com/${repositoryName}`
|
|
11
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
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'
|
|
6
|
+
export { default as parseECRRepositoryHostname } from './parseECRRepositoryHostname'
|
|
7
|
+
export { default as upsertECRRepository } from './upsertECRRepository'
|
|
8
|
+
export { default as checkECRRepositoryPolicy } from './checkECRRepositoryPolicy'
|
|
9
|
+
export { default as checkECRImageAccess } from './checkECRImageAccess'
|
|
10
|
+
export { default as formatECRRepositoryHostname } from './formatECRRepositoryHostname'
|
|
11
|
+
export { default as formatECRImageUri } from './formatECRImageUri'
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @prettier
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from 'promisify-child-process'
|
|
5
|
+
import base64 from 'base64-js'
|
|
6
|
+
import {
|
|
7
|
+
ECRClient,
|
|
8
|
+
ECRClientConfig,
|
|
9
|
+
GetAuthorizationTokenCommand,
|
|
10
|
+
} from '@aws-sdk/client-ecr'
|
|
11
|
+
import parseECRImageUri from './parseECRImageUri'
|
|
12
|
+
import * as log4jcore from 'log4jcore'
|
|
13
|
+
|
|
14
|
+
const log = log4jcore.logger('@jcoreio/aws-ecr-utils/loginToECR')
|
|
15
|
+
|
|
16
|
+
export default async function loginToECR({
|
|
17
|
+
ecr,
|
|
18
|
+
forImages,
|
|
19
|
+
awsConfig,
|
|
20
|
+
}: {
|
|
21
|
+
ecr?: ECRClient
|
|
22
|
+
forImages?: string[]
|
|
23
|
+
awsConfig?: ECRClientConfig
|
|
24
|
+
}): Promise<void> {
|
|
25
|
+
if (forImages) {
|
|
26
|
+
log.debug('logging into AWS ECR for images:', forImages)
|
|
27
|
+
const regions = new Set(
|
|
28
|
+
forImages.flatMap((image) => {
|
|
29
|
+
try {
|
|
30
|
+
return [parseECRImageUri(image).region]
|
|
31
|
+
} catch {
|
|
32
|
+
return []
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
)
|
|
36
|
+
log.debug('parsed AWS regions from images:', regions)
|
|
37
|
+
await Promise.all(
|
|
38
|
+
[...regions].map(async (region) =>
|
|
39
|
+
loginToECR({
|
|
40
|
+
awsConfig: { ...awsConfig, region },
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
if (!ecr) ecr = new ECRClient({ ...awsConfig })
|
|
47
|
+
|
|
48
|
+
log.debug('logging into ECR for region:', await ecr.config.region())
|
|
49
|
+
const { authorizationData } = await ecr.send(
|
|
50
|
+
new GetAuthorizationTokenCommand()
|
|
51
|
+
)
|
|
52
|
+
const { authorizationToken, proxyEndpoint } = authorizationData?.[0] || {}
|
|
53
|
+
log.debug('GetAuthorizationToken data:', {
|
|
54
|
+
authorizationToken,
|
|
55
|
+
proxyEndpoint,
|
|
56
|
+
})
|
|
57
|
+
if (!authorizationToken) {
|
|
58
|
+
throw new Error('failed to get authorizationToken from ECR')
|
|
59
|
+
}
|
|
60
|
+
if (!proxyEndpoint) {
|
|
61
|
+
throw new Error('failed to get proxyEndpoint from ECR')
|
|
62
|
+
}
|
|
63
|
+
// this is silly...
|
|
64
|
+
const decoded = Buffer.from(base64.toByteArray(authorizationToken)).toString(
|
|
65
|
+
'utf8'
|
|
66
|
+
)
|
|
67
|
+
const [user, password] = decoded.split(/:/)
|
|
68
|
+
const dockerArgs = ['login', '-u', user, '--password-stdin', proxyEndpoint]
|
|
69
|
+
log.debug(
|
|
70
|
+
'running: docker',
|
|
71
|
+
...dockerArgs.map((arg) =>
|
|
72
|
+
/^[-_a-z0-9]+$/i.test(arg) ? arg : `'${arg.replace(/'/g, `'\\'')}'`)}'`
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
const child = spawn('docker', dockerArgs, {
|
|
76
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
77
|
+
encoding: 'utf8',
|
|
78
|
+
})
|
|
79
|
+
if (!child.stdin) {
|
|
80
|
+
throw new Error('expected child.stdin to be defined')
|
|
81
|
+
}
|
|
82
|
+
child.stdin.write(password)
|
|
83
|
+
child.stdin.end()
|
|
84
|
+
await child.then(
|
|
85
|
+
() => log.debug('ECR login succeeded'),
|
|
86
|
+
(error: unknown) => {
|
|
87
|
+
if (error && typeof error === 'object') {
|
|
88
|
+
if ('code' in error)
|
|
89
|
+
log.debug('docker login exited with code', error.code)
|
|
90
|
+
if ('signal' in error)
|
|
91
|
+
log.debug('docker login was killed with signal', error.signal)
|
|
92
|
+
}
|
|
93
|
+
throw error
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default function parseECRImageUri(imageUri: string): {
|
|
2
|
+
registryId: string
|
|
3
|
+
region: string
|
|
4
|
+
repositoryName: string
|
|
5
|
+
imageTag: string
|
|
6
|
+
} {
|
|
7
|
+
const match = /(\d+)\.dkr\.ecr\.([^.]+)\.amazonaws\.com\/([^:]+):(.+)/.exec(
|
|
8
|
+
imageUri
|
|
9
|
+
)
|
|
10
|
+
if (!match) throw new Error(`invalid imageUri: ${imageUri}`)
|
|
11
|
+
const [, registryId, region, repositoryName, imageTag] = match
|
|
12
|
+
return { registryId, region, repositoryName, imageTag }
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default function parseECRRepositoryHostname(hostname: string): {
|
|
2
|
+
registryId: string
|
|
3
|
+
region: string
|
|
4
|
+
repositoryName: string
|
|
5
|
+
} {
|
|
6
|
+
const match = /^([^.]+)\.dkr\.ecr\.([^.]+)\.amazonaws\.com\/([^:]+)/.exec(
|
|
7
|
+
hostname
|
|
8
|
+
)
|
|
9
|
+
if (!match) throw new Error(`invalid ECR repository hostname: ${hostname}`)
|
|
10
|
+
const [, registryId, region, repositoryName] = match
|
|
11
|
+
return { registryId, region, repositoryName }
|
|
12
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @prettier
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
BatchGetImageCommand,
|
|
6
|
+
ECRClient,
|
|
7
|
+
ECRClientConfig,
|
|
8
|
+
PutImageCommand,
|
|
9
|
+
} from '@aws-sdk/client-ecr'
|
|
10
|
+
import parseECRImageUri from './parseECRImageUri'
|
|
11
|
+
|
|
12
|
+
export default async function tagECRImage({
|
|
13
|
+
ecr,
|
|
14
|
+
awsConfig,
|
|
15
|
+
imageUri,
|
|
16
|
+
tags,
|
|
17
|
+
}: {
|
|
18
|
+
ecr?: ECRClient
|
|
19
|
+
awsConfig?: ECRClientConfig
|
|
20
|
+
imageUri: string
|
|
21
|
+
tags: string[]
|
|
22
|
+
}): Promise<void> {
|
|
23
|
+
const { region, repositoryName, imageTag } = parseECRImageUri(imageUri)
|
|
24
|
+
if (!ecr) ecr = new ECRClient({ ...awsConfig, region })
|
|
25
|
+
|
|
26
|
+
const imageManifest = await ecr
|
|
27
|
+
.send(
|
|
28
|
+
new BatchGetImageCommand({
|
|
29
|
+
repositoryName,
|
|
30
|
+
imageIds: [{ imageTag }],
|
|
31
|
+
})
|
|
32
|
+
)
|
|
33
|
+
.then((r) => r.images?.[0]?.imageManifest)
|
|
34
|
+
|
|
35
|
+
if (!imageManifest) {
|
|
36
|
+
throw new Error(`failed to get image manifest for ${imageUri}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (imageManifest) {
|
|
40
|
+
// add other tags to ECR
|
|
41
|
+
for (const tag of tags) {
|
|
42
|
+
// eslint-disable-next-line no-console
|
|
43
|
+
console.error(`Adding tag ${repositoryName}:${tag}`)
|
|
44
|
+
try {
|
|
45
|
+
await ecr.send(
|
|
46
|
+
new PutImageCommand({
|
|
47
|
+
repositoryName,
|
|
48
|
+
imageManifest,
|
|
49
|
+
imageTag: tag.substring(tag.indexOf(':') + 1),
|
|
50
|
+
})
|
|
51
|
+
)
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if ((error as any)?.code !== 'ImageAlreadyExistsException') throw error
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
CreateRepositoryCommand,
|
|
5
|
+
DescribeRepositoriesCommand,
|
|
6
|
+
ECRClient,
|
|
7
|
+
ECRClientConfig,
|
|
8
|
+
Repository,
|
|
9
|
+
} from '@aws-sdk/client-ecr'
|
|
10
|
+
|
|
11
|
+
export default async function upsertECRRepository({
|
|
12
|
+
ecr,
|
|
13
|
+
awsConfig,
|
|
14
|
+
repositoryName,
|
|
15
|
+
}: {
|
|
16
|
+
ecr?: ECRClient
|
|
17
|
+
awsConfig?: ECRClientConfig
|
|
18
|
+
repositoryName: string
|
|
19
|
+
}): Promise<Repository> {
|
|
20
|
+
if (!ecr) ecr = new ECRClient({ ...awsConfig })
|
|
21
|
+
try {
|
|
22
|
+
const { repositories } = await ecr.send(
|
|
23
|
+
new DescribeRepositoriesCommand({ repositoryNames: [repositoryName] })
|
|
24
|
+
)
|
|
25
|
+
const repository = repositories?.[0]
|
|
26
|
+
if (repository) return repository
|
|
27
|
+
} catch {
|
|
28
|
+
// ignore
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line no-console
|
|
32
|
+
console.error(`Creating ECR repository {bold ${repositoryName}}...`)
|
|
33
|
+
const { repository } = await ecr.send(
|
|
34
|
+
new CreateRepositoryCommand({ repositoryName })
|
|
35
|
+
)
|
|
36
|
+
if (!repository) {
|
|
37
|
+
throw new Error(`repository is missing from createRepository response`)
|
|
38
|
+
}
|
|
39
|
+
return repository
|
|
40
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @prettier
|
|
3
|
+
*/
|
|
4
|
+
import { ECRClient, ECRClientConfig } from '@aws-sdk/client-ecr';
|
|
5
|
+
export default function tagECRImage({
|
|
6
|
+
ecr,
|
|
7
|
+
awsConfig,
|
|
8
|
+
imageUri,
|
|
9
|
+
tags
|
|
10
|
+
}: {
|
|
11
|
+
ecr?: ECRClient;
|
|
12
|
+
awsConfig?: ECRClientConfig;
|
|
13
|
+
imageUri: string;
|
|
14
|
+
tags: string[];
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
//# sourceMappingURL=tagECRImage.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagECRImage.d.mts","names":["ECRClient","ECRClientConfig","tagECRImage","ecr","awsConfig","imageUri","tags","Promise"],"sources":["src/tagECRImage.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAGA,SAEEA,SAAS,EACTC,eAAe,QAEV,qBAAqB;AAG5B,wBAA8BC,WAAWA,CAAC;EACxCC,GAAG;EACHC,SAAS;EACTC,QAAQ;EACRC;CACD,EAAE;EACDH,GAAG,CAAC,EAAEH,SAAS;EACfI,SAAS,CAAC,EAAEH,eAAe;EAC3BI,QAAQ,EAAE,MAAM;EAChBC,IAAI,EAAE,MAAM,EAAE;CACf,GAAGC,OAAO,CAAC,IAAI,CAAC","ignoreList":[]}
|
package/tagECRImage.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @prettier
|
|
3
3
|
*/
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
import { ECRClient, ECRClientConfig } from '@aws-sdk/client-ecr';
|
|
5
|
+
declare function tagECRImage({
|
|
6
|
+
ecr,
|
|
7
|
+
awsConfig,
|
|
8
|
+
imageUri,
|
|
9
|
+
tags
|
|
10
|
+
}: {
|
|
11
|
+
ecr?: ECRClient;
|
|
12
|
+
awsConfig?: ECRClientConfig;
|
|
13
|
+
imageUri: string;
|
|
14
|
+
tags: string[];
|
|
10
15
|
}): Promise<void>;
|
|
16
|
+
export = tagECRImage;
|
|
17
|
+
//# sourceMappingURL=tagECRImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagECRImage.d.ts","names":["ECRClient","ECRClientConfig","tagECRImage","ecr","awsConfig","imageUri","tags","Promise"],"sources":["src/tagECRImage.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAGA,SAEEA,SAAS,EACTC,eAAe,QAEV,qBAAqB;AAG5B,iBAA8BC,WAAWA,CAAC;EACxCC,GAAG;EACHC,SAAS;EACTC,QAAQ;EACRC;CACD,EAAE;EACDH,GAAG,CAAC,EAAEH,SAAS;EACfI,SAAS,CAAC,EAAEH,eAAe;EAC3BI,QAAQ,EAAE,MAAM;EAChBC,IAAI,EAAE,MAAM,EAAE;CACf,GAAGC,OAAO,CAAC,IAAI,CAAC;AAmChB,SAAAL,WAAA","ignoreList":[]}
|
package/tagECRImage.js
CHANGED
|
@@ -8,11 +8,11 @@ exports["default"] = tagECRImage;
|
|
|
8
8
|
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
|
|
9
9
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
10
|
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
|
|
11
|
-
var
|
|
11
|
+
var _clientEcr = require("@aws-sdk/client-ecr");
|
|
12
12
|
var _parseECRImageUri2 = _interopRequireDefault(require("./parseECRImageUri.js"));
|
|
13
|
-
function _createForOfIteratorHelper(
|
|
14
|
-
function _unsupportedIterableToArray(
|
|
15
|
-
function _arrayLikeToArray(
|
|
13
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
14
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
15
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
16
16
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
17
17
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /**
|
|
18
18
|
* @prettier
|
|
@@ -21,88 +21,89 @@ function tagECRImage(_x) {
|
|
|
21
21
|
return _tagECRImage.apply(this, arguments);
|
|
22
22
|
}
|
|
23
23
|
function _tagECRImage() {
|
|
24
|
-
_tagECRImage = (0, _asyncToGenerator2["default"])(
|
|
25
|
-
var ecr, awsConfig, imageUri, tags, _parseECRImageUri, region, repositoryName, imageTag, imageManifest, _iterator, _step, tag;
|
|
26
|
-
return _regenerator["default"].wrap(function
|
|
24
|
+
_tagECRImage = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(_ref) {
|
|
25
|
+
var ecr, awsConfig, imageUri, tags, _parseECRImageUri, region, repositoryName, imageTag, imageManifest, _iterator, _step, tag, _t, _t2;
|
|
26
|
+
return _regenerator["default"].wrap(function (_context) {
|
|
27
27
|
while (1) switch (_context.prev = _context.next) {
|
|
28
28
|
case 0:
|
|
29
29
|
ecr = _ref.ecr, awsConfig = _ref.awsConfig, imageUri = _ref.imageUri, tags = _ref.tags;
|
|
30
30
|
_parseECRImageUri = (0, _parseECRImageUri2["default"])(imageUri), region = _parseECRImageUri.region, repositoryName = _parseECRImageUri.repositoryName, imageTag = _parseECRImageUri.imageTag;
|
|
31
|
-
if (!ecr) ecr = new
|
|
31
|
+
if (!ecr) ecr = new _clientEcr.ECRClient(_objectSpread(_objectSpread({}, awsConfig), {}, {
|
|
32
32
|
region: region
|
|
33
33
|
}));
|
|
34
|
-
_context.next =
|
|
35
|
-
return ecr.
|
|
34
|
+
_context.next = 1;
|
|
35
|
+
return ecr.send(new _clientEcr.BatchGetImageCommand({
|
|
36
36
|
repositoryName: repositoryName,
|
|
37
37
|
imageIds: [{
|
|
38
38
|
imageTag: imageTag
|
|
39
39
|
}]
|
|
40
|
-
})
|
|
40
|
+
})).then(function (r) {
|
|
41
41
|
var _r$images;
|
|
42
|
-
return
|
|
42
|
+
return (_r$images = r.images) === null || _r$images === void 0 || (_r$images = _r$images[0]) === null || _r$images === void 0 ? void 0 : _r$images.imageManifest;
|
|
43
43
|
});
|
|
44
|
-
case
|
|
44
|
+
case 1:
|
|
45
45
|
imageManifest = _context.sent;
|
|
46
46
|
if (imageManifest) {
|
|
47
|
-
_context.next =
|
|
47
|
+
_context.next = 2;
|
|
48
48
|
break;
|
|
49
49
|
}
|
|
50
50
|
throw new Error("failed to get image manifest for ".concat(imageUri));
|
|
51
|
-
case
|
|
51
|
+
case 2:
|
|
52
52
|
if (!imageManifest) {
|
|
53
|
-
_context.next =
|
|
53
|
+
_context.next = 12;
|
|
54
54
|
break;
|
|
55
55
|
}
|
|
56
56
|
// add other tags to ECR
|
|
57
57
|
_iterator = _createForOfIteratorHelper(tags);
|
|
58
|
-
_context.prev =
|
|
58
|
+
_context.prev = 3;
|
|
59
59
|
_iterator.s();
|
|
60
|
-
case
|
|
60
|
+
case 4:
|
|
61
61
|
if ((_step = _iterator.n()).done) {
|
|
62
|
-
_context.next =
|
|
62
|
+
_context.next = 9;
|
|
63
63
|
break;
|
|
64
64
|
}
|
|
65
65
|
tag = _step.value;
|
|
66
66
|
// eslint-disable-next-line no-console
|
|
67
67
|
console.error("Adding tag ".concat(repositoryName, ":").concat(tag));
|
|
68
|
-
_context.prev =
|
|
69
|
-
_context.next =
|
|
70
|
-
return ecr.
|
|
68
|
+
_context.prev = 5;
|
|
69
|
+
_context.next = 6;
|
|
70
|
+
return ecr.send(new _clientEcr.PutImageCommand({
|
|
71
71
|
repositoryName: repositoryName,
|
|
72
72
|
imageManifest: imageManifest,
|
|
73
73
|
imageTag: tag.substring(tag.indexOf(':') + 1)
|
|
74
|
-
})
|
|
75
|
-
case
|
|
76
|
-
_context.next =
|
|
74
|
+
}));
|
|
75
|
+
case 6:
|
|
76
|
+
_context.next = 8;
|
|
77
77
|
break;
|
|
78
|
-
case
|
|
79
|
-
_context.prev =
|
|
80
|
-
|
|
81
|
-
if (!((
|
|
82
|
-
_context.next =
|
|
78
|
+
case 7:
|
|
79
|
+
_context.prev = 7;
|
|
80
|
+
_t = _context["catch"](5);
|
|
81
|
+
if (!((_t === null || _t === void 0 ? void 0 : _t.code) !== 'ImageAlreadyExistsException')) {
|
|
82
|
+
_context.next = 8;
|
|
83
83
|
break;
|
|
84
84
|
}
|
|
85
|
-
throw
|
|
86
|
-
case
|
|
87
|
-
_context.next =
|
|
85
|
+
throw _t;
|
|
86
|
+
case 8:
|
|
87
|
+
_context.next = 4;
|
|
88
88
|
break;
|
|
89
|
-
case
|
|
90
|
-
_context.next =
|
|
89
|
+
case 9:
|
|
90
|
+
_context.next = 11;
|
|
91
91
|
break;
|
|
92
|
-
case
|
|
93
|
-
_context.prev =
|
|
94
|
-
|
|
95
|
-
_iterator.e(
|
|
96
|
-
case
|
|
97
|
-
_context.prev =
|
|
92
|
+
case 10:
|
|
93
|
+
_context.prev = 10;
|
|
94
|
+
_t2 = _context["catch"](3);
|
|
95
|
+
_iterator.e(_t2);
|
|
96
|
+
case 11:
|
|
97
|
+
_context.prev = 11;
|
|
98
98
|
_iterator.f();
|
|
99
|
-
return _context.finish(
|
|
100
|
-
case
|
|
99
|
+
return _context.finish(11);
|
|
100
|
+
case 12:
|
|
101
101
|
case "end":
|
|
102
102
|
return _context.stop();
|
|
103
103
|
}
|
|
104
|
-
}, _callee, null, [[
|
|
104
|
+
}, _callee, null, [[3, 10, 11, 12], [5, 7]]);
|
|
105
105
|
}));
|
|
106
106
|
return _tagECRImage.apply(this, arguments);
|
|
107
107
|
}
|
|
108
|
-
module.exports = exports.default;
|
|
108
|
+
module.exports = exports.default;
|
|
109
|
+
//# sourceMappingURL=tagECRImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagECRImage.js","names":["_clientEcr","require","_parseECRImageUri2","_interopRequireDefault","_createForOfIteratorHelper","r","e","t","Symbol","iterator","Array","isArray","_unsupportedIterableToArray","length","_n","F","s","n","done","value","f","TypeError","o","a","u","call","next","_arrayLikeToArray","toString","slice","constructor","name","from","test","ownKeys","Object","keys","getOwnPropertySymbols","filter","getOwnPropertyDescriptor","enumerable","push","apply","_objectSpread","arguments","forEach","_defineProperty2","getOwnPropertyDescriptors","defineProperties","defineProperty","tagECRImage","_x","_tagECRImage","_asyncToGenerator2","_regenerator","mark","_callee","_ref","ecr","awsConfig","imageUri","tags","_parseECRImageUri","region","repositoryName","imageTag","imageManifest","_iterator","_step","tag","_t","_t2","wrap","_context","prev","parseECRImageUri","ECRClient","send","BatchGetImageCommand","imageIds","then","_r$images","images","sent","Error","concat","console","error","PutImageCommand","substring","indexOf","code","finish","stop","module","exports","default"],"sources":["src/tagECRImage.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|