From 417e5e89403cbe7c673534fa63338f993e8fa064 Mon Sep 17 00:00:00 2001 From: Hsing-Hui Hsu Date: Tue, 7 May 2019 01:21:46 -0700 Subject: [PATCH] fix(aws-ecs): allow linux parameters to be settable (#2397) Fixes #2380 --- .../integ.pipeline-ecs-deploy.expected.json | 8 -- .../aws-ecs/lib/container-definition.ts | 10 +- .../@aws-cdk/aws-ecs/lib/linux-parameters.ts | 43 +++++-- .../ec2/integ.event-task.lit.expected.json | 10 +- .../test/ec2/integ.lb-awsvpc-nw.expected.json | 10 +- .../test/ec2/integ.lb-bridge-nw.expected.json | 10 +- .../test/ec2/integ.sd-awsvpc-nw.expected.json | 8 -- .../test/ec2/integ.sd-bridge-nw.expected.json | 8 -- .../test/ec2/test.ec2-task-definition.ts | 8 -- .../fargate/integ.asset-image.expected.json | 10 +- .../test/fargate/integ.l3.expected.json | 8 -- .../fargate/integ.lb-awsvpc-nw.expected.json | 8 -- .../aws-ecs/test/test.container-definition.ts | 120 +++++++++++++++--- .../test/__snapshots__/synth.test.js.snap | 8 -- 14 files changed, 150 insertions(+), 119 deletions(-) diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.expected.json b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.expected.json index 508f1f92dabc9..242911394e9da 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.expected.json +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-ecs-deploy.expected.json @@ -231,14 +231,6 @@ "Essential": true, "Image": "amazon/amazon-ecs-sample", "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "MountPoints": [], "Name": "Container", "PortMappings": [], diff --git a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts index 3d1403beb949a..fb6f1c581135c 100644 --- a/packages/@aws-cdk/aws-ecs/lib/container-definition.ts +++ b/packages/@aws-cdk/aws-ecs/lib/container-definition.ts @@ -168,6 +168,11 @@ export interface ContainerDefinitionOptions { * Configures a custom log driver for the container. */ readonly logging?: LogDriver; + + /** + * Configures Linux Parameters + */ + readonly linuxParameters?: LinuxParameters; } /** @@ -187,7 +192,7 @@ export class ContainerDefinition extends cdk.Construct { /** * Access Linux Parameters */ - public readonly linuxParameters = new LinuxParameters(); + public readonly linuxParameters?: LinuxParameters; /** * The configured mount points @@ -234,6 +239,7 @@ export class ContainerDefinition extends cdk.Construct { this.essential = props.essential !== undefined ? props.essential : true; this.taskDefinition = props.taskDefinition; this.memoryLimitSpecified = props.memoryLimitMiB !== undefined || props.memoryReservationMiB !== undefined; + this.linuxParameters = props.linuxParameters; props.image.bind(this); if (props.logging) { props.logging.bind(this); } @@ -394,7 +400,7 @@ export class ContainerDefinition extends cdk.Construct { extraHosts: this.props.extraHosts && renderKV(this.props.extraHosts, 'hostname', 'ipAddress'), healthCheck: this.props.healthCheck && renderHealthCheck(this.props.healthCheck), links: this.links, - linuxParameters: this.linuxParameters.renderLinuxParameters(), + linuxParameters: this.linuxParameters && this.linuxParameters.renderLinuxParameters(), }; } } diff --git a/packages/@aws-cdk/aws-ecs/lib/linux-parameters.ts b/packages/@aws-cdk/aws-ecs/lib/linux-parameters.ts index a17656298767c..154d7bea07811 100644 --- a/packages/@aws-cdk/aws-ecs/lib/linux-parameters.ts +++ b/packages/@aws-cdk/aws-ecs/lib/linux-parameters.ts @@ -1,38 +1,61 @@ +import cdk = require('@aws-cdk/cdk'); import { CfnTaskDefinition } from './ecs.generated'; /** - * Linux parameter setup in a container + * Properties for defining Linux Parameters */ -export class LinuxParameters { +export interface LinuxParametersProps { /** * Whether the init process is enabled */ - public initProcessEnabled?: boolean; + readonly initProcessEnabled?: boolean; /** * The shared memory size */ - public sharedMemorySize?: number; + readonly sharedMemorySize?: number; +} + +/** + * Linux Parameters for an ECS container + */ +export class LinuxParameters extends cdk.Construct { + /** + * Whether the init process is enabled + */ + private readonly initProcessEnabled?: boolean; + + /** + * The shared memory size. Not valid for Fargate launch type + */ + private readonly sharedMemorySize?: number; /** * Capabilities to be added */ - private readonly capAdd: Capability[] = []; + private readonly capAdd = new Array(); /** * Capabilities to be dropped */ - private readonly capDrop: Capability[] = []; + private readonly capDrop = new Array(); /** * Device mounts */ - private readonly devices: Device[] = []; + private readonly devices = new Array(); /** - * TMPFS mounts + * TmpFs mounts */ - private readonly tmpfs: Tmpfs[] = []; + private readonly tmpfs = new Array(); + + constructor(scope: cdk.Construct, id: string, props: LinuxParametersProps = {}) { + super(scope, id); + + this.sharedMemorySize = props.sharedMemorySize; + this.initProcessEnabled = props.initProcessEnabled; + } /** * Add one or more capabilities @@ -61,6 +84,8 @@ export class LinuxParameters { /** * Add one or more tmpfs mounts + * + * Only works with EC2 launch type. */ public addTmpfs(...tmpfs: Tmpfs[]) { this.tmpfs.push(...tmpfs); diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json index cf64430816ede..502085b90f7ce 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.event-task.lit.expected.json @@ -710,14 +710,6 @@ ] }, "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "LogConfiguration": { "LogDriver": "awslogs", "Options": { @@ -1159,4 +1151,4 @@ "Description": "S3 key for asset version \"aws-ecs-integ-ecs/AdoptEcrRepositorydbc60defc59544bcaa5c28c95d68f62c/Code\"" } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json index 09dc8a742e401..83eac819f4fbe 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-awsvpc-nw.expected.json @@ -766,14 +766,6 @@ "Essential": true, "Image": "amazon/amazon-ecs-sample", "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "Memory": 256, "MountPoints": [], "Name": "web", @@ -1006,4 +998,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json index bef9bc1361830..028f5ec650302 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.lb-bridge-nw.expected.json @@ -787,14 +787,6 @@ "Essential": true, "Image": "amazon/amazon-ecs-sample", "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "Memory": 256, "MountPoints": [], "Name": "web", @@ -969,4 +961,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-awsvpc-nw.expected.json index 2e0a8566b610a..770f6c475d76a 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-awsvpc-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-awsvpc-nw.expected.json @@ -775,14 +775,6 @@ "Essential": true, "Image": "amazon/amazon-ecs-sample", "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "Memory": 256, "MountPoints": [], "Name": "frontend", diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-bridge-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-bridge-nw.expected.json index 32b795000af0c..ee4a100f8cf81 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-bridge-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/ec2/integ.sd-bridge-nw.expected.json @@ -775,14 +775,6 @@ "Essential": true, "Image": "amazon/amazon-ecs-sample", "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "Memory": 256, "MountPoints": [], "Name": "frontend", diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-task-definition.ts b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-task-definition.ts index 3ded27b87c6e4..0ba65423fac86 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-task-definition.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-task-definition.ts @@ -71,14 +71,6 @@ export = { Memory: 512, Image: "amazon/amazon-ecs-sample", Links: [], - LinuxParameters: { - Capabilities: { - Add: [], - Drop: [] - }, - Devices: [], - Tmpfs: [] - }, MountPoints: [], Name: "web", PortMappings: [{ diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json index 95576fee3a795..48fd16d5fb7b7 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.asset-image.expected.json @@ -761,14 +761,6 @@ ] }, "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "LogConfiguration": { "LogDriver": "awslogs", "Options": { @@ -1040,4 +1032,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json index 67092cc624428..c23e9a0ae37fc 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.l3.expected.json @@ -481,14 +481,6 @@ "Essential": true, "Image": "amazon/amazon-ecs-sample", "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "LogConfiguration": { "LogDriver": "awslogs", "Options": { diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json index 21beb1d2c0d63..69a97813475a1 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json +++ b/packages/@aws-cdk/aws-ecs/test/fargate/integ.lb-awsvpc-nw.expected.json @@ -381,14 +381,6 @@ "Essential": true, "Image": "amazon/amazon-ecs-sample", "Links": [], - "LinuxParameters": { - "Capabilities": { - "Add": [], - "Drop": [] - }, - "Devices": [], - "Tmpfs": [] - }, "MountPoints": [], "Name": "web", "PortMappings": [ diff --git a/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts b/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts index e91b7fa95f574..e0661b909e510 100644 --- a/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts +++ b/packages/@aws-cdk/aws-ecs/test/test.container-definition.ts @@ -148,8 +148,8 @@ export = { test.done(); }, } - }, + "Ingress Port": { "With network mode AwsVpc": { "Ingress port should be the same as container port"(test: Test) { @@ -176,6 +176,7 @@ export = { test.done(); }, }, + "With network mode Host ": { "Ingress port should be the same as container port"(test: Test) { // GIVEN @@ -268,7 +269,6 @@ export = { } }); - // THEN // THEN expect(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { ContainerDefinitions: [ @@ -478,10 +478,10 @@ export = { // WHEN taskDefinition.addContainer('Container', { - image: ecs.ContainerImage.fromRegistry('user-x/my-app', { - credentials: repoCreds - }), - memoryLimitMiB: 2048, + image: ecs.ContainerImage.fromRegistry('user-x/my-app', { + credentials: repoCreds + }), + memoryLimitMiB: 2048, }); // THEN @@ -489,27 +489,115 @@ export = { ContainerDefinitions: [ { Image: 'user-x/my-app', - RepositoryCredentials: { - CredentialsParameter: mySecretArn - }, + RepositoryCredentials: { + CredentialsParameter: mySecretArn + }, } ] })); expect(stack).to(haveResourceLike('AWS::IAM::Policy', { PolicyDocument: { - Statement: [ - { - Action: "secretsmanager:GetSecretValue", - Effect: "Allow", - Resource: mySecretArn - } - ] + Statement: [ + { + Action: "secretsmanager:GetSecretValue", + Effect: "Allow", + Resource: mySecretArn + } + ] } })); test.done(); }, + 'Can specify linux parameters': { + 'before calling addContainer'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); + + const linuxParameters = new ecs.LinuxParameters(stack, 'LinuxParameters', { + initProcessEnabled: true, + sharedMemorySize: 1024, + }); + + linuxParameters.addCapabilities(ecs.Capability.All); + linuxParameters.dropCapabilities(ecs.Capability.Kill); + + // WHEN + taskDefinition.addContainer('cont', { + image: ecs.ContainerImage.fromRegistry('test'), + memoryLimitMiB: 1024, + linuxParameters, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [ + { + Image: 'test', + LinuxParameters: { + Capabilities: { + Add: ["ALL"], + Drop: ["KILL"] + }, + Devices: [], + Tmpfs: [], + InitProcessEnabled: true, + SharedMemorySize: 1024, + }, + } + ] + })); + + test.done(); + }, + + 'after calling addContainer'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); + + const linuxParameters = new ecs.LinuxParameters(stack, 'LinuxParameters', { + initProcessEnabled: true, + sharedMemorySize: 1024, + }); + + linuxParameters.addCapabilities(ecs.Capability.All); + + // WHEN + taskDefinition.addContainer('cont', { + image: ecs.ContainerImage.fromRegistry('test'), + memoryLimitMiB: 1024, + linuxParameters, + }); + + // Mutate linuxParameter after added to a container + linuxParameters.dropCapabilities(ecs.Capability.Setuid); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', { + ContainerDefinitions: [ + { + Image: 'test', + LinuxParameters: { + Capabilities: { + Add: ["ALL"], + Drop: ["SETUID"] + }, + Devices: [], + Tmpfs: [], + InitProcessEnabled: true, + SharedMemorySize: 1024, + }, + } + ] + })); + + test.done(); + }, + }, + // render extra hosts test }; diff --git a/packages/decdk/test/__snapshots__/synth.test.js.snap b/packages/decdk/test/__snapshots__/synth.test.js.snap index 43b02931055f4..a89d53a44d62d 100644 --- a/packages/decdk/test/__snapshots__/synth.test.js.snap +++ b/packages/decdk/test/__snapshots__/synth.test.js.snap @@ -616,14 +616,6 @@ Object { "Essential": true, "Image": "redis", "Links": Array [], - "LinuxParameters": Object { - "Capabilities": Object { - "Add": Array [], - "Drop": Array [], - }, - "Devices": Array [], - "Tmpfs": Array [], - }, "Memory": 1024, "MountPoints": Array [], "Name": "ContainerDef",