diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/README.md b/packages/@aws-cdk/aws-imagebuilder-alpha/README.md index 9eb9853db3a7b..2e66f1422b64a 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/README.md +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/README.md @@ -36,6 +36,181 @@ 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 + +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 diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/awslint.json b/packages/@aws-cdk/aws-imagebuilder-alpha/awslint.json index c5c5908d695b0..e4d9db5467b58 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/awslint.json +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/awslint.json @@ -1,5 +1,6 @@ { "exclude": [ - "props-no-arn-refs:@aws-cdk/aws-imagebuilder-alpha.InfrastructureConfigurationProps.ec2InstanceHostResourceGroupArn" + "props-no-arn-refs:@aws-cdk/aws-imagebuilder-alpha.InfrastructureConfigurationProps.ec2InstanceHostResourceGroupArn", + "no-unused-type:@aws-cdk/aws-imagebuilder-alpha.ContainerType" ] } diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts new file mode 100644 index 0000000000000..c0992191ffc1f --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/base-image.ts @@ -0,0 +1,110 @@ +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 BaseContainerImage { + /** + * The DockerHub image to use as the base image in a container recipe + * + * @param repository The DockerHub repository where the base image resides in + * @param tag The tag of the base image in the DockerHub repository + */ + public static fromDockerHub(repository: string, tag: string): BaseContainerImage { + return new BaseContainerImage(`${repository}:${tag}`); + } + + /** + * The ECR container image to use as the base image in a container recipe + * + * @param repository The ECR repository where the base image resides in + * @param tag The tag of the base image in the ECR repository + */ + public static fromEcr(repository: ecr.IRepository, tag: string): BaseContainerImage { + return new BaseContainerImage(repository.repositoryUriForTag(tag)); + } + + /** + * The ECR public container image to use as the base image in a container recipe + * + * @param registryAlias The alias of the ECR public registry where the base image resides in + * @param repositoryName The name of the ECR public repository, where the base image resides in + * @param tag The tag of the base image in the ECR public repository + */ + public static fromEcrPublic(registryAlias: string, repositoryName: string, tag: string): BaseContainerImage { + return new BaseContainerImage(`public.ecr.aws/${registryAlias}/${repositoryName}:${tag}`); + } + + /** + * The string value of the base image to use in a container recipe. This can be an EC2 Image Builder image ARN, + * an ECR or ECR public image, or a container URI sourced from a third-party container registry such as DockerHub. + * + * @param baseContainerImageString The base image as a direct string value + */ + public static fromString(baseContainerImageString: string): BaseContainerImage { + return new BaseContainerImage(baseContainerImageString); + } + + /** + * The rendered base image to use + **/ + public readonly image: string; + + protected constructor(image: string) { + this.image = image; + } +} + +/** + * Represents a container instance image that is used to launch the instance used for building the container for an + * EC2 Image Builder container build. + */ +export class ContainerInstanceImage { + /** + * The AMI ID to use to launch the instance for building the container image + * + * @param amiId The AMI ID to use as the container instance image + */ + public static fromAmiId(amiId: string): ContainerInstanceImage { + return new ContainerInstanceImage(amiId); + } + + /** + * The SSM parameter to use to launch the instance for building the container image + * + * @param parameter The SSM parameter to use as the container instance image + */ + public static fromSsmParameter(parameter: ssm.IStringParameter): ContainerInstanceImage { + return new ContainerInstanceImage(`ssm:${parameter.parameterArn}`); + } + + /** + * The name 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 + */ + public static fromSsmParameterName(parameterName: string): ContainerInstanceImage { + return new ContainerInstanceImage(`ssm:${parameterName}`); + } + + /** + * The string value of the container instance image to use in a container recipe. This can either be: + * - an SSM parameter reference, prefixed with `ssm:` and followed by the parameter name or ARN + * - an AMI ID + * + * @param containerInstanceImageString The container instance image as a direct string value + */ + public static fromString(containerInstanceImageString: string): ContainerInstanceImage { + return new ContainerInstanceImage(containerInstanceImageString); + } + + /** + * The rendered container instance image to use + **/ + public readonly image: string; + + protected constructor(image: string) { + this.image = image; + } +} diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/container-recipe.ts new file mode 100644 index 0000000000000..5579f8092d7ef --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/container-recipe.ts @@ -0,0 +1,643 @@ +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 { CfnContainerRecipe } from 'aws-cdk-lib/aws-imagebuilder'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as s3 from 'aws-cdk-lib/aws-s3'; +import * as s3assets from 'aws-cdk-lib/aws-s3-assets'; +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 { OSVersion } from './os-version'; +import { ComponentConfiguration, IRecipeBase } from './recipe-base'; + +const CONTAINER_RECIPE_SYMBOL = Symbol.for('@aws-cdk/aws-imagebuilder-alpha.ContainerRecipe'); + +/** + * Represents the latest version of a container 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'; + +/** + * The default version to use in the container 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 Container Recipe. + */ +export interface IContainerRecipe extends IRecipeBase { + /** + * The ARN of the container recipe + * + * @attribute + */ + readonly containerRecipeArn: string; + + /** + * The name of the container recipe + * + * @attribute + */ + readonly containerRecipeName: string; + + /** + * The version of the container recipe + * + * @attribute + */ + readonly containerRecipeVersion: string; +} + +/** + * Properties for creating a Container Recipe resource + */ +export interface ContainerRecipeProps { + /** + * The base image for customizations specified in the container recipe. + */ + readonly baseImage: BaseContainerImage; + + /** + * The container repository where the output container image is stored. + */ + readonly targetRepository: Repository; + + /** + * The name of the container recipe. + * + * @default a name is generated + */ + readonly containerRecipeName?: string; + + /** + * The version of the container recipe. + * + * @default 1.0.x + */ + readonly containerRecipeVersion?: string; + + /** + * The description of the container recipe. + * + * @default None + */ + readonly description?: string; + + /** + * The dockerfile template used to build the container image. + * + * @default - a standard dockerfile template will be generated to pull the base image, perform environment setup, and + * run all components in the recipe + */ + readonly dockerfile?: DockerfileData; + + /** + * The list of component configurations to apply in the image build. + * + * @default None + */ + readonly components?: ComponentConfiguration[]; + + /** + * The KMS key used to encrypt the dockerfile template. + * + * @default None + */ + readonly kmsKey?: kms.IKey; + + /** + * 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; + + /** + * The operating system (OS) version of the base image. + * + * @default - Image Builder will determine the OS version of the base image, if sourced from a third-party container + * registry. Otherwise, the OS version of the base image is required. + */ + readonly osVersion?: OSVersion; + + /** + * The block devices to attach to the instance used for building, testing, and distributing the container image. + * + * @default the block devices of the instance image will be used + */ + readonly instanceBlockDevices?: ec2.BlockDevice[]; + + /** + * The image to use to launch the instance used for building, testing, and distributing the container image. + * + * @default Image Builder will use the appropriate ECS-optimized AMI + */ + readonly instanceImage?: ContainerInstanceImage; + + /** + * The tags to apply to the container recipe + * + * @default None + */ + readonly tags?: { [key: string]: string }; +} + +/** + * The type of the container being used in the container recipe + */ +export enum ContainerType { + /** + * Indicates the container recipe uses a Docker container + */ + DOCKER = 'DOCKER', +} + +/** + * The rendered Dockerfile value, for use in CloudFormation. + * - For inline dockerfiles, dockerfileTemplateData is the Dockerfile template text + * - For S3-backed dockerfiles, dockerfileTemplateUri is the S3 URL + */ +export interface DockerfileTemplateConfig { + /** + * The rendered Dockerfile data, for use in CloudFormation + * + * @default - none if dockerfileTemplateUri is set + */ + readonly dockerfileTemplateData?: string; + + /** + * The rendered Dockerfile URI, for use in CloudFormation + * + * @default - none if dockerfileTemplateData is set + */ + readonly dockerfileTemplateUri?: string; +} + +/** + * Helper class for referencing and uploading dockerfile data for the container recipe + */ +export abstract class DockerfileData { + /** + * Uploads dockerfile data from a local file to S3 to use as the dockerfile data + * + * @param scope The construct scope + * @param id Identifier of the construct + * @param path The local path to the dockerfile data file + * @param options S3 asset upload options + */ + public static fromAsset( + scope: Construct, + id: string, + path: string, + options: s3assets.AssetOptions = {}, + ): S3DockerfileData { + const asset = new s3assets.Asset(scope, id, { ...options, path }); + return new S3DockerfileDataFromAsset(asset); + } + + /** + * References dockerfile data from a pre-existing S3 object + * + * @param bucket The S3 bucket where the dockerfile data is stored + * @param key The S3 key of the dockerfile data file + */ + public static fromS3(bucket: s3.IBucket, key: string): S3DockerfileData { + return new S3DockerfileDataFromBucketKey(bucket, key); + } + + /** + * Uses an inline string as the dockerfile data + * + * @param data An inline string representing the dockerfile data + */ + public static fromInline(data: string): DockerfileData { + return new InlineDockerfileData(data); + } + + /** + * The rendered Dockerfile value, for use in CloudFormation. + * - For inline dockerfiles, dockerfileTemplateData is the Dockerfile template text + * - For S3-backed dockerfiles, dockerfileTemplateUri is the S3 URL + */ + abstract render(): DockerfileTemplateConfig; +} + +/** + * Helper class for S3-based dockerfile data references, containing additional permission grant methods on the S3 object + */ +export abstract class S3DockerfileData extends DockerfileData { + protected readonly bucket: s3.IBucket; + protected readonly key: string; + + protected constructor(bucket: s3.IBucket, key: string) { + super(); + + this.bucket = bucket; + this.key = key; + } + + /** + * The rendered Dockerfile S3 URL, for use in CloudFormation + */ + public render(): DockerfileTemplateConfig { + return { dockerfileTemplateUri: this.bucket.s3UrlForObject(this.key) }; + } + + /** + * Grant put permissions to the given grantee for the dockerfile data in S3 + * + * @param grantee The principal + */ + public grantPut(grantee: iam.IGrantable): iam.Grant { + return this.bucket.grantPut(grantee, this.key); + } + + /** + * Grant read permissions to the given grantee for the dockerfile data in S3 + * + * @param grantee The principal + */ + public grantRead(grantee: iam.IGrantable): iam.Grant { + return this.bucket.grantRead(grantee, this.key); + } +} + +class InlineDockerfileData extends DockerfileData { + protected readonly data: string; + + public constructor(data: string) { + super(); + + this.data = data; + } + + /** + * The rendered Dockerfile text, for use in CloudFormation + */ + public render(): DockerfileTemplateConfig { + return { dockerfileTemplateData: this.data }; + } +} + +class S3DockerfileDataFromBucketKey extends S3DockerfileData { + public constructor(bucket: s3.IBucket, key: string) { + super(bucket, key); + } +} + +class S3DockerfileDataFromAsset extends S3DockerfileData { + public constructor(asset: s3assets.Asset) { + super(asset.bucket, asset.s3ObjectKey); + } +} + +/** + * Properties for an EC2 Image Builder container recipe + */ +export interface ContainerRecipeAttributes { + /** + * The ARN of the container recipe + * + * @default - derived from containerRecipeName + */ + readonly containerRecipeArn?: string; + + /** + * The name of the container recipe + * + * @default - derived from containerRecipeArn + */ + readonly containerRecipeName?: string; + + /** + * The version of the container recipe + * + * @default - derived from containerRecipeArn. if a containerRecipeName is provided, the latest version, x.x.x, will + * be used. + */ + readonly containerRecipeVersion?: string; +} + +/** + * A new or imported Container Recipe + */ +export abstract class ContainerRecipeBase extends cdk.Resource implements IContainerRecipe { + /** + * The ARN of the container recipe + */ + abstract readonly containerRecipeArn: string; + + /** + * The name of the container recipe + */ + abstract readonly containerRecipeName: string; + + /** + * The version of the container recipe + */ + abstract readonly containerRecipeVersion: string; + + /** + * Grant custom actions to the given grantee for the container 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.containerRecipeArn], + scope: this, + }); + } + + /** + * Grant read permissions to the given grantee for the container recipe + * + * @param grantee The principal + */ + public grantRead(grantee: iam.IGrantable): iam.Grant { + return this.grant(grantee, 'imagebuilder:GetContainerRecipe'); + } + + /** + * Indicates whether the recipe is a Container Recipe + * + * @internal + */ + public _isContainerRecipe(): this is IContainerRecipe { + return true; + } +} + +/** + * Represents an EC2 Image Builder Container Recipe. + * + * @see https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-recipes.html + */ +@propertyInjectable +export class ContainerRecipe extends ContainerRecipeBase { + /** Uniquely identifies this class. */ + public static readonly PROPERTY_INJECTION_ID: string = '@aws-cdk.aws-imagebuilder-alpha.ContainerRecipe'; + + /** + * Import an existing container recipe given its ARN. + */ + public static fromContainerRecipeArn(scope: Construct, id: string, containerRecipeArn: string): IContainerRecipe { + return this.fromContainerRecipeAttributes(scope, id, { containerRecipeArn }); + } + + /** + * Import the latest version of an existing container 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 fromContainerRecipeName(scope: Construct, id: string, containerRecipeName: string): IContainerRecipe { + return this.fromContainerRecipeAttributes(scope, id, { containerRecipeName }); + } + + /** + * Import an existing container recipe by providing its attributes. If the container 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 fromContainerRecipeAttributes( + scope: Construct, + id: string, + attrs: ContainerRecipeAttributes, + ): IContainerRecipe { + if (!attrs.containerRecipeArn && !attrs.containerRecipeName) { + throw new cdk.ValidationError( + 'either either containerRecipeArn or containerRecipeName must be provided to import a container recipe', + scope, + ); + } + + const containerRecipeArn = + attrs.containerRecipeArn ?? + cdk.Stack.of(scope).formatArn({ + service: 'imagebuilder', + resource: 'container-recipe', + resourceName: `${attrs.containerRecipeName}/${attrs.containerRecipeVersion ?? LATEST_VERSION}`, + }); + + const [containerRecipeName, containerRecipeVersion] = (() => { + if (attrs.containerRecipeName) { + return [attrs.containerRecipeName, attrs.containerRecipeVersion ?? LATEST_VERSION]; + } + + const containerRecipeNameVersion = cdk.Stack.of(scope).splitArn( + containerRecipeArn, + cdk.ArnFormat.SLASH_RESOURCE_NAME, + ).resourceName!; + + const containerRecipeNameVersionSplit = cdk.Fn.split('/', containerRecipeNameVersion); + return [cdk.Fn.select(0, containerRecipeNameVersionSplit), cdk.Fn.select(1, containerRecipeNameVersionSplit)]; + })(); + + class Import extends ContainerRecipeBase { + public readonly containerRecipeArn = containerRecipeArn; + public readonly containerRecipeName = containerRecipeName; + public readonly containerRecipeVersion = containerRecipeVersion; + } + + return new Import(scope, id); + } + + /** + * Return whether the given object is a ContainerRecipe. + */ + public static isContainerRecipe(x: any): x is ContainerRecipe { + return x !== null && typeof x === 'object' && CONTAINER_RECIPE_SYMBOL in x; + } + + /** + * The ARN of the container recipe + */ + public readonly containerRecipeArn: string; + + /** + * The name of the container recipe + */ + public readonly containerRecipeName: string; + + /** + * The version of the container recipe + */ + public readonly containerRecipeVersion: string; + + private readonly instanceBlockDevices: ec2.BlockDevice[] = []; + + public constructor(scope: Construct, id: string, props: ContainerRecipeProps) { + super(scope, id, { + physicalName: + props.containerRecipeName ?? + cdk.Lazy.string({ + produce: () => + cdk.Names.uniqueResourceName(this, { + maxLength: 128, + separator: '-', + allowedSpecialCharacters: '-', + }).toLowerCase(), // Enforce lowercase for the auto-generated fallback + }), + }); + + Object.defineProperty(this, CONTAINER_RECIPE_SYMBOL, { value: true }); + + this.validateContainerRecipeName(); + + this.addInstanceBlockDevice(...(props.instanceBlockDevices ?? [])); + + const components: CfnContainerRecipe.ComponentConfigurationProperty[] | undefined = props.components?.map( + (component) => ({ + componentArn: component.component.componentArn, + ...(component.parameters && { + parameters: Object.entries(component.parameters).map( + ([name, param]): CfnContainerRecipe.ComponentParameterProperty => ({ + name, + value: param.value, + }), + ), + }), + }), + ); + + const dockerfile = + props.dockerfile ?? + DockerfileData.fromInline( + 'FROM {{{ imagebuilder:parentImage }}}\n{{{ imagebuilder:environments }}}\n{{{ imagebuilder:components }}}', + ); + + const containerRecipeVersion = props.containerRecipeVersion ?? DEFAULT_RECIPE_VERSION; + const containerRecipe = new CfnContainerRecipe(this, 'Resource', { + name: this.physicalName, + version: containerRecipeVersion, + description: props.description, + parentImage: props.baseImage.image, + containerType: ContainerType.DOCKER, + targetRepository: { + repositoryName: props.targetRepository.repositoryName, + service: props.targetRepository.service, + }, + platformOverride: props.osVersion?.platform, + imageOsVersionOverride: props.osVersion?.osVersion, + kmsKeyId: props.kmsKey?.keyArn, + instanceConfiguration: cdk.Lazy.any({ produce: () => this.buildInstanceConfiguration(props) }), + workingDirectory: props.workingDirectory, + tags: props.tags, + ...dockerfile.render(), + ...(components?.length && { components }), + }); + + this.containerRecipeName = this.getResourceNameAttribute(containerRecipe.attrName); + this.containerRecipeArn = this.getResourceArnAttribute(containerRecipe.attrArn, { + service: 'imagebuilder', + resource: 'container-recipe', + resourceName: `${this.physicalName}/${containerRecipeVersion}`, + }); + this.containerRecipeVersion = containerRecipe.getAtt('Version').toString(); + } + + /** + * Adds block devices to attach to the instance used for building, testing, and distributing the container image. + * + * @param instanceBlockDevices - The list of block devices to attach + */ + public addInstanceBlockDevice(...instanceBlockDevices: ec2.BlockDevice[]): void { + this.instanceBlockDevices.push(...instanceBlockDevices); + } + + /** + * Renders the block devices provided as input to the construct, into the block device mapping structure that + * CfnContainerRecipe expects to receive. + * + * This is rendered at synthesis time, as users can add additional block devices with `addInstanceBlockDevice`, after + * the construct has been instantiated. + * + * @private + */ + private renderBlockDevices(): CfnContainerRecipe.InstanceBlockDeviceMappingProperty[] | undefined { + const blockDevices = this.instanceBlockDevices.map( + (blockDevice): CfnContainerRecipe.InstanceBlockDeviceMappingProperty => { + const ebsDevice = blockDevice.volume.ebsDevice; + const ebs: CfnContainerRecipe.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; + } + + /** + * Generates the instance configuration property into the `InstanceConfiguration` type in the CloudFormation L1 + * definition. + * + * @param props The props passed as input to the construct + * @private + */ + private buildInstanceConfiguration( + props: ContainerRecipeProps, + ): CfnContainerRecipe.InstanceConfigurationProperty | undefined { + const blockDevices = this.renderBlockDevices(); + + const instanceConfiguration: CfnContainerRecipe.InstanceConfigurationProperty = { + ...(blockDevices?.length && { blockDeviceMappings: blockDevices }), + ...(props.instanceImage !== undefined && { image: props.instanceImage.image }), + }; + + return Object.keys(instanceConfiguration).length ? instanceConfiguration : undefined; + } + + private validateContainerRecipeName() { + 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 containerRecipeName cannot be longer than 128 characters, got: '${this.physicalName}'`, + this, + ); + } + + if (this.physicalName.includes(' ')) { + throw new cdk.ValidationError(`the containerRecipeName cannot contain spaces, got: '${this.physicalName}'`, this); + } + + if (this.physicalName.includes('_')) { + throw new cdk.ValidationError( + `the containerRecipeName cannot contain underscores, got: '${this.physicalName}'`, + this, + ); + } + + if (this.physicalName !== this.physicalName.toLowerCase()) { + throw new cdk.ValidationError(`the containerRecipeName must be lowercase, got: '${this.physicalName}'`, this); + } + } +} diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/distribution-configuration.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/distribution-configuration.ts index 8cc35baa3a364..a6396526cc187 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/distribution-configuration.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/distribution-configuration.ts @@ -588,6 +588,17 @@ export class DistributionConfiguration extends DistributionConfigurationBase { } } + /** + * Renders the AMI and container distributions provided as input to the construct, into the `Distribution[]` structure + * that CfnDistributionConfiguration expects to receive. Distributions provided to CfnDistributionConfiguration must + * map to a unique region per entry in the list - this render function also handles combining AMI and container + * distributions in the same region into a single entry. + * + * This is rendered at synthesis time, as users can add additional AMI and container distributions with + * `addAmiDistributions` and `addContainerDistributions`, after the construct has been instantiated. + * + * @private + */ private renderDistributions(): CfnDistributionConfiguration.DistributionProperty[] { if ( !Object.keys(this.amiDistributionsByRegion).length && diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts index 8ce5becc539dd..1bca16e8ef708 100644 --- a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts @@ -1,7 +1,10 @@ // AWS::ImageBuilder CloudFormation Resources: export * from './component'; +export * from './container-recipe'; export * from './distribution-configuration'; export * from './infrastructure-configuration'; +export * from './base-image'; export * from './os-version'; +export * from './recipe-base'; diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts new file mode 100644 index 0000000000000..866cb3edf75e7 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/lib/recipe-base.ts @@ -0,0 +1,72 @@ +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'; + +/** + * The parameter value for a component parameter + */ +export class ComponentParameterValue { + /** + * The value of the parameter as a string + * + * @param value The string value of the parameter + */ + public static fromString(value: string): ComponentParameterValue { + return new ComponentParameterValue([value]); + } + + /** + * The rendered parameter value + */ + public readonly value: string[]; + + protected constructor(value: string[]) { + this.value = value; + } +} + +/** + * Configuration details for a component, to include in a recipe + */ +export interface ComponentConfiguration { + /** + * The component to execute as part of the image build + */ + readonly component: IComponent; + + /** + * The parameters to use when executing the component + * + * @default - no parameters. if the component contains parameters, their default values will be used. otherwise, any + * required parameters that are not included will result in a build failure + */ + readonly parameters?: { [name: string]: ComponentParameterValue }; +} + +/** + * A base interface for EC2 Image Builder recipes + */ +export interface IRecipeBase extends cdk.IResource { + /** + * Grant custom actions to the given grantee for the recipe + * + * @param grantee The principal + * @param actions The list of actions + */ + grant(grantee: iam.IGrantable, ...actions: string[]): iam.Grant; + + /** + * Grant read permissions to the given grantee for the recipe + * + * @param grantee The principal + */ + grantRead(grantee: iam.IGrantable): iam.Grant; + + /** + * Indicates whether the recipe is a Container Recipe + * + * @internal + */ + _isContainerRecipe(): this is IContainerRecipe; +} diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/assets/Dockerfile b/packages/@aws-cdk/aws-imagebuilder-alpha/test/assets/Dockerfile new file mode 100644 index 0000000000000..2cb8966fbc242 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/assets/Dockerfile @@ -0,0 +1,4 @@ +FROM {{{ imagebuilder:parentImage }}} +CMD ["echo", "Hello, world!"] +{{{ imagebuilder:environments }}} +{{{ imagebuilder:components }}} 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 new file mode 100644 index 0000000000000..44ac6269ddf8e --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/base-image.test.ts @@ -0,0 +1,79 @@ +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'; + +describe('Base Container 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 container base image for a dockerhub image', () => { + const baseImage = BaseContainerImage.fromDockerHub('amazonlinux', 'latest'); + expect(baseImage.image).toEqual('amazonlinux:latest'); + }); + + test('should return the correct container base image for an ECR image', () => { + const baseImage = BaseContainerImage.fromEcr( + ecr.Repository.fromRepositoryName(stack, 'BaseImageRepo', 'base-image-repo'), + 'latest', + ); + expect(stack.resolve(baseImage.image)).toEqual({ + 'Fn::Join': ['', ['123456789012.dkr.ecr.us-east-1.', { Ref: 'AWS::URLSuffix' }, '/base-image-repo:latest']], + }); + }); + + test('should return the correct container base image for an ECR public image', () => { + const baseImage = BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'); + expect(baseImage.image).toEqual('public.ecr.aws/amazonlinux/amazonlinux:latest'); + }); + + test('should return the correct container base image for a generic string', () => { + const baseImage = BaseContainerImage.fromString('base-image'); + expect(baseImage.image).toEqual('base-image'); + }); +}); + +describe('Container Instance 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 container instance image for an AMI ID', () => { + const containerInstanceImage = ContainerInstanceImage.fromAmiId('ami-12345678'); + expect(containerInstanceImage.image).toEqual('ami-12345678'); + }); + + test('should return the correct container instance image for an SSM parameter', () => { + const containerInstanceImage = ContainerInstanceImage.fromSsmParameter( + ssm.StringParameter.fromStringParameterAttributes(stack, 'Parameter', { + parameterName: '/imagebuilder/ami', + forceDynamicReference: true, + }), + ); + expect(stack.resolve(containerInstanceImage.image)).toEqual({ + 'Fn::Join': [ + '', + ['ssm:arn:', { Ref: 'AWS::Partition' }, ':ssm:us-east-1:123456789012:parameter/imagebuilder/ami'], + ], + }); + }); + + test('should return the correct container instance image for an SSM parameter name', () => { + const containerInstanceImage = ContainerInstanceImage.fromSsmParameterName('/imagebuilder/ami'); + expect(containerInstanceImage.image).toEqual('ssm:/imagebuilder/ami'); + }); + + test('should return the correct container instance image for a generic string', () => { + const baseImage = ContainerInstanceImage.fromString('container-instance-image'); + expect(baseImage.image).toEqual('container-instance-image'); + }); +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/container-recipe.test.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/container-recipe.test.ts new file mode 100644 index 0000000000000..db76bcee6e0ef --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/container-recipe.test.ts @@ -0,0 +1,671 @@ +import * as path from 'path'; +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 ecr from 'aws-cdk-lib/aws-ecr'; +import * as iam from 'aws-cdk-lib/aws-iam'; +import * as kms from 'aws-cdk-lib/aws-kms'; +import * as s3 from 'aws-cdk-lib/aws-s3'; +import { + AwsManagedComponent, + BaseContainerImage, + Component, + ComponentParameterValue, + ContainerInstanceImage, + ContainerRecipe, + DockerfileData, + IRecipeBase, + OSVersion, + Platform, + Repository, +} from '../lib'; + +describe('Container 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 containerRecipe = ContainerRecipe.fromContainerRecipeName( + stack, + 'ContainerRecipe', + 'imported-container-recipe-by-name', + ); + + expect(stack.resolve(containerRecipe.containerRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:123456789012:container-recipe/imported-container-recipe-by-name/x.x.x', + ], + ], + }); + expect(containerRecipe.containerRecipeName).toEqual('imported-container-recipe-by-name'); + expect(containerRecipe.containerRecipeVersion).toEqual('x.x.x'); + expect((containerRecipe as IRecipeBase)._isContainerRecipe()).toBeTruthy(); + }); + + test('imported by name as an unresolved token', () => { + const containerRecipe = ContainerRecipe.fromContainerRecipeName( + stack, + 'ContainerRecipe', + `test-container-recipe-${stack.partition}`, + ); + + expect(stack.resolve(containerRecipe.containerRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:123456789012:container-recipe/test-container-recipe-', + { Ref: 'AWS::Partition' }, + '/x.x.x', + ], + ], + }); + expect(stack.resolve(containerRecipe.containerRecipeName)).toEqual({ + 'Fn::Join': ['', ['test-container-recipe-', { Ref: 'AWS::Partition' }]], + }); + expect(containerRecipe.containerRecipeVersion).toEqual('x.x.x'); + }); + + test('imported by arn', () => { + const containerRecipe = ContainerRecipe.fromContainerRecipeArn( + stack, + 'ContainerRecipe', + 'arn:aws:imagebuilder:us-east-1:123456789012:container-recipe/imported-container-recipe-by-arn/1.2.3', + ); + + expect(stack.resolve(containerRecipe.containerRecipeArn)).toEqual( + 'arn:aws:imagebuilder:us-east-1:123456789012:container-recipe/imported-container-recipe-by-arn/1.2.3', + ); + expect(containerRecipe.containerRecipeName).toEqual('imported-container-recipe-by-arn'); + expect(containerRecipe.containerRecipeVersion).toEqual('1.2.3'); + }); + + test('imported by arn as an unresolved token', () => { + const containerRecipe = ContainerRecipe.fromContainerRecipeArn( + stack, + 'ContainerRecipe', + `arn:aws:imagebuilder:us-east-1:123456789012:container-recipe/test-container-recipe-${stack.partition}/1.2.3`, + ); + + expect(stack.resolve(containerRecipe.containerRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:aws:imagebuilder:us-east-1:123456789012:container-recipe/test-container-recipe-', + { Ref: 'AWS::Partition' }, + '/1.2.3', + ], + ], + }); + expect(stack.resolve(containerRecipe.containerRecipeName)).toEqual({ + 'Fn::Select': [ + 0, + { + 'Fn::Split': ['/', { 'Fn::Join': ['', ['test-container-recipe-', { Ref: 'AWS::Partition' }, '/1.2.3']] }], + }, + ], + }); + expect(stack.resolve(containerRecipe.containerRecipeVersion)).toEqual({ + 'Fn::Select': [ + 1, + { + 'Fn::Split': ['/', { 'Fn::Join': ['', ['test-container-recipe-', { Ref: 'AWS::Partition' }, '/1.2.3']] }], + }, + ], + }); + }); + + test('imported by attributes', () => { + const containerRecipe = ContainerRecipe.fromContainerRecipeAttributes(stack, 'ContainerRecipe', { + containerRecipeName: 'imported-container-recipe-by-attributes', + containerRecipeVersion: '1.2.3', + }); + + expect(stack.resolve(containerRecipe.containerRecipeArn)).toEqual({ + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':imagebuilder:us-east-1:123456789012:container-recipe/imported-container-recipe-by-attributes/1.2.3', + ], + ], + }); + expect(containerRecipe.containerRecipeName).toEqual('imported-container-recipe-by-attributes'); + expect(containerRecipe.containerRecipeVersion).toEqual('1.2.3'); + }); + + test('with all parameters', () => { + const containerRecipe = new ContainerRecipe(stack, 'ContainerRecipe', { + containerRecipeName: 'test-container-recipe', + containerRecipeVersion: '1.2.3', + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + description: 'A test container recipe', + dockerfile: DockerfileData.fromInline(`FROM {{{ imagebuilder:parentImage }}} +CMD ["echo", "Hello, world!"] +{{{ imagebuilder:environments }}} +{{{ imagebuilder:components }}}`), + kmsKey: kms.Key.fromKeyArn( + stack, + 'ComponentKey', + stack.formatArn({ service: 'kms', resource: 'key', resourceName: '1234abcd-12ab-34cd-56ef-1234567890ab' }), + ), + 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'), + }, + }, + ], + workingDirectory: '/var/tmp', + osVersion: OSVersion.custom(Platform.LINUX, 'Custom OS'), + instanceImage: ContainerInstanceImage.fromSsmParameterName( + '/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id', + ), + instanceBlockDevices: [ + { + mappingEnabled: false, + deviceName: '/dev/sda1', + volume: ec2.BlockDeviceVolume.ephemeral(0), + }, + ], + tags: { + key1: 'value1', + key2: 'value2', + }, + }); + + containerRecipe.addInstanceBlockDevice( + { + 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(ContainerRecipe.isContainerRecipe(containerRecipe as unknown)).toBeTruthy(); + expect(ContainerRecipe.isContainerRecipe('ContainerRecipe')).toBeFalsy(); + expect((containerRecipe as IRecipeBase)._isContainerRecipe()).toBeTruthy(); + + Template.fromStack(stack).templateMatches({ + Resources: { + ContainerRecipe8A7CC9ED: Match.objectEquals({ + Type: 'AWS::ImageBuilder::ContainerRecipe', + Properties: { + 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'] }, + ], + }, + ], + ContainerType: 'DOCKER', + Description: 'A test container recipe', + DockerfileTemplateData: + 'FROM {{{ imagebuilder:parentImage }}}\nCMD ["echo", "Hello, world!"]\n{{{ imagebuilder:environments }}}\n{{{ imagebuilder:components }}}', + ImageOsVersionOverride: 'Custom OS', + InstanceConfiguration: { + 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', + }, + }, + ], + Image: 'ssm:/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id', + }, + KmsKeyId: { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':kms:us-east-1:123456789012:key/1234abcd-12ab-34cd-56ef-1234567890ab', + ], + ], + }, + Name: 'test-container-recipe', + ParentImage: 'public.ecr.aws/amazonlinux/amazonlinux:latest', + PlatformOverride: 'Linux', + Tags: { + key1: 'value1', + key2: 'value2', + }, + TargetRepository: { + RepositoryName: 'test-repository', + Service: 'ECR', + }, + Version: '1.2.3', + WorkingDirectory: '/var/tmp', + }, + }), + }, + }); + }); + + test('with required parameters', () => { + new ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + }); + + Template.fromStack(stack).templateMatches({ + Resources: { + ContainerRecipe8A7CC9ED: Match.objectEquals({ + Type: 'AWS::ImageBuilder::ContainerRecipe', + Properties: { + Name: 'stack-containerrecipe-fcc21fd4', + Version: '1.0.x', + ContainerType: 'DOCKER', + ParentImage: 'amazonlinux:latest', + DockerfileTemplateData: + 'FROM {{{ imagebuilder:parentImage }}}\n{{{ imagebuilder:environments }}}\n{{{ imagebuilder:components }}}', + TargetRepository: { + RepositoryName: 'test-repository', + Service: 'ECR', + }, + }, + }), + }, + }); + }); + + test('with dockerfile data as a file asset', () => { + new ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + dockerfile: DockerfileData.fromAsset(stack, 'DockerfileData', path.join(__dirname, 'assets', 'Dockerfile')), + }); + + Template.fromStack(stack).templateMatches({ + Resources: { + ContainerRecipe8A7CC9ED: Match.objectEquals({ + Type: 'AWS::ImageBuilder::ContainerRecipe', + Properties: { + Name: 'stack-containerrecipe-fcc21fd4', + Version: '1.0.x', + ContainerType: 'DOCKER', + ParentImage: 'amazonlinux:latest', + DockerfileTemplateUri: + 's3://cdk-hnb659fds-assets-123456789012-us-east-1/2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e', + TargetRepository: { + RepositoryName: 'test-repository', + Service: 'ECR', + }, + }, + }), + }, + }); + }); + + test('with dockerfile data as an S3 location', () => { + const bucket = s3.Bucket.fromBucketName(stack, 'Bucket', 'dockerfile-bucket-123456789012-us-east-1'); + new ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + dockerfile: DockerfileData.fromS3(bucket, 'dockerfile/Dockerfile'), + }); + + Template.fromStack(stack).templateMatches({ + Resources: { + ContainerRecipe8A7CC9ED: Match.objectEquals({ + Type: 'AWS::ImageBuilder::ContainerRecipe', + Properties: { + Name: 'stack-containerrecipe-fcc21fd4', + Version: '1.0.x', + ContainerType: 'DOCKER', + ParentImage: 'amazonlinux:latest', + DockerfileTemplateUri: 's3://dockerfile-bucket-123456789012-us-east-1/dockerfile/Dockerfile', + TargetRepository: { + RepositoryName: 'test-repository', + Service: 'ECR', + }, + }, + }), + }, + }); + }); + + test('grants read access to IAM roles', () => { + const containerRecipe = new ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + }); + + const role = new iam.Role(stack, 'Role', { assumedBy: new iam.AccountPrincipal('123456789012') }); + + containerRecipe.grantRead(role); + + const template = Template.fromStack(stack); + + template.resourceCountIs('AWS::IAM::Policy', 1); + template.resourceCountIs('AWS::IAM::Role', 1); + template.resourceCountIs('AWS::ImageBuilder::ContainerRecipe', 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:GetContainerRecipe', + Resource: { + 'Fn::GetAtt': ['ContainerRecipe8A7CC9ED', 'Arn'], + }, + }, + ], + }, + Roles: [Match.anyValue()], + }); + }); + + test('grants permissions to IAM roles', () => { + const containerRecipe = new ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + }); + + const role = new iam.Role(stack, 'Role', { assumedBy: new iam.AccountPrincipal('123456789012') }); + + containerRecipe.grant(role, 'imagebuilder:DeleteContainerRecipe'); + + const template = Template.fromStack(stack); + + template.resourceCountIs('AWS::IAM::Policy', 1); + template.resourceCountIs('AWS::IAM::Role', 1); + template.resourceCountIs('AWS::ImageBuilder::ContainerRecipe', 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:DeleteContainerRecipe', + Resource: { + 'Fn::GetAtt': ['ContainerRecipe8A7CC9ED', 'Arn'], + }, + }, + ], + }, + Roles: [Match.anyValue()], + }); + }); + + test('grants S3 put permissions on S3 asset to IAM roles', () => { + const bucket = s3.Bucket.fromBucketName(stack, 'Bucket', 'dockerfile-bucket-123456789012-us-east-1'); + const role = new iam.Role(stack, 'Role', { assumedBy: new iam.AccountPrincipal('123456789012') }); + const dockerfileData = DockerfileData.fromS3(bucket, 'assets/Dockerfile'); + new ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + dockerfile: dockerfileData, + }); + + dockerfileData.grantPut(role); + + const template = Template.fromStack(stack); + + template.resourceCountIs('AWS::IAM::Policy', 1); + template.resourceCountIs('AWS::IAM::Role', 1); + template.resourceCountIs('AWS::ImageBuilder::ContainerRecipe', 1); + expect(Object.keys(template.toJSON().Resources)).toHaveLength(3); + + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyName: Match.anyValue(), + PolicyDocument: { + Statement: [ + { + Effect: 'Allow', + Action: Match.arrayWith(['s3:PutObject']), + Resource: { + 'Fn::Join': [ + '', + ['arn:', { Ref: 'AWS::Partition' }, ':s3:::dockerfile-bucket-123456789012-us-east-1/assets/Dockerfile'], + ], + }, + }, + ], + }, + Roles: [Match.anyValue()], + }); + }); + + test('grants S3 read permissions on S3 asset to IAM roles', () => { + const bucket = s3.Bucket.fromBucketName(stack, 'Bucket', 'dockerfile-bucket-123456789012-us-east-1'); + const role = new iam.Role(stack, 'Role', { assumedBy: new iam.AccountPrincipal('123456789012') }); + const dockerfileData = DockerfileData.fromS3(bucket, 'assets/Dockerfile'); + new ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr(ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository')), + dockerfile: dockerfileData, + }); + + dockerfileData.grantRead(role); + + const template = Template.fromStack(stack); + + template.resourceCountIs('AWS::IAM::Policy', 1); + template.resourceCountIs('AWS::IAM::Role', 1); + template.resourceCountIs('AWS::ImageBuilder::ContainerRecipe', 1); + expect(Object.keys(template.toJSON().Resources)).toHaveLength(3); + + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyName: Match.anyValue(), + PolicyDocument: { + Statement: [ + { + Effect: 'Allow', + Action: Match.arrayWith(['s3:GetObject*']), + Resource: [ + { + 'Fn::Join': ['', ['arn:', { Ref: 'AWS::Partition' }, ':s3:::dockerfile-bucket-123456789012-us-east-1']], + }, + { + 'Fn::Join': [ + '', + [ + 'arn:', + { Ref: 'AWS::Partition' }, + ':s3:::dockerfile-bucket-123456789012-us-east-1/assets/Dockerfile', + ], + ], + }, + ], + }, + ], + }, + Roles: [Match.anyValue()], + }); + }); + + test('does not throw a validation error when a containerRecipeArn and containerRecipeName are provided when importing by attributes', () => { + expect(() => + ContainerRecipe.fromContainerRecipeAttributes(stack, 'ContainerRecipe', { + containerRecipeArn: + 'arn:aws:imagebuilder:us-east-1:123456789012:container-recipe/imported-container-recipe/x.x.x', + containerRecipeName: 'imported-container-recipe', + }), + ).not.toThrow(cdk.ValidationError); + }); + + test('throws a validation error when neither a containerRecipeArn or containerRecipeName are provided when importing by attributes', () => { + expect(() => ContainerRecipe.fromContainerRecipeAttributes(stack, 'ContainerRecipe', {})).toThrow( + cdk.ValidationError, + ); + }); + + test('throws a validation error when the resource name is too long', () => { + expect( + () => + new ContainerRecipe(stack, 'ContainerRecipe', { + containerRecipeName: 'a'.repeat(129), + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr( + ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository'), + ), + }), + ).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when the resource name contains spaces', () => { + expect( + () => + new ContainerRecipe(stack, 'ContainerRecipe', { + containerRecipeName: 'test recipe', + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr( + ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository'), + ), + }), + ).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when the resource name contains underscores', () => { + expect( + () => + new ContainerRecipe(stack, 'ContainerRecipe', { + containerRecipeName: 'test_recipe', + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr( + ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository'), + ), + }), + ).toThrow(cdk.ValidationError); + }); + + test('throws a validation error when the resource name contains uppercase characters', () => { + expect( + () => + new ContainerRecipe(stack, 'ContainerRecipe', { + containerRecipeName: 'TestRecipe', + baseImage: BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + targetRepository: Repository.fromEcr( + ecr.Repository.fromRepositoryName(stack, 'Repository', 'test-repository'), + ), + }), + ).toThrow(cdk.ValidationError); + }); +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.assets.json new file mode 100644 index 0000000000000..168e4e3614267 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2 Template", + "source": { + "path": "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.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.container-recipe.js.snapshot/ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.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.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-all-parameters.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-all-parameters.assets.json new file mode 100644 index 0000000000000..beb1117b473ab --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-all-parameters.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "e87db65fcd4d5bb5b177638609ec2eec0b23db6f629a3c5e15e68de9919e2e68": { + "displayName": "aws-cdk-imagebuilder-container-recipe-all-parameters Template", + "source": { + "path": "aws-cdk-imagebuilder-container-recipe-all-parameters.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-a421d656": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "e87db65fcd4d5bb5b177638609ec2eec0b23db6f629a3c5e15e68de9919e2e68.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.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-all-parameters.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-all-parameters.template.json new file mode 100644 index 0000000000000..a295d599cade9 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-all-parameters.template.json @@ -0,0 +1,144 @@ +{ + "Resources": { + "Repository22E53BBD": { + "Type": "AWS::ECR::Repository", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "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-container-recipe-all-parameters-parameterizedcomponent-145a71d0", + "Platform": "Linux", + "Version": "1.0.0" + } + }, + "ContainerRecipe8A7CC9ED": { + "Type": "AWS::ImageBuilder::ContainerRecipe", + "Properties": { + "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" + ] + } + ] + } + ], + "ContainerType": "DOCKER", + "Description": "A test container recipe", + "DockerfileTemplateData": "FROM {{{ imagebuilder:parentImage }}}\nCMD [\"echo\", \"Hello, world!\"]\n{{{ imagebuilder:environments }}}\n{{{ imagebuilder:components }}}", + "ImageOsVersionOverride": "Amazon Linux 2023", + "InstanceConfiguration": { + "BlockDeviceMappings": [ + { + "DeviceName": "/dev/sda2", + "Ebs": { + "DeleteOnTermination": true, + "Iops": 1000, + "SnapshotId": "snap-123", + "Throughput": 125, + "VolumeSize": 75, + "VolumeType": "gp3" + } + } + ], + "Image": "ssm:/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id" + }, + "Name": "test-container-recipe", + "ParentImage": "public.ecr.aws/amazonlinux/amazonlinux:latest", + "PlatformOverride": "Linux", + "Tags": { + "key1": "value1", + "key2": "value2" + }, + "TargetRepository": { + "RepositoryName": { + "Ref": "Repository22E53BBD" + }, + "Service": "ECR" + }, + "Version": "1.2.x", + "WorkingDirectory": "/var/tmp" + } + } + }, + "Outputs": { + "ContainerRecipeVersion": { + "Value": { + "Fn::GetAtt": [ + "ContainerRecipe8A7CC9ED", + "Version" + ] + } + } + }, + "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.container-recipe.js.snapshot/cdk.out b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-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.container-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.container-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/integ.json new file mode 100644 index 0000000000000..033c931833e8d --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "ContainerRecipeTest-AllParameters/DefaultTest": { + "stacks": [ + "aws-cdk-imagebuilder-container-recipe-all-parameters" + ], + "assertionStack": "ContainerRecipeTest-AllParameters/DefaultTest/DeployAssert", + "assertionStackName": "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/manifest.json new file mode 100644 index 0000000000000..e33292d0a1f1a --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/manifest.json @@ -0,0 +1,638 @@ +{ + "version": "48.0.0", + "artifacts": { + "aws-cdk-imagebuilder-container-recipe-all-parameters.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-imagebuilder-container-recipe-all-parameters.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-imagebuilder-container-recipe-all-parameters": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-imagebuilder-container-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}/e87db65fcd4d5bb5b177638609ec2eec0b23db6f629a3c5e15e68de9919e2e68.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-imagebuilder-container-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-container-recipe-all-parameters.assets" + ], + "metadata": { + "/aws-cdk-imagebuilder-container-recipe-all-parameters/Repository": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "removalPolicy": "destroy" + } + } + ], + "/aws-cdk-imagebuilder-container-recipe-all-parameters/Repository/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Repository22E53BBD" + } + ], + "/aws-cdk-imagebuilder-container-recipe-all-parameters/ParameterizedComponent/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ParameterizedComponentD29478CA" + } + ], + "/aws-cdk-imagebuilder-container-recipe-all-parameters/ContainerRecipe/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ContainerRecipe8A7CC9ED", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] + } + ], + "/aws-cdk-imagebuilder-container-recipe-all-parameters/ContainerRecipeVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "ContainerRecipeVersion" + } + ], + "/aws-cdk-imagebuilder-container-recipe-all-parameters/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-imagebuilder-container-recipe-all-parameters/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-imagebuilder-container-recipe-all-parameters" + }, + "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.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": [ + "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.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": [ + "ContainerRecipeTestAllParametersDefaultTestDeployAssert5A6D24C2.assets" + ], + "metadata": { + "/ContainerRecipeTest-AllParameters/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ContainerRecipeTest-AllParameters/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ContainerRecipeTest-AllParameters/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.container-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.js.snapshot/tree.json new file mode 100644 index 0000000000000..e3ef4f9b2c2c5 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-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-container-recipe-all-parameters":{"id":"aws-cdk-imagebuilder-container-recipe-all-parameters","path":"aws-cdk-imagebuilder-container-recipe-all-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Repository":{"id":"Repository","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/Repository","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.Repository","version":"0.0.0","metadata":[{"removalPolicy":"destroy"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/Repository/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.CfnRepository","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECR::Repository","aws:cdk:cloudformation:props":{}}}}},"ParameterizedComponent":{"id":"ParameterizedComponent","path":"aws-cdk-imagebuilder-container-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-container-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-container-recipe-all-parameters-parameterizedcomponent-145a71d0","platform":"Linux","version":"1.0.0"}}}}},"Component2":{"id":"Component2","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/Component2","constructInfo":{"fqn":"aws-cdk-lib.Resource","version":"0.0.0","metadata":[]}},"ContainerRecipe":{"id":"ContainerRecipe","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/ContainerRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ContainerRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/ContainerRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnContainerRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ContainerRecipe","aws:cdk:cloudformation:props":{"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"]}]}],"containerType":"DOCKER","description":"A test container recipe","dockerfileTemplateData":"FROM {{{ imagebuilder:parentImage }}}\nCMD [\"echo\", \"Hello, world!\"]\n{{{ imagebuilder:environments }}}\n{{{ imagebuilder:components }}}","imageOsVersionOverride":"Amazon Linux 2023","instanceConfiguration":{"blockDeviceMappings":[{"deviceName":"/dev/sda2","ebs":{"deleteOnTermination":true,"iops":1000,"snapshotId":"snap-123","throughput":125,"volumeSize":75,"volumeType":"gp3"}}],"image":"ssm:/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id"},"name":"test-container-recipe","parentImage":"public.ecr.aws/amazonlinux/amazonlinux:latest","platformOverride":"Linux","tags":{"key1":"value1","key2":"value2"},"targetRepository":{"repositoryName":{"Ref":"Repository22E53BBD"},"service":"ECR"},"version":"1.2.x","workingDirectory":"/var/tmp"}}}}},"ContainerRecipeVersion":{"id":"ContainerRecipeVersion","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/ContainerRecipeVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-all-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ContainerRecipeTest-AllParameters":{"id":"ContainerRecipeTest-AllParameters","path":"ContainerRecipeTest-AllParameters","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ContainerRecipeTest-AllParameters/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ContainerRecipeTest-AllParameters/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ContainerRecipeTest-AllParameters/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ContainerRecipeTest-AllParameters/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ContainerRecipeTest-AllParameters/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.container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.ts new file mode 100644 index 0000000000000..fe49456a70829 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.all-parameters.container-recipe.ts @@ -0,0 +1,96 @@ +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 ecr from 'aws-cdk-lib/aws-ecr'; +import * as imagebuilder from '../lib'; +import { DockerfileData } from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-container-recipe-all-parameters'); + +const repository = new ecr.Repository(stack, 'Repository', { removalPolicy: cdk.RemovalPolicy.DESTROY }); + +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: imagebuilder.ComponentStepInputs.fromObject({ + commands: ['echo ${{ parameter1 }}', 'echo ${{ parameter2 }}'], + }), + }, + ], + }, + ], + }), +}); + +const containerRecipe = new imagebuilder.ContainerRecipe(stack, 'ContainerRecipe', { + containerRecipeName: 'test-container-recipe', + containerRecipeVersion: '1.2.x', + description: 'A test container recipe', + baseImage: imagebuilder.BaseContainerImage.fromEcrPublic('amazonlinux', 'amazonlinux', 'latest'), + osVersion: imagebuilder.OSVersion.AMAZON_LINUX_2023, + targetRepository: imagebuilder.Repository.fromEcr(repository), + dockerfile: DockerfileData.fromInline(`FROM {{{ imagebuilder:parentImage }}} +CMD ["echo", "Hello, world!"] +{{{ imagebuilder:environments }}} +{{{ imagebuilder:components }}}`), + 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'), + }, + }, + ], + workingDirectory: '/var/tmp', + instanceImage: imagebuilder.ContainerInstanceImage.fromSsmParameterName( + '/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended/image_id', + ), + tags: { + key1: 'value1', + key2: 'value2', + }, +}); + +containerRecipe.addInstanceBlockDevice({ + deviceName: '/dev/sda2', + volume: ec2.BlockDeviceVolume.ebsFromSnapshot('snap-123', { + volumeSize: 75, + deleteOnTermination: true, + iops: 1000, + volumeType: ec2.EbsDeviceVolumeType.GENERAL_PURPOSE_SSD_GP3, + throughput: 125, + }), +}); + +new cdk.CfnOutput(stack, 'ContainerRecipeVersion', { value: containerRecipe.containerRecipeVersion }); + +new integ.IntegTest(app, 'ContainerRecipeTest-AllParameters', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json new file mode 100644 index 0000000000000..85d7ee73af19b --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE Template", + "source": { + "path": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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.asset.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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.asset.container-recipe.js.snapshot/asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e new file mode 100644 index 0000000000000..2cb8966fbc242 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e @@ -0,0 +1,4 @@ +FROM {{{ imagebuilder:parentImage }}} +CMD ["echo", "Hello, world!"] +{{{ imagebuilder:environments }}} +{{{ imagebuilder:components }}} diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-asset.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-asset.assets.json new file mode 100644 index 0000000000000..d09609f73e50b --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-asset.assets.json @@ -0,0 +1,34 @@ +{ + "version": "48.0.0", + "files": { + "2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e": { + "displayName": "DockerfileData", + "source": { + "path": "asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-2b746983": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "6bcc8fea0abd7b7f596517f0011f19a0d3249001ba15d35c1224f98f7828afbe": { + "displayName": "aws-cdk-imagebuilder-container-recipe-asset Template", + "source": { + "path": "aws-cdk-imagebuilder-container-recipe-asset.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-d64aae4a": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6bcc8fea0abd7b7f596517f0011f19a0d3249001ba15d35c1224f98f7828afbe.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.asset.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-asset.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-asset.template.json new file mode 100644 index 0000000000000..ebdd564bfe775 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-asset.template.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "Repository22E53BBD": { + "Type": "AWS::ECR::Repository", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ContainerRecipe8A7CC9ED": { + "Type": "AWS::ImageBuilder::ContainerRecipe", + "Properties": { + "ContainerType": "DOCKER", + "DockerfileTemplateUri": { + "Fn::Join": [ + "", + [ + "s3://", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e" + ] + ] + }, + "Name": "aws-cdk-imagebuilder-container-recipe-asset-containerrecipe-768c3a07", + "ParentImage": "amazonlinux:latest", + "TargetRepository": { + "RepositoryName": { + "Ref": "Repository22E53BBD" + }, + "Service": "ECR" + }, + "Version": "1.0.x" + } + } + }, + "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.asset.container-recipe.js.snapshot/cdk.out b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-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.asset.container-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/integ.json new file mode 100644 index 0000000000000..3e75a95940d55 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "ContainerRecipeTest/DefaultTest": { + "stacks": [ + "aws-cdk-imagebuilder-container-recipe-asset" + ], + "assertionStack": "ContainerRecipeTest/DefaultTest/DeployAssert", + "assertionStackName": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/manifest.json new file mode 100644 index 0000000000000..6f2b8f8e98a0c --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/manifest.json @@ -0,0 +1,626 @@ +{ + "version": "48.0.0", + "artifacts": { + "aws-cdk-imagebuilder-container-recipe-asset.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-imagebuilder-container-recipe-asset.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-imagebuilder-container-recipe-asset": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-imagebuilder-container-recipe-asset.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}/6bcc8fea0abd7b7f596517f0011f19a0d3249001ba15d35c1224f98f7828afbe.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-imagebuilder-container-recipe-asset.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-container-recipe-asset.assets" + ], + "metadata": { + "/aws-cdk-imagebuilder-container-recipe-asset/Repository": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "removalPolicy": "destroy" + } + } + ], + "/aws-cdk-imagebuilder-container-recipe-asset/Repository/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Repository22E53BBD" + } + ], + "/aws-cdk-imagebuilder-container-recipe-asset/ContainerRecipe/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ContainerRecipe8A7CC9ED", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] + } + ], + "/aws-cdk-imagebuilder-container-recipe-asset/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-imagebuilder-container-recipe-asset/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-imagebuilder-container-recipe-asset" + }, + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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": [ + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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": [ + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets" + ], + "metadata": { + "/ContainerRecipeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ContainerRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ContainerRecipeTest/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.asset.container-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.js.snapshot/tree.json new file mode 100644 index 0000000000000..f4efb5c705ce6 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-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-container-recipe-asset":{"id":"aws-cdk-imagebuilder-container-recipe-asset","path":"aws-cdk-imagebuilder-container-recipe-asset","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Repository":{"id":"Repository","path":"aws-cdk-imagebuilder-container-recipe-asset/Repository","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.Repository","version":"0.0.0","metadata":[{"removalPolicy":"destroy"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-asset/Repository/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.CfnRepository","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECR::Repository","aws:cdk:cloudformation:props":{}}}}},"DockerfileData":{"id":"DockerfileData","path":"aws-cdk-imagebuilder-container-recipe-asset/DockerfileData","constructInfo":{"fqn":"aws-cdk-lib.aws_s3_assets.Asset","version":"0.0.0"},"children":{"Stage":{"id":"Stage","path":"aws-cdk-imagebuilder-container-recipe-asset/DockerfileData/Stage","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"AssetBucket":{"id":"AssetBucket","path":"aws-cdk-imagebuilder-container-recipe-asset/DockerfileData/AssetBucket","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.BucketBase","version":"0.0.0","metadata":[]}}}},"ContainerRecipe":{"id":"ContainerRecipe","path":"aws-cdk-imagebuilder-container-recipe-asset/ContainerRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ContainerRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-asset/ContainerRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnContainerRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ContainerRecipe","aws:cdk:cloudformation:props":{"containerType":"DOCKER","dockerfileTemplateUri":{"Fn::Join":["",["s3://",{"Fn::Sub":"cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"},"/2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e"]]},"name":"aws-cdk-imagebuilder-container-recipe-asset-containerrecipe-768c3a07","parentImage":"amazonlinux:latest","targetRepository":{"repositoryName":{"Ref":"Repository22E53BBD"},"service":"ECR"},"version":"1.0.x"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-asset/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-asset/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ContainerRecipeTest":{"id":"ContainerRecipeTest","path":"ContainerRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ContainerRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ContainerRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ContainerRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ContainerRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ContainerRecipeTest/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.asset.container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.ts new file mode 100644 index 0000000000000..e7ae747615b18 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.asset.container-recipe.ts @@ -0,0 +1,24 @@ +import * as path from 'path'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as ecr from 'aws-cdk-lib/aws-ecr'; +import * as imagebuilder from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-container-recipe-asset'); + +const repository = new ecr.Repository(stack, 'Repository', { removalPolicy: cdk.RemovalPolicy.DESTROY }); + +new imagebuilder.ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr(repository), + dockerfile: imagebuilder.DockerfileData.fromAsset( + stack, + 'DockerfileData', + path.join(__dirname, 'assets', 'Dockerfile'), + ), +}); + +new integ.IntegTest(app, 'ContainerRecipeTest', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json new file mode 100644 index 0000000000000..85d7ee73af19b --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE Template", + "source": { + "path": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-default-parameters.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-default-parameters.assets.json new file mode 100644 index 0000000000000..ae54c1e147b4b --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-default-parameters.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "849aac21ed3e00a1f6ab3e308dbc6cc9e688fa1b13681a7bbd2ac1a4ce0babd4": { + "displayName": "aws-cdk-imagebuilder-container-recipe-default-parameters Template", + "source": { + "path": "aws-cdk-imagebuilder-container-recipe-default-parameters.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-3ba410f7": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "849aac21ed3e00a1f6ab3e308dbc6cc9e688fa1b13681a7bbd2ac1a4ce0babd4.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.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-default-parameters.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-default-parameters.template.json new file mode 100644 index 0000000000000..856ac3f831201 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-default-parameters.template.json @@ -0,0 +1,69 @@ +{ + "Resources": { + "Repository22E53BBD": { + "Type": "AWS::ECR::Repository", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ContainerRecipe8A7CC9ED": { + "Type": "AWS::ImageBuilder::ContainerRecipe", + "Properties": { + "ContainerType": "DOCKER", + "DockerfileTemplateData": "FROM {{{ imagebuilder:parentImage }}}\n{{{ imagebuilder:environments }}}\n{{{ imagebuilder:components }}}", + "Name": "aws-cdk-imagebuilder-container-recipe-default-parameters-containerrecipe-6909b380", + "ParentImage": "amazonlinux:latest", + "TargetRepository": { + "RepositoryName": { + "Ref": "Repository22E53BBD" + }, + "Service": "ECR" + }, + "Version": "1.0.x" + } + } + }, + "Outputs": { + "ContainerRecipeVersion": { + "Value": { + "Fn::GetAtt": [ + "ContainerRecipe8A7CC9ED", + "Version" + ] + } + } + }, + "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.container-recipe.js.snapshot/cdk.out b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-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.container-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.container-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/integ.json new file mode 100644 index 0000000000000..4d76f2cb334fd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "ContainerRecipeTest/DefaultTest": { + "stacks": [ + "aws-cdk-imagebuilder-container-recipe-default-parameters" + ], + "assertionStack": "ContainerRecipeTest/DefaultTest/DeployAssert", + "assertionStackName": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/manifest.json new file mode 100644 index 0000000000000..37f87c994420a --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/manifest.json @@ -0,0 +1,629 @@ +{ + "version": "48.0.0", + "artifacts": { + "aws-cdk-imagebuilder-container-recipe-default-parameters.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-imagebuilder-container-recipe-default-parameters.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-imagebuilder-container-recipe-default-parameters": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-imagebuilder-container-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}/849aac21ed3e00a1f6ab3e308dbc6cc9e688fa1b13681a7bbd2ac1a4ce0babd4.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-imagebuilder-container-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-container-recipe-default-parameters.assets" + ], + "metadata": { + "/aws-cdk-imagebuilder-container-recipe-default-parameters/Repository": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "removalPolicy": "destroy" + } + } + ], + "/aws-cdk-imagebuilder-container-recipe-default-parameters/Repository/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Repository22E53BBD" + } + ], + "/aws-cdk-imagebuilder-container-recipe-default-parameters/ContainerRecipe/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ContainerRecipe8A7CC9ED" + } + ], + "/aws-cdk-imagebuilder-container-recipe-default-parameters/ContainerRecipeVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "ContainerRecipeVersion" + } + ], + "/aws-cdk-imagebuilder-container-recipe-default-parameters/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-imagebuilder-container-recipe-default-parameters/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-imagebuilder-container-recipe-default-parameters" + }, + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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": [ + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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": [ + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets" + ], + "metadata": { + "/ContainerRecipeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ContainerRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ContainerRecipeTest/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.container-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.js.snapshot/tree.json new file mode 100644 index 0000000000000..2c982483102fc --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-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-container-recipe-default-parameters":{"id":"aws-cdk-imagebuilder-container-recipe-default-parameters","path":"aws-cdk-imagebuilder-container-recipe-default-parameters","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Repository":{"id":"Repository","path":"aws-cdk-imagebuilder-container-recipe-default-parameters/Repository","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.Repository","version":"0.0.0","metadata":[{"removalPolicy":"destroy"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-default-parameters/Repository/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.CfnRepository","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECR::Repository","aws:cdk:cloudformation:props":{}}}}},"ContainerRecipe":{"id":"ContainerRecipe","path":"aws-cdk-imagebuilder-container-recipe-default-parameters/ContainerRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ContainerRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-default-parameters/ContainerRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnContainerRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ContainerRecipe","aws:cdk:cloudformation:props":{"containerType":"DOCKER","dockerfileTemplateData":"FROM {{{ imagebuilder:parentImage }}}\n{{{ imagebuilder:environments }}}\n{{{ imagebuilder:components }}}","name":"aws-cdk-imagebuilder-container-recipe-default-parameters-containerrecipe-6909b380","parentImage":"amazonlinux:latest","targetRepository":{"repositoryName":{"Ref":"Repository22E53BBD"},"service":"ECR"},"version":"1.0.x"}}}}},"ContainerRecipeVersion":{"id":"ContainerRecipeVersion","path":"aws-cdk-imagebuilder-container-recipe-default-parameters/ContainerRecipeVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnOutput","version":"0.0.0"}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-default-parameters/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-default-parameters/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ContainerRecipeTest":{"id":"ContainerRecipeTest","path":"ContainerRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ContainerRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ContainerRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ContainerRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ContainerRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ContainerRecipeTest/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.container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.ts new file mode 100644 index 0000000000000..155821a95487f --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.default-parameters.container-recipe.ts @@ -0,0 +1,20 @@ +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as ecr from 'aws-cdk-lib/aws-ecr'; +import * as imagebuilder from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-container-recipe-default-parameters'); + +const repository = new ecr.Repository(stack, 'Repository', { removalPolicy: cdk.RemovalPolicy.DESTROY }); + +const containerRecipe = new imagebuilder.ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr(repository), +}); + +new cdk.CfnOutput(stack, 'ContainerRecipeVersion', { value: containerRecipe.containerRecipeVersion }); + +new integ.IntegTest(app, 'ContainerRecipeTest-DefaultParameters', { + testCases: [stack], +}); diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json new file mode 100644 index 0000000000000..85d7ee73af19b --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json @@ -0,0 +1,20 @@ +{ + "version": "48.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "displayName": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE Template", + "source": { + "path": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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.s3.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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.s3.container-recipe.js.snapshot/asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e new file mode 100644 index 0000000000000..2cb8966fbc242 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e @@ -0,0 +1,4 @@ +FROM {{{ imagebuilder:parentImage }}} +CMD ["echo", "Hello, world!"] +{{{ imagebuilder:environments }}} +{{{ imagebuilder:components }}} diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-s3.assets.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-s3.assets.json new file mode 100644 index 0000000000000..d8a98c4b31e78 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-s3.assets.json @@ -0,0 +1,34 @@ +{ + "version": "48.0.0", + "files": { + "2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e": { + "displayName": "asset", + "source": { + "path": "asset.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-2b746983": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "5dc77165204fc374a9a5b63c348ae317dda803c1bc82487dc6c15087b0110453": { + "displayName": "aws-cdk-imagebuilder-container-recipe-s3 Template", + "source": { + "path": "aws-cdk-imagebuilder-container-recipe-s3.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region-7c51d7ae": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "5dc77165204fc374a9a5b63c348ae317dda803c1bc82487dc6c15087b0110453.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.s3.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-s3.template.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-s3.template.json new file mode 100644 index 0000000000000..e450112a7b5d3 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/aws-cdk-imagebuilder-container-recipe-s3.template.json @@ -0,0 +1,70 @@ +{ + "Resources": { + "Repository22E53BBD": { + "Type": "AWS::ECR::Repository", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "ContainerRecipe8A7CC9ED": { + "Type": "AWS::ImageBuilder::ContainerRecipe", + "Properties": { + "ContainerType": "DOCKER", + "DockerfileTemplateUri": { + "Fn::Join": [ + "", + [ + "s3://", + { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "/2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e" + ] + ] + }, + "Name": "aws-cdk-imagebuilder-container-recipe-s3-containerrecipe-b3c588a7", + "ParentImage": "amazonlinux:latest", + "TargetRepository": { + "RepositoryName": { + "Ref": "Repository22E53BBD" + }, + "Service": "ECR" + }, + "Version": "1.0.x" + } + } + }, + "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.s3.container-recipe.js.snapshot/cdk.out b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/cdk.out new file mode 100644 index 0000000000000..523a9aac37cbf --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-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.s3.container-recipe.js.snapshot/integ.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/integ.json new file mode 100644 index 0000000000000..ce22f7daafdee --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "48.0.0", + "testCases": { + "ContainerRecipeTest/DefaultTest": { + "stacks": [ + "aws-cdk-imagebuilder-container-recipe-s3" + ], + "assertionStack": "ContainerRecipeTest/DefaultTest/DeployAssert", + "assertionStackName": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE" + } + }, + "minimumCliVersion": "2.1027.0" +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/manifest.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/manifest.json new file mode 100644 index 0000000000000..9e492964132f5 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/manifest.json @@ -0,0 +1,626 @@ +{ + "version": "48.0.0", + "artifacts": { + "aws-cdk-imagebuilder-container-recipe-s3.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-imagebuilder-container-recipe-s3.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-imagebuilder-container-recipe-s3": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-imagebuilder-container-recipe-s3.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}/5dc77165204fc374a9a5b63c348ae317dda803c1bc82487dc6c15087b0110453.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-imagebuilder-container-recipe-s3.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-container-recipe-s3.assets" + ], + "metadata": { + "/aws-cdk-imagebuilder-container-recipe-s3/Repository": [ + { + "type": "aws:cdk:analytics:construct", + "data": { + "removalPolicy": "destroy" + } + } + ], + "/aws-cdk-imagebuilder-container-recipe-s3/Repository/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Repository22E53BBD" + } + ], + "/aws-cdk-imagebuilder-container-recipe-s3/ContainerRecipe/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ContainerRecipe8A7CC9ED", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_REPLACE" + ] + } + ], + "/aws-cdk-imagebuilder-container-recipe-s3/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-imagebuilder-container-recipe-s3/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-imagebuilder-container-recipe-s3" + }, + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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": [ + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.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": [ + "ContainerRecipeTestDefaultTestDeployAssertB3A3E9AE.assets" + ], + "metadata": { + "/ContainerRecipeTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/ContainerRecipeTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "ContainerRecipeTest/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.s3.container-recipe.js.snapshot/tree.json b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.js.snapshot/tree.json new file mode 100644 index 0000000000000..0b64b8ef3caec --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-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-container-recipe-s3":{"id":"aws-cdk-imagebuilder-container-recipe-s3","path":"aws-cdk-imagebuilder-container-recipe-s3","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"Repository":{"id":"Repository","path":"aws-cdk-imagebuilder-container-recipe-s3/Repository","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.Repository","version":"0.0.0","metadata":[{"removalPolicy":"destroy"}]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-s3/Repository/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_ecr.CfnRepository","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ECR::Repository","aws:cdk:cloudformation:props":{}}}}},"asset":{"id":"asset","path":"aws-cdk-imagebuilder-container-recipe-s3/asset","constructInfo":{"fqn":"aws-cdk-lib.aws_s3_assets.Asset","version":"0.0.0"},"children":{"Stage":{"id":"Stage","path":"aws-cdk-imagebuilder-container-recipe-s3/asset/Stage","constructInfo":{"fqn":"aws-cdk-lib.AssetStaging","version":"0.0.0"}},"AssetBucket":{"id":"AssetBucket","path":"aws-cdk-imagebuilder-container-recipe-s3/asset/AssetBucket","constructInfo":{"fqn":"aws-cdk-lib.aws_s3.BucketBase","version":"0.0.0","metadata":[]}}}},"ContainerRecipe":{"id":"ContainerRecipe","path":"aws-cdk-imagebuilder-container-recipe-s3/ContainerRecipe","constructInfo":{"fqn":"@aws-cdk/aws-imagebuilder-alpha.ContainerRecipe","version":"0.0.0","metadata":[]},"children":{"Resource":{"id":"Resource","path":"aws-cdk-imagebuilder-container-recipe-s3/ContainerRecipe/Resource","constructInfo":{"fqn":"aws-cdk-lib.aws_imagebuilder.CfnContainerRecipe","version":"0.0.0"},"attributes":{"aws:cdk:cloudformation:type":"AWS::ImageBuilder::ContainerRecipe","aws:cdk:cloudformation:props":{"containerType":"DOCKER","dockerfileTemplateUri":{"Fn::Join":["",["s3://",{"Fn::Sub":"cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"},"/2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e.2c4690a423fb29c09c3fa969e7c7e6e5e2d612e0d354bee3fab6945e833ebe8e"]]},"name":"aws-cdk-imagebuilder-container-recipe-s3-containerrecipe-b3c588a7","parentImage":"amazonlinux:latest","targetRepository":{"repositoryName":{"Ref":"Repository22E53BBD"},"service":"ECR"},"version":"1.0.x"}}}}},"BootstrapVersion":{"id":"BootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-s3/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"aws-cdk-imagebuilder-container-recipe-s3/CheckBootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnRule","version":"0.0.0"}}}},"ContainerRecipeTest":{"id":"ContainerRecipeTest","path":"ContainerRecipeTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTest","version":"0.0.0"},"children":{"DefaultTest":{"id":"DefaultTest","path":"ContainerRecipeTest/DefaultTest","constructInfo":{"fqn":"@aws-cdk/integ-tests-alpha.IntegTestCase","version":"0.0.0"},"children":{"Default":{"id":"Default","path":"ContainerRecipeTest/DefaultTest/Default","constructInfo":{"fqn":"constructs.Construct","version":"10.4.3"}},"DeployAssert":{"id":"DeployAssert","path":"ContainerRecipeTest/DefaultTest/DeployAssert","constructInfo":{"fqn":"aws-cdk-lib.Stack","version":"0.0.0"},"children":{"BootstrapVersion":{"id":"BootstrapVersion","path":"ContainerRecipeTest/DefaultTest/DeployAssert/BootstrapVersion","constructInfo":{"fqn":"aws-cdk-lib.CfnParameter","version":"0.0.0"}},"CheckBootstrapVersion":{"id":"CheckBootstrapVersion","path":"ContainerRecipeTest/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.s3.container-recipe.ts b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.ts new file mode 100644 index 0000000000000..aca4105a7bf84 --- /dev/null +++ b/packages/@aws-cdk/aws-imagebuilder-alpha/test/integ.s3.container-recipe.ts @@ -0,0 +1,25 @@ +import * as path from 'path'; +import * as integ from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as ecr from 'aws-cdk-lib/aws-ecr'; +import * as s3assets from 'aws-cdk-lib/aws-s3-assets'; +import * as imagebuilder from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-imagebuilder-container-recipe-s3'); + +const repository = new ecr.Repository(stack, 'Repository', { removalPolicy: cdk.RemovalPolicy.DESTROY }); + +const asset = new s3assets.Asset(stack, 'asset', { + path: path.join(__dirname, 'assets', 'Dockerfile'), +}); + +new imagebuilder.ContainerRecipe(stack, 'ContainerRecipe', { + baseImage: imagebuilder.BaseContainerImage.fromDockerHub('amazonlinux', 'latest'), + targetRepository: imagebuilder.Repository.fromEcr(repository), + dockerfile: imagebuilder.DockerfileData.fromS3(asset.bucket, asset.s3ObjectKey), +}); + +new integ.IntegTest(app, 'ContainerRecipeTest', { + testCases: [stack], +});