Remove vagrant nodes from chef server on destroy
When working with Vagrant and Chef Server, one thing that bothered me most was to manually remove the node and client registrations. The good thing: it is possible. The bad thing: you have to add the code to every Vagrantfile
where you want to use it (I'll try to create a plugin in the near future). All you need to do is to add the following lines of code to your Vagrantfile
:
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
The chef config is read from a knife.rb
(see Share your chef's knife.rb config with vagrant for details). All it does is asking the chef server to remove the node and client registration using the REST API. Simply type:
$ vagrant destroy
If you don't wanna delete production clients by accident, I suggest to give your vagrant boxes unique names. I usually do it like this:
vm_name = "vagrant-#{name}-#{ENV['USER']}"
config.vm.host_name = vm_name
This way I get something like vagrant-myproject-box1-thomas
, assuming that name
is set to myproject-box1
. This also has the benefit that when working in a team on the same project you don't have collisions (assuming that the user names are unique).
Written by Thomas Massmann
Related protips
3 Responses
This works with single and multi vm environments.
AFAIK https://github.com/cassianoleal/vagrant-butcher does exactly that.
Yes, I know. But at the time of writing this code fragment vagrant butcher did not exist. I'm using the butcher now as well.