vagrant 0.1.4 → 0.2.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. data/Gemfile +1 -1
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/bin/vagrant-box +1 -2
  5. data/bin/vagrant-down +1 -2
  6. data/bin/vagrant-halt +1 -2
  7. data/bin/vagrant-init +1 -2
  8. data/bin/vagrant-package +1 -2
  9. data/bin/vagrant-reload +1 -2
  10. data/bin/vagrant-resume +1 -2
  11. data/bin/vagrant-ssh +1 -2
  12. data/bin/vagrant-status +29 -0
  13. data/bin/vagrant-suspend +1 -2
  14. data/bin/vagrant-up +1 -2
  15. data/config/default.rb +5 -9
  16. data/keys/README.md +10 -0
  17. data/keys/vagrant +27 -0
  18. data/keys/vagrant.pub +1 -0
  19. data/lib/vagrant/actions/base.rb +14 -0
  20. data/lib/vagrant/actions/collection.rb +36 -0
  21. data/lib/vagrant/actions/runner.rb +4 -10
  22. data/lib/vagrant/actions/vm/boot.rb +4 -5
  23. data/lib/vagrant/actions/vm/customize.rb +17 -0
  24. data/lib/vagrant/actions/vm/destroy.rb +11 -2
  25. data/lib/vagrant/actions/vm/forward_ports.rb +24 -0
  26. data/lib/vagrant/actions/vm/import.rb +1 -0
  27. data/lib/vagrant/actions/vm/provision.rb +30 -52
  28. data/lib/vagrant/actions/vm/reload.rb +2 -2
  29. data/lib/vagrant/actions/vm/shared_folders.rb +37 -25
  30. data/lib/vagrant/actions/vm/up.rb +8 -4
  31. data/lib/vagrant/active_list.rb +66 -0
  32. data/lib/vagrant/commands.rb +44 -0
  33. data/lib/vagrant/config.rb +64 -47
  34. data/lib/vagrant/downloaders/file.rb +2 -12
  35. data/lib/vagrant/env.rb +48 -12
  36. data/lib/vagrant/provisioners/base.rb +22 -0
  37. data/lib/vagrant/provisioners/chef.rb +102 -0
  38. data/lib/vagrant/provisioners/chef_server.rb +96 -0
  39. data/lib/vagrant/provisioners/chef_solo.rb +67 -0
  40. data/lib/vagrant/ssh.rb +25 -6
  41. data/lib/vagrant/stacked_proc_runner.rb +33 -0
  42. data/lib/vagrant/vm.rb +8 -0
  43. data/lib/vagrant.rb +10 -5
  44. data/test/test_helper.rb +22 -6
  45. data/test/vagrant/actions/collection_test.rb +110 -0
  46. data/test/vagrant/actions/runner_test.rb +11 -7
  47. data/test/vagrant/actions/vm/boot_test.rb +7 -7
  48. data/test/vagrant/actions/vm/customize_test.rb +16 -0
  49. data/test/vagrant/actions/vm/destroy_test.rb +19 -6
  50. data/test/vagrant/actions/vm/forward_ports_test.rb +52 -0
  51. data/test/vagrant/actions/vm/import_test.rb +10 -3
  52. data/test/vagrant/actions/vm/provision_test.rb +75 -70
  53. data/test/vagrant/actions/vm/reload_test.rb +3 -2
  54. data/test/vagrant/actions/vm/shared_folders_test.rb +62 -9
  55. data/test/vagrant/actions/vm/up_test.rb +4 -4
  56. data/test/vagrant/active_list_test.rb +169 -0
  57. data/test/vagrant/config_test.rb +145 -29
  58. data/test/vagrant/downloaders/file_test.rb +4 -19
  59. data/test/vagrant/env_test.rb +96 -23
  60. data/test/vagrant/provisioners/base_test.rb +27 -0
  61. data/test/vagrant/provisioners/chef_server_test.rb +175 -0
  62. data/test/vagrant/provisioners/chef_solo_test.rb +142 -0
  63. data/test/vagrant/provisioners/chef_test.rb +116 -0
  64. data/test/vagrant/ssh_test.rb +29 -8
  65. data/test/vagrant/stacked_proc_runner_test.rb +43 -0
  66. data/test/vagrant/vm_test.rb +23 -0
  67. data/vagrant.gemspec +35 -8
  68. metadata +42 -11
  69. data/script/vagrant-ssh-expect.sh +0 -22
