mongrel_cluster 0.1
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/COPYING +20 -0
- data/LICENSE +20 -0
- data/README +17 -0
- data/Rakefile +38 -0
- data/lib/mongrel_cluster/init.rb +197 -0
- data/resources/defaults.yaml +2 -0
- data/tools/rakehelp.rb +105 -0
- metadata +69 -0
data/COPYING
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006 Bradley Taylor, bradley@railsmachine.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2006 Bradley Taylor, bradley@railsmachine.com
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
== Mongrel Cluster Plugin
|
2
|
+
|
3
|
+
Tool to help start/stop/restart multiple mongrel servers to use behind a load balancer like Pound or Balance. This plugin adds an option to specify a number of Mongrel servers to launch, a range of ports, and a configuration file for the cluster. Use "-h" to see command syntax.
|
4
|
+
|
5
|
+
Configure cluster and write configuration file:
|
6
|
+
mongrel_rails cluster::configure
|
7
|
+
|
8
|
+
Start cluster:
|
9
|
+
mongrel_rails cluster::start
|
10
|
+
|
11
|
+
Restart cluster:
|
12
|
+
mongrel_rails cluster::restart
|
13
|
+
|
14
|
+
Stop cluster:
|
15
|
+
mongrel_rails cluster::stop
|
16
|
+
|
17
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'tools/rakehelp'
|
7
|
+
require 'fileutils'
|
8
|
+
include FileUtils
|
9
|
+
|
10
|
+
setup_tests
|
11
|
+
setup_clean ["pkg", "lib/*.bundle", "*.gem", ".config"]
|
12
|
+
|
13
|
+
setup_rdoc ['README', 'LICENSE', 'COPYING', 'lib/**/*.rb', 'doc/**/*.rdoc']
|
14
|
+
|
15
|
+
desc "Does a full compile, test run"
|
16
|
+
task :default => [:test, :package]
|
17
|
+
|
18
|
+
version="0.1"
|
19
|
+
name="mongrel_cluster"
|
20
|
+
|
21
|
+
setup_gem(name, version) do |spec|
|
22
|
+
spec.summary = "The mongrel_cluster GemPlugin"
|
23
|
+
spec.description = spec.summary
|
24
|
+
spec.author="Bradley Taylor"
|
25
|
+
spec.add_dependency('gem_plugin', '>= 0.2.1')
|
26
|
+
spec.add_dependency('mongrel', '>= 0.3.12.2')
|
27
|
+
spec.files += Dir.glob("resources/**/*")
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
task :install => [:test, :package] do
|
32
|
+
sh %{sudo gem install pkg/#{name}-#{version}.gem}
|
33
|
+
end
|
34
|
+
|
35
|
+
task :uninstall => [:clean] do
|
36
|
+
sh %{sudo gem uninstall #{name}}
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require 'gem_plugin'
|
2
|
+
require 'mongrel'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Cluster
|
6
|
+
|
7
|
+
class Start < GemPlugin::Plugin "/commands"
|
8
|
+
include Mongrel::Command::Base
|
9
|
+
|
10
|
+
def configure
|
11
|
+
options [['-C', '--config PATH', "Path to configuraion file", :@config_file, "config/mongrel_cluster.yml"]]
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate
|
15
|
+
valid_exists?(@config_file, "Configuration file does not exist. Run mongrel_rails cluster::configure.")
|
16
|
+
return @valid
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
@options = {
|
21
|
+
"environment" => ENV['RAILS_ENV'] || "development",
|
22
|
+
"port" => 3000,
|
23
|
+
"address" => "0.0.0.0",
|
24
|
+
"log_file" => "log/mongrel.log",
|
25
|
+
"pid_file" => "log/mongrel.pid",
|
26
|
+
"servers" => 2
|
27
|
+
}
|
28
|
+
|
29
|
+
@conf_options = YAML.load_file(@config_file)
|
30
|
+
@options.merge! @conf_options if @conf_options
|
31
|
+
port = @options["port"].to_i - 1
|
32
|
+
pid = @options["pid_file"].split(".")
|
33
|
+
puts "Starting #{@options["servers"]} Mongrel servers..."
|
34
|
+
1.upto(@options["servers"].to_i) do |i|
|
35
|
+
argv = [ "mongrel_rails" ]
|
36
|
+
argv << "start"
|
37
|
+
argv << "-d"
|
38
|
+
argv << "-e #{@options["environment"]}"
|
39
|
+
argv << "-p #{port+i}"
|
40
|
+
argv << "-a #{@options["address"]}"
|
41
|
+
argv << "-l #{@options["log_file"]}"
|
42
|
+
argv << "-P #{pid[0]}-#{i}.#{pid[1]}"
|
43
|
+
argv << "-c #{@options["cwd"]}"
|
44
|
+
argv << "-t #{@options["timeout"]}"
|
45
|
+
argv << "-m #{@options["mime_map"]}" if @options["mime_map"]
|
46
|
+
argv << "-r #{@options["docroot"]}"
|
47
|
+
argv << "-n #{@options["num-procs"]}"
|
48
|
+
argv << "-B" if @options["debug"]
|
49
|
+
argv << "-S #{@options["config_script"]}" if @options["config_script"]
|
50
|
+
cmd = argv.join " "
|
51
|
+
puts cmd
|
52
|
+
status = `#{cmd}`
|
53
|
+
puts status
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Stop < GemPlugin::Plugin "/commands"
|
59
|
+
include Mongrel::Command::Base
|
60
|
+
|
61
|
+
def configure
|
62
|
+
options [
|
63
|
+
['-C', '--config PATH', "Path to config file", :@config_file, "config/mongrel_cluster.yml"],
|
64
|
+
['-f', '--force', "Force the shutdown.", :@force, false]
|
65
|
+
]
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate
|
69
|
+
valid_exists?(@config_file, "Configuration file does not exist. Run mongrel_rails cluster::configure.")
|
70
|
+
return @valid
|
71
|
+
end
|
72
|
+
|
73
|
+
def run
|
74
|
+
@options = {
|
75
|
+
"environment" => ENV['RAILS_ENV'] || "development",
|
76
|
+
"port" => 3000,
|
77
|
+
"address" => "0.0.0.0",
|
78
|
+
"log_file" => "log/mongrel.log",
|
79
|
+
"pid_file" => "log/mongrel.pid",
|
80
|
+
"servers" => 2
|
81
|
+
}
|
82
|
+
|
83
|
+
@conf_options = YAML.load_file(@config_file)
|
84
|
+
@options.merge! @conf_options if @conf_options
|
85
|
+
pid = @options["pid_file"].split(".")
|
86
|
+
puts "Stopping #{@options["servers"]} Mongrel servers..."
|
87
|
+
1.upto(@options["servers"].to_i) do |i|
|
88
|
+
cmd = "mongrel_rails stop -P #{pid[0]}-#{i}.#{pid[1]} -c #{@options["cwd"]} #{"-f" if @force }"
|
89
|
+
puts cmd
|
90
|
+
status = `#{cmd}`
|
91
|
+
puts status
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Restart < GemPlugin::Plugin "/commands"
|
97
|
+
include Mongrel::Command::Base
|
98
|
+
|
99
|
+
def configure
|
100
|
+
options [
|
101
|
+
['-C', '--config PATH', "Path to config file", :@config_file, "config/mongrel_cluster.yml"],
|
102
|
+
['-s', '--soft', "Do a soft restart rather than a process exit restart", :@soft, false]
|
103
|
+
]
|
104
|
+
end
|
105
|
+
|
106
|
+
def validate
|
107
|
+
valid_exists?(@config_file, "Configuration file does not exist. Run mongrel_rails cluster::configure.")
|
108
|
+
return @valid
|
109
|
+
end
|
110
|
+
|
111
|
+
def run
|
112
|
+
@options = {
|
113
|
+
"environment" => ENV['RAILS_ENV'] || "development",
|
114
|
+
"port" => 3000,
|
115
|
+
"address" => "0.0.0.0",
|
116
|
+
"log_file" => "log/mongrel.log",
|
117
|
+
"pid_file" => "log/mongrel.pid",
|
118
|
+
"servers" => 2
|
119
|
+
}
|
120
|
+
|
121
|
+
@conf_options = YAML.load_file(@config_file)
|
122
|
+
@options.merge! @conf_options if @conf_options
|
123
|
+
pid = @options["pid_file"].split(".")
|
124
|
+
puts "Restarting #{@options["servers"]} Mongrel servers..."
|
125
|
+
1.upto(@options["servers"].to_i) do |i|
|
126
|
+
cmd = "mongrel_rails restart -P #{pid[0]}-#{i}.#{pid[1]} -c #{@options["cwd"]} #{"-s" if @soft }"
|
127
|
+
puts cmd
|
128
|
+
status = `#{cmd}`
|
129
|
+
puts status
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class Configure < GemPlugin::Plugin "/commands"
|
135
|
+
include Mongrel::Command::Base
|
136
|
+
|
137
|
+
def configure
|
138
|
+
options [
|
139
|
+
["-e", "--environment ENV", "Rails environment to run as", :@environment, ENV['RAILS_ENV'] || "development"],
|
140
|
+
['-p', '--port PORT', "Starting port to bind to", :@port, 3000],
|
141
|
+
['-a', '--address ADDR', "Address to bind to", :@address, "0.0.0.0"],
|
142
|
+
['-l', '--log FILE', "Where to write log messages", :@log_file, "log/mongrel.log"],
|
143
|
+
['-P', '--pid FILE', "Where to write the PID", :@pid_file, "log/mongrel.pid"],
|
144
|
+
['-c', '--chdir PATH', "Change to dir before starting (will be expanded)", :@cwd, Dir.pwd],
|
145
|
+
['-t', '--timeout SECONDS', "Timeout all requests after SECONDS time", :@timeout, 120],
|
146
|
+
['-m', '--mime PATH', "A YAML file that lists additional MIME types", :@mime_map, nil],
|
147
|
+
['-r', '--root PATH', "Set the document root (default 'public')", :@docroot, "public"],
|
148
|
+
['-n', '--num-procs INT', "Number of processor threads to use", :@num_procs, 1024],
|
149
|
+
['-B', '--debug', "Enable debugging mode", :@debug, false],
|
150
|
+
['-S', '--script PATH', "Load the given file as an extra config script.", :@config_script, nil],
|
151
|
+
['-N', '--num-servers INT', "Number of Mongrel servers", :@servers, 2],
|
152
|
+
['-C', '--config PATH', "Path to config file", :@config_file, "config/mongrel_cluster.yml"]
|
153
|
+
]
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate
|
157
|
+
@servers = @servers.to_i
|
158
|
+
@port = @port.to_i
|
159
|
+
@timeout = @timeout.to_i
|
160
|
+
|
161
|
+
@cwd = File.expand_path(@cwd)
|
162
|
+
valid_dir? @cwd, "Invalid path to change to during daemon mode: #{@cwd}"
|
163
|
+
valid?(@servers > 0, "Must give a valid number of servers")
|
164
|
+
valid?(@port > 0, "Must give a valid starting port")
|
165
|
+
valid?(@timeout > 0, "Must give a valid timeout for requests")
|
166
|
+
|
167
|
+
valid_dir? File.dirname(@log_file), "Path to log file not valid: #{@log_file}"
|
168
|
+
valid_dir? File.dirname(@pid_file), "Path to pid file not valid: #{@pid_file}"
|
169
|
+
valid_dir? File.dirname(@config_file), "Path to config file not valid: #{@config_file}"
|
170
|
+
|
171
|
+
valid_dir? File.dirname(@docroot), "Path to docroot not valid: #{@docroot}"
|
172
|
+
valid_exists? @mime_map, "MIME mapping file does not exist: #{@mime_map}" if @mime_map
|
173
|
+
|
174
|
+
return @valid
|
175
|
+
end
|
176
|
+
|
177
|
+
def run
|
178
|
+
@options = {
|
179
|
+
"environment" => @environment,
|
180
|
+
"port" => @port,
|
181
|
+
"address" => @address,
|
182
|
+
"log_file" => @log_file,
|
183
|
+
"pid_file" => @pid_file,
|
184
|
+
"servers" => @servers,
|
185
|
+
"cwd" => @cwd,
|
186
|
+
"timeout" => @timeout,
|
187
|
+
"mime_map" => @mime_map,
|
188
|
+
"docroot" => @docroot,
|
189
|
+
"debug" => @debug,
|
190
|
+
"config_script" => @config_script,
|
191
|
+
"num-procs" => @num_procs
|
192
|
+
}
|
193
|
+
puts "Writing configuration file to #{@config_file}."
|
194
|
+
File.open(@config_file,"w") {|f| f.write(@options.to_yaml)}
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
data/tools/rakehelp.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
def make(makedir)
|
3
|
+
Dir.chdir(makedir) do
|
4
|
+
sh(PLATFORM =~ /win32/ ? 'nmake' : 'make')
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
def extconf(dir)
|
10
|
+
Dir.chdir(dir) do ruby "extconf.rb" end
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def setup_tests
|
15
|
+
Rake::TestTask.new do |t|
|
16
|
+
t.libs << "test"
|
17
|
+
t.test_files = FileList['test/test*.rb']
|
18
|
+
t.verbose = true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def setup_clean otherfiles
|
24
|
+
files = ['build/*', '**/*.o', '**/*.so', '**/*.a', 'lib/*-*', '**/*.log'] + otherfiles
|
25
|
+
CLEAN.include(files)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def setup_rdoc files
|
30
|
+
Rake::RDocTask.new do |rdoc|
|
31
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
32
|
+
rdoc.options << '--line-numbers'
|
33
|
+
rdoc.rdoc_files.add(files)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def setup_extension(dir, extension)
|
39
|
+
ext = "ext/#{dir}"
|
40
|
+
ext_so = "#{ext}/#{extension}.#{Config::CONFIG['DLEXT']}"
|
41
|
+
ext_files = FileList[
|
42
|
+
"#{ext}/*.c",
|
43
|
+
"#{ext}/*.h",
|
44
|
+
"#{ext}/extconf.rb",
|
45
|
+
"#{ext}/Makefile",
|
46
|
+
"lib"
|
47
|
+
]
|
48
|
+
|
49
|
+
task "lib" do
|
50
|
+
directory "lib"
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "Builds just the #{extension} extension"
|
54
|
+
task extension.to_sym => ["#{ext}/Makefile", ext_so ]
|
55
|
+
|
56
|
+
file "#{ext}/Makefile" => ["#{ext}/extconf.rb"] do
|
57
|
+
extconf "#{ext}"
|
58
|
+
end
|
59
|
+
|
60
|
+
file ext_so => ext_files do
|
61
|
+
make "#{ext}"
|
62
|
+
cp ext_so, "lib"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def base_gem_spec(pkg_name, pkg_version)
|
68
|
+
pkg_version = pkg_version
|
69
|
+
pkg_name = pkg_name
|
70
|
+
pkg_file_name = "#{pkg_name}-#{pkg_version}"
|
71
|
+
Gem::Specification.new do |s|
|
72
|
+
s.name = pkg_name
|
73
|
+
s.version = pkg_version
|
74
|
+
s.platform = Gem::Platform::RUBY
|
75
|
+
s.has_rdoc = true
|
76
|
+
s.extra_rdoc_files = [ "README" ]
|
77
|
+
|
78
|
+
s.files = %w(COPYING LICENSE README Rakefile) +
|
79
|
+
Dir.glob("{bin,doc/rdoc,test,lib}/**/*") +
|
80
|
+
Dir.glob("ext/**/*.{h,c,rb}") +
|
81
|
+
Dir.glob("examples/**/*.rb") +
|
82
|
+
Dir.glob("tools/*.rb")
|
83
|
+
|
84
|
+
s.require_path = "lib"
|
85
|
+
s.extensions = FileList["ext/**/extconf.rb"].to_a
|
86
|
+
s.bindir = "bin"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def setup_gem(pkg_name, pkg_version)
|
91
|
+
spec = base_gem_spec(pkg_name, pkg_version)
|
92
|
+
yield spec if block_given?
|
93
|
+
|
94
|
+
Rake::GemPackageTask.new(spec) do |p|
|
95
|
+
p.gem_spec = spec
|
96
|
+
p.need_tar = true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def setup_win32_gem(pkg_name, pkg_version)
|
101
|
+
spec = base_gem_spec(pkg_name, pkg_version)
|
102
|
+
yield spec if block_given?
|
103
|
+
|
104
|
+
Gem::Builder.new(spec).build
|
105
|
+
end
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: mongrel_cluster
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: "0.1"
|
7
|
+
date: 2006-04-24 00:00:00 -04:00
|
8
|
+
summary: The mongrel_cluster GemPlugin
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email:
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description: The mongrel_cluster GemPlugin
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- Bradley Taylor
|
30
|
+
files:
|
31
|
+
- COPYING
|
32
|
+
- LICENSE
|
33
|
+
- README
|
34
|
+
- Rakefile
|
35
|
+
- lib/mongrel_cluster
|
36
|
+
- lib/mongrel_cluster/init.rb
|
37
|
+
- tools/rakehelp.rb
|
38
|
+
- resources/defaults.yaml
|
39
|
+
test_files: []
|
40
|
+
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
extra_rdoc_files:
|
44
|
+
- README
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
dependencies:
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: gem_plugin
|
54
|
+
version_requirement:
|
55
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 0.2.1
|
60
|
+
version:
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: mongrel
|
63
|
+
version_requirement:
|
64
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.3.12.2
|
69
|
+
version:
|