CloudFormationテンプレートファイルからパラメータシートを自動生成するツールの紹介

この記事は、NTTテクノクロス Advent Calendar 2022の25日目（最終日）の記事になります。
こんにちは。NTTテクノクロスの堀江です。普段はAWSやAzure上でのシステム設計、構築や調査検証系の案件を幅広く担当しています。

## はじめに

本記事では、AWS CloudFormation（以降、cfnと表記）のテンプレートファイルから、表形式のパラメータシートを自動生成する自作ツール - 名付けて「**cfn-docgen**」 - を紹介したいと思います。
ツールの概要と使い方だけでなく、ツールを作成するに至った背景と、私が考えるプラクティスについても説明していきたいと思います。

## cfn-docgenとは

**cfn-docgenは、Json/Yaml形式で記述されたcfnテンプレートファイルから、表形式のパラメータシート - リソース及びその設定値や特記事項の一覧が表形式で記載されたシート - を自動生成するコマンドラインツールです。**
具体的には、例えば下記のようなcfnテンプレートファイルから、

```Yaml
AWSTemplateFormatVersion: 2010-09-09
Description: sample vpc template
Parameters:
  EnvType:
    Description: env type
    Type: String
    Default: dev
Resources: 
  VPC:
    Type: AWS::EC2::VPC
    Metadata:
      UserNotes:
        ResourceNote: This is a note for VPC resource
        PropNotes:
          CidrBlock: This is a note for CidrBlock prop
          Tags[1].Value: This is a note for Value prop of 2nd Tags list prop
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      Tags:
        - Key: ENV
          Value: !Ref EnvType
        - Key: Name
          Value: SampleVpc
```

下記のようなコマンドを実行することで、

```Bash
$ cfn-docgen --in cfn.yaml --fmt xlsx
```

下記のような表形式のパラメータシートが生成されます。

![demo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866958/a9292923-4da2-60f1-c789-6bfa4c9c278d.jpeg)



ツールの主な特徴（売り）は、下記の通りです。
- **cfnテンプレートファイル上で記載を省略したプロパティも全てパラメータシート化**
  - 上記の例では`EnableDnsHostnames`や`InstanceTenancy`の記載がcfnテンプレートファイルにはありませんが、パラメータシート上は（値が空欄の状態で）記載され、値の設定見落としが無いかをチェック可能になります。
- **利用者独自のコメントを記述可能**
    - 各リソース、各プロパティごとに、cfnテンプレートファイルの`Metadata`セクションにコメント（備考や特記事項）を付与しておくことで、パラメータシートでその内容を横通しで確認可能になります。
  - リソースに対するコメントは`Metadata.UserNotes.ResourceNote`として、各プロパティに関しては`Metadata.UserNotes.PropNotes.{Property}`として定義可能です。
- **全てのセクションをパラメータシート化可能**
    - （上記の例では省略しましたが、）cfnテンプレートファイルの`Resources`セクションだけでなく、`Parameters`、`Mappings`、 `Outputs`、`CreationPolicy`、`UpdatePolicy`、`UpdateReplacePlocy`、`DeletionPolicy`、`DependsOn`といった他のセクションについてもパラメータシート化されます。
- **パラメータシートの形式は、エクセル/md/csv/html形式の何れかを選択可能**


**コマンドラインツール（CLI）としてだけでなく、Dockerイメージ、AWS SAMアプリケーション、Python API、GUIとしても利用可能です。詳細は[GitHubのリポジトリ](https://github.com/horietakehiro/cfn-docgen)をご参照ください。**

※因みにGUIの操作イメージは以下のような感じです。

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/866958/8dd79869-d753-2567-6b7d-f8bb3be333ab.gif)


## ツールを作成した背景

### なぜパラメータシートが必要なのか

そもそも、cfnを使用するのであれば、パラメータシートなんて不要では？と思われる方もいらっしゃるかと思います。私も基本的にその考えに賛成です。というかそもそもcfnテンプレートすら、可能なら直に書かずcdkで自動生成出来るのが理想的だと思っています。

では、パラメータシートが必要になる（作成せざるを得ない）のはどの様な状況かというと、個人的には以下の様な状況が挙げられると思います。

