🌧️

 AWS CDKのARN文字列に対するreplaceに失敗した話

2023/11/26に公開

結論

CDKのデプロイ時に確定するような値(ARNやリソース名)に対してreplaceは実行できない。
CloudFormationテンプレートが合成されるまでは内部的に${TOKEN[XXXX]}という文字列形式で取り扱われている。
公式ドキュメント:https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/tokens.html

失敗例

サンプルコード

.
├── bin
│   └── cdk.ts
├── lib
│   ├── sampleStack.SampleFunction.ts
│   └── sampleStack.ts
(略)
bin/cdk.ts
import * as cdk from 'aws-cdk-lib';
import { SampleStack } from '../lib/sampleStack';

const app = new cdk.App();
new SampleStack(app, 'SampleStack');
lib/sampleStack.SampleFunction.ts
export const handler = () => {
  console.log(process.env.queueArn)
};
lib/sampleStack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';

export class SampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    const queue = new sqs.Queue(this, 'SampleQueue', {
      queueName: 'sampleQueue',
      visibilityTimeout: cdk.Duration.seconds(300),
    });

    new NodejsFunction(this, 'SampleFunction', {
      functionName: 'sampleFunction',
      environment: {
        queueArn: queue.queueArn.replace('ap-northeast-1', 'us-east-1'),
      }
    });
  }
}

cdk deployを実行する

Lambdaの環境変数を確認すると、replace処理が実行されていないことが確認できる。

コンソールに出力して確認する

確認のため、エラーを吐かせてコンソールにqueue.queueArnを出力する。

lib/sampleStack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';

export class SampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    const queue = new sqs.Queue(this, 'SampleQueue', {
      queueName: 'sampleQueue',
      visibilityTimeout: cdk.Duration.seconds(300),
    });

    new NodejsFunction(this, 'SampleFunction', {
      functionName: 'sampleFunction',
      environment: {
        queueArn: queue.queueArn.replace('ap-northeast-1', 'us-east-1'),
      }
    });

    throw new Error(queue.queueArn);
  }
}

出力結果は以下のようになった。
queueのARNが${Token[TOKEN.16]}という文字列で扱われていることが確認できる。

/home/cdk-sample/lib/sampleStack.ts:22
    throw new Error(queue.queueArn);
          ^
Error: ${Token[TOKEN.16]}
    at new SampleStack (/home/cdk/lib/sampleStack.ts:22:11)
    at Object.<anonymous> (/home/cdk/bin/cdk.ts:5:1)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module.m._compile (/home/cdk/node_modules/ts-node/src/index.ts:1618:23)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Object.require.extensions.<computed> [as .ts] (/home/cdk/node_modules/ts-node/src/index.ts:1621:12)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Function.Module._load (node:internal/modules/cjs/loader:1023:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at phase4 (/home/cdk/node_modules/ts-node/src/bin.ts:649:14)

Subprocess exited with error 1

補足

文字列のreplace処理は失敗するが、連結処理は実行できる。
以下、公式ドキュメントより抜粋。

次の例に示すように、通常の文字列のように渡したり、連結したりできます。

const functionName = bucket.bucketName + 'Function';

また、次の例に示すように、使用している言語で文字列補間も使用できます。

const functionName = `${bucket.bucketName}Function`;

Discussion