logstash-core 1.5.0.beta2-java
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.
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
|