ようへいの日々精進XP

よかろうもん

YAMAHA ネットワーク機器 Firmware の更新を Slack に通知する Lambda ファンクションの一例

tl;dr

YAMAHA ネットワーク機器の Firmware 更新情報が RSS で配信されていたらいいのになあと思っていたら, 有志の方が RSS を配信するサイト (https://rtxpro.com/) を作られていたので, そのサイトを利用させて頂いて, 対象機器の Firmware が更新されたら Slack に通知する Lambda ファンクションを作りましたので共有させて頂きます.

f:id:inokara:20200418101304p:plain

こんな通知が Slack の指定したチャンネルに通知されます.

作ったもの

リポジトリ

github.com

デプロイには serverless framework が必要です.

処理の流れ

以下のような感じで動きます.

sequence dialog

使い方

ファイル

リポジトリには以下のファイルが含まれています.

$ tree -L 1
.
├── README.md
├── docs
├── env-dev.yml
├── handler.py
├── node_modules
├── package-lock.json
├── package.json
├── requirements.txt
└── serverless.yml

2 directories, 7 files

設定ファイル env-dev.yml の修正

設定ファイルというか, 環境変数を定義した YAML ファイル (env-dev.yml) を環境に応じて修正します.

SLACK_CHANNEL: "#your-slack-channel"
SLACK_USERNAME: "YAMAHA Firmware Release Check"
SLACK_ICON_EMOJI: ":police_car:"
FIRMWARE_RELEASE_URL: "https://rtxpro.com/?feed=rss2"
YAMAHA_URL: "http://www.rtpro.yamaha.co.jp/RT/firmware/"
SSM_PARAMETER_NAME: "your-ssm-parameter-name"
MACHINES: "RTX1200,WLX402,SWX2100"
DYNAMODB_TABLE: "yamaha-firmware-notify"

Slack の Incomming Webhook URL を利用するので事前に払い出しておきましょう. また, Incomming Webhook URL は AWS Systems Manager パラメータストアに登録して Lambda から利用します. パラメータストアへのデータ登録は以下のように pstore という拙作のツールを使うと便利だと思います!(さり気なく宣伝)

$ pstore -put -name=your-ssm-parameter-name -value=https://hooks.slack.com/services/XXXXXX/YYYYYYYYYY/ZzZzZzZzZzZzZzZzZzZzZzZz -secure

MACHINES には利用している YAMAHA ネットワーク機器の機種名を設定します. 以下のように, 複数の機器を対象にする場合には , (カンマ区切り) で設定します.

MACHINES: "RTX1200,WLX402,SWX2100"

あとはデプロイ

以下のようにデプロイします.

$ sls deploy --stage=dev

簡単ですね. デプロイ時に DynamoDB のテーブルも一緒に作成されますのでご了承下さい.

CloudWatch Events で定期的 (一日に一回) に https://rtxpro.com/?feed=rss2 をチェックして, MACHINES に指定された機器の更新通知があれば Slack に通知されます.

メモ

なんで DynamoDB 使っているのか

同じ通知が何度も飛んでしまうことを防ぐ為, 通知済みの更新情報を登録する目的で DynamoDB を利用しています. 以下のようなデータが登録されます.

f:id:inokara:20200418114157p:plain

また, データをテーブルに書き込む際 (put_item) に DynamoDB の重複排除処理を利用して通知済みかを判断しています. 以下のような処理の流れになるかと思います.

sequence dialog

以下, コードの一部です.

def write_table(machine, rev):
    dynamodb = boto3.client('dynamodb', region_name=region)

    try:
        dynamodb.put_item(
            TableName=dynamodb_table,
            Item={
                'machine': {'S': machine},
                'revision': {'S': rev}
            },
            Expected={
                'revision': {
                    'Exists': False
                }
            }
        )
    except ClientError as e:
        if e.response['Error']['Code'] == 'ConditionalCheckFailedException':
            print('duplicate key')
            return False
        else:
            raise
    else:
        return True

条件パラメータとして Expected を利用していて, 同じ revision が登録されていた場合, 例外処理として write_table 関数は false を返すようにしています. 尚, 以下のドキュメントよると Expected の代替えとして ConditionExpression を利用するようにと書かれています.

docs.aws.amazon.com

以上

メモでした.

最後になりますが, https://rtxpro.com/ を公開してくださっている管理者の方には大変感謝しております. 有難うございます.