From d4c7e2011018798b642c8bb401d61a401bfda46f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 29 Aug 2013 11:13:43 -0700 Subject: [PATCH] core: ProvisionerCleanup task to run cleanup on provisioners --- CHANGELOG.md | 2 + lib/vagrant/action.rb | 1 + .../action/builtin/mixin_provisioners.rb | 43 +++++++++++++++++++ lib/vagrant/action/builtin/provision.rb | 28 ++++-------- .../action/builtin/provisioner_cleanup.rb | 29 +++++++++++++ lib/vagrant/plugin/v2/provisioner.rb | 6 +++ plugins/providers/virtualbox/action.rb | 1 + .../chef/provisioner/chef_client.rb | 17 ++++---- templates/locales/en.yml | 2 + 9 files changed, 101 insertions(+), 28 deletions(-) create mode 100644 lib/vagrant/action/builtin/mixin_provisioners.rb create mode 100644 lib/vagrant/action/builtin/provisioner_cleanup.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index edb1e0ed9..74fe0e673 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ FEATURES: CoreOS. [GH-2022] - Solaris 11 guest support. [GH-2052] - Support for environments in the Chef-solo provisioner. [GH-1915] + - Provisioners can now define "cleanup" tasks that are executed on + `vagrant destroy`. [GH-1302] IMPROVEMENTS: diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index 74b55ac6a..67e71decc 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -20,6 +20,7 @@ module Vagrant autoload :Lock, "vagrant/action/builtin/lock" autoload :NFS, "vagrant/action/builtin/nfs" autoload :Provision, "vagrant/action/builtin/provision" + autoload :ProvisionerCleanup, "vagrant/action/builtin/provisioner_cleanup" autoload :SetHostname, "vagrant/action/builtin/set_hostname" autoload :SSHExec, "vagrant/action/builtin/ssh_exec" autoload :SSHRun, "vagrant/action/builtin/ssh_run" diff --git a/lib/vagrant/action/builtin/mixin_provisioners.rb b/lib/vagrant/action/builtin/mixin_provisioners.rb new file mode 100644 index 000000000..aa303cb08 --- /dev/null +++ b/lib/vagrant/action/builtin/mixin_provisioners.rb @@ -0,0 +1,43 @@ +module Vagrant + module Action + module Builtin + module MixinProvisioners + # This returns all the instances of the configured provisioners. + # This is safe to call multiple times since it will cache the results. + # + # @return [Array] + def provisioner_instances + return @_provisioner_instances if @_provisioner_instances + + # Make the mapping that'll keep track of provisioner => type + @_provisioner_types = {} + + # Get all the configured provisioners + @_provisioner_instances = env[:machine].config.vm.provisioners.map do |provisioner| + # Instantiate the provisioner + klass = Vagrant.plugin("2").manager.provisioners[provisioner.name] + result = klass.new(env[:machine], provisioner.config) + + # Store in the type map so that --provision-with works properly + @_provisioner_types[result] = provisioner.name + + # Return the result + result + end + + return @_provisioner_instances + end + + # This will return a mapping of a provisioner instance to its + # type. + def provisioner_type_map + # Call this in order to initial the map if it hasn't been already + provisioner_instances + + # Return the type map + @_provisioner_types + end + end + end + end +end diff --git a/lib/vagrant/action/builtin/provision.rb b/lib/vagrant/action/builtin/provision.rb index 7c6cefd4f..8e4838cbb 100644 --- a/lib/vagrant/action/builtin/provision.rb +++ b/lib/vagrant/action/builtin/provision.rb @@ -1,5 +1,7 @@ require "log4r" +require_relative "mixin_provisioners" + module Vagrant module Action module Builtin @@ -10,6 +12,8 @@ module Vagrant # can do some setup, and then run again (on the return path) against # a running machine. class Provision + include MixinProvisioners + def initialize(app, env) @app = app @logger = Log4r::Logger.new("vagrant::action::builtin::provision") @@ -20,24 +24,8 @@ module Vagrant enabled = true enabled = env[:provision_enabled] if env.has_key?(:provision_enabled) - # This keeps track of a mapping between provisioner and type - type_map = {} - - # Get all the configured provisioners - provisioners = env[:machine].config.vm.provisioners.map do |provisioner| - # Instantiate the provisioner - klass = Vagrant.plugin("2").manager.provisioners[provisioner.name] - result = klass.new(env[:machine], provisioner.config) - - # Store in the type map so that --provision-with works properly - type_map[result] = provisioner.name - - # Return the result - result - end - # Ask the provisioners to modify the configuration if needed - provisioners.each do |p| + provisioner_instances.each do |p| p.configure(env[:machine].config) end @@ -46,11 +34,11 @@ module Vagrant # Actually provision if we enabled it if enabled - provisioners.each do |p| + provisioner_instances.each do |p| next if env[:provision_types] && \ - !env[:provision_types].include?(type_map[p]) + !env[:provision_types].include?(provisioner_type_map[p]) - run_provisioner(env, type_map[p].to_s, p) + run_provisioner(env, provisioner_type_map[p].to_s, p) end end end diff --git a/lib/vagrant/action/builtin/provisioner_cleanup.rb b/lib/vagrant/action/builtin/provisioner_cleanup.rb new file mode 100644 index 000000000..bebfbe11f --- /dev/null +++ b/lib/vagrant/action/builtin/provisioner_cleanup.rb @@ -0,0 +1,29 @@ +require "log4r" + +module Vagrant + module Action + module Builtin + # This action will run the cleanup methods on provisioners and should + # be used as part of any Destroy action. + class ProvisionerCleanup + def initialize(app, env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::builtin::provision_cleanup") + end + + def call(env) + # Ask the provisioners to modify the configuration if needed + provisioners.each do |p| + env[:ui].info(I18n.t( + "vagrant.provisioner_cleanup", + name: provisioner_type_map[p].to_s)) + p.cleanup + end + + # Continue, we need the VM to be booted. + @app.call(env) + end + end + end + end +end diff --git a/lib/vagrant/plugin/v2/provisioner.rb b/lib/vagrant/plugin/v2/provisioner.rb index 131c78880..25a0a6acc 100644 --- a/lib/vagrant/plugin/v2/provisioner.rb +++ b/lib/vagrant/plugin/v2/provisioner.rb @@ -41,6 +41,12 @@ module Vagrant # No return value is expected. def provision end + + # This is the method called when destroying a machine that allows + # for any state related to the machine created by the provisioner + # to be cleaned up. + def cleanup + end end end end diff --git a/plugins/providers/virtualbox/action.rb b/plugins/providers/virtualbox/action.rb index c94a08421..5608d8a23 100644 --- a/plugins/providers/virtualbox/action.rb +++ b/plugins/providers/virtualbox/action.rb @@ -97,6 +97,7 @@ module VagrantPlugins b3.use Destroy b3.use CleanMachineFolder b3.use DestroyUnusedNetworkInterfaces + b3.use ProvisionerCleanup else b3.use MessageWillNotDestroy end diff --git a/plugins/provisioners/chef/provisioner/chef_client.rb b/plugins/provisioners/chef/provisioner/chef_client.rb index e277814a3..0b9e2af65 100644 --- a/plugins/provisioners/chef/provisioner/chef_client.rb +++ b/plugins/provisioners/chef/provisioner/chef_client.rb @@ -25,6 +25,11 @@ module VagrantPlugins run_chef_client end + def cleanup + delete_from_chef_server('client') if config.delete_client + delete_from_chef_server('node') if config.delete_node + end + def create_client_key_folder @machine.env.ui.info I18n.t("vagrant.provisioners.chef.client_key_folder") path = Pathname.new(@config.client_key_path) @@ -98,15 +103,11 @@ module VagrantPlugins File.join(@config.provisioning_path, "validation.pem") end - def cleanup - delete_from_chef_server('client') if config.delete_client - delete_from_chef_server('node') if config.delete_node - end - def delete_from_chef_server(deletable) - node_name = (config.node_name || env[:vm].config.vm.host_name) - env[:ui].info I18n.t("vagrant.provisioners.chef.deleting_from_server", - :deletable => deletable, :name => node_name) + node_name = config.node_name || env[:vm].config.vm.host_name + env[:ui].info(I18n.t( + "vagrant.provisioners.chef.deleting_from_server", + deletable: deletable, name: node_name)) Kernel.system("knife #{deletable} delete --yes #{node_name} > /dev/null 2>&1") end end diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 514f8e2c7..fe9acae77 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -27,6 +27,8 @@ en: Executing run file for CFEngine... chef_run_list_empty: |- Warning: Chef solo run list is empty. This may not be what you want. + provisioner_cleanup: |- + Running cleanup tasks for '%{name}' provisioner... cfengine_config: classes_array: |-