Last Updated: March 08, 2016
·
4.557K
· tmassman

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).

3 Responses
Add your response

This works with single and multi vm environments.

over 1 year ago ·
over 1 year ago ·

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.

over 1 year ago ·