vagrantup 0.6.9 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +37 -0
  4. data/Gemfile +0 -8
  5. data/README.md +5 -0
  6. data/config/default.rb +1 -3
  7. data/contrib/README.md +12 -0
  8. data/contrib/emacs/vagrant.el +8 -0
  9. data/contrib/vim/vagrantfile.vim +9 -0
  10. data/lib/vagrant/action/box/download.rb +0 -1
  11. data/lib/vagrant/action/box.rb +11 -0
  12. data/lib/vagrant/action/builtin.rb +1 -2
  13. data/lib/vagrant/action/env.rb +7 -0
  14. data/lib/vagrant/action/general.rb +8 -0
  15. data/lib/vagrant/action/vm/boot.rb +3 -2
  16. data/lib/vagrant/action/vm/check_box.rb +1 -0
  17. data/lib/vagrant/action/vm/clean_machine_folder.rb +1 -1
  18. data/lib/vagrant/action/vm/destroy.rb +1 -1
  19. data/lib/vagrant/action/vm/destroy_unused_network_interfaces.rb +7 -12
  20. data/lib/vagrant/action/vm/network.rb +1 -1
  21. data/lib/vagrant/action/vm/nfs.rb +3 -1
  22. data/lib/vagrant/action/vm/provision.rb +14 -25
  23. data/lib/vagrant/action/vm/share_folders.rb +11 -4
  24. data/lib/vagrant/action/vm.rb +30 -0
  25. data/lib/vagrant/action.rb +12 -0
  26. data/lib/vagrant/command.rb +25 -0
  27. data/lib/vagrant/config/base.rb +17 -3
  28. data/lib/vagrant/config/ssh.rb +2 -2
  29. data/lib/vagrant/config/top.rb +61 -0
  30. data/lib/vagrant/config/vagrant.rb +1 -6
  31. data/lib/vagrant/config/vm/provisioner.rb +56 -0
  32. data/lib/vagrant/config/vm/sub_vm.rb +17 -0
  33. data/lib/vagrant/config/vm.rb +34 -20
  34. data/lib/vagrant/config.rb +78 -128
  35. data/lib/vagrant/downloaders/file.rb +1 -0
  36. data/lib/vagrant/downloaders/http.rb +9 -0
  37. data/lib/vagrant/downloaders.rb +7 -0
  38. data/lib/vagrant/environment.rb +26 -14
  39. data/lib/vagrant/errors.rb +5 -15
  40. data/lib/vagrant/hosts.rb +7 -0
  41. data/lib/vagrant/provisioners/base.rb +19 -1
  42. data/lib/vagrant/provisioners/chef.rb +31 -52
  43. data/lib/vagrant/provisioners/chef_server.rb +34 -10
  44. data/lib/vagrant/provisioners/chef_solo.rb +31 -9
  45. data/lib/vagrant/provisioners/puppet.rb +111 -60
  46. data/lib/vagrant/provisioners/puppet_server.rb +57 -0
  47. data/lib/vagrant/provisioners.rb +8 -0
  48. data/lib/vagrant/ssh/session.rb +81 -0
  49. data/lib/vagrant/ssh.rb +6 -76
  50. data/lib/vagrant/systems/base.rb +16 -1
  51. data/lib/vagrant/systems/debian.rb +26 -0
  52. data/lib/vagrant/systems/gentoo.rb +27 -0
  53. data/lib/vagrant/systems/linux/config.rb +21 -0
  54. data/lib/vagrant/systems/linux/error.rb +9 -0
  55. data/lib/vagrant/systems/linux.rb +14 -56
  56. data/lib/vagrant/systems/redhat.rb +31 -0
  57. data/lib/vagrant/systems.rb +9 -0
  58. data/lib/vagrant/test_helpers.rb +1 -1
  59. data/lib/vagrant/version.rb +1 -1
  60. data/lib/vagrant/vm.rb +25 -5
  61. data/lib/vagrant.rb +14 -18
  62. data/templates/chef_solo_solo.erb +11 -3
  63. data/templates/commands/init/Vagrantfile.erb +13 -11
  64. data/templates/locales/en.yml +76 -26
  65. data/templates/{network_entry.erb → network_entry_debian.erb} +0 -0
  66. data/templates/network_entry_gentoo.erb +7 -0
  67. data/templates/network_entry_redhat.erb +8 -0
  68. data/templates/ssh_config.erb +1 -1
  69. data/test/vagrant/action/vm/check_box_test.rb +1 -0
  70. data/test/vagrant/action/vm/clean_machine_folder_test.rb +6 -4
  71. data/test/vagrant/action/vm/destroy_test.rb +1 -1
  72. data/test/vagrant/action/vm/destroy_unused_network_interfaces_test.rb +10 -7
  73. data/test/vagrant/action/vm/nfs_test.rb +7 -1
  74. data/test/vagrant/action/vm/provision_test.rb +24 -79
  75. data/test/vagrant/action/vm/share_folders_test.rb +6 -1
  76. data/test/vagrant/command/helpers_test.rb +2 -2
  77. data/test/vagrant/config/base_test.rb +0 -6
  78. data/test/vagrant/config/vagrant_test.rb +0 -8
  79. data/test/vagrant/config/vm/provisioner_test.rb +92 -0
  80. data/test/vagrant/config/vm_test.rb +8 -0
  81. data/test/vagrant/config_test.rb +49 -89
  82. data/test/vagrant/downloaders/file_test.rb +18 -4
  83. data/test/vagrant/environment_test.rb +36 -12
  84. data/test/vagrant/provisioners/base_test.rb +28 -1
  85. data/test/vagrant/provisioners/chef_server_test.rb +50 -41
  86. data/test/vagrant/provisioners/chef_solo_test.rb +39 -16
  87. data/test/vagrant/provisioners/chef_test.rb +11 -81
  88. data/test/vagrant/provisioners/puppet_server_test.rb +69 -0
  89. data/test/vagrant/provisioners/puppet_test.rb +116 -69
  90. data/test/vagrant/{ssh_session_test.rb → ssh/session_test.rb} +0 -0
  91. data/test/vagrant/ssh_test.rb +20 -7
  92. data/test/vagrant/systems/base_test.rb +18 -0
  93. data/test/vagrant/systems/linux_test.rb +2 -2
  94. data/test/vagrant/vm_test.rb +33 -5
  95. data/vagrant.gemspec +6 -5
  96. metadata +38 -14
  97. data/lib/vagrant/action/vm/disable_networks.rb +0 -34
  98. data/lib/vagrant/util/glob_loader.rb +0 -24
  99. data/test/vagrant/action/vm/disable_networks_test.rb +0 -48