@@ -11,13 +11,17 @@ virtual machine already exists and is not a file! The dotfile is
11
11
  currently configured to be `#{Env.dotfile_path}`
12
12
 
13
13
  To change this value, please see `config.vagrant.dotfile_name`
14
+
15
+ This often exists if you're trying to create a Vagrant virtual
16
+ environment from your home directory. To resolve this, you can either
17
+ modify the configuration a bit, or simply use a different directory.
14
18
  msg
15
19
  end
16
20
 
17
21
  # Up is a "meta-action" so it really just queues up a bunch
18
22
  # of other actions in its place:
19
- steps = [Import, ForwardPorts, SharedFolders, Boot]
20
- steps << Provision if Vagrant.config.chef.enabled
23
+ steps = [Import, Customize, ForwardPorts, SharedFolders, Boot]
24
+ steps << Provision if !Vagrant.config.vm.provisioner.nil?
21
25
  steps.insert(0, MoveHardDrive) if Vagrant.config.vm.hd_location
22
26
 
23
27
  steps.each do |action_klass|
@@ -31,8 +35,8 @@ msg
31
35
  end
32
36
 
33
37
  def persist
34
- logger.info "Persisting the VM UUID (#{@runner.vm.uuid})..."
35
- Env.persist_vm(@runner.vm)
38
+ logger.info "Persisting the VM UUID (#{@runner.uuid})..."
39
+ Env.persist_vm(@runner)
36
40
  end
37
41
 
38
42
  def setup_mac_address
@@ -0,0 +1,66 @@
1
+ module Vagrant
2
+ # This class represents the active list of vagrant virtual
3
+ # machines.
4
+ class ActiveList
5
+ FILENAME = "active.json"
6
+
7
+ @@list = nil
8
+
9
+ class <<self
10
+ # Parses and returns the list of UUIDs from the active VM
11
+ # JSON file. This will cache the result, which can be reloaded
12
+ # by setting the `reload` parameter to true.
13
+ #
14
+ # @return [Array<String>]
15
+ def list(reload = false)
16
+ return @@list unless @@list.nil? || reload
17
+
18
+ @@list ||= []
19
+ return @@list unless File.file?(path)
20
+ File.open(path, "r") do |f|
21
+ @@list = JSON.parse(f.read)
22
+ end
23
+
24
+ @@list
25
+ end
26
+
27
+ # Returns an array of {Vagrant::VM} objects which are currently
28
+ # active.
29
+ def vms
30
+ list.collect { |uuid| Vagrant::VM.find(uuid) }.compact
31
+ end
32
+
33
+ # Returns an array of UUIDs filtered so each is verified to exist.
34
+ def filtered_list
35
+ vms.collect { |vm| vm.uuid }
36
+ end
37
+
38
+ # Adds a virtual environment to the list of active virtual machines
39
+ def add(vm)
40
+ list << vm.uuid
41
+ list.uniq!
42
+ save
43
+ end
44
+
45
+ # Remove a virtual environment from the list of active virtual machines
46
+ def remove(vm)
47
+ vm = vm.uuid if vm.is_a?(Vagrant::VM)
48
+ list.delete(vm)
49
+ save
50
+ end
51
+
52
+ # Persists the list down to the JSON file.
53
+ def save
54
+ File.open(path, "w+") do |f|
55
+ f.write(filtered_list.to_json)
56
+ end
57
+ end
58
+
59
+ # Returns the path to the JSON file which holds the UUIDs of the
60
+ # active virtual machines managed by Vagrant.
61
+ def path
62
+ File.join(Env.home_path, FILENAME)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -24,6 +24,49 @@ error
24
24
  FileUtils.cp(File.join(PROJECT_ROOT, "templates", Env::ROOTFILE_NAME), rootfile_path)
25
25
  end
26
26
 
