Search code examples
vagrantchef-infra

Chef in local mode cookbooks only


I'm trying to set up a workflow to develop Chef cookbooks locally. We're currently using Chef Server with the provisioned nodes using chef-client.

As part of the new workflow, we want to be able to start using Vagrant to test cookbooks locally to avoid incurring in the costs of testing on a remote machine in a cloud.

I'm able to launch and provision a local Vagrant machine, but the one thing I'm not really sure how to do is to have Chef load the local version of the cookbook, but still talk to the Chef server for everything else (environments, roles, data bags, etc.), so I don't have to upload the cookbook via knife every time I make a change I want to test. Is this possible?

In other words, can I make chef-client talk to the local chef-zero server only for the cookbooks but to the remote Chef server for everything else? Or maybe a different approach that would yield the same effect? I'm open to suggestions.

UPDATE

I think an example will help to express what I'm looking for. I'm realizing that this may not really be what I need, but I'm curious about how to achieve it anyway. In this scenario, a recipe reads from a databag stored in the remote Chef server

metadata.rb

name             'proxy-cookbook'
version          '0.0.0'

.kitchen.yml

---
driver:
  name: vagrant

provisioner:
  name: chef_zero

platforms:
  - name: ubuntu-12.04

suites:
  - name: default
    run_list:
      - recipe[proxy-cookbook::default]
    attributes:

recipes/default.rb

...
key = data_bag_item("key", "main")
....

Now, I know I can create something along the lines of:

data_bags/main.json

{
  "id": "main",
  "key": "s3cr3tk3y"
}

And have my kitchen tests read from that data bag; but that is exactly what I'm trying to avoid. Is it possible to either:

  • Instruct test-kitchen to get the actual data bag from chef server,
  • Have chef-zero retrieve a temporary copy of the data bags for local tests, or
  • Quickly "dump" the contents of a remote Chef server locally?

I hope that makes sense. I can add some context if necessary.


Solution

  • I think I found what I was looking for.

    You can use knife to download the Chef server objects that you need. You can bootstrap this in .kitchen.yml so you don't have to do it manually every time.

    .kitchen.yml

    ...
    driver:
      name: vagrant
      pre_create_command: 'mkdir -p chef-server; knife download /data_bags /roles /environments --chef-repo-path chef-server/'
    ...
    provisioner:
      name: chef_zero
      data_bags_path: chef-server/data_bags
      roles_path: chef-server/roles
      environments_path: chef-server/environments
      client_rb:
        environment: development
    ...
    

    And then I just added the chef-server directory to .gitignore

    .gitignore

    chef-server/
    

    There might be a less redundant way of doing this, but this works for me right now, and since I just wanted to document this, I'm leaving it like that.