question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

(aws-docdb): should not try to validate list of subnets if they are unresolved

See original GitHub issue

When importing a VPC information from CloudFormation Export (using fn.import) the cluster constructor does not work.

The VPC.fromVPCAttribute reference the subnets using one “ImportedSubnet”. When the DocumentCluster is constructed there is a check for the number of subnets (>=2). However in this case, the array of subnets contains only one object.

tried to comment the test in cluster.js and the CF template is properly created

Reproduction Steps

Assuming there is a stack exporting the following

Networking-VPC-ID => “vpc-XXXX” Networking-PrivateSubnets-IDs => “subnet-XXX,subnet-YYY,subnet-ZZZZ”

` vpc=Vpc.fromVpcAttributes(this.scope, “ImportedVPC”, { vpcId: Fn.importValue(“Networking-VPC-ID”), availabilityZones: Fn.getAzs(Aws.REGION), privateSubnetIds: Fn.split(“,”, Fn.importValue(“Networking-PrivateSubnets-IDs”)), });

cluster = new DatabaseCluster(this, DatabaseCluster, { instanceType: InstanceType.of(InstanceClass.T3, InstanceSize.MEDIUM), engineVersion: “4.0.0”, masterUser: { username: ‘masterUser’ // NOTE: ‘admin’ is reserved by DocumentDB }, vpc: vpc, vpcSubnets: { subnetType: SubnetType.PRIVATE } }); `

Generate the following error: Error: Cluster requires at least 2 subnets, got 1 .....

What did you expect to happen?

I was expecting to create a stack with a SubnetGroup as follow "Type": "AWS::DocDB::DBSubnetGroup", "Properties": { "DBSubnetGroupDescription": "Subnet group for DocumentDBConstruct-Database", "SubnetIds": { "Fn::Split": [ ",", { "Fn::ImportValue": "Networking-PrivateSubnets-IDs" } ] } },

What actually happened?

Does not generate the stack. The test in cluster.js if (subnetIds.length < 2) { throw new Error(Cluster requires at least 2 subnets, got ${subnetIds.length}); }

stop the synthetization of the stack

Environment

  • CDK CLI Version : N/A
  • Framework Version: 1.97.0
  • Node.js Version: v15.11.0
  • OS : Mac OS - N/A
  • **Language (Version): TypeScript **

Other

Issue is not environement specific. I believe the test in cluster.js to prevent creating a cluster on a VPC with only one Subnet kinda make sense. However it does not take into account the case when the vpc is imported from a CloudFormation Import (Standard practice in CF)


This is 🐛 Bug Report

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:7
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
mmassenziocommented, Dec 18, 2021

UPDATE

So this is definitely a bug, somewhere. If I try to deploy this very same code to a VPC with 2 PRIVATE subnets, it still fails, but commenting out the selection:

//            .vpcSubnets(subnetSelection)

then this works. It seems to me that somehow the selection of ISOLATED subnets is ignored (when it shouldn’t - ie, before the VPC lookup) but is then honored when it’s too late (at actual creation, after the lookup)

Or something like that - it’s really hard to figure out what’s going on where.

Bottom line, AFAICT, one cannot deploy a DocDB using CDK in a VPC with only ISOLATED subnets (well, it is possible, by doing some very hacky workaround to get the ckd.context.json created first).

If this is a known/desired limitation, it should be documented somewhere, though. Thanks.

0reactions
mmassenziocommented, Dec 18, 2021

Not sure whether this is a related issue, but when using a VPC “looked up” (via tags) the builder for DocDB fails; while the very same code for RDS (Postgres) succeeds - in the sense that CDK runs it twice: the first time it looks up the VPC (and creates the cdk.context.json file) and the second time round it uses it.

The funny thing is, if I comment out the DocDB code and make the CDK run once with synth it resolves the VPC (and creates the context) if I then uncomment the DocDB code, and make it run again, it success (because it finds it in the context).

I cannot share the entire repo, as it’s private, but here is the condensed version:

  1. the VPC code lookup (this works, in several places, no problem):
  public IVpc findVpc(Construct scope, String vpcName) {
    return Vpc.fromLookup(scope, "somethingelse", VpcLookupOptions.builder()
        .tags(Map.of(
            VPC_NAME, vpcName,
            ENVIRONMENT, p.getDeploymentEnv()
        ))
        .build());
  }

(incidentally we use the VPC_NAME tag instead of the vpcName() method, because the actual name gets mangled with the stack name, and instead we want to preserve the actual name we configure – it doesn’t really matter, this code works just fine)

