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(batch-alpha): add RuntimePlatform prop #26506

Closed
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-batch-alpha/lib/ecs-container-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Construct, IConstruct } from 'constructs';
import { CfnJobDefinition } from 'aws-cdk-lib/aws-batch';
import { LinuxParameters } from './linux-parameters';
import { LogGroup } from 'aws-cdk-lib/aws-logs';
import { RuntimePlatform } from './runtime-platform';

const EFS_VOLUME_SYMBOL = Symbol.for('aws-cdk-lib/aws-batch/lib/container-definition.EfsVolume');
const HOST_VOLUME_SYMBOL = Symbol.for('aws-cdk-lib/aws-batch/lib/container-definition.HostVolume');
Expand Down Expand Up @@ -429,6 +430,15 @@ export interface IEcsContainerDefinition extends IConstruct {
*/
readonly readonlyRootFilesystem?: boolean;

/**
* The operating system that your task definitions are running on.
*
* A runtimePlatform is supported only for tasks using the Fargate launch type.
*
* @default - Undefined.
Copy link
Contributor

Choose a reason for hiding this comment

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

Please don't write "undefined". We all know that the JavaScript value of a missing variable is undefined.

Describe what the behavior is if the value is left undefined.

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this property need to be on the interface? IEcsContainerDefinition ?

It only needs to be here if downstream consumers of this class need to make decisions based on runtimePlatform. If so, it also needs to be added to EcsContainerDefinition.fromContainerDefinitionAttributes().

*/
readonly runtimePlatform?: RuntimePlatform;

/**
* A map from environment variable names to the secrets for the container. Allows your job definitions
* to reference the secret by the environment variable name defined in this property.
Expand Down Expand Up @@ -546,6 +556,15 @@ export interface EcsContainerDefinitionProps {
*/
readonly readonlyRootFilesystem?: boolean;

/**
* The operating system that your task definitions are running on.
*
* A runtimePlatform is supported only for tasks using the Fargate launch type.
*
* @default - Undefined.
Copy link
Contributor

Choose a reason for hiding this comment

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

Same.

*/
readonly runtimePlatform?: RuntimePlatform;
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of having this subproperty, how about we inline the 2 fields from RuntimePlatform here? It will be easier to work with for users.

Prefer flat properties, CDK Design Guidelines, section Props.


/**
* A map from environment variable names to the secrets for the container. Allows your job definitions
* to reference the secret by the environment variable name defined in this property.
Expand Down Expand Up @@ -585,6 +604,7 @@ abstract class EcsContainerDefinitionBase extends Construct implements IEcsConta
public readonly linuxParameters?: LinuxParameters;
public readonly logDriverConfig?: ecs.LogDriverConfig;
public readonly readonlyRootFilesystem?: boolean;
public readonly runtimePlatform?: RuntimePlatform;
public readonly secrets?: { [envVarName: string]: Secret };
public readonly user?: string;
public readonly volumes: EcsVolume[];
Expand Down Expand Up @@ -618,6 +638,10 @@ abstract class EcsContainerDefinitionBase extends Construct implements IEcsConta
this.user = props.user;
this.volumes = props.volumes ?? [];

if (props.runtimePlatform) {
this.runtimePlatform = props.runtimePlatform;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you should modify the _renderContainerDefinition() function to add the new runtimePlatform property like

runtimePlatform: this.runtimePlatform

So it will synth a new container definition for ContainerProperties

this.imageConfig = props.image.bind(this, {
...this as any,
taskDefinition: {
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-batch-alpha/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export * from './linux-parameters';
export * from './managed-compute-environment';
export * from './multinode-job-definition';
export * from './scheduling-policy';
export * from './unmanaged-compute-environment';
export * from './unmanaged-compute-environment';
export * from './runtime-platform';
110 changes: 110 additions & 0 deletions packages/@aws-cdk/aws-batch-alpha/lib/runtime-platform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* The CpuArchitecture for Runtime Platform.
*/
export class CpuArchitecture {
/**
* ARM64
* */
public static readonly ARM64 = CpuArchitecture.of('ARM64');

/**
* X86_64
*/
public static readonly X86_64 = CpuArchitecture.of('X86_64');

/**
* Other cpu architecture.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-runtimeplatform.html#cfn-ecs-taskdefinition-runtimeplatform-cpuarchitecture for all available cpu architecture.
*
* @param cpuArchitecture cpu architecture.
*
*/
public static of(cpuArchitecture: string) { return new CpuArchitecture(cpuArchitecture); }

/**
*
* @param _cpuArchitecture The CPU architecture.
*/
private constructor(public readonly _cpuArchitecture: string) { }
}

/**
* The operating system for Fargate Runtime Platform.
*/
export class OperatingSystemFamily {
/**
* LINUX
*/
public static readonly LINUX = OperatingSystemFamily.of('LINUX');

/**
* WINDOWS_SERVER_2004_CORE
*/
public static readonly WINDOWS_SERVER_2004_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_2004_CORE');

/**
* WINDOWS_SERVER_2016_FULL
*/
public static readonly WINDOWS_SERVER_2016_FULL = OperatingSystemFamily.of('WINDOWS_SERVER_2016_FULL');

/**
* WINDOWS_SERVER_2019_CORE
*/
public static readonly WINDOWS_SERVER_2019_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_2019_CORE');

/**
* WINDOWS_SERVER_2019_FULL
*/
public static readonly WINDOWS_SERVER_2019_FULL = OperatingSystemFamily.of('WINDOWS_SERVER_2019_FULL');

/**
* WINDOWS_SERVER_2022_CORE
*/
public static readonly WINDOWS_SERVER_2022_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_2022_CORE');

/**
* WINDOWS_SERVER_2022_FULL
*/
public static readonly WINDOWS_SERVER_2022_FULL = OperatingSystemFamily.of('WINDOWS_SERVER_2022_FULL');

/**
* WINDOWS_SERVER_20H2_CORE
*/
public static readonly WINDOWS_SERVER_20H2_CORE = OperatingSystemFamily.of('WINDOWS_SERVER_20H2_CORE');

/*
* Other operating system family.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-runtimeplatform.html#cfn-ecs-taskdefinition-runtimeplatform-operatingsystemfamily for all available operating system family.
khushail marked this conversation as resolved.
Show resolved Hide resolved
*
* @param family operating system family.
*
*/
public static of(family: string) { return new OperatingSystemFamily(family); }

/**
*
* @param _operatingSystemFamily The operating system family.
*/
private constructor(public readonly _operatingSystemFamily: string) { }
}

/**
* The interface for Runtime Platform.
*/
export interface RuntimePlatform {
/**
* The CpuArchitecture for Fargate Runtime Platform
*
* @default - Undefined.
*/
readonly cpuArchitecture?: CpuArchitecture,

/**
* The operating system for Fargate Runtime Platform.
*
* @default - Undefined.
*/
readonly operatingSystemFamily?: OperatingSystemFamily,
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Template } from 'aws-cdk-lib/assertions';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import { DefaultTokenResolver, Size, StringConcat, Stack, Tokenization } from 'aws-cdk-lib';
import { Compatibility, EcsEc2ContainerDefinition, EcsFargateContainerDefinition, EcsJobDefinition } from '../lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Compatibility, CpuArchitecture, EcsEc2ContainerDefinition, EcsFargateContainerDefinition, EcsJobDefinition, OperatingSystemFamily, JobQueue, ManagedEc2EcsComputeEnvironment } from '../lib';
import { Vpc } from 'aws-cdk-lib/aws-ec2';


test('EcsJobDefinition respects propagateTags', () => {
// GIVEN
Expand Down Expand Up @@ -42,6 +45,29 @@ test('EcsJobDefinition uses Compatibility.EC2 for EC2 containers', () => {
});
});

test('EcsJobDefinition uses runtimePlatform EC2 containers', () => {
// GIVEN
const stack = new Stack();

// WHEN
new EcsJobDefinition(stack, 'ECSJobDefn', {
container: new EcsEc2ContainerDefinition(stack, 'EcsContainer', {
cpu: 256,
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
memory: Size.mebibytes(2048),
runtimePlatform: {
cpuArchitecture: CpuArchitecture.ARM64,
operatingSystemFamily: OperatingSystemFamily.LINUX,
},
}),
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Batch::JobDefinition', {
PlatformCapabilities: [Compatibility.EC2],
});
});

test('EcsJobDefinition uses Compatibility.FARGATE for Fargate containers', () => {
// GIVEN
const stack = new Stack();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Vpc } from 'aws-cdk-lib/aws-ec2';
import { ContainerImage, FargatePlatformVersion } from 'aws-cdk-lib/aws-ecs';
import { ContainerImage, CpuArchitecture, FargatePlatformVersion, OperatingSystemFamily } from 'aws-cdk-lib/aws-ecs';
import * as efs from 'aws-cdk-lib/aws-efs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ssm from 'aws-cdk-lib/aws-ssm';
Expand Down Expand Up @@ -42,6 +42,10 @@ new batch.EcsJobDefinition(stack, 'ECSJobDefn', {
name: batch.UlimitName.CORE,
softLimit: 10,
}],
runtimePlatform: {
cpuArchitecture: CpuArchitecture.ARM64,
operatingSystemFamily: OperatingSystemFamily.LINUX,
},
secrets: {
MY_SECRET_ENV_VAR: batch.Secret.fromSecretsManager(new secretsmanager.Secret(stack, 'mySecret')),
ANOTHER_ONE: batch.Secret.fromSecretsManagerVersion(new secretsmanager.Secret(stack, 'anotherSecret'), {
Expand Down
Loading