Skip to content

Commit

Permalink
chore(apprunner): add validation cpu and memory for app runner (#25877)
Browse files Browse the repository at this point in the history
This PR adds the same validation for the App Runner's CPU and Memory values as [CloudFormation's input patterns](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apprunner-service-instanceconfiguration.html#cfn-apprunner-service-instanceconfiguration-cpu).

Closes #25872

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
go-to-k authored Jun 12, 2023
1 parent 12fe60e commit e6073fc
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 8 deletions.
28 changes: 26 additions & 2 deletions packages/@aws-cdk/aws-apprunner-alpha/lib/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,19 @@ export class Cpu {
*
* @param unit custom CPU unit
*/
public static of(unit: string) { return new Cpu(unit); }
public static of(unit: string): Cpu {
const numericPatterns = ['256', '512', '1024', '2048', '4096'];
const unitPatterns = ['0.25 vCPU', '0.5 vCPU', '1 vCPU', '2 vCPU', '4 vCPU'];
const allowedPatterns = numericPatterns.concat(unitPatterns);
const isValidValue = allowedPatterns.some(
(pattern) => pattern === unit,
);
if (!isValidValue) {
throw new Error('CPU value is invalid');
};

return new Cpu(unit);
}

/**
*
Expand Down Expand Up @@ -126,7 +138,19 @@ export class Memory {
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-apprunner-service-instanceconfiguration.html#cfn-apprunner-service-instanceconfiguration-memory
*/
public static of(unit: string) { return new Memory(unit); }
public static of(unit: string): Memory {
const numericPatterns = ['512', '1024', '2048', '3072', '4096', '6144', '8192', '10240', '12288'];
const unitPatterns = ['0.5 GB', '1 GB', '2 GB', '3 GB', '4 GB', '6 GB', '8 GB', '10 GB', '12 GB'];
const allowedPatterns = numericPatterns.concat(unitPatterns);
const isValidValue = allowedPatterns.some(
(pattern) => pattern === unit,
);
if (!isValidValue) {
throw new Error('Memory value is invalid');
};

return new Memory(unit);
}

/**
*
Expand Down
76 changes: 70 additions & 6 deletions packages/@aws-cdk/aws-apprunner-alpha/test/service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ test('custom IAM access role and instance role are allowed', () => {
});
});

test('cpu and memory properties are allowed', () => {
test('cpu and memory properties as unit values are allowed', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'demo-stack');
Expand All @@ -925,7 +925,7 @@ test('cpu and memory properties are allowed', () => {
});
});

test('custom cpu and memory units are allowed', () => {
test('cpu and memory properties as numeric values are allowed', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'demo-stack');
Expand All @@ -934,14 +934,14 @@ test('custom cpu and memory units are allowed', () => {
source: apprunner.Source.fromEcrPublic({
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
}),
cpu: apprunner.Cpu.of('Some vCPU'),
memory: apprunner.Memory.of('Some GB'),
cpu: apprunner.Cpu.of('1024'),
memory: apprunner.Memory.of('3072'),
});
// THEN
Template.fromStack(stack).hasResourceProperties('AWS::AppRunner::Service', {
InstanceConfiguration: {
Cpu: 'Some vCPU',
Memory: 'Some GB',
Cpu: '1024',
Memory: '3072',
},
NetworkConfiguration: {
EgressConfiguration: {
Expand All @@ -951,6 +951,70 @@ test('custom cpu and memory units are allowed', () => {
});
});

test('invalid cpu property as unit value is not allowed', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'demo-stack');
// WHEN
expect(() => {
new apprunner.Service(stack, 'DemoService', {
source: apprunner.Source.fromEcrPublic({
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
}),
cpu: apprunner.Cpu.of('1000 vCPU'),
memory: apprunner.Memory.of('3 GB'),
});
}).toThrow('CPU value is invalid');
});

test('invalid cpu property as numeric value is not allowed', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'demo-stack');
// WHEN
expect(() => {
new apprunner.Service(stack, 'DemoService', {
source: apprunner.Source.fromEcrPublic({
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
}),
cpu: apprunner.Cpu.of('1'),
memory: apprunner.Memory.of('3 GB'),
});
}).toThrow('CPU value is invalid');
});

test('invalid memory property as unit value is not allowed', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'demo-stack');
// WHEN
expect(() => {
new apprunner.Service(stack, 'DemoService', {
source: apprunner.Source.fromEcrPublic({
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
}),
cpu: apprunner.Cpu.of('1 vCPU'),
memory: apprunner.Memory.of('3000 GB'),
});
}).toThrow('Memory value is invalid');
});

test('invalid memory property as numeric value is not allowed', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'demo-stack');
// WHEN
expect(() => {
new apprunner.Service(stack, 'DemoService', {
source: apprunner.Source.fromEcrPublic({
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
}),
cpu: apprunner.Cpu.of('1 vCPU'),
memory: apprunner.Memory.of('3'),
});
}).toThrow('Memory value is invalid');
});

test('environment variable with a prefix of AWSAPPRUNNER should throw an error', () => {
// GIVEN
const app = new cdk.App();
Expand Down

0 comments on commit e6073fc

Please sign in to comment.