@@ -12,23 +12,30 @@ module Vagrant
12
12
  vm.ssh.execute do |ssh|
13
13
  # Checks for the existence of chef binary and error if it
14
14
  # doesn't exist.
15
- ssh.exec!("which #{binary}", :error_class => ChefError, :_key => :chef_not_detected, :binary => binary)
15
+ ssh.exec!("sudo -i which #{binary}", :error_class => ChefError, :_key => :chef_not_detected, :binary => binary)
16
16
  end
17
17
  end
18
18
 
19
19
  def chown_provisioning_folder
20
20
  vm.ssh.execute do |ssh|
21
- ssh.exec!("sudo mkdir -p #{env.config.chef.provisioning_path}")
22
- ssh.exec!("sudo chown #{env.config.ssh.username} #{env.config.chef.provisioning_path}")
21
+ ssh.exec!("sudo mkdir -p #{config.provisioning_path}")
22
+ ssh.exec!("sudo chown #{env.config.ssh.username} #{config.provisioning_path}")
23
23
  end
24
24
  end
25
25
 
26
26
  def setup_config(template, filename, template_vars)
27
27
  config_file = TemplateRenderer.render(template, {
28
- :log_level => env.config.chef.log_level.to_sym
28
+ :log_level => config.log_level.to_sym,
29
+ :http_proxy => config.http_proxy,
30
+ :http_proxy_user => config.http_proxy_user,
31
+ :http_proxy_pass => config.http_proxy_pass,
32
+ :https_proxy => config.https_proxy,
33
+ :https_proxy_user => config.https_proxy_user,
34
+ :https_proxy_pass => config.https_proxy_pass,
35
+ :no_proxy => config.no_proxy
29
36
  }.merge(template_vars))
