PlantUMLによってコードベースでAWSのアーキテクチャー図を作る方法

AWS上にサービスを構築するうえで、アーキテクチャー図を作る機会はままあるかと思います。
その際、draw.ioやCacooなどのウェブサービスで作っている人も多いのではないでしょうか。
今回は別のアプローチとして、PlantUMLによってコードベースでAWSのアーキテクチャー図を作る方法をご紹介します。

## PlantUMLの実行環境を用意

まずは、PlantUMLの実行環境を用意します。
ローカル環境にインストールするのもいいですが、素早く試したい場合は[PlantUML Web Server](http://www.plantuml.com/plantuml)を使うのが便利です。

## AWSのアイコンセットを用意

PlantUMLでは、ファイルパスやURLを指定してリソースをインポートすることができます。
これにより自作の画像を組み込むことができるわけですが、ありがたいことにAWSが公式にPlantUMLのためのアイコンセットを配布しています。

- [awslabs/aws-icons-for-plantuml](https://github.com/awslabs/aws-icons-for-plantuml)

記事執筆時点でスター数が57と、まだ世の中にはあまり知られていないようです。

## PlantUMLのコードを書く

さっそくですが、次のようなコードを書いてみましょう。

```
@startuml Two Modes - Technical View

!define AWSPuml https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/master/dist
!include AWSPuml/AWSCommon.puml
!include AWSPuml/General/Users.puml
!include AWSPuml/Mobile/APIGateway.puml
!include AWSPuml/SecurityIdentityAndCompliance/Cognito.puml
!include AWSPuml/Compute/Lambda.puml
!include AWSPuml/Database/DynamoDB.puml

left to right direction

Users(sources, "Events", "millions of users")
APIGateway(votingAPI, "Voting API", "user votes")
Cognito(userAuth, "User Authentication", "jwt to submit votes")
Lambda(generateToken, "User Credentials", "return jwt")
Lambda(recordVote, "Record Vote", "enter or update vote per user")
DynamoDB(voteDb, "Vote Database", "one entry per user")

sources --> userAuth
sources --> votingAPI
userAuth <--> generateToken
votingAPI --> recordVote
recordVote --> voteDb

@enduml
```

出典：https://github.com/awslabs/aws-icons-for-plantuml/blob/master/README.md

すると、このような図が生成されます。

```plantuml
@startuml Two Modes - Technical View

!define AWSPuml https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/master/dist
!include AWSPuml/AWSCommon.puml
!include AWSPuml/General/Users.puml
!include AWSPuml/Mobile/APIGateway.puml
!include AWSPuml/SecurityIdentityAndCompliance/Cognito.puml
!include AWSPuml/Compute/Lambda.puml
!include AWSPuml/Database/DynamoDB.puml

left to right direction

Users(sources, "Events", "millions of users")
APIGateway(votingAPI, "Voting API", "user votes")
Cognito(userAuth, "User Authentication", "jwt to submit votes")
Lambda(generateToken, "User Credentials", "return jwt")
Lambda(recordVote, "Record Vote", "enter or update vote per user")
DynamoDB(voteDb, "Vote Database", "one entry per user")

sources --> userAuth
sources --> votingAPI
userAuth <--> generateToken
votingAPI --> recordVote
recordVote --> voteDb

@enduml
```

それぞれのコードの意味を紐解いていきます。

### AWSのアイコンをインポート

```
!define AWSPuml https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/master/dist
!include AWSPuml/AWSCommon.puml
!include AWSPuml/General/Users.puml
!include AWSPuml/Mobile/APIGateway.puml
!include AWSPuml/SecurityIdentityAndCompliance/Cognito.puml
!include AWSPuml/Compute/Lambda.puml
!include AWSPuml/Database/DynamoDB.puml
```

使用するAWSのアイコンをインポートしています。
ここではGitHub上のURLを指定していますが、次のようにローカルのファイルパスを指定してもかまいません。

```
!define AWSPuml path/to/AWSPuml
```

### 描画方向を指定

```
left to right direction
```

図の描画方向を左から右に指定しています。
デフォルトでは上から下なので、この行を書かなければ次のようになります。

```plantuml
@startuml Two Modes - Technical View

!define AWSPuml https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/master/dist
!include AWSPuml/AWSCommon.puml
!include AWSPuml/General/Users.puml
!include AWSPuml/Mobile/APIGateway.puml
!include AWSPuml/SecurityIdentityAndCompliance/Cognito.puml
!include AWSPuml/Compute/Lambda.puml
!include AWSPuml/Database/DynamoDB.puml

Users(sources, "Events", "millions of users")
APIGateway(votingAPI, "Voting API", "user votes")
Cognito(userAuth, "User Authentication", "jwt to submit votes")
Lambda(generateToken, "User Credentials", "return jwt")
Lambda(recordVote, "Record Vote", "enter or update vote per user")
DynamoDB(voteDb, "Vote Database", "one entry per user")

sources --> userAuth
sources --> votingAPI
userAuth <--> generateToken
votingAPI --> recordVote
recordVote --> voteDb

@enduml
```

### AWSのリソースを定義

```
Users(sources, "Events", "millions of users")
APIGateway(votingAPI, "Voting API", "user votes")
Cognito(userAuth, "User Authentication", "jwt to submit votes")
Lambda(generateToken, "User Credentials", "return jwt")
Lambda(recordVote, "Record Vote", "enter or update vote per user")
DynamoDB(voteDb, "Vote Database", "one entry per user")
```

配置するAWSのリソースを定義しています。
名前の部分は、実際のリソース名にすると分かりやすいでしょう。

### 各リソースの関係を定義

```
sources --> userAuth
sources --> votingAPI
userAuth <--> generateToken
votingAPI --> recordVote
recordVote --> voteDb
```

それぞれのリソースの関係を定義しています。
リソース間を`-->`や`<--`で繋ぐと一方向、`<-->`で繋ぐと双方向の矢印が描画されます。

## 生成した図を埋め込む

QiitaやQiita TeamではPlantUMLの埋め込みに対応しているので、コードブロックの言語に`plantuml`を指定することで図が生成されます。

## おわりに

CloudFormationのテンプレートを読み込んで、PlantUML用のコードを出力してくれるようなツールがあれば最高ですね。[^1]

[^1]: [言い出しっぺの法則](https://ja.wikipedia.org/wiki/%E8%A8%80%E3%81%84%E5%87%BA%E3%81%97%E3%81%A3%E3%81%BA%E3%81%AE%E6%B3%95%E5%89%87)とか言わないでください。