The VPC is deployed across 2 AZs and has only ISOLATED subnets (yes, I know they are deprecated, but no one bothered to adjust the Java version of CDK, so that’s all there is right now)

Unfortunately, this fails:

    SubnetSelection subnetSelection = SubnetSelection.builder()
        .subnetType(SubnetType.ISOLATED)
        .build();

    software.amazon.awscdk.services.docdb.DatabaseCluster dbCluster =
        DatabaseCluster.Builder.create(scope, "ApiDocDb")
            .dbClusterName(mongo.getDbName())
            .masterUser(Login.builder()
                .username(mongo.getAdminUser())
                .kmsKey(passwordKey)
                .password(SecretValue.secretsManager(mongo.getSsmSecretName()))
                .build())
            .vpc(vpc)
            .vpcSubnets(subnetSelection)
            .securityGroup(dbSecurityGroup)
            .instanceType(InstanceType.of(InstanceClass.MEMORY5, InstanceSize.LARGE))
            .instances(mongo.getReplicas())
            .storageEncrypted(true)
            .build();

with this error:

21-12-17 Fri 21:01:51 [WARN ] Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'main': Invocation of init method failed; nested exception is software.amazon.jsii.JsiiException: Cluster requires at least 2 subnets, got 0
Error: Cluster requires at least 2 subnets, got 0
    at new DatabaseCluster (/tmp/jsii-kernel-3Hii0j/node_modules/@aws-cdk/aws-docdb/lib/cluster.js:61:19)
    at /tmp/jsii-java-runtime17765149654098498693/lib/program.js:8432:58
    at Kernel._wrapSandboxCode (/tmp/jsii-java-runtime17765149654098498693/lib/program.js:8860:24)
    at Kernel._create (/tmp/jsii-java-runtime17765149654098498693/lib/program.js:8432:34)
    at Kernel.create (/tmp/jsii-java-runtime17765149654098498693/lib/program.js:8173:29)
    at KernelHost.processRequest (/tmp/jsii-java-runtime17765149654098498693/lib/program.js:9757:36)
    at KernelHost.run (/tmp/jsii-java-runtime17765149654098498693/lib/program.js:9720:22)
    at Immediate._onImmediate (/tmp/jsii-java-runtime17765149654098498693/lib/program.js:9721:46)
    at processImmediate (internal/timers.js:464:21)

When we run the exact same code (in the same class, pretty much all the same) but for RDS:

    software.amazon.awscdk.services.rds.DatabaseInstance dbInstance =
        software.amazon.awscdk.services.rds.DatabaseInstance.Builder.create(scope,
                "PostgresDB")
            .engine(engine)
            .instanceIdentifier(postgres.getDbName())
            .vpc(vpc)
            .vpcSubnets(SubnetSelection.builder()
                .subnetType(SubnetType.ISOLATED)
                .build())
            .securityGroups(List.of(dbSecurityGroup))
            .instanceType(InstanceType.of(
                InstanceClass.BURSTABLE3,
                InstanceSize.SMALL))
            .credentials(Credentials.fromSecret(masterPassword))
            .backupRetention(Duration.days(RETENTION_DAYS))
            .storageEncrypted(true)
            .storageEncryptionKey(pgKey)
            .deleteAutomatedBackups(true)
            .performanceInsightRetention(PerformanceInsightRetention.LONG_TERM)
            .publiclyAccessible(false)
            .build();

this works just fine.

Not really sure whether this is a bug, or “works as intended” and I’m missing how to work around it. Looking pretty much everywhere on the intertubes provided no clue - any suggestion appreciated.

We’re using CDK and Solutions versions 1.129.0 (this is the most recent for Solutions; and yes, I know 2.0 is out, but right now we need this to work)

Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Creating an Amazon DocumentDB Subnet Group
When creating an Amazon DocumentDB cluster, you must choose a Amazon VPC and corresponding subnet group within that Amazon VPC to launch your...
Read more >
VPC error: Unresolved resource dependencies [VPC] in the ...
i am trying to launch and ec2 instance in public subnet (subnetA) and rds in private subnet (subnetB). it creates the vpc but...
Read more >
How can I check when a subnet was created?
If you don't have CloudTrail enabled, you will probably be out of luck, as I don't see a timestamp field available via the...
Read more >
Creating an Amazon DocumentDB Subnet Group - 亚马逊云科技
When creating an Amazon DocumentDB cluster, you must choose a Amazon VPC and ... If you attempt to create an instance in AZ...
Read more >
How do I resolve template validation or template format errors ...
How to Create a VPC Using Cloudformation · CloudFormation Course for Beginners · How to avoid the AWS CloudFormation Resource Limit - Serverless ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found