berkshelf-apiで自前のcookbookサーバを立てる

Berkshelf 3ではBerksfileの書き方が変わります。
https://github.com/berkshelf/berkshelf/wiki/2.x-to-3.0-Upgrade-Guide
から引用すると

before

````ruby
chef_api :config
site :opscode

metadata
````

after

````ruby
source 'http://hogehoge.yourdomain.com:26200'
source 'https://api.berkshelf.com'

metadata
````

なんかますますGemfileっぽくなってるわけですが、見慣れないアドレスが書かれています。api.berkshelf.com。なにこれ。

Berkshelf 3では、cookbookの依存解決の方法が変わり、index server(Berkshelf API)というものが間に入るようになります。
今までBerkfsileにgit: git://github.com/xxxx/xxxx.gitとかchef_api: configとか書いてたのを、index serverがまとめて引き受けますよ、という感じなんでしょうか。
それに伴い、上記のBerksfileのような書き方になるようです。

このBerkshelf API server、ソースが公開されていて、誰でも立てることができるようになっています。
https://github.com/berkshelf/berkshelf-api

READMEを読むと、opscode community siteやchef serverだけでなく、github、ローカルディレクトリからもcookbookを読み込むことができるようです。
また、Berkshelf API serverを作るためのcookbook ( https://github.com/poise/berkshelf-api )やherokuのcontainer ( https://github.com/berkshelf/api.berkshelf.com )もあるようです。（Herokuよく知らないから間違ってるかも）

とはいえ、まずはミニマムな構成で動かして試してみましょう。
インストール＆起動方法は簡単、

```
$ gem install berkshelf-api
$ berks-api
```

bundlerでもOK

起動すると26200ポートでサーバが起動します。

```
$ bundle exec berks-api
I, [2014-03-13T00:21:09.677552 #28913]  INFO -- : Cache Manager starting...
I, [2014-03-13T00:21:09.677711 #28913]  INFO -- : Loading save from /Users/cazador/.berkshelf/api-server/cerch
I, [2014-03-13T00:21:09.677854 #28913]  INFO -- : Cache contains 0 items
I, [2014-03-13T00:21:09.678268 #28913]  INFO -- : Cache Builder starting...
I, [2014-03-13T00:21:09.731048 #28913]  INFO -- : REST Gateway listening on 0.0.0.0:26200
I, [2014-03-13T00:21:09.752133 #28913]  INFO -- : processing #<Berkshelf::API::CacheBuilder::Worker::Opscode:0x007fcfa9bdf8a0>

```

これだけだとcookbookを一つも持っていないので、なんの役にも立ちません。
cookbookの置き場所を教えてやる必要があります。
ここでは置き場所としてchef-zeroを使います。

berkshelf-apiはconfigをjsonで設定することができます。

````json:config.json
{
  "endpoints": [
    {
      "type": "chef_server",
      "options": {
        "url": "http://localhost:8889",
        "client_name": "reset",
        "client_key": "reset.pem",
        "ssl_verify": false
      }
    }
  ]
}

````
内容は簡単で、urlにchef-zeroが動いているマシンのURLを指定するだけです。あと、ssl_verifyをfalseにしておく必要があります。
※ chef-zeroなのに何故かclient_keyを指定しないと動かなかったのでダミーのclient_nameとclient_keyを置いています。
※ chef serverでもssl_verifyを消して、client_name, keyを本物にしてやると動きます。

berks-apiコマンドにconfig.jsonを渡して起動します。すると、chef-zeroにcookbookの情報を取得しに行きます。

````
$ bundle exec berks-api -c config.json
I, [2014-03-13T00:47:08.138002 #87267]  INFO -- : Cache Manager starting...
I, [2014-03-13T00:47:08.138116 #87267]  INFO -- : Loading save from /Users/cazador/.berkshelf/api-server/cerch
I, [2014-03-13T00:47:08.138289 #87267]  INFO -- : Cache contains 1 items
I, [2014-03-13T00:47:08.138793 #87267]  INFO -- : Cache Builder starting...
I, [2014-03-13T00:47:08.199125 #87267]  INFO -- : REST Gateway listening on 0.0.0.0:26200
I, [2014-03-13T00:47:08.224667 #87267]  INFO -- : processing #<Berkshelf::API::CacheBuilder::Worker::ChefServer:0x007ff330b6fe10>
I, [2014-03-13T00:47:08.232235 #87267]  INFO -- : found 1 cookbooks from #<Berkshelf::API::CacheBuilder::Worker::ChefServer:0x007ff330b6fe10>
I, [2014-03-13T00:47:08.232717 #87267]  INFO -- : about to merge cookbooks
I, [2014-03-13T00:47:08.232754 #87267]  INFO -- : #<Berkshelf::API::CacheManager:0x007ff330b8e338> adding (0) items...
I, [2014-03-13T00:47:08.232775 #87267]  INFO -- : #<Berkshelf::API::CacheManager:0x007ff330b8e338> removing (0) items...
I, [2014-03-13T00:47:08.232792 #87267]  INFO -- : #<Berkshelf::API::CacheManager:0x007ff330b8e338> cache updated.
I, [2014-03-13T00:47:08.232810 #87267]  INFO -- : #<Berkshelf::API::CacheManager:0x007ff330b8e338> cache updated.
I, [2014-03-13T00:47:13.235229 #87267]  INFO -- : processing #<Berkshelf::API::CacheBuilder::Worker::ChefServer:0x007ff330b6fe10>
I, [2014-03-13T00:47:13.242653 #87267]  INFO -- : found 1 cookbooks from #<Berkshelf::API::CacheBuilder::Worker::ChefServer:0x007ff330b6fe10>
I, [2014-03-13T00:47:13.243178 #87267]  INFO -- : about to merge cookbooks

````


あとは、"http://(berks-apiが動いているマシン):26200"をBerksfileに指定して、berks installとかすれば依存するcookbookを含めてダウンロードしてきてくれます。

## 補足
berks-apiのログを見ていると、~/.berkshelf/api-server/cerchに対して何かやっていることがわかります。
中身を見てみると

````
$ cat ~/.berkshelf/api-server/cerch | jq .
{
  "endpoints_checksum": "024fcbefc06093e948f32a2120aac6bfc356c28a",
  "sample": {
    "0.1.0": {
      "location_path": "http://localhost:8889/",
      "location_type": "chef_server",
      "dependencies": {},
      "platforms": {},
      "endpoint_priority": 0
    }
  }
}
````
cookbookの名前、version、依存するcookbook、cookbookの取得先の情報をキャッシュしているようです。
変な挙動をした時はここを見ると何かわかるかもしれません。