Skip to content

Commit 1d65608

Browse files
authored
feat: Storage size settings for AMI builder (#617)
1 parent c1ee867 commit 1d65608

File tree

8 files changed

+229
-108
lines changed

8 files changed

+229
-108
lines changed

API.md

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/image-builders/aws-image-builder/ami.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { aws_imagebuilder as imagebuilder } from 'aws-cdk-lib';
33
import { Construct } from 'constructs';
44
import { ImageBuilderComponent } from './builder';
55
import { ImageBuilderObjectBase } from './common';
6-
import { Architecture, Os } from '../../providers';
6+
import { amiRootDevice, Architecture, Os } from '../../providers';
77
import { uniqueImageBuilderName } from '../common';
88

99
/**
@@ -27,6 +27,11 @@ interface AmiRecipeProperties {
2727
*/
2828
readonly baseAmi: string;
2929

30+
/**
31+
* Storage size for the builder.
32+
*/
33+
readonly storageSize?: cdk.Size;
34+
3035
/**
3136
* Components to add to target container image.
3237
*/
@@ -57,12 +62,23 @@ export class AmiRecipe extends ImageBuilderObjectBase {
5762
};
5863
});
5964

65+
const blockDeviceMappings = props.storageSize ? [
66+
{
67+
deviceName: amiRootDevice(this, props.baseAmi).ref,
68+
ebs: {
69+
volumeSize: props.storageSize.toGibibytes(),
70+
deleteOnTermination: true,
71+
},
72+
},
73+
] : undefined;
74+
6075
this.name = uniqueImageBuilderName(this);
6176
this.version = this.generateVersion('ImageRecipe', this.name, {
6277
platform: props.platform,
6378
components,
6479
parentAmi: props.baseAmi,
6580
tags: props.tags,
81+
blockDeviceMappings,
6682
});
6783

6884
let workingDirectory;
@@ -81,6 +97,7 @@ export class AmiRecipe extends ImageBuilderObjectBase {
8197
components,
8298
workingDirectory,
8399
tags: props.tags,
100+
blockDeviceMappings,
84101
});
85102

86103
this.arn = recipe.attrArn;

