Remove all "chef" configuration and moved chef solo provisioning to its own class
This commit is contained in:
parent
6878a3ea4d
commit
d81e5dc28d
|
@ -20,10 +20,9 @@ Vagrant::Config.run do |config|
|
|||
config.package.name = 'vagrant'
|
||||
config.package.extension = '.box'
|
||||
|
||||
config.chef.enabled = false
|
||||
config.chef.cookbooks_path = "cookbooks"
|
||||
config.chef.provisioning_path = "/tmp/vagrant-chef"
|
||||
config.chef.json = {
|
||||
config.chef_solo.cookbooks_path = "cookbooks"
|
||||
config.chef_solo.provisioning_path = "/tmp/vagrant-chef"
|
||||
config.chef_solo.json = {
|
||||
:instance_role => "vagrant",
|
||||
:recipes => ["vagrant_main"]
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
|
|||
# The libs which must be loaded prior to the rest
|
||||
%w{tempfile open-uri json pathname logger uri net/http virtualbox net/ssh archive/tar/minitar
|
||||
net/scp fileutils vagrant/util vagrant/actions/base vagrant/downloaders/base vagrant/actions/runner
|
||||
vagrant/provisioners/base}.each do |f|
|
||||
vagrant/config vagrant/provisioners/base}.each do |f|
|
||||
require f
|
||||
end
|
||||
|
||||
|
|
|
@ -2,69 +2,6 @@ module Vagrant
|
|||
module Actions
|
||||
module VM
|
||||
class Provision < Base
|
||||
def prepare
|
||||
Vagrant.config.vm.share_folder("vagrant-provisioning", cookbooks_path, File.expand_path(Vagrant.config.chef.cookbooks_path, Env.root_path))
|
||||
end
|
||||
|
||||
def execute!
|
||||
chown_provisioning_folder
|
||||
setup_json
|
||||
setup_solo_config
|
||||
run_chef_solo
|
||||
end
|
||||
|
||||
def chown_provisioning_folder
|
||||
logger.info "Setting permissions on provisioning folder..."
|
||||
SSH.execute do |ssh|
|
||||
ssh.exec!("sudo chown #{Vagrant.config.ssh.username} #{Vagrant.config.chef.provisioning_path}")
|
||||
end
|
||||
end
|
||||
|
||||
def setup_json
|
||||
logger.info "Generating JSON and uploading..."
|
||||
|
||||
# Set up initial configuration
|
||||
data = {
|
||||
:config => Vagrant.config,
|
||||
:directory => Vagrant.config.vm.project_directory,
|
||||
}
|
||||
|
||||
# And wrap it under the "vagrant" namespace
|
||||
data = { :vagrant => data }
|
||||
|
||||
# Merge with the "extra data" which isn't put under the
|
||||
# vagrant namespace by default
|
||||
data.merge!(Vagrant.config.chef.json)
|
||||
|
||||
json = data.to_json
|
||||
|
||||
SSH.upload!(StringIO.new(json), File.join(Vagrant.config.chef.provisioning_path, "dna.json"))
|
||||
end
|
||||
|
||||
def setup_solo_config
|
||||
solo_file = <<-solo
|
||||
file_cache_path "#{Vagrant.config.chef.provisioning_path}"
|
||||
cookbook_path "#{cookbooks_path}"
|
||||
solo
|
||||
|
||||
logger.info "Uploading chef-solo configuration script..."
|
||||
SSH.upload!(StringIO.new(solo_file), File.join(Vagrant.config.chef.provisioning_path, "solo.rb"))
|
||||
end
|
||||
|
||||
def run_chef_solo
|
||||
logger.info "Running chef recipes..."
|
||||
SSH.execute do |ssh|
|
||||
ssh.exec!("cd #{Vagrant.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
|
||||
# TODO: Very verbose. It would be easier to save the data and only show it during
|
||||
# an error, or when verbosity level is set high
|
||||
logger.info("#{stream}: #{data}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cookbooks_path
|
||||
File.join(Vagrant.config.chef.provisioning_path, "cookbooks")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ module Vagrant
|
|||
def prepare
|
||||
steps = [ForwardPorts, SharedFolders, Boot]
|
||||
steps.unshift(Halt) if @runner.vm.running?
|
||||
steps << Provision if Vagrant.config.chef.enabled
|
||||
steps << Provision if !Vagrant.config.vm.provisioner.nil?
|
||||
|
||||
steps.each do |action_klass|
|
||||
@runner.add_action(action_klass)
|
||||
|
|
|
@ -17,7 +17,7 @@ msg
|
|||
# Up is a "meta-action" so it really just queues up a bunch
|
||||
# of other actions in its place:
|
||||
steps = [Import, ForwardPorts, SharedFolders, Boot]
|
||||
steps << Provision if Vagrant.config.chef.enabled
|
||||
steps << Provision if !Vagrant.config.vm.provisioner.nil?
|
||||
steps.insert(0, MoveHardDrive) if Vagrant.config.vm.hd_location
|
||||
|
||||
steps.each do |action_klass|
|
||||
|
|
|
@ -14,7 +14,7 @@ module Vagrant
|
|||
end
|
||||
|
||||
def configures(key, klass)
|
||||
@@config.class.configures(key, klass)
|
||||
config.class.configures(key, klass)
|
||||
end
|
||||
|
||||
def config
|
||||
|
@ -75,11 +75,12 @@ module Vagrant
|
|||
attr_reader :shared_folders
|
||||
attr_accessor :hd_location
|
||||
attr_accessor :disk_image_format
|
||||
|
||||
attr_accessor :provisioner
|
||||
|
||||
def initialize
|
||||
@forwarded_ports = {}
|
||||
@shared_folders = {}
|
||||
@provisioner = nil
|
||||
end
|
||||
|
||||
def forward_port(name, guestport, hostport, protocol="TCP")
|
||||
|
@ -112,25 +113,6 @@ module Vagrant
|
|||
attr_accessor :extension
|
||||
end
|
||||
|
||||
class ChefConfig < Base
|
||||
attr_accessor :cookbooks_path
|
||||
attr_accessor :provisioning_path
|
||||
attr_accessor :json
|
||||
attr_accessor :enabled
|
||||
|
||||
def initialize
|
||||
@enabled = false
|
||||
end
|
||||
|
||||
def to_json
|
||||
# Overridden so that the 'json' key could be removed, since its just
|
||||
# merged into the config anyways
|
||||
data = instance_variables_hash
|
||||
data.delete(:json)
|
||||
data.to_json
|
||||
end
|
||||
end
|
||||
|
||||
class VagrantConfig < Base
|
||||
attr_accessor :dotfile_name
|
||||
attr_accessor :log_output
|
||||
|
@ -159,7 +141,6 @@ module Vagrant
|
|||
configures :package, PackageConfig
|
||||
configures :ssh, SSHConfig
|
||||
configures :vm, VMConfig
|
||||
configures :chef, ChefConfig
|
||||
configures :vagrant, VagrantConfig
|
||||
|
||||
def initialize
|
||||
|
|
|
@ -7,7 +7,13 @@ module Vagrant
|
|||
class Base
|
||||
include Vagrant::Util
|
||||
|
||||
# This is the single method called to provision the system. This method
|
||||
# This is the method called to "prepare" the provisioner. This is called
|
||||
# before any actions are run by the action runner (see {Vagrant::Actions::Runner}).
|
||||
# This can be used to setup shared folders, forward ports, etc. Whatever is
|
||||
# necessary on a "meta" level.
|
||||
def prepare; end
|
||||
|
||||
# This is the method called to provision the system. This method
|
||||
# is expected to do whatever necessary to provision the system (create files,
|
||||
# SSH, etc.)
|
||||
def provision!; end
|
||||
|
|
|
@ -2,6 +2,87 @@ module Vagrant
|
|||
module Provisioners
|
||||
# This class implements provisioning via chef-solo.
|
||||
class ChefSolo < Base
|
||||
# This is the configuration which is available through `config.chef_solo`
|
||||
class CustomConfig < Vagrant::Config::Base
|
||||
attr_accessor :cookbooks_path
|
||||
attr_accessor :provisioning_path
|
||||
attr_accessor :json
|
||||
|
||||
def to_json
|
||||
# Overridden so that the 'json' key could be removed, since its just
|
||||
# merged into the config anyways
|
||||
data = instance_variables_hash
|
||||
data.delete(:json)
|
||||
data.to_json
|
||||
end
|
||||
end
|
||||
|
||||
# Tell the Vagrant configure class about our custom configuration
|
||||
Config.configures :chef_solo, CustomConfig
|
||||
|
||||
def prepare
|
||||
Vagrant.config.vm.share_folder("vagrant-chef-solo", cookbooks_path, File.expand_path(Vagrant.config.chef_solo.cookbooks_path, Env.root_path))
|
||||
end
|
||||
|
||||
def provision!
|
||||
chown_provisioning_folder
|
||||
setup_json
|
||||
setup_solo_config
|
||||
run_chef_solo
|
||||
end
|
||||
|
||||
def chown_provisioning_folder
|
||||
logger.info "Setting permissions on chef solo provisioning folder..."
|
||||
SSH.execute do |ssh|
|
||||
ssh.exec!("sudo chown #{Vagrant.config.ssh.username} #{Vagrant.config.chef_solo.provisioning_path}")
|
||||
end
|
||||
end
|
||||
|
||||
def setup_json
|
||||
logger.info "Generating chef solo JSON and uploading..."
|
||||
|
||||
# Set up initial configuration
|
||||
data = {
|
||||
:config => Vagrant.config,
|
||||
:directory => Vagrant.config.vm.project_directory,
|
||||
}
|
||||
|
||||
# And wrap it under the "vagrant" namespace
|
||||
data = { :vagrant => data }
|
||||
|
||||
# Merge with the "extra data" which isn't put under the
|
||||
# vagrant namespace by default
|
||||
data.merge!(Vagrant.config.chef_solo.json)
|
||||
|
||||
json = data.to_json
|
||||
|
||||
SSH.upload!(StringIO.new(json), File.join(Vagrant.config.chef_solo.provisioning_path, "dna.json"))
|
||||
end
|
||||
|
||||
def setup_solo_config
|
||||
solo_file = <<-solo
|
||||
file_cache_path "#{Vagrant.config.chef_solo.provisioning_path}"
|
||||
cookbook_path "#{cookbooks_path}"
|
||||
solo
|
||||
|
||||
logger.info "Uploading chef-solo configuration script..."
|
||||
SSH.upload!(StringIO.new(solo_file), File.join(Vagrant.config.chef_solo.provisioning_path, "solo.rb"))
|
||||
end
|
||||
|
||||
def run_chef_solo
|
||||
logger.info "Running chef-solo..."
|
||||
SSH.execute do |ssh|
|
||||
ssh.exec!("cd #{Vagrant.config.chef_solo.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
|
||||
# TODO: Very verbose. It would be easier to save the data and only show it during
|
||||
# an error, or when verbosity level is set high
|
||||
logger.info("#{stream}: #{data}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def cookbooks_path
|
||||
File.join(Vagrant.config.chef_solo.provisioning_path, "cookbooks")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -42,9 +42,10 @@ class Test::Unit::TestCase
|
|||
config.package.name = 'vagrant'
|
||||
config.package.extension = '.box'
|
||||
|
||||
config.chef.cookbooks_path = "cookbooks"
|
||||
config.chef.provisioning_path = "/tmp/hobo-chef"
|
||||
config.chef.json = {
|
||||
# Chef solo
|
||||
config.chef_solo.cookbooks_path = "cookbooks"
|
||||
config.chef_solo.provisioning_path = "/tmp/hobo-chef"
|
||||
config.chef_solo.json = {
|
||||
:recipes => ["hobo_main"]
|
||||
}
|
||||
|
||||
|
|
|
@ -2,103 +2,7 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
|
|||
|
||||
class ProvisionActionTest < Test::Unit::TestCase
|
||||
setup do
|
||||
@mock_vm, @vm, @action = mock_action(Vagrant::Actions::VM::Provision)
|
||||
|
||||
Vagrant::SSH.stubs(:execute)
|
||||
Vagrant::SSH.stubs(:upload!)
|
||||
|
||||
@runner, @vm, @action = mock_action(Vagrant::Actions::VM::Provision)
|
||||
mock_config
|
||||
end
|
||||
|
||||
context "shared folders" do
|
||||
should "setup shared folder on VM for the cookbooks" do
|
||||
File.expects(:expand_path).with(Vagrant.config.chef.cookbooks_path, Vagrant::Env.root_path).returns("foo")
|
||||
@action.expects(:cookbooks_path).returns("bar")
|
||||
Vagrant.config.vm.expects(:share_folder).with("vagrant-provisioning", "bar", "foo").once
|
||||
@action.prepare
|
||||
end
|
||||
end
|
||||
|
||||
context "cookbooks path" do
|
||||
should "return the proper cookbook path" do
|
||||
cookbooks_path = File.join(Vagrant.config.chef.provisioning_path, "cookbooks")
|
||||
assert_equal cookbooks_path, @action.cookbooks_path
|
||||
end
|
||||
end
|
||||
|
||||
context "permissions on provisioning folder" do
|
||||
should "chown the folder to the ssh user" do
|
||||
ssh = mock("ssh")
|
||||
ssh.expects(:exec!).with("sudo chown #{Vagrant.config.ssh.username} #{Vagrant.config.chef.provisioning_path}")
|
||||
Vagrant::SSH.expects(:execute).yields(ssh)
|
||||
@action.chown_provisioning_folder
|
||||
end
|
||||
end
|
||||
|
||||
context "generating and uploading json" do
|
||||
def assert_json
|
||||
Vagrant::SSH.expects(:upload!).with do |json, path|
|
||||
data = JSON.parse(json.read)
|
||||
yield data
|
||||
true
|
||||
end
|
||||
|
||||
@action.setup_json
|
||||
end
|
||||
|
||||
should "merge in the extra json specified in the config" do
|
||||
Vagrant.config.chef.json = { :foo => "BAR" }
|
||||
assert_json do |data|
|
||||
assert_equal "BAR", data["foo"]
|
||||
end
|
||||
end
|
||||
|
||||
should "add the directory as a special case to the JSON" do
|
||||
assert_json do |data|
|
||||
assert_equal Vagrant.config.vm.project_directory, data["vagrant"]["directory"]
|
||||
end
|
||||
end
|
||||
|
||||
should "add the config to the JSON" do
|
||||
assert_json do |data|
|
||||
assert_equal Vagrant.config.vm.project_directory, data["vagrant"]["config"]["vm"]["project_directory"]
|
||||
end
|
||||
end
|
||||
|
||||
should "upload a StringIO to dna.json" do
|
||||
StringIO.expects(:new).with(anything).returns("bar")
|
||||
File.expects(:join).with(Vagrant.config.chef.provisioning_path, "dna.json").once.returns("baz")
|
||||
Vagrant::SSH.expects(:upload!).with("bar", "baz").once
|
||||
@action.setup_json
|
||||
end
|
||||
end
|
||||
|
||||
context "generating and uploading chef solo configuration file" do
|
||||
should "upload properly generate the configuration file using configuration data" do
|
||||
expected_config = <<-config
|
||||
file_cache_path "#{Vagrant.config.chef.provisioning_path}"
|
||||
cookbook_path "#{@action.cookbooks_path}"
|
||||
config
|
||||
|
||||
StringIO.expects(:new).with(expected_config).once
|
||||
@action.setup_solo_config
|
||||
end
|
||||
|
||||
should "upload this file as solo.rb to the provisioning folder" do
|
||||
@action.expects(:cookbooks_path).returns("cookbooks")
|
||||
StringIO.expects(:new).returns("foo")
|
||||
File.expects(:join).with(Vagrant.config.chef.provisioning_path, "solo.rb").once.returns("bar")
|
||||
Vagrant::SSH.expects(:upload!).with("foo", "bar").once
|
||||
@action.setup_solo_config
|
||||
end
|
||||
end
|
||||
|
||||
context "running chef solo" do
|
||||
should "cd into the provisioning directory and run chef solo" do
|
||||
ssh = mock("ssh")
|
||||
ssh.expects(:exec!).with("cd #{Vagrant.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json").once
|
||||
Vagrant::SSH.expects(:execute).yields(ssh)
|
||||
@action.run_chef_solo
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,7 +33,8 @@ class ReloadActionTest < Test::Unit::TestCase
|
|||
|
||||
should "add in the provisioning step if enabled" do
|
||||
mock_config do |config|
|
||||
config.chef.enabled = true
|
||||
# Dummy provisioner to test
|
||||
config.vm.provisioner = "foo"
|
||||
end
|
||||
|
||||
@default_order.push(Vagrant::Actions::VM::Provision)
|
||||
|
|
|
@ -47,7 +47,7 @@ class UpActionTest < Test::Unit::TestCase
|
|||
|
||||
should "add in the provisioning step if enabled" do
|
||||
mock_config do |config|
|
||||
config.chef.enabled = true
|
||||
config.vm.provisioner = "foo"
|
||||
end
|
||||
|
||||
@default_order.push(Vagrant::Actions::VM::Provision)
|
||||
|
|
|
@ -117,18 +117,6 @@ class ConfigTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
context "chef config" do
|
||||
setup do
|
||||
@config = Vagrant::Config::ChefConfig.new
|
||||
@config.json = "HEY"
|
||||
end
|
||||
|
||||
should "not include the 'json' key in the config dump" do
|
||||
result = JSON.parse(@config.to_json)
|
||||
assert !result.has_key?("json")
|
||||
end
|
||||
end
|
||||
|
||||
context "top config class" do
|
||||
setup do
|
||||
@configures_list = []
|
||||
|
|
|
@ -16,5 +16,12 @@ class BaseProvisionerTest < Test::Unit::TestCase
|
|||
@base.provision!
|
||||
end
|
||||
end
|
||||
|
||||
should "implement prepare which does nothing" do
|
||||
assert_nothing_raised do
|
||||
assert @base.respond_to?(:prepare)
|
||||
@base.prepare
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
|
||||
|
||||
class ChefSoloProvisionerTest < Test::Unit::TestCase
|
||||
setup do
|
||||
@action = Vagrant::Provisioners::ChefSolo.new
|
||||
|
||||
Vagrant::SSH.stubs(:execute)
|
||||
Vagrant::SSH.stubs(:upload!)
|
||||
|
||||
mock_config
|
||||
end
|
||||
|
||||
context "config" do
|
||||
setup do
|
||||
@config = Vagrant::Provisioners::ChefSolo::CustomConfig.new
|
||||
@config.json = "HEY"
|
||||
end
|
||||
|
||||
should "not include the 'json' key in the config dump" do
|
||||
result = JSON.parse(@config.to_json)
|
||||
assert !result.has_key?("json")
|
||||
end
|
||||
end
|
||||
|
||||
context "shared folders" do
|
||||
should "setup shared folder on VM for the cookbooks" do
|
||||
File.expects(:expand_path).with(Vagrant.config.chef_solo.cookbooks_path, Vagrant::Env.root_path).returns("foo")
|
||||
@action.expects(:cookbooks_path).returns("bar")
|
||||
Vagrant.config.vm.expects(:share_folder).with("vagrant-chef-solo", "bar", "foo").once
|
||||
@action.prepare
|
||||
end
|
||||
end
|
||||
|
||||
context "cookbooks path" do
|
||||
should "return the proper cookbook path" do
|
||||
cookbooks_path = File.join(Vagrant.config.chef_solo.provisioning_path, "cookbooks")
|
||||
assert_equal cookbooks_path, @action.cookbooks_path
|
||||
end
|
||||
end
|
||||
|
||||
context "permissions on provisioning folder" do
|
||||
should "chown the folder to the ssh user" do
|
||||
ssh = mock("ssh")
|
||||
ssh.expects(:exec!).with("sudo chown #{Vagrant.config.ssh.username} #{Vagrant.config.chef_solo.provisioning_path}")
|
||||
Vagrant::SSH.expects(:execute).yields(ssh)
|
||||
@action.chown_provisioning_folder
|
||||
end
|
||||
end
|
||||
|
||||
context "generating and uploading json" do
|
||||
def assert_json
|
||||
Vagrant::SSH.expects(:upload!).with do |json, path|
|
||||
data = JSON.parse(json.read)
|
||||
yield data
|
||||
true
|
||||
end
|
||||
|
||||
@action.setup_json
|
||||
end
|
||||
|
||||
should "merge in the extra json specified in the config" do
|
||||
Vagrant.config.chef_solo.json = { :foo => "BAR" }
|
||||
assert_json do |data|
|
||||
assert_equal "BAR", data["foo"]
|
||||
end
|
||||
end
|
||||
|
||||
should "add the directory as a special case to the JSON" do
|
||||
assert_json do |data|
|
||||
assert_equal Vagrant.config.vm.project_directory, data["vagrant"]["directory"]
|
||||
end
|
||||
end
|
||||
|
||||
should "add the config to the JSON" do
|
||||
assert_json do |data|
|
||||
assert_equal Vagrant.config.vm.project_directory, data["vagrant"]["config"]["vm"]["project_directory"]
|
||||
end
|
||||
end
|
||||
|
||||
should "upload a StringIO to dna.json" do
|
||||
StringIO.expects(:new).with(anything).returns("bar")
|
||||
File.expects(:join).with(Vagrant.config.chef_solo.provisioning_path, "dna.json").once.returns("baz")
|
||||
Vagrant::SSH.expects(:upload!).with("bar", "baz").once
|
||||
@action.setup_json
|
||||
end
|
||||
end
|
||||
|
||||
context "generating and uploading chef solo configuration file" do
|
||||
should "upload properly generate the configuration file using configuration data" do
|
||||
expected_config = <<-config
|
||||
file_cache_path "#{Vagrant.config.chef_solo.provisioning_path}"
|
||||
cookbook_path "#{@action.cookbooks_path}"
|
||||
config
|
||||
|
||||
StringIO.expects(:new).with(expected_config).once
|
||||
@action.setup_solo_config
|
||||
end
|
||||
|
||||
should "upload this file as solo.rb to the provisioning folder" do
|
||||
@action.expects(:cookbooks_path).returns("cookbooks")
|
||||
StringIO.expects(:new).returns("foo")
|
||||
File.expects(:join).with(Vagrant.config.chef_solo.provisioning_path, "solo.rb").once.returns("bar")
|
||||
Vagrant::SSH.expects(:upload!).with("foo", "bar").once
|
||||
@action.setup_solo_config
|
||||
end
|
||||
end
|
||||
|
||||
context "running chef solo" do
|
||||
should "cd into the provisioning directory and run chef solo" do
|
||||
ssh = mock("ssh")
|
||||
ssh.expects(:exec!).with("cd #{Vagrant.config.chef_solo.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json").once
|
||||
Vagrant::SSH.expects(:execute).yields(ssh)
|
||||
@action.run_chef_solo
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue