(aws-ecs): Unable to use multiple EnvironmentFile
- 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
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