src/image-builders/aws-image-builder/builder.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ export interface AwsImageBuilderRunnerImageBuilderProps {
3939
*/
4040
readonly instanceType?: ec2.InstanceType;
4141

42+
/**
43+
* Size of volume available for builder instances. This modifies the boot volume size and doesn't add any additional volumes.
44+
*
45+
* Use this if you're building images with big components and need more space.
46+
*
47+
* @default default size for AMI (usually 30GB for Linux and 50GB for Windows)
48+
*/
49+
readonly storageSize?: cdk.Size;
50+
4251
/**
4352
* Options for fast launch.
4453
*
@@ -312,6 +321,7 @@ export class AwsImageBuilderRunnerImageBuilder extends RunnerImageBuilderBase {
312321
private infrastructure: imagebuilder.CfnInfrastructureConfiguration | undefined;
313322
private readonly role: iam.Role;
314323
private readonly fastLaunchOptions?: FastLaunchOptions;
324+
private readonly storageSize?: cdk.Size;
315325
private readonly waitOnDeploy: boolean;
316326
private readonly dockerSetupCommands: string[];
317327
private readonly tags: { [key: string]: string };
@@ -335,6 +345,7 @@ export class AwsImageBuilderRunnerImageBuilder extends RunnerImageBuilderBase {
335345
this.baseAmi = props?.baseAmi ?? defaultBaseAmi(this, this.os, this.architecture);
336346
this.instanceType = props?.awsImageBuilderOptions?.instanceType ?? ec2.InstanceType.of(ec2.InstanceClass.M6I, ec2.InstanceSize.LARGE);
337347
this.fastLaunchOptions = props?.awsImageBuilderOptions?.fastLaunchOptions;
348+
this.storageSize = props?.awsImageBuilderOptions?.storageSize;
338349
this.waitOnDeploy = props?.waitOnDeploy ?? true;
339350
this.dockerSetupCommands = props?.dockerSetupCommands ?? [];
340351

@@ -766,6 +777,7 @@ export class AwsImageBuilderRunnerImageBuilder extends RunnerImageBuilderBase {
766777
components: this.bindComponents(),
767778
architecture: this.architecture,
768779
baseAmi: this.baseAmi,
780+
storageSize: this.storageSize,
769781
tags: this.tags,
770782
});
771783

src/providers/ami-root-device.lambda.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { DescribeImagesCommand, DescribeLaunchTemplateVersionsCommand, EC2Client } from '@aws-sdk/client-ec2';
2+
import { GetImageCommand, ImagebuilderClient } from '@aws-sdk/client-imagebuilder';
23
import { GetParameterCommand, SSMClient } from '@aws-sdk/client-ssm';
34
import * as AWSLambda from 'aws-lambda';
45
import { customResourceRespond } from '../lambda-helpers';
56

67
const ssm = new SSMClient();
78
const ec2 = new EC2Client();
9+
const ib = new ImagebuilderClient();
810

911

1012
async function handleAmi(event: AWSLambda.CloudFormationCustomResourceEvent, ami: string) {
@@ -75,6 +77,20 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
7577
break;
7678
}
7779

80+
if (ami.match('^arn:aws[^:]*:imagebuilder:[^:]+:[^:]+:image/.*$')) {
81+
console.log(`Checking Image Builder ${ami}`);
82+
83+
const img = await ib.send(new GetImageCommand({ imageBuildVersionArn: ami }));
84+
const actualAmi = img.image?.outputResources?.amis?.[0]?.image;
85+
if (!actualAmi) {
86+
await customResourceRespond(event, 'FAILED', `${ami} doesn't have an AMI`, 'ERROR', {});
87+
break;
88+
}
89+
90+
await handleAmi(event, actualAmi);
91+
break;
92+
}
93+
7894
await customResourceRespond(event, 'FAILED', `Unknown type of AMI ${ami}`, 'ERROR', {});
7995
break;
8096
case 'Delete':

src/providers/common.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,8 @@ export abstract class BaseProvider extends Construct {
507507
/**
508508
* Use custom resource to determine the root device name of a given AMI, Launch Template, or SSM parameter pointing to AMI.
509509
*
510+
* TODO move somewhere more common as it's used by both providers and AMI builder now
511+
*
510512
* @internal
511513
*/
512514
export function amiRootDevice(scope: Construct, ami?: string) {
@@ -521,6 +523,7 @@ export function amiRootDevice(scope: Construct, ami?: string) {
521523
'ssm:GetParameter',
522524
'ec2:DescribeImages',
523525
'ec2:DescribeLaunchTemplateVersions',
526+
'imagebuilder:GetImage',
524527
],
525528
resources: ['*'],
526529
}),

