環境
- node @12.18.3
- npm @6.14.6
- aws-cdk @1.61.1
事象
cdk init
で作成したプロジェクトで、
cdk deploy
時に以下のエラーメッセージが表示され、デプロイを進めることができない。
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
原因
環境変数にCDK_DEFAULT_ACCOUNT
とCDK_DEFAULT_REGION
設定されていないかららしい。
もしくは自身のStack
クラスのprops
にenv
を渡してあげればよいとのこと。
コード中にVpc.fromLookup
を使用している箇所があるのだが、この環境変数が無いと既存のVPCを探しに行けないようでエラーになる模様。
ハマる
まず、試しに環境変数CDK_DEFAULT_ACCOUNT
とCDK_DEFAULT_REGION
を設定してやってみる。
$ export CDK_DEFAULT_ACCOUNT=xxxxxxxxx
$ export CDK_DEFAULT_REGION=ap-northeast-1
$ cdk deploy
設定しましたが?😇
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
まだハマる
となればもう一つの手段、env
を設定する方法で試してみる。
const app = new cdk.App();
new MyStack(app, 'my-stack', {
env: {
acount: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION
}
})
が、これも同じエラーが出て結局動かない。
どうも納得がいかないので、ライブラリのソースコードを見にいく。
まさか渡したenv
が実は渡ってないんじゃ無いの?と思いconsole.log
を置いてみる。
aws-cdk/core > lib > context-provider.js@42行目付近
static getValue(scope, options) {
const stack = stack_1.Stack.of(scope);
+ console.log(util.inspect(scope))
if (token_1.Token.isUnresolved(stack.account) || token_1.Token.isUnresolved(stack.region)) {
throw new Error(`Cannot retrieve value from context provider ${options.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)');
}
保存して、cdk deploy
WatchDifferentialLogsStack {
node:
ConstructNode { ... },
account: 'xxxxxxxxxxxx',
region: 'ap-northeast-1',
environment: 'aws://xxxxxxxxxxxx/ap-northeast-1',
terminationProtection: undefined,
_stackName: 'my-stack',
tags:
TagManager { ... },
}
WatchDifferentialLogsStack {
node:
ConstructNode { ... },
account: '${Token[AWS.AccountId.0]}',
region: '${Token[AWS.Region.4]}',
environment: 'aws://unknown-account/unknown-region',
terminationProtection: undefined,
_stackName: 'my-stack',
tags:
TagManager { ... },
}
※出力されたログが長いので一部省略
このクラスが謎に2回呼ばれている上に、2回目の方はaccount
もregion
も消えてしまっており、このタイミングでエラーが出ていることがわかる。
const app = new cdk.App();
new MyStack(app, 'my-stack', {
env: {
acount: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION
}
})
このコード自体を消してみると1回だけ呼ばれ、account
とregion
が消えている方のログだけが出力される。
つまり何かしらの機構で自動的に呼ばれているためそちら側でenv
を差さなければならないのでは?
対策
呼んでいるところで差せるのがベストではあるが見つからないため、外で差せないなら中で差せばいいのではないかと思いつき下記のように。
export class MyStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
const newProps = props ?? {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION
}
}
super(scope, id, newProps);
}
ひとまず無事に通って、デプロイはできるように🎉
ただこれで良いのかどうかはすごい微妙なので、もっとスマートな解決方法ご存知の方がいらっしゃいましたら私にも教えてください😇
Issue
実は、GithubのIssueにこの手のものは結構出ているけれども、
一通り眺めてみてもあまり解決していなさそう。