30
37
 
31
- vm.ssh.upload!(StringIO.new(config_file), File.join(env.config.chef.provisioning_path, filename))
38
+ vm.ssh.upload!(StringIO.new(config_file), File.join(config.provisioning_path, filename))
32
39
  end
33
40
 
34
41
  def setup_json
@@ -45,11 +52,11 @@ module Vagrant
45
52
 
46
53
  # Merge with the "extra data" which isn't put under the
47
54
  # vagrant namespace by default
48
- data.merge!(env.config.chef.json)
55
+ data.merge!(config.json)
49
56
 
50
57
  json = data.to_json
51
58
 
52
- vm.ssh.upload!(StringIO.new(json), File.join(env.config.chef.provisioning_path, "dna.json"))
59
+ vm.ssh.upload!(StringIO.new(json), File.join(config.provisioning_path, "dna.json"))
53
60
  end
54
61
  end
55
62
 
@@ -61,37 +68,31 @@ module Vagrant
61
68
 
62
69
  class Chef < Base
63
70
  # This is the configuration which is available through `config.chef`
64
- class ChefConfig < Vagrant::Config::Base
65
- configures :chef
66
-
67
- # Chef server specific config
68
- attr_accessor :chef_server_url
69
- attr_accessor :validation_key_path
70
- attr_accessor :validation_client_name
71
- attr_accessor :client_key_path
72
- attr_accessor :node_name
73
-
74
- # Chef solo specific config
75
- attr_accessor :cookbooks_path
76
- attr_accessor :roles_path
77
- attr_accessor :recipe_url
78
-
71
+ class Config < Vagrant::Config::Base
79
72
  # Shared config
73
+ attr_accessor :node_name
80
74
  attr_accessor :provisioning_path
81
75
  attr_accessor :log_level
82
76
  attr_accessor :json
77
+ attr_accessor :http_proxy
78
+ attr_accessor :http_proxy_user
79
+ attr_accessor :http_proxy_pass
80
+ attr_accessor :https_proxy
81
+ attr_accessor :https_proxy_user
82
+ attr_accessor :https_proxy_pass
83
+ attr_accessor :no_proxy
83
84
 
84
85
  def initialize
85
- @validation_client_name = "chef-validator"
86
- @client_key_path = "/etc/chef/client.pem"
87
-
88
- @cookbooks_path = ["cookbooks", [:vm, "cookbooks"]]
89
- @roles_path = []
90
86
  @provisioning_path = "/tmp/vagrant-chef"
91
87
  @log_level = :info
92
- @json = {
93
- :instance_role => "vagrant",
94
- }
88
+ @json = { :instance_role => "vagrant" }
89
+ @http_proxy = nil
90
+ @http_proxy_user = nil
91
+ @http_proxy_pass = nil
92
+ @https_proxy = nil
93
+ @https_proxy_user = nil
94
+ @https_proxy_pass = nil
95
+ @no_proxy = nil
95
96
  end
96
97
 
97
98
  # Returns the run list for the provisioning
@@ -123,28 +124,6 @@ module Vagrant
123
124
  result.delete("json")
124
125
  result
125
126
  end
126
-
127
- def validate(errors)
128
- if top.vm.provisioner == :chef_solo
129
- # Validate chef solo settings
130
- errors.add(I18n.t("vagrant.config.chef.cookbooks_path_empty")) if !cookbooks_path || [cookbooks_path].flatten.empty?
131
- end
132
-
133
- if top.vm.provisioner == :chef_server
134
- # Validate chef server settings
135
- errors.add(I18n.t("vagrant.config.chef.server_url_empty")) if !chef_server_url || chef_server_url.strip == ""
136
- errors.add(I18n.t("vagrant.config.chef.validation_key_path")) if !validation_key_path
137
- end
138
-
139
- if top.vm.provisioner == :chef_solo
140
- # On chef solo, a run list MUST be specified
141
- errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if !json[:run_list] || run_list.empty?
142
- elsif top.vm.provisioner == :chef_server
143
- # On chef server, the run list is allowed to be nil, which causes it
144
- # to sync with the chef server.
145
- errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if json[:run_list] && run_list.empty?
146
- end
147
- end
148
127
  end
