サーバー設定ツール「Chef」をより便利に使うためのテクニック 4ページ

Data Bagを使ったRecipeを作成する

 続いて、RecipeからData Bagに格納したデータにアクセスする方法を説明しよう。今回は「setup-user」というCookbookを作成し、そこから先ほどのData Bagにアクセスしてユーザーやグループを作成することにする。

$ cd chef-repo/cookbooks/
$ knife cookbook create setup-user -o .
** Creating cookbook setup-user
** Creating README for cookbook: setup-user
** Creating CHANGELOG for cookbook: setup-user
** Creating metadata for cookbook: setup-user
$ vi setup-user/recipes/default.rb
Recipe(default.rb)の内容は、以下のようになる。
accounts = data_bag('initial_accounts')
accounts.each do |id|
  item = data_bag_item('initial_accounts', id)

  item['groups'].each do |g|
    group g['name'] do
      gid g['gid']
      action :create
    end
  end

  item['users'].each do |u|
    user u['name'] do
      home u['home']
      password u['password']
      shell u['shell']
      uid u['uid']
      gid u['gid']
      supports :manage_home => true
      action :create
    end
  end
end

 Recipe内からData Bagのデータを取得するには、data_bag関数を使用する。引数には対象のData Bag名を文字列で指定する。たとえば「initial_accounts」というData Bagを取得するには、以下のようになる。

accounts = data_bag('initial_accounts')

 data_bag関数の戻り値は、data_bagに含まれるデータの「id」を格納した配列となる。続いて、Data Bag名とidを引数に与えてdata_bag_item関数を実行することで、データをハッシュとして取得できる。今回の例では、以下のように配列のeachメソッドを使ってidを順番に取り出し、それを引数としてdata_bag_item関数を呼び出すことでデータを取り出している。

accounts.each do |id|
  item = data_bag_item('initial_accounts', id)

 data_bag_item関数の戻り値は、JSONで指定したものと同じデータ構造を持つハッシュとなっており、以下のように[‘キー名’]という書式で各項目を取得可能だ。

  item['groups'].each do |g|
    group g['name'] do
      gid g['gid']
      action :create
    end
  end

 作成したCookbookは前回解説したとおり「knife cookbook upload」コマンドでアップロードできる。

$ knife cookbook upload setup-user

 このCookbookをクライアント側で実行すると、以下のようにユーザーおよびグループが作成される。

# chef-client -o setup-user
Starting Chef Client, version 11.6.2
[2013-10-24T19:58:40+09:00] WARN: Run List override has been provided.
[2013-10-24T19:58:40+09:00] WARN: Original Run List: []
[2013-10-24T19:58:40+09:00] WARN: Overridden Run List: [recipe[setup-user]]
resolving cookbooks for run list: ["setup-user"]
Synchronizing Cookbooks:
  - setup-user
Compiling Cookbooks...
Converging 2 resources
Recipe: setup-user::default
  * group[taro] action create (up to date)
  * user[taro] action create
    - alter user user[taro]

Chef Client finished, 1 resources updated

 このように作成されたCookbookでは、Cookbook側を変更することなく、Data Bagのみを変更することで作成するユーザーを追加したり、その情報を変更することが可能だ。たとえば、新たに「jiro」というユーザーを追加したい場合、JSONファイルを以下のように修正すれば良い。

{
  "id": "default",
  "groups": [
    {
      "name": "hylom",
      "gid": 1000
    },
    {
      "name": "jiro",
      "gid": 1001
    }
  ],
  "users": [
    {
      "name": "hylom",
      "home": "/home/hylom",
      "password": "$6$OmC3KootOURrqOaP$63rwQ2bSE8op8wXa.ZWzgxm/iGvePTzEL5lOntmkPyYh5Qwh4lWs2DtyoEHcvsbYV5Q6a2ezzrZueb2ydrkhz0",
      "shell": "/bin/bash",
      "uid": 1000,
      "gid": "hylom"
    },
    {
      "name": "jiro",
      "home": "/home/jiro",
      "password": "$6$OmC3KootOURrqOaP$63rwQ2bSE8op8wXa.ZWzgxm/iGvePTzEL5lOntmkPyYh5Qwh4lWs2DtyoEHcvsbYV5Q6a2ezzrZueb2ydrkhz0",
      "shell": "/bin/bash",
      "uid": 1001,
      "gid": "jiro"
    }
  ]
}

 このJSONデータをData Bagに格納し、再度Cookbookを実行すると新たにユーザー「jiro」が作成される。

$ knife data bag from_file initial_accounts default.json
# chef-client -o setup-user
Starting Chef Client, version 11.6.2
[2013-10-24T20:08:31+09:00] WARN: Run List override has been provided.
[2013-10-24T20:08:31+09:00] WARN: Original Run List: [recipe[setup-user]]
[2013-10-24T20:08:31+09:00] WARN: Overridden Run List: [recipe[setup-user]]
resolving cookbooks for run list: ["setup-user"]
Synchronizing Cookbooks:
  - setup-user
Compiling Cookbooks...
Converging 4 resources
Recipe: setup-user::default
  * group[taro] action create (up to date)
  * group[jiro] action create
    - create group[jiro]

  * user[taro] action create (up to date)
  * user[jiro] action create
    - create user user[jiro]

Chef Client finished, 2 resources updated