aws / aws/aws-cdk

(aws-ecs): Unable to use multiple EnvironmentFile

Open
#21,313 2 comments 3 reactions 0 assignees View on GitHub
@aws-cdk/aws-ecs bug effort/small p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

### Describe the bug

The use of multiple `ecs.EnvironmentFile.fromAsset()` in `taskDefinition.addContainer()` resulted to an error.

### Expected Behavior

Able to use `ecs.EnvironmentFile.fromAsset()` multiple times in a stack.

### Current Behavior

Unable to synth the stack.

```
~/cdk/node_modules/constructs/src/construct.ts:403
throw new Error(`There is already a Construct with name '${childName}' in ${typeName}${name.length > 0 ? ' [' + name + ']' : ''}`);
^
Error: There is already a Construct with name 'EnvironmentFile' in ContainerDefinition [DefaultContainer]
at Node.addChild (~/cdk/node_modules/constructs/src/construct.ts:403:13)
at new Node (~/cdk/node_modules/constructs/src/construct.ts:71:17)
at new Construct (~/cdk/node_modules/constructs/src/construct.ts:464:17)
at new Asset (~/cdk/node_modules/aws-cdk-lib/aws-s3-assets/lib/asset.js:1:473)
at AssetEnvironmentFile.bind (~/cdk/node_modules/aws-cdk-lib/aws-ecs/lib/environment-file.js:1:1481)
at new ContainerDefinition (~/cdk/node_modules/aws-cdk-lib/aws-ecs/lib/container-definition.js:1:3421)
at Ec2TaskDefinition.addContainer (~/cdk/node_modules/aws-cdk-lib/aws-ecs/lib/base/task-definition.js:1:8925)
at new SampleStack (~/cdk/lib/sample-stack.ts:19:20)
at createApp (~/cdk/bin/cloud-cdk.ts:336:3)
at Object. (~/cdk/bin/cloud-cdk.ts:384:1)
```

### Reproduction Steps

```ts
import * as cdk from "aws-cdk-lib";
import * as ecs from "aws-cdk-lib/aws-ecs";
import { Construct } from "constructs";

export class SampleStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

const taskDefinition = new ecs.Ec2TaskDefinition(this, 'TaskDef');

taskDefinition.addContainer('DefaultContainer', {
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
memoryLimitMiB: 512,
environmentFiles: [
ecs.EnvironmentFile.fromAsset('demo-1.env'),
ecs.EnvironmentFile.fromAsset('demo-2.env'),
]
});
}
}
```

### Possible Solution

Modify the `Asset` ID from `EnvironmentFile` to something that is derived from the asset path.

```ts
import { Construct } from "constructs";
import { EnvironmentFile, EnvironmentFileConfig, EnvironmentFileType } from "aws-cdk-lib/aws-ecs";
import { Asset, AssetOptions } from "aws-cdk-lib/aws-s3-assets";
import * as iam from "aws-cdk-lib/aws-iam";
import * as crypto from "crypto";

export class FixedAssetEnvironmentFile extends EnvironmentFile {
private asset?: Asset;
private grantees: iam.IGrantable[] = [];

/**
* @param path The path to the asset file or directory.
* @param options
*/
constructor(
public readonly path: string,
private readonly options: AssetOptions = {},
) {
super();
}

public grantRead(grantee: iam.IGrantable) {
this.grantees.push(grantee);
}

public bind(scope: Construct): EnvironmentFileConfig {
const hash = crypto.createHash('sha256')
.update(this.path)
.digest('hex');

// If the same AssetCode is used multiple times, retain only the first instantiation.
if (!this.asset) {
this.asset = new Asset(scope, hash, {
path: this.path,
...this.options,
});
}

let grantee = this.grantees.pop();

while (grantee) {
this.asset.grantRead(grantee);

grantee = this.grantees.pop();
}

if (!this.asset.isFile) {
throw new Error(`Asset must be a single file (${this.path})`);
}

return {
fileType: EnvironmentFileType.S3,
s3Location: {
bucketName: this.asset.s3BucketName,
objectKey: this.asset.s3ObjectKey,
},
};
}
}

```

### Additional Information/Context

_No response_

### CDK CLI Version

2.33.0 (build 859272d)

### Framework Version

_No response_

### Node.js Version

v16.16.0

### OS

MacOS

### Language

Typescript

### Language Version

3.9.10

### Other information

Related PR: https://github.com/aws/aws-cdk/pull/10673

Contributor guide

Open the contributing guide

Research direction

Start by reading the aws-ecs EnvironmentFile binding shown in the stack trace, then trace how ContainerDefinition creates the s3-assets Asset. Reproduce the failure with the two demo environment files and compare it with the related PR; done means the sample stack synthesizes successfully when multiple EnvironmentFile.fromAsset() values are used.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, infrastructure
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.