149
128
  end
150
129
  end
@@ -5,10 +5,34 @@ module Vagrant
5
5
  # This class implements provisioning via chef-client, allowing provisioning
6
6
  # with a chef server.
7
7
  class ChefServer < Chef
8
+ register :chef_server
9
+
10
+ class Config < Chef::Config
11
+ attr_accessor :chef_server_url
12
+ attr_accessor :validation_key_path
13
+ attr_accessor :validation_client_name
14
+ attr_accessor :client_key_path
15
+
16
+ def initialize
17
+ super
18
+
19
+ @validation_client_name = "chef-validator"
20
+ @client_key_path = "/etc/chef/client.pem"
21
+ end
22
+
23
+ def validate(errors)
24
+ super
25
+
26
+ errors.add(I18n.t("vagrant.config.chef.server_url_empty")) if !chef_server_url || chef_server_url.strip == ""
27
+ errors.add(I18n.t("vagrant.config.chef.validation_key_path")) if !validation_key_path
28
+ errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if json[:run_list] && run_list.empty?
29
+ end
30
+ end
31
+
8
32
  def prepare
9
- raise ChefError, :server_validation_key_required if env.config.chef.validation_key_path.nil?
33
+ raise ChefError, :server_validation_key_required if config.validation_key_path.nil?
10
34
  raise ChefError, :server_validation_key_doesnt_exist if !File.file?(validation_key_path)
11
- raise ChefError, :server_url_required if env.config.chef.chef_server_url.nil?
35
+ raise ChefError, :server_url_required if config.chef_server_url.nil?
12
36
  end
13
37
 
14
38
  def provision!
@@ -23,7 +47,7 @@ module Vagrant
23
47
 
24
48
  def create_client_key_folder
25
49
  env.ui.info I18n.t("vagrant.provisioners.chef.client_key_folder")
26
- path = Pathname.new(env.config.chef.client_key_path)
50
+ path = Pathname.new(config.client_key_path)
27
51
 
28
52
  vm.ssh.execute do |ssh|
29
53
  ssh.exec!("sudo mkdir -p #{path.dirname}")
@@ -37,16 +61,16 @@ module Vagrant
37
61
 
38
62
  def setup_server_config
39
63
  setup_config("chef_server_client", "client.rb", {
40
- :node_name => env.config.chef.node_name,
41
- :chef_server_url => env.config.chef.chef_server_url,
42
- :validation_client_name => env.config.chef.validation_client_name,
64
+ :node_name => config.node_name,
65
+ :chef_server_url => config.chef_server_url,
66
+ :validation_client_name => config.validation_client_name,
43
67
  :validation_key => guest_validation_key_path,
44
- :client_key => env.config.chef.client_key_path
68
+ :client_key => config.client_key_path
45
69
  })
46
70
  end
47
71
 
48
72
  def run_chef_client
49
- command = "cd #{env.config.chef.provisioning_path} && sudo -E chef-client -c client.rb -j dna.json"
73
+ command = "sudo -i 'cd #{config.provisioning_path} && chef-client -c client.rb -j dna.json'"
50
74
 
51
75
  env.ui.info I18n.t("vagrant.provisioners.chef.running_client")
52
76
  vm.ssh.execute do |ssh|
@@ -61,11 +85,11 @@ module Vagrant
61
85
  end
62
86
 
63
87
  def validation_key_path
64
- File.expand_path(env.config.chef.validation_key_path, env.root_path)
88
+ File.expand_path(config.validation_key_path, env.root_path)
65
89
  end
66
90
 
67
91
  def guest_validation_key_path
68
- File.join(env.config.chef.provisioning_path, "validation.pem")
92
+ File.join(config.provisioning_path, "validation.pem")
69
93
  end
