Hobo::Config revamp

This commit is contained in:
Mitchell Hashimoto 2010-02-01 22:14:40 -08:00
parent 303cc90a12
commit c9d341ae2b
10 changed files with 175 additions and 151 deletions

13
config/default.rb Normal file
View File

@ -0,0 +1,13 @@
Hobo::Config.run do |config|
# default config goes here
config.ssh.uname = "hobo"
config.ssh.pass = "hobo"
config.ssh.host = "localhost"
config.ssh.port = 2222
config.ssh.max_tries = 10
config.dotfile_name = ".hobo"
config.vm.base = "~/.hobo/base/base.ovf"
config.vm.base_mac = "0800279C2E41"
end

View File

@ -1,12 +0,0 @@
:ssh:
:uname: hobo
:pass: hobo
:host: localhost
:port: 2222
:max_tries: 10
:dotfile_name: .hobo
:vm:
:base: ~/.hobo/base/base.ovf
:base_mac: 0800279C2E41

View File

@ -1,29 +1,64 @@
require 'forwardable'
module Hobo module Hobo
module_function def self.config
Config.config
end
class Config
@config = nil
@config_runners = []
class <<self
def config def config
@@config @config ||= Config::Top.new
end end
def config!(hash) def config_runners
@@config = hash @config_runners ||= []
end end
def set_config_value(chain, val, cfg=@@config) def run(&block)
keys = chain.split('.') config_runners << block
return if keys.empty?
if keys.length == 1
# If we're out of keys and the value for this key is not a leaf blow up
raise InvalidSettingAlteration if cfg[keys.first.to_sym].is_a?(Hash)
# set the value and return if the value is a leaf
return cfg[keys.first.to_sym] = val
end end
set_config_value(keys[1..-1].join('.'), val, cfg[keys.first.to_sym]) def execute!
config_runners.each do |block|
block.call(config)
end
end
end
end end
class InvalidSettingAlteration < StandardError; end class Config
class Base
def [](key)
send(key)
end
end
class SSHConfig < Base
attr_accessor :uname
attr_accessor :pass
attr_accessor :host
attr_accessor :port
attr_accessor :max_tries
end
class VMConfig < Base
attr_accessor :base
attr_accessor :base_mac
end
class Top < Base
attr_accessor :dotfile_name
attr_reader :ssh
attr_reader :vm
def initialize
@ssh = SSHConfig.new
@vm = VMConfig.new
end
end
end
end end

View File

@ -2,13 +2,7 @@ require 'yaml'
module Hobo module Hobo
class Env class Env
HOBOFILE_NAME = "hobofile" HOBOFILE_NAME = "Hobofile"
HOME = File.expand_path('~/.hobo')
CONFIG = { File.join(HOME, 'config.yml') => '/config/default.yml' }
ENSURE = {
:files => CONFIG.merge({}), #additional files go mhia!
:dirs => [HOME] #additional dirs go mhia!
}
# Initialize class variables used # Initialize class variables used
@@persisted_vm = nil @@persisted_vm = nil
@ -17,7 +11,7 @@ module Hobo
class << self class << self
def persisted_vm; @@persisted_vm; end def persisted_vm; @@persisted_vm; end
def root_path; @@root_path; end def root_path; @@root_path; end
def dotfile_path; File.join(root_path, Hobo.config[:dotfile_name]); end def dotfile_path; File.join(root_path, Hobo.config.dotfile_name); end
def load! def load!
load_root_path! load_root_path!
@ -25,25 +19,19 @@ module Hobo
load_vm! load_vm!
end end
def ensure_directories
ENSURE[:dirs].each do |name|
Dir.mkdir(name) unless File.exists?(name)
end
end
def ensure_files
ENSURE[:files].each do |target, default|
File.copy(File.join(PROJECT_ROOT, default), target) unless File.exists?(target)
end
end
def load_config! def load_config!
ensure_directories load_paths = [
ensure_files File.join(PROJECT_ROOT, "config", "default.rb"),
File.join(root_path, HOBOFILE_NAME)
]
HOBO_LOGGER.info "Loading config from #{CONFIG.keys.first}" load_paths.each do |path|
parsed = YAML.load_file(CONFIG.keys.first) HOBO_LOGGER.info "Loading config from #{path}..."
Hobo.config!(parsed) load path if File.exist?(path)
end
# Execute the configurations
Config.execute!
end end
def load_vm! def load_vm!

View File

@ -6,7 +6,7 @@ module Hobo
def connect(opts={}) def connect(opts={})
options = {} options = {}
[:port, :host, :pass, :uname].each do |param| [:port, :host, :pass, :uname].each do |param|
options[param] = opts[param] || Hobo.config[:ssh][param] options[param] = opts[param] || Hobo.config.ssh.send(param)
end end
Kernel.exec "#{SCRIPT} #{options[:uname]} #{options[:pass]} #{options[:host]} #{options[:port]}".strip Kernel.exec "#{SCRIPT} #{options[:uname]} #{options[:pass]} #{options[:host]} #{options[:port]}".strip