test/default.integ.snapshot/github-runners-test.assets.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -105,54 +105,54 @@
105105
}
106106
}
107107
},
108-
"83c9fbef7e367049876156e1b2fd8fb89d8044003b26b693e2e7aca16fd4fb7f": {
108+
"88cc171bf3103a3b98ba0006fc7e5c6fdfd338c03591b344bb4cf60f1a9da18c": {
109109
"source": {
110-
"path": "asset.83c9fbef7e367049876156e1b2fd8fb89d8044003b26b693e2e7aca16fd4fb7f.lambda",
110+
"path": "asset.88cc171bf3103a3b98ba0006fc7e5c6fdfd338c03591b344bb4cf60f1a9da18c.lambda",
111111
"packaging": "zip"
112112
},
113113
"destinations": {
114114
"current_account-current_region": {
115115
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
116-
"objectKey": "83c9fbef7e367049876156e1b2fd8fb89d8044003b26b693e2e7aca16fd4fb7f.zip",
116+
"objectKey": "88cc171bf3103a3b98ba0006fc7e5c6fdfd338c03591b344bb4cf60f1a9da18c.zip",
117117
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
118118
}
119119
}
120120
},
121-
"58d5d36cd7892b7fd12ad066a7375852ea9dccee4d69b43d39d22c6017650342": {
121+
"83c9fbef7e367049876156e1b2fd8fb89d8044003b26b693e2e7aca16fd4fb7f": {
122122
"source": {
123-
"path": "asset.58d5d36cd7892b7fd12ad066a7375852ea9dccee4d69b43d39d22c6017650342.lambda",
123+
"path": "asset.83c9fbef7e367049876156e1b2fd8fb89d8044003b26b693e2e7aca16fd4fb7f.lambda",
124124
"packaging": "zip"
125125
},
126126
"destinations": {
127127
"current_account-current_region": {
128128
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
129-
"objectKey": "58d5d36cd7892b7fd12ad066a7375852ea9dccee4d69b43d39d22c6017650342.zip",
129+
"objectKey": "83c9fbef7e367049876156e1b2fd8fb89d8044003b26b693e2e7aca16fd4fb7f.zip",
130130
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
131131
}
132132
}
133133
},
134-
"49869fe027dea4e6f2328c09949544583e341ef66f515b3b37ddacf60879a30c": {
134+
"58d5d36cd7892b7fd12ad066a7375852ea9dccee4d69b43d39d22c6017650342": {
135135
"source": {
136-
"path": "asset.49869fe027dea4e6f2328c09949544583e341ef66f515b3b37ddacf60879a30c.lambda",
136+
"path": "asset.58d5d36cd7892b7fd12ad066a7375852ea9dccee4d69b43d39d22c6017650342.lambda",
137137
"packaging": "zip"
138138
},
139139
"destinations": {
140140
"current_account-current_region": {
141141
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
142-
"objectKey": "49869fe027dea4e6f2328c09949544583e341ef66f515b3b37ddacf60879a30c.zip",
142+
"objectKey": "58d5d36cd7892b7fd12ad066a7375852ea9dccee4d69b43d39d22c6017650342.zip",
143143
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
144144
}
145145
}
146146
},
147-
"2b3e3110ffb96a7df77acaa663361ec1c03e985af62941397f4806ba6fbde75f": {
147+
"49869fe027dea4e6f2328c09949544583e341ef66f515b3b37ddacf60879a30c": {
148148
"source": {
149-
"path": "asset.2b3e3110ffb96a7df77acaa663361ec1c03e985af62941397f4806ba6fbde75f.lambda",
149+
"path": "asset.49869fe027dea4e6f2328c09949544583e341ef66f515b3b37ddacf60879a30c.lambda",
150150
"packaging": "zip"
151151
},
152152
"destinations": {
153153
"current_account-current_region": {
154154
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
155-
"objectKey": "2b3e3110ffb96a7df77acaa663361ec1c03e985af62941397f4806ba6fbde75f.zip",
155+
"objectKey": "49869fe027dea4e6f2328c09949544583e341ef66f515b3b37ddacf60879a30c.zip",
156156
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
157157
}
158158
}
@@ -209,15 +209,15 @@
209209
}
210210
}
211211
},
212-
"3567610749b1cf82857927a0f111cfd36a7121619b529d37f8173ea62c8e5352": {
212+
"ad6535663e15be1d9ef317b02833ee916c2e2121ebf0a5bf118355124cce1a65": {
213213
"source": {
214214
"path": "github-runners-test.template.json",
215215
"packaging": "file"
216216
},
217217
"destinations": {
218218
"current_account-current_region": {
219219
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
220-
"objectKey": "3567610749b1cf82857927a0f111cfd36a7121619b529d37f8173ea62c8e5352.json",
220+
"objectKey": "ad6535663e15be1d9ef317b02833ee916c2e2121ebf0a5bf118355124cce1a65.json",
221221
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
222222
}
223223
}

0 commit comments

Comments
 (0)