Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ecs-patterns): add missing NLB task image options #30775

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,32 @@ export interface NetworkLoadBalancedTaskImageOptions {
* @default - No labels.
*/
readonly dockerLabels?: { [key: string]: string };

/**
* The entry point that's passed to the container.
*
* This parameter maps to `Entrypoint` in the [Create a container](https://docs.docker.com/engine/api/v1.38/#operation/ContainerCreate) section
* of the [Docker Remote API](https://docs.docker.com/engine/api/v1.38/) and the `--entrypoint` option to
* [docker run](https://docs.docker.com/engine/reference/commandline/run/).
*
* For more information about the Docker `ENTRYPOINT` parameter, see https://docs.docker.com/engine/reference/builder/#entrypoint.
*
* @default none
*/
readonly entryPoint?: string[];

/**
* The command that's passed to the container. If there are multiple arguments, make sure that each argument is a separated string in the array.
*
* This parameter maps to `Cmd` in the [Create a container](https://docs.docker.com/engine/api/v1.38/#operation/ContainerCreate) section
* of the [Docker Remote API](https://docs.docker.com/engine/api/v1.38/) and the `COMMAND` parameter to
* [docker run](https://docs.docker.com/engine/reference/commandline/run/).
*
* For more information about the Docker `CMD` parameter, see https://docs.docker.com/engine/reference/builder/#cmd.
*
* @default none
*/
readonly command?: string[];
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ export class NetworkLoadBalancedEc2Service extends NetworkLoadBalancedServiceBas
secrets: taskImageOptions.secrets,
logging: logDriver,
dockerLabels: taskImageOptions.dockerLabels,
command: taskImageOptions.command,
entryPoint: taskImageOptions.entryPoint,
Comment on lines +129 to +130
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly we should have some unit tests for these commands in NetworkLoadBalancedEc2Service. We have some similar test cases for ApplicationLoadBalancedEc2Service.

});
container.addPortMappings({
containerPort: taskImageOptions.containerPort || 80,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Construct } from 'constructs';
import { ISecurityGroup, SubnetSelection } from '../../../aws-ec2';
import { FargateService, FargateTaskDefinition } from '../../../aws-ecs';
import { FargateService, FargateTaskDefinition, HealthCheck } from '../../../aws-ecs';
import { FeatureFlags } from '../../../core';
import * as cxapi from '../../../cx-api';
import { FargateServiceBaseProps } from '../base/fargate-service-base';
Expand Down Expand Up @@ -31,6 +31,13 @@ export interface NetworkLoadBalancedFargateServiceProps extends NetworkLoadBalan
* @default - A new security group is created.
*/
readonly securityGroups?: ISecurityGroup[];

/**
* The health check command and associated configuration parameters for the container.
*
* @default - Health check configuration from container.
*/
readonly healthCheck?: HealthCheck;
}

