Skip to content

Commit 56ce9ff

Browse files
Elad Ben-Israelmergify[bot]
authored andcommitted
feat(ecr-assets): fail if tokens are used in buildArgs (#3989)
* feat(ecr-assets): fail if tokens are used in buildArgs Since `buildArgs` are used before deployment, if tokens are used, we will fail quickly with a nice message. Fixes #3981 * do not import Token, since its not used
1 parent f6ef79d commit 56ce9ff

File tree

2 files changed

+48
-12
lines changed

2 files changed

+48
-12
lines changed

packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import assets = require('@aws-cdk/assets');
22
import ecr = require('@aws-cdk/aws-ecr');
33
import cdk = require('@aws-cdk/core');
4+
import { Token } from '@aws-cdk/core';
45
import cxapi = require('@aws-cdk/cx-api');
56
import fs = require('fs');
67
import path = require('path');
@@ -19,14 +20,18 @@ export interface DockerImageAssetProps extends assets.CopyOptions {
1920
* from a Kubernetes Pod. Note, this is only the repository name, without the
2021
* registry and the tag parts.
2122
*
22-
* @default automatically derived from the asset's ID.
23+
* @default - automatically derived from the asset's ID.
2324
*/
2425
readonly repositoryName?: string;
2526

2627
/**
27-
* Build args to pass to the `docker build` command
28+
* Build args to pass to the `docker build` command.
2829
*
29-
* @default no build args are passed
30+
* Since Docker build arguments are resolved before deployment, keys and
31+
* values cannot refer to unresolved tokens (such as `lambda.functionArn` or
32+
* `queue.queueUrl`).
33+
*
34+
* @default - no build args are passed
3035
*/
3136
readonly buildArgs?: { [key: string]: string };
3237
}
@@ -59,6 +64,9 @@ export class DockerImageAsset extends cdk.Construct implements assets.IAsset {
5964
constructor(scope: cdk.Construct, id: string, props: DockerImageAssetProps) {
6065
super(scope, id);
6166

67+
// verify buildArgs do not use tokens in neither keys nor values
68+
validateBuildArgs(props.buildArgs);
69+
6270
// resolve full path
6371
const dir = path.resolve(props.directory);
6472
if (!fs.existsSync(dir)) {
@@ -110,3 +118,11 @@ export class DockerImageAsset extends cdk.Construct implements assets.IAsset {
110118
this.artifactHash = imageSha;
111119
}
112120
}
121+
122+
function validateBuildArgs(buildArgs?: { [key: string]: string }) {
123+
for (const [ key, value ] of Object.entries(buildArgs || {})) {
124+
if (Token.isUnresolved(key) || Token.isUnresolved(value)) {
125+
throw new Error(`Cannot use tokens in keys or values of "buildArgs" since they are needed before deployment`);
126+
}
127+
}
128+
}

packages/@aws-cdk/aws-ecr-assets/test/test.image-asset.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect, haveResource, SynthUtils } from '@aws-cdk/assert';
22
import iam = require('@aws-cdk/aws-iam');
3-
import cdk = require('@aws-cdk/core');
3+
import { App, Lazy, Stack } from '@aws-cdk/core';
44
import fs = require('fs');
55
import { Test } from 'nodeunit';
66
import path = require('path');
@@ -11,7 +11,7 @@ import { DockerImageAsset } from '../lib';
1111
export = {
1212
'test instantiating Asset Image'(test: Test) {
1313
// GIVEN
14-
const stack = new cdk.Stack();
14+
const stack = new Stack();
1515

1616
// WHEN
1717
new DockerImageAsset(stack, 'Image', {
@@ -31,7 +31,7 @@ export = {
3131

3232
'with build args'(test: Test) {
3333
// GIVEN
34-
const stack = new cdk.Stack();
34+
const stack = new Stack();
3535

3636
// WHEN
3737
const asset = new DockerImageAsset(stack, 'Image', {
@@ -49,7 +49,7 @@ export = {
4949

5050
'asset.repository.grantPull can be used to grant a principal permissions to use the image'(test: Test) {
5151
// GIVEN
52-
const stack = new cdk.Stack();
52+
const stack = new Stack();
5353
const user = new iam.User(stack, 'MyUser');
5454
const asset = new DockerImageAsset(stack, 'Image', {
5555
directory: path.join(__dirname, 'demo-image')
@@ -106,7 +106,7 @@ export = {
106106

107107
'asset.repository.addToResourcePolicy can be used to modify the ECR resource policy via the adoption custom resource'(test: Test) {
108108
// GIVEN
109-
const stack = new cdk.Stack();
109+
const stack = new Stack();
110110
const asset = new DockerImageAsset(stack, 'Image', {
111111
directory: path.join(__dirname, 'demo-image')
112112
});
@@ -141,7 +141,7 @@ export = {
141141

142142
'fails if the directory does not exist'(test: Test) {
143143
// GIVEN
144-
const stack = new cdk.Stack();
144+
const stack = new Stack();
145145

146146
// THEN
147147
test.throws(() => {
@@ -154,7 +154,7 @@ export = {
154154

155155
'fails if the directory does not contain a Dockerfile'(test: Test) {
156156
// GIVEN
157-
const stack = new cdk.Stack();
157+
const stack = new Stack();
158158

159159
// THEN
160160
test.throws(() => {
@@ -166,8 +166,8 @@ export = {
166166
},
167167

168168
'docker directory is staged if asset staging is enabled'(test: Test) {
169-
const app = new cdk.App();
170-
const stack = new cdk.Stack(app, 'stack');
169+
const app = new App();
170+
const stack = new Stack(app, 'stack');
171171

172172
new DockerImageAsset(stack, 'MyAsset', {
173173
directory: path.join(__dirname, 'demo-image')
@@ -177,6 +177,26 @@ export = {
177177

178178
test.ok(fs.existsSync(path.join(session.directory, 'asset.1a17a141505ac69144931fe263d130f4612251caa4bbbdaf68a44ed0f405439c/Dockerfile')));
179179
test.ok(fs.existsSync(path.join(session.directory, 'asset.1a17a141505ac69144931fe263d130f4612251caa4bbbdaf68a44ed0f405439c/index.py')));
180+
test.done();
181+
},
182+
183+
'fails if using tokens in build args keys or values'(test: Test) {
184+
// GIVEN
185+
const stack = new Stack();
186+
const token = Lazy.stringValue({ produce: () => 'foo' });
187+
const expected = /Cannot use tokens in keys or values of "buildArgs" since they are needed before deployment/;
188+
189+
// THEN
190+
test.throws(() => new DockerImageAsset(stack, 'MyAsset1', {
191+
directory: path.join(__dirname, 'demo-image'),
192+
buildArgs: { [token]: 'value' }
193+
}), expected);
194+
195+
test.throws(() => new DockerImageAsset(stack, 'MyAsset2', {
196+
directory: path.join(__dirname, 'demo-image'),
197+
buildArgs: { key: token }
198+
}), expected);
199+
180200
test.done();
181201
}
182202
};

0 commit comments

Comments
 (0)