rconf 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
@@ -0,0 +1,27 @@
|
|
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
|
+
# Linux specific implementation
|
15
|
+
class Platform
|
16
|
+
|
17
|
+
attr_reader :flavor, :release
|
18
|
+
|
19
|
+
# Initialize flavor and release
|
20
|
+
def init
|
21
|
+
@flavor = 'mac_os_x'
|
22
|
+
@release = `sw_vers -productVersion`
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
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
|
+
# Linux specific implementation
|
15
|
+
class Platform
|
16
|
+
|
17
|
+
FEDORA_REL = '/etc/fedora-release'
|
18
|
+
FEDORA_SIG = /Fedora release ([0-9]+) \(.*\)/
|
19
|
+
|
20
|
+
attr_reader :flavor, :release
|
21
|
+
|
22
|
+
# Initialize flavor and release
|
23
|
+
def init
|
24
|
+
system('lsb_release --help > /dev/null 2>&1')
|
25
|
+
if $?.success?
|
26
|
+
# Use the lsb_release utility if it's available
|
27
|
+
@flavor = `lsb_release -is`.strip.downcase
|
28
|
+
@release = `lsb_release -rs`.strip
|
29
|
+
elsif File.exist?(FEDORA_REL) && (match = FEDORA_SIG.match(File.read(FEDORA_REL)))
|
30
|
+
# Parse the fedora-release file if it exists
|
31
|
+
@distro = 'fedora'
|
32
|
+
@release = match[1]
|
33
|
+
else
|
34
|
+
@distro = @release = 'unknown'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
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 'Win32API'
|
14
|
+
|
15
|
+
module RightConf
|
16
|
+
|
17
|
+
# Linux specific implementation
|
18
|
+
class Platform
|
19
|
+
|
20
|
+
attr_reader :flavor, :release
|
21
|
+
|
22
|
+
# Initialize flavor and release
|
23
|
+
def init
|
24
|
+
GetVersionEx = Win32API.new("kernel32", "GetVersionEx", 'P', 'L')
|
25
|
+
osversioninfo = [
|
26
|
+
148, # size of this struct (IN)
|
27
|
+
0, # major version (OUT)
|
28
|
+
0, # minor version (OUT)
|
29
|
+
0, # build (OUT)
|
30
|
+
0, # platform (OUT)
|
31
|
+
"\0" * 128 # additional info (OUT)
|
32
|
+
].pack('LLLLLa128')
|
33
|
+
|
34
|
+
raise 'Failed to detect Windows version' unless GetVersionEx.call(osversioninfo) == 1 # => 1, means succeeded
|
35
|
+
version = osversioninfo.unpack('LLLLLZ128') # 'Z' means ASCIIZ string
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,72 @@
|
|
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
|
+
# Provide progress report methods used by configurators
|
15
|
+
module ProgressReporter
|
16
|
+
|
17
|
+
# Create list of reporters upon inclusion
|
18
|
+
# Also setup forwarders
|
19
|
+
#
|
20
|
+
# === Parameters
|
21
|
+
# base(Object):: Object including this module
|
22
|
+
def self.included(base)
|
23
|
+
@@reporters ||= []
|
24
|
+
[ :report_section, :report, :report_check, :report_success,
|
25
|
+
:report_failure, :report_fatal, :report_result ].each do |meth|
|
26
|
+
meta_def(meth) { |*args| @@reporters.each { |r| r.__send__(meth, *args) } }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Print progress reports to stdout, default behavior
|
31
|
+
#
|
32
|
+
# === Return
|
33
|
+
# true:: Always return true
|
34
|
+
def self.report_to_stdout
|
35
|
+
@@reporters ||= []
|
36
|
+
@@reporters << StdoutReporter.new
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
# Save progress reports to given file
|
41
|
+
#
|
42
|
+
# === Parameters
|
43
|
+
# path(String):: Path to file where progress reports should be saved
|
44
|
+
#
|
45
|
+
# === Return
|
46
|
+
# true:: Always return true
|
47
|
+
def self.report_to_file(path)
|
48
|
+
@@reporters ||= []
|
49
|
+
@@reporters << FileReporter.new(path)
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
# Define method programmatically (a.k.a. meta-programming a.k.a use-sparingly)
|
56
|
+
#
|
57
|
+
# === Parameters
|
58
|
+
# name(String):: Method name
|
59
|
+
# blk(Proc):: Method implementation
|
60
|
+
#
|
61
|
+
# === Return
|
62
|
+
# true:: Always return true
|
63
|
+
def self.meta_def(name, &blk)
|
64
|
+
self.instance_eval { define_method(name, &blk) }
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Load all progress reporters
|
72
|
+
Dir[File.join(File.dirname(__FILE__), 'progress_reporters', '*.rb')].each { |r| require r }
|
@@ -0,0 +1,156 @@
|
|
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
|
+
# Common base to all progress reporters
|
15
|
+
#
|
16
|
+
# Reporters expose the following report methods whose default implementations
|
17
|
+
# can be overridden in descendants:
|
18
|
+
#
|
19
|
+
# - report_message:: Standard progress report message
|
20
|
+
# - report_section:: Title
|
21
|
+
# - report_error:: Non fatal error
|
22
|
+
# - report_fatal:: Fatal error, will raise after reporting message
|
23
|
+
# - report_check:: Report a check being done on system, should be followed by
|
24
|
+
# - report_success:: Report check success
|
25
|
+
# - report_failure:: Report check failure
|
26
|
+
# - report_result:: Report check success or failure depending on argument
|
27
|
+
#
|
28
|
+
# Alternatively reporters can override any associated formatting method
|
29
|
+
# (:format_message, :format_section, etc.) and/or the :write method used to
|
30
|
+
# write the progress report.
|
31
|
+
class BaseReporter
|
32
|
+
|
33
|
+
# Report methods are associated with formatting methods
|
34
|
+
# Call the formatting method then call the reporter 'write' method
|
35
|
+
# Reporters can override any formatting method and/or the write method
|
36
|
+
#
|
37
|
+
# === Parameters
|
38
|
+
# meth(Symbol):: Reporting method
|
39
|
+
# args(Array):: Arguments
|
40
|
+
#
|
41
|
+
# === Return
|
42
|
+
# true:: Always return true
|
43
|
+
#
|
44
|
+
# === Raise
|
45
|
+
# (Exception):: If there is no formatting method
|
46
|
+
def method_missing(meth, *args)
|
47
|
+
# Shortcut for standard progress report message
|
48
|
+
meth = :report_message if meth == :report
|
49
|
+
if meth.to_s =~ /^report_([a-zA-Z]+)$/
|
50
|
+
format_method = "format_#{Regexp.last_match[1]}".to_s
|
51
|
+
if self.respond_to?(format_method)
|
52
|
+
text = self.__send__(format_method, *args)
|
53
|
+
write(text)
|
54
|
+
exit 1 if Regexp.last_match[1] == 'fatal'
|
55
|
+
else
|
56
|
+
super(meth, *args)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
super(meth, *args)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Report success or failure
|
64
|
+
#
|
65
|
+
# === Parameters
|
66
|
+
# res(TrueClass|FalseClass):: true for success, false for failure
|
67
|
+
#
|
68
|
+
# === Return
|
69
|
+
# true:: Always return true
|
70
|
+
def report_result(res)
|
71
|
+
res ? report_success : report_failure
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
# Actually write text, implement in descendant
|
77
|
+
#
|
78
|
+
# === Parameters
|
79
|
+
# text(String):: Text to be written
|
80
|
+
#
|
81
|
+
# === Return
|
82
|
+
# true:: Always return true
|
83
|
+
def write(text)
|
84
|
+
raise "Implement!"
|
85
|
+
end
|
86
|
+
|
87
|
+
# Generic progress report formatting
|
88
|
+
#
|
89
|
+
# === Parameters
|
90
|
+
# message(String):: Progress report content
|
91
|
+
#
|
92
|
+
# === Return
|
93
|
+
# text(String):: Resulting text
|
94
|
+
def format_message(message)
|
95
|
+
text = message + "\n"
|
96
|
+
end
|
97
|
+
|
98
|
+
# Format new progress report section
|
99
|
+
#
|
100
|
+
# === Parameters
|
101
|
+
# section(String):: Section title
|
102
|
+
#
|
103
|
+
# === Return
|
104
|
+
# text(String):: Resulting text
|
105
|
+
def format_section(section)
|
106
|
+
text = ['', '-' * 80, section.upcase, '-' * 80, ''].join("\n")
|
107
|
+
end
|
108
|
+
|
109
|
+
# Format non-fatal error
|
110
|
+
#
|
111
|
+
# === Parameters
|
112
|
+
# error(String):: Error to report
|
113
|
+
#
|
114
|
+
# === Return
|
115
|
+
# text(String):: Resulting text
|
116
|
+
def format_error(error)
|
117
|
+
text = '**WARN: ' + error + "\n"
|
118
|
+
end
|
119
|
+
|
120
|
+
# Format check
|
121
|
+
#
|
122
|
+
# === Parameters
|
123
|
+
# check(String):: Check title
|
124
|
+
#
|
125
|
+
# === Return
|
126
|
+
# text(String):: Resulting text
|
127
|
+
def format_check(check)
|
128
|
+
text = check + '...'
|
129
|
+
end
|
130
|
+
|
131
|
+
# Format check success
|
132
|
+
#
|
133
|
+
# === Return
|
134
|
+
# text(String):: Resulting text
|
135
|
+
def format_success
|
136
|
+
text ="OK\n"
|
137
|
+
end
|
138
|
+
|
139
|
+
# Format check failure
|
140
|
+
#
|
141
|
+
# === Return
|
142
|
+
# text(String):: Resulting text
|
143
|
+
def format_failure
|
144
|
+
text ="FAILED\n"
|
145
|
+
end
|
146
|
+
|
147
|
+
# Format fatal error
|
148
|
+
#
|
149
|
+
# === Return
|
150
|
+
# text(String):: Resulting text
|
151
|
+
def format_fatal(error)
|
152
|
+
text = "\n***FATAL: " + error + "\n"
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,58 @@
|
|
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
|
+
# File progress reporter, logs progress to file
|
15
|
+
class FileReporter < BaseReporter
|
16
|
+
|
17
|
+
# Set filename and check file can be written to
|
18
|
+
# Create file directory if needed
|
19
|
+
#
|
20
|
+
# === Parameters
|
21
|
+
# path(String):: Path to progress reports file
|
22
|
+
#
|
23
|
+
# === Raise
|
24
|
+
# (Exception):: If progress report file is not writable
|
25
|
+
def initialize(path)
|
26
|
+
FileUtils.mkdir_p(File.dirname(path))
|
27
|
+
system("touch #{path}")
|
28
|
+
raise "Could not initialize progress report file #{path}" unless $?.success?
|
29
|
+
@path = path
|
30
|
+
end
|
31
|
+
|
32
|
+
# Write lines to progress report file, prepend timestamp
|
33
|
+
#
|
34
|
+
# === Parameters
|
35
|
+
# lines(Array|String):: Lines to be written as array of strings or strings
|
36
|
+
#
|
37
|
+
# === Return
|
38
|
+
# true:: Always return true
|
39
|
+
def write(lines)
|
40
|
+
lines = '' if lines.nil?
|
41
|
+
lines = lines.split("\n") if lines.is_a?(String)
|
42
|
+
lines = lines.flatten
|
43
|
+
begin
|
44
|
+
File.open(@path, 'a') do |f|
|
45
|
+
lines.each do |line|
|
46
|
+
f.puts Time.now.strftime("[%m/%d/%Y %H:%M:%S] ") + line
|
47
|
+
end
|
48
|
+
end
|
49
|
+
rescue Exception => e
|
50
|
+
puts lines.join("\n")
|
51
|
+
end
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
@@ -0,0 +1,83 @@
|
|
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
|
+
$stdout.sync = true
|
13
|
+
|
14
|
+
module RightConf
|
15
|
+
|
16
|
+
# STDOUT progress reporter, logs progress to console
|
17
|
+
class StdoutReporter < BaseReporter
|
18
|
+
|
19
|
+
# Print given text to STDOUT
|
20
|
+
#
|
21
|
+
# === Parameters
|
22
|
+
# text(String):: Text to be printed
|
23
|
+
#
|
24
|
+
# === Return
|
25
|
+
# true:: Always return true
|
26
|
+
def write(text)
|
27
|
+
$stdout.print(text)
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
# Format new progress report section
|
32
|
+
#
|
33
|
+
# === Parameters
|
34
|
+
# section(String):: Section title
|
35
|
+
#
|
36
|
+
# === Return
|
37
|
+
# text(String):: Formatted text
|
38
|
+
def format_section(section)
|
39
|
+
text = super(section).green
|
40
|
+
end
|
41
|
+
|
42
|
+
# Format check, should be followed by +report_success+ or +report_failure+
|
43
|
+
#
|
44
|
+
# === Parameters
|
45
|
+
# check(String):: Check title
|
46
|
+
#
|
47
|
+
# === Return
|
48
|
+
# text(String):: Formatted text
|
49
|
+
def format_check(check)
|
50
|
+
text = super(check)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Format check success
|
54
|
+
#
|
55
|
+
# === Return
|
56
|
+
# text(String):: Formatted text
|
57
|
+
def format_success
|
58
|
+
text = super.blue
|
59
|
+
end
|
60
|
+
|
61
|
+
# Format check failure
|
62
|
+
#
|
63
|
+
# === Return
|
64
|
+
# text(String):: Formatted text
|
65
|
+
def format_failure
|
66
|
+
text = super.red
|
67
|
+
end
|
68
|
+
|
69
|
+
# Format fatal error and raise exception to stop execution
|
70
|
+
#
|
71
|
+
# === Return
|
72
|
+
# text(String):: Formatted text
|
73
|
+
def format_fatal(error)
|
74
|
+
text = super.split("\n")
|
75
|
+
text[0] = text[0].red.bold
|
76
|
+
text[1] = text[1].red.bold if text.size > 1
|
77
|
+
text.join("\n") + "\n"
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|