11
0

AWS CDKでクイック作成リンク用のテンプレートを合成する

Posted at

クイック作成リンクとは

CloudFormationのスタック作成用マネジメントコンソールへリンクするURLを使って,GUIで簡単にスタックを作成する仕組み.URLのクエリパラメータにスタック名やスタックのパラメータを埋め込むことができるので,それらはページを開いたときに入力済となるので,最短1クリックでスタックを作成可能なページを準備できます.

公式ドキュメント

使いどころ

顧客など非開発者がGUIを操作してスタックを作成する際などに便利です.クイック作成リンクあらかじめ作成しお渡ししておけば,誰でもCloudFormationスタックを作成可能です.

CDKを使ってクイック作成リンクを作成する手順

前提

  • cdk init 実施済
  • cdk bootstrap 実施済

手順

  1. CDKを使って,スタックパラメータを含むテンプレートを合成する(鬼門)
  2. cdk-assetsを使って,テンプレートをS3にpushする
  3. クイック作成リンクを生成する

STEP1:CDKを使って,スタックパラメータを含むテンプレートを合成する

CfnParameterクラスを使って,スタックパラメータを含むCDKのコードを実装していきます.CfnParameterクラスはCDKの一般的なユースケースにおいて非推奨とされていますが,クイック作成リンクのユースケースにおいては使わざる得ないです.
公式ドキュメントにて一般的にはメリットがないと明記されており,constractの利用が推奨されています.)

本記事では,下記のサンプルコードを例に部分的に抜粋しながら解説します.パラメータをもとに2つのSQSの作成するCDKのサンプルです.
※サンプルコード全体は,GitHub上に公開しているのでご参照ください.

// サンプルコード
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as sqs from 'aws-cdk-lib/aws-sqs';

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

    // params
    const fifoQueue = new cdk.CfnParameter(this, 'ParamFifoQueue', {
      allowedValues: ['true', 'false'],
      default: 'false'
    });
    const contentBasedDeduplication = new cdk.CfnParameter(this, 'ParamContentBasedDeduplication', {
      allowedValues: ['true', 'false'],
      default: 'false'
    });
    const visibilityTimeout = new cdk.CfnParameter(this, 'ParamVisibilityTimeout', {
      type: 'Number',
      default: 300
    })

    // example resource (SQS-1)
    const queue1 = new sqs.Queue(this, 'CdkQuickCreateLinksQueue1', {
      visibilityTimeout: cdk.Duration.seconds(visibilityTimeout.valueAsNumber)
    });

    // set bool params to prop as L1 construct (SQS-1)
    const cfnQueue1 = queue1.node.defaultChild as sqs.CfnQueue;
    const fifoCondition = new cdk.CfnCondition(this, 'FifoCondition', {
      expression: cdk.Fn.conditionEquals(fifoQueue, 'true')
    })
    cfnQueue1.addPropertyOverride('FifoQueue',
      cdk.Fn.conditionIf(fifoCondition.logicalId, true, cdk.Fn.ref("AWS::NoValue"))
    );

    // example resource (SQS-2)
    const queue2 = new sqs.Queue(this, 'CdkQuickCreateLinksQueue2', {
      fifo: true,
      visibilityTimeout: cdk.Duration.seconds(visibilityTimeout.valueAsNumber)
    });

    // set bool params to prop as L1 construct (SQS-2)
    const cfnQueue2 = queue2.node.defaultChild as sqs.CfnQueue;
    cfnQueue2.addPropertyOverride('ContentBasedDeduplication',
      cdk.Fn.ref(contentBasedDeduplication.logicalId)
    );

    // output for check params
    new cdk.CfnOutput(this, 'OutputFifoQueue', {
      value: fifoQueue.valueAsString
    })
    new cdk.CfnOutput(this, 'OutputContentBasedDeduplication', {
      value: contentBasedDeduplication.valueAsString
    })
    new cdk.CfnOutput(this, 'OutputVisibilityTimeout', {
      value: visibilityTimeout.valueAsString
    })
  }
}

パラメータの定義

// パラメータ定義抜粋
const fifoQueue = new cdk.CfnParameter(this, 'ParamFifoQueue', {
      allowedValues: ['true', 'false'],
      default: 'false'
    });
const contentBasedDeduplication = new cdk.CfnParameter(this, 'ParamContentBasedDeduplication', {
  allowedValues: ['true', 'false'],
  default: 'false'
});
const visibilityTimeout = new cdk.CfnParameter(this, 'ParamVisibilityTimeout', {
  type: 'Number',
  default: 300
})

今回用意するパラメータは3つ.2つはbool型(実際にはtrue/falseの文字列)と,数値のパラメータが1つです.

パラメータをリソースのpropsに引き渡し

i. 数値や文字列の場合

// SQS作成部分抜粋(数値パラメータの場合)
const queue1 = new sqs.Queue(this, 'CdkQuickCreateLinksQueue1', {
  visibilityTimeout: cdk.Duration.seconds(visibilityTimeout.valueAsNumber)
});

数値や文字列のパラメータの場合,valueAsNumbervalueAsStringを用いてL2コンストラクタのpropsにそのままパラメータを引き渡すことが可能です.
cdk synth実行後に合成されるテンプレートをみると,組み込み関数Refを用いて,パラメータがスタック作成時に後から参照されるようにテンプレートが合成されます.