27
+ # Outputs the status of the current environment. This command outputs
28
+ # useful information such as whether or not the environment is created
29
+ # and if its running, suspended, etc.
30
+ def status
31
+ Env.load!
32
+
33
+ wrap_output do
34
+ if !Env.persisted_vm
35
+ puts <<-msg
36
+ The environment has not yet been created. Run `vagrant up` to create the
37
+ environment.
38
+ msg
39
+ else
40
+ additional_msg = ""
41
+ if Env.persisted_vm.vm.running?
42
+ additional_msg = <<-msg
43
+ To stop this VM, you can run `vagrant halt` to shut it down forcefully,
44
+ or you can run `vagrant suspend` to simply suspend the virtual machine.
45
+ In either case, to restart it again, simply run a `vagrant up`.
46
+ msg
47
+ elsif Env.persisted_vm.vm.saved?
48
+ additional_msg = <<-msg
49
+ To resume this VM, simply run `vagrant up`.
50
+ msg
51
+ elsif Env.persisted_vm.vm.powered_off?
52
+ additional_msg = <<-msg
53
+ To restart this VM, simply run `vagrant up`.
54
+ msg
55
+ end
56
+
57
+ if !additional_msg.empty?
58
+ additional_msg.chomp!
59
+ additional_msg = "\n\n#{additional_msg}"
60
+ end
61
+
62
+ puts <<-msg
63
+ The environment has been created. The status of the current environment's
64
+ virtual machine is: "#{Env.persisted_vm.vm.state}."#{additional_msg}
65
+ msg
66
+ end
67
+ end
68
+ end
69
+
27
70
  # Bring up a vagrant instance. This handles everything from importing
28
71
  # the base VM, setting up shared folders, forwarded ports, etc to
29
72
  # provisioning the instance with chef. {up} also starts the instance,
@@ -139,6 +182,7 @@ Please specify a valid action to take on the boxes, either
139
182
 
140
183
  vagrant box add name uri
141
184
  vagrant box remove name
185
+ vagrant box list
142
186
  error
143
187
  end
144
188
 
@@ -4,32 +4,30 @@ module Vagrant
4
4
  end
5
5
 
6
6
  class Config
7
- @config = nil
8
- @config_runners = []
7
+ extend StackedProcRunner
8
+
9
+ @@config = nil
9
10
 
10
11
  class << self
11
12
  def reset!
12
- @config = nil
13
- config_runners.clear
13
+ @@config = nil
14
+ proc_stack.clear
14
15
  end
15
16
 
16
- def config
17
- @config ||= Config::Top.new
17
+ def configures(key, klass)
18
+ config.class.configures(key, klass)
18
19
  end
19
20
 
20
- def config_runners
21
- @config_runners ||= []
21
+ def config
22
+ @@config ||= Config::Top.new
22
23
  end
23
24
 
24
25
  def run(&block)
25
- config_runners << block
26
+ push_proc(&block)
26
27
  end
27
28
 
28
29
  def execute!
29
- config_runners.each do |block|
30
- block.call(config)
31
- end
32
-
30
+ run_procs!(config)
33
31
  config.loaded!
34
32
  end
35
33
  end
@@ -60,20 +58,32 @@ module Vagrant
60
58
  attr_accessor :forwarded_port_key
61
59
  attr_accessor :max_tries
62
60
  attr_accessor :timeout
61
+ attr_accessor :private_key_path
62
+
63
+ def private_key_path
64
+ File.expand_path(@private_key_path, Env.root_path)
65
+ end
63
66
  end
64
67
 
65
68
  class VMConfig < Base
69
+ include StackedProcRunner
70
+
66
71
  attr_accessor :box
67
72
  attr_accessor :box_ovf
68
73
  attr_accessor :base_mac
69
74
  attr_accessor :project_directory
70
75
  attr_reader :forwarded_ports
76
+ attr_reader :shared_folders
71
77
  attr_accessor :hd_location
72
78
  attr_accessor :disk_image_format
73
-
79
+ attr_accessor :provisioner
80
+ attr_accessor :shared_folder_uid
81
+ attr_accessor :shared_folder_gid
74
82
 
75
83
  def initialize
76
84
  @forwarded_ports = {}
85
+ @shared_folders = {}
86
+ @provisioner = nil
77
87
  end
