Skip to content

Commit

Permalink
core: ProvisionerCleanup task to run cleanup on provisioners
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Aug 29, 2013
1 parent 93c98aa commit d4c7e20
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
1 change: 1 addition & 0 deletions lib/vagrant/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Builtin
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"
Expand Down
43 changes: 43 additions & 0 deletions lib/vagrant/action/builtin/mixin_provisioners.rb
Original file line number Diff line number Diff line change
@@ -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
28 changes: 8 additions & 20 deletions lib/vagrant/action/builtin/provision.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
require "log4r"

require_relative "mixin_provisioners"

module Vagrant
module Action
module Builtin
Expand All @@ -10,6 +12,8 @@ module Builtin
# 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")
Expand All @@ -20,24 +24,8 @@ def call(env)
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

Expand All @@ -46,11 +34,11 @@ def call(env)

# 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
Expand Down
29 changes: 29 additions & 0 deletions lib/vagrant/action/builtin/provisioner_cleanup.rb
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions lib/vagrant/plugin/v2/provisioner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ def configure(root_config)
# 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
Expand Down
1 change: 1 addition & 0 deletions plugins/providers/virtualbox/action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def self.action_destroy
b3.use Destroy
b3.use CleanMachineFolder
b3.use DestroyUnusedNetworkInterfaces
b3.use ProvisionerCleanup
else
b3.use MessageWillNotDestroy
end
Expand Down
17 changes: 9 additions & 8 deletions plugins/provisioners/chef/provisioner/chef_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ def provision
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)
Expand Down Expand Up @@ -98,15 +103,11 @@ def guest_validation_key_path
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
Expand Down
2 changes: 2 additions & 0 deletions templates/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |-
Expand Down

0 comments on commit d4c7e20

Please sign in to comment.