Skip to content

Instantly share code, notes, and snippets.

@thomasmassmann
Last active August 26, 2018 00:24
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save thomasmassmann/4520142 to your computer and use it in GitHub Desktop.
Save thomasmassmann/4520142 to your computer and use it in GitHub Desktop.
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
@thomasmassmann
Copy link
Author

The code is based on the blogpost MultiVM Vagrantfile for Chef by Joshua Timberman, the Chef Server Sandbox by spheromak and the gist by cassiano.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment