capistrano-chef-solo

a capistrano recipe to invoke chef-solo.

Installation

Add this line to your application's Gemfile:

gem 'yyuu-capistrano-chef-solo'

And then execute:

$ bundle

Or install it yourself as:

$ gem install yyuu-capistrano-chef-solo

Usage

This recipe will try to bootstrap your servers with chef-solo. Following processes will be invoked.

  1. Install ruby with using capistrano-rbenv
  2. Install chef with using bundler
  3. Checkout your cookbooks
  4. Generate attributes and run_list for your hosts
  5. Invoke chef-solo

To setup your servers with chef-solo, add following in you config/deploy.rb.

# in "config/deploy.rb"
require "capistrano-chef-solo"
set(:chef_solo_version, "11.4.0")
set(:rbenv_ruby_version, "1.9.3-p392")

Then, create directories for your cookbooks and data bags. By default, capistrano-chef-solo searches them from ./config. (see examples of cookbooks and data bags for details)

$ mkdir -p config/cookbooks config/data_bags

Now you can start using chef-solo via Capistrano.

$ cap chef-solo

Plus, there is special method chef_solo.run_list. You can use this to apply recipes during deployment.

after "deploy:finalize_update" do
  chef_solo.run_list "recipe[foo]", "recipe[bar]", "recipe[baz]"
end

Bootstrap mode

After the first time of boot up of servers, you might need to apply some recipes for your initial setup. Let us say you want to have two users on servers.

  • admin - the default user of system, created by system installer. use this for bootstrap. can invoke all commands via sudo.
  • deploy - the user to use for application deployments. will be created during bootstrap. can invoke all commands via sudo.

There is bootstrap mode for this kind of situations. To setup these users, set them in your Capfile.

set(:user, "deploy")
set(:chef_solo_bootstrap_user, "admin")

Then, apply recipes with bootstrap mode.

% cap -S chef_solo_bootstrap=true chef-solo

After the bootstrap, you can deploy application normaly with deploy user.

% cap deploy:setup

Examples

Using cookbooks

Using cookbooks in local path

By default, capistrano-chef-solo searches cookbooks from local path of config/cookbooks. You can specify the cookbooks directory with using chef_solo_cookbooks_subdir.

set(:chef_solo_cookbooks_scm, :none)
set(:chef_solo_cookbooks_subdir, "config/cookbooks")

Using cookbooks in remote repository

You can use cookbooks in remote repository.

set(:chef_solo_cookbooks_scm, :git)
set(:chef_solo_cookbooks_repository, "git://github.com/opscode/cookbooks.git")
set(:chef_solo_cookbooks_revision, "master")
set(:chef_solo_cookbooks_subdir, "/")

Using single cookbook in remote repository

Also you can use single cookbook in remote repository.

set(:chef_solo_cookbook_name, "python")
set(:chef_solo_cookbooks_scm, :git)
set(:chef_solo_cookbooks_repository, "git://github.com/opscode-cookbooks/python.git")
set(:chef_solo_cookbooks_revision, "master")
set(:chef_solo_cookbooks_subdir, "/")

Using mixed configuration

You can use multiple cookbooks repositories at once.

set(:chef_solo_cookbooks) {{
  # use cookbooks in ./config/cookbooks.
  application => {
    :scm => :none,
    :deploy_subdir => "config/cookbooks",
  },
  # use cookbooks in git repository.
  "cookbooks" => {
    :scm => :git,
    :repository => "git://github.com/opscode/cookbooks.git",
    :revision => "master",
  },
  "python" => {
    :cookbook_name => "python",
    :scm => :git,
    :repository => "git://github.com/opscode-cookbooks/python.git",
    :revision => "master",
  },
}}

Using data bags

Using data bags in local path

You can manage your data bags as similar as cookbooks.

By default, capistrano-chef-solo searches data bags from local path of config/data_bags. You can specify the data bags directory with using chef_solo_data_bags_subdir.

set(:chef_solo_data_bags_scm, :none)
set(:chef_solo_data_bags_subdir, "config/data_bags")

Attributes configuration

By default, the Chef attributes will be generated by following order.

  1. Use non-lazy variables of Capistrano.
  2. Use attributes defined in :chef_solo_attributes.
  3. Use attributes defined in :chef_solo_role_attributes for target role.
  4. Use attributes defined in :chef_solo_host_attributes for target host.

Setting common attributes

To apply same attributes to all hosts.

set(:chef_solo_attributes) {{
  "locales" => { "language" => "ja" },
  "tzdata" => { "timezone" => "Asia/Tokyo" },
}}
set(:chef_solo_run_list, ["recipe[locales]", "recipe[tzdata]"])

Setting individual attributes per roles

In some cases, you may want to apply individual attributes per roles.

Following example will create Chef roles role[app] and role[web]. All attributes defined in :chef_solo_role_attributes will be merged into default_attributes of Chef role.

set(:chef_solo_role_attributes) {
  :app => {
    "foo" => "foo",
  },
  :web => {
    "bar" => "bar",
  },
}
set(:chef_solo_role_run_list) {
  :app => ["recipe[build-essential]"],
}

Setting individual attributes per hosts

In some cases, you may want to apply individual attributes per hosts. (Something like server_id of mysqld or VRRP priority of keepalived)

set(:chef_solo_host_attributes) {
  "foo1.example.com" => {
    "keepalived" => {
      "virtual_router_id" => 1,
      "priority" => 100, #=> MASTER
      "virtual_ipaddress" => "192.168.0.1/24",
    },
  },
  "foo2.example.com" => {
    "keepalived" => {
      "virtual_router_id" => 1,
      "priority" => 50, #=> BACKUP
      "virtual_ipaddress" => "192.168.0.1/24",
    },
  },
}

Testing attributes

You can check generated attributes with using chef-solo:attributes task.

% cap HOST=foo1.example.com chef-solo:attributes

Reference

Following options are available to manage your chef-solo.

  • :chef_solo_version - The version of Chef.
  • :chef_solo_use_bunler - Use bundler to install Chef. Set true by default.
  • :chef_solo_cookbooks - The definition of cookbooks. By default, use cookbooks in ./config/cookbooks.
  • :chef_solo_data_bags - The definition of data bags. By default, use data bags in ./config/data_bags.
  • :chef_solo_attributes - The attributes of chef-solo. must be a Hash<String,String>. This will be converted into JSON.
  • :chef_solo_run_list - The run_list of chef-solo. must be an Array<String>. This will be merged into :chef_solo_attributes.
  • :chef_solo_role_attributes - The per-roles attributes of chef-solo. This must be a Hash<Symbol,Hash<String,String>>.
  • :chef_solo_role_run_list - The per-roles run_list of chef-solo. This must be a Hash<Symbol,Array<String>>.
  • :chef_solo_host_attributes - The per-hosts attributes of chef-solo. This must be a Hash<String,Hash<String,String>>.
  • :chef_solo_host_run_list - The per-hosts run_list of chef-solo. This must be a Hash<String,Array<String>>.
  • :chef_solo_capistrano_attributes - The Capistrano variables to use as Chef attributes.
  • :chef_solo_capistrano_attributes_exclude - The black list for :chef_solo_capistrano_attributes
  • :chef_solo_capistrano_attributes_include - The white list for :chef_solo_capistrano_attributes

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

Author

License

MIT