70
94
  end
71
95
  end
@@ -2,6 +2,28 @@ module Vagrant
2
2
  module Provisioners
3
3
  # This class implements provisioning via chef-solo.
4
4
  class ChefSolo < Chef
5
+ register :chef_solo
6
+
7
+ class Config < Chef::Config
8
+ attr_accessor :cookbooks_path
9
+ attr_accessor :roles_path
10
+ attr_accessor :recipe_url
11
+
12
+ def initialize
13
+ super
14
+
15
+ @cookbooks_path = ["cookbooks", [:vm, "cookbooks"]]
16
+ @roles_path = []
17
+ end
18
+
19
+ def validate(errors)
20
+ super
21
+
22
+ errors.add(I18n.t("vagrant.config.chef.cookbooks_path_empty")) if !cookbooks_path || [cookbooks_path].flatten.empty?
23
+ errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if !json[:run_list] || run_list.empty?
24
+ end
25
+ end
26
+
5
27
  def prepare
6
28
  share_cookbook_folders
7
29
  share_role_folders
@@ -29,16 +51,16 @@ module Vagrant
29
51
 
30
52
  def setup_solo_config
31
53
  setup_config("chef_solo_solo", "solo.rb", {
32
- :node_name => env.config.chef.node_name,
33
- :provisioning_path => env.config.chef.provisioning_path,
54
+ :node_name => config.node_name,
55
+ :provisioning_path => config.provisioning_path,
34
56
  :cookbooks_path => cookbooks_path,
35
- :recipe_url => env.config.chef.recipe_url,
57
+ :recipe_url => config.recipe_url,
36
58
  :roles_path => roles_path,
37
59
  })
38
60
  end
39
61
 
40
62
  def run_chef_solo
41
- command = "cd #{env.config.chef.provisioning_path} && sudo -E chef-solo -c solo.rb -j dna.json"
63
+ command = "sudo -i 'cd #{config.provisioning_path} && chef-solo -c solo.rb -j dna.json'"
42
64
 
43
65
  env.ui.info I18n.t("vagrant.provisioners.chef.running_solo")
44
66
  vm.ssh.execute do |ssh|
@@ -64,7 +86,7 @@ module Vagrant
64
86
  end
65
87
 
66
88
  def folder_path(*args)
67
- File.join(env.config.chef.provisioning_path, args.join("-"))
89
+ File.join(config.provisioning_path, args.join("-"))
68
90
  end
69
91
 
70
92
  def folders_path(folders, folder)
@@ -90,11 +112,11 @@ module Vagrant
90
112
  end
91
113
 
92
114
  def host_cookbook_paths
93
- host_folder_paths(env.config.chef.cookbooks_path)
115
+ host_folder_paths(config.cookbooks_path)
94
116
  end
95
117
 
96
118
  def host_role_paths
97
- host_folder_paths(env.config.chef.roles_path)
119
+ host_folder_paths(config.roles_path)
98
120
  end
99
121
 
100
122
  def cookbook_path(i)
@@ -106,11 +128,11 @@ module Vagrant
106
128
  end
107
129
 
108
130
  def cookbooks_path
109
- folders_path(env.config.chef.cookbooks_path, "cookbooks").to_json
131
+ folders_path(config.cookbooks_path, "cookbooks").to_json
110
132
  end
111
133
 
112
134
  def roles_path
113
- folders_path(env.config.chef.roles_path, "roles").to_json
135
+ folders_path(config.roles_path, "roles").to_json
114
136
  end
115
137
  end
116
138
  end
@@ -1,85 +1,136 @@
1
1
  module Vagrant
2
2
  module Provisioners
3
+ class PuppetError < Vagrant::Errors::VagrantError
4
+ error_namespace("vagrant.provisioners.puppet")
5
+ end
3
6
 
4
- class PuppetError < Vagrant::Errors::VagrantError
5
- error_namespace("vagrant.provisioners.puppet")
6
- end
7
+ class Puppet < Base
8
+ register :puppet
7
9
 
