Hobo::Config revamp
This commit is contained in:
parent
303cc90a12
commit
c9d341ae2b
|
@ -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
|
|
@ -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
|
|
@ -1,29 +1,64 @@
|
|||
require 'forwardable'
|
||||
|
||||
module Hobo
|
||||
module_function
|
||||
def self.config
|
||||
Config.config
|
||||
end
|
||||
|
||||
class Config
|
||||
@config = nil
|
||||
@config_runners = []
|
||||
|
||||
class <<self
|
||||
def config
|
||||
@@config
|
||||
@config ||= Config::Top.new
|
||||
end
|
||||
|
||||
def config!(hash)
|
||||
@@config = hash
|
||||
def config_runners
|
||||
@config_runners ||= []
|
||||
end
|
||||
|
||||
def set_config_value(chain, val, cfg=@@config)
|
||||
keys = chain.split('.')
|
||||
|
||||
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
|
||||
def run(&block)
|
||||
config_runners << block
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
@ -2,13 +2,7 @@ require 'yaml'
|
|||
|
||||
module Hobo
|
||||
class Env
|
||||
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!
|
||||
}
|
||||
HOBOFILE_NAME = "Hobofile"
|
||||
|
||||
# Initialize class variables used
|
||||
@@persisted_vm = nil
|
||||
|
@ -17,7 +11,7 @@ module Hobo
|
|||
class << self
|
||||
def persisted_vm; @@persisted_vm; 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!
|
||||
load_root_path!
|
||||
|
@ -25,25 +19,19 @@ module Hobo
|
|||
load_vm!
|
||||
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!
|
||||
ensure_directories
|
||||
ensure_files
|
||||
load_paths = [
|
||||
File.join(PROJECT_ROOT, "config", "default.rb"),
|
||||
File.join(root_path, HOBOFILE_NAME)
|
||||
]
|
||||
|
||||
HOBO_LOGGER.info "Loading config from #{CONFIG.keys.first}"
|
||||
parsed = YAML.load_file(CONFIG.keys.first)
|
||||
Hobo.config!(parsed)
|
||||
load_paths.each do |path|
|
||||
HOBO_LOGGER.info "Loading config from #{path}..."
|
||||
load path if File.exist?(path)
|
||||
end
|
||||
|
||||
# Execute the configurations
|
||||
Config.execute!
|
||||
end
|
||||
|
||||
def load_vm!
|
||||
|
|
|
@ -6,7 +6,7 @@ module Hobo
|
|||
def connect(opts={})
|
||||
options = {}
|
||||
[: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
|
||||
|
||||
Kernel.exec "#{SCRIPT} #{options[:uname]} #{options[:pass]} #{options[:host]} #{options[:port]}".strip
|
||||
|
|
|
@ -1,27 +1,46 @@
|
|||
require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
||||
|
||||
class ConfigTest < Test::Unit::TestCase
|
||||
context "Hobo configuration" do
|
||||
context "accessing configuration" do
|
||||
setup do
|
||||
@settings = {:a => { :b => 1}}
|
||||
Hobo.config!(@settings)
|
||||
Hobo::Config.run { |config| }
|
||||
Hobo::Config.execute!
|
||||
end
|
||||
|
||||
should "alter the config given a dot chain of keys" do
|
||||
Hobo.set_config_value 'a.b', 2
|
||||
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
|
||||
should "forward config to the class method" do
|
||||
assert_equal Hobo.config, Hobo::Config.config
|
||||
end
|
||||
end
|
||||
|
||||
should "not alter settings through the chain method when provided and empty string" do
|
||||
prev = Hobo.config
|
||||
Hobo.set_config_value '', 2
|
||||
assert_equal Hobo.config, prev
|
||||
context "initializing" do
|
||||
teardown do
|
||||
Hobo::Config.instance_variable_set(:@config_runners, nil)
|
||||
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
|
||||
|
|
|
@ -6,10 +6,6 @@ class EnvTest < Test::Unit::TestCase
|
|||
File.expects(:open).with(dotfile, 'r').returns(['foo'])
|
||||
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)
|
||||
"#{dir}/#{hobo_mock_config[:dotfile_name]}"
|
||||
end
|
||||
|
@ -24,6 +20,7 @@ class EnvTest < Test::Unit::TestCase
|
|||
|
||||
setup do
|
||||
Hobo::Env.stubs(:error_and_exit)
|
||||
hobo_mock_config
|
||||
end
|
||||
|
||||
context "requiring a VM" do
|
||||
|
@ -40,6 +37,43 @@ class EnvTest < Test::Unit::TestCase
|
|||
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
|
||||
test "load! should load the config and set the persisted_uid" do
|
||||
Hobo::Env.expects(:load_config!).once
|
||||
|
@ -49,61 +83,9 @@ class EnvTest < Test::Unit::TestCase
|
|||
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
|
||||
setup do
|
||||
Hobo.config! hobo_mock_config
|
||||
hobo_mock_config
|
||||
end
|
||||
|
||||
test "should save it to the dotfile path" do
|
||||
|
@ -118,10 +100,6 @@ class EnvTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
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
|
||||
mock_persisted_vm
|
||||
assert_equal 'foovm', Hobo::Env.persisted_vm
|
||||
|
@ -134,7 +112,7 @@ class EnvTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -3,13 +3,12 @@ require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
|||
class SshTest < Test::Unit::TestCase
|
||||
context "hobo ssh" do
|
||||
setup do
|
||||
@handler = Hobo::SSH
|
||||
@script = Hobo::SSH::SCRIPT
|
||||
Hobo.config!(hobo_mock_config)
|
||||
hobo_mock_config
|
||||
end
|
||||
|
||||
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]}")
|
||||
Hobo::SSH.connect
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), '..', 'test_helper')
|
|||
class VMTest < Test::Unit::TestCase
|
||||
setup do
|
||||
@mock_vm = mock("vm")
|
||||
Hobo.config!(hobo_mock_config)
|
||||
hobo_mock_config
|
||||
|
||||
@persisted_vm = mock("persisted_vm")
|
||||
Hobo::Env.stubs(:persisted_vm).returns(@persisted_vm)
|
||||
|
|
|
@ -28,18 +28,22 @@ require 'mocha'
|
|||
|
||||
class Test::Unit::TestCase
|
||||
def hobo_mock_config
|
||||
{ :ssh => {
|
||||
:uname => 'foo',
|
||||
:pass => 'bar',
|
||||
:host => 'baz',
|
||||
:port => 'bak',
|
||||
:max_tries => 10
|
||||
},
|
||||
:vm => {
|
||||
:base => "foo",
|
||||
:base_mac => "42"
|
||||
},
|
||||
:dotfile_name => '.hobo'
|
||||
}
|
||||
Hobo::Config.instance_variable_set(:@config_runners, nil)
|
||||
Hobo::Config.instance_variable_set(:@config, nil)
|
||||
|
||||
Hobo::Config.run do |config|
|
||||
config.dotfile_name = ".hobo"
|
||||
|
||||
config.ssh.uname = "foo"
|
||||
config.ssh.pass = "bar"
|
||||
config.ssh.host = "baz"
|
||||
config.ssh.port = "bak"
|
||||
config.ssh.max_tries = 10
|
||||
|
||||
config.vm.base = "foo"
|
||||
config.vm.base_mac = "42"
|
||||
end
|
||||
|
||||
Hobo::Config.execute!
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue