logstash-core 1.5.0.beta2-java
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of logstash-core might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/lib/logstash-event.rb +2 -0
- data/lib/logstash.rb +4 -0
- data/lib/logstash/JRUBY-PR1448.rb +32 -0
- data/lib/logstash/agent.rb +355 -0
- data/lib/logstash/bundler.rb +124 -0
- data/lib/logstash/codecs/base.rb +50 -0
- data/lib/logstash/config/config_ast.rb +508 -0
- data/lib/logstash/config/file.rb +39 -0
- data/lib/logstash/config/grammar.rb +3503 -0
- data/lib/logstash/config/mixin.rb +495 -0
- data/lib/logstash/config/registry.rb +13 -0
- data/lib/logstash/environment.rb +168 -0
- data/lib/logstash/errors.rb +12 -0
- data/lib/logstash/event.rb +310 -0
- data/lib/logstash/filters/base.rb +239 -0
- data/lib/logstash/gemfile.rb +175 -0
- data/lib/logstash/inputs/base.rb +137 -0
- data/lib/logstash/inputs/threadable.rb +18 -0
- data/lib/logstash/java_integration.rb +41 -0
- data/lib/logstash/json.rb +53 -0
- data/lib/logstash/logging.rb +91 -0
- data/lib/logstash/multiqueue.rb +53 -0
- data/lib/logstash/namespace.rb +17 -0
- data/lib/logstash/outputs/base.rb +124 -0
- data/lib/logstash/patches.rb +3 -0
- data/lib/logstash/patches/bugfix_jruby_2558.rb +50 -0
- data/lib/logstash/patches/cabin.rb +34 -0
- data/lib/logstash/patches/profile_require_calls.rb +47 -0
- data/lib/logstash/pipeline.rb +305 -0
- data/lib/logstash/plugin.rb +177 -0
- data/lib/logstash/pluginmanager.rb +17 -0
- data/lib/logstash/pluginmanager/install.rb +112 -0
- data/lib/logstash/pluginmanager/list.rb +38 -0
- data/lib/logstash/pluginmanager/main.rb +22 -0
- data/lib/logstash/pluginmanager/maven_tools_patch.rb +12 -0
- data/lib/logstash/pluginmanager/uninstall.rb +49 -0
- data/lib/logstash/pluginmanager/update.rb +50 -0
- data/lib/logstash/pluginmanager/util.rb +88 -0
- data/lib/logstash/program.rb +15 -0
- data/lib/logstash/runner.rb +167 -0
- data/lib/logstash/sized_queue.rb +8 -0
- data/lib/logstash/threadwatchdog.rb +37 -0
- data/lib/logstash/timestamp.rb +97 -0
- data/lib/logstash/util.rb +152 -0
- data/lib/logstash/util/accessors.rb +88 -0
- data/lib/logstash/util/buftok.rb +139 -0
- data/lib/logstash/util/charset.rb +35 -0
- data/lib/logstash/util/fieldreference.rb +68 -0
- data/lib/logstash/util/filetools.rb +185 -0
- data/lib/logstash/util/password.rb +25 -0
- data/lib/logstash/util/plugin_version.rb +43 -0
- data/lib/logstash/util/prctl.rb +11 -0
- data/lib/logstash/util/require-helper.rb +18 -0
- data/lib/logstash/util/retryable.rb +39 -0
- data/lib/logstash/util/socket_peer.rb +7 -0
- data/lib/logstash/version.rb +6 -0
- data/locales/en.yml +176 -0
- metadata +427 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1c512265bcb6873ce0def467329ba6b4a058aea5
|
4
|
+
data.tar.gz: a376414ac39751f9c4e7b67fbb109410fe4d04b8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5520cb37d6482b810ab0501e370bb08e859365d7b5e4217683fc065ecde3c859dde0f3da0c8447ff5b28ab19f9264db9cc4c8e5e5523a6a53bb8c57f3054608a
|
7
|
+
data.tar.gz: b722a0fe0d550a82adafc116bd579489f7871c633d22dce7d9724ca6617c107e09b138a92632babf75eebb704a9f2fb34022e05ed544d0b0381cfc05b4befd64
|
data/lib/logstash.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# This patch fixes a problem that exists in JRuby prior to 1.7.11 where the
|
2
|
+
# ruby binary path used by rubygems is malformed on Windows, causing
|
3
|
+
# dependencies to not install cleanly when using `.\bin\logstash.bat deps`.
|
4
|
+
# This monkeypatch can probably be removed once it's unlikely that people
|
5
|
+
# are still using JRuby older than 1.7.11.
|
6
|
+
class << Gem
|
7
|
+
def ruby
|
8
|
+
ruby_path = original_ruby
|
9
|
+
ruby_path = "java -jar #{jar_path(ruby_path)}" if jarred_path?(ruby_path)
|
10
|
+
ruby_path
|
11
|
+
end
|
12
|
+
|
13
|
+
def jarred_path?(p)
|
14
|
+
p =~ /^file:/
|
15
|
+
end
|
16
|
+
|
17
|
+
# A jar path looks like this on non-Windows platforms:
|
18
|
+
# file:/path/to/file.jar!/path/within/jar/to/file.txt
|
19
|
+
# and like this on Windows:
|
20
|
+
# file:/C:/path/to/file.jar!/path/within/jar/to/file.txt
|
21
|
+
#
|
22
|
+
# This method returns:
|
23
|
+
# /path/to/file.jar
|
24
|
+
# or
|
25
|
+
# C:/path/to/file.jar
|
26
|
+
# as appropriate.
|
27
|
+
def jar_path(p)
|
28
|
+
path = p.sub(/^file:/, "").sub(/!.*/, "")
|
29
|
+
path = path.sub(/^\//, "") if win_platform? && path =~ /^\/[A-Za-z]:/
|
30
|
+
path
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "clamp" # gem 'clamp'
|
3
|
+
require "logstash/environment"
|
4
|
+
require "logstash/errors"
|
5
|
+
require "uri"
|
6
|
+
require "net/http"
|
7
|
+
LogStash::Environment.load_locale!
|
8
|
+
|
9
|
+
class LogStash::Agent < Clamp::Command
|
10
|
+
option ["-f", "--config"], "CONFIG_PATH",
|
11
|
+
I18n.t("logstash.agent.flag.config"),
|
12
|
+
:attribute_name => :config_path
|
13
|
+
|
14
|
+
option "-e", "CONFIG_STRING",
|
15
|
+
I18n.t("logstash.agent.flag.config-string"),
|
16
|
+
:default => "", :attribute_name => :config_string
|
17
|
+
|
18
|
+
option ["-w", "--filterworkers"], "COUNT",
|
19
|
+
I18n.t("logstash.agent.flag.filterworkers"),
|
20
|
+
:attribute_name => :filter_workers, :default => 1, &:to_i
|
21
|
+
|
22
|
+
option "--watchdog-timeout", "SECONDS",
|
23
|
+
I18n.t("logstash.agent.flag.watchdog-timeout"),
|
24
|
+
:default => 10, &:to_f
|
25
|
+
|
26
|
+
option ["-l", "--log"], "FILE",
|
27
|
+
I18n.t("logstash.agent.flag.log"),
|
28
|
+
:attribute_name => :log_file
|
29
|
+
|
30
|
+
# Old support for the '-v' flag'
|
31
|
+
option "-v", :flag,
|
32
|
+
I18n.t("logstash.agent.flag.verbosity"),
|
33
|
+
:attribute_name => :verbosity, :multivalued => true
|
34
|
+
|
35
|
+
option "--quiet", :flag, I18n.t("logstash.agent.flag.quiet")
|
36
|
+
option "--verbose", :flag, I18n.t("logstash.agent.flag.verbose")
|
37
|
+
option "--debug", :flag, I18n.t("logstash.agent.flag.debug")
|
38
|
+
|
39
|
+
option ["-V", "--version"], :flag,
|
40
|
+
I18n.t("logstash.agent.flag.version")
|
41
|
+
|
42
|
+
option ["-p", "--pluginpath"] , "PATH",
|
43
|
+
I18n.t("logstash.agent.flag.pluginpath"),
|
44
|
+
:multivalued => true,
|
45
|
+
:attribute_name => :plugin_paths
|
46
|
+
|
47
|
+
option ["-t", "--configtest"], :flag,
|
48
|
+
I18n.t("logstash.agent.flag.configtest"),
|
49
|
+
:attribute_name => :config_test
|
50
|
+
|
51
|
+
# Emit a warning message.
|
52
|
+
def warn(message)
|
53
|
+
# For now, all warnings are fatal.
|
54
|
+
raise LogStash::ConfigurationError, message
|
55
|
+
end # def warn
|
56
|
+
|
57
|
+
# Emit a failure message and abort.
|
58
|
+
def fail(message)
|
59
|
+
raise LogStash::ConfigurationError, message
|
60
|
+
end # def fail
|
61
|
+
|
62
|
+
def report(message)
|
63
|
+
# Print to stdout just in case we're logging to a file
|
64
|
+
puts message
|
65
|
+
@logger.log(message) if log_file
|
66
|
+
end
|
67
|
+
|
68
|
+
# Run the agent. This method is invoked after clamp parses the
|
69
|
+
# flags given to this program.
|
70
|
+
def execute
|
71
|
+
require "logstash/pipeline"
|
72
|
+
require "cabin" # gem 'cabin'
|
73
|
+
require "logstash/plugin"
|
74
|
+
@logger = Cabin::Channel.get(LogStash)
|
75
|
+
|
76
|
+
if version?
|
77
|
+
show_version
|
78
|
+
return 0
|
79
|
+
end
|
80
|
+
|
81
|
+
# temporarily send logs to stdout as well if a --log is specified
|
82
|
+
# and stdout appears to be a tty
|
83
|
+
show_startup_errors = log_file && STDOUT.tty?
|
84
|
+
|
85
|
+
if show_startup_errors
|
86
|
+
stdout_logs = @logger.subscribe(STDOUT)
|
87
|
+
end
|
88
|
+
configure
|
89
|
+
|
90
|
+
# You must specify a config_string or config_path
|
91
|
+
if @config_string.nil? && @config_path.nil?
|
92
|
+
fail(help + "\n" + I18n.t("logstash.agent.missing-configuration"))
|
93
|
+
end
|
94
|
+
|
95
|
+
@config_string = @config_string.to_s
|
96
|
+
|
97
|
+
if @config_path
|
98
|
+
# Append the config string.
|
99
|
+
# This allows users to provide both -f and -e flags. The combination
|
100
|
+
# is rare, but useful for debugging.
|
101
|
+
@config_string = @config_string + load_config(@config_path)
|
102
|
+
else
|
103
|
+
# include a default stdin input if no inputs given
|
104
|
+
if @config_string !~ /input *{/
|
105
|
+
@config_string += "input { stdin { type => stdin } }"
|
106
|
+
end
|
107
|
+
# include a default stdout output if no outputs given
|
108
|
+
if @config_string !~ /output *{/
|
109
|
+
@config_string += "output { stdout { codec => rubydebug } }"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
begin
|
114
|
+
pipeline = LogStash::Pipeline.new(@config_string)
|
115
|
+
rescue LoadError => e
|
116
|
+
fail("Configuration problem.")
|
117
|
+
end
|
118
|
+
|
119
|
+
# Make SIGINT shutdown the pipeline.
|
120
|
+
sigint_id = Stud::trap("INT") do
|
121
|
+
@logger.warn(I18n.t("logstash.agent.sigint"))
|
122
|
+
pipeline.shutdown
|
123
|
+
end
|
124
|
+
|
125
|
+
# Make SIGTERM shutdown the pipeline.
|
126
|
+
sigterm_id = Stud::trap("TERM") do
|
127
|
+
@logger.warn(I18n.t("logstash.agent.sigterm"))
|
128
|
+
pipeline.shutdown
|
129
|
+
end
|
130
|
+
|
131
|
+
Stud::trap("HUP") do
|
132
|
+
@logger.info(I18n.t("logstash.agent.sighup"))
|
133
|
+
configure_logging(log_file)
|
134
|
+
end
|
135
|
+
|
136
|
+
pipeline.configure("filter-workers", filter_workers)
|
137
|
+
|
138
|
+
# Stop now if we are only asking for a config test.
|
139
|
+
if config_test?
|
140
|
+
report "Configuration OK"
|
141
|
+
return
|
142
|
+
end
|
143
|
+
|
144
|
+
@logger.unsubscribe(stdout_logs) if show_startup_errors
|
145
|
+
|
146
|
+
# TODO(sissel): Get pipeline completion status.
|
147
|
+
pipeline.run
|
148
|
+
return 0
|
149
|
+
rescue LogStash::ConfigurationError => e
|
150
|
+
@logger.unsubscribe(stdout_logs) if show_startup_errors
|
151
|
+
report I18n.t("logstash.agent.error", :error => e)
|
152
|
+
if !config_test?
|
153
|
+
report I18n.t("logstash.agent.configtest-flag-information")
|
154
|
+
end
|
155
|
+
return 1
|
156
|
+
rescue => e
|
157
|
+
@logger.unsubscribe(stdout_logs) if show_startup_errors
|
158
|
+
report I18n.t("oops", :error => e)
|
159
|
+
report e.backtrace if @logger.debug? || $DEBUGLIST.include?("stacktrace")
|
160
|
+
return 1
|
161
|
+
ensure
|
162
|
+
@log_fd.close if @log_fd
|
163
|
+
Stud::untrap("INT", sigint_id) unless sigint_id.nil?
|
164
|
+
Stud::untrap("TERM", sigterm_id) unless sigterm_id.nil?
|
165
|
+
end # def execute
|
166
|
+
|
167
|
+
def show_version
|
168
|
+
show_version_logstash
|
169
|
+
|
170
|
+
if [:info, :debug].include?(verbosity?) || debug? || verbose?
|
171
|
+
show_version_ruby
|
172
|
+
|
173
|
+
if RUBY_PLATFORM == "java"
|
174
|
+
show_version_java
|
175
|
+
show_version_elasticsearch
|
176
|
+
end
|
177
|
+
|
178
|
+
if [:debug].include?(verbosity?) || debug?
|
179
|
+
show_gems
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end # def show_version
|
183
|
+
|
184
|
+
def show_version_logstash
|
185
|
+
require "logstash/version"
|
186
|
+
puts "logstash #{LOGSTASH_VERSION}"
|
187
|
+
end # def show_version_logstash
|
188
|
+
|
189
|
+
def show_version_ruby
|
190
|
+
puts RUBY_DESCRIPTION
|
191
|
+
end # def show_version_ruby
|
192
|
+
|
193
|
+
def show_version_elasticsearch
|
194
|
+
LogStash::Environment.load_elasticsearch_jars!
|
195
|
+
|
196
|
+
$stdout.write("Elasticsearch: ");
|
197
|
+
org.elasticsearch.Version::main([])
|
198
|
+
end # def show_version_elasticsearch
|
199
|
+
|
200
|
+
def show_version_java
|
201
|
+
properties = java.lang.System.getProperties
|
202
|
+
puts "java #{properties["java.version"]} (#{properties["java.vendor"]})"
|
203
|
+
puts "jvm #{properties["java.vm.name"]} / #{properties["java.vm.version"]}"
|
204
|
+
end # def show_version_java
|
205
|
+
|
206
|
+
def show_gems
|
207
|
+
require "rubygems"
|
208
|
+
Gem::Specification.each do |spec|
|
209
|
+
puts "gem #{spec.name} #{spec.version}"
|
210
|
+
end
|
211
|
+
end # def show_gems
|
212
|
+
|
213
|
+
# Do any start-time configuration.
|
214
|
+
#
|
215
|
+
# Log file stuff, plugin path checking, etc.
|
216
|
+
def configure
|
217
|
+
configure_logging(log_file)
|
218
|
+
configure_plugin_path(plugin_paths) if !plugin_paths.nil?
|
219
|
+
end # def configure
|
220
|
+
|
221
|
+
# Point logging at a specific path.
|
222
|
+
def configure_logging(path)
|
223
|
+
# Set with the -v (or -vv...) flag
|
224
|
+
if quiet?
|
225
|
+
@logger.level = :error
|
226
|
+
elsif verbose?
|
227
|
+
@logger.level = :info
|
228
|
+
elsif debug?
|
229
|
+
@logger.level = :debug
|
230
|
+
else
|
231
|
+
# Old support for the -v and -vv stuff.
|
232
|
+
if verbosity? && verbosity?.any?
|
233
|
+
# this is an array with length of how many times the flag is given
|
234
|
+
if verbosity?.length == 1
|
235
|
+
@logger.warn("The -v flag is deprecated and will be removed in a future release. You should use --verbose instead.")
|
236
|
+
@logger.level = :info
|
237
|
+
else
|
238
|
+
@logger.warn("The -vv flag is deprecated and will be removed in a future release. You should use --debug instead.")
|
239
|
+
@logger.level = :debug
|
240
|
+
end
|
241
|
+
else
|
242
|
+
@logger.level = :warn
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
if log_file
|
248
|
+
# TODO(sissel): Implement file output/rotation in Cabin.
|
249
|
+
# TODO(sissel): Catch exceptions, report sane errors.
|
250
|
+
begin
|
251
|
+
@log_fd.close if @log_fd
|
252
|
+
@log_fd = File.new(path, "a")
|
253
|
+
rescue => e
|
254
|
+
fail(I18n.t("logstash.agent.configuration.log_file_failed",
|
255
|
+
:path => path, :error => e))
|
256
|
+
end
|
257
|
+
|
258
|
+
puts "Sending logstash logs to #{path}."
|
259
|
+
@logger.unsubscribe(@logger_subscription) if @logger_subscription
|
260
|
+
@logger_subscription = @logger.subscribe(@log_fd)
|
261
|
+
else
|
262
|
+
@logger.subscribe(STDOUT)
|
263
|
+
end
|
264
|
+
|
265
|
+
# TODO(sissel): redirect stdout/stderr to the log as well
|
266
|
+
# http://jira.codehaus.org/browse/JRUBY-7003
|
267
|
+
end # def configure_logging
|
268
|
+
|
269
|
+
# Validate and add any paths to the list of locations
|
270
|
+
# logstash will look to find plugins.
|
271
|
+
def configure_plugin_path(paths)
|
272
|
+
# Append any plugin paths to the ruby search path
|
273
|
+
paths.each do |path|
|
274
|
+
# Verify the path exists
|
275
|
+
if !Dir.exists?(path)
|
276
|
+
warn(I18n.t("logstash.agent.configuration.plugin_path_missing",
|
277
|
+
:path => path))
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
# TODO(sissel): Verify the path looks like the correct form.
|
282
|
+
# aka, there must be file in path/logstash/{inputs,codecs,filters,outputs}/*.rb
|
283
|
+
plugin_glob = File.join(path, "logstash", "{inputs,codecs,filters,outputs}", "*.rb")
|
284
|
+
if Dir.glob(plugin_glob).empty?
|
285
|
+
@logger.warn(I18n.t("logstash.agent.configuration.no_plugins_found",
|
286
|
+
:path => path, :plugin_glob => plugin_glob))
|
287
|
+
end
|
288
|
+
|
289
|
+
# We push plugin paths to the front of the LOAD_PATH so that folks
|
290
|
+
# can override any core logstash plugins if they need to.
|
291
|
+
@logger.debug("Adding plugin path", :path => path)
|
292
|
+
$LOAD_PATH.unshift(path)
|
293
|
+
end
|
294
|
+
end # def configure_plugin_path
|
295
|
+
|
296
|
+
def load_config(path)
|
297
|
+
begin
|
298
|
+
uri = URI.parse(path)
|
299
|
+
|
300
|
+
case uri.scheme
|
301
|
+
when nil then
|
302
|
+
local_config(path)
|
303
|
+
when /http/ then
|
304
|
+
fetch_config(uri)
|
305
|
+
when "file" then
|
306
|
+
local_config(uri.path)
|
307
|
+
else
|
308
|
+
fail(I18n.t("logstash.agent.configuration.scheme-not-supported", :path => path))
|
309
|
+
end
|
310
|
+
rescue URI::InvalidURIError
|
311
|
+
# fallback for windows.
|
312
|
+
# if the parsing of the file failed we assume we can reach it locally.
|
313
|
+
# some relative path on windows arent parsed correctly (.\logstash.conf)
|
314
|
+
local_config(path)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
def local_config(path)
|
319
|
+
path = File.expand_path(path)
|
320
|
+
path = File.join(path, "*") if File.directory?(path)
|
321
|
+
|
322
|
+
if Dir.glob(path).length == 0
|
323
|
+
fail(I18n.t("logstash.agent.configuration.file-not-found", :path => path))
|
324
|
+
end
|
325
|
+
|
326
|
+
config = ""
|
327
|
+
encoding_issue_files = []
|
328
|
+
Dir.glob(path).sort.each do |file|
|
329
|
+
next unless File.file?(file)
|
330
|
+
if file.match(/~$/)
|
331
|
+
@logger.debug("NOT reading config file because it is a temp file", :file => file)
|
332
|
+
next
|
333
|
+
end
|
334
|
+
@logger.debug("Reading config file", :file => file)
|
335
|
+
cfg = File.read(file)
|
336
|
+
if !cfg.ascii_only? && !cfg.valid_encoding?
|
337
|
+
encoding_issue_files << file
|
338
|
+
end
|
339
|
+
config << cfg + "\n"
|
340
|
+
end
|
341
|
+
if (encoding_issue_files.any?)
|
342
|
+
fail("The following config files contains non-ascii characters but are not UTF-8 encoded #{encoding_issue_files}")
|
343
|
+
end
|
344
|
+
return config
|
345
|
+
end # def load_config
|
346
|
+
|
347
|
+
def fetch_config(uri)
|
348
|
+
begin
|
349
|
+
Net::HTTP.get(uri) + "\n"
|
350
|
+
rescue Exception => e
|
351
|
+
fail(I18n.t("logstash.agent.configuration.fetch-failed", :path => uri.to_s, :message => e.message))
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
end # class LogStash::Agent
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require "bundler"
|
2
|
+
require "bundler/cli"
|
3
|
+
|
4
|
+
module Bundler
|
5
|
+
# Patch bundler to write a .lock file specific to the version of ruby.
|
6
|
+
# This keeps MRI/JRuby/RBX from conflicting over the Gemfile.lock updates
|
7
|
+
module SharedHelpers
|
8
|
+
def default_lockfile
|
9
|
+
ruby = "#{LogStash::Environment.ruby_engine}-#{LogStash::Environment.ruby_abi_version}"
|
10
|
+
Pathname.new("#{default_gemfile}.#{ruby}.lock")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add the Bundler.reset! method which has been added in master but is not in 1.7.9.
|
15
|
+
class << self
|
16
|
+
unless self.method_defined?("reset!")
|
17
|
+
def reset!
|
18
|
+
@definition = nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def reset_settings
|
23
|
+
# reset!
|
24
|
+
# clear_gemspec_cache
|
25
|
+
|
26
|
+
# remove_instance_variable(:@setup) if defined?(@setup)
|
27
|
+
# remove_instance_variable(:@locked_gems) if defined?(@locked_gems)
|
28
|
+
# remove_instance_variable(:@load) if defined?(@load)
|
29
|
+
remove_instance_variable(:@settings) if defined?(@settings)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module LogStash
|
35
|
+
module Bundler
|
36
|
+
|
37
|
+
# capture any $stdout from the passed block. also trap any exception in that block, in which case the trapped exception will be returned
|
38
|
+
# @param [Proc] the code block to execute
|
39
|
+
# @return [String, Exception] the captured $stdout string and any trapped exception or nil if none
|
40
|
+
def self.capture_stdout(&block)
|
41
|
+
old_stdout = $stdout
|
42
|
+
$stdout = StringIO.new("", "w")
|
43
|
+
begin
|
44
|
+
block.call
|
45
|
+
rescue => e
|
46
|
+
return [$stdout.string, e]
|
47
|
+
end
|
48
|
+
|
49
|
+
[$stdout.string, nil]
|
50
|
+
ensure
|
51
|
+
$stdout = old_stdout
|
52
|
+
end
|
53
|
+
|
54
|
+
# execute bundle install and capture any $stdout output. any raised exception in the process will be trapped
|
55
|
+
# and returned. logs errors to $stdout.
|
56
|
+
# @param options [Hash] invoke options with default values, :max_tries => 10, :clean => false, :install => false, :update => false
|
57
|
+
# @param options[:update] must be either false or a String or an Array of String
|
58
|
+
# @return [String, Exception] the installation captured output and any raised exception or nil if none
|
59
|
+
def self.invoke_bundler!(options = {})
|
60
|
+
options = {:max_tries => 10, :clean => false, :install => false, :update => false, :without => [:development]}.merge(options)
|
61
|
+
options[:without] = Array(options[:without])
|
62
|
+
options[:update] = Array(options[:update]) if options[:update]
|
63
|
+
|
64
|
+
ENV["GEM_PATH"] = LogStash::Environment.logstash_gem_home
|
65
|
+
ENV["BUNDLE_PATH"] = LogStash::Environment::BUNDLE_DIR
|
66
|
+
ENV["BUNDLE_GEMFILE"] = LogStash::Environment::GEMFILE_PATH
|
67
|
+
ENV["BUNDLE_WITHOUT"] = options[:without].join(":")
|
68
|
+
|
69
|
+
try = 0
|
70
|
+
|
71
|
+
# capture_stdout also traps any raised exception and pass them back as the function return [output, exception]
|
72
|
+
capture_stdout do
|
73
|
+
loop do
|
74
|
+
begin
|
75
|
+
::Bundler.reset!
|
76
|
+
::Bundler::CLI.start(bundler_arguments(options))
|
77
|
+
break
|
78
|
+
rescue ::Bundler::VersionConflict => e
|
79
|
+
$stderr.puts("Plugin version conflict, aborting")
|
80
|
+
raise(e)
|
81
|
+
rescue ::Bundler::GemNotFound => e
|
82
|
+
$stderr.puts("Plugin not found, aborting")
|
83
|
+
raise(e)
|
84
|
+
rescue => e
|
85
|
+
if try >= options[:max_tries]
|
86
|
+
$stderr.puts("Too many retries, aborting, caused by #{e.class}")
|
87
|
+
$stderr.puts(e.message) if ENV["DEBUG"]
|
88
|
+
raise(e)
|
89
|
+
end
|
90
|
+
|
91
|
+
try += 1
|
92
|
+
$stderr.puts("Error #{e.class}, retrying #{try}/#{options[:max_tries]}")
|
93
|
+
$stderr.puts(e.message) if ENV["DEBUG"]
|
94
|
+
sleep(0.5)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# build Bundler::CLI.start arguments array from the given options hash
|
101
|
+
# @param option [Hash] the invoke_bundler! options hash
|
102
|
+
# @return [Array<String>] Bundler::CLI.start string arguments array
|
103
|
+
def self.bundler_arguments(options = {})
|
104
|
+
arguments = []
|
105
|
+
|
106
|
+
if options[:install]
|
107
|
+
arguments << "install"
|
108
|
+
arguments << "--gemfile=#{LogStash::Environment::GEMFILE_PATH}"
|
109
|
+
arguments << ["--path", LogStash::Environment::BUNDLE_DIR]
|
110
|
+
# note that generating "--without=" when options[:without] is empty is intended
|
111
|
+
arguments << "--without=#{options[:without].join(' ')}"
|
112
|
+
end
|
113
|
+
|
114
|
+
if options[:update]
|
115
|
+
arguments << "update"
|
116
|
+
arguments << options[:update]
|
117
|
+
end
|
118
|
+
|
119
|
+
arguments << "--clean" if options[:clean]
|
120
|
+
|
121
|
+
arguments.flatten
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|