もくもく会

Nagoya.cloud.firstの#3に飛び込みで参加してみました。
前日ぎりぎりの申し込みでなんか申し訳なかったです。

さて、いろんなコミュニティ界隈の方が来られていて、お話はしたことなかったのですが、Cloud DaysとかAWSの展示会とか、なんかお見かけした記憶があるお顔がちらほらいらっしゃった感じです。ただ、私、人の顔を覚えるのが極端に出来が悪いので、明確に覚えているわけではないのですが。

コミュニティといえば、今月21にはJAWS-UGもあるので、そちらにも顔を出せたらなぁと思っております。
もっぱらインサイドにこもっていたエンジニアなので、どんどん出て行って顔を覚えてもらっていかないといけませんね。JAWSくらいは所属したほうがいいのかしら。
フリーランスの方々はどうなさってるんでしょうね。正解なんてないのでしょうけど。

さて。

とりあえずもくもく会ではzabbixのAPIをぶっ叩くことにいたします。とはいってもAPI自体はとても単純なJSON-RPCなんですが、Zabbix自体が基本的に複雑怪奇なシステムなので、APIリファレンスがとんでもない分量あるわけで、欲しいデータがどうやってとれるか、という検証に近いです。

基本的にはuser.loginのメソッドをとりあえず投げ、APIキーをもらったら後はそれをつけてやり取りするだけです。別にPerlでもPythonでもRubyでも好きなので書けばいいわけですが、インフラエンジニアはPerlかPythonだろ。というのがよくある話。

とはいえ、普段コードなんてほとんど書いていませんし、最近書くコードなんてTerraformとAnsibleです。YAMLとJSON書いてるだけなのとほぼ変わりません。
そろそろGoogle Appsのスプレッドシートにも手を出さないといけないですね。もくもく会でも取り組んでる方いらっしゃいました。

閑話休題。
つまりですね。めんどくさいからbashでやろう。ということになりました。というか私が何か作ってるときのモックはだいたいBashかPerlですが、最近Perlしばらく書いてなかったので、文法に時間とられるのが嫌だったので、Bashで突っ走ることにしました。

特に発表とかしに行ったわけではないので、ここで成果は簡単に公開しておきます。
インフラ界隈なので、おもむろにbashとviだけで物事を始めるのはとてもよくある話だと思います。いちいちIDEとか立ち上げない。そもそも私のPCにIDE自体インストールされていません。
DockerfileもAnsible RoleもTerraform taskもすべてviがあればいいのだ、で済ませています。だからTypoだらけになるわけなんですが。

さて、まずはJSON-RPCでAPIキーを取りに行きます。

コードはshellscriptの「明示的に示さなければあらゆる変数はグローバルスコープである」という頭の悪い仕様を悪用し逆手に取ります。
いや、ふつうの言語でコードで書くなら参照渡しすればいいだけなんですが。ポインタなんかbashにあるわけがないでしょう。頑張っても配列と辞書配列までです。
RESULTも何等かの形のJSONに直して吐き出させよう、というのが魂胆で、そもそもJSONをいちいちクエリ投げるたびにかっこの数を数えたくない、というのが本音です。
なので、からっぽのデフォルトのJSON構造体を作っておいて、あとはjqに頑張ってもらおう。という謎仕様。
とりあえずこんな感じでAPIキーが取れます。


#!/bin/bash
ID_VAL=1
readonly JSON='{"jsonrpc":"2.0" , "id":null , "params":{} , "method":null }'
QUERY_RET=""
# アカウント設定
readonly USER='username'
readonly PASS='password'

# API基本設定
readonly HEADER="'Content-Type: application/json-rpc'"
readonly API_URL='http://127.0.0.1/api_jsonrpc.php'

# 利用コマンド
readonly JQ=$(which jq)
readonly CURL="$(which curl) -s -XGET -H ${HEADER}"

function api_init () {
set_method user.login
set_params user ${USER}
set_params password ${PASS}
query_run
echo ${QUERY_RET} | ${JQ} -r '.result'
}

function query_clear () {
QUERY=${JSON} && return 0
}

