これまでサービスで使うCPANモジュールの管理と言えばrpm/debパッケージが主流だと思いますが、最近ではperlbrewで使いたいバージョンのperlをインストールすることもあり、rpm/debでは対応できなくなってきています。
perlbrewのperlに対してプロジェクトが依存しているCPANモジュールを入れる際、
$ perlbrew switch perl-5.12.3
$ cd /path/to/MyProj
$ perl Makefile.PL
$ cpanm --installdeps .
などと cpanm —installdeps が使えます。
しかし、これではサーバを新規セットアップするたびに、最新のモジュールが入ることになりサーバ間でモジュールのバージョンの差異が生まれる可能性があります。
そこで対応策として考えられるのが開発サーバで—installdepsを実行し、perlbrewのディレクトリごと本番サーバにrsyncする方法です。しかしこの方法はOSのアーキテクチャ変更やメジャーバージョンの変更、ディストリビューションの変更に弱いという問題があります。もしアーキテクチャが変更された場合は本番サーバ、開発サーバの両方用意してperlbrewとCPANモジュールを入れ直す必要がありますが、その際に元の開発サーバと同じバージョンのモジュールが入る保証はありません。
そこで、プロジェクトが依存しているCPANモジュール(とそのCPANモジュールが依存しているモジュール)を全てローカルにダウンロードし、プロジェクトのディレクトリ内で外部依存が無いCPANの部分ミラーを作成し、cpanmでそのミラーだけからモジュールをインストールするという手段を考えました。
まず、DarkPAN(CPAN for intranet) の管理ツールであるOrePANをインストールします。変更がまだあるので自分のforkから
$ cpanm https://github.com/kazeburo/OrePAN/tarball/master
これで、orepan.pl と orepan_index.pl というのが入ります。このコマンドでローカルのCPANミラーのindexを生成できます。
次に、依存モジュールのdownloadだけを行うオプションを追加したcpanmを持ってきます。適当patchなので、これも自分のforkから
$ curl -LO https://github.com/kazeburo/cpanminus/raw/master/cpanm > cpanm
$ chmod +x ./cpanm
このcpanmを使って依存モジュールのダウンロードを行います
$ cwd
/path/to/MyProj
$ perl Makefile.PL
$./cpanm --dpan=./cpan --installdeps .
--> Working on .
Configuring /path/to/MyProj ... OK
==> Found dependencies: Router::Simple::Sinatraish, Tiffany, Module::Find
--> Working on Router::Simple::Sinatraish
Fetching http://search.cpan.org/CPAN/authors/id/T/TO/TOKUHIROM/Router-Simple-Sinatraish-0.02.tar.gz ... OK
Configuring Router-Simple-Sinatraish-0.02 ... OK
Copy to /path/to/MyProj/cpan/authors/id/T/TO/TOKUHIROM/Router-Simple-Sinatraish-0.02.tar.gz
--> Working on Tiffany
Fetching http://search.cpan.org/CPAN/authors/id/T/TO/TOKUHIROM/Tiffany-0.03.tar.gz ... OK
Configuring Tiffany-0.03 ... OK
Copy to /path/to/MyProj/cpan/authors/id/T/TO/TOKUHIROM/Tiffany-0.03.tar.gz
..
extlibにモジュールを導入する際は、-l や -L オプションも一緒に使います
$./cpanm -l extlib —dpan=./cpan —installdeps .
./cpanディレクトリにCPANと同じディレクトリ構造で依存モジュールのダウンロードしていきます。インストールはされません
$ find ./cpan -name "*.tar.gz"
./cpan/authors/id/C/CR/CRENZ/Module-Find-0.10.tar.gz
./cpan/authors/id/T/TO/TOKUHIROM/Router-Simple-Sinatraish-0.02.tar.gz
./cpan/authors/id/T/TO/TOKUHIROM/Tiffany-0.03.tar.gz
全てのダウンロードが終わったら、今度はindexを作成します。先ほどインストールしたOrePANを使います
$ orepan_index.pl --repository ./cpan
...
2011-02-03T17:24:45 [INFO] Save cpan/modules/02packages.details.txt.gz at /...
これでcpan/modules以下にindexファイルができ、CPANミラーの準備ができました。このミラーのディレクトリはVCSでプロジェクトと同様に管理してしまうのがよさげです。
このミラーからモジュールを導入する場合は
$ cpanm --mirror file:///path/to/MyProj/cpan --mirror-only --installdeps .
このようにmirrorとmirror-onlyのオプションを使います。これで外部にモジュールを取りにいくことはなく、ローカルのみから依存モジュールを一括で導入可能です。
もし、依存モジュールが増えたり、依存モジュールのバージョンが新しくなった場合は Makefile.PL を更新しもう一度 cpanmを動かします
$ vim Makefile.PL
$ perl Makefile.PL
$ ./cpanm --dpan=./cpan --installdeps .
今度は、cpanmがcpan/modulesディレクトリ中の02packages.details.txt.gzを読み込んで必要なモジュールだけダウンロードします。依存モジュールのどこかで明示的に書かれていない限り勝手にバージョンがあがってしまう事はありません。
そしてindexを再生成します
$ rm -f ./cpan/modules/02packages.details.txt.gz
$ orepan_index.pl --repository ./cpan
モジュールを減らす場合はcpan/authorディレクトリから削除して、同じ様にindexを作り直せば完了です
この方法の良い点として、おまけ的ですが、search.cpan.orgが止まっていたり、グローバルにアクセスできない場所でも問題なく依存モジュールがインストール可能であること、ダウンロードの手間が無いのでインストールがちょっと高速になることも挙げられます。
いかがでしょうかNe。