rconf 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +56 -0
- data/Rakefile +63 -0
- data/bin/rconf +102 -0
- data/examples/sample.rc +9 -0
- data/lib/rconf.rb +24 -0
- data/lib/rconf/command.rb +112 -0
- data/lib/rconf/configurator.rb +179 -0
- data/lib/rconf/configurator_registry.rb +63 -0
- data/lib/rconf/configurators/bundler_configurator.rb +85 -0
- data/lib/rconf/configurators/ruby_configurator.rb +151 -0
- data/lib/rconf/language.rb +91 -0
- data/lib/rconf/platform.rb +114 -0
- data/lib/rconf/platforms/darwin.rb +27 -0
- data/lib/rconf/platforms/linux.rb +40 -0
- data/lib/rconf/platforms/windows.rb +40 -0
- data/lib/rconf/progress_reporter.rb +72 -0
- data/lib/rconf/progress_reporters/base_reporter.rb +156 -0
- data/lib/rconf/progress_reporters/file_reporter.rb +58 -0
- data/lib/rconf/progress_reporters/stdout_reporter.rb +83 -0
- data/lib/rconf/ruby_extensions.rb +56 -0
- data/lib/rconf/trollop.rb +782 -0
- data/lib/rconf/version.rb +30 -0
- data/rconf.gemspec +24 -0
- data/spec/command_spec.rb +38 -0
- data/spec/configurator_spec.rb +64 -0
- data/spec/configurators/bundler_configurator_spec.rb +51 -0
- data/spec/configurators/ruby_configurator_spec.rb +60 -0
- data/spec/language_spec.rb +60 -0
- data/spec/platform_spec.rb +37 -0
- data/spec/progress_reporters/base_reporter_spec.rb +84 -0
- data/spec/progress_reporters/file_reporter_spec.rb +31 -0
- data/spec/progress_reporters/stdout_reporter_spec.rb +23 -0
- data/spec/ruby_extensions_spec.rb +35 -0
- data/spec/spec_helper.rb +21 -0
- metadata +129 -0
data/README.rdoc
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
= right_env
|
2
|
+
|
3
|
+
== INTRODUCTION
|
4
|
+
|
5
|
+
As RightScale systems evolve, developers are faced with having to maintain a
|
6
|
+
quickly growing list of applications. Each application requires different tools
|
7
|
+
for development and for deployment. Tools may include different versions of
|
8
|
+
ruby, rubygems, bundler etc. Being able to setup an environment appropriately
|
9
|
+
for each application is becoming increasingly complex and switching from one
|
10
|
+
application to another for development in particular is quickly becoming
|
11
|
+
close to impossible.
|
12
|
+
|
13
|
+
RightEnv aims at addressing some of these difficulties by providing a uniform
|
14
|
+
and consistent mechanism for applications developed at RightScale to
|
15
|
+
declaratively specify the tools they depend on in various systems (development,
|
16
|
+
test, staging, production) and platforms (linux, darwin and windows). RightEnv
|
17
|
+
uses a DSL close to Chef recipes for defining an application configuration.
|
18
|
+
Each application must be equipped with a definition that must reside at the top
|
19
|
+
level directory of the application and must be named "<application>.re" (where
|
20
|
+
"<application>" should be subsituted with the name of the application.
|
21
|
+
Configuring the system to run the application then merely consists of running
|
22
|
+
the "script/bootstrap_environment" script provided in the "script" directory
|
23
|
+
("script/bootstrap_environment.bat" on windows).
|
24
|
+
|
25
|
+
Internally RightEnv relies on 'configurators' to configure the machine
|
26
|
+
appropriately. There is one configurator per tool that needs configuration.
|
27
|
+
Each configurator is dynamically instantiated by RightEnv as it reads the
|
28
|
+
application configuration file. This makes for an extensible system where new
|
29
|
+
configurator may be added to configure new tools that new applications may
|
30
|
+
rely on. For a list of available configurators run "script/configurator --list".
|
31
|
+
|
32
|
+
== REQUIREMENTS
|
33
|
+
|
34
|
+
=== Running
|
35
|
+
|
36
|
+
- Linux and MAc OS X
|
37
|
+
|
38
|
+
- ruby >= 1.8.6
|
39
|
+
- curl
|
40
|
+
- tar
|
41
|
+
|
42
|
+
- Windows
|
43
|
+
|
44
|
+
- ruby >= 1.8.6
|
45
|
+
- Win32API gem
|
46
|
+
|
47
|
+
=== Unit testing
|
48
|
+
|
49
|
+
Install the following gems for testing:
|
50
|
+
- rspec >= 2.0
|
51
|
+
- flexmock
|
52
|
+
|
53
|
+
Then the build can be tested with
|
54
|
+
|
55
|
+
rake spec
|
56
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright (C) 2011 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and
|
10
|
+
# the licensee
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
|
14
|
+
require 'fileutils'
|
15
|
+
require 'rake'
|
16
|
+
require 'rspec/core/rake_task'
|
17
|
+
require 'rake/rdoctask'
|
18
|
+
require 'rake/gempackagetask'
|
19
|
+
require 'rake/clean'
|
20
|
+
|
21
|
+
task :default => 'spec'
|
22
|
+
|
23
|
+
# == Unit Tests == #
|
24
|
+
|
25
|
+
desc "Run unit tests"
|
26
|
+
RSpec::Core::RakeTask.new do |t|
|
27
|
+
t.rspec_opts = ["--color"]
|
28
|
+
end
|
29
|
+
|
30
|
+
namespace :spec do
|
31
|
+
desc "Run unit tests with RCov"
|
32
|
+
RSpec::Core::RakeTask.new(:rcov) do |t|
|
33
|
+
t.rcov = true
|
34
|
+
t.rcov_opts = %q[--exclude "spec"]
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Print Specdoc for unit tests"
|
38
|
+
RSpec::Core::RakeTask.new(:doc) do |t|
|
39
|
+
t.rspec_opts = ["--format", "documentation"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# == Gem == #
|
44
|
+
|
45
|
+
gemtask = Rake::GemPackageTask.new(Gem::Specification.load('rconf.gemspec')) do |package|
|
46
|
+
package.package_dir = ENV['PACKAGE_DIR'] || 'pkg'
|
47
|
+
package.need_zip = true
|
48
|
+
package.need_tar = true
|
49
|
+
end
|
50
|
+
|
51
|
+
directory gemtask.package_dir
|
52
|
+
|
53
|
+
CLEAN.include(gemtask.package_dir)
|
54
|
+
|
55
|
+
# == Documentation == #
|
56
|
+
|
57
|
+
desc "Generate API documentation to doc/rdocs/index.html"
|
58
|
+
Rake::RDocTask.new do |rd|
|
59
|
+
rd.rdoc_dir = 'doc/rdocs'
|
60
|
+
rd.main = 'README.rdoc'
|
61
|
+
rd.rdoc_files.include 'README.rdoc', "lib/**/*.rb"
|
62
|
+
end
|
63
|
+
|
data/bin/rconf
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (C) 2011 RightScale, Inc, All Rights Reserved Worldwide.
|
3
|
+
#
|
4
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
5
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
6
|
+
# reproduction, modification, or disclosure of this program is
|
7
|
+
# strictly prohibited. Any use of this program by an authorized
|
8
|
+
# licensee is strictly subject to the terms and conditions,
|
9
|
+
# including confidentiality obligations, set forth in the applicable
|
10
|
+
# License Agreement between RightScale.com, Inc. and
|
11
|
+
# the licensee
|
12
|
+
|
13
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'rconf')
|
14
|
+
|
15
|
+
module RightConf
|
16
|
+
|
17
|
+
class Configurer
|
18
|
+
|
19
|
+
include ProgressReporter
|
20
|
+
|
21
|
+
def self.run
|
22
|
+
opts = Trollop::options do
|
23
|
+
version 'rconf 0.1 (c) 2011 RightScale'
|
24
|
+
banner <<-EOS
|
25
|
+
#{DESCRIPTION}
|
26
|
+
|
27
|
+
Usage:
|
28
|
+
rconf [options]
|
29
|
+
|
30
|
+
where [options] are:
|
31
|
+
EOS
|
32
|
+
|
33
|
+
opt :configurators, 'Show available configurators'
|
34
|
+
opt :config, 'Set path to configuration file', :type => :string
|
35
|
+
opt :output, 'Output file (output to STDOUT by default)', :type => :string
|
36
|
+
end
|
37
|
+
if opts[:config].nil?
|
38
|
+
opts[:config] = Dir['./*.rc']
|
39
|
+
if opts[:config].empty?
|
40
|
+
Trollop::die :config, "not used and could not find a '.rc' file in the working directory"
|
41
|
+
else
|
42
|
+
opts[:config] = opts[:config].first
|
43
|
+
end
|
44
|
+
end
|
45
|
+
if opts[:output]
|
46
|
+
begin
|
47
|
+
FileUtils.mkdir_p(File.dirname(opts[:output]))
|
48
|
+
rescue Exception => e
|
49
|
+
Trollop::die :output, "Failed to initialize output file: #{e.message}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
new.configure(opts)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Actually configure environment
|
56
|
+
#
|
57
|
+
# === Parameters
|
58
|
+
# options[:config](String):: Configuration file
|
59
|
+
# options[:output](String):: Output file, optional
|
60
|
+
#
|
61
|
+
# === Return
|
62
|
+
# true:: Always return true
|
63
|
+
def configure(options)
|
64
|
+
if options[:configurators]
|
65
|
+
puts "The following configurators are registered:\n\n"
|
66
|
+
ConfiguratorRegistry.each do |key, configurator|
|
67
|
+
puts "== #{key} ==".bold
|
68
|
+
puts configurator.desc
|
69
|
+
puts 'Settings:'
|
70
|
+
max_size = configurator.all_settings.keys.map(&:to_s).map(&:size).max
|
71
|
+
configurator.all_settings.each do |name, desc|
|
72
|
+
num_spaces = max_size - name.to_s.size + 1
|
73
|
+
print " - #{name.to_s.blue}:#{' ' * num_spaces}#{desc}"
|
74
|
+
if configurator.required_settings.include?(name)
|
75
|
+
puts ' [required]'.green
|
76
|
+
else
|
77
|
+
puts
|
78
|
+
end
|
79
|
+
end
|
80
|
+
puts
|
81
|
+
end
|
82
|
+
exit 0
|
83
|
+
end
|
84
|
+
ProgressReporter.report_to_stdout
|
85
|
+
ProgressReporter.report_to_file(options[:output]) if options[:output]
|
86
|
+
begin
|
87
|
+
lang = Language.load(options[:config])
|
88
|
+
report_fatal("Validation of configuration file failed:\n -#{lang.validation_errors.join("\n -").map(&:red)}") unless lang.validation_errors.empty?
|
89
|
+
Dir.chdir(File.dirname(options[:config])) { lang.configurators.each(&:run) }
|
90
|
+
report("Successfully configured #{File.basename(options[:config], '.rc').blue} for #{Platform.family.to_s.blue}")
|
91
|
+
lang.configurators.each { |c| report("NOTE: #{c.post_note}") if c.post_note }
|
92
|
+
rescue Exception => e
|
93
|
+
raise if e.is_a?(SystemExit)
|
94
|
+
report_fatal("Execution failed with exception '#{e.message.red}'\n#{e.backtrace.join("\n").map(&:grey)}")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Yeeeehaaaa!
|
102
|
+
RightConf::Configurer.run
|
data/examples/sample.rc
ADDED
data/lib/rconf.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright (C) 2011 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and
|
10
|
+
# the licensee
|
11
|
+
|
12
|
+
BASE_DIR = File.join(File.dirname(__FILE__), 'rconf')
|
13
|
+
|
14
|
+
require 'FileUtils'
|
15
|
+
require File.join(BASE_DIR, 'ruby_extensions')
|
16
|
+
require File.join(BASE_DIR, 'progress_reporter')
|
17
|
+
require File.join(BASE_DIR, 'command')
|
18
|
+
require File.join(BASE_DIR, 'configurator_registry')
|
19
|
+
require File.join(BASE_DIR, 'configurator')
|
20
|
+
require File.join(BASE_DIR, 'language')
|
21
|
+
require File.join(BASE_DIR, 'platform')
|
22
|
+
require File.join(BASE_DIR, 'trollop')
|
23
|
+
require File.join(BASE_DIR, 'version')
|
24
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Copyright (C) 2011 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and
|
10
|
+
# the licensee
|
11
|
+
|
12
|
+
require 'shellwords'
|
13
|
+
|
14
|
+
module RightConf
|
15
|
+
|
16
|
+
class Command
|
17
|
+
|
18
|
+
include Singleton
|
19
|
+
include ProgressReporter
|
20
|
+
|
21
|
+
# Execute given command with given arguments
|
22
|
+
#
|
23
|
+
# === Parameters
|
24
|
+
# command(String):: Command to run
|
25
|
+
# args(Array):: Command arguments
|
26
|
+
#
|
27
|
+
# === Return
|
28
|
+
# result(CommandResult):: Result of execution (output and exit status)
|
29
|
+
def execute(command, *args)
|
30
|
+
opts = {}
|
31
|
+
if !args.empty? && args[-1].is_a?(Hash)
|
32
|
+
opts = args[-1]
|
33
|
+
args = args[0..-2]
|
34
|
+
end
|
35
|
+
res = Platform.dispatch(command, *args) { :execute }
|
36
|
+
if !res.success? && msg = opts[:abort_on_failure]
|
37
|
+
report_fatal("#{msg}: '#{command} #{args.join(' ')}' returned\n#{res.output}")
|
38
|
+
end
|
39
|
+
res
|
40
|
+
end
|
41
|
+
|
42
|
+
# Execute given command on *nix systems
|
43
|
+
#
|
44
|
+
# === Parameters
|
45
|
+
# command(String):: Command name
|
46
|
+
# params(Array):: List of parameters to pass to command
|
47
|
+
#
|
48
|
+
# === Return
|
49
|
+
# result(CommandResult):: Result of execution (output and exit status)
|
50
|
+
def execute_linux(command, *args)
|
51
|
+
out = `#{@prefix} #{Shellwords.join([command, *args])} 2>&1`
|
52
|
+
result = CommandResult.new(out, $?.exitstatus)
|
53
|
+
end
|
54
|
+
alias :execute_darwin :execute_linux
|
55
|
+
|
56
|
+
# Execute given command on Windows systems
|
57
|
+
#
|
58
|
+
# === Parameters
|
59
|
+
# command(String):: Command name
|
60
|
+
# params(Array):: List of parameters to pass to command
|
61
|
+
#
|
62
|
+
# === Return
|
63
|
+
# result(CommandResult):: Result of execution (output and exit status)
|
64
|
+
def execute_windows(command, *args)
|
65
|
+
raise 'TBD!'
|
66
|
+
end
|
67
|
+
|
68
|
+
# Set prefix to be used for all commands
|
69
|
+
#
|
70
|
+
# === Parameters
|
71
|
+
# prefix(String):: Commands prefix
|
72
|
+
#
|
73
|
+
# === Return
|
74
|
+
# true:: Always return true
|
75
|
+
def set_prefix(prefix)
|
76
|
+
@prefix = prefix
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
# Command results
|
83
|
+
class CommandResult
|
84
|
+
|
85
|
+
# Process output
|
86
|
+
attr_reader :output
|
87
|
+
|
88
|
+
# Process exit status
|
89
|
+
attr_reader :status
|
90
|
+
|
91
|
+
# Initialize output and exit status
|
92
|
+
#
|
93
|
+
# === Parameters
|
94
|
+
# output(String):: Process output
|
95
|
+
# status(Fixnum):: Process exit status
|
96
|
+
def initialize(output, status)
|
97
|
+
@output = output
|
98
|
+
@status = status
|
99
|
+
end
|
100
|
+
|
101
|
+
# Whether process exited successfully
|
102
|
+
#
|
103
|
+
# === Return
|
104
|
+
# true:: If process exited with status code 0
|
105
|
+
# false:: Otherwise
|
106
|
+
def success?
|
107
|
+
@status == 0
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
# Copyright (C) 2011 RightScale, Inc, All Rights Reserved Worldwide.
|
2
|
+
#
|
3
|
+
# THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE
|
4
|
+
# AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use,
|
5
|
+
# reproduction, modification, or disclosure of this program is
|
6
|
+
# strictly prohibited. Any use of this program by an authorized
|
7
|
+
# licensee is strictly subject to the terms and conditions,
|
8
|
+
# including confidentiality obligations, set forth in the applicable
|
9
|
+
# License Agreement between RightScale.com, Inc. and
|
10
|
+
# the licensee
|
11
|
+
|
12
|
+
module RightConf
|
13
|
+
|
14
|
+
# Configurator mixin, defines DSL and common validation method
|
15
|
+
module Configurator
|
16
|
+
|
17
|
+
include ProgressReporter
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
|
21
|
+
# Key associated with configurator
|
22
|
+
attr_reader :key
|
23
|
+
|
24
|
+
# Description
|
25
|
+
attr_reader :desc
|
26
|
+
|
27
|
+
# Access to settings for documentation
|
28
|
+
attr_reader :all_settings
|
29
|
+
|
30
|
+
# Access to required settings for validation
|
31
|
+
attr_reader :required_settings
|
32
|
+
|
33
|
+
# Associate configurator with given key
|
34
|
+
#
|
35
|
+
# === Parameters
|
36
|
+
# key(Symbol):: Key configurator should be associated with
|
37
|
+
#
|
38
|
+
# === Return
|
39
|
+
# true:: Always return true
|
40
|
+
def register(key)
|
41
|
+
ConfiguratorRegistry[key] = self
|
42
|
+
@key = key
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
# Store description for documentation
|
47
|
+
#
|
48
|
+
# === Parameters
|
49
|
+
# description(String):: Description
|
50
|
+
#
|
51
|
+
# === Return
|
52
|
+
# true:: Always return true
|
53
|
+
def description(description)
|
54
|
+
@desc = description
|
55
|
+
true
|
56
|
+
end
|
57
|
+
|
58
|
+
# Store settings and their descriptions in a hash
|
59
|
+
#
|
60
|
+
# === Parameters
|
61
|
+
# settings(Hash):: Settings descriptions indexed by names
|
62
|
+
#
|
63
|
+
# === Return
|
64
|
+
# true:: Always return true
|
65
|
+
def settings(settings)
|
66
|
+
@all_settings = settings
|
67
|
+
true
|
68
|
+
end
|
69
|
+
|
70
|
+
# Store required settings for validation
|
71
|
+
#
|
72
|
+
# === Parameters
|
73
|
+
# settings(Array):: List of settings that should be checked
|
74
|
+
#
|
75
|
+
# === Return
|
76
|
+
# true:: Always return true
|
77
|
+
def validate_has_settings(*settings)
|
78
|
+
@required_settings = settings.flatten
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# Extend base class with ClassMethods module methods
|
85
|
+
#
|
86
|
+
# === Parameters
|
87
|
+
# base(Object):: Object including module
|
88
|
+
def self.included(base)
|
89
|
+
base.__send__(:extend, ClassMethods)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Check whether configurator has values for all required settings
|
93
|
+
#
|
94
|
+
# === Return
|
95
|
+
# nil:: If settings are valid for this configurator
|
96
|
+
# error(String):: Error message otherwise
|
97
|
+
def validate
|
98
|
+
init
|
99
|
+
required = self.class.required_settings
|
100
|
+
return nil unless required
|
101
|
+
missing = required.flatten.select { |s| !@settings_values.include?(s) }
|
102
|
+
error = case missing.size
|
103
|
+
when 0 then nil
|
104
|
+
when 1 then "Required setting #{missing.first} is "
|
105
|
+
else
|
106
|
+
"Required settings #{missing.join(', ')} are "
|
107
|
+
end
|
108
|
+
error += "missing for configuration section '#{self.class.key}'" if error
|
109
|
+
error
|
110
|
+
end
|
111
|
+
|
112
|
+
# Run configurator for current platform
|
113
|
+
#
|
114
|
+
# === Parameters
|
115
|
+
# args:: Pass-through arguments, given to platform specific implementation
|
116
|
+
#
|
117
|
+
# === Return
|
118
|
+
# true:: Always return true
|
119
|
+
def run(*args)
|
120
|
+
init
|
121
|
+
Platform.dispatch(*args) { :run }
|
122
|
+
true
|
123
|
+
end
|
124
|
+
|
125
|
+
# Get value of configuration option
|
126
|
+
#
|
127
|
+
# === Parameters
|
128
|
+
# config_option(Symbol):: Configuration option to return
|
129
|
+
#
|
130
|
+
# === Returns
|
131
|
+
# value:: Value of configuration option if there is one
|
132
|
+
# nil:: Otherwise
|
133
|
+
def [](config_option)
|
134
|
+
init
|
135
|
+
@settings_values[config_option]
|
136
|
+
end
|
137
|
+
|
138
|
+
protected
|
139
|
+
|
140
|
+
# DSL implementation, set settings value if arguments, get it otherwise.
|
141
|
+
#
|
142
|
+
# === Parameters
|
143
|
+
# meth(Symbol):: Method symbol
|
144
|
+
# args(Array):: List of arguments
|
145
|
+
#
|
146
|
+
# === Return
|
147
|
+
# res(Object):: Configuration setting value or setter return value if
|
148
|
+
# arguments
|
149
|
+
def method_missing(meth, *args)
|
150
|
+
init
|
151
|
+
num_args = args.length
|
152
|
+
res = nil
|
153
|
+
if num_args > 0
|
154
|
+
meth = $1.to_sym unless (meth.to_s =~ /(.+)=$/).nil?
|
155
|
+
value = num_args == 1 ? args[0] : args
|
156
|
+
method_name = meth.id2name
|
157
|
+
if self.public_methods.include?("#{method_name}=")
|
158
|
+
res = self.send("#{method_name}=", value)
|
159
|
+
else
|
160
|
+
res = @settings_values[meth] = value
|
161
|
+
end
|
162
|
+
end
|
163
|
+
res || @settings_values[meth]
|
164
|
+
end
|
165
|
+
|
166
|
+
# Initialize configuration settings hash
|
167
|
+
#
|
168
|
+
# === Return
|
169
|
+
# true:: Always return true
|
170
|
+
def init
|
171
|
+
@settings_values ||= Hash.new
|
172
|
+
true
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Load all configurators
|
179
|
+
Dir[File.join(File.dirname(__FILE__), 'configurators', '*.rb')].each { |c| require c }
|