8
- class PuppetConfig < Vagrant::Config::Base
9
- configures :puppet
10
+ class Config < Vagrant::Config::Base
11
+ attr_accessor :manifest_file
12
+ attr_accessor :manifests_path
13
+ attr_accessor :module_path
14
+ attr_accessor :pp_path
15
+ attr_accessor :options
10
16
 
11
- attr_accessor :manifest_file
12
- attr_accessor :manifests_path
13
- attr_accessor :pp_path
14
- attr_accessor :options
17
+ def initialize
18
+ @manifest_file = nil
19
+ @manifests_path = "manifests"
20
+ @module_path = nil
21
+ @pp_path = "/tmp/vagrant-puppet"
22
+ @options = []
23
+ end
15
24
 
16
- def initialize
17
- @manifest_file = ""
18
- @manifests_path = "manifests"
19
- @pp_path = "/tmp/vagrant-puppet"
20
- @options = []
21
- end
22
- end
25
+ # Returns the manifests path expanded relative to the root path of the
26
+ # environment.
27
+ def expanded_manifests_path
28
+ Pathname.new(manifests_path).expand_path(env.root_path)
29
+ end
23
30
 
24
- class Puppet < Base
25
- def prepare
26
- check_manifest_dir
27
- share_manifests
28
- end
31
+ # Returns the manifest file if set otherwise returns the box name pp file
32
+ # which may or may not exist.
33
+ def computed_manifest_file
34
+ manifest_file || "#{top.vm.box}.pp"
35
+ end
29
36
 
30
- def provision!
31
- verify_binary("puppet")
32
- create_pp_path
33
- set_manifest
34
- run_puppet_client
35
- end
37
+ # Returns the module paths as an array of paths expanded relative to the
38
+ # root path.
39
+ def expanded_module_paths
40
+ return [] if !module_path
36
41
 
37
- def check_manifest_dir
38
- Dir.mkdir(env.config.puppet.manifests_path) unless File.directory?(env.config.puppet.manifests_path)
39
- end
42
+ # Get all the paths and expand them relative to the root path, returning
43
+ # the array of expanded paths
44
+ paths = module_path
45
+ paths = [paths] if !paths.is_a?(Array)
46
+ paths.map do |path|
47
+ Pathname.new(path).expand_path(env.root_path)
48
+ end
49
+ end
40
50
 
41
- def share_manifests
42
- env.config.vm.share_folder("manifests", env.config.puppet.pp_path, env.config.puppet.manifests_path)
43
- end
51
+ def validate(errors)
52
+ super
44
53
 
45
- def verify_binary(binary)
46
- vm.ssh.execute do |ssh|
47
- ssh.exec!("which #{binary}", :error_class => PuppetError, :_key => :puppet_not_detected, :binary => binary)
54
+ # Manifests path/file validation
55
+ if !expanded_manifests_path.directory?
56
+ errors.add(I18n.t("vagrant.provisioners.puppet.manifests_path_missing", :path => expanded_manifests_path))
57
+ else
58
+ if !expanded_manifests_path.join(computed_manifest_file).file?
59
+ errors.add(I18n.t("vagrant.provisioners.puppet.manifest_missing", :manifest => computed_manifest_file))
60
+ end
61
+ end
62
+
63
+ # Module paths validation
64
+ expanded_module_paths.each do |path|
65
+ if !path.directory?
66
+ errors.add(I18n.t("vagrant.provisioners.puppet.module_path_missing", :path => path))
67
+ end
68
+ end
69
+ end
48
70
  end
49
- end
50
71
 
51
- def create_pp_path
52
- vm.ssh.execute do |ssh|
53
- ssh.exec!("sudo mkdir -p #{env.config.puppet.pp_path}")
54
- ssh.exec!("sudo chown #{env.config.ssh.username} #{env.config.puppet.pp_path}")
72
+ def prepare
73
+ set_module_paths
74
+ share_manifests
75
+ share_module_paths
55
76
  end
56
- end
57
77
 
58
- def set_manifest
59
- @manifest = !env.config.puppet.manifest_file.empty? ? env.config.puppet.manifest_file : "#{env.config.vm.box}.pp"
78
+ def provision!
79
+ verify_binary("puppet")
80
+ run_puppet_client
81
+ end
60
82
 
61
- if File.exists?("#{env.config.puppet.manifests_path}/#{@manifest}")
62
- env.ui.info I18n.t("vagrant.provisioners.puppet.manifest_to_run", :manifest => @manifest)
63
- return @manifest
64
- else
65
- raise PuppetError, :_key => :manifest_missing, :manifest => @manifest
83
+ def share_manifests
84
+ env.config.vm.share_folder("manifests", manifests_guest_path, config.expanded_manifests_path)
66
85
  end
67
- end
68
86
 
69
- def run_puppet_client
70
- options = env.config.puppet.options
71
- options = options.join(" ") if options.is_a?(Array)
72
- command = "cd #{env.config.puppet.pp_path} && sudo -E puppet #{options} #{@manifest}"
87
+ def share_module_paths
88
+ count = 0
89
+ @module_paths.each do |from, to|
90
+ # Sorry for the cryptic key here, but VirtualBox has a strange limit on
91
+ # maximum size for it and its something small (around 10)
92
+ env.config.vm.share_folder("v-pp-m#{count}", to, from)
93
+ count += 1
94
+ end
95
+ end
96
+
97
+ def set_module_paths
98
+ @module_paths = {}
99
+ config.expanded_module_paths.each_with_index do |path, i|
100
+ @module_paths[path] = File.join(config.pp_path, "modules-#{i}")
101
+ end
102
+ end
103
+
104
+ def manifests_guest_path
105
+ File.join(config.pp_path, "manifests")
106
+ end
107
+
108
+ def verify_binary(binary)
109
+ vm.ssh.execute do |ssh|
110
+ ssh.exec!("sudo -i which #{binary}", :error_class => PuppetError, :_key => :puppet_not_detected, :binary => binary)
111
+ end
112
+ end
113
+
114
+ def run_puppet_client
115
+ options = [config.options].flatten
116
+ options << "--modulepath '#{@module_paths.values.join(':')}'" if !@module_paths.empty?
117
+ options << config.computed_manifest_file
118
+ options = options.join(" ")
119
+
120
+ command = "sudo -i 'cd #{manifests_guest_path}; puppet #{options}'"
73
121
 
74
- env.ui.info I18n.t("vagrant.provisioners.puppet.running_puppet")
122
+ env.ui.info I18n.t("vagrant.provisioners.puppet.running_puppet", :manifest => config.computed_manifest_file)
75
123
 
76
- vm.ssh.execute do |ssh|
77
- ssh.exec!(command) do |channel, type, data|
78
- ssh.check_exit_status(data, command) if type == :exit_status
79
- env.ui.info("#{data}: #{type}") if type != :exit_status
124
+ vm.ssh.execute do |ssh|
125
+ ssh.exec! command do |ch, type, data|
126
+ if type == :exit_status
127
+ ssh.check_exit_status(data, command)
128
+ else
129
+ env.ui.info(data)
130
+ end
131
+ end
80
132
  end
81
133
  end
82
134
  end
83
135
  end
84
- end
85
136
  end
@@ -0,0 +1,57 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ class PuppetServerError < Vagrant::Errors::VagrantError
4
+ error_namespace("vagrant.provisioners.puppet_server")
5
+ end
6
+
7
+ class PuppetServer < Base
8
+ register :puppet_server
9
+
10
+ class Config < Vagrant::Config::Base
11
+ attr_accessor :puppet_server
12
+ attr_accessor :puppet_node
13
+ attr_accessor :options
14
+
15
+ def initialize
16
+ @puppet_server = "puppet"
17
+ @puppet_node = "puppet_node"
18
+ @options = []
19
+ end
20
+ end
21
+
22
+ def provision!
23
+ verify_binary("puppetd")
24
+ run_puppetd_client
25
+ end
26
+
27
+ def verify_binary(binary)
28
+ vm.ssh.execute do |ssh|
29
+ ssh.shell do |sh|
30
+ sh.execute("sudo -i which #{binary}", :error_class => PuppetServerError, :_key => :puppetd_not_detected, :binary => binary)
31
+ end
32
+ end
33
+ end
34
+
35
+ def run_puppetd_client
36
+ options = config.options
37
+ options = options.join(" ") if options.is_a?(Array)
38
+ if config.puppet_node
39
+ cn = config.puppet_node
40
+ else
41
+ cn = env.config.vm.box
42
+ end
43
+
44
+ command = "sudo -i puppetd #{options} --server #{config.puppet_server} --certname #{cn}"
45
+
46
+ env.ui.info I18n.t("vagrant.provisioners.puppet_server.running_puppetd")
47
+
48
+ vm.ssh.execute do |ssh|
49
+ ssh.exec!(command) do |channel, type, data|
50
+ ssh.check_exit_status(data, command) if type == :exit_status
51
+ env.ui.info(data) if type != :exit_status
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,8 @@
1
+ # These aren't autoloaded because they have to register things such
2
+ # as configuration classes right away with Vagrant.
3
+ require 'vagrant/provisioners/base'
4
+ require 'vagrant/provisioners/chef'
5
+ require 'vagrant/provisioners/chef_server'
6
+ require 'vagrant/provisioners/chef_solo'
7
+ require 'vagrant/provisioners/puppet'
8
+ require 'vagrant/provisioners/puppet_server'
@@ -0,0 +1,81 @@
1
+ module Vagrant
2
+ class SSH
3
+ # A helper class which wraps around `Net::SSH::Connection::Session`
4
+ # in order to provide basic command error checking while still
5
+ # providing access to the actual session object.
6
+ class Session
7
+ include Util::Retryable
8
+
9
+ attr_reader :session
10
+
11
+ def initialize(session)
12
+ @session = session
13
+ end
14
+
15
+ # Executes a given command and simply returns true/false if the
16
+ # command succeeded or not.
17
+ def test?(command)
18
+ exec!(command) do |ch, type, data|
19
+ return true if type == :exit_status && data == 0
20
+ end
21
+
22
+ false
23
+ end
24
+
25
+ # Executes a given command on the SSH session and blocks until
26
+ # the command completes. This is an almost line for line copy of
27
+ # the actual `exec!` implementation, except that this
28
+ # implementation also reports `:exit_status` to the block if given.
29
+ def exec!(command, options=nil, &block)
30
+ options = { :error_check => true }.merge(options || {})
31
+
32
+ block ||= Proc.new do |ch, type, data|
33
+ check_exit_status(data, command, options) if type == :exit_status && options[:error_check]
34
+
35
+ ch[:result] ||= ""
36
+ ch[:result] << data if [:stdout, :stderr].include?(type)
37
+ end
38
+
39
+ retryable(:tries => 5, :on => IOError, :sleep => 0.5) do
40
+ metach = session.open_channel do |channel|
41
+ channel.exec(command) do |ch, success|
42
+ raise "could not execute command: #{command.inspect}" unless success
43
+
44
+ # Output stdout data to the block
45
+ channel.on_data do |ch2, data|
46
+ block.call(ch2, :stdout, data)
47
+ end
48
+
49
+ # Output stderr data to the block
50
+ channel.on_extended_data do |ch2, type, data|
51
+ block.call(ch2, :stderr, data)
52
+ end
53
+
54
+ # Output exit status information to the block
55
+ channel.on_request("exit-status") do |ch2, data|
56
+ block.call(ch2, :exit_status, data.read_long)
57
+ end
58
+ end
59
+ end
60
+
61
+ metach.wait
62
+ metach[:result]
63
+ end
64
+ end
65
+
66
+ # Checks for an erroroneous exit status and raises an exception
67
+ # if so.
68
+ def check_exit_status(exit_status, command, options=nil)
69
+ if exit_status != 0
70
+ options = {
71
+ :_error_class => Errors::VagrantError,
72
+ :_key => :ssh_bad_exit_status,
73
+ :command => command
74
+ }.merge(options || {})
75
+
76
+ raise options[:_error_class], options
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end