From d951d058ce0b1571b62b33c854819804d58819e3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 11 Jan 2011 21:07:12 -0800 Subject: [PATCH] Initial work on this. Tests are completely broken. --- config/default.rb | 1 - lib/vagrant/config/vm.rb | 22 ++++++++---- lib/vagrant/config/vm/provisioner.rb | 44 +++++++++++++++++++++++ lib/vagrant/provisioners/chef.rb | 44 +---------------------- lib/vagrant/provisioners/chef_server.rb | 23 ++++++++++++ lib/vagrant/provisioners/chef_solo.rb | 20 +++++++++++ lib/vagrant/provisioners/puppet.rb | 2 +- lib/vagrant/provisioners/puppet_server.rb | 2 +- templates/locales/en.yml | 1 + 9 files changed, 107 insertions(+), 52 deletions(-) create mode 100644 lib/vagrant/config/vm/provisioner.rb diff --git a/config/default.rb b/config/default.rb index f313af3b8..4725d2b5e 100644 --- a/config/default.rb +++ b/config/default.rb @@ -19,7 +19,6 @@ Vagrant::Config.run do |config| config.vm.base_mac = nil config.vm.forward_port("ssh", 22, 2222, :auto => true) config.vm.disk_image_format = 'VMDK' - config.vm.provisioner = nil config.vm.shared_folder_uid = nil config.vm.shared_folder_gid = nil config.vm.boot_mode = "vrdp" diff --git a/lib/vagrant/config/vm.rb b/lib/vagrant/config/vm.rb index 0758867bd..552dcc4f8 100644 --- a/lib/vagrant/config/vm.rb +++ b/lib/vagrant/config/vm.rb @@ -1,4 +1,5 @@ require 'vagrant/config/vm/sub_vm' +require 'vagrant/config/vm/provisioner' module Vagrant class Config @@ -16,8 +17,8 @@ module Vagrant attr_reader :forwarded_ports attr_reader :shared_folders attr_reader :network_options + attr_reader :provisioners attr_accessor :disk_image_format - attr_accessor :provisioner attr_writer :shared_folder_uid attr_writer :shared_folder_gid attr_accessor :system @@ -25,8 +26,8 @@ module Vagrant def initialize @forwarded_ports = {} @shared_folders = {} - @provisioner = nil @network_options = [] + @provisioners = [] end def forward_port(name, guestport, hostport, options=nil) @@ -59,6 +60,10 @@ module Vagrant @network_options[options[:adapter]] = options end + def provisioner(name, options=nil, &block) + @provisioners << Provisioner.new(name, options, &block) + end + def shared_folder_uid @shared_folder_uid || env.config.ssh.username end @@ -100,6 +105,11 @@ module Vagrant end def validate(errors) + errors.add(I18n.t("vagrant.config.vm.box_missing")) if !box + errors.add(I18n.t("vagrant.config.vm.box_not_found", :name => box)) if box && !box_url && !env.box + errors.add(I18n.t("vagrant.config.vm.boot_mode_invalid")) if ![:vrdp, :gui].include?(boot_mode.to_sym) + errors.add(I18n.t("vagrant.config.vm.base_mac_invalid")) if env.box && !base_mac + shared_folders.each do |name, options| if !File.directory?(File.expand_path(options[:hostpath].to_s, env.root_path)) errors.add(I18n.t("vagrant.config.vm.shared_folder_hostpath_missing", @@ -108,10 +118,10 @@ module Vagrant end end - errors.add(I18n.t("vagrant.config.vm.box_missing")) if !box - errors.add(I18n.t("vagrant.config.vm.box_not_found", :name => box)) if box && !box_url && !env.box - errors.add(I18n.t("vagrant.config.vm.boot_mode_invalid")) if ![:vrdp, :gui].include?(boot_mode.to_sym) - errors.add(I18n.t("vagrant.config.vm.base_mac_invalid")) if env.box && !base_mac + # Each provisioner can validate itself + provisioners.each do |prov| + prov.validate(errors) + end end end end diff --git a/lib/vagrant/config/vm/provisioner.rb b/lib/vagrant/config/vm/provisioner.rb new file mode 100644 index 000000000..939100013 --- /dev/null +++ b/lib/vagrant/config/vm/provisioner.rb @@ -0,0 +1,44 @@ +module Vagrant + class Config + class VMConfig < Base + # Represents a single configured provisioner for a VM. + class Provisioner + attr_reader :shortcut + attr_reader :provisioner + attr_reader :config + + def initialize(shortcut, options=nil, &block) + @shortcut = shortcut + @provisioner = Provisioners::Base.registered[shortcut] + @config = nil + + configure(options, &block) + end + + # Configures the provisioner if it can (if it is valid). + def configure(options=nil, &block) + # We assume that every provisioner has a `Config` class beneath + # it for configuring. + return if !defined?(@provisioner::Config) + + # Instantiate the config class and configure it + @config = @provisioner::Config.new + block.call(@config) if block + + # TODO: Deal with the options hash + end + + def validate(errors) + if !provisioner + # If we don't have a provisioner then the whole thing is invalid. + errors.add(I18n.t("vagrant.config.vm.provisioner_not_found", :shortcut => shortcut)) + return + end + + # Pass on validation to the provisioner config + config.validate(errors) if config + end + end + end + end +end diff --git a/lib/vagrant/provisioners/chef.rb b/lib/vagrant/provisioners/chef.rb index c757b5de7..217e2c9d7 100644 --- a/lib/vagrant/provisioners/chef.rb +++ b/lib/vagrant/provisioners/chef.rb @@ -68,21 +68,7 @@ module Vagrant class Chef < Base # This is the configuration which is available through `config.chef` - class ChefConfig < Vagrant::Config::Base - configures :chef - - # Chef server specific config - attr_accessor :chef_server_url - attr_accessor :validation_key_path - attr_accessor :validation_client_name - attr_accessor :client_key_path - attr_accessor :node_name - - # Chef solo specific config - attr_accessor :cookbooks_path - attr_accessor :roles_path - attr_accessor :recipe_url - + class Config < Vagrant::Config::Base # Shared config attr_accessor :provisioning_path attr_accessor :log_level @@ -96,12 +82,6 @@ module Vagrant attr_accessor :no_proxy def initialize - @validation_client_name = "chef-validator" - @client_key_path = "/etc/chef/client.pem" - - @cookbooks_path = ["cookbooks", [:vm, "cookbooks"]] - @roles_path = [] - @provisioning_path = "/tmp/vagrant-chef" @log_level = :info @json = { :instance_role => "vagrant" } @@ -143,28 +123,6 @@ module Vagrant result.delete("json") result end - - def validate(errors) - if top.vm.provisioner == :chef_solo - # Validate chef solo settings - errors.add(I18n.t("vagrant.config.chef.cookbooks_path_empty")) if !cookbooks_path || [cookbooks_path].flatten.empty? - end - - if top.vm.provisioner == :chef_server - # Validate chef server settings - errors.add(I18n.t("vagrant.config.chef.server_url_empty")) if !chef_server_url || chef_server_url.strip == "" - errors.add(I18n.t("vagrant.config.chef.validation_key_path")) if !validation_key_path - end - - if top.vm.provisioner == :chef_solo - # On chef solo, a run list MUST be specified - errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if !json[:run_list] || run_list.empty? - elsif top.vm.provisioner == :chef_server - # On chef server, the run list is allowed to be nil, which causes it - # to sync with the chef server. - errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if json[:run_list] && run_list.empty? - end - end end end end diff --git a/lib/vagrant/provisioners/chef_server.rb b/lib/vagrant/provisioners/chef_server.rb index 3cc3f3d45..9361c5414 100644 --- a/lib/vagrant/provisioners/chef_server.rb +++ b/lib/vagrant/provisioners/chef_server.rb @@ -7,6 +7,29 @@ module Vagrant class ChefServer < Chef register :chef_server + class Config < Chef::Config + attr_accessor :chef_server_url + attr_accessor :validation_key_path + attr_accessor :validation_client_name + attr_accessor :client_key_path + attr_accessor :node_name + + def initialize + super + + @validation_client_name = "chef-validator" + @client_key_path = "/etc/chef/client.pem" + end + + def validate(errors) + super + + errors.add(I18n.t("vagrant.config.chef.server_url_empty")) if !chef_server_url || chef_server_url.strip == "" + errors.add(I18n.t("vagrant.config.chef.validation_key_path")) if !validation_key_path + errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if json[:run_list] && run_list.empty? + end + end + def prepare raise ChefError, :server_validation_key_required if env.config.chef.validation_key_path.nil? raise ChefError, :server_validation_key_doesnt_exist if !File.file?(validation_key_path) diff --git a/lib/vagrant/provisioners/chef_solo.rb b/lib/vagrant/provisioners/chef_solo.rb index d8fc67167..4284c42d1 100644 --- a/lib/vagrant/provisioners/chef_solo.rb +++ b/lib/vagrant/provisioners/chef_solo.rb @@ -4,6 +4,26 @@ module Vagrant class ChefSolo < Chef register :chef_solo + class Config < Chef::Config + attr_accessor :cookbooks_path + attr_accessor :roles_path + attr_accessor :recipe_url + + def initialize + super + + @cookbooks_path = ["cookbooks", [:vm, "cookbooks"]] + @roles_path = [] + end + + def validate(errors) + super + + errors.add(I18n.t("vagrant.config.chef.cookbooks_path_empty")) if !cookbooks_path || [cookbooks_path].flatten.empty? + errors.add(I18n.t("vagrant.config.chef.run_list_empty")) if !json[:run_list] || run_list.empty? + end + end + def prepare share_cookbook_folders share_role_folders diff --git a/lib/vagrant/provisioners/puppet.rb b/lib/vagrant/provisioners/puppet.rb index 2c01e4e24..cfcc0cb90 100644 --- a/lib/vagrant/provisioners/puppet.rb +++ b/lib/vagrant/provisioners/puppet.rb @@ -5,7 +5,7 @@ module Vagrant end class PuppetConfig < Vagrant::Config::Base - configures :puppet + # configures :puppet attr_accessor :manifest_file attr_accessor :manifests_path diff --git a/lib/vagrant/provisioners/puppet_server.rb b/lib/vagrant/provisioners/puppet_server.rb index 89decdd0c..a0b699768 100644 --- a/lib/vagrant/provisioners/puppet_server.rb +++ b/lib/vagrant/provisioners/puppet_server.rb @@ -5,7 +5,7 @@ module Vagrant end class PuppetServerConfig < Vagrant::Config::Base - configures :puppet_server + # configures :puppet_server attr_accessor :puppet_server attr_accessor :puppet_node diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 6c95489c6..b5f6d4d98 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -140,6 +140,7 @@ en: box_missing: "A box must be specified." box_not_found: "The box '%{name}' could not be found." shared_folder_hostpath_missing: "Shared folder host path for '%{name}' doesn't exist: %{path}" + provisioner_not_found: "The provisioner '%{shortcut}' doesn't exist." #------------------------------------------------------------------------------- # Translations for commands. e.g. `vagrant x`