JunosのOn-box Pythonを使ってみる #おまけ1 ChatOps的な何か/CommitしたらSlackにポストしてみる

[先日](http://qiita.com/kazubu/items/6d5c94cf32436c4d228f)、JunosのOn-box PythonによるCommit Scriptをご紹介しました。
そのなかで、Commit Scriptにて実現できることの例として「ChatOps的な何か」とかふわっとした事を書いていました。

というわけで(?)、今回はChatOps的な何かということで、手始めにJunosルータでCommitしたらSlackにポストするCommit Scriptを書いてみました、という一発ネタです。
(この程度のことをChatOpsと呼ぶと怒られてしまうかもしれませんが、そこは手軽な例ということでご容赦下さい。)

# コード

スクリプトとしては以下のようなものになります。URLは適当に置き換える必要があります。

```post-slack.py
from junos import Junos_Context
import json
import urllib
import urllib2

def post_slack(_username, _text):
  url = 'https://hooks.slack.com/services/************'
  headers = {'Content-Type': 'application/json'}
  params = json.dumps({"username": _username, "text": _text})

  req = urllib2.Request(url, params, headers)
  res = urllib2.urlopen(req)

  if res.getcode() != 200:
    message = '{0} {1} failed: {2}'.format(method, uri, res.getcode())
    raise SlackPostError(message)

def main():
  login_name = Junos_Context['user-context']['login-name']
  host_name = Junos_Context['hostname']
  product_name = Junos_Context['product']

  name = 'Junos Router({0})'.format(host_name)

  type = 'commit'
  if Junos_Context['commit-context'].has_key('commit-check'):
    type = 'commit check'
  elif Junos_Context['commit-context'].has_key('commit-confirm'):
    type = 'commit confirmed'
  elif Junos_Context['commit-context'].has_key('commit-boot'):
    print 'boot-time commit should be ignored'
    sys.exit()

  comment = ''
  if Junos_Context['commit-context'].has_key('commit-comment'):
    comment = ' with comment: {0}'.format(Junos_Context['commit-context']['commit-comment'])

  text = 'User {0} trying {1} to {2}({3}){4}.'.format(login_name, type, host_name, product_name, comment)
  post_slack(name, text)

if __name__ == '__main__':
  main()
```

# 実行結果

こんな感じで動作します。

![slack-junos-post2.png](https://qiita-image-store.s3.amazonaws.com/0/104974/31956169-2272-4869-587f-0ec93cfa68e2.png)


# 解説

単純なスクリプトなので読めばなんとなく分かるかと思いますが、簡単に解説しておきます。

このスクリプトでは、Commitイベントが発生すると、そのCommitイベントがどういう種別のものなのかによってメッセージを作り分け、Slackにそれをポストします。
Commit Scriptでは、`Junos_Context`という変数を参照することで、そのCommitイベントが誰によってどういう理由で実行されたのかといった情報を得ることができます。
たとえば、以下のような入力を得ることができます。

```junos_context.json
{
	"product": "vmx",
	"user-context": {
		"login-name": "root",
		"user": "root",
		"class-name": "super-user",
		"uid": "0"
	},
	"routing-engine-name": "re0",
	"script-type": "commit",
	"re-master": null,
	"hostname": "vmx1",
	"pid": "17688",
	"tty": "/dev/pts/1",
	"commit-context": {
		"database-path": "/var/run/db/juniper.db",
		"commit-check": null
	},
	"chassis": "others",
	"localtime": "Tue Dec 27 19:36:45 2016",
	"localtime-iso": "2016-12-27 19:36:45 UTC"
}
```

この結果を読んでみると、"vmx1"というホスト名を持つ"vmx"という製品で、"root"というユーザーによって、Commit Checkが行われた、と言うことがわかります。
どういったパラメーターが含まれるのかは[公式ドキュメント](https://www.juniper.net/techpubs/en_US/junos16.1/topics/reference/general/junos-script-automation-junos-xsl-global-params-and-var.html)に纏まっていますので、それを元にして、commit checkかどうか、commit confirmedかどうか、コメントがあるか、といった条件でメッセージを生成しています。

Slackにポストする部分については、post_slackメソッドとして切り出していますが、JSON形式でPostしたい内容を含むパラメータを生成し、Urllib2を使ってPOSTするだけとなっています。

ちなみに、Commit Scriptでは、そのCommitが成功したのかどうかということは分かりませんので、仮にCommitが失敗した場合でも、Slackにはポストされることになります。