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

fix(aws-batch): Support omitting ComputeEnvironment security groups so that they can be specified in Launch Template #21579

Merged
merged 23 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
36 changes: 36 additions & 0 deletions packages/@aws-cdk/aws-batch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,42 @@ const myComputeEnv = new batch.ComputeEnvironment(this, 'ComputeEnv', {
});
```

Note that if your launch template explicitly specifies network interfaces,
for example to use an Elastic Fabric Adapter, you must explicitly tell CDK not to
auto-create security groups in the `ComputeEnvironment` construct. Instead, you must
define them in the Launch Template, and set `useLaunchTemplateNetworkInterface`. For example:

```ts
declare const vpc: ec2.Vpc;

const efaSecurityGroup = new ec2.SecurityGroup(this, 'EFASecurityGroup', {
vpc,
});

const launchTemplateEFA = new ec2.CfnLaunchTemplate(this, 'LaunchTemplate', {
launchTemplateName: 'LaunchTemplateName',
launchTemplateData: {
networkInterfaces: [{
deviceIndex: 0,
subnetId: vpc.privateSubnets[0].subnetId,
interfaceType: 'efa',
groups: [efaSecurityGroup.securityGroupId],
}],
},
});

const computeEnvironmentEFA = new batch.ComputeEnvironment(this, 'EFAComputeEnv', {
managed: true,
computeResources: {
useLaunchTemplateNetworkInterface: true,
tcutts marked this conversation as resolved.
Show resolved Hide resolved
vpc,
launchTemplate: {
launchTemplateName: launchTemplateEFA.launchTemplateName as string,
},
},
});
```

### Importing an existing Compute Environment

To import an existing batch compute environment, call `ComputeEnvironment.fromComputeEnvironmentArn()`.
Expand Down
50 changes: 41 additions & 9 deletions packages/@aws-cdk/aws-batch/lib/compute-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,17 @@ export interface ComputeResources {
*/
readonly launchTemplate?: LaunchTemplateSpecification;

/**
* Use security groups defined in the launch template network interfaces
*
* In some cases, such as specifying Elastic Fabric Adapters, network
* network interfaces must be used to specify security groups. This
* parameter is mutually exclusive with securityGroups
*
* @default - false
*/
readonly useLaunchTemplateNetworkInterface?: boolean;

/**
* The types of EC2 instances that may be launched in the compute environment. You can specify instance
* families to launch any instance type within those families (for example, c4 or p3), or you can specify
Expand All @@ -138,9 +149,11 @@ export interface ComputeResources {
readonly instanceTypes?: ec2.InstanceType[];

/**
* The EC2 security group(s) associated with instances launched in the compute environment.
* Up to 5 EC2 security group(s) associated with instances launched in the compute environment.
*
* This parameter is mutually exclusive with useLaunchTemplateInterface
*
* @default - AWS default security group.
* @default - Create a single default security group.
tcutts marked this conversation as resolved.
Show resolved Hide resolved
*/
readonly securityGroups?: ec2.ISecurityGroup[];

Expand Down Expand Up @@ -375,7 +388,9 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
const spotFleetRole = this.getSpotFleetRole(props);
let computeResources: CfnComputeEnvironment.ComputeResourcesProperty | undefined;

this.connections = this.buildConnections(props.computeResources?.vpc, props.computeResources?.securityGroups);
const useLaunchTemplateNetworkInterface = props.computeResources?.useLaunchTemplateNetworkInterface ? true : false;

this.connections = this.buildConnections(useLaunchTemplateNetworkInterface, props.computeResources?.vpc, props.computeResources?.securityGroups);

// Only allow compute resources to be set when using MANAGED type
if (props.computeResources && this.isManaged(props)) {
Expand All @@ -388,7 +403,7 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
launchTemplate: props.computeResources.launchTemplate,
maxvCpus: props.computeResources.maxvCpus || 256,
placementGroup: props.computeResources.placementGroup,
securityGroupIds: this.getSecurityGroupIds(),
securityGroupIds: this.getSecurityGroupIds(useLaunchTemplateNetworkInterface),
spotIamFleetRole: spotFleetRole?.roleArn,
subnets: props.computeResources.vpc.selectSubnets(props.computeResources.vpcSubnets).subnetIds,
tags: props.computeResources.computeResourcesTags,
Expand Down Expand Up @@ -520,6 +535,11 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
if (props.computeResources.spotFleetRole !== undefined) {
throw new Error('Spot fleet role must not be set for Fargate compute environments');
}

// useNetworkInterfaces cannot be specified for Fargate
if (props.computeResources.useLaunchTemplateNetworkInterface !== undefined) {
throw new Error('LaunchTemplate network interfaces must not be set for Fargate compute environments');
tcutts marked this conversation as resolved.
Show resolved Hide resolved
}
} else {
// VALIDATE FOR ON_DEMAND AND SPOT
if (props.computeResources.minvCpus) {
Expand Down Expand Up @@ -547,6 +567,18 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
throw new Error('You must specify either the launch template ID or launch template name in the request.');
}

//useLaunchTemplateNetworkInterface requires a launch template
if (props.computeResources.useLaunchTemplateNetworkInterface &&
!props.computeResources.launchTemplate ) {
throw new Error('useLaunchTemplateNetworkInterfaces requires launchTemplate to be specified');
}

// useLaunchTemplateNetworkInteface cannot have securityGroups defined
if (props.computeResources.useLaunchTemplateNetworkInterface &&
props.computeResources.securityGroups ) {
throw new Error('securityGroups cannot be specified if useLaunchTemplateNetworkInterfaces is true');
}

// Setting a bid percentage is only allowed on SPOT resources +
// Cannot use SPOT_CAPACITY_OPTIMIZED when using ON_DEMAND
if (props.computeResources.type === ComputeResourceType.ON_DEMAND) {
Expand Down Expand Up @@ -584,9 +616,9 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
return instanceTypes.map((type: ec2.InstanceType) => type.toString());
}

private buildConnections(vpc?: ec2.IVpc, securityGroups?:ec2.ISecurityGroup[]): ec2.Connections {
private buildConnections(useLaunchTemplateNetworkInterface: boolean, vpc?: ec2.IVpc, securityGroups?:ec2.ISecurityGroup[]): ec2.Connections {

if (vpc === undefined) {
if (vpc === undefined || useLaunchTemplateNetworkInterface ) {
return new ec2.Connections({});
}

Expand All @@ -597,12 +629,12 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment,
],
});
}

return new ec2.Connections({ securityGroups });
};

private getSecurityGroupIds(): string[] | undefined {
if (this.connections === undefined) {
private getSecurityGroupIds(useLaunchTemplateInterface: boolean): string[] | undefined {
if (this.connections === undefined ||
useLaunchTemplateInterface ) {
return undefined;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Loading