Chef "Top-Level Cookbooks" Workflow
chef-tlc-workflow supports an opiniated workflow for working with Chef. It is based on the strict distinction of top-level vs. dependent cookbooks (see below) and it's currently focussed on chef-solo only.
First of all, it provides a working sample for deployment to esx, ec2 and local from within single Vagrantfile.
Other than that it provides helper methods to use the dependencies defined in metadata.rb from within librarian Cheffiles. This ensures consistency between the dependencies specified in metadata and resolved via librarian (NOTE: to be replaced with Berkshelf soon!)
Finally, it ensures a consistent gem set by declaring all the gems we use in our workflow in its own gemspec, i.e. chef-tlc-workflow is the only gem you need to depend on - everything else (like vagrant, mcloud, etc..) comes in as transitive dependencies.
Terminology
- infrastructure is a Chef-Repo like structure which describes the nodes that are part of it and which services are to be installed on these nodes via top-level cookbooks
- top-level cookbooks are the top-level cookbooks that fully configure a node by combining a set of dependent cookbooks, configuring them appropriately and locking them at a specific version.
- dependent cookbooks are the finer-grained, reusable and flexible cookbooks that you typically leverage for building high-level services in terms of top-level cookbooks
Installation
Add this line to your application's Gemfile:
gem 'chef-tlc-workflow'
And then execute:
$ bundle
Or install it yourself as:
$ gem install chef-tlc-workflow
Prerequisites
You need Vagrant 1.2.x and the following plugins for the sample Vagrantfile to work:
vagrant plugin install vagrant-aws --plugin-version 0.2.2
vagrant plugin install vagrant-managed-servers --plugin-version 0.1.0
vagrant plugin install vagrant-omnibus --plugin-version 1.0.2
vagrant plugin install vagrant-cachier --plugin-version 0.1.0
Usage
Deployment to VirtualBox, AWS and Managed ESX Servers
Assuming you are in the test/vagrant-1.x-bootstrap directory you need to install the bundle first:
$ cd test/vagrant-1.x-bootstrap
$ bundle install
Fetching gem from http://rubygems.org/..
Fetching gem from https://gems.gemfury.com/psBbdHx94zqZrvxpiVmm/..
Using rake (0.9.6)
Using Platform (0.4.0)
Using ansi (1.4.3)
Using archive-tar-minitar (0.5.2)
Using multi_json (1.7.6)
...
Then you need to resolve the sample-app top-level cookbook along with all its dependencies into the ./cookbooks directory:
$ rake resolve_sample_app
cd tmp/tlc/sample-app-0.1.0 && librarian-chef install --path D:/Repos/_github/chef-tlc-workflow/test/vagrant-1.x-bootstrap/cookbooks/sample-app-0.1.0
Installing apache2 (1.5.0)
Installing apt (1.3.2)
Installing sample-app (0.1.0)
See, the dependencies are now resolved per top-level cookbook (i.e. sample-app-0.1.0 in this case) separately:
$ ls -la cookbooks/sample-app-0.1.0
total 12
drwxr-xr-x 5 tkn tkn 0 Jun 11 17:44 .
drwxr-xr-x 3 tkn tkn 0 Jun 11 17:44 ..
drwxr-xr-x 7 tkn tkn 4096 Jun 11 17:44 apache2
drwxr-xr-x 6 tkn tkn 4096 Jun 11 17:44 apt
drwxr-xr-x 6 tkn tkn 4096 Jun 11 17:44 sample-app
Deploy to VirtualBox:
vagrant up sample-app-vbox
Deploy to AWS via [vagrant-aws]:
vagrant up sample-app-aws --provider=aws
Deploy to a managed ESX Server:
vagrant up sample-app-esx --provider=managed
vagrant provision sample-app-esx
Librarian Helper
NOTE: this is going to be replaced with Berkshelf soon
Since librarian does not support reading the cookbook dependencies from metadata.rb, the ChefTLCWorkflow::Helpers module adds this functionality.
In the trivial case you can use it in your cookbook project's Cheffile like so:
require 'chef-tlc-workflow/helpers'
ChefTLCWorkflow::Helpers::.each do |cb_name, cb_version|
cookbook cb_name, cb_version
end
If some of the cookbooks defined in metadata.rb are not available from the community site, you can define your overrides like so:
...
@overrides = {
'tlc-base' => { :git => 'https://github.com/tknerr/cookbook-tlc-base.git', :ref => 'master' },
}
ChefTLCWorkflow::Helpers::.each do |cb_name, cb_version|
cookbook cb_name, cb_version, @overrides[cb_name]
end
Single Gemfile Dependency
It references all gems we need for our Chef workflow, this means that your Gemfile basically looks like this:
source :rubygems
gem "chef-tlc-workflow", "0.2.0"
This brings in all the transitive gem dependencies as defined in the chef-tlc-workflow.gemspec, e.g. librarian, chef, foodcritic, etc...
While this is not ideal in terms of keeping the LOAD_PATH as small as possible, it's a tradeoff in favor of convenience and consistency.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request