LoginSignup
6
4

More than 5 years have passed since last update.

HubotにOpsWorksのDeploymentを監視させてSlackに流す

Last updated at Posted at 2015-08-05

経緯

  • OpsWorks(Chef)の実行時間は長い
  • 完了はできるだけ早く知りたい
  • 誰かが操作したら教えて欲しい
  • つまり、操作の通知の機能が欲しい

OpsWorksには通知の機能がない

インスタンス間のオーケストレーション的な通知はあるんですが、SNSでイベント通知的な機能がない。

作ってみた

各操作の情報は OpsWorks:DescribeDeployments で取れる。 Deploymentsと書いてるけどCommandsも取れるので、これを監視して新しいのが来たら通知する感じ。

依存ライブラリ

  • aws-sdk (2.1.42)
  • cron (1.0.9)

※()内は実際に使用しているバージョンでそれでしか動かないわけではないです

必要なIAM権限

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "opsworks:Describe*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

Hubot Script

stack_id channel、cron周期やメッセージ内容は適宜変更してください。
IAM Roleが付与されたEC2で動く前提なので、そうではない場合はcredentialの指定が必要です。
あと、 :opsworks: はカスタム絵文字なのでSlack標準では無いです。

opswork-deployment-notify.coffee
# Description
#   OpsWorks deployment notify
#
# Configuration:
#   None
#
# Commands:
#   None
#
# Author:
#   Masashi Terui

cron = require('cron').CronJob
AWS = require('aws-sdk');
opsworks = new AWS.OpsWorks({region: 'us-east-1'});
channel = '#your-channel'

module.exports = (robot) ->
  new cron '*/10 * * * * *', () =>
    before = Math.floor(new Date().getTime() / 1000) - 10
    opsworks.describeStacks {}, (err, stacks) ->
      if err
        console.log(err, err.stack)
      else
        for stack in stacks.Stacks
          opsworks.describeDeployments {StackId: stack.StackId}, (err, deploys) ->
            if err
              console.log(err, err.stack)
            else
              for deploy in deploys.Deployments
                created_at = Math.floor(new Date(deploy.CreatedAt).getTime() / 1000)
                if deploy.CompletedAt == ""
                  completed_at = 0
                else
                  completed_at = Math.floor(new Date(deploy.CompletedAt).getTime() / 1000)
                if before <= created_at
                  data = deploy
                  opsworks.describeInstances {InstanceIds: data.InstanceIds}, (err, instances) ->
                    if err
                      console.log(err, err.stack)
                    else
                      ins_list = []
                      for instance in instances.Instances
                        ins_list.push "- #{instance.Hostname} (#{instance.PrivateIp})"
                      msg = "
:opsworks: 開始しました \n
```\n
ID: #{data.DeploymentId} \n
Command: #{data.Command.Name} \n
Comment: #{data.Comment} \n
[Instances] \n#{ins_list.join('\n')} \n
```\n
"
                      robot.send {room: channel}, msg
                if before <= completed_at
                  data = deploy
                  opsworks.describeInstances {InstanceIds: data.InstanceIds}, (err, instances) ->
                    if err
                      console.log(err, err.stack)
                    else
                      ins_list = []
                      for instance in instances.Instances
                        ins_list.push "- #{instance.Hostname} (#{instance.PrivateIp})"
                      emoji = ':ok:'
                      emoji = ':ng:' if deploy.Status == "failed"
                      msg = "
:opsworks: 終了しました #{emoji} \n
```\n
ID: #{data.DeploymentId} \n
Status : #{data.Status} \n
Command: #{data.Command.Name} \n
Comment: #{data.Comment} \n
[Instances] \n#{ins_list.join('\n')} \n
```\n
"
                      robot.send {room: channel}, msg
  , null, true, "Asia/Tokyo"

ソース汚くてごめんなさい。。。
でも、これで快適なOpsWorks生活に一歩近づきました。

6
4
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
6
4