View File

@ -1,27 +1,46 @@
require File.join(File.dirname(__FILE__), '..', 'test_helper') require File.join(File.dirname(__FILE__), '..', 'test_helper')
class ConfigTest < Test::Unit::TestCase class ConfigTest < Test::Unit::TestCase
context "Hobo configuration" do context "accessing configuration" do
setup do setup do
@settings = {:a => { :b => 1}} Hobo::Config.run { |config| }
Hobo.config!(@settings) Hobo::Config.execute!
end end
should "alter the config given a dot chain of keys" do should "forward config to the class method" do
Hobo.set_config_value 'a.b', 2 assert_equal Hobo.config, Hobo::Config.config
assert_equal Hobo.config[:a][:b], 2
end
should "prevent the alteration of a non leaf setting value" do
assert_raise Hobo::InvalidSettingAlteration do
Hobo.set_config_value 'a', 2
end end
end end
should "not alter settings through the chain method when provided and empty string" do context "initializing" do
prev = Hobo.config teardown do
Hobo.set_config_value '', 2 Hobo::Config.instance_variable_set(:@config_runners, nil)
assert_equal Hobo.config, prev Hobo::Config.instance_variable_set(:@config, nil)
end
should "not run the blocks right away" do
obj = mock("obj")
obj.expects(:foo).never
Hobo::Config.run { |config| obj.foo }
Hobo::Config.run { |config| obj.foo }
Hobo::Config.run { |config| obj.foo }
end
should "run the blocks when execute! is ran" do
obj = mock("obj")
obj.expects(:foo).times(2)
Hobo::Config.run { |config| obj.foo }
Hobo::Config.run { |config| obj.foo }
Hobo::Config.execute!
end
should "run the blocks with the same config object" do
config = mock("config")
config.expects(:foo).twice
Hobo::Config.stubs(:config).returns(config)
Hobo::Config.run { |config| config.foo }
Hobo::Config.run { |config| config.foo }
Hobo::Config.execute!
end end
end end
end end

View File

@ -6,10 +6,6 @@ class EnvTest < Test::Unit::TestCase
File.expects(:open).with(dotfile, 'r').returns(['foo']) File.expects(:open).with(dotfile, 'r').returns(['foo'])
end end
def config_file_expectation
YAML.expects(:load_file).with(Hobo::Env::CONFIG.keys.first).returns(hobo_mock_config)
end
def dotfile(dir=Dir.pwd) def dotfile(dir=Dir.pwd)
"#{dir}/#{hobo_mock_config[:dotfile_name]}" "#{dir}/#{hobo_mock_config[:dotfile_name]}"
end end
@ -24,6 +20,7 @@ class EnvTest < Test::Unit::TestCase
setup do setup do
Hobo::Env.stubs(:error_and_exit) Hobo::Env.stubs(:error_and_exit)
hobo_mock_config
end end
context "requiring a VM" do context "requiring a VM" do
@ -40,6 +37,43 @@ class EnvTest < Test::Unit::TestCase
end end
end end
context "loading config" do
setup do
@root_path = "/foo"
Hobo::Env.stubs(:root_path).returns(@root_path)
File.stubs(:exist?).returns(false)
Hobo::Config.stubs(:execute!)
end
should "load from the project root" do
File.expects(:exist?).with(File.join(PROJECT_ROOT, "config", "default.rb")).once
Hobo::Env.load_config!
end
should "load from the root path" do
File.expects(:exist?).with(File.join(@root_path, Hobo::Env::HOBOFILE_NAME)).once
Hobo::Env.load_config!
end
should "load the files only if exist? returns true" do
File.expects(:exist?).once.returns(true)
Hobo::Env.expects(:load).once
Hobo::Env.load_config!
end
should "not load the files if exist? returns false" do
Hobo::Env.expects(:load).never
Hobo::Env.load_config!
end
should "execute after loading" do
File.expects(:exist?).once.returns(true)
Hobo::Env.expects(:load).once
Hobo::Config.expects(:execute!).once
Hobo::Env.load_config!
end
end
context "initial load" do context "initial load" do
test "load! should load the config and set the persisted_uid" do test "load! should load the config and set the persisted_uid" do
Hobo::Env.expects(:load_config!).once Hobo::Env.expects(:load_config!).once
@ -49,61 +83,9 @@ class EnvTest < Test::Unit::TestCase
end end
end end
context "loading config" do
setup do
@handler = Hobo::Env
@ensure = Hobo::Env::ENSURE
Hobo.config! nil
end
test "should not create any directories if they exist" do
File.expects(:exists?).times(@ensure[:dirs].length).returns(true)
Dir.expects(:mkdir).never
@handler.ensure_directories
end
test "should not copy any files if they exist" do
File.expects(:exists?).times(@ensure[:files].length).returns(true)
File.expects(:copy).never
@handler.ensure_files
end
test "should create the ensured directories if they don't exist" do
file_seq = sequence("file_seq")
@ensure[:dirs].each do |dir|
File.expects(:exists?).returns(false).in_sequence(file_seq)
Dir.expects(:mkdir).with(dir).in_sequence(file_seq)
end
@handler.ensure_directories
end
test "should create the ensured files if they don't exist" do
file_seq = sequence("file_seq")
@ensure[:files].each do |target, default|
File.expects(:exists?).with(target).returns(false).in_sequence(file_seq)
File.expects(:copy).with(File.join(PROJECT_ROOT, default), target).in_sequence(file_seq)
end
@handler.ensure_files
end
test "should load of the default" do
config_file_expectation
@handler.load_config!
assert_equal Hobo.config[:ssh], hobo_mock_config[:ssh]
end
test "Hobo.config should be nil unless loaded" do
assert_equal Hobo.config, nil
end
end
context "persisting the VM into a file" do context "persisting the VM into a file" do
setup do setup do
Hobo.config! hobo_mock_config hobo_mock_config
end end
test "should save it to the dotfile path" do test "should save it to the dotfile path" do
@ -118,10 +100,6 @@ class EnvTest < Test::Unit::TestCase
end end
context "loading the UUID out from the persisted file" do context "loading the UUID out from the persisted file" do
setup do
Hobo.config! hobo_mock_config
end
test "loading of the uuid from the dotfile" do test "loading of the uuid from the dotfile" do
mock_persisted_vm mock_persisted_vm
assert_equal 'foovm', Hobo::Env.persisted_vm assert_equal 'foovm', Hobo::Env.persisted_vm
@ -134,7 +112,7 @@ class EnvTest < Test::Unit::TestCase
end end
test "should build up the dotfile out of the root path and the dotfile name" do test "should build up the dotfile out of the root path and the dotfile name" do
assert_equal File.join(Hobo::Env.root_path, hobo_mock_config[:dotfile_name]), Hobo::Env.dotfile_path assert_equal File.join(Hobo::Env.root_path, Hobo.config.dotfile_name), Hobo::Env.dotfile_path
end end
end end

