Home > OS >  AWS CDK says Argument of type 'this' is not assignable to parameter of type 'Construc
AWS CDK says Argument of type 'this' is not assignable to parameter of type 'Construc

Time:01-11

I am working with a problem that has a few other similar solutions posted on stackoverflow

(1) Argument of type 'this' is not assignable to parameter of type 'Construct' in AWS CDK

(2) AWS CDK, typescript - Argument of type 'this' is not assignable to parameter of type 'Construct'

I tried making all my aws library versions match per this advice:

"This might happen because you are using CDK module with a different version than the CDK core library. CDK updates very often so it's a quite common error.

For fixing this you need to update all the cdk packages to the same version."

The advice is repeated here in different words, so i did all that:

Delete node_modules folder
Delete package-lock.json
Ensure all dependencies in package.json are using same version.
Remove carrot ^ symbol before dependencies
npm install

Now my package json is this:

{
    "name": "cdk-eb-infra",
    "version": "0.1.0",
    "bin": {
        "cdk-eb-infra": "bin/cdk-eb-infra.js"
    },
    "scripts": {
        "build": "tsc",
        "watch": "tsc -w",
        "test": "jest",
        "cdk": "cdk"
    },
    "devDependencies": {
        "@types/jest": "^29.2.4",
        "@types/node": "18.11.15",
        "aws-cdk": "2.59.0",
        "jest": "^29.3.1",
        "ts-jest": "^29.0.3",
        "ts-node": "^10.9.1",
        "typescript": "~4.9.4"
    },
    "dependencies": {
        "@aws-cdk/aws-elasticbeanstalk": "1.187.0", // note identical versions
        "@aws-cdk/aws-iam": "1.187.0", // note identical versions
        "@aws-cdk/aws-s3-assets": "1.187.0", // note identical versions
        "@aws-cdk/core": "1.187.0", // note identical versions
        "aws-cdk-lib": "2.59.0",
        "constructs": "^10.0.0",
        "source-map-support": "^0.5.21"
    }
}

Now I try to run cdk deploy and I get

lib/cdk-eb-infra-stack.ts:20:57 - error TS2345: Argument of type 'this' is not assignable to parameter of type 'Construct'.
  Type 'CdkEbInfraStack' is missing the following properties from type 'Construct': onValidate, onPrepare, onSynthesize, validate, and 2 more.

20         const app = new elasticbeanstalk.CfnApplication(this, "Application", {
                                                           ~~~~
lib/cdk-eb-infra-stack.ts:25:76 - error TS2345: Argument of type 'this' is not assignable to parameter of type 'Construct'.

25         const appVersionProps = new elasticbeanstalk.CfnApplicationVersion(this, "AppVersion", {
                                                                              ~~~~
lib/cdk-eb-infra-stack.ts:37:37 - error TS2345: Argument of type 'this' is not assignable to parameter of type 'Construct'.

37         const myRole = new iam.Role(this, `${appName}-aws-elasticbeanstalk-ec2-role`, {
                                       ~~~~
lib/cdk-eb-infra-stack.ts:46:60 - error TS2345: Argument of type 'this' is not assignable to parameter of type 'Construct'.

46         const instanceProfile = new iam.CfnInstanceProfile(this, myProfileName, {

What is the solution?

edit: Sharing the (sorry, long) code of my cdk-eb-infra-stack.ts file in the /lib folder:

import * as cdk from "aws-cdk-lib";
import iam = require("@aws-cdk/aws-iam");
import elasticbeanstalk = require("@aws-cdk/aws-elasticbeanstalk");
import s3assets = require("@aws-cdk/aws-s3-assets");
import { Construct } from "constructs";
// 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`,
        });

        // Create a ElasticBeanStalk app.
        const appName = "MyWebApp";
        const app = new elasticbeanstalk.CfnApplication(this, "Application", {
            applicationName: appName,
        });

        // Create an app version from the S3 asset defined earlier
        const appVersionProps = new elasticbeanstalk.CfnApplicationVersion(this, "AppVersion", {
            applicationName: appName,
            sourceBundle: {
                s3Bucket: webAppZipArchive.s3BucketName,
                s3Key: webAppZipArchive.s3ObjectKey,
            },
        });

        // Make sure that Elastic Beanstalk app exists before creating an app version
        appVersionProps.addDependsOn(app);

        // Create role and instance profile
        const myRole = new iam.Role(this, `${appName}-aws-elasticbeanstalk-ec2-role`, {
            assumedBy: 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],
        });
    }
}

I did exclusively copy-paste from Module 2: Create Infrastructure using AWS CDK

CodePudding user response:

You are mixing V1 and V2 dependencies. Remove the V1 dependencies, that is, the packages in your package.json with version 1.187.0. Import service-specific packages from aws-cdk-lib:

import {
  aws_iam as iam,
  aws_elasticbeanstalk as elasticbeanstalk,
  aws_s3_assets as s3_assets,
} from "aws-cdk-lib";

In V2, only the non-stable "alpha" modules are in separate packages.

CodePudding user response:

It appears you are mixing CDKv1 and CDKv2 packages.

CDKv2 Migration docs

This would fall under Ensure all dependencies in package.json are using same version.

Change

"dependencies": {
    "@aws-cdk/aws-elasticbeanstalk": "1.187.0", // note identical versions
    "@aws-cdk/aws-iam": "1.187.0", // note identical versions
    "@aws-cdk/aws-s3-assets": "1.187.0", // note identical versions
    "@aws-cdk/core": "1.187.0", // note identical versions
    "aws-cdk-lib": "2.59.0",
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.21"
}

to

"dependencies": {
    "aws-cdk-lib": "2.59.0", // CDKv2
    "constructs": "^10.0.0",
    "source-map-support": "^0.5.21"
}

Edit: per the answer from @fedonev

Update your imports like so:

import {
  aws_iam as iam,
  aws_elasticbeanstalk as elasticbeanstalk,
  aws_s3_assets as s3_assets,
} from "aws-cdk-lib";

In V2, only the non-stable "alpha" modules are in separate packages.

Pardon me, I am new to citing on StackOverflow. Edit if there is a better way to attribute @fedonev

CodePudding user response:

Both Fedonev and Jacob Greenbow posted helpful responses. I was able to make the following changes and get it working:

import { Stack, StackProps, aws_iam as iam, aws_elasticbeanstalk as elasticbeanstalk, aws_s3_assets as s3_assets } from "aws-cdk-lib";
import { Construct } from "constructs";
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class CdkEbInfraStack extends Stack {
    constructor(scope: Construct, id: string, props?: 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 s3_assets.Asset(this, "WebAppZip", {
            path: `${__dirname}/../app.zip`,
        });

        // Create a ElasticBeanStalk app.
        const appName = "MyWebApp";
        const app = new elasticbeanstalk.CfnApplication(this, "Application", {
            applicationName: appName,
        });

        // Create an app version from the S3 asset defined earlier
        const appVersionProps = new elasticbeanstalk.CfnApplicationVersion(this, "AppVersion", {
            applicationName: appName,
            sourceBundle: {
                s3Bucket: webAppZipArchive.s3BucketName,
                s3Key: webAppZipArchive.s3ObjectKey,
            },
        });

        // Make sure that Elastic Beanstalk app exists before creating an app version
        appVersionProps.addDependsOn(app);

        // Create role and instance profile
        const myRole = new iam.Role(this, `${appName}-aws-elasticbeanstalk-ec2-role`, {
            assumedBy: 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],
        });
    }
}

Note that the Stack and StackProps had to be imported too to avoid breaking the rest of amazon's example.

  • Related