function query_run () {
QUERY_RET=""
set_id
[[ $( echo ${QUERY} | ${JQ} -r '.method' ) != "user.login" ]] && set_auth
local ret=$( echo "${CURL} -d '${QUERY}' ${API_URL}" | sh )
QUERY_RET=${ret}
echo ${ret}
query_clear
}

function set_json () {
local parent=$1 ; shift
local type=$1 ; shift
local key=$1 ; shift
local value=$1 ; shift

case ${type} in
array ) QUERY=$( echo ${QUERY} | ${JQ} --arg value ${value} ''${parent}'.'${key}'|=.+[$value]' );;
object ) QUERY=$( echo ${QUERY} | ${JQ} --arg value ${value} ''${parent}'|=.+{'${key}':$value}' );;
* ) err "Function set_json : Unknown type.";;
esac
}

function set_id () {
set_json . object id ${ID_VAL}
}

function set_auth () {
local auth="null"
[[ $# -ne 0 ]] && auth=$1
set_json . object auth ${auth}
}

function set_params () {
local key=$1 ; shift
local value=$1 ; shift
local type
[[ $# -eq 1 ]] && type=${1} || type="object"

set_json .params ${type} ${key} ${value}
}

function set_method () {
local method=$1
set_json . object method ${method}
}

function initialize () {
query_clear
}

initialize
AUTH=$( api_init )
echo ${AUTH}

やってることが5行で終わることを延々と長くした、という感がぬぐえませんが、この後いろいろデータとったり加工したりすることを考えると、汎用化してファンクションにするのは間違ってないと思うのですよ。自分用のスクリプトではfunctionは別ファイルに逃がしてsourceで読み込んでいますし、定数的に使ってる設定値も別ファイルに逃がしている感じですね。
あとはまあ、欲しい値についてset_methodしてset_paramsで条件決めてquery_run。結果をjqで.resultでパースしてごにょごにょしてストアしたいとこに突っ込む、そんな感じ。

params:{}だけが階層化されていて、それ以外はルート直下のKey-Valueオブジェクト。paramsもその下一段階で(ほぼ)終わりなのですが、万が一を考慮して親キーを指定して階層が深くなっても対応できるようにはしてあります。その時はラッパーファンクションを作るか、set_jsonを直接呼ぶか、というところですかね。

2.0のマニュアルを眺めながらやってたんですが、item.getするとものすごい量のデータを返そうとしてzabbix側でphpのmemory_limitオーバーのエラー起こしまくる。
grafanaも同じことやってるんだからできるはず、とは思うんですがもしかして一ヶ月分とかのリクエストの時、細かくTime Periodを切り分けてるのかな。でも私が今欲しいのは細かいレベルでのデータ詳細じゃなくて月次レポートなんだから丸まってる値が欲しいんだけどな…。

一応TimeFromとTimetillを短く切ればとれるのは確認し、そこから足し算して平均と最大と最小を取るところまでは完了したので、割と進んだのかな、とは思います。

で、家に帰ってZabbix3.4のAPIのドキュメント見たら、trend.getが追加されてた…。これでええやないか…。
試してみたら十分に粒度が粗くなったTrend値を返してくれました。悩んでた時間を返してほしい。

というかZabbixのドキュメント、日本語が2.2までしかないせいかデフォルトで2.0とかのページを表示するので地味に不便ですね。英文で構わないのでlatestのドキュメントを優先してほしいものですが。
地味にTrigger関数が増えてたり、地味にMacroの使用箇所が増えてたり、地味に機能が追加されてたり、Zabbixって画面変化乏しいから地味なんですよね。3.4のダッシュボードのウィジット化はそれなりに派手ですが。

4.0はわりと大きな変化をする、とは聞いているのですが、Zabbix開発チームのデザインセンスはそこまで期待してないので機能のほうでお願いします。
フロントエンドは他のツールが頑張ってくれるはずです。
監視系ってみんなGUIのデザインセンスがいまいちひどいですよね。Nagiosとかもそうだし。monitなんてテーブルべた書きに見えるし。別に困らないし、レスポンシブになりました、とかテーマフォルダにテーマを入れて、とか言われてもそんなことより機能をだな、って言いたくなりますからGUIが腐ってるのはむしろ誉め言葉なのかもしれません。

あとはテキスト整形を作らないといけませんが、気力がつきましたのでまた後日作ることとします。