{
    "Parameters": {
        "ParamVisibilityTimeout": {
            "Type": "Number",
            "Default": 300
        }
    },
    "Resources": {
        "CdkQuickCreateLinksQueue254C8F5FB": {
            "Type": "AWS::SQS::Queue",
            "Properties": {
                "VisibilityTimeout": {
                 "Ref": "ParamVisibilityTimeout"
                }
            }
        }
    }
}

ii. boolの場合

boolの場合が鬼門で,valueAsBoolが用意されておらず,L2コンストラクトのbool型のpropに文字列を引き渡すことはできません.
また,CfnParameterはテンプレート合成時に実際のValueが取得できないので,例えば下記のような条件文を使った制御はできません.(このあたりが一般的にCfnParameterが非推奨とされている理由のようです.)

// NGコード
const queue1 = new sqs.Queue(this, 'CdkQuickCreateLinksQueue1', {
  fifo: fifoQueue.valueAsString === 'true'
});

そこでbool型の場合,L2コンストラクトをL1コンストラクトに変換したうえで,合成後のCloudFormationテンプレートをそのまま記述する要領で,リソースのpropsにパラメータの参照情報を上書きしていきます.その設定方法は複数あります.
第一に,true or nullを設定する場合は,下記にように実装する方法があります.例えばSQSのFifoQueue設定の場合,標準キューを作成する際に明示的にfalseを設定するとスタックの作成に失敗してしまうので,その場合はAWS::NoValueが設定されるようにconditionを組み立てていきます.
参考

// SQS設定上書き部分抜粋(boolパラメータ設定例1)
const cfnQueue1 = queue1.node.defaultChild as sqs.CfnQueue;
const fifoCondition = new cdk.CfnCondition(this, 'FifoCondition', {
  expression: cdk.Fn.conditionEquals(fifoQueue, 'true')
})
cfnQueue1.addPropertyOverride('FifoQueue',
  cdk.Fn.conditionIf(fifoCondition.logicalId, true, cdk.Fn.ref("AWS::NoValue"))
);

一方で,SQSのコンテンツに基づく重複排除設定の例の場合,単純にtrue/falseを設定することができるので,conditionの組み立ては不要です.

// SQS設定上書き部分抜粋(boolパラメータ設定例2)
const cfnQueue2 = queue2.node.defaultChild as sqs.CfnQueue;
cfnQueue2.addPropertyOverride('ContentBasedDeduplication',
  cdk.Fn.ref(contentBasedDeduplication.logicalId)
);

最後に,CDKの実装が終わったらcdk synthを実行してテンプレートを合成します.

STEP2:cdk-assetsを使って,テンプレートをS3にpushする

テンプレートを合成したら,CDKプロジェクト配下でnpm install cdk-assetsを実行し,テンプレートをS3にpushするパッケージをインストールのうえ,cdk-assets publish --path cdk.out/<XXXX: synthで合成されたテンプレート>Stack.assets.json -v を実行します.これにより,cdk bootstrap時に生成されたS3バケットに対してテンプレートがpushされます.
(本記事のサンプルコードの場合は,実際はnpx cdk-assets publish --path cdk.out/CdkDeploymentControllerTestStack.assets.json -vというコマンドになります.)

cdk-assetsが何者かについては,こちらで一部解説されています.通常のCDKフローにおいては,cdk deployコマンドでテンプレートのS3 pushとスタックの作成が同時に行われますが,cdk-assetsを用いることでテンプレートのS3 pushのみを実行できます.

STEP3:クイック作成リンクを生成する

クイック作成リンクのURLの構文は,公式ドキュメントに記載されています.

templateURLに設定すべきクエリですが,デフォルトのままcdk bootstrapを行った場合,cdk-XXXXXXX-assets-<aws account number>-<region>といった見た目のS3バケットにテンプレートがpushされます.cdk assetsコマンドの実行結果からも,push先のバケットとオブジェクトが確認可能です.

※ クイックパラメータのイメージ

https://(region).console.aws.amazon.com/cloudformation/home?region=(region)#/stacks/create/review
?stackName=(your Stack name)
&templateURL=(your template S3 URL)
&param_ParamContentBasedDeduplication=(true/false)
&param_ParamFifoQueue=(true/false)
&param_ParamVisibilityTimeout=(123)

クエリパラメータ(param_Xxxxxx)を省略した場合,CDKのCfnParameterで設定したデフォルト値が入ります.

あとは,生成したクイック作成リンクを実際にスタックを作成する人に教えたうえで,マネジメントコンソールログイン状態でアクセスしてもらうことで,スタック名やパラメータをGUI上で確認しながら,1クリックでスタックを作成できます.
もちろん,GUI上のデフォルトで入力されている値を後から変更することは可能です.

まとめ(クイック作成リンク×CDKの惜しいところ)

CDKは素のCloudFormationよりも「よしなに」AWSリソースを構築してくれるため大変便利ですが,クイック作成リンクを使う場合は本来非推奨のCFnParameterを使わざる得ないため,特にbool型のパラメータを使う場合に苦労する可能性があります.
また,クイック作成リンクはスタックを新規で作成する際に使うことができますが,既存スタックの更新する際には使えないなど,少々惜しい点が残ります.

参考リンク

11
0
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
0