Skip to content

Conversation

@tarunb12
Copy link
Contributor

@tarunb12 tarunb12 commented Nov 18, 2025

Issue

aws/aws-cdk-rfcs#789

Reason for this change

This change adds a new alpha module for EC2 Image Builder L2 Constructs (@aws-cdk/aws-imagebuilder-alpha), as outlined in aws/aws-cdk-rfcs#789. This PR specifically implements the ContainerRecipe construct.

Description of changes

This change implements the ContainerRecipe construct, which is a higher-level construct of CfnContainerRecipe.

Example

const containerRecipe = new imagebuilder.ContainerRecipe(this, 'ContainerRecipe', {
  containerRecipeName: 'test-container-recipe',
  containerRecipeVersion: '1.0.0',
  description: 'A Container Recipe',
  baseImage: imagebuilder.BaseImage.fromEcr(
    this,
    'ECRImage',
    ecr.Repository.fromRepositoryName(this, 'SourceRepository', 'source-repository'),
    'latest',
  ),
  dockerfile: imagebuilder.DockerfileData.fromInline(`
    FROM {{{ imagebuilder:parentImage }}}
    CMD ["echo", "Hello, world!"]
    {{{ imagebuilder:environments }}}
    {{{ imagebuilder:components }}}
  `),
  targetRepository: imagebuilder.Repository.fromEcr(
    ecr.Repository.fromRepositoryName(this, 'TargetRepository', 'imagebuilder-repository'),
  ),
  // Use an AWS-managed component, shared component, and a self-owned component with parameters
  components: [
    {
      component: imagebuilder.AwsManagedComponent.fromAwsManagedComponentName(
        this,
        'update-linux-component',
        'update-linux',
      ),
    },
    {
      component: imagebuilder.Component.fromComponentArn(
        this,
        'ComplianceTestComponent',
        `arn:${this.partition}:imagebuilder:${this.region}:123456789012:component/compliance-test/2025.x.x.x`,
      ),
    },
    {
      component: imagebuilder.Component.fromComponentAttributes(this, 'CustomComponent', {
        componentName: 'custom-component',
      }),
      parameters: {
        CUSTOM_PARAMETER: imagebuilder.ComponentParameterValue.fromString('custom-parameter-value'),
      },
    },
  ],
  workingDirectory: '/var/tmp',
  // The image + block devices to use for the EC2 instance used for building the container image
  instanceImage: imagebuilder.ContainerInstanceImage.fromSsmParameterName(
    this,
    'ContainerInstanceImage',
    '/aws/service/ecs/optimized-ami/amazon-linux-2023/recommended',
  ),
  instanceBlockDevices: [
    {
      deviceName: '/dev/sda1',
      mappingEnabled: true,
      volume: ec2.BlockDeviceVolume.ebs(50, {
        deleteOnTermination: true,
        iops: 1000,
        volumeType: ec2.EbsDeviceVolumeType.GP3,
        throughput: 1000,
        encrypted: true,
        kmsKey: kms.Key.fromLookup(this, 'VolumeKey', { aliasName: 'alias/volume-encryption-key' }),
      }),
    },
  ],
});

Describe any new or updated permissions being added

N/A - new L2 construct in alpha module

Description of how you validated changes

Validated with unit tests and integration tests. Manually verified generated CFN templates as well.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@github-actions github-actions bot added the p2 label Nov 18, 2025
@aws-cdk-automation aws-cdk-automation requested a review from a team November 18, 2025 08:18
@github-actions github-actions bot added the beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK label Nov 18, 2025
@aws-cdk-automation aws-cdk-automation added the pr/needs-further-review PR requires additional review from our team specialists due to the scope or complexity of changes. label Nov 18, 2025
@tarunb12 tarunb12 marked this pull request as ready for review November 18, 2025 09:02
@kumsmrit kumsmrit self-assigned this Nov 18, 2025
@aws-cdk-automation aws-cdk-automation added the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Nov 18, 2025
* @param string The container instance image as a direct string value
*/
public static fromString(string: string): BaseContainerImage {
return new ContainerInstanceImage(string);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the expected return type BaseContainerImage here?

// }

/**
* The string value of the base image to use in a container recipe
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we elaborate what could this string value represent.

}

/**
* The string value of the container instance image to use in a container recipe
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we elaborate what could this string value represent.

attrs: ContainerRecipeAttributes,
): IContainerRecipe {
if (attrs.containerRecipeArn && (attrs.containerRecipeName || attrs.containerRecipeVersion)) {
throw new cdk.ValidationError(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this validation error needed? Can we just not parse the attributes as required?

this.instanceBlockDevices.push(...instanceBlockDevices);
}

private renderBlockDevices(): CfnContainerRecipe.InstanceBlockDeviceMappingProperty[] | undefined {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add JSDoc here explaining what this helper does.

*
* @param string The base image as a direct string value
*/
public static fromString(string: string): BaseContainerImage {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Param name string is not intuitive, rename this to something meaningful and update doc string accordingly.

@tarunb12 tarunb12 force-pushed the imagebuilder-container-recipe branch from 039ee95 to b4532cb Compare November 19, 2025 04:21
@mergify mergify bot dismissed kumsmrit’s stale review November 19, 2025 04:22

Pull request has been modified.

@aws-cdk-automation aws-cdk-automation removed the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Nov 19, 2025
* @param parameter The SSM parameter to use as the container instance image
*/
public static fromSsmParameter(parameter: ssm.IStringParameter): ContainerInstanceImage {
return this.fromSsmParameterName(parameter.parameterArn);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method says parameterName, this should be changed to:

Suggested change
return this.fromSsmParameterName(parameter.parameterArn);
return this.fromSsmParameterName(parameter.parameterName);

}

/**
* The string value of the container instance image to use in a container recipe. This can either be an SSM parameter,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the CFN docs, this should be more explicit for SSM parameter:

Suggested change
* The string value of the container instance image to use in a container recipe. This can either be an SSM parameter,
* 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


const CONTAINER_RECIPE_SYMBOL = Symbol.for('@aws-cdk/aws-imagebuilder-alpha.ContainerRecipe');

const LATEST_VERSION = 'x.x.x';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add JSDoc here explaining what this magic value x.x.x represents, and link reference docs.

resource: 'container-recipe',
resourceName: `${this.physicalName}/${containerRecipeVersion}`,
});
this.containerRecipeVersion = containerRecipe.getAtt('Version').toString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CFN docs doesn’t define a return value with Version attribute for Fn::GetAtt

/**
* The version of the container recipe
*
* @attribute
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this marked as an attribute? CFN docs don’t define a Version return value.

* 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
* run all components in the recipe
* run all components in the recipe

* 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:/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
* Windows builds, this would be C:/
* Windows builds, this would be C:/

version: containerRecipeVersion,
description: props.description,
parentImage: props.baseImage.image,
containerType: 'DOCKER',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be extracted to enum to support other containerTypes?

*
* @default None
*/
readonly components?: ComponentConfiguration[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is marked optional, but CFN doc states - "Recipes require a minimum of one build component" ?


/**
* The resulting inline string or S3 URL which references the dockerfile data
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can also add:

* - For inline dockerfiles, this is the Dockerfile template text
* - For S3-backed dockerfiles, this is the S3 URL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK p2 pr/needs-further-review PR requires additional review from our team specialists due to the scope or complexity of changes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants