Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Create a vagrant box with chef server provisioning and automatic client and node cleanup on the server when the vagrant box gets destroyed. All necessary api keys and config options are taken from environment variables. The knife.rb must live inside a .chef directory besides the Vagrantfile.
# Opscode chef configurations.
export KNIFE_CHEF_SERVER="https://chef-api.example.com"
export KNIFE_CLIENT_KEY="$HOME/.chef/client.pem"
export KNIFE_NODE_NAME="myclient"
export KNIFE_VALIDATION_CLIENT_NAME="chef-validator"
export KNIFE_VALIDATION_CLIENT_KEY="$HOME/.chef/chef-validator.pem"
# Logging.
log_level :debug
log_location STDOUT
# Chef server configuration.
chef_server_url "#{ENV['KNIFE_CHEF_SERVER']}"
client_key "#{ENV['KNIFE_CLIENT_KEY']}"
node_name "#{ENV['KNIFE_NODE_NAME']}"
validation_client_name "#{ENV['KNIFE_VALIDATION_CLIENT_NAME']}"
validation_key "#{ENV['KNIFE_VALIDATION_CLIENT_KEY']}"
# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'chef'
Chef::Config.from_file(File.join(File.dirname(__FILE__), '.chef', 'knife.rb'))
vms = {
"testbox" => {
:box => "precise64",
:ipaddress => "192.168.33.10",
:run_list => "role[base]"
}
}
Vagrant::Config.run do |global_config|
vms.each_pair do |name, options|
global_config.vm.define name do |config|
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = options[:box]
vm_name = "vagrant-#{name}-#{ENV['USER']}"
# Boot with a GUI so you can see the screen. (Default is headless)
# config.vm.boot_mode = :gui
# Assign this VM to a host-only network IP, allowing you to access it
# via the IP. Host-only networks can talk to the host machine as well as
# any other machines on the same network, but cannot be accessed (through this
# network interface) by any external networks.
config.vm.network :hostonly, options[:ipaddress]
config.vm.host_name = vm_name
# Enable provisioning with chef server, specifying the chef server URL,
# and the path to the validation key (relative to this Vagrantfile).
config.vm.provision :chef_client do |chef|
chef.chef_server_url = Chef::Config[:chef_server_url]
chef.log_level = Chef::Config[:log_level]
chef.node_name = vm_name
chef.validation_key_path = Chef::Config[:validation_key]
chef.validation_client_name = Chef::Config[:validation_client_name]
chef.environment = "development"
run_list = []
run_list << ENV['CHEF_RUN_LIST'].split(",") if ENV.has_key?('CHEF_RUN_LIST')
chef.run_list = [options[:run_list].split(","), run_list].flatten
end
end
end
end
module Vagrant
module Provisioners
class Base
require 'chef'
require 'chef/config'
require 'chef/knife'
end
class ChefClient
::Chef::Config.from_file(File.join(File.dirname(__FILE__), '.chef', 'knife.rb'))
def cleanup
node = env[:vm].config.vm.host_name
env[:ui].info "Attempting to clean up client '#{node}' on chef server."
begin
::Chef::REST.new(::Chef::Config[:chef_server_url]).delete_rest("clients/#{node}")
rescue Net::HTTPServerException => e
if e.message == '404 "Not Found"'
env[:ui].info "Client '#{node}' not found."
else
env[:ui].error "An error occured. You will have to remove the client manually."
end
rescue Exception => e
env[:ui].error "An error occured. You will have to remove the client manually."
else
env[:ui].info "Client '#{node}' successfully removed from chef server."
end
env[:ui].info "Attempting to clean up node '#{node}' on chef server."
begin
::Chef::REST.new(::Chef::Config[:chef_server_url]).delete_rest("nodes/#{node}")
rescue Net::HTTPServerException => e
if e.message == '404 "Not Found"'
env[:ui].info "Node '#{node}' not found."
else
env[:ui].error "An error occured. You will have to remove the node manually."
end
rescue Exception => e
env[:ui].error "An error occured. You will have to remove the node manually."
else
env[:ui].info "Node '#{node}' successfully removed from chef server."
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.