core: ProvisionerCleanup task to run cleanup on provisioners

This commit is contained in:
Mitchell Hashimoto 2013-08-29 11:13:43 -07:00
parent 93c98aad01
commit d4c7e20110
9 changed files with 101 additions and 28 deletions

View File

@ -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:

View File

@ -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"

View File

@ -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<Provisioner>]
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -97,6 +97,7 @@ module VagrantPlugins
b3.use Destroy
b3.use CleanMachineFolder
b3.use DestroyUnusedNetworkInterfaces
b3.use ProvisionerCleanup
else
b3.use MessageWillNotDestroy
end

View File

@ -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

View File

@ -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: |-