/**
Expand Down Expand Up @@ -79,10 +86,13 @@ export class NetworkLoadBalancedFargateService extends NetworkLoadBalancedServic
const containerName = taskImageOptions.containerName ?? 'web';
const container = this.taskDefinition.addContainer(containerName, {
image: taskImageOptions.image,
healthCheck: props.healthCheck,
logging: logDriver,
environment: taskImageOptions.environment,
secrets: taskImageOptions.secrets,
dockerLabels: taskImageOptions.dockerLabels,
command: taskImageOptions.command,
entryPoint: taskImageOptions.entryPoint,
Comment on lines +89 to +95
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see similar properties available in ApplicationLoadBalancedFargateService and since we are adding the same to NetworkLoadBalancedFargateService, I would recommend we have some unit test that covers these properties. We could have some testcases similar to these in ApplicationLoadBalancedFargateService.

});
container.addPortMappings({
containerPort: taskImageOptions.containerPort || 80,
Expand Down
69 changes: 69 additions & 0 deletions packages/aws-cdk-lib/aws-ecs-patterns/test/ec2/l3s.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,75 @@ describe('ApplicationLoadBalancedEc2Service', () => {
});

describe('NetworkLoadBalancedEc2Service', () => {
test('ECS loadbalanced construct', () => {
// GIVEN
const stack = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'VPC');
const cluster = new ecs.Cluster(stack, 'Cluster', { vpc });
cluster.addAsgCapacityProvider(new AsgCapacityProvider(stack, 'DefaultAutoScalingGroupProvider', {
autoScalingGroup: new AutoScalingGroup(stack, 'DefaultAutoScalingGroup', {
vpc,
instanceType: new ec2.InstanceType('t2.micro'),
machineImage: MachineImage.latestAmazonLinux(),
}),
}));

// WHEN
new ecsPatterns.NetworkLoadBalancedEc2Service(stack, 'Service', {
cluster,
memoryLimitMiB: 1024,
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('test'),
environment: {
TEST_ENVIRONMENT_VARIABLE1: 'test environment variable 1 value',
TEST_ENVIRONMENT_VARIABLE2: 'test environment variable 2 value',
},
dockerLabels: { label1: 'labelValue1', label2: 'labelValue2' },
entryPoint: ['echo', 'ecs-is-awesome'],
command: ['/bin/bash'],
},
desiredCount: 2,
ipAddressType: IpAddressType.DUAL_STACK,
});

// THEN - stack contains a load balancer and a service
Template.fromStack(stack).resourceCountIs('AWS::ElasticLoadBalancingV2::LoadBalancer', 1);
Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::LoadBalancer', {
Scheme: 'internet-facing',
Type: 'network',
IpAddressType: 'dualstack',
});

Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', {
DesiredCount: 2,
LaunchType: 'EC2',
});

Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', {
ContainerDefinitions: [
Match.objectLike({
Environment: [
{
Name: 'TEST_ENVIRONMENT_VARIABLE1',
Value: 'test environment variable 1 value',
},
{
Name: 'TEST_ENVIRONMENT_VARIABLE2',
Value: 'test environment variable 2 value',
},
],
Memory: 1024,
DockerLabels: {
label1: 'labelValue1',
label2: 'labelValue2',
},
EntryPoint: ['echo', 'ecs-is-awesome'],
Command: ['/bin/bash'],
}),
],
});
});

test('setting vpc and cluster throws error', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1436,6 +1436,57 @@ describe('ApplicationLoadBalancedFargateService', () => {
});

describe('NetworkLoadBalancedFargateService', () => {
test('setting healthCheckGracePeriod works', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new ecsPatterns.NetworkLoadBalancedFargateService(stack, 'Service', {
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('/aws/aws-example-app'),
},
healthCheckGracePeriod: cdk.Duration.seconds(600),
});
// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ECS::Service', {
HealthCheckGracePeriodSeconds: 600,
});
});

test('setting healthCheck works', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new ecsPatterns.NetworkLoadBalancedFargateService(stack, 'Service', {
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('/aws/aws-example-app'),
},
healthCheck: {
command: ['CMD-SHELL', 'curl -f http://localhost/ || exit 1'],
interval: cdk.Duration.minutes(1),
retries: 5,
startPeriod: cdk.Duration.minutes(1),
timeout: cdk.Duration.minutes(1),
},
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', {
ContainerDefinitions: Match.arrayWith([
Match.objectLike({
HealthCheck: {
Command: ['CMD-SHELL', 'curl -f http://localhost/ || exit 1'],
Interval: 60,
Retries: 5,
StartPeriod: 60,
Timeout: 60,
},
}),
]),
});
});

test('setting loadBalancerType to Network creates an NLB Public', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down Expand Up @@ -1714,6 +1765,50 @@ describe('NetworkLoadBalancedFargateService', () => {
});
});

test('setting a command for taskImageOption', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new ecsPatterns.NetworkLoadBalancedFargateService(stack, 'Service', {
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('/aws/aws-example-app'),
command: ['./app/bin/start.sh', '--foo'],
},
});
// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', {
ContainerDefinitions: [
Match.objectLike({
Image: '/aws/aws-example-app',
Command: ['./app/bin/start.sh', '--foo'],
}),
],
});
});

test('setting an entryPoint for taskImageOptions', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new ecsPatterns.NetworkLoadBalancedFargateService(stack, 'Service', {
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('/aws/aws-example-app'),
entryPoint: ['echo', 'foo'],
},
});
// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ECS::TaskDefinition', {
ContainerDefinitions: [
Match.objectLike({
Image: '/aws/aws-example-app',
EntryPoint: ['echo', 'foo'],
}),
],
});
});

test('setting NLB circuitBreaker works', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down
Loading