5

I'm currently using Vagrant with Chef-solo and it's been working great. I would like to extend the vagrant magic to the chef server. I've switched my provisioner in the Vagrantfile from chef-solo to chef-client and have added the necessary code:

chef.chef_server_url        = "https://chef.mydomain.com"
chef.validation_client_name = "chef-validator"
chef.validation_key_path    = "/Users/inigo/.chef/chef-validator.pem"

My question is how do I go about automating the creation of the client so I don't have to issue the knife commands to create the client and the corresponding client.pem key. Then later I have to issue the knife commands to delete the client when I'm done with it.

I was hoping this is something Vagrant can do and all I would need is some added code to the Vagrantfile then the "vagrant up" "vagrant destroy" commands would handle it all. Unfortunately my googling around have not turned up anything. I've seen posts on how to setup chef-server with vagrant but i'm interested in chef clients. Perhaps a plugin for vagrant or maybe berkshelf?

One more question.. right now when I generate the client.pem key I place it in the shared directory: /vagrant so the VM can get to it. Is there a better way?

Thanks!

Here's is the output of vagrant up:

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
[default] Importing base box 'Berkshelf-CentOS-6.3-x86_64-minimal'...
[default] Matching MAC address for NAT networking...
[default] Setting the name of the VM...
[default] Clearing any previously set forwarded ports...
[Berkshelf] Uploading cookbooks to 'https://chef.mydomain.com:443/'
[Berkshelf] Using testcookbook (0.0.1)
[Berkshelf] Uploading testcookbook (0.0.1) to: 'https://chef.mydomain.com:443/'
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Preparing network interfaces based on configuration...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Setting hostname...
[default] Configuring and enabling network interfaces...
[default] Mounting shared folders...
[default] -- /vagrant
[default] Installing Chef 11.6.0 Omnibus package...
[default] Running provisioner: chef_client...
Creating folder to hold client key...
Uploading chef client validation key...
Generating chef JSON and uploading...
Running chef-client...
[2013-08-15T15:42:28+00:00] INFO: Forking chef instance to converge...
[2013-08-15T15:42:28+00:00] INFO: *** Chef 11.6.0 ***
[2013-08-15T15:42:28+00:00] INFO: Client key /etc/chef/client.pem is not present - registering

====================================================================================
Chef encountered an error attempting to create the client "mytestcookbook-berkshelf"
====================================================================================


