AWS Service health dashboardのRSSを、Slackに一括登録する

# 背景

* Personal Health dashboardがありつつ、やはりService health dashboardの情報は、それはそれとして購読したい。
* SlackにRSSリーダーがあるけど、1 URLずつ `/feed subscribe https://.....rss` と実行する必要があり拷問である。複数をベタっと貼ってもエラーになる。どうにか一括登録したい。
* https://status.aws.amazon.com/rss/all.rss という全部入りがあるけど、使ってないリージョンのまで入ってるので、購読すると無駄にうるさい。また直近15記事しかなく、広域障害発生時は猛烈に流れて使い物にならないことが想定できる。製品ごとリージョンごとRSSで見るしかなさそう
* ググると手製の東京リージョンOPMLとか見つかるけど、数年前のものだったりする。常に最新のRSSであってほしい

# 解法

* https://status.aws.amazon.com/ からRSSのURLを、グローバルサービス、リージョナルサービスにバラして、ほしいリージョンだけにする。CLIで。
* Slack API から `/feed subscribe` コマンドを実行して登録する

# RSSのURLぜんぶ取ってくる

curlしたものをモゴモゴして取ってきます。

```bash
curl -s https://status.aws.amazon.com/ \
| perl -wpl -e 's|\"|\n|g' | grep "/rss/" \
| perl -wpl -e 's|^|https://status.aws.amazon.com|g' \
| sort -u \
>  all.txt
```

# グローバルとリージョナルに分割する

URLリストを眺めると、リージョナルサービスにはリージョン名がURLに含まれており、グローバルサービスはサービス名だけであることがわかります。すっごく雑に、

* ハイフンが複数個なければグローバルサービス
* ハイフンが複数個あるならリージョナルサービス

とバラせそうでした。

```bash
cat all.txt \
| grep -Ev '.*-.*-.*-' > global-products.txt

cat all.txt \
| grep -E '.*-.*-.*-' > regional-products.txt
```

最初はハイフンの有無で分けてみたのですが、以下の例外があることがわかり、「ハイフンが複数個の有無」で、としました。

```
https://status.aws.amazon.com/rss/import-export.rss
https://status.aws.amazon.com/rss/management-console.rss
https://status.aws.amazon.com/rss/s3-us-standard.rss
```

# リージョンごとに分割

せいぜい2 - 3リージョンしか使ってないでしょうから、欲しいリージョンのものだけに絞りたい、なので分割します。

```bash
rm -f regional-products.*.txt
cat regional-products.txt \
| rev | awk -F'[.-]' '{print $0 " " $2 "-" $3 "-" $4}' | rev \
| awk '{print "echo " $2 " >> regional-products." $1 ".txt"}' \
| bash
```

# SlackのAPIトークンを発行する

SlackのAPI `chat.command` を利用するためレガシートークンを用意してください。

* https://api.slack.com/legacy/custom-integrations/legacy-tokens

このトークンは、トークンの発行者の権限の範囲で、トークンの発行者の名義で、広範にAPIを使えてしまうトークンであるため、厳重に保管してください。

# 手元にrubyをインストールする

2.6系で最新を選んでおけばいいのではないでしょうか。この後で使う `slack-ruby-client` も入れておいてください。

```bash
brew install rbenv ruby-build
rbenv install 2.6.6
rbenv global 2.6.6
gem install slack-ruby-client
```

# Slackに一括登録するRubyスクリプトを用意する

https://gist.github.com/sasasin/28fbb22d3e40dd8518be5f2f30df5e42 をテキトーな場所に転がしてください。

以下のように動かすことができます。

```
export SLACK_API_TOKEN="xoxp-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
./slack_slash_command.rb "#general" "/feed" "subscribe https://status.aws.amazon.com/rss/iam.rss"
```

# Slackに一括登録する

これまでの情報を総合して、以下のように実行することで一括登録できます。

```bash
export SLACK_API_TOKEN="xoxp-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
export CHANNEL_NAME="#投稿先チャンネル名"
cat global-products.txt \
| xargs -L1 -I XXX ./slack_slash_command.rb "${CHANNEL_NAME}" "/feed" "subscribe "XXX
cat regional-products.ap-northeast-1.txt \
| xargs -L1 -I XXX ./slack_slash_command.rb "${CHANNEL_NAME}" "/feed" "subscribe "XXX
cat regional-products.us-east-1.txt \
| xargs -L1 -I XXX ./slack_slash_command.rb "${CHANNEL_NAME}" "/feed" "subscribe "XXX
```

# CodeBuildで定期実行する

一回やってそれきりではないはず。利用するAWS製品もリージョンも増減していくでしょうから、それなり簡単に自動登録したいでしょう。CodeBuildで定期実行させましょう。

こんなbuildspecです。

```yaml
version: 0.2

env:
  parameter-store:
    # 格納先のSSMパラメータストア名は好みで
    SLACK_CHANNEL_NAME: "/CodeBuild/SLACK_CHANNEL_NAME"
    SLACK_API_TOKEN: "/CodeBuild/SLACK_API_TOKEN"

phases:
  install:
    commands:
      - gem install slack-ruby-client
      - curl -s -o ./slack_slash_command.rb https://gist.githubusercontent.com/sasasin/28fbb22d3e40dd8518be5f2f30df5e42/raw/0294724cc31abeb2f02b04ac05fd95d28732d37d/slack_slash_command.rb
      - chmod +x slack_slash_command.rb

  build:
    commands:
      - |
        curl -s https://status.aws.amazon.com/ \
        | perl -wpl -e 's|\"|\n|g' | grep "/rss/" \
        | perl -wpl -e 's|^|https://status.aws.amazon.com|g' \
        | sort -u \
        >  all.txt
      - cat all.txt | grep -Ev '.*-.*-.*-' > global-products.txt
      - cat all.txt | grep -E '.*-.*-.*-' > regional-products.txt
      - |
        rm -f regional-products.*.txt
        cat regional-products.txt \
        | rev | awk -F'[.-]' '{print $0 " " $2 "-" $3 "-" $4}' | rev \
        | awk '{print "echo " $2 " >> regional-products." $1 ".txt"}' \
        | bash
      - ls -alF *.txt
      - |
        cat global-products.txt \
            regional-products.ap-northeast-1.txt \
            regional-products.us-east-1.txt \
        | while read FEED_URL; do
            ./slack_slash_command.rb "${SLACK_CHANNEL_NAME}" "/feed" "subscribe ${FEED_URL}"
            sleep 3
        done

```

* コンテナイメージは  `ruby:2.6-buster` で動作確認しています
* チャンネル名やSlackトークンは、SSMパラメータストアなどに入れましょう。 `SLACK_CHANNEL_NAME` はパブリックチャンネルの場合は `#general` のように `#` を付ける必要があります
* [いますぐ使うCodeBuild](https://qiita.com/sasasin/items/6e5f7001cba350851d49) を参考に、好みの周期で定期実行させます
* 例として東京とバージニア北部リージョンで動かしてます
* 当初 `sleep 3` は入れずに動かしたら、途中から「お前やりすぎ3秒後にリトライしろ」でコケるようになったので追加してます

# 参考

* https://status.aws.amazon.com/
* https://hub.docker.com/_/ruby
* https://github.com/slack-ruby/slack-ruby-client
* https://github.com/ErikKalkoken/slackApiDoc/blob/master/chat.command.md
*  [いますぐ使うCodeBuild](https://qiita.com/sasasin/items/6e5f7001cba350851d49)