share facebook facebook2 twitter menu hatena pocket slack

2014.11.07 FRI

chef-handler-slack を使ってみたのと Jenkins に通知を飛ばすハンドラを作って gem で公開してみた

川原 洋平

WRITTEN BY川原 洋平

どうも、cloudpackハンドラ・カワハラ@inokara)です。

はじめに

以下の記事を参考にさせて頂いて chef-client の実行結果を Slack に飛ばしてみたのでメモです。

さらにググってみるとハンドラとして chef-handler-jenkins が既に存在していましたが、勉強を兼ねて自作してついでに gem 化して公開したのでメモです。


参考


chef-handler-slack

chef-handler-slack

読んで時の如くでございます。

通知の飛ばし方

使い方はとっても簡単です、上記のブログ記事に書かれている手順に従って cookbook に組み込んで収束させれば通知が飛ぶようになります。(但し、デフォルトでは収束に失敗しない(Excepstion とならない)限りは通知が飛びませんでした)

収束に失敗すると以下のように通知が飛びます。

chef-handler-slack で通知を飛ばす: cookbookでの収束に失敗した場合の通知

成功した通知も飛ばしたい

ちなみに成功した場合にも通知を飛ばしたい場合には…ソースコードにちょっと手心を加えます。

        if not run_status.success?
          msg = "Chef run failed on *#{source}*"
          if !run_status.exception.nil?
            msg += "n```"
            msg += run_status.formatted_exception.encode('UTF-8', {:invalid => :replace, :undef => :replace, :replace => '?'})
            msg += '```'
          end

          send(msg)
        else
         # 以下に出力させたい内容を追記します
         msg = "Chef run finished *#{source}*"
         send(msg)
        end

出力させたい内容は run_status の以下のメソッドで指定可能です。

名称 説明
node Node Object(ohai の収集した Attribute 等を含む)
success? 実行時に例外を含んでいなければ真を返す
failled? 実行時に例外を含んでいれば真を返す
start_time Node Object を作成した後、Chef::RunContext を作成する前の時刻
end_time Chef-client 終了時の時刻
elapsed_time start_time と end_time の差
all_resources run_list によって読み込んだ Recipe に定義されているリソースの一覧
updated_resources all_resources のうちで Chef::Runnner によって変更されたリソースの一覧
exception 発生した例外のクラス
formatted_exception 発生した例外クラスとメッセージの文字列
backtrace 例外発生時のバックトレース
run_context Chef::RunContext オブジェクトの全ての内容

上記は「Chef 活用ガイド」から引用させて頂きました。有難うございます。m(__)m

楽しいチャットオプス

まだまだ試用段階なので通知をトリガーに次の処理をどうこうするとかは考えていませんが、通知をチャット飛ばすことで得られるメリットとしては…

  • 他のメンバーとの情報共有がメールと比べるとカジュアルに出来る
  • カジュアルな情報共有なので自分だけのオプス、秘伝のタレ、秘伝のレシピにならずにすみそう

この二つかなと考えています。

Chef 等の構成自動管理ツール(この言い方が正しいかわかりませんが)が浸透してきても、結局それを使う(使いこなす)人が限られてしまっては上記のように秘伝のタレが秘伝のレシピになってしまいそうな状況を見ることがあります。そんな状況を少しでも打開する一つの方法としてチャットをベースとした情報共有とそれらの連携は必要なのではないかなと思っています。


俺の Chef ハンドラ

chef-handler-jenkins_notifier

勉強を兼ねて作りました。

次期バージョンの予定としては…

  • https 対応
  • 認証対応(しました)

を予定しております。

使い方等

README.md を御覧ください。尚、事前に Jenkins 環境を構築して通知を飛ばす為のジョブを作成しておきましょう。

デモ

早速ですがデモです。
まずは以下のように Excepstion させますね。

chef-handler-jenkins_notifierのデモ (1): Exception を発生させる

さすれば Jenkins 先生には以下のように通知されます。

chef-handler-jenkins_notifierのデモ (2): Jenkins に Exception が通知される

ついでに run_status.success?true の場合には…

chef-handler-jenkins_notifierのデモ (3): 処理を成功させる

ポーカーフェイスな先生も心なしかご満悦です。

chef-handler-jenkins_notifierのデモ (4): Jenkins にも成功が通知される

苦労したところ(よくわからんかったところ)

ハンドラの動作や含まれる情報についてはこちらを参考させて頂き、Chef::Runstatus オブジェクトから幾つかのメソッドを取ることで通知の内容はコントロール出来ることは解りましたが、Jenkins に通知を飛ばす際に通知内容を 16 進数のバイナリにエンコードする必要があり、その方法を探すのが苦労しましたが…世界は広し、同じことをやろうとされている方が僕らの stack overflow にいらっしゃいましたので参考にさせて頂きました。

ざっくり言うと以下のような流れでバイナリエンコードします。

  • メッセージ(今回は run_status から取得したい各種メソッド)を配列にぶっ込む
  • ぶっこんだ配列を join して文字列に変換(セパレータは n
  • 変換した文字列を unpack メソッドを使って処理

実際に以下のように処理しています。

          log = []
          log << "n"
          log << "Chef run Success on #{run_status.node.name}"
(中略)
          log << "elapsed_time: " + run_status.elapsed_time.to_s + "s"
          log << "n"
          log = log.join("n")
          submit_jenkins run_status,log,result
        end
      end
(中略)
      def submit_jenkins(run_status, log, result)
        binlog = log.unpack("H*").first

最後に

暫くは Chef の Handler を作りつつ、改めて Chef の勉強をしなおしていきたいと考えています…。

元記事はこちらです。
chef-handler-slack を使ってみたのと Jenkins に通知を飛ばすハンドラを作って gem で公開してみた