Skip to content

Commit 4eac4de

Browse files
authored
feat(codebuild): improved support for ARM build images (#19052)
Fixes #18916 Fixes #9817 ### Motivation CDK currently has poor and hidden support for using ARM build images for CodeBuild that do not match what you can do with the Console. Currently, CDK has under LinuxBuildImage two constants not mentioned in the documentation. The constants internally map to a hidden ArmBuildImage class, which provides support for the standard CodeBuild ARM build images. That is the extent of the support, making ARM a second class citizen compared to x86-64 Linux and Windows build images as, for example, you can't use custom aarch64 ECR images. ### Changes This pull request addresses the missing support by: - renaming the previously hidden class ArmBuildImage to LinuxArmBuildImage (in case there are Windows ARM Build Images in the future). - exporting LinuxArmBuildImage so it can be used. - adding the two ARM constants present in LinuxBuildImage also to LinuxArmBuildImage. The constants are also left under LinuxBuildImage to not break backwards compatibility. - adding the method fromEcrRepository() to support custom ARM build images. - making the LinuxArmBuildImage closer to the LinuxBuildImage and WindowsBuildImage (built with props instead of just image name). - updating documentation to show examples of ARM and highlighting the LinuxBuildImage is for x86-64. ### Testing The unit test for ARM image is still valid. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 5de7b86 commit 4eac4de

File tree

5 files changed

+458
-37
lines changed

5 files changed

+458
-37
lines changed

packages/@aws-cdk/aws-codebuild/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,12 @@ can use the `environment` property to customize the build environment:
280280
## Images
281281

282282
The CodeBuild library supports both Linux and Windows images via the
283-
`LinuxBuildImage` and `WindowsBuildImage` classes, respectively.
283+
`LinuxBuildImage` (or `LinuxArmBuildImage`), and `WindowsBuildImage` classes, respectively.
284284

285285
You can specify one of the predefined Windows/Linux images by using one
286286
of the constants such as `WindowsBuildImage.WIN_SERVER_CORE_2019_BASE`,
287-
`WindowsBuildImage.WINDOWS_BASE_2_0` or `LinuxBuildImage.STANDARD_2_0`.
287+
`WindowsBuildImage.WINDOWS_BASE_2_0`, `LinuxBuildImage.STANDARD_2_0`, or
288+
`LinuxArmBuildImage.AMAZON_LINUX_2_ARM`.
288289

289290
Alternatively, you can specify a custom image using one of the static methods on
290291
`LinuxBuildImage`:
@@ -302,6 +303,10 @@ or one of the corresponding methods on `WindowsBuildImage`:
302303
* `WindowsBuildImage.fromEcrRepository(repo[, tag, imageType])`
303304
* `WindowsBuildImage.fromAsset(parent, id, props, [, imageType])`
304305

306+
or one of the corresponding methods on `LinuxArmBuildImage`:
307+
308+
* `LinuxArmBuildImage.fromEcrRepository(repo[, tag])`
309+
305310
Note that the `WindowsBuildImage` version of the static methods accepts an optional parameter of type `WindowsImageType`,
306311
which can be either `WindowsImageType.STANDARD`, the default, or `WindowsImageType.SERVER_2019`:
307312

packages/@aws-cdk/aws-codebuild/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from './build-spec';
1111
export * from './file-location';
1212
export * from './linux-gpu-build-image';
1313
export * from './untrusted-code-boundary-policy';
14+
export * from './linux-arm-build-image';
1415

1516
// AWS::CodeBuild CloudFormation Resources:
1617
export * from './codebuild.generated';
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import * as ecr from '@aws-cdk/aws-ecr';
2+
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
3+
import { BuildSpec } from './build-spec';
4+
import { runScriptLinuxBuildSpec } from './private/run-script-linux-build-spec';
5+
import { BuildEnvironment, ComputeType, IBuildImage, ImagePullPrincipalType } from './project';
6+
7+
/**
8+
* Construction properties of {@link LinuxArmBuildImage}.
9+
* Module-private, as the constructor of {@link LinuxArmBuildImage} is private.
10+
*/
11+
interface LinuxArmBuildImageProps {
12+
readonly imageId: string;
13+
readonly imagePullPrincipalType?: ImagePullPrincipalType;
14+
readonly secretsManagerCredentials?: secretsmanager.ISecret;
15+
readonly repository?: ecr.IRepository;
16+
}
17+
18+
/**
19+
* A CodeBuild image running aarch64 Linux.
20+
*
21+
* This class has a bunch of public constants that represent the CodeBuild ARM images.
22+
*
23+
* You can also specify a custom image using the static method:
24+
*
25+
* - LinuxBuildImage.fromEcrRepository(repo[, tag])
26+
*
27+
*
28+
* @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
29+
*/
30+
export class LinuxArmBuildImage implements IBuildImage {
31+
/** Image "aws/codebuild/amazonlinux2-aarch64-standard:1.0". */
32+
public static readonly AMAZON_LINUX_2_STANDARD_1_0 = LinuxArmBuildImage.fromCodeBuildImageId('aws/codebuild/amazonlinux2-aarch64-standard:1.0');
33+
/** Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". */
34+
public static readonly AMAZON_LINUX_2_STANDARD_2_0 = LinuxArmBuildImage.fromCodeBuildImageId('aws/codebuild/amazonlinux2-aarch64-standard:2.0');
35+
36+
/**
37+
* Returns an ARM image running Linux from an ECR repository.
38+
*
39+
* NOTE: if the repository is external (i.e. imported), then we won't be able to add
40+
* a resource policy statement for it so CodeBuild can pull the image.
41+
*
42+
* @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-ecr.html
43+
*
44+
* @param repository The ECR repository
45+
* @param tag Image tag (default "latest")
46+
* @returns An aarch64 Linux build image from an ECR repository.
47+
*/
48+
public static fromEcrRepository(repository: ecr.IRepository, tag: string = 'latest'): IBuildImage {
49+
return new LinuxArmBuildImage({
50+
imageId: repository.repositoryUriForTag(tag),
51+
imagePullPrincipalType: ImagePullPrincipalType.SERVICE_ROLE,
52+
repository,
53+
});
54+
}
55+
56+
/**
57+
* Uses a Docker image provided by CodeBuild.
58+
*
59+
* @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
60+
*
61+
* @param id The image identifier
62+
* @example 'aws/codebuild/amazonlinux2-aarch64-standard:1.0'
63+
* @returns A Docker image provided by CodeBuild.
64+
*/
65+
public static fromCodeBuildImageId(id: string): IBuildImage {
66+
return new LinuxArmBuildImage({
67+
imageId: id,
68+
imagePullPrincipalType: ImagePullPrincipalType.CODEBUILD,
69+
});
70+
}
71+
72+
public readonly type = 'ARM_CONTAINER';
73+
public readonly defaultComputeType = ComputeType.LARGE;
74+
public readonly imageId: string;
75+
public readonly imagePullPrincipalType?: ImagePullPrincipalType;
76+
public readonly secretsManagerCredentials?: secretsmanager.ISecret;
77+
public readonly repository?: ecr.IRepository;
78+
79+
private constructor(props: LinuxArmBuildImageProps) {
80+
this.imageId = props.imageId;
81+
this.imagePullPrincipalType = props.imagePullPrincipalType;
82+
this.secretsManagerCredentials = props.secretsManagerCredentials;
83+
this.repository = props.repository;
84+
}
85+
86+
/**
87+
* Validates by checking the BuildEnvironment computeType as aarch64 images only support ComputeType.SMALL and
88+
* ComputeType.LARGE
89+
* @param buildEnvironment BuildEnvironment
90+
*/
91+
public validate(buildEnvironment: BuildEnvironment): string[] {
92+
const ret = [];
93+
if (buildEnvironment.computeType &&
94+
buildEnvironment.computeType !== ComputeType.SMALL &&
95+
buildEnvironment.computeType !== ComputeType.LARGE) {
96+
ret.push(`ARM images only support ComputeTypes '${ComputeType.SMALL}' and '${ComputeType.LARGE}' - ` +
97+
`'${buildEnvironment.computeType}' was given`);
98+
}
99+
return ret;
100+
}
101+
102+
public runScriptBuildspec(entrypoint: string): BuildSpec {
103+
return runScriptLinuxBuildSpec(entrypoint);
104+
}
105+
}

packages/@aws-cdk/aws-codebuild/lib/project.ts

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,32 +1642,6 @@ export interface IBindableBuildImage extends IBuildImage {
16421642
bind(scope: CoreConstruct, project: IProject, options: BuildImageBindOptions): BuildImageConfig;
16431643
}
16441644

1645-
class ArmBuildImage implements IBuildImage {
1646-
public readonly type = 'ARM_CONTAINER';
1647-
public readonly defaultComputeType = ComputeType.LARGE;
1648-
public readonly imagePullPrincipalType = ImagePullPrincipalType.CODEBUILD;
1649-
public readonly imageId: string;
1650-
1651-
constructor(imageId: string) {
1652-
this.imageId = imageId;
1653-
}
1654-
1655-
public validate(buildEnvironment: BuildEnvironment): string[] {
1656-
const ret = [];
1657-
if (buildEnvironment.computeType &&
1658-
buildEnvironment.computeType !== ComputeType.SMALL &&
1659-
buildEnvironment.computeType !== ComputeType.LARGE) {
1660-
ret.push(`ARM images only support ComputeTypes '${ComputeType.SMALL}' and '${ComputeType.LARGE}' - ` +
1661-
`'${buildEnvironment.computeType}' was given`);
1662-
}
1663-
return ret;
1664-
}
1665-
1666-
public runScriptBuildspec(entrypoint: string): BuildSpec {
1667-
return runScriptLinuxBuildSpec(entrypoint);
1668-
}
1669-
}
1670-
16711645
/**
16721646
* The options when creating a CodeBuild Docker build image
16731647
* using {@link LinuxBuildImage.fromDockerRegistry}
@@ -1695,8 +1669,12 @@ interface LinuxBuildImageProps {
16951669
readonly repository?: ecr.IRepository;
16961670
}
16971671

1672+
// Keep around to resolve a circular dependency until removing deprecated ARM image constants from LinuxBuildImage
1673+
// eslint-disable-next-line no-duplicate-imports, import/order
1674+
import { LinuxArmBuildImage } from './linux-arm-build-image';
1675+
16981676
/**
1699-
* A CodeBuild image running Linux.
1677+
* A CodeBuild image running x86-64 Linux.
17001678
*
17011679
* This class has a bunch of public constants that represent the most popular images.
17021680
*
@@ -1723,9 +1701,13 @@ export class LinuxBuildImage implements IBuildImage {
17231701
/** The Amazon Linux 2 x86_64 standard image, version `3.0`. */
17241702
public static readonly AMAZON_LINUX_2_3 = LinuxBuildImage.codeBuildImage('aws/codebuild/amazonlinux2-x86_64-standard:3.0');
17251703

1726-
public static readonly AMAZON_LINUX_2_ARM: IBuildImage = new ArmBuildImage('aws/codebuild/amazonlinux2-aarch64-standard:1.0');
1727-
/** Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0". */
1728-
public static readonly AMAZON_LINUX_2_ARM_2: IBuildImage = new ArmBuildImage('aws/codebuild/amazonlinux2-aarch64-standard:2.0');
1704+
/** @deprecated Use LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0 instead. */
1705+
public static readonly AMAZON_LINUX_2_ARM = LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_1_0;
1706+
/**
1707+
* Image "aws/codebuild/amazonlinux2-aarch64-standard:2.0".
1708+
* @deprecated Use LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0 instead.
1709+
* */
1710+
public static readonly AMAZON_LINUX_2_ARM_2 = LinuxArmBuildImage.AMAZON_LINUX_2_STANDARD_2_0;
17291711

17301712
/** @deprecated Use {@link STANDARD_2_0} and specify runtime in buildspec runtime-versions section */
17311713
public static readonly UBUNTU_14_04_BASE = LinuxBuildImage.codeBuildImage('aws/codebuild/ubuntu-base:14.04');
@@ -1789,7 +1771,7 @@ export class LinuxBuildImage implements IBuildImage {
17891771
public static readonly UBUNTU_14_04_DOTNET_CORE_2_1 = LinuxBuildImage.codeBuildImage('aws/codebuild/dot-net:core-2.1');
17901772

17911773
/**
1792-
* @returns a Linux build image from a Docker Hub image.
1774+
* @returns a x86-64 Linux build image from a Docker Hub image.
17931775
*/
17941776
public static fromDockerRegistry(name: string, options: DockerImageOptions = {}): IBuildImage {
17951777
return new LinuxBuildImage({
@@ -1800,7 +1782,7 @@ export class LinuxBuildImage implements IBuildImage {
18001782
}
18011783

18021784
/**
1803-
* @returns A Linux build image from an ECR repository.
1785+
* @returns A x86-64 Linux build image from an ECR repository.
18041786
*
18051787
* NOTE: if the repository is external (i.e. imported), then we won't be able to add
18061788
* a resource policy statement for it so CodeBuild can pull the image.
@@ -1819,7 +1801,7 @@ export class LinuxBuildImage implements IBuildImage {
18191801
}
18201802

18211803
/**
1822-
* Uses an Docker image asset as a Linux build image.
1804+
* Uses an Docker image asset as a x86-64 Linux build image.
18231805
*/
18241806
public static fromAsset(scope: Construct, id: string, props: DockerImageAssetProps): IBuildImage {
18251807
const asset = new DockerImageAsset(scope, id, props);
@@ -1961,7 +1943,7 @@ export class WindowsBuildImage implements IBuildImage {
19611943
}
19621944

19631945
/**
1964-
* @returns A Linux build image from an ECR repository.
1946+
* @returns A Windows build image from an ECR repository.
19651947
*
19661948
* NOTE: if the repository is external (i.e. imported), then we won't be able to add
19671949
* a resource policy statement for it so CodeBuild can pull the image.
@@ -2125,4 +2107,4 @@ export enum ProjectNotificationEvents {
21252107

21262108
function isBindableBuildImage(x: unknown): x is IBindableBuildImage {
21272109
return typeof x === 'object' && !!x && !!(x as any).bind;
2128-
}
2110+
}

0 commit comments

Comments
 (0)