78
88
 
79
89
  def forward_port(name, guestport, hostport, protocol="TCP")
@@ -84,13 +94,28 @@ module Vagrant
84
94
  }
85
95
  end
86
96
 
97
+ def share_folder(name, guestpath, hostpath)
98
+ @shared_folders[name] = {
99
+ :guestpath => guestpath,
100
+ :hostpath => hostpath
101
+ }
102
+ end
103
+
87
104
  def hd_location=(val)
88
- raise Exception.new "disk_storage must be set to a directory" unless File.directory?(val)
105
+ raise Exception.new("disk_storage must be set to a directory") unless File.directory?(val)
89
106
  @hd_location=val
90
107
  end
91
108
 
92
- def base
93
- File.expand_path(@base)
109
+ def shared_folder_uid
110
+ @shared_folder_uid || Vagrant.config.ssh.username
111
+ end
112
+
113
+ def shared_folder_gid
114
+ @shared_folder_gid || Vagrant.config.ssh.username
115
+ end
116
+
117
+ def customize(&block)
118
+ push_proc(&block)
94
119
  end
95
120
  end
96
121
 
@@ -99,48 +124,40 @@ module Vagrant
99
124
  attr_accessor :extension
100
125
  end
101
126
 
102
- class ChefConfig < Base
103
- attr_accessor :cookbooks_path
104
- attr_accessor :provisioning_path
105
- attr_accessor :json
106
- attr_accessor :enabled
107
-
108
- def initialize
109
- @enabled = false
110
- end
111
-
112
- def to_json
113
- # Overridden so that the 'json' key could be removed, since its just
114
- # merged into the config anyways
115
- data = instance_variables_hash
116
- data.delete(:json)
117
- data.to_json
118
- end
119
- end
120
-
121
127
  class VagrantConfig < Base
122
128
  attr_accessor :dotfile_name
123
129
  attr_accessor :log_output
124
130
  attr_accessor :home
125
131
 
126
132
  def home
127
- File.expand_path(@home)
133
+ @home ? File.expand_path(@home) : nil
128
134
  end
129
135
  end
130
136
 
131
137
  class Top < Base
132
- attr_reader :package
133
- attr_reader :ssh
134
- attr_reader :vm
135
- attr_reader :chef
136
- attr_reader :vagrant
138
+ @@configures = []
139
+
140
+ class <<self
141
+ def configures_list
142
+ @@configures ||= []
143
+ end
144
+
145
+ def configures(key, klass)
146
+ configures_list << [key, klass]
147
+ attr_reader key.to_sym
148
+ end
149
+ end
150
+
151
+ # Setup default configures
152
+ configures :package, PackageConfig
153
+ configures :ssh, SSHConfig
154
+ configures :vm, VMConfig
155
+ configures :vagrant, VagrantConfig
137
156
 
138
157
  def initialize
139
- @ssh = SSHConfig.new
140
- @vm = VMConfig.new
141
- @chef = ChefConfig.new
142
- @vagrant = VagrantConfig.new
143
- @package = PackageConfig.new
158
+ self.class.configures_list.each do |key, klass|
159
+ instance_variable_set("@#{key}".to_sym, klass.new)
160
+ end
144
161
 
145
162
  @loaded = false
146
163
  end
@@ -3,19 +3,9 @@ module Vagrant
3
3
  # "Downloads" a file to a temporary file. Basically, this downloader
4
4
  # simply does a file copy.
5
5
  class File < Base
6
- BUFFERSIZE = 1048576 # 1 MB
7
-
8
6
  def download!(source_url, destination_file)
9
- # For now we read the contents of one into a buffer
10
- # and copy it into the other. In the future, we should do
11
- # a system-level file copy (FileUtils.cp).
12
- open(source_url) do |f|
13
- loop do
14
- break if f.eof?
15
- destination_file.write(f.read(BUFFERSIZE))
16
- end
17
- end
7
+ FileUtils.cp(source_url, destination_file.path)
18
8
  end
19
9
  end
20
10
  end
21
- end
11
+ end
data/lib/vagrant/env.rb CHANGED
@@ -24,21 +24,52 @@ module Vagrant
24
24
  load_config!
