sunshine 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +237 -0
- data/Manifest.txt +70 -0
- data/README.txt +277 -0
- data/Rakefile +46 -0
- data/bin/sunshine +5 -0
- data/examples/deploy.rb +61 -0
- data/examples/deploy_tasks.rake +112 -0
- data/examples/standalone_deploy.rb +31 -0
- data/lib/commands/add.rb +96 -0
- data/lib/commands/default.rb +169 -0
- data/lib/commands/list.rb +322 -0
- data/lib/commands/restart.rb +62 -0
- data/lib/commands/rm.rb +83 -0
- data/lib/commands/run.rb +151 -0
- data/lib/commands/start.rb +72 -0
- data/lib/commands/stop.rb +61 -0
- data/lib/sunshine/app.rb +876 -0
- data/lib/sunshine/binder.rb +70 -0
- data/lib/sunshine/crontab.rb +143 -0
- data/lib/sunshine/daemon.rb +380 -0
- data/lib/sunshine/daemons/ar_sendmail.rb +28 -0
- data/lib/sunshine/daemons/delayed_job.rb +30 -0
- data/lib/sunshine/daemons/nginx.rb +104 -0
- data/lib/sunshine/daemons/rainbows.rb +35 -0
- data/lib/sunshine/daemons/server.rb +66 -0
- data/lib/sunshine/daemons/unicorn.rb +26 -0
- data/lib/sunshine/dependencies.rb +103 -0
- data/lib/sunshine/dependency_lib.rb +200 -0
- data/lib/sunshine/exceptions.rb +54 -0
- data/lib/sunshine/healthcheck.rb +83 -0
- data/lib/sunshine/output.rb +131 -0
- data/lib/sunshine/package_managers/apt.rb +48 -0
- data/lib/sunshine/package_managers/dependency.rb +349 -0
- data/lib/sunshine/package_managers/gem.rb +54 -0
- data/lib/sunshine/package_managers/yum.rb +62 -0
- data/lib/sunshine/remote_shell.rb +241 -0
- data/lib/sunshine/repo.rb +128 -0
- data/lib/sunshine/repos/git_repo.rb +122 -0
- data/lib/sunshine/repos/rsync_repo.rb +29 -0
- data/lib/sunshine/repos/svn_repo.rb +78 -0
- data/lib/sunshine/server_app.rb +554 -0
- data/lib/sunshine/shell.rb +384 -0
- data/lib/sunshine.rb +391 -0
- data/templates/logrotate/logrotate.conf.erb +11 -0
- data/templates/nginx/nginx.conf.erb +109 -0
- data/templates/nginx/nginx_optimize.conf +23 -0
- data/templates/nginx/nginx_proxy.conf +13 -0
- data/templates/rainbows/rainbows.conf.erb +18 -0
- data/templates/tasks/sunshine.rake +114 -0
- data/templates/unicorn/unicorn.conf.erb +6 -0
- data/test/fixtures/app_configs/test_app.yml +11 -0
- data/test/fixtures/sunshine_test/test_upload +0 -0
- data/test/mocks/mock_object.rb +179 -0
- data/test/mocks/mock_open4.rb +117 -0
- data/test/test_helper.rb +188 -0
- data/test/unit/test_app.rb +489 -0
- data/test/unit/test_binder.rb +20 -0
- data/test/unit/test_crontab.rb +128 -0
- data/test/unit/test_git_repo.rb +26 -0
- data/test/unit/test_healthcheck.rb +70 -0
- data/test/unit/test_nginx.rb +107 -0
- data/test/unit/test_rainbows.rb +26 -0
- data/test/unit/test_remote_shell.rb +102 -0
- data/test/unit/test_repo.rb +42 -0
- data/test/unit/test_server.rb +324 -0
- data/test/unit/test_server_app.rb +425 -0
- data/test/unit/test_shell.rb +97 -0
- data/test/unit/test_sunshine.rb +157 -0
- data/test/unit/test_svn_repo.rb +55 -0
- data/test/unit/test_unicorn.rb +22 -0
- metadata +217 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
##
|
4
|
+
# The Output class handles all of the logging to the shell
|
5
|
+
# during the Sunshine runtime.
|
6
|
+
|
7
|
+
class Output
|
8
|
+
|
9
|
+
COLORS = {
|
10
|
+
Logger::UNKNOWN => :red,
|
11
|
+
Logger::FATAL => :red,
|
12
|
+
Logger::ERROR => :red,
|
13
|
+
Logger::WARN => :yellow,
|
14
|
+
Logger::INFO => :default,
|
15
|
+
Logger::DEBUG => :cyan,
|
16
|
+
}
|
17
|
+
|
18
|
+
attr_accessor :logger, :indent, :level
|
19
|
+
|
20
|
+
def initialize(options={})
|
21
|
+
@logger = Logger.new options[:output] || $stdout
|
22
|
+
@logger.formatter = lambda{|sev, time, progname, msg| msg}
|
23
|
+
@level = @logger.level = options[:level] || Logger::DEBUG
|
24
|
+
@indent = 0
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Prints messages according to the standard output format.
|
29
|
+
# Options supported:
|
30
|
+
# :level: level of the log message
|
31
|
+
# :indent: indentation of the message
|
32
|
+
def print(title, message, options={})
|
33
|
+
severity = options[:level] || Logger::DEBUG
|
34
|
+
color = COLORS[severity]
|
35
|
+
|
36
|
+
options[:indent] = 0 if options[:indent] < 0
|
37
|
+
indent = " " * (options[:indent].to_i * 2)
|
38
|
+
|
39
|
+
print_string = message.split("\n")
|
40
|
+
print_string.map!{|m| "#{indent}[#{title}] #{m.chomp}"}
|
41
|
+
print_string = "#{print_string.join("\n")} \n"
|
42
|
+
print_string = print_string.foreground(color)
|
43
|
+
print_string = print_string.bright if indent.empty?
|
44
|
+
|
45
|
+
@logger.add(severity, print_string)
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Generic log message which handles log indentation (for clarity).
|
50
|
+
# Log indentation if achieved done by passing a block:
|
51
|
+
#
|
52
|
+
# output.log("MAIN", "Main thing is happening") do
|
53
|
+
# ...
|
54
|
+
# output.log("SUB1", "Sub process thing") do
|
55
|
+
# ...
|
56
|
+
# output.log("SUB2", "Innermost process thing")
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# output.log("MAIN", "Start something else")
|
61
|
+
#
|
62
|
+
# ------
|
63
|
+
# > [MAIN] Main thing is happening
|
64
|
+
# > [SUB1] Sub process thing
|
65
|
+
# > [SUB2] Innermost process thing
|
66
|
+
# >
|
67
|
+
# > [MAIN] Start something else
|
68
|
+
#
|
69
|
+
# Log level is set to the instance's default unless
|
70
|
+
# specified in the options argument with :level => Logger::LEVEL.
|
71
|
+
# The default log level is Logger::INFO
|
72
|
+
#
|
73
|
+
# Best practice for using log levels is to call the level methods
|
74
|
+
# which all work similarly to the log method:
|
75
|
+
# unknown, fatal, error, warn, info, debug
|
76
|
+
def log(title, message, options={}, &block)
|
77
|
+
unless Sunshine.trace?
|
78
|
+
return block.call if block_given?
|
79
|
+
return
|
80
|
+
end
|
81
|
+
|
82
|
+
options = {:indent => @indent}.merge(options)
|
83
|
+
self.print(title, message, options)
|
84
|
+
if block_given?
|
85
|
+
@indent = @indent + 1
|
86
|
+
begin
|
87
|
+
block.call
|
88
|
+
ensure
|
89
|
+
@indent = @indent - 1 unless @indent <= 0
|
90
|
+
@logger << "\n"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Log a message of log level unknown.
|
97
|
+
def unknown(title, message, options={}, &block)
|
98
|
+
self.log(title, message, options.merge(:level => Logger::UNKNOWN), &block)
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# Log a message of log level fatal.
|
103
|
+
def fatal(title, message, options={}, &block)
|
104
|
+
self.log(title, message, options.merge(:level => Logger::FATAL), &block)
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Log a message of log level error.
|
109
|
+
def error(title, message, options={}, &block)
|
110
|
+
self.log(title, message, options.merge(:level => Logger::ERROR), &block)
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Log a message of log level warn.
|
115
|
+
def warn(title, message, options={}, &block)
|
116
|
+
self.log(title, message, options.merge(:level => Logger::WARN), &block)
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Log a message of log level info.
|
121
|
+
def info(title, message, options={}, &block)
|
122
|
+
self.log(title, message, options.merge(:level => Logger::INFO), &block)
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Log a message of log level debug.
|
127
|
+
def debug(title, message, options={}, &block)
|
128
|
+
self.log(title, message, options.merge(:level => Logger::DEBUG), &block)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
##
|
4
|
+
# The Apt dependency class supports basic apt-get features:
|
5
|
+
#
|
6
|
+
# dependency_lib.instance_eval do
|
7
|
+
# apt "ruby", :version => '1.9'
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# See the Dependency class for more info.
|
11
|
+
|
12
|
+
class Apt < Dependency
|
13
|
+
|
14
|
+
def initialize(name, options={}, &block)
|
15
|
+
super(name, options) do
|
16
|
+
pkg_name = build_pkg_name @pkg.dup, options
|
17
|
+
|
18
|
+
install "apt-get install -y #{pkg_name}"
|
19
|
+
uninstall "apt-get remove -y #{pkg_name}"
|
20
|
+
|
21
|
+
@pkg = "#{@pkg}-#{options[:version]}" if options[:version]
|
22
|
+
check_test "apt-cache search ^#{@pkg} | grep -c ^#{@pkg}", '-ge 1'
|
23
|
+
|
24
|
+
instance_eval(&block) if block_given?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def build_pkg_name pkg_name, options={}
|
32
|
+
pkg_name << "=#{options[:version]}" if options[:version]
|
33
|
+
|
34
|
+
pkg_name
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def run_command(command, options={})
|
39
|
+
if @dependency_lib
|
40
|
+
if @dependency_lib.exist?('apt')
|
41
|
+
@dependency_lib.install 'apt', options
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,349 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
##
|
4
|
+
# Dependency objects let you define how to install, check, and remove
|
5
|
+
# a described package, including parent dependency lookup and installation.
|
6
|
+
#
|
7
|
+
# Dependency.new "ruby", :tree => dependency_lib do
|
8
|
+
# install "sudo yum install ruby"
|
9
|
+
# uninstall "sudo yum remove ruby"
|
10
|
+
# check_test "yum list installed ruby | grep -c ruby", "-ge 1"
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# Dependencies are more commonly defined through a Settler class'
|
14
|
+
# constructor methods:
|
15
|
+
#
|
16
|
+
# dependency_lib.instance_eval do
|
17
|
+
# dependency 'custom' do
|
18
|
+
# requires 'yum', 'ruby'
|
19
|
+
# install 'sudo yum install custom'
|
20
|
+
# uninstall 'sudo yum remove custom'
|
21
|
+
# check 'yum list installed custom'
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# The Dependency class is simple to inherit and use as a built-in part of
|
26
|
+
# Settler (see the Yum implementation for more info):
|
27
|
+
#
|
28
|
+
# class Yum < Dependency
|
29
|
+
# def initialize(name, options={}, &block)
|
30
|
+
# super(dep_lib, name, options) do
|
31
|
+
# # Define install, check, and uninstall scripts specific to yum
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
# ...
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# Once a subclass is defined a constructor method is added automatically
|
38
|
+
# to the Settler class:
|
39
|
+
#
|
40
|
+
# dependency_lib.instance_eval do
|
41
|
+
# yum "ruby", :version => '1.9'
|
42
|
+
# end
|
43
|
+
|
44
|
+
class Dependency
|
45
|
+
|
46
|
+
class CmdError < Exception; end
|
47
|
+
class InstallError < Exception; end
|
48
|
+
class UninstallError < Exception; end
|
49
|
+
|
50
|
+
|
51
|
+
##
|
52
|
+
# Check if sudo should be used
|
53
|
+
|
54
|
+
def self.sudo
|
55
|
+
@sudo ||= nil
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
##
|
60
|
+
# Assign a sudo value. A value of nil means 'don't assign sudo',
|
61
|
+
# true means sudo, string means sudo -u, false means, explicitely
|
62
|
+
# don't use sudo. Yum and Gem dependency types default to sudo=true.
|
63
|
+
|
64
|
+
def self.sudo= value
|
65
|
+
@sudo = value
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
attr_reader :name, :pkg, :parents, :children
|
70
|
+
|
71
|
+
def initialize name, options={}, &block
|
72
|
+
@dependency_lib = options[:tree]
|
73
|
+
|
74
|
+
@name = name.to_s
|
75
|
+
@pkg = options[:pkg] || @name
|
76
|
+
@options = options.dup
|
77
|
+
|
78
|
+
@install = nil
|
79
|
+
@uninstall = nil
|
80
|
+
@check = nil
|
81
|
+
|
82
|
+
@parents = []
|
83
|
+
@children = []
|
84
|
+
|
85
|
+
@shell = Sunshine.shell
|
86
|
+
|
87
|
+
requires(*options[:requires]) if options[:requires]
|
88
|
+
|
89
|
+
instance_eval(&block) if block_given?
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
##
|
94
|
+
# Append a child dependency
|
95
|
+
|
96
|
+
def add_child name
|
97
|
+
@children << name
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
##
|
102
|
+
# Get direct child dependencies
|
103
|
+
|
104
|
+
def child_dependencies
|
105
|
+
@children
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
##
|
110
|
+
# Define the command that checks if the dependency is installed.
|
111
|
+
# The check command must have an appropriate exitcode:
|
112
|
+
#
|
113
|
+
# dep.check "test -s 'yum list installed depname'"
|
114
|
+
|
115
|
+
def check cmd_str=nil, &block
|
116
|
+
@check = cmd_str || block
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
##
|
121
|
+
# Define checking that the dependency is installed via unix's 'test':
|
122
|
+
#
|
123
|
+
# dep.check_test "yum list installed depname | grep -c depname", "-ge 1"
|
124
|
+
|
125
|
+
def check_test cmd_str, condition_str
|
126
|
+
check "test \"$(#{cmd_str})\" #{condition_str}"
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
##
|
131
|
+
# Define the install command for the dependency:
|
132
|
+
#
|
133
|
+
# dep.install "yum install depname"
|
134
|
+
|
135
|
+
def install cmd=nil, &block
|
136
|
+
@install = cmd || block
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
##
|
141
|
+
# Run the install command for the dependency
|
142
|
+
# Allows options:
|
143
|
+
# :call:: obj - an object that responds to call will be passed the bash cmd
|
144
|
+
# :skip_parents:: true - install regardless of missing parent dependencies
|
145
|
+
#
|
146
|
+
# runner = lambda{|str| system(str)}
|
147
|
+
# dep.install! :call => runner
|
148
|
+
|
149
|
+
def install! options={}
|
150
|
+
return if installed?(options)
|
151
|
+
|
152
|
+
if options[:skip_parents]
|
153
|
+
missing = missing_parents?
|
154
|
+
if missing
|
155
|
+
raise(InstallError, "Could not install #{@name}. "+
|
156
|
+
"Missing dependencies #{missing.join(", ")}")
|
157
|
+
end
|
158
|
+
else
|
159
|
+
install_parents!(options)
|
160
|
+
end
|
161
|
+
|
162
|
+
run_command(@install, options)
|
163
|
+
raise(InstallError, "Failed installing #{@name}") unless
|
164
|
+
installed?(options)
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
##
|
169
|
+
# Call install on direct parent dependencies
|
170
|
+
# Allows options:
|
171
|
+
# :call:: obj - an object that responds to call will be passed the bash cmd
|
172
|
+
#
|
173
|
+
# runner = lambda{|str| system(str)}
|
174
|
+
# dep.install_parents! :call => runner
|
175
|
+
|
176
|
+
def install_parents! options={}
|
177
|
+
return unless @dependency_lib
|
178
|
+
|
179
|
+
@parents.each do |dep|
|
180
|
+
@dependency_lib.get(dep, options).install!(options)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
##
|
186
|
+
# Run the check command to verify that the dependency is installed
|
187
|
+
# Allows options:
|
188
|
+
# :call:: obj - an object that responds to call will be passed the bash cmd
|
189
|
+
#
|
190
|
+
# runner = lambda{|str| system(str)}
|
191
|
+
# dep.installed? :call => runner
|
192
|
+
|
193
|
+
def installed? options={}
|
194
|
+
run_command @check, options
|
195
|
+
rescue => e
|
196
|
+
false
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
##
|
201
|
+
# Checks if any parents dependencies are missing
|
202
|
+
# Allows options:
|
203
|
+
# :call:: obj - an object that responds to call will be passed the bash cmd
|
204
|
+
#
|
205
|
+
# runner = lambda{|str| system(str)}
|
206
|
+
# dep.missing_parents? :call => runner
|
207
|
+
|
208
|
+
|
209
|
+
def missing_parents? options={}
|
210
|
+
return unless @dependency_lib
|
211
|
+
|
212
|
+
missing = []
|
213
|
+
@parents.each do |dep|
|
214
|
+
parent_dep = @dependency_lib.get dep, options
|
215
|
+
|
216
|
+
missing << dep unless parent_dep.installed?(options)
|
217
|
+
|
218
|
+
return missing if options[:limit] && options[:limit] == missing.length
|
219
|
+
end
|
220
|
+
|
221
|
+
missing.empty? ? nil : missing
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
##
|
226
|
+
# Get direct parent dependencies
|
227
|
+
|
228
|
+
def parent_dependencies
|
229
|
+
@parents
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
##
|
234
|
+
# Define which dependencies this dependency relies on:
|
235
|
+
#
|
236
|
+
# dep.requires 'rubygems', 'rdoc'
|
237
|
+
|
238
|
+
def requires *deps
|
239
|
+
return unless @dependency_lib
|
240
|
+
|
241
|
+
@parents.concat(deps).uniq!
|
242
|
+
deps.each do |dep|
|
243
|
+
@dependency_lib.dependencies[dep].each{|d| d.add_child(@name) }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
##
|
249
|
+
# Define the uninstall command for the dependency:
|
250
|
+
#
|
251
|
+
# dep.uninstall "yum remove depname"
|
252
|
+
|
253
|
+
def uninstall cmd=nil, &block
|
254
|
+
@uninstall = cmd || block
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
##
|
259
|
+
# Run the uninstall command for the dependency
|
260
|
+
# Allows options:
|
261
|
+
# :call:: obj - an object that responds to call will be passed the bash cmd
|
262
|
+
# :force:: true - uninstalls regardless of child dependencies
|
263
|
+
# :remove_children:: true - removes direct child dependencies
|
264
|
+
# :remove_children:: :recursive - removes children recursively
|
265
|
+
|
266
|
+
def uninstall! options={}
|
267
|
+
if !options[:remove_children] && !options[:force]
|
268
|
+
raise UninstallError, "The #{@name} has child dependencies."
|
269
|
+
end
|
270
|
+
uninstall_children!(options) if options[:remove_children]
|
271
|
+
run_command(@uninstall, options)
|
272
|
+
raise(UninstallError, "Failed removing #{@name}") if installed?(options)
|
273
|
+
end
|
274
|
+
|
275
|
+
|
276
|
+
##
|
277
|
+
# Removes child dependencies
|
278
|
+
# Allows options:
|
279
|
+
# :call:: obj - an object that responds to call will be passed the bash cmd
|
280
|
+
# :force:: true - uninstalls regardless of child dependencies
|
281
|
+
# :remove_children:: true - removes direct child dependencies
|
282
|
+
# :remove_children:: :recursive - removes children recursively
|
283
|
+
|
284
|
+
def uninstall_children! options={}
|
285
|
+
return unless @dependency_lib
|
286
|
+
|
287
|
+
options = options.dup
|
288
|
+
|
289
|
+
@children.each do |dep|
|
290
|
+
options.delete(:remove_children) unless
|
291
|
+
options[:remove_children] == :recursive
|
292
|
+
|
293
|
+
@dependency_lib.get(dep, options).uninstall!(options)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
##
|
299
|
+
# Alias for name
|
300
|
+
|
301
|
+
def to_s
|
302
|
+
@name
|
303
|
+
end
|
304
|
+
|
305
|
+
|
306
|
+
private
|
307
|
+
|
308
|
+
def run_command command, options={}
|
309
|
+
shell = options[:call] || @shell
|
310
|
+
|
311
|
+
if Proc === command
|
312
|
+
command.call shell, self.class.sudo
|
313
|
+
|
314
|
+
else
|
315
|
+
shell.call command, :sudo => self.class.sudo
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
|
320
|
+
def self.short_class_name str
|
321
|
+
str.to_s.split(":").last
|
322
|
+
end
|
323
|
+
|
324
|
+
|
325
|
+
def self.underscore str
|
326
|
+
str.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
327
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
|
328
|
+
end
|
329
|
+
|
330
|
+
|
331
|
+
def self.inherited(subclass)
|
332
|
+
class_name = short_class_name subclass.to_s
|
333
|
+
method_name = underscore class_name
|
334
|
+
|
335
|
+
DependencyLib.class_eval <<-STR, __FILE__, __LINE__ + 1
|
336
|
+
def #{method_name}(name, options={}, &block)
|
337
|
+
dep = #{class_name}.new(name, options.merge(:tree => self), &block)
|
338
|
+
self.add dep
|
339
|
+
dep
|
340
|
+
end
|
341
|
+
STR
|
342
|
+
|
343
|
+
DependencyLib.dependency_types << subclass
|
344
|
+
end
|
345
|
+
|
346
|
+
inherited self
|
347
|
+
|
348
|
+
end
|
349
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
##
|
4
|
+
# The Gem dependency class supports most of rubygem's installation features:
|
5
|
+
#
|
6
|
+
# dependency_lib.instance_eval do
|
7
|
+
# gem "rdoc", :version => '~>0.8',
|
8
|
+
# :source => 'http://gemcutter.org',
|
9
|
+
# :opts => '--use-lib blah' # Anything after --
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
# See the Dependency class for more info.
|
13
|
+
|
14
|
+
class Gem < Dependency
|
15
|
+
|
16
|
+
self.sudo = true
|
17
|
+
|
18
|
+
|
19
|
+
def initialize(name, options={}, &block)
|
20
|
+
super(name, options) do
|
21
|
+
version = options[:version] ? " --version '#{options[:version]}'" : ""
|
22
|
+
|
23
|
+
source = if options[:source]
|
24
|
+
" --source #{options[:source]} --source http://gemcutter.org"
|
25
|
+
end
|
26
|
+
|
27
|
+
install_opts = " --no-ri --no-rdoc"
|
28
|
+
if options[:opts]
|
29
|
+
install_opts = "#{install_opts} -- #{options[:opts]}"
|
30
|
+
end
|
31
|
+
|
32
|
+
install "gem install #{@pkg}#{version}#{source}#{install_opts}"
|
33
|
+
uninstall "gem uninstall #{@pkg}#{version}"
|
34
|
+
check "gem list #{@pkg} -i#{version}"
|
35
|
+
|
36
|
+
requires(*options[:require].to_a) if options[:require]
|
37
|
+
|
38
|
+
instance_eval(&block) if block_given?
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def run_command(command, options={})
|
46
|
+
if @dependency_lib
|
47
|
+
@dependency_lib.install 'rubygems', options if
|
48
|
+
@dependency_lib.exist?('rubygems')
|
49
|
+
end
|
50
|
+
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Sunshine
|
2
|
+
|
3
|
+
##
|
4
|
+
# The Yum dependency class supports most of yum's installation features:
|
5
|
+
#
|
6
|
+
# dependency_lib.instance_eval do
|
7
|
+
# yum "ruby", :version => '1.9',
|
8
|
+
# :rel => 'release-num',
|
9
|
+
# :arch => 'i386',
|
10
|
+
# :epoch => 'some-epoch'
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# See the Dependency class for more info.
|
14
|
+
|
15
|
+
class Yum < Dependency
|
16
|
+
|
17
|
+
self.sudo = true
|
18
|
+
|
19
|
+
|
20
|
+
def initialize(name, options={}, &block)
|
21
|
+
super(name, options) do
|
22
|
+
pkg_name = build_pkg_name @pkg.dup, options
|
23
|
+
|
24
|
+
install "yum install -y #{pkg_name}"
|
25
|
+
uninstall "yum remove -y #{pkg_name}"
|
26
|
+
check_test "yum list installed #{pkg_name} | grep -c #{@pkg}", '-ge 1'
|
27
|
+
|
28
|
+
instance_eval(&block) if block_given?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def build_pkg_name pkg_name, options={}
|
36
|
+
if options[:version]
|
37
|
+
pkg_name << "-#{options[:version]}"
|
38
|
+
|
39
|
+
if options[:rel]
|
40
|
+
pkg_name << "-#{options[:rel]}"
|
41
|
+
|
42
|
+
pkg_name = "#{options[:epoch]}:#{pkg_name}" if
|
43
|
+
options[:arch] && options[:epoch]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
pkg_name << ".#{options[:arch]}" if options[:arch]
|
48
|
+
pkg_name
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def run_command(command, options={})
|
53
|
+
if @dependency_lib
|
54
|
+
if @dependency_lib.exist?('yum')
|
55
|
+
@dependency_lib.install 'yum', options
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
super
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|