Skip to content

aws-cdk-lib: AwsCustomResource sometimes does not install dependencies correctly #28005

@ijxy

Description

@ijxy

Describe the bug

We use a custom resource to invoke a cloudfront invalidation, leveraging the AwsCustomResource construct to do so.

Usually this works fine, but sometimes it fails due to a missing @aws-sdk/client-cloudfront error. In other words, there sometimes seems to be an issue with installing the AWS SDK.

Expected Behavior

The custom resource should install the required AWS SDK dependencies and Just Work.

Current Behavior

Usually the invalidation works as expected, but it regularly fails with the below error:

❌ Deployment failed: Error: The stack named <redacted> failed to deploy: UPDATE_ROLLBACK_COMPLETE: Received response status [FAILED] from custom resource. Message returned: Package @aws-sdk/client-cloudfront does not exist. (RequestId: 864c37-7ce-4ba9-9bdb-9fa82af627)
at FullCloudFormationDeployment.monitorDeployment (/home/runner/work/<redacted>/<redacted>/node_modules/aws-cdk/lib/index.js:426:0236)
at process.processTicksAndRejections (node:internal/process/task_queues:9
:
)
at async Object.deployStack2 [as deployStack] (/home/runner/work/<redacted>/<redacted>/node_modules/aws-cdk/lib/index.js:429:***3307)
at async /home/runner/work/<redacted>/<redacted>/node_modules/aws-cdk/lib/index.js:429:3698

Reproduction Steps

Below is the exact code for the custom resource that we are using.

import {aws_cloudfront, custom_resources} from "aws-cdk-lib";
import {Construct} from "constructs";

export type CloudFrontInvalidationProps = {
  distribution: aws_cloudfront.IDistribution;
  paths: Array<string>;
};

export class CloudFrontInvalidation extends custom_resources.AwsCustomResource {
  constructor(scope: Construct, {distribution, paths}: CloudFrontInvalidationProps) {
    const id = `CloudFrontInvalidation-${Date.now()}`;
    super(scope, id, {
      onCreate: {
        physicalResourceId: custom_resources.PhysicalResourceId.fromResponse("Invalidation.Id"),
        service: "CloudFront",
        action: "createInvalidation",
        parameters: {
          DistributionId: distribution.distributionId,
          InvalidationBatch: {
            CallerReference: Date.now().toString(),
            Paths: {
              Quantity: paths.length,
              Items: paths,
            },
          },
        },
      },
      policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({
        resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE,
      }),
    });
  }
}

We use this construct in conjunction with two BucketDeployments such that the invalidation is triggered after the distribution and bucket deployments have finished updating, like so:

const invalidation = new CloudFrontInvalidation(this, {
  distribution,
  paths: ["/*"],
});
invalidation.node.addDependency(distribution, hashedAssetsDeployment, unhashedAssetsDeployment);

Possible Solution

https://github.com/aws/aws-cdk/tree/main/packages/aws-cdk-lib/custom-resources

The manner in which AWS SDK dependencies are handled seems to be by installing the V2 SDK and then using an adapter.

I don't see why it needs to be so convoluted and brittle–at this point in time, using the V3 SDK directly seems like the sensible thing to do since they are pre-installed in the Lambda Runtime on Node ≥18 (ie installing them should not even be needed).

Additional Information/Context

No response

CDK CLI Version

2.90.0 (build 8c535e4)

Framework Version

No response

Node.js Version

18

OS

Linux

Language

TypeScript

Language Version

No response

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    aws-cdk-libRelated to the aws-cdk-lib packagebugThis issue is a bug.closed-for-stalenessThis issue was automatically closed because it hadn't received any attention in a while.response-requestedWaiting on additional info and feedback. Will move to "closing-soon" in 7 days.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions