Aws-cdk: Vpc.fromLookup can't determine region

Created on 5 Nov 2019  路  19Comments  路  Source: aws/aws-cdk


I receive this error

Cannot retrieve value from context provider vpc-provider since account/region are not specified at the stack level. Either configure "env" with explicit account and region when you define your stack, or use the environment variables "CDK_DEFAULT_ACCOUNT" and "CDK_DEFAULT_REGION" to inherit environment information from the CLI (not recommended for production stacks)

even though I set the env in the stack and also set the environment variable CDK_DEFAULT_REGION.

Reproduction Steps

import cdk = require('@aws-cdk/core');
import {  Vpc } from "@aws-cdk/aws-ec2";

const stack = new cdk.Stack(
    new cdk.App(),
    'test',
    {
        env: {
            region: 'us-west-2'
        }
    }
);

Vpc.fromLookup( stack, 'vpc-lookup', { isDefault: true} );

Error Log

Cannot retrieve value from context provider vpc-provider since account/region are not specified at the stack level. Either configure "env" with explicit account and region when you define your stack, or use the environment variables "CDK_DEFAULT_ACCOUNT" and "CDK_DEFAULT_REGION" to inherit environment information from the CLI (not recommended for production stacks)

Environment

  • CLI Version : 1.13.1 (build 96cfc63)
  • Framework Version:: 1.13.1
  • OS : Linux (Manjaro)
  • Language : TypeScript

This is :bug: Bug Report

@aws-cdaws-ec2 bug

All 19 comments

@aaronsturm like the error message says, you're missing the account in your env. So it should be:

const stack = new cdk.Stack(new cdk.App(), 'test', {
  env: {
    region: 'us-west-2',
    account: '123456789012', // your account here
  },
});

Thanks,
Adam

Wouldn't that be picked up from from ~/.aws folder? I didn't set that since deploys were working without needing to set that variable.

No, it won't be taken from ~/.aws. It needs to be set explicitly.

Thanks for the quick responses! Is this a feature that I can request, or will that always be the case? We switch between AWS environments through the AWS_PROFILE environment variable. I'll create an internal workaround for now.

@skinny85 I'm running into the same issue even when I define the environment fully with region and account. Tried getting some help on gitter, but no luck. I added some logging to see what is going on and noticed that they are output twice, once resolved, then unresolved. Doesn't matter that they seem to be found (as indicated by --verbose output) by the CDK. What am I missing? I'm using aws-mfa

import cdk = require("@aws-cdk/core");
import ec2 = require("@aws-cdk/aws-ec2");

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

    console.log(`stack.account ${this.account}, stack.region ${this.region}`)
    console.log(`stack.account ${cdk.Token.isUnresolved(this.account)}, stack.region >${cdk.Token.isUnresolved(this.region)}`)

    ec2.Vpc.fromLookup(this, "whatever", { tags: { ["sx_name"]: "primary"}});
  }
}

const cdkEnv: cdk.Environment = {
  region: process.env.CDK_DEFAULT_REGION,
  account: process.env.CDK_DEFAULT_ACCOUNT
}

const xpEnv: cdk.Environment = {
  region: 'us-east-1',
  account: '123456789012'
}

const chosenEnv = xpEnv
console.log(`ourEnv.account: ${chosenEnv.account}, ourEnv.region: ${chosenEnv.region}`)

new TestInitStack(new cdk.App(), "TestInitStack", {
    env: chosenEnv
});
--verbose output:
env: {
  CDK_DEFAULT_REGION: 'us-east-1',
  CDK_DEFAULT_ACCOUNT: '123456789012',
  CDK_CONTEXT_JSON: '{"aws:cdk:enable-path-metadata":true,"aws:cdk:enable-asset-metadata":true}',
  CDK_OUTDIR: 'cdk.out',
  CDK_CLI_ASM_VERSION: '1.10.0',
  CDK_CLI_VERSION: '1.15.0'
}
ourEnv.account: 123456789012, ourEnv.region: us-east-1
stack.account 123456789012, stack.region us-east-1
stack.account false, stack.region false
stack.account ${Token[AWS::AccountId.0]}, stack.region ${Token[AWS::Region.4]}
stack.account true, stack.region true
Cannot retrieve value from context provider vpc-provider since account/region are not specified at the stack level. Either configure "env" with explicit account and region when you define your stack, or use the environment variables "CDK_DEFAULT_ACCOUNT" and "CDK_DEFAULT_REGION" to inherit environment information from the CLI (not recommended for production stacks)
Subprocess exited with error 1
Error: Subprocess exited with error 1
    at ChildProcess.<anonymous> (/usr/local/lib/node_modules/aws-cdk/lib/api/cxapp/exec.ts:115:23)