- **パラメータシートが無いと何となく不安な場合**
  - チームのAWS使用経験が浅い等の理由で、パラメータシートも作成していないと不安ということがあるような場合ですね。
- **設定値に対する設計背景や特記事項をキッチリ残したい場合**
  - （Yaml形式の）cfnテンプレートファイルにコメントとして書くのでなく、表形式のパラメータシートとして設計背景や備考、特記事項をキッチリ残したい場合ですね。
- **人力でcfnテンプレートのレビューを行いたい場合**
  - cfnテンプレートファイルよりも、表形式のパラメータシートの方が（多少は）人力での可読性や検索性高いかと思います。
  - ※勿論、検証用のテストを書いて自動化出来るのが理想だが、1点目のような、AWSの使用経験が浅かったりコードを書ける人が居ない場合は難しいかと思います。
- **お客様から納品物として「パラメータシート」の提示を求められる場合**
  - 大人の事情で否応なく作成しなくてはいけない場合ですね。

AWSの利用経験がまだまだ浅く（≒クラウドネイティブな思想、DevOpsに馴染みがなく）、WF色の強い（伝統的な）開発体制のプロジェクトほど、上記の様なケースが発生する可能性が高くなるのではと考えています。

### なぜパラメータシートを自動生成したいのか

**一方で、上述の様な理由からパラメータシートを作成する必要があっても、パラメータシートを手動で作成すべきではない**。というのが私の考えです。理由としては以下の通りです。

- **作業コストが単純に2倍**
  - パラメータシートで整理する内容と、cfnテンプレートで定義する内容は情報量としてはほぼ等価であり、同じ内容のドキュメントを2種類作成・保守しているに等しい。
- **設定値がどうせ乖離していく**
  - 仮に「パラメータシートで整理した内容をcfnテンプレートに反映しよう」というルールを決めても、どこかで必ず反映ミスや反映漏れが発生すると考えた方が良いです。
  - 大規模かつ長期間のプロジェクトほど、それが発生する可能性は高くなるかと思います。

また、（特にエクセル形式の）パラメータシートは以下の様な限界があるとも考えます。

- **cfnテンプレートの文法を表現し切れない**
  - そもそもJson/Yaml形式の定義をテーブル（エクセル）形式に落とし込むのに手間が掛かる。
  - cfnテンプレートの組み込み関数やリソース間の動的参照をパラメータシート上でどう表現するのかが難しい。作業者によってフォーマットの差異も生じやすい。

- **パラメータシートは差分確認が難しい**
  - Yaml/Json形式のcfnテンプレートファイルであれば、gitやvscodeで簡単に差分を確認出来ますが、例えばエクセル形式のパラメータシートはバージョン毎の差分の確認が難しい。

### 導き出したソリューション

そういう訳で、「パラメータシートを作成する必要があるが、パラメータシートは手動で作成したくない」、という状況に対応するため、パラメータシートを自動生成出来るcfn-docgenというツールを作成するに至りました。

パラメータシートを作成する必要がある場合に、私が推奨するプラクティスは以下の2点です。

- **cfnテンプレートからパラメータシートを自動生成する**
  - pydocやjavadocを使用して、アプリケーションコードからドキュメントを自動生成するイメージ
- **パラメータシートはReadOnlyのドキュメントとして、リソースの検索やレビュー、納品物としてのみ活用する**
  - マスターはあくまでもcfnテンプレートファイル
  - 設定値を編集する場合はcfnテンプレートの方を編集し、その都度パラメータシートを再度自動生成する


## おわりに

今年は会社の粋な計らいで、[AWS re:Invent 2022](https://reinvent.awsevents.com/)に初めて現地参加することが出来ました。期間中は非常にエレガントなAWSの活用事例やモダンなプラクティスを沢山聞くことができ、AWSに対するモチベーションが益々高まった1週間となりました。
一方で仕事をしていると、AWSに不慣れなエンジニア及び、それでも頑張ってAWSを活用していこうとするプロジェクトがまだまだ沢山存在しているなと感じまることが多々あります。このツールが、そんな過渡期的な位置にある人々とプロジェクトの生産性を向上させる力になればと思います。

それでは皆様。We wish you a merry Christmas and a happy new year!