skip to Main Content

In my cdk-eb-infra-stack.ts file, I’m getting an error when passing this as parameter into CDK methods.

Here’s what my file looks like:

import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import s3assets = require("@aws-cdk/aws-s3-assets");
import elasticbeanstalk = require("@aws-cdk/aws-elasticbeanstalk");
import iam = require("@aws-cdk/aws-iam");
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class CdkEbInfraStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here
    // Construct an S3 asset from the ZIP located from directory up
    const webAppZipArchive = new s3assets.Asset(this, "WebAppZip", {
      path: `${__dirname}/../app.zip`,
    });

    const appName = "REDACTED";
    const app = new elasticbeanstalk.CfnApplication(this, "Application", {
      applicationName: appName,
    });

    const appVersionProps = new elasticbeanstalk.CfnApplicationVersion(
      this,
      "AppVersion",
      {
        applicationName: appName,
        sourceBundle: {
          s3Bucket: webAppZipArchive.s3BucketName,
          s3Key: webAppZipArchive.s3ObjectKey,
        },
      }
    );

    appVersionProps.addDependsOn(app);

    // Create role and instance profile
    const myRole = new iam.Role(
      this,
      `${appName}-aws-elasticbeanstalk-ec2-role`,
      {
        assumeBy: new iam.ServicePrincipal("ec2.amazonaws.com"),
      }
    );

    const managedPolicy = iam.ManagedPolicy.fromAwsManagedPolicyName(
      "AWSElasticBeanstalkWebTier"
    );
    myRole.addManagedPolicy(managedPolicy);

    const myProfileName = `${appName}-InstanceProfile`;

    const instanceProfile = new iam.CfnInstanceProfile(this, myProfileName, {
      instanceProfileName: myProfileName,
      roles: [myRole.roleName],
    });

    const optionSettingProperties: elasticbeanstalk.CfnEnvironment.OptionSettingProperty[] =
      [
        {
          namespace: "aws:autoscaling:launchconfiguration",
          optionName: "IamInstanceProfile",
          value: myProfileName,
        },
        {
          namespace: "aws:autoscaling:asg",
          optionName: "MinSize",
          value: "1",
        },
        {
          namespace: "aws:autoscaling:asg",
          optionName: "MaxSize",
          value: "1",
        },
        {
          namespace: "aws:ec2:instances",
          optionName: "InstanceTypes",
          value: "t2.micro",
        },
      ];

    // Create an Elastic Beanstalk environment to run the application
    const elbEnv = new elasticbeanstalk.CfnEnvironment(this, "Environment", {
      environmentName: "REDACTED",
      applicationName: app.applicationName || appName,
      solutionStackName: "64bit Amazon Linux 2 v5.5.6 running Node.js 16",
      optionSettings: optionSettingProperties,
      versionLabel: appVersionProps.ref,
    });

    // example resource
    // const queue = new sqs.Queue(this, 'CdkEbInfraQueue', {
    //   visibilityTimeout: cdk.Duration.seconds(300)
    // });
  }
}

I know this problem occurs due to versions of aws-cdk packages differing, but I’ve implemented all the solutions I could find and I unfortunately haven’t been able to resolve it.

My dependencies in my package.json file look like this;

  "dependencies": {
    "@aws-cdk/aws-elasticbeanstalk": "^1.172.0",
    "@aws-cdk/aws-iam": "^1.172.0",
    "@aws-cdk/aws-s3-assets": "^1.172.0",
    "@aws-cdk/core": "^1.172.0",
    "aws-cdk-lib": "2.41.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.21"
  }

And my globally installed cdk looks like this:

[email protected]

Before, I had the global cdk installed at the latest version. I thought that it being a different version to the @aws-cdk packages might be causing the issue, so I downloaded it at the same version as the packages. It doesn’t seem to have solved the problem though.

These are all the packages installed in my cdk-eb-infra project directory:

├── @aws-cdk/[email protected]
├── @aws-cdk/[email protected]
├── @aws-cdk/[email protected]
├── @aws-cdk/[email protected]
├── @types/[email protected]
├── @types/[email protected]
├── @types/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

What is it that I’m missing here?

2

Answers


  1. Chosen as BEST ANSWER

    Pretty ridiculous that they haven't updated the documentation for this, but fortunately managed to resolve the problem. The solution had nothing to do with library version mismatch, but rather to do with the fact that importing individual libraries related to different AWS services is now legacy. AWS CDK v2 now stores all packages in aws-cdk-lib. When importing, import the individual dependencies from it like so (using s3 assets as an example):

    import { aws_s3 as s3 } from 'aws-cdk-lib';
    

    You can read more about it here.


  2. The guide OP linked to is outdated since AWS updated aws-cdk-lib to version 2 to include all the individual functions for AWS core services.
    these three lines (and corresponding code calling these libraries) are the problem:

    import iam = require('@aws-cdk/aws-iam');
    import elasticbeanstalk = require('@aws-cdk/aws-elasticbeanstalk');
    import s3assets = require('@aws-cdk/aws-s3-assets');
    

    Replace them with this line:

    import * as cdk from 'aws-cdk-lib';

    What this does is import all the classes from the entire library (maybe overkill, but it’s a beginner tutorial right?) So you automatically get every class from iam, elasticbeanstalk and s3assets.

    Later on in the code, though, you’ll have to rearrange slightly, for example line 14:

    // Construct an S3 asset from the ZIP located from directory up.
        const webAppZipArchive = new s3assets.Asset(this, 'WebAppZip', {
            path: `${__dirname}/../app.zip`,    });
    

    s3assets will no longer work since we don’t declare that up in the imports anymore with the require directive. (if you want this to work as the tutorial shows you can individually import aws-cdk classes using the info at "work with cdk typescript aws docs" )

    To fix this we need to specifically call the exact scope of the relevant construct – aws_s3_assets.Asset (see below):

     // Construct an S3 asset from the ZIP located from directory up.
    const webAppZipArchive = new cdk.aws_s3_assets.Asset(this,
    'WebAppZip', {
          path: `${__dirname}/../app.zip`,
    

    You’ll want to make this adjustment for every time you try to call one of your functions from your three outdated imports (iam, elasticbeanstalk, s3assets).

    I used ConstructsHub to look up the proper submodule names to update the code (make sure you change to latest version since that link might get stale quickly.)

    You will need to rm -rf node_modules , rm -rf package-lock.json and npm install to update your packages, then run npm build run to update the typescript.

    It should compile without error if you caught all the spots where the v2 functions changed.

    Lastly, I had to update the Environment Settings (last block of code) with a more recent SolutionStackName

    The current list can be found using
    aws elasticbeanstalk list-available-solution-stacks

    Pick your current node version. You can follow the rest of the tut to get deployed!

    Hope this helps someone else going through this!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search