View File

@ -3,13 +3,12 @@ require File.join(File.dirname(__FILE__), '..', 'test_helper')
class SshTest < Test::Unit::TestCase class SshTest < Test::Unit::TestCase
context "hobo ssh" do context "hobo ssh" do
setup do setup do
@handler = Hobo::SSH
@script = Hobo::SSH::SCRIPT @script = Hobo::SSH::SCRIPT
Hobo.config!(hobo_mock_config) hobo_mock_config
end end
test "should call exec with defaults when no options are supplied" do test "should call exec with defaults when no options are supplied" do
ssh = hobo_mock_config[:ssh] ssh = Hobo.config.ssh
Kernel.expects(:exec).with("#{@script} #{ssh[:uname]} #{ssh[:pass]} #{ssh[:host]} #{ssh[:port]}") Kernel.expects(:exec).with("#{@script} #{ssh[:uname]} #{ssh[:pass]} #{ssh[:host]} #{ssh[:port]}")
Hobo::SSH.connect Hobo::SSH.connect
end end

View File

@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), '..', 'test_helper')
class VMTest < Test::Unit::TestCase class VMTest < Test::Unit::TestCase
setup do setup do
@mock_vm = mock("vm") @mock_vm = mock("vm")
Hobo.config!(hobo_mock_config) hobo_mock_config
@persisted_vm = mock("persisted_vm") @persisted_vm = mock("persisted_vm")
Hobo::Env.stubs(:persisted_vm).returns(@persisted_vm) Hobo::Env.stubs(:persisted_vm).returns(@persisted_vm)

View File

@ -28,18 +28,22 @@ require 'mocha'
class Test::Unit::TestCase class Test::Unit::TestCase
def hobo_mock_config def hobo_mock_config
{ :ssh => { Hobo::Config.instance_variable_set(:@config_runners, nil)
:uname => 'foo', Hobo::Config.instance_variable_set(:@config, nil)
:pass => 'bar',
:host => 'baz', Hobo::Config.run do |config|
:port => 'bak', config.dotfile_name = ".hobo"
:max_tries => 10
}, config.ssh.uname = "foo"
:vm => { config.ssh.pass = "bar"
:base => "foo", config.ssh.host = "baz"
:base_mac => "42" config.ssh.port = "bak"
}, config.ssh.max_tries = 10
:dotfile_name => '.hobo'
} config.vm.base = "foo"
config.vm.base_mac = "42"
end
Hobo::Config.execute!
end end
end end