25
25
  load_home_directory!
26
26
  load_box!
27
+ load_config!
28
+ check_virtualbox!
27
29
  load_vm!
28
30
  end
29
31
 
32
+ def check_virtualbox!
33
+ version = VirtualBox::Command.version
34
+ if version.nil?
35
+ error_and_exit(<<-msg)
36
+ Vagrant could not detect VirtualBox! Make sure VirtualBox is properly installed.
37
+ If VirtualBox is installed, you may need to tweak the paths to the `VBoxManage`
38
+ application which ships with VirtualBox and the path to the global XML configuration
39
+ which VirtualBox typically stores somewhere in your home directory.
40
+
41
+ The following shows how to configure VirtualBox. This can be done in the
42
+ Vagrantfile. Note that 90% of the time, you shouldn't need to do this if VirtualBox
43
+ is installed. Please use the various Vagrant support lines to request more information
44
+ if you can't get this working.
45
+
46
+ VirtualBox::Command.vboxmanage = "/path/to/my/VBoxManage"
47
+ VirtualBox::Global.vboxconfig = "~/path/to/VirtualBox.xml"
48
+ msg
49
+ elsif version.to_f < 3.1
50
+ error_and_exit(<<-msg)
51
+ Vagrant has detected that you have VirtualBox version #{version} installed!
52
+ Vagrant requires that you use at least VirtualBox version 3.1. Please install
53
+ a more recent version of VirtualBox to continue.
54
+ msg
55
+ end
56
+ end
57
+
30
58
  def load_config!
31
59
  # Prepare load paths for config files
32
60
  load_paths = [File.join(PROJECT_ROOT, "config", "default.rb")]
33
61
  load_paths << File.join(box.directory, ROOTFILE_NAME) if box
62
+ load_paths << File.join(home_path, ROOTFILE_NAME) if Vagrant.config.vagrant.home
34
63
  load_paths << File.join(root_path, ROOTFILE_NAME) if root_path
35
64
 
36
65
  # Then clear out the old data
37
66
  Config.reset!
38
67
 
39
68
  load_paths.each do |path|
40
- logger.info "Loading config from #{path}..."
41
- load path if File.exist?(path)
69
+ if File.exist?(path)
70
+ logger.info "Loading config from #{path}..."
71
+ load path
72
+ end
42
73
  end
43
74
 
44
75
  # Execute the configurations
@@ -63,11 +94,6 @@ module Vagrant
63
94
  return unless root_path
64
95
 
65
96
  @@box = Box.find(Vagrant.config.vm.box) if Vagrant.config.vm.box
66
-
67
- if @@box
68
- logger.info("Reloading configuration to account for loaded box...")
69
- load_config!
70
- end
71
97
  end
72
98
 
73
99
  def load_vm!
@@ -81,18 +107,28 @@ module Vagrant
81
107
  end
82
108
 
83
109
  def persist_vm(vm)
110
+ # Save to the dotfile for this project
84
111
  File.open(dotfile_path, 'w+') do |f|
85
112
  f.write(vm.uuid)
86
113
  end
114
+
115
+ # Also add to the global store
116
+ ActiveList.add(vm)
117
+ end
118
+
119
+ def depersist_vm(vm)
120
+ # Delete the dotfile if it exists
121
+ File.delete(dotfile_path) if File.exist?(dotfile_path)
122
+
123
+ # Remove from the global store
124
+ ActiveList.remove(vm)
87
125
  end
88
126
 
89
127
  def load_root_path!(path=nil)
90
- path ||= Pathname.new(Dir.pwd)
128
+ path = Pathname.new(File.expand_path(path || Dir.pwd))
91
129
 
92
- # Stop if we're at the root. 2nd regex matches windows drives
93
- # such as C:. and Z:. Portability of this check will need to be
94
- # researched.
95
- return false if path.to_s == '/' || path.to_s =~ /^[A-Z]:\.$/
130
+ # Stop if we're at the root.
131
+ return false if path.root?
96
132
 
97
133
  file = "#{path}/#{ROOTFILE_NAME}"
98
134
  if File.exist?(file)
@@ -0,0 +1,22 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ # The base class for a "provisioner." A provisioner is responsible for
4
+ # provisioning a Vagrant system. This has been abstracted out to provide
5
+ # support for multiple solutions such as Chef Solo, Chef Client, and
6
+ # Puppet.
7
+ class Base
8
+ include Vagrant::Util
9
+
10
+ # This is the method called to "prepare" the provisioner. This is called
11
+ # before any actions are run by the action runner (see {Vagrant::Actions::Runner}).
12
+ # This can be used to setup shared folders, forward ports, etc. Whatever is
13
+ # necessary on a "meta" level.
14
+ def prepare; end
15
+
16
+ # This is the method called to provision the system. This method
17
+ # is expected to do whatever necessary to provision the system (create files,
18
+ # SSH, etc.)
19
+ def provision!; end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,102 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ # This class is a base class where the common functinality shared between
4
+ # chef-solo and chef-client provisioning are stored. This is **not an actual
5
+ # provisioner**. Instead, {ChefSolo} or {ChefServer} should be used.
6
+ class Chef < Base
7
+ # This is the configuration which is available through `config.chef`
8
+ class ChefConfig < Vagrant::Config::Base
9
+ # Chef server specific config
10
+ attr_accessor :chef_server_url
11
+ attr_accessor :validation_key_path
12
+ attr_accessor :validation_client_name
13
+ attr_accessor :client_key_path
14
+
15
+ # Chef solo specific config
16
+ attr_accessor :cookbooks_path
17
+
18
+ # Shared config
19
+ attr_accessor :provisioning_path
20
+ attr_accessor :json
21
+
22
+ def initialize
23
+ @validation_client_name = "chef-validator"
24
+ @client_key_path = "/etc/chef/client.pem"
25
+
26
+ @cookbooks_path = "cookbooks"
27
+ @provisioning_path = "/tmp/vagrant-chef"
28
+ @json = {
29
+ :instance_role => "vagrant",
30
+ :run_list => ["recipe[vagrant_main]"]
31
+ }
32
+ end
33
+
34
+ # Returns the run list for the provisioning
35
+ def run_list
36
+ json[:run_list]
37
+ end
38
+
39
+ # Sets the run list to the specified value
40
+ def run_list=(value)
41
+ json[:run_list] = value
42
+ end
43
+
44
+ # Adds a recipe to the run list
45
+ def add_recipe(name)
46
+ name = "recipe[#{name}]" unless name =~ /^recipe\[(.+?)\]$/
47
+ run_list << name
48
+ end
49
+
50
+ # Adds a role to the run list
51
+ def add_role(name)
52
+ name = "role[#{name}]" unless name =~ /^role\[(.+?)\]$/
53
+ run_list << name
54
+ end
55
+
56
+ def to_json
57
+ # Overridden so that the 'json' key could be removed, since its just
58
+ # merged into the config anyways
59
+ data = instance_variables_hash
60
+ data.delete(:json)
61
+ data.to_json
62
+ end
63
+ end
64
+
65
+ # Tell the Vagrant configure class about our custom configuration
66
+ Config.configures :chef, ChefConfig
67
+
68
+ def prepare
69
+ raise Actions::ActionException.new("Vagrant::Provisioners::Chef is not a valid provisioner! Use ChefSolo or ChefServer instead.")
70
+ end
71
+
72
+ def chown_provisioning_folder
73
+ logger.info "Setting permissions on chef provisioning folder..."
74
+ SSH.execute do |ssh|
75
+ ssh.exec!("sudo mkdir -p #{Vagrant.config.chef.provisioning_path}")
76
+ ssh.exec!("sudo chown #{Vagrant.config.ssh.username} #{Vagrant.config.chef.provisioning_path}")
77
+ end
78
+ end
79
+
80
+ def setup_json
81
+ logger.info "Generating chef JSON and uploading..."
82
+
83
+ # Set up initial configuration
84
+ data = {
85
+ :config => Vagrant.config,
86
+ :directory => Vagrant.config.vm.project_directory,
87
+ }
88
+
89
+ # And wrap it under the "vagrant" namespace
90
+ data = { :vagrant => data }
91
+
92
+ # Merge with the "extra data" which isn't put under the
93
+ # vagrant namespace by default
94
+ data.merge!(Vagrant.config.chef.json)
95
+
96
+ json = data.to_json
97
+
98
+ SSH.upload!(StringIO.new(json), File.join(Vagrant.config.chef.provisioning_path, "dna.json"))
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,96 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ # This class implements provisioning via chef-client, allowing provisioning
4
+ # with a chef server.
5
+ class ChefServer < Chef
6
+ def prepare
7
+ if Vagrant.config.chef.validation_key_path.nil?
8
+ raise Actions::ActionException.new(<<-msg)
9
+ Chef server provisioning requires that the `config.chef.validation_key_path` configuration
10
+ be set to a path on your local machine of the validation key used to register the
11
+ VM with the chef server.
12
+ msg
13
+ elsif !File.file?(Vagrant.config.chef.validation_key_path)
14
+ raise Actions::ActionException.new(<<-msg)
15
+ The validation key set for `config.chef.validation_key_path` does not exist! This
16
+ file needs to exist so it can be uploaded to the virtual machine. It is
17
+ currently set to "#{Vagrant.config.chef.validation_key_path}"
18
+ msg
19
+ end
20
+
21
+ if Vagrant.config.chef.chef_server_url.nil?
22
+ raise Actions::ActionException.new(<<-msg)
23
+ Chef server provisioning requires that the `config.chef.chef_server_url` be set to the
24
+ URL of your chef server. Examples include "http://12.12.12.12:4000" and
25
+ "http://myserver.com:4000" (the port of course can be different, but 4000 is the default)
26
+ msg
27
+ end
28
+ end
29
+
30
+ def provision!
31
+ chown_provisioning_folder
32
+ create_client_key_folder
33
+ upload_validation_key
34
+ setup_json
35
+ setup_config
36
+ run_chef_client
37
+ end
38
+
39
+ def create_client_key_folder
40
+ logger.info "Creating folder to hold client key..."
41
+ path = Pathname.new(Vagrant.config.chef.client_key_path)
42
+
43
+ SSH.execute do |ssh|
44
+ ssh.exec!("sudo mkdir -p #{path.dirname}")
45
+ end
46
+ end
47
+
48
+ def upload_validation_key
49
+ logger.info "Uploading chef client validation key..."
50
+ SSH.upload!(validation_key_path, guest_validation_key_path)
51
+ end
52
+
53
+ def setup_config
54
+ solo_file = <<-solo
55
+ log_level :info
56
+ log_location STDOUT
57
+ ssl_verify_mode :verify_none
58
+ chef_server_url "#{Vagrant.config.chef.chef_server_url}"
59
+
60
+ validation_client_name "#{Vagrant.config.chef.validation_client_name}"
61
+ validation_key "#{guest_validation_key_path}"
62
+ client_key "#{Vagrant.config.chef.client_key_path}"
63
+
64
+ file_store_path "/srv/chef/file_store"
65
+ file_cache_path "/srv/chef/cache"
66
+
67
+ pid_file "/var/run/chef/chef-client.pid"
68
+
69
+ Mixlib::Log::Formatter.show_time = true
70
+ solo
71
+
72
+ logger.info "Uploading chef-client configuration script..."
73
+ SSH.upload!(StringIO.new(solo_file), File.join(Vagrant.config.chef.provisioning_path, "client.rb"))
74
+ end
75
+
76
+ def run_chef_client
77
+ logger.info "Running chef-client..."
78
+ SSH.execute do |ssh|
79
+ ssh.exec!("cd #{Vagrant.config.chef.provisioning_path} && sudo chef-client -c client.rb -j dna.json") do |channel, data, stream|
80
+ # TODO: Very verbose. It would be easier to save the data and only show it during
81
+ # an error, or when verbosity level is set high
82
+ logger.info("#{stream}: #{data}")
83
+ end
84
+ end
85
+ end
86
+
87
+ def validation_key_path
88
+ File.expand_path(Vagrant.config.chef.validation_key_path, Env.root_path)
89
+ end
90
+
91
+ def guest_validation_key_path
92
+ File.join(Vagrant.config.chef.provisioning_path, "validation.pem")
93
+ end
94
+ end
95
+ end
96
+ end