Skip to content

Commit b79b2e4

Browse files
authored
fix(ecs): firelens configFileValue is unnecessarily required (#20636)
`FirelensOptions` should have only optional properties, but `configFileValue` was previously marked as required. This caused some confusion and incorrect configuration like `configFileValue = ''` as seen here: aws/aws-for-fluent-bit#352. This fix marks `configFileValue` as optional, and makes sure that `configFileValue` and `configFileType` are set together, or not at all. See [docs](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-firelensconfiguration.html#cfn-ecs-taskdefinition-firelensconfiguration-options). Signed-off-by: Wesley Pettit <wppttt@amazon.com> Needed to fix: aws/aws-for-fluent-bit#352 ---- ### All Submissions: * [ ] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 1f91112 commit b79b2e4

3 files changed

Lines changed: 80 additions & 19 deletions

File tree

packages/@aws-cdk/aws-ecs/lib/firelens-log-router.ts

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,22 @@ export interface FirelensOptions {
5353
readonly enableECSLogMetadata?: boolean;
5454

5555
/**
56-
* Custom configuration file, s3 or file
56+
* Custom configuration file, s3 or file.
57+
* Both configFileType and configFileValue must be used together
58+
* to define a custom configuration source.
59+
*
5760
* @default - determined by checking configFileValue with S3 ARN.
5861
*/
5962
readonly configFileType?: FirelensConfigFileType;
6063

6164
/**
6265
* Custom configuration file, S3 ARN or a file path
66+
* Both configFileType and configFileValue must be used together
67+
* to define a custom configuration source.
68+
*
69+
* @default - no config file value
6370
*/
64-
readonly configFileValue: string;
71+
readonly configFileValue?: string;
6572
}
6673

6774
/**
@@ -109,6 +116,16 @@ export interface FirelensLogRouterDefinitionOptions extends ContainerDefinitionO
109116
function renderFirelensConfig(firelensConfig: FirelensConfig): CfnTaskDefinition.FirelensConfigurationProperty {
110117
if (!firelensConfig.options) {
111118
return { type: firelensConfig.type };
119+
} else if (firelensConfig.options.configFileValue === undefined) {
120+
// config file options work as a pair together to define a custom config source
121+
// a custom config source is optional,
122+
// and thus the `config-file-x` keys should be set together or not at all
123+
return {
124+
type: firelensConfig.type,
125+
options: {
126+
'enable-ecs-log-metadata': firelensConfig.options.enableECSLogMetadata ? 'true' : 'false',
127+
},
128+
};
112129
} else {
113130
// firelensConfig.options.configFileType has been filled with s3 or file type in constructor.
114131
return {
@@ -201,33 +218,43 @@ export class FirelensLogRouter extends ContainerDefinition {
201218
super(scope, id, props);
202219
const options = props.firelensConfig.options;
203220
if (options) {
221+
if ((options.configFileValue && options.configFileType === undefined) || (options.configFileValue === undefined && options.configFileType)) {
222+
throw new Error('configFileValue and configFileType must be set together to define a custom config source');
223+
}
224+
225+
const hasConfig = (options.configFileValue !== undefined);
204226
const enableECSLogMetadata = options.enableECSLogMetadata || options.enableECSLogMetadata === undefined;
205227
const configFileType = (options.configFileType === undefined || options.configFileType === FirelensConfigFileType.S3) &&
206-
(cdk.Token.isUnresolved(options.configFileValue) || /arn:aws[a-zA-Z-]*:s3:::.+/.test(options.configFileValue))
228+
(cdk.Token.isUnresolved(options.configFileValue) || /arn:aws[a-zA-Z-]*:s3:::.+/.test(options.configFileValue || ''))
207229
? FirelensConfigFileType.S3 : FirelensConfigFileType.FILE;
230+
208231
this.firelensConfig = {
209232
type: props.firelensConfig.type,
210233
options: {
211234
enableECSLogMetadata,
212-
configFileType,
213-
configFileValue: options.configFileValue,
235+
...(hasConfig ? {
236+
configFileType,
237+
configFileValue: options.configFileValue,
238+
} : {}),
214239
},
215240
};
216241

217-
// grant s3 access permissions
218-
if (configFileType === FirelensConfigFileType.S3) {
219-
props.taskDefinition.addToExecutionRolePolicy(new iam.PolicyStatement({
220-
actions: [
221-
's3:GetObject',
222-
],
223-
resources: [options.configFileValue],
224-
}));
225-
props.taskDefinition.addToExecutionRolePolicy(new iam.PolicyStatement({
226-
actions: [
227-
's3:GetBucketLocation',
228-
],
229-
resources: [options.configFileValue.split('/')[0]],
230-
}));
242+
if (hasConfig) {
243+
// grant s3 access permissions
244+
if (configFileType === FirelensConfigFileType.S3) {
245+
props.taskDefinition.addToExecutionRolePolicy(new iam.PolicyStatement({
246+
actions: [
247+
's3:GetObject',
248+
],
249+
resources: [(options.configFileValue ?? '')],
250+
}));
251+
props.taskDefinition.addToExecutionRolePolicy(new iam.PolicyStatement({
252+
actions: [
253+
's3:GetBucketLocation',
254+
],
255+
resources: [(options.configFileValue ?? '').split('/')[0]],
256+
}));
257+
}
231258
}
232259
} else {
233260
this.firelensConfig = props.firelensConfig;

packages/@aws-cdk/aws-ecs/test/ec2/integ.firelens-s3-config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ taskDefinition.addFirelensLogRouter('log_router', {
2828
options: {
2929
enableECSLogMetadata: false,
3030
configFileValue: `${asset.bucket.bucketArn}/${asset.s3ObjectKey}`,
31+
configFileType: ecs.FirelensConfigFileType.S3,
3132
},
3233
},
3334
logging: new ecs.AwsLogDriver({ streamPrefix: 'firelens' }),

packages/@aws-cdk/aws-ecs/test/firelens-log-driver.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ describe('firelens log driver', () => {
288288
options: {
289289
enableECSLogMetadata: false,
290290
configFileValue: 'arn:aws:s3:::mybucket/fluent.conf',
291+
configFileType: ecs.FirelensConfigFileType.S3,
291292
},
292293
},
293294
logging: new ecs.AwsLogDriver({ streamPrefix: 'firelens' }),
@@ -349,5 +350,37 @@ describe('firelens log driver', () => {
349350
],
350351
});
351352
});
353+
354+
test('firelens config options are fully optional', () => {
355+
// GIVEN
356+
td.addFirelensLogRouter('log_router', {
357+
image: ecs.obtainDefaultFluentBitECRImage(td, undefined, '2.1.0'),
358+
firelensConfig: {
359+
type: ecs.FirelensLogRouterType.FLUENTBIT,
360+
options: {
361+
enableECSLogMetadata: false,
362+
},
363+
},
364+
logging: new ecs.AwsLogDriver({ streamPrefix: 'firelens' }),
365+
memoryReservationMiB: 50,
366+
});
367+
368+
// THEN
369+
Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', {
370+
ContainerDefinitions: [
371+
Match.objectLike({
372+
Essential: true,
373+
MemoryReservation: 50,
374+
Name: 'log_router',
375+
FirelensConfiguration: {
376+
Type: 'fluentbit',
377+
Options: {
378+
'enable-ecs-log-metadata': 'false',
379+
},
380+
},
381+
}),
382+
],
383+
});
384+
});
352385
});
353386
});

0 commit comments

Comments
 (0)