Skip to content

Commit

Permalink
feat(ecs): add support for ProxyConfiguration in ECS TaskDefinition (a…
Browse files Browse the repository at this point in the history
…ws#4007)

* Add proxyConfiguration support

* Fix test case

* Improve the user experience when setting proxy configuration

* Add base proxy configuration class and an app mesh proxy
configuration class

* Add generic proxy configuration class

* Remove generic proxy configuration and minor changes

* Add integ test, reword error message

* Fix integ test and unit test

* Update with support for empty string for egressIgnoredIPs/Ports

* Refactoring bind method

* Minor refactoring to renderProperties method
  • Loading branch information
iamhopaul123 authored and mergify[bot] committed Oct 2, 2019
1 parent bd36c6c commit 68e1e85
Show file tree
Hide file tree
Showing 9 changed files with 1,313 additions and 2 deletions.
9 changes: 9 additions & 0 deletions packages/@aws-cdk/aws-ecs/lib/base/task-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Construct, IResource, Lazy, Resource } from '@aws-cdk/core';
import { ContainerDefinition, ContainerDefinitionOptions, PortMapping, Protocol } from '../container-definition';
import { CfnTaskDefinition } from '../ecs.generated';
import { PlacementConstraint } from '../placement';
import { ProxyConfiguration } from '../proxy-configuration/proxy-configuration';

/**
* The interface for all task definitions.
Expand Down Expand Up @@ -64,6 +65,13 @@ export interface CommonTaskDefinitionProps {
*/
readonly taskRole?: iam.IRole;

/**
* The configuration details for the App Mesh proxy.
*
* @default - No proxy configuration.
*/
readonly proxyConfiguration?: ProxyConfiguration;

/**
* The list of volume definitions for the task. For more information, see
* [Task Definition Parameter Volumes](https://docs.aws.amazon.com/AmazonECS/latest/developerguide//task_definition_parameters.html#volumes).
Expand Down Expand Up @@ -279,6 +287,7 @@ export class TaskDefinition extends TaskDefinitionBase {
placementConstraints: Lazy.anyValue({ produce: () =>
!isFargateCompatible(this.compatibility) ? this.placementConstraints : undefined
}, { omitEmptyArray: true }),
proxyConfiguration: props.proxyConfiguration ? props.proxyConfiguration.bind(this.stack, this) : undefined,
cpu: props.cpu,
memory: props.memoryMiB,
});
Expand Down
4 changes: 4 additions & 0 deletions packages/@aws-cdk/aws-ecs/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export * from './log-drivers/syslog-log-driver';
export * from './log-drivers/log-driver';
export * from './log-drivers/log-drivers';

export * from './proxy-configuration/app-mesh-proxy-configuration';
export * from './proxy-configuration/proxy-configuration';
export * from './proxy-configuration/proxy-configurations';

// AWS::ECS CloudFormation Resources:
//
export * from './ecs.generated';
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { Construct } from '@aws-cdk/core';
import { TaskDefinition } from '../base/task-definition';
import { CfnTaskDefinition } from '../ecs.generated';
import { ProxyConfiguration } from './proxy-configuration';

/**
* Interface for setting the properties of proxy configuration.
*/
export interface AppMeshProxyConfigurationProps {
/**
* The user ID (UID) of the proxy container as defined by the user parameter in a container definition.
* This is used to ensure the proxy ignores its own traffic. If IgnoredGID is specified, this field can be empty.
*/
readonly ignoredUID?: number;

/**
* The group ID (GID) of the proxy container as defined by the user parameter in a container definition.
* This is used to ensure the proxy ignores its own traffic. If IgnoredUID is specified, this field can be empty.
*/
readonly ignoredGID?: number;

/**
* The list of ports that the application uses.
* Network traffic to these ports is forwarded to the ProxyIngressPort and ProxyEgressPort.
*/
readonly appPorts: number[];

/**
* Specifies the port that incoming traffic to the AppPorts is directed to.
*/
readonly proxyIngressPort: number;

/**
* Specifies the port that outgoing traffic from the AppPorts is directed to.
*/
readonly proxyEgressPort: number;

/**
* The egress traffic going to these specified ports is ignored and not redirected to the ProxyEgressPort. It can be an empty list.
*/
readonly egressIgnoredPorts?: number[];

/**
* The egress traffic going to these specified IP addresses is ignored and not redirected to the ProxyEgressPort. It can be an empty list.
*/
readonly egressIgnoredIPs?: string[];
}

/**
* The configuration to use when setting an App Mesh proxy configuration.
*/
export interface AppMeshProxyConfigurationConfigProps {
/**
* The name of the container that will serve as the App Mesh proxy.
*/
readonly containerName: string;

/**
* The set of network configuration parameters to provide the Container Network Interface (CNI) plugin.
*/
readonly properties: AppMeshProxyConfigurationProps;
}

/**
* The class for App Mesh proxy configurations.
*
* For tasks using the EC2 launch type, the container instances require at least version 1.26.0 of the container agent and at least version
* 1.26.0-1 of the ecs-init package to enable a proxy configuration. If your container instances are launched from the Amazon ECS-optimized
* AMI version 20190301 or later, then they contain the required versions of the container agent and ecs-init.
* For more information, see [Amazon ECS-optimized AMIs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html).
*
* For tasks using the Fargate launch type, the task or service requires platform version 1.3.0 or later.
*/
export class AppMeshProxyConfiguration extends ProxyConfiguration {
/**
* Constructs a new instance of the AppMeshProxyConfiguration class.
*/
constructor(private readonly props: AppMeshProxyConfigurationConfigProps) {
super();
if (props.properties) {
if (!props.properties.ignoredUID && !props.properties.ignoredGID) {
throw new Error("At least one of ignoredUID or ignoredGID should be specified.");
}
}
}

/**
* Called when the proxy configuration is configured on a task definition.
*/
public bind(_scope: Construct, _taskDefinition: TaskDefinition): CfnTaskDefinition.ProxyConfigurationProperty {
const configProps = this.props.properties;
const configType = "APPMESH";
return {
containerName: this.props.containerName,
proxyConfigurationProperties: renderProperties(configProps),
type: configType
};
}
}

function renderProperties(props: AppMeshProxyConfigurationProps): CfnTaskDefinition.KeyValuePairProperty[] {
const ret = [];
for (const [k, v] of Object.entries(props)) {
const key = String(k);
const value = String(v);
if (value !== "undefined" && value !== "") {
const capitalizedKey = key.charAt(0).toUpperCase() + key.slice(1);
ret.push({ ["name"]: capitalizedKey, ["value"]: value });
}
}
return ret;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Construct } from '@aws-cdk/core';
import { TaskDefinition } from '../base/task-definition';
import { CfnTaskDefinition } from '../ecs.generated';

/**
* The base class for proxy configurations.
*/
export abstract class ProxyConfiguration {
/**
* Called when the proxy configuration is configured on a task definition.
*/
public abstract bind(_scope: Construct, _taskDefinition: TaskDefinition): CfnTaskDefinition.ProxyConfigurationProperty;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { AppMeshProxyConfiguration, AppMeshProxyConfigurationConfigProps } from './app-mesh-proxy-configuration';
import { ProxyConfiguration } from './proxy-configuration';

/**
* The base class for proxy configurations.
*/
export class ProxyConfigurations {
/**
* Constructs a new instance of the ProxyConfiguration class.
*/
public static appMeshProxyConfiguration(props: AppMeshProxyConfigurationConfigProps): ProxyConfiguration {
return new AppMeshProxyConfiguration(props);
}
}
Loading

0 comments on commit 68e1e85

Please sign in to comment.