ボタン一発で @nifty ID を切り替える Google Chrome 拡張 Nifty Id Switcher
インストール:Chrome Web Store - nifty id switcher
ソース:tily/nifty-id-switcher
ものすごくニッチな感じの Google Chrome 拡張を作りました。
ニフティクラウドで複数のアカウントを使い分けている人とかにおすすめです。
本当に基本的な機能しか実装しておらず、デザインも適当なのでプルリクをお願いします。
- 個人の製作物でありニフティ株式会社とは一切関係ありません
- パスワードを含む @nifty ID アカウント情報を Google Chrome のローカルストレージへ保存します、自己責任でご利用ください
追記:ログアウトのロジックが足りないのとか、もろもろ不具合に気づいたので近日中に直します。
Chef のレシピから serverspec のテストを自動生成する chef-serverspec-handler という gem を作ってみた
『Chef のレシピは「こうあるべき」を記述するものだから、レシピからテストが自動生成できるべきだよな』とずっと思っていたんだけど、最近触りはじめた serverspec がシンプルで簡単に自動生成できそうなのでやってみた。
使い方は上記リンクに書いてある通りなのですが、たとえば Chef のレシピにこう書いてあるやつを、
template '/var/tmp/template.txt' do source 'template.txt.erb' mode 0777 owner 'root' group 'root' variables(:val1 => 'val1', :val2 => 'val2', :val3 => 'val3') action :create end
このような serverspec のテストに自動変換してくれます。
context file('/var/tmp/template.txt') do it { should be_file should be_mode 777 should be_owned_by 'root' should contain 'val1' should contain 'val2' should contain 'val3' } end
この形がよいのかどうかはよく分からないけど Chef の Handler として実装してあり、--why-run オプションと組み合わせて使うことを想定しています。
コンセプトコードみたいなものなので、ちゃんと動かないところがたくさんあるかも。というか試しに Opscode コミュニティの wordpress クックブック + ニフティクラウドの CentOS 6.3 64bit Plain サーバーで試したら、自動生成された 77 テスト中 4 つのテストが失敗した。
Failures: [18/829] 1) apache2::default Package "apache2" Failure/Error: it { should be_installed } rpm -q apache2 パッケージ apache2 はインストールされていません。 expected Package "apache2" to be installed # ./spec/localhost/apache2/default_spec.rb:5:in `block (3 levels) in <top (required)>' 2) apache2::mod_php5 Package "php package" Failure/Error: it { should be_installed } rpm -q php\ package パッケージ php package はインストールされていません。 expected Package "php package" to be installed # ./spec/localhost/apache2/mod_php5_spec.rb:9:in `block (3 levels) in <top (required)>' 3) mysql::server File "/etc/my.cnf" Failure/Error: should contain 'false' grep -q -- false /etc/my.cnf expected File "/etc/my.cnf" to contain "false" # ./spec/localhost/mysql/server_spec.rb:73:in `block (3 levels) in <top (required)>' 4) wordpress::default File "/etc/httpd/sites-available/wordpress.conf" Failure/Error: should contain '{:template=>"wordpress.conf.erb", :enable=>true, :docroot=>"/var/www/wordpress", :server_name=>"localhost", :server_aliases=>["localhost"], :na me=>"wordpress"}' grep -q -- \{:template\=\>\"wordpress.conf.erb\",\ :enable\=\>true,\ :docroot\=\>\"/var/www/wordpress\",\ :server_name\=\>\"localhost\",\ :server_aliases\=\>\[\"localhost\" \],\ :name\=\>\"wordpress\"\} /etc/httpd/sites-available/wordpress.conf expected File "/etc/httpd/sites-available/wordpress.conf" to contain "{:template=>\"wordpress.conf.erb\", :enable=>true, :docroot=>\"/var/www/wordpress\", :server_name=>\"l ocalhost\", :server_aliases=>[\"localhost\"], :name=>\"wordpress\"}" # ./spec/localhost/wordpress/default_spec.rb:44:in `block (3 levels) in <top (required)>'
1,2 は CentOS なのに Debian/Ubuntu のパッケージをインストールしようとしているのでレシピが悪いように思うのですが、
3,4 は chef-serverspec-handler が template リソースの variables で指定されたハッシュの値を単純に should contain しているのがダメで、そもそも variables は単純な値の埋め込み以外にも true/false を渡してテンプレートの内容を切り分けるような用途にも使うので、テンプレートの内容を論理的に解析する必要があり、対応するのがむずかしそうに思った。
というようにマダマダな感じなのですが、既存のレシピ資産にテストを書く足がかりにはなると思うので、よかったらお試しください。
Chef の Cookbooks を一発で NIFTYCloud クラウドストレージにアップロードする ncss-cookbooks コマンド
ニフティクラウド上で手軽に Chef を試したいときには、ニフティクラウドストレージへ tgz 形式でアップロードした上で chef-solo コマンドの -r オプションで URL を指定する方法が便利です。
$ chef-solo -j node.json -r https://my-bucket.ncss.nifty.com/v0.0.0/cookbooks.tgz
上記コマンドを打つと、chef-solo は -r に指定された tgz アーカイブファイルをウェブ経由で取得し、ローカルへ展開した上で cookbooks を実行してくれます。
chef-solo -r で取得できるのは便利なのですが、いちいち cookbooks を tgz に書庫化してニフティクラウドストレージへアップロードする部分が面倒なので、これを自動化するコマンドを作りました。
インストール
$ gem install ncss-cookbooks
使い方
管理している cookbooks レポジトリの直下に VERSION というファイルを作成してバージョンを書き込みます。
$ echo "0.0.0" > VERSION
環境変数でニフティクラウドストレージの API キーを設定します。
$ export ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXX $ export SECRET_ACCESS_KEY=YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
あとはバケットを作成するコマンドと、作成したバケットに cookbooks.tgz をアップロードするコマンドを叩くだけです。
$ ncss-cookbooks create my-bucket $ ncss-cookbooks upload my-bucket Version is v0.0.0 Creating directory /tmp/ncss-cookbooks-20130519-30448-2im9m1/cookbooks/ Copying files from /home/tily/dev/ncss-cookbooks to /tmp/ncss-cookbooks-20130519-30448-2im9m1/cookbooks/ Excluded /home/tily/dev/ncss-cookbooks/.git Archiving /tmp/ncss-cookbooks-20130519-30448-2im9m1/cookbooks/ to /tmp/ncss-cookbooks-20130519-30448-2im9m1/cookbooks.tgz Uploading /tmp/ncss-cookbooks-20130519-30448-2im9m1/cookbooks.tgz to bucket:my-bucket, object:v0.0.0/cookbooks.tgz Temporary directory /tmp/ncss-cookbooks-20130519-30448-2im9m1 will be deleted automatically Uploaded to https://my-bucket.ncss.nifty.com/v0.0.0/cookbooks.tgz
発行された URL は chef-solo -r から利用できます。
$ chef-solo -j node.json -r https://my-bucket.ncss.nifty.com/v0.0.0/cookbooks.tgz
あとがき
- 特に大したことはやっていないのですが、バージョン管理の運用と組み合わせて使えるので結構便利なのではないかと思います
- 最初 knife コマンドに組み込もうと思ったのですが、knife は色々なファイルをロードして結構重いので単体のコマンドにしてみました
- 個人的には前に作ったニフティクラウドを vagrant のように使える some コマンドと組み合わせて使おうと思っています
- そもそも chef-solo -r が BASIC 認証等に対応していないので cookbooks.tgz を認証なしの URL に置かなければならないのが少し厳しい感じがします、やはり本格的に運用するなら Chef サーバーでしょうか
ニフティクラウドを vagrant のように使える some コマンド
heroku の中の人が作った sumo (相撲)というツールがあります。vagrant のような感覚で amazon ec2 のインスタンスを作ったり Chef で設定したり削除できたりするやつです。これを修正してニフティクラウドでも使えるようにしてみました。独自の機能もいろいろ追加してあります。
詳しくは上記 github の README を参照していただきたいのですが、ここでは mysql サーバーを立てる例を簡単に説明してみます。
設定ファイルを書く
~/.some ディレクトリを作成し、~/.some/config.yml に下記の設定を書き込みます。
- ~/.some/config.yml
--- access_key: XXXXXXXXXXXXXXXXXXXX secret_key: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY cookbooks_url: http://some.ncss.nifty.com/cookbooks.tgz role: mysql: | { "run_list": [ "recipe[mysql::server]" ], "mysql": { "server_root_password": "mysql", "server_debian_password": "mysql", "server_repl_password": "mysql", "bind_address": "ZZZ.ZZZ.ZZZ.ZZZ", "allow_remote_root": true } }
some コマンド実行
実行するのは 2 つのコマンドのみです。
$ some launch mysql ---> Launch instance... 0ebfa18a (8.4s) ---> Acquire hostname... AAA.AAA.AAA.AAA (82.5s) ---> Wait for ssh... done (0.0s) ---> Bootstrap chef... done (63.3s) ---> Setup mysql... done (145.4s)
$ some openfw 3306 port 3306 scheduled for open
ここまで終われば SSH ログインができるようになっているし、
$ some ssh AAA.AAA.AAA.AAA Enter passphrase for key '/home/tily/.some/keypair.pem': (パスワードを入力) [root@localhost ~]#
外部から mysql サービスに接続できるようになっています。便利。
$ mysql -h AAA.AAA.AAA.AAA -u root -p Enter password: (パスワードを入力) Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.1.67-log Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql>
何が行われているか
簡単に流れを説明します。
$ some launch mysql
- 存在しなければ something という名前の FW を作成する
- 存在しなければ something という名前の SSH キーを作成してローカルの ~/.some/keypair.pem に保存する
- FW=something, SSH キー=something でサーバーを作成する
- サーバーが起動し SSH が疎通するまで待つ
- SSH が疎通したら SSH 経由でサーバーに Chef をインストールし /etc/chef/solo.rb を設定する
- config.yml に書いてある mysql の設定をサーバーの /etc/chef/dna.json に置く
- config.yml の cookbooks_url から cookbooks を取得し chef-solo を実行する
$ some openfw 3306
- something FW の 3306 ポートを開放する
という感じです。ちなみに要らなくなったサーバーはコマンド一発で削除することができます。
$ some terminate 0ebfa18a ---> Wait to stop... done (20.8s) AAA.AAA.AAA.AAA scheduled for termination
編集後記
自分でガシガシ使えそうなツールが作れたのでよかった。
あと最近 vagrant が流行っているようなんだけど、個人的にはクラウドは面倒を他人に委ねることだから、sumo や cucumber-chef のように本番環境だけでなく検証やテストも外部に委ねられるようになるのが未来だと思っています。
cookbook とか用意しなくても chef を試せる patty.rb というスクリプトを書いた
オハイ! Chef はよくも悪くも仕組みが大げさなので、思いついたときにぱっと試すのが面倒くさいと前々から思っていた。
なんとか cookbook を作らなくても簡単に試す仕組みを作れないかなと思って、自分のアプリケーションから Chef Solo を呼び出す — Gist とか 手軽に chef-solo を実行するためにスケルトンを作ってくれるやつ (ユースケース要検討) — Gist とか色々試していたんだけど、先日Opscode 社 Chef ハンズオン・トレーニングに出席したときに shef がかなり理想に近いことが分かったので、shef のコードを読み、インタラクティブ・シェルではなく 1 枚のファイルの中にレシピとテンプレートを記述できる仕組みを作ってみた。
こんな感じのレシピファイルを作成して、
- recipe.rb
file '/tmp/hello.txt' do content "hello!\n" end template "/tmp/hello2.txt" do local true source "hello" variables :name => 'world' end template "/tmp/foobar.txt" do local true source "foobar" variables :name => 'tily' end __END__ @@ hello hello, <%= @name %> @@ foobar this is another template: name is <%= @name %>
こんな風に実行すると、
- 実行方法
ruby patty.rb recipe.rb
chef-solo っぽくスタンドアロンで Chef を実行できる。
- 実行結果
bash-3.2$ ruby patty.rb recipe.rb Loading....[2012-11-10T12:48:58+09:00] DEBUG: Building node object for linwttaa.local [2012-11-10T12:48:58+09:00] DEBUG: Extracting run list from JSON attributes provided on command line [2012-11-10T12:48:58+09:00] DEBUG: Applying attributes from json file [2012-11-10T12:48:58+09:00] DEBUG: Platform is mac_os_x version 10.7 [2012-11-10T12:48:58+09:00] INFO: Run List is [] [2012-11-10T12:48:58+09:00] INFO: Run List expands to [] done. [2012-11-10T12:48:59+09:00] INFO: Processing file[/tmp/hello.txt] action create ((eval) line 2) --- /var/folders/9q/tq6hwz3j7qd_nctywdr_4mp40000gn/T/chef-tempfile20121110-23863-enwe0z 2012-11-10 12:48:59.000000000 +0900 +++ /var/folders/9q/tq6hwz3j7qd_nctywdr_4mp40000gn/T/chef-diff20121110-23863-vo0wbv 2012-11-10 12:48:59.000000000 +0900 @@ -0,0 +1 @@ +hello! [2012-11-10T12:48:59+09:00] INFO: entered create [2012-11-10T12:48:59+09:00] INFO: file[/tmp/hello.txt] created file /tmp/hello.txt [2012-11-10T12:48:59+09:00] INFO: Processing template[/tmp/hello2.txt] action create ((eval) line 6) [2012-11-10T12:48:59+09:00] DEBUG: Current content's checksum: [2012-11-10T12:48:59+09:00] DEBUG: Rendered content's checksum: 853ff93762a06ddbf722c4ebe9ddd66d8f63ddaea97f521c3ecc20da7c976020 --- /var/folders/9q/tq6hwz3j7qd_nctywdr_4mp40000gn/T/chef-tempfile20121110-23863-4d1443 2012-11-10 12:48:59.000000000 +0900 +++ /var/folders/9q/tq6hwz3j7qd_nctywdr_4mp40000gn/T/chef-rendered-template20121110-23863-8svaro 2012-11-10 12:48:59.000000000 +0900 @@ -0,0 +1 @@ +hello, world [2012-11-10T12:48:59+09:00] INFO: template[/tmp/hello2.txt] updated content [2012-11-10T12:48:59+09:00] INFO: Processing template[/tmp/foobar.txt] action create ((eval) line 12) [2012-11-10T12:48:59+09:00] DEBUG: Current content's checksum: [2012-11-10T12:48:59+09:00] DEBUG: Rendered content's checksum: 04fc2a8f0333e6412a408e347ca49aab17b1b179f42be3d4cc2fd42fc4bcdf50 --- /var/folders/9q/tq6hwz3j7qd_nctywdr_4mp40000gn/T/chef-tempfile20121110-23863-1woio2b 2012-11-10 12:48:59.000000000 +0900 +++ /var/folders/9q/tq6hwz3j7qd_nctywdr_4mp40000gn/T/chef-rendered-template20121110-23863-1ai39uj 2012-11-10 12:48:59.000000000 +0900 @@ -0,0 +1 @@ +this is another template: name is tily [2012-11-10T12:48:59+09:00] INFO: template[/tmp/foobar.txt] updated content
実験的なスクリプトなのであまり品質は高くないかも。でもなんかこういう「Chef をカンタンに使える仕組み」がもっとあっていいと思っている。
Opscode 社 Chef ハンズオン・トレーニング
ブログを書くのが遅れてしまったのですが、10/5(金) 10:00〜17:00 に「Opscode 社 Chef ハンズオン・トレーニング」というものに参加してきました。
Opscode 社員である Sean OMeara 氏から Chef の中級的な使い方を教えてもらうというもので、非常に内容が濃く充実した時間を過ごすことができました。
内容については jedipunkz さん・tkak さんがかなり詳しく書いてくださっているので (ありがとうございます!)、この記事には個人的におもしろかったところや感想を書いておきます。
参考:
構成管理の歴史
Sean 氏曰く、従来型の構成管理では下に挙げる 4 つのアプローチが採用されてきました。
- 手動で設定を行う (Manual Configuration)
- スクリプトを書く (Scripting)
- ファイル配布 (File Distribution)
- 実行管理 (Execution Management)
- Cluster SSH、Golden Images、ISConf
スクリプトを書く (Scripting)
上記はいずれも欠点を抱えており、「手動で実行する」というのはサーバが増えれば増えるほど非効率になるためもちろん論外ですが、一見筋の良さそうな「スクリプトを書く」というアプローチにも不便なところがあります。
Sean 氏は "not safe to run twice" (2 回実行したときに安全ではない) と表現されていましたが、このことについて自分の言葉で少し説明してみます。
そもそも「環境構築のためにスクリプトを書く」とき、ほとんどのケースでは「まっさらなサーバ」に対して「1 度だけ実行する」こと、つまり「初期構築」専用であることが前提となっているように思います。
これは当然のようですが、実は効率が悪い面もあります。なぜなら「環境」というのは 1 度作ったあとで要件が変わり、変更を施す必要がかならずと言っていいほど出てくるからです。
こんなとき「スクリプトを書く」アプローチでは、下記のどれかで対処するかと思います。
- 仕方ないから新しい変更点だけは手動で適用してしまう
- 新しい変更点を手動で適用し、古くなったスクリプトの末尾にも書き加えておく
- 新しい変更点を加える 2 つめのスクリプトを作成して実行する
- 古いスクリプトで実行した結果を全て切り戻した上で、修正したスクリプトを実行する
- サーバを一度初期化し、修正したスクリプトを実行する
どれもイマイチだし、そもそも「一度作成したスクリプトをどう保守していくか」という運用指針を考えるのがすごく面倒くさいです。
(あとサーバの運用がすでに開始されている場合には、4・5 番目は使えなかったり。)
これに対して Chef がサーバに設定を反映する過程は "convergence" (収束、あるべき状態に持っていく) と呼ばれており、「レシピ」は「初期構築」専用ではなく何度も実行することを前提としています。
たとえばレシピでは「ファイルへの書き込み」をこのように記述することができますが、
file "/tmp/file1" do content "hi there!\n" end
これは「初期構築時に 1 回だけファイルを書き込む」ことを意味しているわけではありません。実際の挙動は下記のようになります。
- もし /tmp/file1 が存在しない場合
- /tmp/file1 を作成し、"hi there!\n" という文字列を書き込む
- もし /tmp/file2 が存在する場合
- 内容が "hi there!\n" だった場合
- なにもしない
- 内容が "hi there!\n" ではなかった場合
- /tmp/file2 を上書きし、"hi there!\n" という文字列を書き込む
- 内容が "hi there!\n" だった場合
このように比較してみると Chef が「2 度実行しても安全」なのがよく分かると思います。
この仕組みなら 1 つのレシピを、初期構築だけでなく運用時のどの場面でも差分適用のために利用できます。
(もちろん、スクリプトでも「ファイルが存在しない場合にだけ書き込む」といった convergence を実装することはできますが、それはすなわち独自で Chef を実装するようなものなので、最初から Chef を使っておいたほうが効率がよいです。)
ファイル配布 (File Distribution)
次に、これもよく使われているように思うのですが、NFS / rsync 等の方法で複数のサーバへディレクトリ構造ごとファイルを同期する「ファイル配布」という方法があります。
Sean 氏は「スクリプトを書くよりはマシだけど『Apache を再起動する』とかサービス管理は行えない」と言っていました。
まさにその通りで、静的にディレクトリ構造を同期するだけなので、サーバの内部で行わなければならない「サービス起動」「シンボリックリンク張り替え」「Cron 登録」等は行うことができません。別途 capistrano 等の他の仕組みと組み合わせるのがメジャーでしょうか。
実行管理 (Execution Management)
Sean 氏によると今いちばん普及しているのが「実行管理」という手法らしいです。
勉強不足で「実行管理」というのがどういうくくりなのかいまいちピンとこなかったのですが、例としては "Cluster SSH、Golden Images、ISConf" が挙げられていました。
このうち "Cluster SSH" というのは capistrano や tomahawk 等、複数サーバへ SSH 経由でコマンド実行する仕組みのことを指しているのだと思います。Sean 氏は「サーバの台数が極端に増えたときにスケールしない」というようなことを言っていたように思います (うろ覚え)。
Golden Images というのはあとから調べて分かったのですが、設定済みのサーバを再利用可能なイメージの形で保存しておき、使い回す手法のようです (クラウドが主流になってからは非常によく使われている手法だと思います。)
「分かりやすい」「すぐにサーバを作れる」「どんな OS でも使える」のがメリットですが、下記のようなデメリットもあります。
- Web サーバ/DB サーバ/DNS サーバ等、サーバの種類に応じて多数のイメージを管理する必要がある
- イメージに対して加えた変更の履歴が管理できない
- イメージに対して加えた変更を、運用中のサーバに加える際にはリブートが必要になる
参考:
説明してきた通り、構成管理には本当にさまざまなやり方があり、そしてそのどれもが「なんかイマイチ」だったのですが、そういう欠点を考慮した上で解決策 (pull 型アーキテクチャや convergence) を提示しようとしてきたのが CFEngine/Puppet/Chef の流れだったんだろうな、というのをしみじみと感じました。
shef の使い方
shef というツールがあるのは知っていたけど、どういう風に使うのかあまり具体的な例を見れてよかったです。
下記が実際に Sean 氏が打っていたコマンド。人に Chef がどんなものかを説明する際にも使えそうに思いました。
[root@localhost ~]# shef --solo chef > attributes chef:attributes > default['foo']['bar']='baz' chef:attributes > ^D chef > node['foo']['bar'] chef > recipe chef:recipe > file "/tmp/file1" do chef:recipe > content "hi there!\n" chef:recipe ?> end chef:recipe > file "/tmp/file2" do chef:recipe > content "hi there again!\n" chef:recipe ?> end chef:recipe > file "/tmp/file3" do chef:recipe > content "blah\n" chef:recipe ?> end chef:recipe > run_chef chef:recipe > # C-z で抜けて /tmp/file1 を消したり /tmp/file2 の内容を書き換えたりして、 chef:recipe > # fg で戻り run_chef を実行し「同じ状態」に保ってくれることを確かめていた。 chef:recipe > resources # 誰かが質問していたリソースの一覧を見るコマンド
Tab キーでメソッドの補完をしてくれるのも便利そうでした (これは irb 自体の機能か…)。
chef > node.na[Tabキー] node.name node.name= node.name_type node.named_captures node.names node.nan? node.native
その他雑多なメモ
- 環境 (environment) について
- 検索時に環境で絞り込む haproxy cookbook の例 (solr のクエリに "AND chef_environment:#{node.chef_environment}")
- 環境は cookbook のバージョンを管理するために使える
- タグ (tag) はあまり使われていないっぽい (環境のように cookbook のバージョン管理もできない)
- why-run について
- dry-run とは違う (https://www.usenix.org/sites/default/files/conference/protected-files/omeara_ucms12_slides.pdf)
- convergence する度に why-run の出力は変わる可能性があるので、why-run をテストの代わりにしてはならない
- Chef は基本的に pull だが push したいときにどうするのか?
- 99% は Chef、最後の 1% は capistrano や fabric に任せる (スケールしない)
- 手動で chef を実行する
- data_bags を使って chef 実行のタイミングを制御する
まとめ
とりとめのないメモになってしまいましたが、Chef を開発している Opscode 社の社員が Chef をどんな風に使いこなしているのかを実演してもらえたのがすごく良かったです。
また機会があればぜひ参加したいと思いました。英語が話せなくて質問ができなかったので、今度はがんばって英語で質問したりしたい。
最後になりましたが、主催者の皆様、お誘いありがとうございました&お疲れ様でした。
オープンソースカンファレンス2012 Tokyo/Fall で話した資料を公開しました
すっかり忘れていたけど 2012/09/08 に オープンソースカンファレンス2012 Tokyo/Fall で Japan Chef Users Group として発表した資料を公開しています。前半は基礎的な話だけど、後半は割とあまり日本のウェブ界隈では取り上げられていない内容のような気がする。よかったらご参照ください。 (資料はブラウザで見るタイプのものなんだけど、Google Chrome でしか動作確認していないので他ブラウザだと崩れるかもです)