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(batch): support cfn parameters for managed compute environment properties minvcpus, maxvcpus, and spotbidpercentage #32954

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
18 changes: 11 additions & 7 deletions packages/aws-cdk-lib/aws-batch/lib/managed-compute-environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as ec2 from '../../aws-ec2';
import * as eks from '../../aws-eks';
import * as iam from '../../aws-iam';
import { IRole } from '../../aws-iam';
import { ArnFormat, Duration, ITaggable, Lazy, Resource, Stack, TagManager, TagType } from '../../core';
import { ArnFormat, Duration, ITaggable, Lazy, Resource, Stack, TagManager, TagType, Token } from '../../core';

/**
* Represents a Managed ComputeEnvironment. Batch will provision EC2 Instances to
Expand Down Expand Up @@ -1193,10 +1193,14 @@ function validateSpotConfig(id: string, spot?: boolean, spotBidPercentage?: numb
if (spotBidPercentage) {
if (!spot) {
throw new Error(`Managed ComputeEnvironment '${id}' specifies 'spotBidPercentage' without specifying 'spot'`);
} else if (spotBidPercentage > 100) {
throw new Error(`Managed ComputeEnvironment '${id}' specifies 'spotBidPercentage' > 100`);
} else if (spotBidPercentage < 0) {
throw new Error(`Managed ComputeEnvironment '${id}' specifies 'spotBidPercentage' < 0`);
}

if (!Token.isUnresolved(spotBidPercentage)) {
if (spotBidPercentage > 100) {
throw new Error(`Managed ComputeEnvironment '${id}' specifies 'spotBidPercentage' > 100`);
} else if (spotBidPercentage < 0) {
throw new Error(`Managed ComputeEnvironment '${id}' specifies 'spotBidPercentage' < 0`);
}
}
}

Expand All @@ -1208,10 +1212,10 @@ function validateSpotConfig(id: string, spot?: boolean, spotBidPercentage?: numb
}

function validateVCpus(id: string, minvCpus: number, maxvCpus: number): void {
if (minvCpus < 0) {
if (!Token.isUnresolved(minvCpus) && minvCpus < 0) {
throw new Error(`Managed ComputeEnvironment '${id}' has 'minvCpus' = ${minvCpus} < 0; 'minvCpus' cannot be less than zero`);
}
if (minvCpus > maxvCpus) {
if (!Token.isUnresolved(minvCpus) && !Token.isUnresolved(maxvCpus) && minvCpus > maxvCpus) {
throw new Error(`Managed ComputeEnvironment '${id}' has 'minvCpus' = ${minvCpus} > 'maxvCpus' = ${maxvCpus}; 'minvCpus' cannot be greater than 'maxvCpus'`);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { Template } from '../../assertions';
import * as ec2 from '../../aws-ec2';
import * as eks from '../../aws-eks';
import { ArnPrincipal, Role, ServicePrincipal } from '../../aws-iam';
import { Stack, Duration, Tags } from '../../core';
import { Stack, Duration, Tags, CfnParameter } from '../../core';
import { AllocationStrategy, CfnComputeEnvironmentProps, ManagedEc2EcsComputeEnvironment, ManagedEc2EcsComputeEnvironmentProps, ManagedEc2EksComputeEnvironment, ManagedEc2EksComputeEnvironmentProps, FargateComputeEnvironment, EcsMachineImageType, EksMachineImageType } from '../lib';
import { Type } from '@aws-sdk/client-cloudwatch-logs';

const defaultExpectedEcsProps: CfnComputeEnvironmentProps = {
type: 'managed',
Expand Down Expand Up @@ -133,6 +134,32 @@ describe.each([ManagedEc2EcsComputeEnvironment, ManagedEc2EksComputeEnvironment]
});
});

test('can specify parameterized maxvCpus', () => {
// WHEN
const maxVCpuParameter = new CfnParameter(stack, 'MaxVCpuParameter', {
default: 512,
minValue: 1,
type: 'Number',
});

new ComputeEnvironment(stack, 'MyCE', {
...defaultProps,
vpc,
maxvCpus: maxVCpuParameter.valueAsNumber,
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', {
...expectedProps,
ComputeResources: {
...defaultComputeResources,
MaxvCpus: {
Ref: 'MaxVCpuParameter',
},
},
});
});

test('can specify minvCpus', () => {
// WHEN
new ComputeEnvironment(stack, 'MyCE', {
Expand All @@ -151,6 +178,61 @@ describe.each([ManagedEc2EcsComputeEnvironment, ManagedEc2EksComputeEnvironment]
});
});

test('can specify parameterized minvCpus', () => {
// WHEN
const minVCpuParameter = new CfnParameter(stack, 'MinVCpuParameter', {
default: 512,
minValue: 1,
type: 'Number',
});

new ComputeEnvironment(stack, 'MyCE', {
...defaultProps,
vpc,
minvCpus: minVCpuParameter.valueAsNumber,
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', {
...expectedProps,
ComputeResources: {
...defaultComputeResources,
MinvCpus: {
Ref: 'MinVCpuParameter',
},
},
});
});

test('can specify spotBidPercentage as a parameter', () => {
// WHEN
const spotBidPercentageParameter = new CfnParameter(stack, 'SpotBidPercentageParameter', {
default: 100,
minValue: 1,
type: 'Number',
});

new ComputeEnvironment(stack, 'MyCE', {
...defaultProps,
vpc,
spot: true,
spotBidPercentage: spotBidPercentageParameter.valueAsNumber,
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::Batch::ComputeEnvironment', {
...expectedProps,
ComputeResources: {
...defaultComputeResources,
Type: 'SPOT',
AllocationStrategy: AllocationStrategy.SPOT_PRICE_CAPACITY_OPTIMIZED,
BidPercentage: {
Ref: 'SpotBidPercentageParameter',
},
},
});
});

test('can be disabled', () => {
// WHEN
new ComputeEnvironment(stack, 'MyCE', {
Expand Down Expand Up @@ -675,6 +757,20 @@ describe.each([ManagedEc2EcsComputeEnvironment, ManagedEc2EksComputeEnvironment]
}).toThrow(/Managed ComputeEnvironment 'MyCE' specifies 'spotBidPercentage' without specifying 'spot'/);
});

test('throws error when spotBidPercentage is a parameter and spot is not enabled', () => {
// THEN
expect(() => {
new ComputeEnvironment(stack, 'MyCE', {
...defaultProps,
vpc,
spotBidPercentage: new CfnParameter(stack, 'SpotBidPercentageParameter', {
type: 'Number',
}),
spot: false,
});
}).toThrow(/Managed ComputeEnvironment 'MyCE' specifies 'spotBidPercentage' without specifying 'spot'/);
});

test('throws error when spotBidPercentage > 100', () => {
// THEN
expect(() => {
Expand Down Expand Up @@ -711,6 +807,38 @@ describe.each([ManagedEc2EcsComputeEnvironment, ManagedEc2EksComputeEnvironment]
}).toThrow(/Managed ComputeEnvironment 'MyCE' has 'minvCpus' = 1024 > 'maxvCpus' = 512; 'minvCpus' cannot be greater than 'maxvCpus'/);
});

test('skips validation for minvCpus < maxvCpus check when either properties are tokens', () => {
// WHEN
const minVCpuParameter = new CfnParameter(stack, 'MinVCpuParameter', {
default: 512,
minValue: 0,
type: 'Number',
});

const maxVCpuParameter = new CfnParameter(stack, 'MaxVCpuParameter', {
default: 512,
minValue: 1,
type: 'Number',
});

// THEN
expect(() => {
new ComputeEnvironment(stack, 'MyCE', {
...defaultProps,
vpc,
maxvCpus: maxVCpuParameter.valueAsNumber,
minvCpus: 1024,
});

new ComputeEnvironment(stack, 'MyOtherCE', {
...defaultProps,
vpc,
maxvCpus: 1024,
minvCpus: minVCpuParameter.valueAsNumber,
});
}).not.toThrow(/Managed ComputeEnvironment 'MyCE' has 'minvCpus' = 1024 > 'maxvCpus' = 512; 'minvCpus' cannot be greater than 'maxvCpus'/);
});

test('throws error when minvCpus < 0', () => {
// THEN
expect(() => {
Expand Down
Loading