When if I set the environment variable CDK_DEFAULT_ACCOUNT=1234 (obviously using my account) I get the same error message. I even tried inlining it CDK_DEFAULT_ACCOUNT=1234 cdk deploy. Am I doing something wrong?

The CDK sets them based on your ~/.aws setup. If you want to use the environment variables in code, you define the stack props like so:
{ env { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT } }
Unfortunately, in my case the stack props env doesn't seem to stick (see my comment) and I get the error anyways.

Read up on this: https://docs.aws.amazon.com/cdk/latest/guide/environments.html

If you want to use dynamic AWS accounts, you must use code like the following:

new MyDevStack(this, 'dev', { 
  env: { 
    account: process.env.CDK_DEFAULT_ACCOUNT, 
    region: process.env.CDK_DEFAULT_REGION 
}});

We recommend that you don't, and that if you want to deploy to 5 different accounts, you instantiate your stack 5 times in your application, once for each account. Defining where a stack goes is different from obtaining credentials necessary to deploy it.

Closing this issue.

@niels1voo, I cannot reproduce your problem. The code you showed works for me as intended. Please open a new issue if you would like to dig into this deeper.

@skinny85 Any how to specify the current account and region where the stack is being created?

@skinny85 Any how to specify the current account and region where the stack is being created?

From #5724, I assume you're using Python, so it would be:

class MyStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # your constructs go here...

And then when actually instantiating MyStack:

```python
from aws_cdk import core
from hello.hello_stack import MyStack

app = core.App()
MyStack(app, "Name", env={'region': 'us-west-2', 'account': '123456789012'})
app.synth()

@skinny85 Thanks. I use like below, but just wanted whether it can be inferred like cfn sedoname AWS::Account.

Ec2Stack(app, "ec2",env=core.Enviornment('region'= 'ap-southeast-2',
'account'= '1234567890'))

You can skip passing env when creating your stack, but then you can't use Vpc.from_lookup (what account would the CDK use to lookup the VPC in?).

@skinny85 In the same account the stack to be created passed via the --profile.

@skinny85 In the same account the stack to be created passed via the --profile.

No. That would mean a different template could be generated depending on what you pass in the command-line --profile switch. That's against CDK tenets -- a template should be stable with regards to its inputs. Everything that changes its behavior should be in source code, not from ephemeral inputs like command-line options.

@skinny85 Thanks. Does it also mean that generated cfn by cdk synth is not meant to be used in other cases e.g. service catalog where we want the stack to work differently based on input provided in cfn param?

No, it's fine to use for those cases, but you can't rely on things like Vpc.from_lookup in those templates (that makes sense I hope, because every account / region will have different VPCs!). You would probably either create the VPC in that same template, or pass in the VPC ID through a parameter, for example.

@skinny85 I have also found that I can use core.AWS.ACCOUNT_ID

https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_core.Aws.html

Sure. There's also Aws.REGION, Aws.STACK_NAME, etc. Just don't use Vpc.from_lookup 馃檪.

No, it's fine to use for those cases, but you can't rely on things like Vpc.from_lookup in those templates (that makes sense I hope, because every account / region will have different VPCs!). You would probably either create the VPC in that same template, or pass in the VPC ID through a parameter, for example.

How does it work as a param? I can't synth a stack which uses CfnParameter to pass VpcId to fromLookup because of the error Vpc.fromLookup() must be concrete (no Tokens). I'm struggling to come up with a strategy to synth a stack in CDK which dynamically looks up a vpc based on vpcId or tag input and doesn't have hardcoded account/region.

Was this page helpful?
0 / 5 - 0 ratings