[2013-08-15T15:42:29+00:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
[2013-08-15T15:42:29+00:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
Chef never successfully completed! Any errors should be visible in the
output above. Please fix your recipes so that they properly complete.

And here's what the content of the chef-stacktrace.out file looks like on failed vagrant up:

Generated at 2013-08-16 03:42:20 +0000
OpenSSL::PKey::RSAError: private key needed.
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/mixlib-authentication-1.3.0/lib/mixlib/authentication/signedheaderauth.rb:94:in `private_encrypt'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/mixlib-authentication-1.3.0/lib/mixlib/authentication/signedheaderauth.rb:94:in `sign'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/rest/auth_credentials.rb:51:in `signature_headers'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/rest.rb:322:in `authentication_headers'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/rest.rb:368:in `build_headers'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/rest.rb:166:in `raw_http_request'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/rest.rb:161:in `api_request'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/rest.rb:121:in `post'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/api_client/registration.rb:93:in `create'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/api_client/registration.rb:84:in `create_or_update'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/api_client/registration.rb:57:in `run'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/client.rb:376:in `register'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/client.rb:480:in `do_run'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/client.rb:199:in `block in run'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/client.rb:193:in `fork'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/client.rb:193:in `run'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/application.rb:183:in `run_chef_client'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/application/client.rb:302:in `block in run_application'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/application/client.rb:294:in `loop'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/application/client.rb:294:in `run_application'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/lib/chef/application.rb:66:in `run'
/opt/chef/embedded/lib/ruby/gems/1.9.1/gems/chef-11.6.0/bin/chef-client:26:in `<top (required)>'
/usr/bin/chef-client:23:in `load'
/usr/bin/chef-client:23:in `<main>'

And for good measure.. here's the current Vagrantfile minus all the comment lines:

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
  config.vm.hostname = "testcookbook-berkshelf"
  config.vm.box = "Berkshelf-CentOS-6.3-x86_64-minimal"
  config.vm.box_url = "https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box"
  config.vm.network :private_network, ip: "33.33.33.10"
  config.ssh.max_tries = 40
  config.ssh.timeout   = 120
  config.berkshelf.enabled = true
  config.omnibus.chef_version = :latest
  config.vm.provision :chef_client do |chef|
    chef.chef_server_url        = "https://chef.mydomain.com"
    chef.validation_client_name = "chef-validator"
    chef.validation_key_path    = "/Users/inigo/.chef/chef-validator.pem"
    chef.run_list = [
        "recipe[testcookbook::default]"
    ]
  end
end
Ryan B.
  • 353
  • 4
  • 13

1 Answers1

4

The only thing that's wrong in your example is that chef.validation_key_path is probably pointing to the wrong place.

You have to set that to the location of the validation key in your workstation (probably something like "#{ENV['HOME']}/.chef/validation.pem" or similar).

Once you have that in place, when you vagrant up it will copy the validation key file to the VM and use it to create the client and node automatically on the Chef server.

If you don't mind my shameless plug, I've written a Vagrant plugin called Vagrant::Butcher that deals with the deletion of node and client automatically when you issue a vagrant destroy.

cassianoleal
  • 2,556
  • 19
  • 22
  • That part works actually. It takes the validation.pem file from my workstation which is in `/etc/chef` then boots the VM, installs chef and runs chef-client which attempts to register the new VM to chef the server. I expected it to create the client.pem file at this point but instead it just complains that it can't find it. – Ryan B. Aug 15 '13 at 15:46
  • Thanks for the plugin!.. that's exactly what i need when I'm done testing. It would be nice if there was a counterpart for it: `vagrant up`. I am new to chef so i'm probably missing something that takes care of what i'm looking for already. – Ryan B. Aug 15 '13 at 15:55
  • As I said, `vagrant up` should create the object on the Chef server and then create the `client.pem` file. If it's failing, then there's something specific to your environment that's disallowing it to do so. Have you checked that the client does not exist on the server before running `up`? If it exists, delete it (and its node counterpart) before and try again. If it still fails, paste the full error somewhere -- that might give us a clue to what's going on. :) – cassianoleal Aug 15 '13 at 18:50
  • I did a `berks reconfig` and set the chef_client provisioner instead of chef_solo. I then edited the `Vagrantfile` in my cookbook's dir. and added the following: chef.client_key_path = "/vagrant/.chef/client.pem" then ran the knife client create command to generate the client.pem key and pointed it to the cookbook's .chef directory. this created the pem file in the right place and i was able to `vagrant up` no problem. I think I'll just add a :shell provisioner. I need to read up on it more but i think i can bash out that one line to create the pem key on the fly. – Ryan B. Aug 15 '13 at 22:03
  • `berks init` with `chef_client` set as the provisioner i mean – Ryan B. Aug 16 '13 at 02:22
  • Well .. I guess I can't do that. It appears the shell provisioner is only meant to shell out to the guest and not on the host. Since it's my host that can create the client on the chef server, it's not going to to work. There must be something wrong with my Vagrant or chef setup. I double checked my validation.pem file since some of the posts I've seen seem to point to a malformed validation.pem file however it was fine. I even downloaded another just for good measure. – Ryan B. Aug 16 '13 at 05:59
  • You shouldn't need `chef.client_key_path` on your `Vagrantfile`. Try commenting that line out and check that `chef.validation_client_name` and `chef.validation_key_path` are properly set. Remember that `chef.validation_key_path` should point to the validation `.pem` file on the host. – cassianoleal Aug 16 '13 at 12:53
  • @cassianoleal Vagrant::Butcher is awesome! Saves me from having to remember the "knife client delete" and "knife node delete" commands after destroying the VM... and most importantly prevents the annoying delays caused by failed "vagrant up" attempts when I had forgotten to issue those commands!!! – Alan Mar 15 '14 at 01:08
  • :) That's the exact reason why I created it. When I began with Chef, it not only annoyed me, but it was also a great source of misunderstanding as I sometimes thought there was something wrong with my configuration. Many things changed since then, and Vagrant actually has this functionality built in (see the Cleanup section on the [docs](http://docs.vagrantup.com/v2/provisioning/chef_client.html). I still think Butcher is superior though, as it doesn't require a client key (so you don't need to create clients for each developer working on cookbooks) or even Chef itself on the workstation. – cassianoleal Mar 15 '14 at 11:27
  • Similar functionality has been proposed to enter the core, but Mitchell is still not very happy about the added dependencies. See [this pull request](https://github.com/mitchellh/vagrant/pull/3014) for more info. – cassianoleal Mar 15 '14 at 11:28