11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

「Develop fun!」を体現する! Works Human IntelligenceAdvent Calendar 2022

Day 11

[cdk] L2の既存リソースに、L1にしかない設定をした話

Last updated at Posted at 2022-12-10

この記事の想定読者

  • AWSの基本知識がある
  • CloudFormationを使った事がある
  • cdkも使った事がある

L1とL2(とL3)

スタックをコードとして管理したい時、CloudFormationではyamlかjson形式で記述します。cdkでは、TypeScriptなどのメジャーな言語で記載する事が出来ます。cdkは、内部的には一旦CloudFormationに変換します。

そのcdkでは3種類の記述方法があります。下に紹介した公式ページに詳細はお願いしますが、L1はCloudFormationと同レベルの細かい設定が必要ですが、L2は必須の情報だけ設定すればあとはcdkがよしなにデフォルト設定してくれます。

L3では標準的な構成に関してさらにサービスをまとめてくれます。例えばApplicationLoadBalancedFargateServiceではALBとFargateのスタックをまとめて対応してくれます。

L2の難点

コード上の設定箇所が少ないのでありがたいL2ですが、細かい部分を指定したい場合に、L2だと対応していない時があるという難点があります。事前にわかっていれば最初からL1で作成するなどの対応が可能ですが、既にL2でスタックを作成している場合にL1に切り替えるとリソースが作り直されてしまう可能性があります(※未検証。後述しますがL2からL1へのキャストも出来るぐらいなので、スタック名を同じにすれば条件によっては大丈夫かもしれません)。

今回の具体例

Cognitoで、ユーザーを作成した場合の招待メッセージや、認証コードを送信する際のメッセージのフォーマットを指定したいけど、L2のドキュメントを探してもではその属性が存在しませんでした。
L1のドキュメントでは「verificationMessageTemplate」、「adminCreateUserConfig」の2プロパティになります。

対応ポイント

後述、参考にさせて頂いたページの追記版になってしまいますが、以下の通りです。

L2オブジェクトをL1のクラスにキャストする

L2オブジェクトにあるnode.defaultChild属性で、L1のクラスにキャスト出来ます。

import * as cognito from "@aws-cdk/aws-cognito";
  // ・・中略・・
  // L2クラスのオブジェクト作成
  const userPool = new cognito.UserPool(this, "UserPool", {
  // ・・中略・・
  // L1クラスへキャスト
  const cfnUserPool = userPool.node.defaultChild as cognito.CfnUserPool;
  // ・・後略・・

addPropertyOverrideメソッドを使う

L1形式ではクラス名はCfn****となっていますが、表題のメソッドが存在します。このメソッドによりプロパティの上書きが出来ます。

プロパティ名および値はCloudFormationのものを使用

上記関数で指定する時、プロパティ名は値はCloudFormationを意識したものになります。
自分は躓いてしまった所なのですが、L1の設定名であるadminCreateUserConfigでは駄目で、CloudFormationの設定名であるAdminCreateUserConfigを使う必要があります(アッパーキャメルケースを使う)。
また、指定する値に関してです。プリミティブ型なら特に気にかけませんが、オブジェクト型の場合、L1のプロパティオブジェクトでなくjson形式で指定する必要があります。
L1クラスの関数なので当たり前と言えば当たり前です(L1形式ならaddPropertyOverrideを使わずに直接指定できる)。

成功
  cfnUserPool.addPropertyOverride('AdminCreateUserConfig', {
    InviteMessageTemplate: {
      EmailSubject: '仮パスワードをお送りします',
      EmailMessage: 'ユーザーIDは{username}です。一時パスワードは「{####}」です。 ',
      SMSMessage: 'ユーザーIDは{username}です。一時パスワードは「{####}」です。 '
    }
  });
  cfnUserPool.addPropertyOverride('VerificationMessageTemplate', {
    DefaultEmailOption: 'CONFIRM_WITH_CODE',
    EmailSubject: '認証コードをお送りします',
    EmailMessage: '認証コード「{####}」を入力してください。',
    SmsMessage: '認証コード「{####}」を入力してください。',
  });
駄目なケース
  const adminCreateUserConfig: cognito.CfnUserPool.AdminCreateUserConfigProperty = {
    allowAdminCreateUserOnly: true,
    inviteMessageTemplate: {
      emailSubject: "仮パスワードをお送りします",
      emailMessage: "ユーザーIDは{username}です。一時パスワードは「{####}」です。 ",
      smsMessage: "ユーザーIDは{username}です。一時パスワードは「{####}」です。 "
    }
  };
  const verificationMessageTemplateProperty: cognito.CfnUserPool.VerificationMessageTemplateProperty = {
    defaultEmailOption: 'CONFIRM_WITH_CODE',
    emailSubject: '認証コードをお送りします',
    emailMessage: '認証コード「{####}」を入力してください。',
    smsMessage: '認証コード「{####}」を入力してください。'
  };
  cfnUserPool.addPropertyOverride('adminCreateUserConfig', adminCreateUserConfig);
  cfnUserPool.addPropertyOverride('verificationMessageTemplate', verificationMessageTemplateProperty);

感想

今までL2の難点を考えて、細かい設定する時困るからL1で書こうかなとか思う時があったのですが、この関数の存在を知ったので、安心してL2を使う事が出来ます。L3だと複数種類のスタックで構成される事からnode.defaultChildでなく別の方法があると思います(※未調査。機会があったら調査して別記事にします)
結構常識的なナレッジかもしれませんが、自分が知らなかった事もあり、きっと誰かの役に立つだろうと信じての投稿でした。

参考にさせて頂いたページ

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?