Assurer のプロジェクトサイト立ち上げました
irc#assurer@freenode での会話が盛り上がったので、勢いで ドメインを取得して、独立した trac と svn repos を立ち上げてみました。(最低限の体裁だけ。しかも plagger.org からコピペ。)
id:tokuhirom さんからの contribute で、テストプラグインも増えてます。また、信頼のおける Yappo さんから、Publish::File プラグインを提供してもらいました。感謝感謝。
IRC での会話の流れで、テストだけではなく監視もカバーする、という方向性で行くことになりました。会話の断片はこちらで参照できます。
- http://d.hatena.ne.jp/tokuhirom/20070117/1169018818
- http://subtech.g.hatena.ne.jp/yappo/20070117/1169031325
なんか略称がヒドイことになってます…(その略称に OK を出したのは自分ですが…)
Assurer - サーバテスティングフレームワーク #4
Assurer (SVN) を修正。テストのターゲットとなるホストを、以下の3つのパターンのいずれかで指定できるようにしてみました。
config.yaml 中のテストプラグイン設定で直接指定
test:
- module: HTTP
config:
host: svn.mizzy.org
content: It works!
一番オーソドックスなパターンですね。
コマンドラインオプションで指定
test:
- module: HTTP
config:
content: It works!
といった感じで config.yaml には host を書かずに、
$ ./assurer.pl --config=configy.yaml --host=svn.mizzy.org
とコマンド実行時に指定。同じテストを複数のホストに対して実行する場合、いちいち config.yaml を書き換えるよりも、こっちの方が楽ですね。
config.yaml でターゲットホストをリストで指定
test:
- module: HTTP
config:
content: It works!
hosts:
- svn.mizzy.org
- trac.mizzy.org
2番目のパターンと同じ用に、テストプラグインの設定には host を記述しませんが、別なところにターゲットホストをリストアップしておきます。複数のホストに対して一気に実行するのであれば、この方法が楽ですね。
これの変形で、
test:
- module: HTTP
role: web
config:
contnet: It works!
- module: MySQL
role: mysql
hosts:
web:
- svn.mizzy.org
- trac.mizzy.org
mysql:
- mysql.mizzy.org
といった感じで設定すると、HTTP のテストは svn.mizzy.org と trac.mizzy.org に、MySQL のテストは mysql.mizzy.org に対して実行される、という動作になります。(MySQL テスト用プラグインはまだ存在しませんが。)
複数の役割の異なるホストに対してテストを実行するには、このパターンで。
最後のやつは Archer からのインスパイヤです。
Assurer - サーバテスティングフレームワーク #3
Assurer (SVN) を修正。主な修正点は以下の通りです。
- テスト結果を保持する Assurer::Results クラスを削除。代わりに Test::TAP::Model を使うようにした。
- Format, Publish まわりを実装し、Format::Text, Format::HTML, Publish::Term を実装。
- Assurer::Test でテスト結果をターミナルに表示していたのを、Publish::Term に分離。
format:
- module: HTML
config:
css_uri: htmlmatrix.css
publish:
- module: Term
といった設定をして、
$ ./assurer.pl -c examples/config.yaml > tap.html
と実行すると、こんな感じの HTML が得られます。
これで大枠はだいぶ整ってきた気がする。
Net::LDAPx::Simple と Catalyst::Model::LDAPx::Simple
Net::LDAP::Alterntive あらため Net::LDAP::Abstract ですが、この名前だと Net::LDAP の中のモジュールと区別がつかないし、パッと見何をやるモジュールなのか分からないので、Net::LDAPx::Simple (SVN) とまた名称を変更しました。DBIx::Simple からの連想です。 以下の様な感じで CRUD が一通りできるようになってます。
# Create
my $res = $ldap->create({
dn => 'uid=mizzy, ou=people, o=southpark',
objectclass => [ 'person', 'inetorgperson' ],
sn => 'Miyashita',
cn => 'Gosuke Miyashita',
uid => 'mizzy',
});
# Retrieve
my $entries = $ldap->search({
-or => {
uid => 'miya',
cn => 'miyashita*',
},
}
});
# Update
my $entry = $entries->first;
$entry->telephonenumber('00-0000-0000');
$entry->update;
# Delete
$entry->delete;
ついでに Catalyst::Model::LDAPx::Simple (SVN) もつくりました。Catalyst::Model::* つくるのはじめてなので、こんな感じでいいのかちょっと不安。もう少し他の Catalyst::Model::* のソースを読んでみる。
もうちょいエラーハンドリングちゃんとして、POD 書いたり Helper つくったりした後に CPAN に up 予定。
Assurer - サーバテスティングフレームワーク #2
プラグインの実行フェーズを、test, format, publish の3つにわけてみました。
test:
- module: HTTP
name: http://svn.mizzy.org/ #0
config:
url: http://svn.mizzy.org/
match: It works!
format:
- module: HTML
publish:
- module: Mail
こんな感じで config.yaml を書くと、テスト結果を HTML でフォーマットしてメールで飛ばす、みないな動作になることを意図しています。(まだ Format::HTML や Publish::Mail はつくってないですが。)
format: - module: Text publish: - module: File
とかやると、テキスト形式でファイルに吐き出すとか、そんな感じで。
単にターミナルに結果を表示するだけであれば、format と publish は必要ないです。
これにともなって、プラグインのネームスペースも、Plugin::Test::*, Plugin::Format::*, Plugin::Publish::* の3つに分割しています。
また、Assurer::Results というクラスも新たに追加しました。Plugin::Test::* によるテスト結果を保持しておいて、Plugin::Format::* に渡すためのクラスです。
こんな感じで遅々としてますが、少しづつ前進しています。
Assurer - サーバテスティングフレームワーク #1
typester さん が del.icio.us で「開発参加したい!」とおっしゃってくださったので、#assurer@freenode チャネルつくりました。まだおおまかな仕様すら固まっていない段階なので、いろいろご助言頂けると大変うれしいです。ご興味のある方はぜひ!
で、本題。Assurer (SVN) をちょっと修正しました。修正点は以下の通りです。
- assurer.pl に Plagger の文字が残っていたので、修正しました。(はてブでコメント頂きました。ありがとうございます。)
- Assurer::Test というクラスをつくりました。Assurer::Plugin::HTTP では最初、Test::More を使っていたのですが、代わりにこちらを使うようにしてます。
- 他微修正。
今回追加した Assurer::Test というクラスは Test::Builder を利用していて、 Test::More の代わりとしてテスト用プラグインから利用することを想定しています。
なぜわざわざこのクラスを作ったかというと、テスト結果出力を色分けしたかったからです。実行するとこんな感じの出力になります。(RSS リーダだと色が見えないと思いますが…)
$ ./assurer.pl -c examples/config.yaml [info] Testing http://svn.mizzy.org/ #0 ok 1 - Content of http://svn.mizzy.org/ matches 'It works!' [info] Testing http://svn.mizzy.org/ #1 not ok 2 - Content of http://svn.mizzy.org/ matches 'It not works!' # '<html><body><h1>It works!</h1></body></html>' # doesn't match '(?-xism:It not works!)'
また、
global:
config:
no_diag: 1
といった設定をすると、以下のように diag message を表示しなくなります。
$ ./assurer.pl -c examples/config.yaml [info] Testing http://svn.mizzy.org/ #0 ok 1 - Content of http://svn.mizzy.org/ matches 'It works!' [info] Testing http://svn.mizzy.org/ #1 not ok 2 - Content of http://svn.mizzy.org/ matches 'It not works!'
Assurer::Test は今後、 Assurer::Test::More とか Assurer::Test::Class といった感じでベースとなる Test::* に応じて細分化するかもしれません。
Assurer - サーバテスティングフレームワーク #0
構築したサーバがちゃんと動作するかどうかのテストを自動化したいなー、とスクリプトを書こうと思ったのですが、Perler としてはここはやはり、Plagger とか Archer みたく、プラガブルで YAML で設定書けば OK みたいのを作るべきだろう、ってことで、Assurer (SVN) というサーバテスティングフレームワークをでっちあげてみました。
テストのことを Quality Assurance とか言ったりするし、Plagger や Archer が er で終わってるので、それに倣って命名してます。
今のところ Plagger や Archer からコピペして、ごく簡単な HTTP テストプラグインをつくっただけでまだまだ未完成ですが、以下のような config.yaml で実行すると、HTTP GET して取得したコンテンツに「It works!」が含まれているかどうかテストする、といった感じで動作します。
plugins:
- module: HTTP
config:
url: http://svn.mizzy.org/
match: It works!
これって、サーバのテストだけでなく、監視にも使えるよなー、と思ったところで、ライブドアテクノロジーセミナーで naoya さんが触れていた、Observer というはてな製監視フレームワークとかぶるんじゃないか、という気がしてきました。Plagger ライクって言っていたし。
ということは、はてなが Overver を公開してくれれば、自分で開発する必要がなくなって楽ができそう、ってことで、公開希望とここでつぶやいておきます。
Net::LDAP::Abstract #0
Net::LDAP のラッパモジュール Net::LDAP::Alternative を Net::LDAP::Abstract に変えて、少し修正しました。svn で取得するには以下のように実行して下さい。
svn co http://svn.mizzy.org/public/library/perl/trunk/Net-LDAP-Abstract/
名称を Alternative から Abstract に変えたのは、LDAP アクセスの処理を Net::LDAP の実装よりも更に抽象化しているから、というのと、検索フィルタを SQL::Abstract ライクに書けるから、という理由からです。
たとえば、Net::LDAP では
my $msg = $ldap->search(
base => 'o=southpark',
filter => '(|(&(!(cn=*gosuke))(sn=miyashita))(uid=miya))',
);
とやたらと括弧の多いフィルタを自分で書かなければいけないところを、Net::LDAP::Abstract では
my $entries = $ldap->search({
-or => {
uid => 'miya',
-and => {
sn => 'miyashita',
cn => { '!=' => '*gosuke' },
}
}
});
といった感じで書けます。これは超便利。
フィルタを組み立てるコードは、SQL::Abstract からそのまんまぱくってます。
Net::LDAP::Alternative
perl-ldap (Net::LDAP) のインターフェースがわかりにくくて、たまにこいつでプログラムを書こうとすると、いつもど忘れして perldoc と睨めっこするはめになるので、違うインターフェースで LDAP アクセスできるラッパモジュールを書いてます。とりあえずプロトタイプ版の Net::LDAP::Alternative を置いておきます。まだ未完成で pod すらちゃんと書いてないですが。
インターフェースがどんな風に違うかを例で示してみます。「特定の検索条件にマッチするエントリの電話番号を書き換える」という操作を、Net::LDAP で書くとこんな感じになります。
my $ldap = Net::LDAP->new(
'kenny',
port => 389,
);
$ldap->bind(
'cn=Directory Manager',
password => 'password',
);
my $msg = $ldap->search(
base => 'o=southpark',
filter => '(&(uid=miya)(cn=gosuke*))',
);
for my $entry ( $msg->entries ) {
print $entry->get_value('telephonenumber');
$ldap->modify(
$entry->dn,
replace => { telephonenumber => '00-0000-0000' }
);
}
これを Net::LDAP::Alternative で書くとこうなります。
my $ldap = Net::LDAP::Alternative->new({
host => 'kenny',
port => '389',
bind_dn => 'cn=Directory Manager',
bind_pw => 'password',
base => 'o=southpark',
});
my $entries = $ldap->search({
uid => 'miya',
cn => 'gosuke*',
});
while ( my $entry = $entries->next ) {
print $entry->telephonenumber;
$entry->telephonenumber('00-0000-0000');
$entry->update;
}
Net::LDAP と特に異なる点は、
- bind は明示的にしない。(コンストラクタで bind してる。)
- search を簡略化。LDAP 特有のフィルタ記法で書かなくて良い。
- 検索して得られるエントリをイテレータにしてみた。
- エントリの属性取得のアクセサメソッドを実装。(get_value をつかわなくてよい。)
- エントリの属性変更もアクセサメソッド経由でできるので直感的にわかりやすい。
ってとこですね。
また、1件しか検索結果が返らないことがわかっている場合は、Net::LDAP であれば
my $msg = $ldap->search(
base => 'o=southpark',
filter => '(&(uid=miya)(cn=gosuke*))',
);
my $entry = ($msg->entries)[0];
といった感じでエントリを取得するわけですが、Net::LDAP::Alternative では
my $entry = $ldap->search({
uid => 'miya',
cn => 'gosuke*',
})->first;
といった感じでエントリ取得ができます。
こんな感じで、DBIx::Class のインターフェースを参考にして、直感的にわかりやすいようにしてます。
とりあえずなんとなくつくってみただけなので、これを発展させるかどうかはまだ未定。