From e2e1801d07c60422512d1407c00b16b0ef067674 Mon Sep 17 00:00:00 2001 From: Tarun Belani Date: Tue, 18 Nov 2025 20:23:26 -0800 Subject: [PATCH 1/6] feat(imagebuilder-alpha): add support for Image Recipe Construct --- .../@aws-cdk/aws-imagebuilder-alpha/README.md | 344 +++++++--- .../aws-imagebuilder-alpha/lib/base-image.ts | 61 ++ .../lib/image-recipe.ts | 435 ++++++++++++ .../aws-imagebuilder-alpha/lib/index.ts | 1 + .../aws-imagebuilder-alpha/lib/recipe-base.ts | 8 + .../test/base-image.test.ts | 48 +- .../test/image-recipe.test.ts | 479 ++++++++++++++ ...efaultTestDeployAssertFD6737FA.assets.json | 20 + ...aultTestDeployAssertFD6737FA.template.json | 36 + ...er-image-recipe-all-parameters.assets.json | 20 + ...-image-recipe-all-parameters.template.json | 153 +++++ .../cdk.out | 1 + .../integ.json | 13 + .../manifest.json | 615 +++++++++++++++++ .../tree.json | 1 + .../test/integ.all-parameters.image-recipe.ts | 101 +++ ...efaultTestDeployAssertFD6737FA.assets.json | 20 + ...aultTestDeployAssertFD6737FA.template.json | 36 + ...mage-recipe-default-parameters.assets.json | 20 + ...ge-recipe-default-parameters.template.json | 46 ++ .../cdk.out | 1 + .../integ.json | 13 + .../manifest.json | 618 ++++++++++++++++++ .../tree.json | 1 + .../integ.default-parameters.image-recipe.ts | 16 + ...efaultTestDeployAssertFD6737FA.assets.json | 20 + ...aultTestDeployAssertFD6737FA.template.json | 36 + ...-recipe-marketplace-base-image.assets.json | 20 + ...ecipe-marketplace-base-image.template.json | 46 ++ .../cdk.out | 1 + .../integ.json | 13 + .../manifest.json | 609 +++++++++++++++++ .../tree.json | 1 + ...teg.marketplace-base-image.image-recipe.ts | 14 + 34 files changed, 3791 insertions(+), 76 deletions(-) create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/README.md b/packages/@aws-cdk/aws-imagebuilder-alpha/README.md index 2e66f1422b64a..a37c946280b7d 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/README.md +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/README.md @@ -36,72 +36,76 @@ EC2 Image Builder supports AWS-managed components for common tasks, AWS Marketpl that you create. Components run during specific workflow phases: build and validate phases during the build stage, and test phase during the test stage. -### Container Recipe +### Image Recipe -A container recipe is similar to an image recipe but specifically for container images. It defines the base container -image and components applied to produce the desired configuration for the output container image. Container recipes work -with Docker images from DockerHub, Amazon ECR, or Amazon-managed container images as starting points. +#### Image Recipe Basic Usage -#### Container Recipe Basic Usage - -Create a container recipe with the required base image and target repository: +Create an image recipe with the required base image: ```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'MyContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') +const imageRecipe = new imagebuilder.ImageRecipe(this, 'MyImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64' ) }); ``` -#### Container Recipe Base Images +#### Image Recipe Base Images -##### DockerHub Images +To create a recipe, you have to select a base image to build and customize from. This base image can be referenced from +various sources, such as from SSM parameters, AWS Marketplace products, and AMI IDs directly. -Using public Docker Hub images: +##### SSM Parameters + +Using SSM parameter references: ```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'DockerHubContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') +const imageRecipe = new imagebuilder.ImageRecipe(this, 'SsmImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64' ) }); + +// Using an SSM parameter construct +const parameter = ssm.StringParameter.fromStringParameterName( + this, + 'BaseImageParameter', + '/aws/service/ami-windows-latest/Windows_Server-2022-English-Full-Base' +); +const windowsRecipe = new imagebuilder.ImageRecipe(this, 'WindowsImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameter(parameter) +}); ``` -##### ECR Images +##### AMI IDs -Using images from your own ECR repositories: +When you have a specific AMI to use: ```ts -const sourceRepo = ecr.Repository.fromRepositoryName(this, 'SourceRepo', 'my-base-image'); -const targetRepo = ecr.Repository.fromRepositoryName(this, 'TargetRepo', 'my-container-repo'); - -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromEcr(sourceRepo, '1.0.0'), - targetRepository: imagebuilder.Repository.fromEcr(targetRepo) +const imageRecipe = new imagebuilder.ImageRecipe(this, 'AmiImageRecipe', { + baseImage: imagebuilder.BaseImage.fromAmiId('ami-12345678') }); ``` -##### ECR Public Images +##### Marketplace Images -Using images from Amazon ECR Public: +For marketplace base images: ```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrPublicContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', '2023'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ) +const imageRecipe = new imagebuilder.ImageRecipe(this, 'MarketplaceImageRecipe', { + baseImage: imagebuilder.BaseImage.fromMarketplaceProductId('prod-1234567890abcdef0') }); ``` -#### Container Recipe Components +#### Image Recipe Components -##### Custom Components in Container Recipes +Components from various sources, such as custom-owned, AWS-owned, or AWS Marketplace-owned, can optionally be included +in recipes. For parameterized components, you are able to provide the parameters to use in the recipe, which will be +applied during the image build when executing components. -Add your own components to the container recipe: +##### Custom Components in Image Recipes + +Add your own components to the recipe: ```ts const customComponent = new imagebuilder.Component(this, 'MyComponent', { @@ -116,7 +120,7 @@ const customComponent = new imagebuilder.Component(this, 'MyComponent', { name: 'install-app', action: imagebuilder.ComponentAction.EXECUTE_BASH, inputs: { - commands: ['yum install -y my-container-application'] + commands: ['yum install -y my-application'] } } ] @@ -125,10 +129,9 @@ const customComponent = new imagebuilder.Component(this, 'MyComponent', { }) }); -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'ComponentContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') +const imageRecipe = new imagebuilder.ImageRecipe(this, 'ComponentImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64' ), components: [ { @@ -138,15 +141,14 @@ const containerRecipe = new imagebuilder.ContainerRecipe(this, 'ComponentContain }); ``` -##### AWS-Managed Components in Container Recipes +##### AWS-Managed Components in Image Recipes Use pre-built AWS components: ```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'AwsManagedContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') +const imageRecipe = new imagebuilder.ImageRecipe(this, 'AwsManagedImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64' ), components: [ { @@ -163,46 +165,48 @@ const containerRecipe = new imagebuilder.ContainerRecipe(this, 'AwsManagedContai }); ``` -#### Container Recipe Configuration +##### Component Parameters in Image Recipes -##### Custom Dockerfile - -Provide your own Dockerfile template: +Pass parameters to components that accept them: ```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'CustomDockerfileContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') +const parameterizedComponent = imagebuilder.Component.fromComponentName( + this, + 'ParameterizedComponent', + 'my-parameterized-component' +); + +const imageRecipe = new imagebuilder.ImageRecipe(this, 'ParameterizedImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64' ), - dockerfile: imagebuilder.DockerfileData.fromInline(` -FROM {{{ imagebuilder:parentImage }}} -CMD ["echo", "Hello, world!"] -{{{ imagebuilder:environments }}} -{{{ imagebuilder:components }}} -`) + components: [ + { + component: parameterizedComponent, + parameters: { + environment: imagebuilder.ComponentParameterValue.fromString('production'), + version: imagebuilder.ComponentParameterValue.fromString('1.0.0') + } + } + ] }); ``` -##### Instance Configuration +#### Image Recipe Configuration -Configure the build instance: +##### Block Device Configuration + +Configure storage for the build instance: ```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'InstanceConfigContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ), - // Custom ECS-optimized AMI for building - instanceImage: imagebuilder.ContainerInstanceImage.fromSsmParameterName( - '/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id' +const imageRecipe = new imagebuilder.ImageRecipe(this, 'BlockDeviceImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64' ), - // Additional storage for build process - instanceBlockDevices: [ + blockDevices: [ { - deviceName: '/dev/xvda', - volume: ec2.BlockDeviceVolume.ebs(50, { + deviceName: '/dev/sda1', + volume: ec2.BlockDeviceVolume.ebs(100, { encrypted: true, volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3 }) @@ -211,6 +215,23 @@ const containerRecipe = new imagebuilder.ContainerRecipe(this, 'InstanceConfigCo }); ``` +##### AMI Tagging + +Tag the output AMI: + +```ts +const imageRecipe = new imagebuilder.ImageRecipe(this, 'TaggedImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64' + ), + amiTags: { + Environment: 'Production', + Application: 'WebServer', + Owner: 'DevOps Team' + } +}); +``` + ### Component A component defines the sequence of steps required to customize an instance during image creation (build component) or @@ -455,6 +476,181 @@ const marketplaceComponent = imagebuilder.AwsMarketplaceComponent.fromAwsMarketp ); ``` +### Container Recipe + +A container recipe is similar to an image recipe but specifically for container images. It defines the base container +image and components applied to produce the desired configuration for the output container image. Container recipes work +with Docker images from DockerHub, Amazon ECR, or Amazon-managed container images as starting points. + +#### Container Recipe Basic Usage + +Create a container recipe with the required base image and target repository: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'MyContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ) +}); +``` + +#### Container Recipe Base Images + +##### DockerHub Images + +Using public Docker Hub images: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'DockerHubContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ) +}); +``` + +##### ECR Images + +Using images from your own ECR repositories: + +```ts +const sourceRepo = ecr.Repository.fromRepositoryName(this, 'SourceRepo', 'my-base-image'); +const targetRepo = ecr.Repository.fromRepositoryName(this, 'TargetRepo', 'my-container-repo'); + +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromEcr(sourceRepo, '1.0.0'), + targetRepository: imagebuilder.Repository.fromEcr(targetRepo) +}); +``` + +##### ECR Public Images + +Using images from Amazon ECR Public: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrPublicContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', '2023'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ) +}); +``` + +#### Container Recipe Components + +##### Custom Components in Container Recipes + +Add your own components to the container recipe: + +```ts +const customComponent = new imagebuilder.Component(this, 'MyComponent', { + platform: imagebuilder.Platform.LINUX, + data: imagebuilder.ComponentData.fromJsonObject({ + schemaVersion: imagebuilder.ComponentSchemaVersion.V1_0, + phases: [ + { + name: imagebuilder.ComponentPhaseName.BUILD, + steps: [ + { + name: 'install-app', + action: imagebuilder.ComponentAction.EXECUTE_BASH, + inputs: { + commands: ['yum install -y my-container-application'] + } + } + ] + } + ] + }) +}); + +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'ComponentContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + components: [ + { + component: customComponent + } + ] +}); +``` + +##### AWS-Managed Components in Container Recipes + +Use pre-built AWS components: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'AwsManagedContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + components: [ + { + component: imagebuilder.AwsManagedComponent.updateOS(this, 'UpdateOS', { + platform: imagebuilder.Platform.LINUX + }) + }, + { + component: imagebuilder.AwsManagedComponent.awsCliV2(this, 'AwsCli', { + platform: imagebuilder.Platform.LINUX + }) + } + ] +}); +``` + +#### Container Recipe Configuration + +##### Custom Dockerfile + +Provide your own Dockerfile template: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'CustomDockerfileContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + dockerfile: imagebuilder.DockerfileData.fromInline(` +FROM {{{ imagebuilder:parentImage }}} +CMD ["echo", "Hello, world!"] +{{{ imagebuilder:environments }}} +{{{ imagebuilder:components }}} +`) +}); +``` + +##### Instance Configuration + +Configure the build instance: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'InstanceConfigContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + // Custom ECS-optimized AMI for building + instanceImage: imagebuilder.ContainerInstanceImage.fromSsmParameterName( + '/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id' + ), + // Additional storage for build process + instanceBlockDevices: [ + { + deviceName: '/dev/xvda', + volume: ec2.BlockDeviceVolume.ebs(50, { + encrypted: true, + volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3 + }) + } + ] +}); +``` + ### Infrastructure Configuration Infrastructure configuration defines the compute resources and environment settings used during the image building diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts index c0992191ffc1f..64a622e664106 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts @@ -1,6 +1,66 @@ import * as ecr from 'aws-cdk-lib/aws-ecr'; import * as ssm from 'aws-cdk-lib/aws-ssm'; +/** + * Represents a base image that is used to start from in EC2 Image Builder image builds + */ +export class BaseImage { + /** + * The AMI ID to use as a base image in an image recipe + * + * @param amiId The AMI ID to use as the base image + */ + public static fromAmiId(amiId: string): BaseImage { + return new BaseImage(amiId); + } + + /** + * The marketplace product ID for an AMI product to use as the base image in an image recipe + * + * @param productId The Marketplace AMI product ID to use as the base image + */ + public static fromMarketplaceProductId(productId: string): BaseImage { + return new BaseImage(productId); + } + + /** + * The SSM parameter to use as the base image in an image recipe + * + * @param parameter The SSM parameter to use as the base image + */ + public static fromSsmParameter(parameter: ssm.IParameter): BaseImage { + return this.fromSsmParameterName(parameter.parameterArn); + } + + /** + * The parameter name for the SSM parameter to use as the base image in an image recipe + * + * @param parameterName The name of the SSM parameter to use as the base image + */ + public static fromSsmParameterName(parameterName: string): BaseImage { + return new BaseImage(`ssm:${parameterName}`); + } + + /** + * The direct string value of the base image to use in an image recipe. This can be an EC2 Image Builder image ARN, + * an SSM parameter, an AWS Marketplace product ID, or an AMI ID. + * + * @param baseImageString The base image as a direct string value + */ + public static fromString(baseImageString: string): BaseImage { + return new BaseImage(baseImageString); + } + + /** + * The rendered base image to use + **/ + public readonly image: string; + + protected constructor(image: string) { + this.image = image; + } +} + /** * Represents a base image that is used to start from in EC2 Image Builder image builds */ @@ -108,3 +168,4 @@ export class ContainerInstanceImage { this.image = image; } } + diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts new file mode 100644 index 0000000000000..a4d2ff9f7bc75 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts @@ -0,0 +1,435 @@ +import * as cdk from 'aws-cdk-lib'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import { CfnImageRecipe } from 'aws-cdk-lib/aws-imagebuilder'; +import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable'; +import { Construct } from 'constructs'; +import { BaseImage } from './base-image'; +import { ComponentConfiguration, IRecipeBase } from './recipe-base'; + +const IMAGE_RECIPE_SYMBOL = Symbol.for('@aws-cdk/aws-imagebuilder-alpha.ImageRecipe'); + +const LATEST_VERSION = 'x.x.x'; + +/** + * An EC2 Image Builder Image Recipe. + */ +export interface IImageRecipe extends IRecipeBase { + /** + * The ARN of the image recipe + * + * @attribute + */ + readonly imageRecipeArn: string; + + /** + * The name of the image recipe + * + * @attribute + */ + readonly imageRecipeName: string; + + /** + * The version of the image recipe + * + * @attribute + */ + readonly imageRecipeVersion: string; +} + +/** + * Properties for creating an Image Recipe resource + */ +export interface ImageRecipeProps { + /** + * The base image for customizations specified in the container recipe. + */ + readonly baseImage: BaseImage; + + /** + * The name of the image recipe. + * + * @default - a name is generated + */ + readonly imageRecipeName?: string; + + /** + * The version of the image recipe. + * + * @default 1.0.0 + */ + readonly imageRecipeVersion?: string; + + /** + * The description of the image recipe. + * + * @default None + */ + readonly description?: string; + + /** + * The list of component configurations to apply in the image build. + * + * @default None + */ + readonly components?: ComponentConfiguration[]; + + /** + * The additional tags to assign to the output AMI generated by the build. + * + * @default None + */ + readonly amiTags?: { [key: string]: string }; + + /** + * The block devices to attach to the instance used for building the image. + * + * @default None + */ + readonly blockDevices?: ec2.BlockDevice[]; + + /** + * The working directory for use during build and test workflows. + * + * @default - the Image Builder default working directory is used. For Linux and macOS builds, this would be /tmp. For + * Windows builds, this would be C:/ + */ + readonly workingDirectory?: string; + + /** + * Whether to uninstall the Systems Manager agent from your final build image, prior to creating the new AMI. + * + * @default - this is false if the Systems Manager agent is pre-installed on the base image. Otherwise, this is true. + */ + readonly uninstallSsmAgentAfterBuild?: boolean; + + /** + * The user data commands to pass to Image Builder build and test EC2 instances. For Linux and macOS, Image Builder + * uses a default user data script to install the Systems Manager agent. If you override the user data, you must + * ensure to add commands to install Systems Manager agent, if it is not pre-installed on your base image. + * + * @default None + */ + readonly userDataOverride?: ec2.UserData; + + /** + * The tags to apply to the image recipe + * + * @default None + */ + readonly tags?: { [key: string]: string }; +} + +/** + * Properties for an EC2 Image Builder image recipe + */ +export interface ImageRecipeAttributes { + /** + * The ARN of the image recipe + * + * @default - the ARN is automatically constructed if an imageRecipeName is provided, otherwise an + * imageRecipeName is required + */ + readonly imageRecipeArn?: string; + + /** + * The name of the image recipe + * + * @default - the name is automatically constructed if an imageRecipeArn is provided, otherwise an imageRecipeName is + * required + */ + readonly imageRecipeName?: string; + + /** + * The version of the image recipe + * + * @default - the version is automatically constructed if an imageRecipeArn is provided, otherwise the latest version + * is used. + */ + readonly imageRecipeVersion?: string; +} + +/** + * A new or imported Image Recipe + */ +abstract class ImageRecipeBase extends cdk.Resource implements IImageRecipe { + /** + * The ARN of the image recipe + */ + abstract readonly imageRecipeArn: string; + + /** + * The name of the image recipe + */ + abstract readonly imageRecipeName: string; + + /** + * The version of the image recipe + */ + abstract readonly imageRecipeVersion: string; + + /** + * Grant custom actions to the given grantee for the image recipe + * + * @param grantee The principal + * @param actions The list of actions + */ + public grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant { + return iam.Grant.addToPrincipal({ + grantee, + actions, + resourceArns: [this.imageRecipeArn], + scope: this, + }); + } + + /** + * Grant read permissions to the given grantee for the image recipe + * + * @param grantee The principal + */ + public grantRead(grantee: iam.IGrantable): iam.Grant { + return this.grant(grantee, 'imagebuilder:GetImageRecipe'); + } + + /** + * Indicates whether the recipe is an Image Recipe + * + * @internal + */ + public _isImageRecipe(): this is IImageRecipe { + return true; + } +} + +/** + * Represents an EC2 Image Builder Image Recipe. + * + * @see https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html + */ +@propertyInjectable +export class ImageRecipe extends ImageRecipeBase { + /** Uniquely identifies this class. */ + public static readonly PROPERTY_INJECTION_ID: string = '@aws-cdk.aws-imagebuilder-alpha.ImageRecipe'; + + /** + * Import an existing image recipe given its ARN. + */ + public static fromImageRecipeArn(scope: Construct, id: string, imageRecipeArn: string): IImageRecipe { + return this.fromImageRecipeAttributes(scope, id, { imageRecipeArn }); + } + + /** + * Import the latest version of an existing image recipe given its name. The provided name must be normalized by + * converting all alphabetical characters to lowercase, and replacing all spaces and underscores with hyphens. + */ + public static fromImageRecipeName(scope: Construct, id: string, imageRecipeName: string): IImageRecipe { + return this.fromImageRecipeAttributes(scope, id, { imageRecipeName }); + } + + /** + * Import an existing image recipe by providing its attributes. If the image recipe name is provided as an attribute, + * it must be normalized by converting all alphabetical characters to lowercase, and replacing all spaces and + * underscores with hyphens. + */ + public static fromImageRecipeAttributes(scope: Construct, id: string, attrs: ImageRecipeAttributes): IImageRecipe { + if (attrs.imageRecipeArn && (attrs.imageRecipeName || attrs.imageRecipeVersion)) { + throw new cdk.ValidationError( + 'an imageRecipeName and imageRecipeVersion cannot be provided when an imageRecipeArn is provided', + scope, + ); + } + + if (!attrs.imageRecipeArn && !attrs.imageRecipeName) { + throw new cdk.ValidationError('either imageRecipeArn or imageRecipeName is required', scope); + } + + const imageRecipeArn = + attrs.imageRecipeArn ?? + cdk.Stack.of(scope).formatArn({ + service: 'imagebuilder', + resource: 'image-recipe', + resourceName: `${attrs.imageRecipeName}/${attrs.imageRecipeVersion ?? LATEST_VERSION}`, + }); + + const [imageRecipeName, imageRecipeVersion] = (() => { + if (attrs.imageRecipeName) { + return [attrs.imageRecipeName, attrs.imageRecipeVersion ?? LATEST_VERSION]; + } + + const imageRecipeNameVersion = cdk.Stack.of(scope).splitArn( + imageRecipeArn, + cdk.ArnFormat.SLASH_RESOURCE_NAME, + ).resourceName!; + + const imageRecipeNameVersionSplit = cdk.Fn.split('/', imageRecipeNameVersion); + return [cdk.Fn.select(0, imageRecipeNameVersionSplit), cdk.Fn.select(1, imageRecipeNameVersionSplit)]; + })(); + + class Import extends ImageRecipeBase { + public readonly imageRecipeArn = imageRecipeArn; + public readonly imageRecipeName = imageRecipeName; + public readonly imageRecipeVersion = imageRecipeVersion; + } + + return new Import(scope, id); + } + + /** + * Return whether the given object is an ImageRecipe. + */ + public static isImageRecipe(x: any): x is ImageRecipe { + return x !== null && typeof x === 'object' && IMAGE_RECIPE_SYMBOL in x; + } + + /** + * The ARN of the image recipe + */ + public readonly imageRecipeArn: string; + + /** + * The name of the image recipe + */ + public readonly imageRecipeName: string; + + /** + * The version of the image recipe + */ + public readonly imageRecipeVersion: string; + + private readonly blockDevices: ec2.BlockDevice[] = []; + + public constructor(scope: Construct, id: string, props: ImageRecipeProps) { + super(scope, id, { + physicalName: + props.imageRecipeName ?? + cdk.Lazy.string({ + produce: () => + cdk.Names.uniqueResourceName(this, { + maxLength: 128, + separator: '-', + allowedSpecialCharacters: '-', + }).toLowerCase(), // Enforce lowercase for the auto-generated fallback + }), + }); + + Object.defineProperty(this, IMAGE_RECIPE_SYMBOL, { value: true }); + + this.validateImageRecipeName(); + + this.addBlockDevices(...(props.blockDevices ?? [])); + + const components: CfnImageRecipe.ComponentConfigurationProperty[] | undefined = props.components?.map( + (component) => ({ + componentArn: component.component.componentArn, + ...(Object.keys(component.parameters ?? {}).length && { + parameters: Object.entries(component.parameters!).map( + ([key, value]): CfnImageRecipe.ComponentParameterProperty => ({ name: key, value: value.value }), + ), + }), + }), + ); + + const imageRecipeVersion = props.imageRecipeVersion ?? '1.0.0'; + const imageRecipe = new CfnImageRecipe(this, 'Resource', { + name: this.physicalName, + version: imageRecipeVersion, + description: props.description, + parentImage: props.baseImage.image, + blockDeviceMappings: cdk.Lazy.any({ produce: () => this.renderBlockDevices() }), + workingDirectory: props.workingDirectory, + additionalInstanceConfiguration: this.buildAdditionalInstanceConfiguration(props), + amiTags: props.amiTags, + tags: props.tags, + ...(components?.length && { components }), + }); + + this.imageRecipeName = this.getResourceNameAttribute(imageRecipe.attrName); + this.imageRecipeArn = this.getResourceArnAttribute(imageRecipe.attrArn, { + service: 'imagebuilder', + resource: 'image-recipe', + resourceName: `${this.physicalName}/${imageRecipeVersion}`, + }); + this.imageRecipeVersion = imageRecipe.getAtt('Version').toString(); + } + + /** + * Adds block devices to attach to the instance used for building the image. + * + * @param blockDevices The list of block devices to attach + */ + public addBlockDevices(...blockDevices: ec2.BlockDevice[]): void { + this.blockDevices.push(...blockDevices); + } + + private renderBlockDevices(): CfnImageRecipe.InstanceBlockDeviceMappingProperty[] | undefined { + const blockDevices = this.blockDevices.map((blockDevice): CfnImageRecipe.InstanceBlockDeviceMappingProperty => { + const ebsDevice = blockDevice.volume.ebsDevice; + const ebs: CfnImageRecipe.EbsInstanceBlockDeviceSpecificationProperty = { + ...(ebsDevice?.deleteOnTermination !== undefined && { deleteOnTermination: ebsDevice.deleteOnTermination }), + ...(ebsDevice?.encrypted !== undefined && { encrypted: ebsDevice.encrypted }), + ...(ebsDevice?.iops !== undefined && { iops: ebsDevice.iops }), + ...(ebsDevice?.kmsKey !== undefined && { kmsKeyId: ebsDevice.kmsKey.keyArn }), + ...(ebsDevice?.snapshotId !== undefined && { snapshotId: ebsDevice.snapshotId }), + ...(ebsDevice?.throughput !== undefined && { throughput: ebsDevice.throughput }), + ...(ebsDevice?.volumeSize !== undefined && { volumeSize: ebsDevice.volumeSize }), + ...(ebsDevice?.volumeType !== undefined && { volumeType: ebsDevice.volumeType }), + }; + + const mappingEnabled = blockDevice.mappingEnabled ?? true; + return { + deviceName: blockDevice.deviceName, + virtualName: blockDevice.volume.virtualName, + ...(!mappingEnabled && { noDevice: '' }), + ...(Object.keys(ebs).length && { ebs }), + }; + }); + + return blockDevices.length ? blockDevices : undefined; + } + + private buildAdditionalInstanceConfiguration( + props: ImageRecipeProps, + ): CfnImageRecipe.AdditionalInstanceConfigurationProperty | undefined { + const systemsManagerAgent: CfnImageRecipe.SystemsManagerAgentProperty = { + ...(props.uninstallSsmAgentAfterBuild !== undefined && { + uninstallAfterBuild: props.uninstallSsmAgentAfterBuild, + }), + }; + + const additionalInstanceConfiguration: CfnImageRecipe.AdditionalInstanceConfigurationProperty = { + ...(Object.keys(systemsManagerAgent).length && { systemsManagerAgent }), + ...(props.userDataOverride !== undefined && { userDataOverride: cdk.Fn.base64(props.userDataOverride.render()) }), + }; + + return Object.keys(additionalInstanceConfiguration).length ? additionalInstanceConfiguration : undefined; + } + + private validateImageRecipeName() { + if (cdk.Token.isUnresolved(this.physicalName)) { + return; // Cannot validate unresolved tokens, given their actual value is rendered at deployment time + } + + if (this.physicalName.length > 128) { + throw new cdk.ValidationError( + `the imageRecipeName cannot be longer than 128 characters, got: '${this.physicalName}'`, + this, + ); + } + + if (this.physicalName.includes(' ')) { + throw new cdk.ValidationError(`the imageRecipeName cannot contain spaces, got: '${this.physicalName}'`, this); + } + + if (this.physicalName.includes('_')) { + throw new cdk.ValidationError( + `the imageRecipeName cannot contain underscores, got: '${this.physicalName}'`, + this, + ); + } + + if (this.physicalName !== this.physicalName.toLowerCase()) { + throw new cdk.ValidationError(`the imageRecipeName must be lowercase, got: '${this.physicalName}'`, this); + } + } +} diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts index 1bca16e8ef708..c8fbd4310b0b1 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts @@ -3,6 +3,7 @@ export * from './component'; export * from './container-recipe'; export * from './distribution-configuration'; +export * from './image-recipe'; export * from './infrastructure-configuration'; export * from './base-image'; diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts index 866cb3edf75e7..17df99a4e0ff6 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts @@ -2,6 +2,7 @@ import * as cdk from 'aws-cdk-lib'; import * as iam from 'aws-cdk-lib/aws-iam'; import { IComponent } from './component'; import { IContainerRecipe } from './container-recipe'; +import { IImageRecipe } from './image-recipe'; /** * The parameter value for a component parameter @@ -69,4 +70,11 @@ export interface IRecipeBase extends cdk.IResource { * @internal */ _isContainerRecipe(): this is IContainerRecipe; + + /** + * Indicates whether the recipe is an Image Recipe + * + * @internal + */ + _isImageRecipe(): this is IImageRecipe; } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts index 44ac6269ddf8e..58cfba25f490a 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts @@ -1,7 +1,51 @@ import * as cdk from 'aws-cdk-lib'; -import * as ecr from 'aws-cdk-lib/aws-ecr'; import * as ssm from 'aws-cdk-lib/aws-ssm'; -import { BaseContainerImage, ContainerInstanceImage } from '../lib'; +import { BaseContainerImage, BaseImage, ContainerInstanceImage } from '../lib'; + +describe('Base Image', () => { + let app: cdk.App; + let stack: cdk.Stack; + + beforeEach(() => { + app = new cdk.App(); + stack = new cdk.Stack(app, 'Stack', { env: { region: 'us-east-1', account: '123456789012' } }); + }); + + test('should return the correct base image for an AMI ID', () => { + const baseImage = BaseImage.fromAmiId('ami-12345678'); + expect(baseImage.image).toEqual('ami-12345678'); + }); + + test('should return the correct base image for a marketplace product ID', () => { + const baseImage = BaseImage.fromMarketplaceProductId('prod-1234'); + expect(baseImage.image).toEqual('prod-1234'); + }); + + test('should return the correct base image for an SSM parameter', () => { + const baseImage = BaseImage.fromSsmParameter( + ssm.StringParameter.fromStringParameterAttributes(stack, 'Parameter', { + parameterName: '/imagebuilder/ami', + forceDynamicReference: true, + }), + ); + expect(stack.resolve(baseImage.image)).toEqual({ + 'Fn::Join': [ + '', + ['ssm:arn:', { Ref: 'AWS::Partition' }, ':ssm:us-east-1:123456789012:parameter/imagebuilder/ami'], + ], + }); + }); + + test('should return the correct base image for an SSM parameter name', () => { + const baseImage = BaseImage.fromSsmParameterName('/imagebuilder/ami'); + expect(baseImage.image).toEqual('ssm:/imagebuilder/ami'); + }); + + test('should return the correct base image for a generic string', () => { + const baseImage = BaseImage.fromString('base-image'); + expect(baseImage.image).toEqual('base-image'); + }); +}); describe('Base Container Image', () => { let app: cdk.App; diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts new file mode 100644 index 0000000000000..d639cbd3f3e97 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts @@ -0,0 +1,479 @@ +import * as cdk from 'aws-cdk-lib'; +import { Match, Template } from 'aws-cdk-lib/assertions'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import { + AwsManagedComponent, + BaseImage, + Component, + ComponentParameterValue, + ImageRecipe, + IRecipeBase, + Platform, +} from '../lib'; + +describe('Image Recipe', () => { + let app: cdk.App; + let stack: cdk.Stack; + + beforeEach(() => { + app = new cdk.App(); + stack = new cdk.Stack(app, 'Stack', { env: { region: 'us-east-1', account: '123456789012' } }); + }); + + test('imported by name', () => { + const imageRecipe = ImageRecipe.fromImageRecipeName(stack, 'ImageRecipe', 'imported-image-recipe-by-name'); + + expect(stack.resolve(imageRecipe.imageRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:123456789012:image-recipe/imported-image-recipe-by-name/x.x.x', + ], + ], + }); + expect(imageRecipe.imageRecipeName).toEqual('imported-image-recipe-by-name'); + expect(imageRecipe.imageRecipeVersion).toEqual('x.x.x'); + expect((imageRecipe as IRecipeBase)._isImageRecipe()).toBeTruthy(); + }); + + test('imported by name as an unresolved token', () => { + const imageRecipe = ImageRecipe.fromImageRecipeName(stack, 'ImageRecipe', `test-image-recipe-${stack.partition}`); + + expect(stack.resolve(imageRecipe.imageRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:123456789012:image-recipe/test-image-recipe-', + { Ref: 'AWS::Partition' }, + '/x.x.x', + ], + ], + }); + expect(stack.resolve(imageRecipe.imageRecipeName)).toEqual({ + 'Fn::Join': ['', ['test-image-recipe-', { Ref: 'AWS::Partition' }]], + }); + expect(imageRecipe.imageRecipeVersion).toEqual('x.x.x'); + }); + + test('imported by arn', () => { + const imageRecipe = ImageRecipe.fromImageRecipeArn( + stack, + 'ImageRecipe', + 'arn:aws:imagebuilder:us-east-1:123456789012:image-recipe/imported-image-recipe-by-arn/1.2.3', + ); + + expect(stack.resolve(imageRecipe.imageRecipeArn)).toEqual( + 'arn:aws:imagebuilder:us-east-1:123456789012:image-recipe/imported-image-recipe-by-arn/1.2.3', + ); + expect(imageRecipe.imageRecipeName).toEqual('imported-image-recipe-by-arn'); + expect(imageRecipe.imageRecipeVersion).toEqual('1.2.3'); + }); + + test('imported by arn as an unresolved token', () => { + const imageRecipe = ImageRecipe.fromImageRecipeArn( + stack, + 'ImageRecipe', + `arn:aws:imagebuilder:us-east-1:123456789012:image-recipe/test-image-recipe-${stack.partition}/1.2.3`, + ); + + expect(stack.resolve(imageRecipe.imageRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:aws:imagebuilder:us-east-1:123456789012:image-recipe/test-image-recipe-', + { Ref: 'AWS::Partition' }, + '/1.2.3', + ], + ], + }); + expect(stack.resolve(imageRecipe.imageRecipeName)).toEqual({ + 'Fn::Select': [ + 0, + { + 'Fn::Split': ['/', { 'Fn::Join': ['', ['test-image-recipe-', { Ref: 'AWS::Partition' }, '/1.2.3']] }], + }, + ], + }); + expect(stack.resolve(imageRecipe.imageRecipeVersion)).toEqual({ + 'Fn::Select': [ + 1, + { + 'Fn::Split': ['/', { 'Fn::Join': ['', ['test-image-recipe-', { Ref: 'AWS::Partition' }, '/1.2.3']] }], + }, + ], + }); + }); + + test('imported by attributes', () => { + const imageRecipe = ImageRecipe.fromImageRecipeAttributes(stack, 'ImageRecipe', { + imageRecipeName: 'imported-image-recipe-by-attributes', + imageRecipeVersion: '1.2.3', + }); + + expect(stack.resolve(imageRecipe.imageRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:123456789012:image-recipe/imported-image-recipe-by-attributes/1.2.3', + ], + ], + }); + expect(imageRecipe.imageRecipeName).toEqual('imported-image-recipe-by-attributes'); + expect(imageRecipe.imageRecipeVersion).toEqual('1.2.3'); + }); + + test('with all parameters', () => { + const userData = ec2.UserData.forLinux(); + userData.addCommands('echo "Hello World"'); + + const imageRecipe = new ImageRecipe(stack, 'ImageRecipe', { + imageRecipeName: 'test-image-recipe', + imageRecipeVersion: '1.2.3', + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + description: 'A test image recipe', + components: [ + { + component: Component.fromComponentAttributes(stack, 'Component1', { + componentName: 'component-1', + componentVersion: '1.2.3', + }), + }, + { component: AwsManagedComponent.helloWorld(stack, 'Component2', { platform: Platform.LINUX }) }, + { + component: Component.fromComponentArn( + stack, + 'Component3', + 'arn:aws:imagebuilder:us-east-1:123456789012:component/parameterized-component/1.2.3/4', + ), + parameters: { + parameter1: ComponentParameterValue.fromString('parameter-value-1'), + parameter2: ComponentParameterValue.fromString('parameter-value-2'), + }, + }, + ], + amiTags: { + imageTag1: 'imageValue1', + imageTag2: 'imageValue2', + }, + workingDirectory: '/var/tmp', + uninstallSsmAgentAfterBuild: true, + userDataOverride: userData, + blockDevices: [ + { + mappingEnabled: false, + deviceName: '/dev/sda1', + volume: ec2.BlockDeviceVolume.ephemeral(0), + }, + ], + tags: { + key1: 'value1', + key2: 'value2', + }, + }); + + imageRecipe.addBlockDevices( + { + deviceName: '/dev/sda2', + volume: ec2.BlockDeviceVolume.ebs(75, { + encrypted: true, + kmsKey: kms.Alias.fromAliasName(stack, 'DeviceKey', 'alias/device-encryption-key'), + deleteOnTermination: true, + iops: 1000, + volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3, + throughput: 125, + }), + }, + { + deviceName: '/dev/sda3', + volume: ec2.BlockDeviceVolume.ebsFromSnapshot('snapshot-id', { + volumeSize: 75, + deleteOnTermination: true, + iops: 1000, + volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3, + throughput: 125, + }), + }, + ); + + expect(ImageRecipe.isImageRecipe(imageRecipe as unknown)).toBeTruthy(); + expect(ImageRecipe.isImageRecipe('ImageRecipe')).toBeFalsy(); + expect((imageRecipe as IRecipeBase)._isImageRecipe()).toBeTruthy(); + + Template.fromStack(stack).templateMatches({ + Resources: { + ImageRecipe8C789631: Match.objectEquals({ + Type: 'AWS::ImageBuilder::ImageRecipe', + Properties: { + AdditionalInstanceConfiguration: { + SystemsManagerAgent: { UninstallAfterBuild: true }, + UserDataOverride: { 'Fn::Base64': '#!/bin/bash\necho "Hello World"' }, + }, + AmiTags: { imageTag1: 'imageValue1', imageTag2: 'imageValue2' }, + BlockDeviceMappings: [ + { DeviceName: '/dev/sda1', NoDevice: '', VirtualName: 'ephemeral0' }, + { + DeviceName: '/dev/sda2', + Ebs: { + DeleteOnTermination: true, + Encrypted: true, + Iops: 1000, + KmsKeyId: { + 'Fn::Join': [ + '', + ['arn:', { Ref: 'AWS::Partition' }, ':kms:us-east-1:123456789012:alias/device-encryption-key'], + ], + }, + Throughput: 125, + VolumeSize: 75, + VolumeType: 'gp3', + }, + }, + { + DeviceName: '/dev/sda3', + Ebs: { + DeleteOnTermination: true, + SnapshotId: 'snapshot-id', + Iops: 1000, + Throughput: 125, + VolumeSize: 75, + VolumeType: 'gp3', + }, + }, + ], + Components: [ + { + ComponentArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:123456789012:component/component-1/1.2.3', + ], + ], + }, + }, + { + ComponentArn: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:aws:component/hello-world-linux/x.x.x', + ], + ], + }, + }, + { + ComponentArn: 'arn:aws:imagebuilder:us-east-1:123456789012:component/parameterized-component/1.2.3/4', + Parameters: [ + { Name: 'parameter1', Value: ['parameter-value-1'] }, + { Name: 'parameter2', Value: ['parameter-value-2'] }, + ], + }, + ], + Description: 'A test image recipe', + Name: 'test-image-recipe', + ParentImage: 'ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + Tags: { key1: 'value1', key2: 'value2' }, + Version: '1.2.3', + WorkingDirectory: '/var/tmp', + }, + }), + }, + }); + }); + + test('with required parameters', () => { + new ImageRecipe(stack, 'ImageRecipe', { + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + }); + + Template.fromStack(stack).templateMatches({ + Resources: { + ImageRecipe8C789631: Match.objectEquals({ + Type: 'AWS::ImageBuilder::ImageRecipe', + Properties: { + Name: 'stack-imagerecipe-1e832b66', + Version: '1.0.0', + ParentImage: 'ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + }, + }), + }, + }); + }); + + test('grants read access to IAM roles', () => { + const imageRecipe = new ImageRecipe(stack, 'ImageRecipe', { + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + }); + + const role = new iam.Role(stack, 'Role', { assumedBy: new iam.AccountPrincipal('123456789012') }); + + imageRecipe.grantRead(role); + + const template = Template.fromStack(stack); + + template.resourceCountIs('AWS::IAM::Policy', 1); + template.resourceCountIs('AWS::IAM::Role', 1); + template.resourceCountIs('AWS::ImageBuilder::ImageRecipe', 1); + expect(Object.keys(template.toJSON().Resources)).toHaveLength(3); + + template.hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + AWS: { + 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::123456789012:root']], + }, + }, + }, + ], + }, + }); + + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Effect: 'Allow', + Action: 'imagebuilder:GetImageRecipe', + Resource: { + 'Fn::GetAtt': ['ImageRecipe8C789631', 'Arn'], + }, + }, + ], + }, + Roles: [Match.anyValue()], + }); + }); + + test('grants permissions to IAM roles', () => { + const imageRecipe = new ImageRecipe(stack, 'ImageRecipe', { + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + }); + + const role = new iam.Role(stack, 'Role', { assumedBy: new iam.AccountPrincipal('123456789012') }); + + imageRecipe.grant(role, 'imagebuilder:DeleteImageRecipe'); + + const template = Template.fromStack(stack); + + template.resourceCountIs('AWS::IAM::Policy', 1); + template.resourceCountIs('AWS::IAM::Role', 1); + template.resourceCountIs('AWS::ImageBuilder::ImageRecipe', 1); + expect(Object.keys(template.toJSON().Resources)).toHaveLength(3); + + template.hasResourceProperties('AWS::IAM::Role', { + AssumeRolePolicyDocument: { + Statement: [ + { + Action: 'sts:AssumeRole', + Effect: 'Allow', + Principal: { + AWS: { + 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':iam::123456789012:root']], + }, + }, + }, + ], + }, + }); + + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: [ + { + Effect: 'Allow', + Action: 'imagebuilder:DeleteImageRecipe', + Resource: { + 'Fn::GetAtt': ['ImageRecipe8C789631', 'Arn'], + }, + }, + ], + }, + Roles: [Match.anyValue()], + }); + }); + + test('throws a validation error when an imageRecipeArn and imageRecipeName are provided when importing by attributes', () => { + expect(() => + ImageRecipe.fromImageRecipeAttributes(stack, 'ImageRecipe', { + imageRecipeArn: 'arn:aws:imagebuilder:us-east-1:123456789012:image-recipe/imported-image-recipe/x.x.x', + imageRecipeName: 'imported-image-recipe', + }), + ).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when neither an imageRecipeArn or imageRecipeName are provided when importing by attributes', () => { + expect(() => ImageRecipe.fromImageRecipeAttributes(stack, 'ImageRecipe', {})).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when the resource name is too long', () => { + expect( + () => + new ImageRecipe(stack, 'ImageRecipe', { + imageRecipeName: 'a'.repeat(129), + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + }), + ).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when the resource name contains spaces', () => { + expect( + () => + new ImageRecipe(stack, 'ImageRecipe', { + imageRecipeName: 'test recipe', + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + }), + ).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when the resource name contains underscores', () => { + expect( + () => + new ImageRecipe(stack, 'ImageRecipe', { + imageRecipeName: 'test_recipe', + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + }), + ).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when the resource name contains uppercase characters', () => { + expect( + () => + new ImageRecipe(stack, 'ImageRecipe', { + imageRecipeName: 'TestRecipe', + baseImage: BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + }), + ).toThrow(cdk.ValidationError); + }); +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json new file mode 100644 index 0000000000000..de53e99c78fe9 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA Template", + "source": { + "path": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d8d86b35": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json new file mode 100644 index 0000000000000..3b2f2689a9cd5 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "1d83592873b042fee5e5aa6ccd858869b17e2af204bdeabd4b36b9aab6ba42ab": { + "displayName": "aws-cdk-imagebuilder-image-recipe-all-parameters Template", + "source": { + "path": "aws-cdk-imagebuilder-image-recipe-all-parameters.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-4de35eda": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "1d83592873b042fee5e5aa6ccd858869b17e2af204bdeabd4b36b9aab6ba42ab.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json new file mode 100644 index 0000000000000..e5e93ae647a29 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json @@ -0,0 +1,153 @@ +{ + "Resources": { + "ParameterizedComponentD29478CA": { + "Type": "AWS::ImageBuilder::Component", + "Properties": { + "Data": "name: ParameterizedComponent\ndescription: This is a parameterized component\nschemaVersion: \"1.0\"\nparameters:\n - parameter1:\n type: string\n description: This is the first parameter\n - parameter2:\n type: string\n description: This is the second parameter\nphases:\n - name: build\n steps:\n - name: step1\n action: ExecuteBash\n inputs:\n commands:\n - echo ${{ parameter1 }}\n - echo ${{ parameter2 }}\n", + "Name": "aws-cdk-imagebuilder-image-recipe-all-parameters-parameterizedcomponent-abcc0eb5", + "Platform": "Linux", + "Version": "1.0.0" + } + }, + "ImageRecipe8C789631": { + "Type": "AWS::ImageBuilder::ImageRecipe", + "Properties": { + "AdditionalInstanceConfiguration": { + "SystemsManagerAgent": { + "UninstallAfterBuild": true + }, + "UserDataOverride": { + "Fn::Base64": "#!/bin/bash\necho \"Hello World\"" + } + }, + "AmiTags": { + "imageTag1": "imageValue1", + "imageTag2": "imageValue2" + }, + "BlockDeviceMappings": [ + { + "DeviceName": "/dev/sda1", + "NoDevice": "", + "VirtualName": "ephemeral0" + }, + { + "DeviceName": "/dev/sda2", + "Ebs": { + "DeleteOnTermination": true, + "Encrypted": true, + "Iops": 1000, + "KmsKeyId": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":kms:", + { + "Ref": "AWS::Region" + }, + ":", + { + "Ref": "AWS::AccountId" + }, + ":alias/device-encryption-key" + ] + ] + }, + "Throughput": 125, + "VolumeSize": 75, + "VolumeType": "gp3" + } + } + ], + "Components": [ + { + "ComponentArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":imagebuilder:", + { + "Ref": "AWS::Region" + }, + ":aws:component/hello-world-linux/x.x.x" + ] + ] + } + }, + { + "ComponentArn": { + "Fn::GetAtt": [ + "ParameterizedComponentD29478CA", + "Arn" + ] + }, + "Parameters": [ + { + "Name": "parameter1", + "Value": [ + "parameter-value-1" + ] + }, + { + "Name": "parameter2", + "Value": [ + "parameter-value-2" + ] + } + ] + } + ], + "Description": "A test image recipe", + "Name": "test-image-recipe", + "ParentImage": "ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64", + "Tags": { + "key1": "value1", + "key2": "value2" + }, + "Version": "1.2.3", + "WorkingDirectory": "/var/tmp" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/cdk.out b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/integ.json new file mode 100644 index 0000000000000..2aa5c6f6571e8 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "ImageRecipeTest/DefaultTest": { + "stacks": [ + "aws-cdk-imagebuilder-image-recipe-all-parameters" + ], + "assertionStack": "ImageRecipeTest/DefaultTest/DeployAssert", + "assertionStackName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json new file mode 100644 index 0000000000000..78c6c98399f30 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json @@ -0,0 +1,615 @@ +{ + "version": "48.0.0", + "artifacts": { + "aws-cdk-imagebuilder-image-recipe-all-parameters.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-imagebuilder-image-recipe-all-parameters": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-imagebuilder-image-recipe-all-parameters.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/1d83592873b042fee5e5aa6ccd858869b17e2af204bdeabd4b36b9aab6ba42ab.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-imagebuilder-image-recipe-all-parameters.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-imagebuilder-image-recipe-all-parameters.assets" + ], + "metadata": { + "/aws-cdk-imagebuilder-image-recipe-all-parameters/ParameterizedComponent/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ParameterizedComponentD29478CA" + } + ], + "/aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipe/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipe8C789631" + } + ], + "/aws-cdk-imagebuilder-image-recipe-all-parameters/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-imagebuilder-image-recipe-all-parameters/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-imagebuilder-image-recipe-all-parameters" + }, + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ImageRecipeTestDefaultTestDeployAssertFD6737FA": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + ], + "metadata": { + "/ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ImageRecipeTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "userValue": true, + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "userValue": true, + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + }, + "@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault": { + "recommendedValue": true, + "explanation": "When enabled, Network Load Balancer will be created with a security group by default." + }, + "@aws-cdk/aws-stepfunctions-tasks:httpInvokeDynamicJsonPathEndpoint": { + "recommendedValue": true, + "explanation": "When enabled, allows using a dynamic apiEndpoint with JSONPath format in HttpInvoke tasks.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:uniqueTargetGroupId": { + "recommendedValue": true, + "explanation": "When enabled, ECS patterns will generate unique target group IDs to prevent conflicts during load balancer replacement" + } + } + } + } + }, + "minimumCliVersion": "2.1031.2" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json new file mode 100644 index 0000000000000..d01bac23a4b5b --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-all-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-all-parameters","path":"aws-cdk-imagebuilder-image-recipe-all-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ParameterizedComponent":{"id":"ParameterizedComponent","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ParameterizedComponent","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.Component","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ParameterizedComponent/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnComponent","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::Component","aws:cdk:cloudformation:props":{"data":"name: ParameterizedComponent\ndescription: This is a parameterized component\nschemaVersion: \"1.0\"\nparameters:\n - parameter1:\n type: string\n description: This is the first parameter\n - parameter2:\n type: string\n description: This is the second parameter\nphases:\n - name: build\n steps:\n - name: step1\n action: ExecuteBash\n inputs:\n commands:\n - echo ${{ parameter1 }}\n - echo ${{ parameter2 }}\n","name":"aws-cdk-imagebuilder-image-recipe-all-parameters-parameterizedcomponent-abcc0eb5","platform":"Linux","version":"1.0.0"}}}}},"Component2":{"id":"Component2","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/Component2","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"additionalInstanceConfiguration":{"systemsManagerAgent":{"uninstallAfterBuild":true},"userDataOverride":{"Fn::Base64":"#!/bin/bash\necho \"Hello World\""}},"amiTags":{"imageTag1":"imageValue1","imageTag2":"imageValue2"},"blockDeviceMappings":[{"deviceName":"/dev/sda1","virtualName":"ephemeral0","noDevice":""},{"deviceName":"/dev/sda2","ebs":{"deleteOnTermination":true,"encrypted":true,"iops":1000,"kmsKeyId":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":kms:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":alias/device-encryption-key"]]},"throughput":125,"volumeSize":75,"volumeType":"gp3"}}],"components":[{"componentArn":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":imagebuilder:",{"Ref":"AWS::Region"},":aws:component/hello-world-linux/x.x.x"]]}},{"componentArn":{"Fn::GetAtt":["ParameterizedComponentD29478CA","Arn"]},"parameters":[{"name":"parameter1","value":["parameter-value-1"]},{"name":"parameter2","value":["parameter-value-2"]}]}],"description":"A test image recipe","name":"test-image-recipe","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","tags":{"key1":"value1","key2":"value2"},"version":"1.2.3","workingDirectory":"/var/tmp"}}}}},"DeviceKey":{"id":"DeviceKey","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/DeviceKey","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts new file mode 100644 index 0000000000000..79f5a90333b0f --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts @@ -0,0 +1,101 @@ +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as ec2 from 'aws-cdk-lib/aws-ec2'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as imagebuilder from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-image-recipe-all-parameters'); + +const userData = ec2.UserData.forLinux(); +userData.addCommands('echo "Hello World"'); + +const parameterizedComponent = new imagebuilder.Component(stack, 'ParameterizedComponent', { + platform: imagebuilder.Platform.LINUX, + data: imagebuilder.ComponentData.fromComponentDocumentJsonObject({ + name: 'ParameterizedComponent', + description: 'This is a parameterized component', + schemaVersion: imagebuilder.ComponentSchemaVersion.V1_0, + parameters: { + parameter1: { + type: imagebuilder.ComponentParameterType.STRING, + description: 'This is the first parameter', + }, + parameter2: { + type: imagebuilder.ComponentParameterType.STRING, + description: 'This is the second parameter', + }, + }, + phases: [ + { + name: imagebuilder.ComponentPhaseName.BUILD, + steps: [ + { + name: 'step1', + action: imagebuilder.ComponentAction.EXECUTE_BASH, + inputs: { + commands: ['echo ${{ parameter1 }}', 'echo ${{ parameter2 }}'], + }, + }, + ], + }, + ], + }), +}); + +const imageRecipe = new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { + imageRecipeName: 'test-image-recipe', + imageRecipeVersion: '1.2.3', + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), + description: 'A test image recipe', + components: [ + { + component: imagebuilder.AwsManagedComponent.helloWorld(stack, 'Component2', { + platform: imagebuilder.Platform.LINUX, + }), + }, + { + component: parameterizedComponent, + parameters: { + parameter1: imagebuilder.ComponentParameterValue.fromString('parameter-value-1'), + parameter2: imagebuilder.ComponentParameterValue.fromString('parameter-value-2'), + }, + }, + ], + amiTags: { + imageTag1: 'imageValue1', + imageTag2: 'imageValue2', + }, + workingDirectory: '/var/tmp', + uninstallSsmAgentAfterBuild: true, + userDataOverride: userData, + blockDevices: [ + { + mappingEnabled: false, + deviceName: '/dev/sda1', + volume: ec2.BlockDeviceVolume.ephemeral(0), + }, + ], + tags: { + key1: 'value1', + key2: 'value2', + }, +}); + +imageRecipe.addBlockDevices({ + deviceName: '/dev/sda2', + volume: ec2.BlockDeviceVolume.ebs(75, { + encrypted: true, + kmsKey: kms.Alias.fromAliasName(stack, 'DeviceKey', 'alias/device-encryption-key'), + deleteOnTermination: true, + iops: 1000, + volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3, + throughput: 125, + }), +}); + +new integ.IntegTest(app, 'ImageRecipeTest', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json new file mode 100644 index 0000000000000..de53e99c78fe9 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA Template", + "source": { + "path": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d8d86b35": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json new file mode 100644 index 0000000000000..a09f9b23d0a20 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "bea22e3a9581d8643504eeb0c0a6824a35aed92df5a24591c83206c446085464": { + "displayName": "aws-cdk-imagebuilder-image-recipe-default-parameters Template", + "source": { + "path": "aws-cdk-imagebuilder-image-recipe-default-parameters.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-5dcd7100": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "bea22e3a9581d8643504eeb0c0a6824a35aed92df5a24591c83206c446085464.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json new file mode 100644 index 0000000000000..d06b26b504903 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json @@ -0,0 +1,46 @@ +{ + "Resources": { + "ImageRecipe8C789631": { + "Type": "AWS::ImageBuilder::ImageRecipe", + "Properties": { + "Name": "aws-cdk-imagebuilder-image-recipe-default-parameters-imagerecipe-81fda979", + "ParentImage": "ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64", + "Version": "1.0.0" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/cdk.out b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/integ.json new file mode 100644 index 0000000000000..a94ca2d736e35 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "ImageRecipeTest/DefaultTest": { + "stacks": [ + "aws-cdk-imagebuilder-image-recipe-default-parameters" + ], + "assertionStack": "ImageRecipeTest/DefaultTest/DeployAssert", + "assertionStackName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json new file mode 100644 index 0000000000000..da4d407fe2893 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json @@ -0,0 +1,618 @@ +{ + "version": "48.0.0", + "artifacts": { + "aws-cdk-imagebuilder-image-recipe-default-parameters.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-imagebuilder-image-recipe-default-parameters": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-imagebuilder-image-recipe-default-parameters.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bea22e3a9581d8643504eeb0c0a6824a35aed92df5a24591c83206c446085464.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-imagebuilder-image-recipe-default-parameters.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-imagebuilder-image-recipe-default-parameters.assets" + ], + "metadata": { + "/aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipe8C789631" + } + ], + "/aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-imagebuilder-image-recipe-default-parameters/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ], + "ImageRecipeWithComponentsDCA1943F": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipeWithComponentsDCA1943F", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ] + }, + "displayName": "aws-cdk-imagebuilder-image-recipe-default-parameters" + }, + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ImageRecipeTestDefaultTestDeployAssertFD6737FA": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + ], + "metadata": { + "/ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ImageRecipeTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "userValue": true, + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "userValue": true, + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + }, + "@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault": { + "recommendedValue": true, + "explanation": "When enabled, Network Load Balancer will be created with a security group by default." + }, + "@aws-cdk/aws-stepfunctions-tasks:httpInvokeDynamicJsonPathEndpoint": { + "recommendedValue": true, + "explanation": "When enabled, allows using a dynamic apiEndpoint with JSONPath format in HttpInvoke tasks.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:uniqueTargetGroupId": { + "recommendedValue": true, + "explanation": "When enabled, ECS patterns will generate unique target group IDs to prevent conflicts during load balancer replacement" + } + } + } + } + }, + "minimumCliVersion": "2.1031.2" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json new file mode 100644 index 0000000000000..44b84714f8e90 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-default-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-default-parameters","path":"aws-cdk-imagebuilder-image-recipe-default-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-default-parameters-imagerecipe-81fda979","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","version":"1.0.0"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts new file mode 100644 index 0000000000000..ce57e3c663fe3 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts @@ -0,0 +1,16 @@ +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as imagebuilder from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-image-recipe-default-parameters'); + +new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { + baseImage: imagebuilder.BaseImage.fromSsmParameterName( + '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', + ), +}); + +new integ.IntegTest(app, 'ImageRecipeTest', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json new file mode 100644 index 0000000000000..de53e99c78fe9 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA Template", + "source": { + "path": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d8d86b35": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json new file mode 100644 index 0000000000000..269d8b97a7eea --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "8891845ec85f7385a0c3e34b81d233ca106bb83de4e67a241991fee6c5d020a3": { + "displayName": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image Template", + "source": { + "path": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-4c6e2429": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "8891845ec85f7385a0c3e34b81d233ca106bb83de4e67a241991fee6c5d020a3.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json new file mode 100644 index 0000000000000..b544a37303e93 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json @@ -0,0 +1,46 @@ +{ + "Resources": { + "ImageRecipe8C789631": { + "Type": "AWS::ImageBuilder::ImageRecipe", + "Properties": { + "Name": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image-imagerecipe-b40d66c5", + "ParentImage": "abcfcbaf-134e-4639-a7b4-fd285b9fcf0a", + "Version": "1.0.0" + } + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/cdk.out b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"48.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json new file mode 100644 index 0000000000000..15f06095f4344 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "ImageRecipeTest/DefaultTest": { + "stacks": [ + "aws-cdk-imagebuilder-image-recipe-marketplace-base-image" + ], + "assertionStack": "ImageRecipeTest/DefaultTest/DeployAssert", + "assertionStackName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json new file mode 100644 index 0000000000000..61946e990f4db --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json @@ -0,0 +1,609 @@ +{ + "version": "48.0.0", + "artifacts": { + "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-imagebuilder-image-recipe-marketplace-base-image": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8891845ec85f7385a0c3e34b81d233ca106bb83de4e67a241991fee6c5d020a3.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets" + ], + "metadata": { + "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipe8C789631" + } + ], + "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image" + }, + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ImageRecipeTestDefaultTestDeployAssertFD6737FA": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + ], + "metadata": { + "/ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ImageRecipeTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "aws-cdk-lib/feature-flag-report": { + "type": "cdk:feature-flag-report", + "properties": { + "module": "aws-cdk-lib", + "flags": { + "@aws-cdk/aws-signer:signingProfileNamePassedToCfn": { + "userValue": true, + "recommendedValue": true, + "explanation": "Pass signingProfileName to CfnSigningProfile" + }, + "@aws-cdk/core:newStyleStackSynthesis": { + "recommendedValue": true, + "explanation": "Switch to new stack synthesis method which enables CI/CD", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:stackRelativeExports": { + "recommendedValue": true, + "explanation": "Name exports based on the construct paths relative to the stack, rather than the global construct path", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:secGroupsDisablesImplicitOpenListener": { + "userValue": true, + "recommendedValue": true, + "explanation": "Disable implicit openListener when custom security groups are provided" + }, + "@aws-cdk/aws-rds:lowercaseDbIdentifier": { + "recommendedValue": true, + "explanation": "Force lowercasing of RDS Cluster names in CDK", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": { + "recommendedValue": true, + "explanation": "Allow adding/removing multiple UsagePlanKeys independently", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeVersionProps": { + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-lambda:recognizeLayerVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to opt in to the updated logical id calculation for Lambda Version created using the `fn.currentVersion`." + }, + "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": { + "recommendedValue": true, + "explanation": "Enable this feature flag to have cloudfront distributions use the security policy TLSv1.2_2021 by default.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:checkSecretUsage": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this flag to make it impossible to accidentally use SecretValues in unsafe locations" + }, + "@aws-cdk/core:target-partitions": { + "recommendedValue": [ + "aws", + "aws-cn" + ], + "explanation": "What regions to include in lookup tables of environment agnostic stacks" + }, + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": { + "userValue": true, + "recommendedValue": true, + "explanation": "ECS extensions will automatically add an `awslogs` driver if no logging is specified" + }, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to have Launch Templates generated by the `InstanceRequireImdsv2Aspect` use unique names." + }, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": { + "userValue": true, + "recommendedValue": true, + "explanation": "ARN format used by ECS. In the new ARN format, the cluster name is part of the resource ID." + }, + "@aws-cdk/aws-iam:minimizePolicies": { + "userValue": true, + "recommendedValue": true, + "explanation": "Minimize IAM policies by combining Statements" + }, + "@aws-cdk/core:validateSnapshotRemovalPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Error on snapshot removal policies on resources that do not support it." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate key aliases that include the stack name" + }, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature flag to create an S3 bucket policy by default in cases where an AWS service would automatically create the Policy if one does not exist." + }, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict KMS key policy for encrypted Queues a bit more" + }, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make default CloudWatch Role behavior safe for multiple API Gateways in one environment" + }, + "@aws-cdk/core:enablePartitionLiterals": { + "userValue": true, + "recommendedValue": true, + "explanation": "Make ARNs concrete if AWS partition is known" + }, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": { + "userValue": true, + "recommendedValue": true, + "explanation": "Event Rules may only push to encrypted SQS queues in the same account" + }, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": { + "userValue": true, + "recommendedValue": true, + "explanation": "Avoid setting the \"ECS\" deployment controller when adding a circuit breaker" + }, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable this feature to create default policy names for imported roles that depend on the stack the role is in." + }, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use S3 Bucket Policy instead of ACLs for Server Access Logging" + }, + "@aws-cdk/aws-route53-patters:useCertificate": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use the official `Certificate` resource instead of `DnsValidatedCertificate`" + }, + "@aws-cdk/customresources:installLatestAwsSdkDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "Whether to install the latest SDK by default in AwsCustomResource" + }, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": { + "userValue": true, + "recommendedValue": true, + "explanation": "Use unique resource name for Database Proxy" + }, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Remove CloudWatch alarms from deployment group" + }, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include authorizer configuration in the calculation of the API deployment logical ID." + }, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": { + "userValue": true, + "recommendedValue": true, + "explanation": "Define user data for a launch template by default when a machine image is provided." + }, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": { + "userValue": true, + "recommendedValue": true, + "explanation": "SecretTargetAttachments uses the ResourcePolicy of the attached Secret." + }, + "@aws-cdk/aws-redshift:columnId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Whether to use an ID to track Redshift column changes" + }, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable AmazonEMRServicePolicy_v2 managed policies" + }, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "Restrict access to the VPC default security group" + }, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a unique id for each RequestValidator added to a method" + }, + "@aws-cdk/aws-kms:aliasNameRef": { + "userValue": true, + "recommendedValue": true, + "explanation": "KMS Alias name and keyArn will have implicit reference to KMS Key" + }, + "@aws-cdk/aws-kms:applyImportedAliasPermissionsToPrincipal": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enable grant methods on Aliases imported by name to use kms:ResourceAliases condition" + }, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": { + "userValue": true, + "recommendedValue": true, + "explanation": "Generate a launch template when creating an AutoScalingGroup" + }, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": { + "userValue": true, + "recommendedValue": true, + "explanation": "Include the stack prefix in the stack name generation process" + }, + "@aws-cdk/aws-efs:denyAnonymousAccess": { + "userValue": true, + "recommendedValue": true, + "explanation": "EFS denies anonymous clients accesses" + }, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables support for Multi-AZ with Standby deployment for opensearch domains" + }, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables aws-lambda-nodejs.Function to use the latest available NodeJs runtime as the default" + }, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, mount targets will have a stable logicalId that is linked to the associated subnet." + }, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a scope of InstanceParameterGroup for AuroraClusterInstance with each parameters will change." + }, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, will always use the arn for identifiers for CfnSourceApiAssociation in the GraphqlApi construct rather than id." + }, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, creating an RDS database cluster from a snapshot will only render credentials for snapshot credentials." + }, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the CodeCommit source action is using the default branch name 'main'." + }, + "@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the logical ID of a Lambda permission for a Lambda action includes an alarm ID." + }, + "@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default value for crossAccountKeys to false." + }, + "@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "Enables Pipeline to set the default pipeline type to V2." + }, + "@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only." + }, + "@aws-cdk/pipelines:reduceAssetRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from PipelineAssetsFileRole trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-eks:nodegroupNameAttribute": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, nodegroupName attribute of the provisioned EKS NodeGroup will not have the cluster name prefix." + }, + "@aws-cdk/aws-ec2:ebsDefaultGp3Volume": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default volume type of the EBS volume will be GP3" + }, + "@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, remove default deployment alarm settings" + }, + "@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, the custom resource used for `AwsCustomResource` will configure the `logApiResponseData` property as true by default" + }, + "@aws-cdk/aws-s3:keepNotificationInImportedBucket": { + "userValue": false, + "recommendedValue": false, + "explanation": "When enabled, Adding notifications to a bucket in the current stack will not remove notification from imported stack." + }, + "@aws-cdk/aws-stepfunctions-tasks:useNewS3UriParametersForBedrockInvokeModelTask": { + "recommendedValue": true, + "explanation": "When enabled, use new props for S3 URI field in task definition of state machine for bedrock invoke model.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/core:explicitStackTags": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, stack tags need to be assigned explicitly on a Stack." + }, + "@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": { + "userValue": false, + "recommendedValue": false, + "explanation": "When set to true along with canContainersAccessInstanceRole=false in ECS cluster, new updated commands will be added to UserData to block container accessing IMDS. **Applicable to Linux only. IMPORTANT: See [details.](#aws-cdkaws-ecsenableImdsBlockingDeprecatedFeature)**" + }, + "@aws-cdk/aws-ecs:disableEcsImdsBlocking": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, CDK synth will throw exception if canContainersAccessInstanceRole is false. **IMPORTANT: See [details.](#aws-cdkaws-ecsdisableEcsImdsBlocking)**" + }, + "@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, we will only grant the necessary permissions when users specify cloudwatch log group through logConfiguration" + }, + "@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled will allow you to specify a resource policy per replica, and not copy the source table policy to all replicas" + }, + "@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, initOptions.timeout and resourceSignalTimeout values will be summed together." + }, + "@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, a Lambda authorizer Permission created when using GraphqlApi will be properly scoped with a SourceArn." + }, + "@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the value of property `instanceResourceId` in construct `DatabaseInstanceReadReplica` will be set to the correct value which is `DbiResourceId` instead of currently `DbInstanceArn`" + }, + "@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CFN templates added with `cfn-include` will error if the template contains Resource Update or Create policies with CFN Intrinsics that include non-primitive values." + }, + "@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, both `@aws-sdk` and `@smithy` packages will be excluded from the Lambda Node.js 18.x runtime to prevent version mismatches in bundled applications." + }, + "@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resource of IAM Run Ecs policy generated by SFN EcsRunTask will reference the definition, instead of constructing ARN." + }, + "@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the BastionHost construct will use the latest Amazon Linux 2023 AMI, instead of Amazon Linux 2." + }, + "@aws-cdk/core:aspectStabilization": { + "recommendedValue": true, + "explanation": "When enabled, a stabilization loop will be run when invoking Aspects during synthesis.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, use a new method for DNS Name of user pool domain target without creating a custom resource." + }, + "@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default security group ingress rules will allow IPv6 ingress from anywhere" + }, + "@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the default behaviour of OIDC provider will reject unauthorized connections" + }, + "@aws-cdk/core:enableAdditionalMetadataCollection": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will expand the scope of usage data collected to better inform CDK development and improve communication for security concerns and emerging issues." + }, + "@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": { + "userValue": false, + "recommendedValue": false, + "explanation": "[Deprecated] When enabled, Lambda will create new inline policies with AddToRolePolicy instead of adding to the Default Policy Statement" + }, + "@aws-cdk/aws-s3:setUniqueReplicationRoleName": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK will automatically generate a unique role name that is used for s3 object replication." + }, + "@aws-cdk/pipelines:reduceStageRoleTrustScope": { + "recommendedValue": true, + "explanation": "Remove the root account principal from Stage addActions trust policy", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-events:requireEventBusPolicySid": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, grantPutEventsTo() will use resource policies with Statement IDs for service principals." + }, + "@aws-cdk/core:aspectPrioritiesMutating": { + "userValue": true, + "recommendedValue": true, + "explanation": "When set to true, Aspects added by the construct library on your behalf will be given a priority of MUTATING." + }, + "@aws-cdk/aws-dynamodb:retainTableReplica": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, table replica will be default to the removal policy of source table unless specified otherwise." + }, + "@aws-cdk/cognito:logUserPoolClientSecretValue": { + "recommendedValue": false, + "explanation": "When disabled, the value of the user pool client secret will not be logged in the custom resource lambda function logs." + }, + "@aws-cdk/pipelines:reduceCrossAccountActionRoleTrustScope": { + "recommendedValue": true, + "explanation": "When enabled, scopes down the trust policy for the cross-account action role", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the resultWriterV2 property of DistributedMap will be used insted of resultWriter" + }, + "@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": { + "userValue": true, + "recommendedValue": true, + "explanation": "Add an S3 trust policy to a KMS key resource policy for SNS subscriptions." + }, + "@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, the EgressOnlyGateway resource is only created if private subnets are defined in the dual-stack VPC." + }, + "@aws-cdk/aws-ec2-alpha:useResourceIdForVpcV2Migration": { + "recommendedValue": false, + "explanation": "When enabled, use resource IDs for VPC V2 migration" + }, + "@aws-cdk/aws-s3:publicAccessBlockedByDefault": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, setting any combination of options for BlockPublicAccess will automatically set true for any options not defined." + }, + "@aws-cdk/aws-lambda:useCdkManagedLogGroup": { + "userValue": true, + "recommendedValue": true, + "explanation": "When enabled, CDK creates and manages loggroup for the lambda function" + }, + "@aws-cdk/aws-elasticloadbalancingv2:networkLoadBalancerWithSecurityGroupByDefault": { + "recommendedValue": true, + "explanation": "When enabled, Network Load Balancer will be created with a security group by default." + }, + "@aws-cdk/aws-stepfunctions-tasks:httpInvokeDynamicJsonPathEndpoint": { + "recommendedValue": true, + "explanation": "When enabled, allows using a dynamic apiEndpoint with JSONPath format in HttpInvoke tasks.", + "unconfiguredBehavesLike": { + "v2": true + } + }, + "@aws-cdk/aws-ecs-patterns:uniqueTargetGroupId": { + "recommendedValue": true, + "explanation": "When enabled, ECS patterns will generate unique target group IDs to prevent conflicts during load balancer replacement" + } + } + } + } + }, + "minimumCliVersion": "2.1031.2" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json new file mode 100644 index 0000000000000..1430428969f4e --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json @@ -0,0 +1 @@ +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-marketplace-base-image":{"id":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image-imagerecipe-b40d66c5","parentImage":"abcfcbaf-134e-4639-a7b4-fd285b9fcf0a","version":"1.0.0"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts new file mode 100644 index 0000000000000..96f7d6ecf5c24 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts @@ -0,0 +1,14 @@ +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as imagebuilder from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-image-recipe-marketplace-base-image'); + +new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { + baseImage: imagebuilder.BaseImage.fromMarketplaceProductId('abcfcbaf-134e-4639-a7b4-fd285b9fcf0a'), +}); + +new integ.IntegTest(app, 'ImageRecipeTest', { + testCases: [stack], +}); From 70b5991e2b392f96a9f93899098742938e13e78b Mon Sep 17 00:00:00 2001 From: Tarun Belani Date: Thu, 20 Nov 2025 06:38:57 -0800 Subject: [PATCH 2/6] Addressed review comments --- .../lib/image-recipe.ts | 20 +++++++++++-------- .../test/image-recipe.test.ts | 2 +- .../test/integ.all-parameters.image-recipe.ts | 4 ++-- ...mage-recipe-default-parameters.assets.json | 6 +++--- ...ge-recipe-default-parameters.template.json | 2 +- .../manifest.json | 16 +++++---------- .../tree.json | 2 +- ...-recipe-marketplace-base-image.assets.json | 6 +++--- ...ecipe-marketplace-base-image.template.json | 2 +- .../manifest.json | 7 +++++-- .../tree.json | 2 +- 11 files changed, 35 insertions(+), 34 deletions(-) diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts index a4d2ff9f7bc75..db0feda7c48d2 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts @@ -9,6 +9,12 @@ import { ComponentConfiguration, IRecipeBase } from './recipe-base'; const IMAGE_RECIPE_SYMBOL = Symbol.for('@aws-cdk/aws-imagebuilder-alpha.ImageRecipe'); +/** + * Represents the latest version of an image recipe. When using the recipe in a pipeline, the pipeline will use the + * latest recipe at the time of execution. + * + * @see https://docs.aws.amazon.com/imagebuilder/latest/userguide/ibhow-semantic-versioning.html + */ const LATEST_VERSION = 'x.x.x'; /** @@ -56,7 +62,7 @@ export interface ImageRecipeProps { /** * The version of the image recipe. * - * @default 1.0.0 + * @default 1.0.x */ readonly imageRecipeVersion?: string; @@ -127,24 +133,22 @@ export interface ImageRecipeAttributes { /** * The ARN of the image recipe * - * @default - the ARN is automatically constructed if an imageRecipeName is provided, otherwise an - * imageRecipeName is required + * @default - derived from the imageRecipeName */ readonly imageRecipeArn?: string; /** * The name of the image recipe * - * @default - the name is automatically constructed if an imageRecipeArn is provided, otherwise an imageRecipeName is - * required + * @default - derived from the imageRecipeArn */ readonly imageRecipeName?: string; /** * The version of the image recipe * - * @default - the version is automatically constructed if an imageRecipeArn is provided, otherwise the latest version - * is used. + * @default - derived from containerRecipeArn. if a containerRecipeName is provided, the latest version, x.x.x, will + * be used */ readonly imageRecipeVersion?: string; } @@ -330,7 +334,7 @@ export class ImageRecipe extends ImageRecipeBase { }), ); - const imageRecipeVersion = props.imageRecipeVersion ?? '1.0.0'; + const imageRecipeVersion = props.imageRecipeVersion ?? '1.0.x'; const imageRecipe = new CfnImageRecipe(this, 'Resource', { name: this.physicalName, version: imageRecipeVersion, diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts index d639cbd3f3e97..fc81bd09fa2a4 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts @@ -308,7 +308,7 @@ describe('Image Recipe', () => { Type: 'AWS::ImageBuilder::ImageRecipe', Properties: { Name: 'stack-imagerecipe-1e832b66', - Version: '1.0.0', + Version: '1.0.x', ParentImage: 'ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', }, }), diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts index 79f5a90333b0f..570228339dfd6 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts @@ -33,9 +33,9 @@ const parameterizedComponent = new imagebuilder.Component(stack, 'ParameterizedC { name: 'step1', action: imagebuilder.ComponentAction.EXECUTE_BASH, - inputs: { + inputs: imagebuilder.ComponentStepInputs.fromObject({ commands: ['echo ${{ parameter1 }}', 'echo ${{ parameter2 }}'], - }, + }), }, ], }, diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json index a09f9b23d0a20..a99b62cacef6a 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json @@ -1,16 +1,16 @@ { "version": "48.0.0", "files": { - "bea22e3a9581d8643504eeb0c0a6824a35aed92df5a24591c83206c446085464": { + "a250cc9d80b525f1559dd4cdc0bc8bc580419c0788b0bf9d20db76fa21a9f7f7": { "displayName": "aws-cdk-imagebuilder-image-recipe-default-parameters Template", "source": { "path": "aws-cdk-imagebuilder-image-recipe-default-parameters.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region-5dcd7100": { + "current_account-current_region-468423fc": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "bea22e3a9581d8643504eeb0c0a6824a35aed92df5a24591c83206c446085464.json", + "objectKey": "a250cc9d80b525f1559dd4cdc0bc8bc580419c0788b0bf9d20db76fa21a9f7f7.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json index d06b26b504903..6145003291d25 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json @@ -5,7 +5,7 @@ "Properties": { "Name": "aws-cdk-imagebuilder-image-recipe-default-parameters-imagerecipe-81fda979", "ParentImage": "ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64", - "Version": "1.0.0" + "Version": "1.0.x" } } }, diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json index da4d407fe2893..87f250ce25193 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bea22e3a9581d8643504eeb0c0a6824a35aed92df5a24591c83206c446085464.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a250cc9d80b525f1559dd4cdc0bc8bc580419c0788b0bf9d20db76fa21a9f7f7.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -37,7 +37,10 @@ "/aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource": [ { "type": "aws:cdk:logicalId", - "data": "ImageRecipe8C789631" + "data": "ImageRecipe8C789631", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] } ], "/aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion": [ @@ -51,15 +54,6 @@ "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } - ], - "ImageRecipeWithComponentsDCA1943F": [ - { - "type": "aws:cdk:logicalId", - "data": "ImageRecipeWithComponentsDCA1943F", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" - ] - } ] }, "displayName": "aws-cdk-imagebuilder-image-recipe-default-parameters" diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json index 44b84714f8e90..ae14359ccc501 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json @@ -1 +1 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-default-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-default-parameters","path":"aws-cdk-imagebuilder-image-recipe-default-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-default-parameters-imagerecipe-81fda979","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","version":"1.0.0"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-default-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-default-parameters","path":"aws-cdk-imagebuilder-image-recipe-default-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-default-parameters-imagerecipe-81fda979","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","version":"1.0.x"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json index 269d8b97a7eea..ed27efd63eb53 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json @@ -1,16 +1,16 @@ { "version": "48.0.0", "files": { - "8891845ec85f7385a0c3e34b81d233ca106bb83de4e67a241991fee6c5d020a3": { + "bf34c2eae6eeafeeb0a1103cd3d55c1509b06980a3c943d21d30022731672b06": { "displayName": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image Template", "source": { "path": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region-4c6e2429": { + "current_account-current_region-525dc300": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "8891845ec85f7385a0c3e34b81d233ca106bb83de4e67a241991fee6c5d020a3.json", + "objectKey": "bf34c2eae6eeafeeb0a1103cd3d55c1509b06980a3c943d21d30022731672b06.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json index b544a37303e93..b236f9e83fa9d 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json @@ -5,7 +5,7 @@ "Properties": { "Name": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image-imagerecipe-b40d66c5", "ParentImage": "abcfcbaf-134e-4639-a7b4-fd285b9fcf0a", - "Version": "1.0.0" + "Version": "1.0.x" } } }, diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json index 61946e990f4db..36a17a28f8744 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8891845ec85f7385a0c3e34b81d233ca106bb83de4e67a241991fee6c5d020a3.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bf34c2eae6eeafeeb0a1103cd3d55c1509b06980a3c943d21d30022731672b06.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -37,7 +37,10 @@ "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource": [ { "type": "aws:cdk:logicalId", - "data": "ImageRecipe8C789631" + "data": "ImageRecipe8C789631", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] } ], "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion": [ diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json index 1430428969f4e..8b583edd58e20 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json @@ -1 +1 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-marketplace-base-image":{"id":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image-imagerecipe-b40d66c5","parentImage":"abcfcbaf-134e-4639-a7b4-fd285b9fcf0a","version":"1.0.0"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-marketplace-base-image":{"id":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image-imagerecipe-b40d66c5","parentImage":"abcfcbaf-134e-4639-a7b4-fd285b9fcf0a","version":"1.0.x"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}}}}} \ No newline at end of file From 2b7e94ee9d4a0c0919b545f91bc80e386faa2f0d Mon Sep 17 00:00:00 2001 From: Tarun Belani Date: Thu, 20 Nov 2025 12:02:20 -0800 Subject: [PATCH 3/6] Addressed review comments --- .../lib/image-recipe.ts | 52 +++++++++++++------ .../test/image-recipe.test.ts | 6 +-- ...er-image-recipe-all-parameters.assets.json | 6 +-- ...-image-recipe-all-parameters.template.json | 10 ++++ .../manifest.json | 8 ++- .../tree.json | 2 +- .../test/integ.all-parameters.image-recipe.ts | 4 +- ...mage-recipe-default-parameters.assets.json | 6 +-- ...ge-recipe-default-parameters.template.json | 10 ++++ .../manifest.json | 13 +++-- .../tree.json | 2 +- .../integ.default-parameters.image-recipe.ts | 4 +- 12 files changed, 88 insertions(+), 35 deletions(-) diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts index db0feda7c48d2..a4e016dc7cc42 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts @@ -17,6 +17,14 @@ const IMAGE_RECIPE_SYMBOL = Symbol.for('@aws-cdk/aws-imagebuilder-alpha.ImageRec */ const LATEST_VERSION = 'x.x.x'; +/** + * The default version to use in the image recipe. When the recipe is updated, the `x` will be incremented off from + * the latest recipe version that exists. + * + * @see https://docs.aws.amazon.com/imagebuilder/latest/userguide/create-image-recipes.html + */ +const DEFAULT_RECIPE_VERSION = '1.0.x'; + /** * An EC2 Image Builder Image Recipe. */ @@ -48,7 +56,7 @@ export interface IImageRecipe extends IRecipeBase { */ export interface ImageRecipeProps { /** - * The base image for customizations specified in the container recipe. + * The base image for customizations specified in the image recipe. */ readonly baseImage: BaseImage; @@ -147,7 +155,7 @@ export interface ImageRecipeAttributes { /** * The version of the image recipe * - * @default - derived from containerRecipeArn. if a containerRecipeName is provided, the latest version, x.x.x, will + * @default - derived from imageRecipeArn. if a imageRecipeName is provided, the latest version, x.x.x, will * be used */ readonly imageRecipeVersion?: string; @@ -237,17 +245,13 @@ export class ImageRecipe extends ImageRecipeBase { * underscores with hyphens. */ public static fromImageRecipeAttributes(scope: Construct, id: string, attrs: ImageRecipeAttributes): IImageRecipe { - if (attrs.imageRecipeArn && (attrs.imageRecipeName || attrs.imageRecipeVersion)) { + if (!attrs.imageRecipeArn && !attrs.imageRecipeName) { throw new cdk.ValidationError( - 'an imageRecipeName and imageRecipeVersion cannot be provided when an imageRecipeArn is provided', + 'either imageRecipeArn or imageRecipeName must be provided to import a image recipe', scope, ); } - if (!attrs.imageRecipeArn && !attrs.imageRecipeName) { - throw new cdk.ValidationError('either imageRecipeArn or imageRecipeName is required', scope); - } - const imageRecipeArn = attrs.imageRecipeArn ?? cdk.Stack.of(scope).formatArn({ @@ -321,20 +325,23 @@ export class ImageRecipe extends ImageRecipeBase { this.validateImageRecipeName(); - this.addBlockDevices(...(props.blockDevices ?? [])); + this.addBlockDevice(...(props.blockDevices ?? [])); const components: CfnImageRecipe.ComponentConfigurationProperty[] | undefined = props.components?.map( (component) => ({ componentArn: component.component.componentArn, - ...(Object.keys(component.parameters ?? {}).length && { - parameters: Object.entries(component.parameters!).map( - ([key, value]): CfnImageRecipe.ComponentParameterProperty => ({ name: key, value: value.value }), + ...(component.parameters && { + parameters: Object.entries(component.parameters).map( + ([name, param]): CfnImageRecipe.ComponentParameterProperty => ({ + name, + value: param.value, + }), ), }), }), ); - const imageRecipeVersion = props.imageRecipeVersion ?? '1.0.x'; + const imageRecipeVersion = props.imageRecipeVersion ?? DEFAULT_RECIPE_VERSION; const imageRecipe = new CfnImageRecipe(this, 'Resource', { name: this.physicalName, version: imageRecipeVersion, @@ -362,10 +369,17 @@ export class ImageRecipe extends ImageRecipeBase { * * @param blockDevices The list of block devices to attach */ - public addBlockDevices(...blockDevices: ec2.BlockDevice[]): void { + public addBlockDevice(...blockDevices: ec2.BlockDevice[]): void { this.blockDevices.push(...blockDevices); } + /** + * Renders the input block devices, into the `BlockDeviceMapping[]` structure that CfnImageRecipe expects to receive. + * This is rendered at synthesis time, as users can add additional block devices with `addBlockDevice`, after the + * construct has been instantiated. + * + * @private + */ private renderBlockDevices(): CfnImageRecipe.InstanceBlockDeviceMappingProperty[] | undefined { const blockDevices = this.blockDevices.map((blockDevice): CfnImageRecipe.InstanceBlockDeviceMappingProperty => { const ebsDevice = blockDevice.volume.ebsDevice; @@ -380,11 +394,10 @@ export class ImageRecipe extends ImageRecipeBase { ...(ebsDevice?.volumeType !== undefined && { volumeType: ebsDevice.volumeType }), }; - const mappingEnabled = blockDevice.mappingEnabled ?? true; return { deviceName: blockDevice.deviceName, virtualName: blockDevice.volume.virtualName, - ...(!mappingEnabled && { noDevice: '' }), + ...(blockDevice.mappingEnabled === false && { noDevice: '' }), ...(Object.keys(ebs).length && { ebs }), }; }); @@ -392,6 +405,13 @@ export class ImageRecipe extends ImageRecipeBase { return blockDevices.length ? blockDevices : undefined; } + /** + * Generates the additional instance configuration property into the `AdditionalInstanceConfiguration` type in the + * CloudFormation L1 definition. + * + * @param props The props passed as input to the construct + * @private + */ private buildAdditionalInstanceConfiguration( props: ImageRecipeProps, ): CfnImageRecipe.AdditionalInstanceConfigurationProperty | undefined { diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts index fc81bd09fa2a4..d6b8d4e868496 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/image-recipe.test.ts @@ -181,7 +181,7 @@ describe('Image Recipe', () => { }, }); - imageRecipe.addBlockDevices( + imageRecipe.addBlockDevice( { deviceName: '/dev/sda2', volume: ec2.BlockDeviceVolume.ebs(75, { @@ -416,13 +416,13 @@ describe('Image Recipe', () => { }); }); - test('throws a validation error when an imageRecipeArn and imageRecipeName are provided when importing by attributes', () => { + test('does not throw a validation error when an imageRecipeArn and imageRecipeName are provided when importing by attributes', () => { expect(() => ImageRecipe.fromImageRecipeAttributes(stack, 'ImageRecipe', { imageRecipeArn: 'arn:aws:imagebuilder:us-east-1:123456789012:image-recipe/imported-image-recipe/x.x.x', imageRecipeName: 'imported-image-recipe', }), - ).toThrow(cdk.ValidationError); + ).not.toThrow(cdk.ValidationError); }); test('throws a validation error when neither an imageRecipeArn or imageRecipeName are provided when importing by attributes', () => { diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json index 3b2f2689a9cd5..5723e60ab110f 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.assets.json @@ -1,16 +1,16 @@ { "version": "48.0.0", "files": { - "1d83592873b042fee5e5aa6ccd858869b17e2af204bdeabd4b36b9aab6ba42ab": { + "fb00c6fb23f3af07cc43f8464a7dc9805d43b0e715cf435e770fba392a99ad68": { "displayName": "aws-cdk-imagebuilder-image-recipe-all-parameters Template", "source": { "path": "aws-cdk-imagebuilder-image-recipe-all-parameters.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region-4de35eda": { + "current_account-current_region-39bee65e": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "1d83592873b042fee5e5aa6ccd858869b17e2af204bdeabd4b36b9aab6ba42ab.json", + "objectKey": "fb00c6fb23f3af07cc43f8464a7dc9805d43b0e715cf435e770fba392a99ad68.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json index e5e93ae647a29..1ba8f6a0f47d7 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-all-parameters.template.json @@ -116,6 +116,16 @@ } } }, + "Outputs": { + "ImageRecipeVersion": { + "Value": { + "Fn::GetAtt": [ + "ImageRecipe8C789631", + "Version" + ] + } + } + }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json index 78c6c98399f30..57b17f44cb08c 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/1d83592873b042fee5e5aa6ccd858869b17e2af204bdeabd4b36b9aab6ba42ab.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/fb00c6fb23f3af07cc43f8464a7dc9805d43b0e715cf435e770fba392a99ad68.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -46,6 +46,12 @@ "data": "ImageRecipe8C789631" } ], + "/aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipeVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipeVersion" + } + ], "/aws-cdk-imagebuilder-image-recipe-all-parameters/BootstrapVersion": [ { "type": "aws:cdk:logicalId", diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json index d01bac23a4b5b..8c27a3efb9891 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.js.snapshot/tree.json @@ -1 +1 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-all-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-all-parameters","path":"aws-cdk-imagebuilder-image-recipe-all-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ParameterizedComponent":{"id":"ParameterizedComponent","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ParameterizedComponent","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.Component","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ParameterizedComponent/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnComponent","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::Component","aws:cdk:cloudformation:props":{"data":"name: ParameterizedComponent\ndescription: This is a parameterized component\nschemaVersion: \"1.0\"\nparameters:\n - parameter1:\n type: string\n description: This is the first parameter\n - parameter2:\n type: string\n description: This is the second parameter\nphases:\n - name: build\n steps:\n - name: step1\n action: ExecuteBash\n inputs:\n commands:\n - echo ${{ parameter1 }}\n - echo ${{ parameter2 }}\n","name":"aws-cdk-imagebuilder-image-recipe-all-parameters-parameterizedcomponent-abcc0eb5","platform":"Linux","version":"1.0.0"}}}}},"Component2":{"id":"Component2","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/Component2","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"additionalInstanceConfiguration":{"systemsManagerAgent":{"uninstallAfterBuild":true},"userDataOverride":{"Fn::Base64":"#!/bin/bash\necho \"Hello World\""}},"amiTags":{"imageTag1":"imageValue1","imageTag2":"imageValue2"},"blockDeviceMappings":[{"deviceName":"/dev/sda1","virtualName":"ephemeral0","noDevice":""},{"deviceName":"/dev/sda2","ebs":{"deleteOnTermination":true,"encrypted":true,"iops":1000,"kmsKeyId":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":kms:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":alias/device-encryption-key"]]},"throughput":125,"volumeSize":75,"volumeType":"gp3"}}],"components":[{"componentArn":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":imagebuilder:",{"Ref":"AWS::Region"},":aws:component/hello-world-linux/x.x.x"]]}},{"componentArn":{"Fn::GetAtt":["ParameterizedComponentD29478CA","Arn"]},"parameters":[{"name":"parameter1","value":["parameter-value-1"]},{"name":"parameter2","value":["parameter-value-2"]}]}],"description":"A test image recipe","name":"test-image-recipe","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","tags":{"key1":"value1","key2":"value2"},"version":"1.2.3","workingDirectory":"/var/tmp"}}}}},"DeviceKey":{"id":"DeviceKey","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/DeviceKey","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.2"}}}}} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-all-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-all-parameters","path":"aws-cdk-imagebuilder-image-recipe-all-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ParameterizedComponent":{"id":"ParameterizedComponent","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ParameterizedComponent","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.Component","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ParameterizedComponent/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnComponent","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::Component","aws:cdk:cloudformation:props":{"data":"name: ParameterizedComponent\ndescription: This is a parameterized component\nschemaVersion: \"1.0\"\nparameters:\n - parameter1:\n type: string\n description: This is the first parameter\n - parameter2:\n type: string\n description: This is the second parameter\nphases:\n - name: build\n steps:\n - name: step1\n action: ExecuteBash\n inputs:\n commands:\n - echo ${{ parameter1 }}\n - echo ${{ parameter2 }}\n","name":"aws-cdk-imagebuilder-image-recipe-all-parameters-parameterizedcomponent-abcc0eb5","platform":"Linux","version":"1.0.0"}}}}},"Component2":{"id":"Component2","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/Component2","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"additionalInstanceConfiguration":{"systemsManagerAgent":{"uninstallAfterBuild":true},"userDataOverride":{"Fn::Base64":"#!/bin/bash\necho \"Hello World\""}},"amiTags":{"imageTag1":"imageValue1","imageTag2":"imageValue2"},"blockDeviceMappings":[{"deviceName":"/dev/sda1","virtualName":"ephemeral0","noDevice":""},{"deviceName":"/dev/sda2","ebs":{"deleteOnTermination":true,"encrypted":true,"iops":1000,"kmsKeyId":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":kms:",{"Ref":"AWS::Region"},":",{"Ref":"AWS::AccountId"},":alias/device-encryption-key"]]},"throughput":125,"volumeSize":75,"volumeType":"gp3"}}],"components":[{"componentArn":{"Fn::Join":["",["arn:",{"Ref":"AWS::Partition"},":imagebuilder:",{"Ref":"AWS::Region"},":aws:component/hello-world-linux/x.x.x"]]}},{"componentArn":{"Fn::GetAtt":["ParameterizedComponentD29478CA","Arn"]},"parameters":[{"name":"parameter1","value":["parameter-value-1"]},{"name":"parameter2","value":["parameter-value-2"]}]}],"description":"A test image recipe","name":"test-image-recipe","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","tags":{"key1":"value1","key2":"value2"},"version":"1.2.3","workingDirectory":"/var/tmp"}}}}},"DeviceKey":{"id":"DeviceKey","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/DeviceKey","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"ImageRecipeVersion":{"id":"ImageRecipeVersion","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/ImageRecipeVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-all-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts index 570228339dfd6..8da22c98fef9d 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts @@ -84,7 +84,7 @@ const imageRecipe = new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { }, }); -imageRecipe.addBlockDevices({ +imageRecipe.addBlockDevice({ deviceName: '/dev/sda2', volume: ec2.BlockDeviceVolume.ebs(75, { encrypted: true, @@ -96,6 +96,8 @@ imageRecipe.addBlockDevices({ }), }); +new cdk.CfnOutput(stack, 'ImageRecipeVersion', { value: imageRecipe.imageRecipeVersion }); + new integ.IntegTest(app, 'ImageRecipeTest', { testCases: [stack], }); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json index a99b62cacef6a..5418d347cb3ed 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.assets.json @@ -1,16 +1,16 @@ { "version": "48.0.0", "files": { - "a250cc9d80b525f1559dd4cdc0bc8bc580419c0788b0bf9d20db76fa21a9f7f7": { + "505b1144ef7a372e49381a430b2d4b8718aed867d8950fa3cf853d8b67df13e0": { "displayName": "aws-cdk-imagebuilder-image-recipe-default-parameters Template", "source": { "path": "aws-cdk-imagebuilder-image-recipe-default-parameters.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region-468423fc": { + "current_account-current_region-ea19c71d": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "a250cc9d80b525f1559dd4cdc0bc8bc580419c0788b0bf9d20db76fa21a9f7f7.json", + "objectKey": "505b1144ef7a372e49381a430b2d4b8718aed867d8950fa3cf853d8b67df13e0.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json index 6145003291d25..aeff6d780f7d1 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-default-parameters.template.json @@ -9,6 +9,16 @@ } } }, + "Outputs": { + "ImageRecipeVersion": { + "Value": { + "Fn::GetAtt": [ + "ImageRecipe8C789631", + "Version" + ] + } + } + }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json index 87f250ce25193..5d359117ddd3a 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/a250cc9d80b525f1559dd4cdc0bc8bc580419c0788b0bf9d20db76fa21a9f7f7.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/505b1144ef7a372e49381a430b2d4b8718aed867d8950fa3cf853d8b67df13e0.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -37,10 +37,13 @@ "/aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource": [ { "type": "aws:cdk:logicalId", - "data": "ImageRecipe8C789631", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "ImageRecipe8C789631" + } + ], + "/aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipeVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipeVersion" } ], "/aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion": [ diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json index ae14359ccc501..cb01b1d96cf44 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.js.snapshot/tree.json @@ -1 +1 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-default-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-default-parameters","path":"aws-cdk-imagebuilder-image-recipe-default-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-default-parameters-imagerecipe-81fda979","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","version":"1.0.x"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}}}}} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-default-parameters":{"id":"aws-cdk-imagebuilder-image-recipe-default-parameters","path":"aws-cdk-imagebuilder-image-recipe-default-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-default-parameters-imagerecipe-81fda979","parentImage":"ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64","version":"1.0.x"}}}}},"ImageRecipeVersion":{"id":"ImageRecipeVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/ImageRecipeVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-default-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts index ce57e3c663fe3..ce90406241583 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts @@ -5,12 +5,14 @@ import * as imagebuilder from '../lib'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-image-recipe-default-parameters'); -new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { +const imageRecipe = new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { baseImage: imagebuilder.BaseImage.fromSsmParameterName( '/aws/service/ami-amazon-linux-latest/al2023-ami-minimal-kernel-default-x86_64', ), }); +new cdk.CfnOutput(stack, 'ImageRecipeVersion', { value: imageRecipe.imageRecipeVersion }); + new integ.IntegTest(app, 'ImageRecipeTest', { testCases: [stack], }); From c15313feaacfddeb0b2457312ac621178dbe43c5 Mon Sep 17 00:00:00 2001 From: Tarun Belani Date: Thu, 20 Nov 2025 12:43:26 -0800 Subject: [PATCH 4/6] Addressed review comments --- .../test/integ.all-parameters.image-recipe.ts | 2 +- .../test/integ.default-parameters.image-recipe.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts index 8da22c98fef9d..b0903c54994c9 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.image-recipe.ts @@ -98,6 +98,6 @@ imageRecipe.addBlockDevice({ new cdk.CfnOutput(stack, 'ImageRecipeVersion', { value: imageRecipe.imageRecipeVersion }); -new integ.IntegTest(app, 'ImageRecipeTest', { +new integ.IntegTest(app, 'ImageRecipeTest-AllParameters', { testCases: [stack], }); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts index ce90406241583..a09aa11ea0383 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.image-recipe.ts @@ -13,6 +13,6 @@ const imageRecipe = new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { new cdk.CfnOutput(stack, 'ImageRecipeVersion', { value: imageRecipe.imageRecipeVersion }); -new integ.IntegTest(app, 'ImageRecipeTest', { +new integ.IntegTest(app, 'ImageRecipeTest-DefaultParameters', { testCases: [stack], }); From 4aea8e6245433d41811f33a10c79361bae1b116e Mon Sep 17 00:00:00 2001 From: Tarun Belani Date: Thu, 20 Nov 2025 19:23:36 -0800 Subject: [PATCH 5/6] Resolve merge conflicts --- .../aws-imagebuilder-alpha/lib/container-recipe.ts | 10 ++++++++++ .../aws-imagebuilder-alpha/lib/image-recipe.ts | 10 ++++++++++ .../@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts | 2 +- .../aws-imagebuilder-alpha/test/base-image.test.ts | 1 + .../test/integ.asset.container-recipe.ts | 2 +- .../test/integ.s3.container-recipe.ts | 2 +- 6 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/container-recipe.ts index 5579f8092d7ef..7ea26ffd5f7ef 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/container-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/container-recipe.ts @@ -9,6 +9,7 @@ import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable'; import { Construct } from 'constructs'; import { BaseContainerImage, ContainerInstanceImage } from './base-image'; import { Repository } from './distribution-configuration'; +import { IImageRecipe } from './image-recipe'; import { OSVersion } from './os-version'; import { ComponentConfiguration, IRecipeBase } from './recipe-base'; @@ -378,6 +379,15 @@ export abstract class ContainerRecipeBase extends cdk.Resource implements IConta public _isContainerRecipe(): this is IContainerRecipe { return true; } + + /** + * Indicates whether the recipe is an Image Recipe + * + * @internal + */ + public _isImageRecipe(): this is IImageRecipe { + return false; + } } /** diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts index a4e016dc7cc42..a635dc813460d 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts @@ -5,6 +5,7 @@ import { CfnImageRecipe } from 'aws-cdk-lib/aws-imagebuilder'; import { propertyInjectable } from 'aws-cdk-lib/core/lib/prop-injectable'; import { Construct } from 'constructs'; import { BaseImage } from './base-image'; +import { IContainerRecipe } from './container-recipe'; import { ComponentConfiguration, IRecipeBase } from './recipe-base'; const IMAGE_RECIPE_SYMBOL = Symbol.for('@aws-cdk/aws-imagebuilder-alpha.ImageRecipe'); @@ -204,6 +205,15 @@ abstract class ImageRecipeBase extends cdk.Resource implements IImageRecipe { return this.grant(grantee, 'imagebuilder:GetImageRecipe'); } + /** + * Indicates whether the recipe is a Container Recipe + * + * @internal + */ + public _isContainerRecipe(): this is IContainerRecipe { + return false; + } + /** * Indicates whether the recipe is an Image Recipe * diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts index 17df99a4e0ff6..027d0d4b6307d 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts @@ -70,7 +70,7 @@ export interface IRecipeBase extends cdk.IResource { * @internal */ _isContainerRecipe(): this is IContainerRecipe; - + /** * Indicates whether the recipe is an Image Recipe * diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts index 58cfba25f490a..e958630b083b6 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts @@ -1,4 +1,5 @@ import * as cdk from 'aws-cdk-lib'; +import * as ecr from 'aws-cdk-lib/aws-ecr'; import * as ssm from 'aws-cdk-lib/aws-ssm'; import { BaseContainerImage, BaseImage, ContainerInstanceImage } from '../lib'; diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.ts index e7ae747615b18..8fef8d438febb 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.ts @@ -19,6 +19,6 @@ new imagebuilder.ContainerRecipe(stack, 'ContainerRecipe', { ), }); -new integ.IntegTest(app, 'ContainerRecipeTest', { +new integ.IntegTest(app, 'ContainerRecipeTest-Asset', { testCases: [stack], }); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.ts index aca4105a7bf84..110386e2d995c 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.ts @@ -20,6 +20,6 @@ new imagebuilder.ContainerRecipe(stack, 'ContainerRecipe', { dockerfile: imagebuilder.DockerfileData.fromS3(asset.bucket, asset.s3ObjectKey), }); -new integ.IntegTest(app, 'ContainerRecipeTest', { +new integ.IntegTest(app, 'ContainerRecipeTest-S3', { testCases: [stack], }); From 5ca5297e0990e8a068b925d84749b502a7225672 Mon Sep 17 00:00:00 2001 From: Tarun Belani Date: Fri, 21 Nov 2025 06:41:49 -0800 Subject: [PATCH 6/6] Addressed review comments --- .../@aws-cdk/aws-imagebuilder-alpha/README.md | 350 +++++++++--------- .../aws-imagebuilder-alpha/lib/base-image.ts | 5 +- .../lib/image-recipe.ts | 2 +- ...faultTestDeployAssert9DCD2BFD.assets.json} | 4 +- ...ultTestDeployAssert9DCD2BFD.template.json} | 0 ...-recipe-marketplace-base-image.assets.json | 6 +- ...ecipe-marketplace-base-image.template.json | 18 + .../integ.json | 6 +- .../manifest.json | 37 +- .../tree.json | 2 +- ...teg.marketplace-base-image.image-recipe.ts | 7 +- 11 files changed, 233 insertions(+), 204 deletions(-) rename packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/{ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json => ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets.json} (75%) rename packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/{ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json => ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.template.json} (100%) diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/README.md b/packages/@aws-cdk/aws-imagebuilder-alpha/README.md index a37c946280b7d..3455df9e81695 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/README.md +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/README.md @@ -232,6 +232,181 @@ const imageRecipe = new imagebuilder.ImageRecipe(this, 'TaggedImageRecipe', { }); ``` +### Container Recipe + +A container recipe is similar to an image recipe but specifically for container images. It defines the base container +image and components applied to produce the desired configuration for the output container image. Container recipes work +with Docker images from DockerHub, Amazon ECR, or Amazon-managed container images as starting points. + +#### Container Recipe Basic Usage + +Create a container recipe with the required base image and target repository: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'MyContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ) +}); +``` + +#### Container Recipe Base Images + +##### DockerHub Images + +Using public Docker Hub images: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'DockerHubContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ) +}); +``` + +##### ECR Images + +Using images from your own ECR repositories: + +```ts +const sourceRepo = ecr.Repository.fromRepositoryName(this, 'SourceRepo', 'my-base-image'); +const targetRepo = ecr.Repository.fromRepositoryName(this, 'TargetRepo', 'my-container-repo'); + +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromEcr(sourceRepo, '1.0.0'), + targetRepository: imagebuilder.Repository.fromEcr(targetRepo) +}); +``` + +##### ECR Public Images + +Using images from Amazon ECR Public: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrPublicContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', '2023'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ) +}); +``` + +#### Container Recipe Components + +##### Custom Components in Container Recipes + +Add your own components to the container recipe: + +```ts +const customComponent = new imagebuilder.Component(this, 'MyComponent', { + platform: imagebuilder.Platform.LINUX, + data: imagebuilder.ComponentData.fromJsonObject({ + schemaVersion: imagebuilder.ComponentSchemaVersion.V1_0, + phases: [ + { + name: imagebuilder.ComponentPhaseName.BUILD, + steps: [ + { + name: 'install-app', + action: imagebuilder.ComponentAction.EXECUTE_BASH, + inputs: { + commands: ['yum install -y my-container-application'] + } + } + ] + } + ] + }) +}); + +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'ComponentContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + components: [ + { + component: customComponent + } + ] +}); +``` + +##### AWS-Managed Components in Container Recipes + +Use pre-built AWS components: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'AwsManagedContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + components: [ + { + component: imagebuilder.AwsManagedComponent.updateOS(this, 'UpdateOS', { + platform: imagebuilder.Platform.LINUX + }) + }, + { + component: imagebuilder.AwsManagedComponent.awsCliV2(this, 'AwsCli', { + platform: imagebuilder.Platform.LINUX + }) + } + ] +}); +``` + +#### Container Recipe Configuration + +##### Custom Dockerfile + +Provide your own Dockerfile template: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'CustomDockerfileContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + dockerfile: imagebuilder.DockerfileData.fromInline(` +FROM {{{ imagebuilder:parentImage }}} +CMD ["echo", "Hello, world!"] +{{{ imagebuilder:environments }}} +{{{ imagebuilder:components }}} +`) +}); +``` + +##### Instance Configuration + +Configure the build instance: + +```ts +const containerRecipe = new imagebuilder.ContainerRecipe(this, 'InstanceConfigContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr( + ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') + ), + // Custom ECS-optimized AMI for building + instanceImage: imagebuilder.ContainerInstanceImage.fromSsmParameterName( + '/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id' + ), + // Additional storage for build process + instanceBlockDevices: [ + { + deviceName: '/dev/xvda', + volume: ec2.BlockDeviceVolume.ebs(50, { + encrypted: true, + volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3 + }) + } + ] +}); +``` + ### Component A component defines the sequence of steps required to customize an instance during image creation (build component) or @@ -476,181 +651,6 @@ const marketplaceComponent = imagebuilder.AwsMarketplaceComponent.fromAwsMarketp ); ``` -### Container Recipe - -A container recipe is similar to an image recipe but specifically for container images. It defines the base container -image and components applied to produce the desired configuration for the output container image. Container recipes work -with Docker images from DockerHub, Amazon ECR, or Amazon-managed container images as starting points. - -#### Container Recipe Basic Usage - -Create a container recipe with the required base image and target repository: - -```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'MyContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ) -}); -``` - -#### Container Recipe Base Images - -##### DockerHub Images - -Using public Docker Hub images: - -```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'DockerHubContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ) -}); -``` - -##### ECR Images - -Using images from your own ECR repositories: - -```ts -const sourceRepo = ecr.Repository.fromRepositoryName(this, 'SourceRepo', 'my-base-image'); -const targetRepo = ecr.Repository.fromRepositoryName(this, 'TargetRepo', 'my-container-repo'); - -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromEcr(sourceRepo, '1.0.0'), - targetRepository: imagebuilder.Repository.fromEcr(targetRepo) -}); -``` - -##### ECR Public Images - -Using images from Amazon ECR Public: - -```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'EcrPublicContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', '2023'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ) -}); -``` - -#### Container Recipe Components - -##### Custom Components in Container Recipes - -Add your own components to the container recipe: - -```ts -const customComponent = new imagebuilder.Component(this, 'MyComponent', { - platform: imagebuilder.Platform.LINUX, - data: imagebuilder.ComponentData.fromJsonObject({ - schemaVersion: imagebuilder.ComponentSchemaVersion.V1_0, - phases: [ - { - name: imagebuilder.ComponentPhaseName.BUILD, - steps: [ - { - name: 'install-app', - action: imagebuilder.ComponentAction.EXECUTE_BASH, - inputs: { - commands: ['yum install -y my-container-application'] - } - } - ] - } - ] - }) -}); - -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'ComponentContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ), - components: [ - { - component: customComponent - } - ] -}); -``` - -##### AWS-Managed Components in Container Recipes - -Use pre-built AWS components: - -```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'AwsManagedContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ), - components: [ - { - component: imagebuilder.AwsManagedComponent.updateOS(this, 'UpdateOS', { - platform: imagebuilder.Platform.LINUX - }) - }, - { - component: imagebuilder.AwsManagedComponent.awsCliV2(this, 'AwsCli', { - platform: imagebuilder.Platform.LINUX - }) - } - ] -}); -``` - -#### Container Recipe Configuration - -##### Custom Dockerfile - -Provide your own Dockerfile template: - -```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'CustomDockerfileContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ), - dockerfile: imagebuilder.DockerfileData.fromInline(` -FROM {{{ imagebuilder:parentImage }}} -CMD ["echo", "Hello, world!"] -{{{ imagebuilder:environments }}} -{{{ imagebuilder:components }}} -`) -}); -``` - -##### Instance Configuration - -Configure the build instance: - -```ts -const containerRecipe = new imagebuilder.ContainerRecipe(this, 'InstanceConfigContainerRecipe', { - baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), - targetRepository: imagebuilder.Repository.fromEcr( - ecr.Repository.fromRepositoryName(this, 'Repository', 'my-container-repo') - ), - // Custom ECS-optimized AMI for building - instanceImage: imagebuilder.ContainerInstanceImage.fromSsmParameterName( - '/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id' - ), - // Additional storage for build process - instanceBlockDevices: [ - { - deviceName: '/dev/xvda', - volume: ec2.BlockDeviceVolume.ebs(50, { - encrypted: true, - volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3 - }) - } - ] -}); -``` - ### Infrastructure Configuration Infrastructure configuration defines the compute resources and environment settings used during the image building diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts index 64a622e664106..86cafa7489b67 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts @@ -29,7 +29,7 @@ export class BaseImage { * @param parameter The SSM parameter to use as the base image */ public static fromSsmParameter(parameter: ssm.IParameter): BaseImage { - return this.fromSsmParameterName(parameter.parameterArn); + return new BaseImage(`ssm:${parameter.parameterArn}`); } /** @@ -140,7 +140,7 @@ export class ContainerInstanceImage { } /** - * The name of the SSM parameter used to launch the instance for building the container image + * The ARN of the SSM parameter used to launch the instance for building the container image * * @param parameterName The name of the SSM parameter used as the container instance image */ @@ -168,4 +168,3 @@ export class ContainerInstanceImage { this.image = image; } } - diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts index a635dc813460d..7a308b3759c21 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/image-recipe.ts @@ -257,7 +257,7 @@ export class ImageRecipe extends ImageRecipeBase { public static fromImageRecipeAttributes(scope: Construct, id: string, attrs: ImageRecipeAttributes): IImageRecipe { if (!attrs.imageRecipeArn && !attrs.imageRecipeName) { throw new cdk.ValidationError( - 'either imageRecipeArn or imageRecipeName must be provided to import a image recipe', + 'either imageRecipeArn or imageRecipeName must be provided to import an image recipe', scope, ); } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets.json similarity index 75% rename from packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json rename to packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets.json index de53e99c78fe9..9196b08d51f67 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets.json @@ -2,9 +2,9 @@ "version": "48.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { - "displayName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA Template", + "displayName": "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD Template", "source": { - "path": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "path": "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.template.json", "packaging": "file" }, "destinations": { diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.template.json similarity index 100% rename from packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json rename to packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.template.json diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json index ed27efd63eb53..e9f0572c3207a 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.assets.json @@ -1,16 +1,16 @@ { "version": "48.0.0", "files": { - "bf34c2eae6eeafeeb0a1103cd3d55c1509b06980a3c943d21d30022731672b06": { + "f3a2598e17b10fe34ff5d1ef8482c668ea518f64e26ccc8fcbe9b4f8eb152aad": { "displayName": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image Template", "source": { "path": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json", "packaging": "file" }, "destinations": { - "current_account-current_region-525dc300": { + "current_account-current_region-ce3c21b6": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "bf34c2eae6eeafeeb0a1103cd3d55c1509b06980a3c943d21d30022731672b06.json", + "objectKey": "f3a2598e17b10fe34ff5d1ef8482c668ea518f64e26ccc8fcbe9b4f8eb152aad.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json index b236f9e83fa9d..6fc8125493b16 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/aws-cdk-imagebuilder-image-recipe-marketplace-base-image.template.json @@ -9,6 +9,24 @@ } } }, + "Outputs": { + "ImageRecipeVersion": { + "Value": { + "Fn::GetAtt": [ + "ImageRecipe8C789631", + "Version" + ] + } + }, + "ImageRecipeArn": { + "Value": { + "Fn::GetAtt": [ + "ImageRecipe8C789631", + "Arn" + ] + } + } + }, "Parameters": { "BootstrapVersion": { "Type": "AWS::SSM::Parameter::Value", diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json index 15f06095f4344..18548b7ce0688 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/integ.json @@ -1,12 +1,12 @@ { "version": "48.0.0", "testCases": { - "ImageRecipeTest/DefaultTest": { + "ImageRecipeTest-MarketplaceBaseImage/DefaultTest": { "stacks": [ "aws-cdk-imagebuilder-image-recipe-marketplace-base-image" ], - "assertionStack": "ImageRecipeTest/DefaultTest/DeployAssert", - "assertionStackName": "ImageRecipeTestDefaultTestDeployAssertFD6737FA" + "assertionStack": "ImageRecipeTest-MarketplaceBaseImage/DefaultTest/DeployAssert", + "assertionStackName": "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD" } }, "minimumCliVersion": "2.1027.0" diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json index 36a17a28f8744..f7122278cab13 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/manifest.json @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/bf34c2eae6eeafeeb0a1103cd3d55c1509b06980a3c943d21d30022731672b06.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/f3a2598e17b10fe34ff5d1ef8482c668ea518f64e26ccc8fcbe9b4f8eb152aad.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -37,10 +37,19 @@ "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource": [ { "type": "aws:cdk:logicalId", - "data": "ImageRecipe8C789631", - "trace": [ - "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" - ] + "data": "ImageRecipe8C789631" + } + ], + "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipeVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipeVersion" + } + ], + "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipeArn": [ + { + "type": "aws:cdk:logicalId", + "data": "ImageRecipeArn" } ], "/aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion": [ @@ -58,19 +67,19 @@ }, "displayName": "aws-cdk-imagebuilder-image-recipe-marketplace-base-image" }, - "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets": { + "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets": { "type": "cdk:asset-manifest", "properties": { - "file": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets.json", + "file": "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" } }, - "ImageRecipeTestDefaultTestDeployAssertFD6737FA": { + "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD": { "type": "aws:cloudformation:stack", "environment": "aws://unknown-account/unknown-region", "properties": { - "templateFile": "ImageRecipeTestDefaultTestDeployAssertFD6737FA.template.json", + "templateFile": "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.template.json", "terminationProtection": false, "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", @@ -79,7 +88,7 @@ "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ - "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets" ], "lookupRole": { "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", @@ -88,23 +97,23 @@ } }, "dependencies": [ - "ImageRecipeTestDefaultTestDeployAssertFD6737FA.assets" + "ImageRecipeTestMarketplaceBaseImageDefaultTestDeployAssert9DCD2BFD.assets" ], "metadata": { - "/ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + "/ImageRecipeTest-MarketplaceBaseImage/DefaultTest/DeployAssert/BootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "BootstrapVersion" } ], - "/ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + "/ImageRecipeTest-MarketplaceBaseImage/DefaultTest/DeployAssert/CheckBootstrapVersion": [ { "type": "aws:cdk:logicalId", "data": "CheckBootstrapVersion" } ] }, - "displayName": "ImageRecipeTest/DefaultTest/DeployAssert" + "displayName": "ImageRecipeTest-MarketplaceBaseImage/DefaultTest/DeployAssert" }, "Tree": { "type": "cdk:tree", diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json index 8b583edd58e20..2cdd0175cb6c4 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.js.snapshot/tree.json @@ -1 +1 @@ -{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-marketplace-base-image":{"id":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image-imagerecipe-b40d66c5","parentImage":"abcfcbaf-134e-4639-a7b4-fd285b9fcf0a","version":"1.0.x"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest":{"id":"ImageRecipeTest","path":"ImageRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}}}}} \ No newline at end of file +{"version":"tree-0.1","tree":{"id":"App","path":"","constructInfo":{"fqn":"aws-cdk-lib.App","version":"0.0.0"},"children":{"aws-cdk-imagebuilder-image-recipe-marketplace-base-image":{"id":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"ImageRecipe":{"id":"ImageRecipe","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ImageRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnImageRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ImageRecipe","aws:cdk:cloudformation:props":{"name":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image-imagerecipe-b40d66c5","parentImage":"abcfcbaf-134e-4639-a7b4-fd285b9fcf0a","version":"1.0.x"}}}}},"ImageRecipeVersion":{"id":"ImageRecipeVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipeVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"ImageRecipeArn":{"id":"ImageRecipeArn","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/ImageRecipeArn","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-image-recipe-marketplace-base-image/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ImageRecipeTest-MarketplaceBaseImage":{"id":"ImageRecipeTest-MarketplaceBaseImage","path":"ImageRecipeTest-MarketplaceBaseImage","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ImageRecipeTest-MarketplaceBaseImage/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ImageRecipeTest-MarketplaceBaseImage/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ImageRecipeTest-MarketplaceBaseImage/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ImageRecipeTest-MarketplaceBaseImage/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ImageRecipeTest-MarketplaceBaseImage/DefaultTest/DeployAssert/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}}}}}},"Tree":{"id":"Tree","path":"Tree","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}}}}} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts index 96f7d6ecf5c24..e84eaca2be6af 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.marketplace-base-image.image-recipe.ts @@ -5,10 +5,13 @@ import * as imagebuilder from '../lib'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-image-recipe-marketplace-base-image'); -new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { +const imageRecipe = new imagebuilder.ImageRecipe(stack, 'ImageRecipe', { baseImage: imagebuilder.BaseImage.fromMarketplaceProductId('abcfcbaf-134e-4639-a7b4-fd285b9fcf0a'), }); -new integ.IntegTest(app, 'ImageRecipeTest', { +new cdk.CfnOutput(stack, 'ImageRecipeVersion', { value: imageRecipe.imageRecipeVersion }); +new cdk.CfnOutput(stack, 'ImageRecipeArn', { value: imageRecipe.imageRecipeArn }); + +new integ.IntegTest(app, 'ImageRecipeTest-MarketplaceBaseImage', { testCases: [stack], });