logstash-core 5.6.16-java → 6.0.0.alpha1-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.
- checksums.yaml +4 -4
- data/gemspec_jars.rb +4 -7
- data/lib/logstash-core/logstash-core.jar +0 -0
- data/lib/logstash-core/version.rb +4 -8
- data/lib/logstash-core_jars.rb +12 -26
- data/lib/logstash/agent.rb +261 -246
- data/lib/logstash/api/commands/default_metadata.rb +1 -1
- data/lib/logstash/api/commands/hot_threads_reporter.rb +5 -11
- data/lib/logstash/api/commands/node.rb +3 -2
- data/lib/logstash/api/commands/stats.rb +3 -2
- data/lib/logstash/bootstrap_check/bad_java.rb +16 -0
- data/lib/logstash/bootstrap_check/bad_ruby.rb +12 -0
- data/lib/logstash/bootstrap_check/default_config.rb +17 -0
- data/lib/logstash/compiler.rb +38 -0
- data/lib/logstash/compiler/lscl.rb +566 -0
- data/lib/logstash/compiler/lscl/lscl_grammar.rb +3503 -0
- data/lib/logstash/compiler/treetop_monkeypatches.rb +92 -0
- data/lib/logstash/config/config_ast.rb +4 -82
- data/lib/logstash/config/mixin.rb +73 -41
- data/lib/logstash/config/pipeline_config.rb +48 -0
- data/lib/logstash/config/source/base.rb +16 -0
- data/lib/logstash/config/source/local.rb +215 -0
- data/lib/logstash/config/source_loader.rb +125 -0
- data/lib/logstash/converge_result.rb +103 -0
- data/lib/logstash/environment.rb +6 -19
- data/lib/logstash/errors.rb +2 -0
- data/lib/logstash/execution_context.rb +4 -7
- data/lib/logstash/filter_delegator.rb +6 -9
- data/lib/logstash/inputs/base.rb +0 -2
- data/lib/logstash/instrument/collector.rb +5 -7
- data/lib/logstash/instrument/metric_store.rb +12 -12
- data/lib/logstash/instrument/metric_type/mean.rb +0 -5
- data/lib/logstash/instrument/namespaced_metric.rb +0 -4
- data/lib/logstash/instrument/namespaced_null_metric.rb +0 -4
- data/lib/logstash/instrument/null_metric.rb +0 -10
- data/lib/logstash/instrument/periodic_poller/cgroup.rb +85 -168
- data/lib/logstash/instrument/periodic_poller/jvm.rb +5 -5
- data/lib/logstash/instrument/periodic_poller/pq.rb +3 -7
- data/lib/logstash/instrument/periodic_pollers.rb +1 -3
- data/lib/logstash/instrument/wrapped_write_client.rb +24 -33
- data/lib/logstash/logging/logger.rb +15 -47
- data/lib/logstash/namespace.rb +0 -1
- data/lib/logstash/output_delegator.rb +5 -7
- data/lib/logstash/outputs/base.rb +0 -2
- data/lib/logstash/pipeline.rb +159 -87
- data/lib/logstash/pipeline_action.rb +13 -0
- data/lib/logstash/pipeline_action/base.rb +29 -0
- data/lib/logstash/pipeline_action/create.rb +47 -0
- data/lib/logstash/pipeline_action/reload.rb +48 -0
- data/lib/logstash/pipeline_action/stop.rb +23 -0
- data/lib/logstash/plugin.rb +0 -1
- data/lib/logstash/plugins/hooks_registry.rb +6 -0
- data/lib/logstash/plugins/registry.rb +0 -1
- data/lib/logstash/program.rb +14 -0
- data/lib/logstash/queue_factory.rb +5 -1
- data/lib/logstash/runner.rb +58 -80
- data/lib/logstash/settings.rb +3 -27
- data/lib/logstash/state_resolver.rb +41 -0
- data/lib/logstash/util/java_version.rb +6 -0
- data/lib/logstash/util/safe_uri.rb +12 -148
- data/lib/logstash/util/thread_dump.rb +4 -7
- data/lib/logstash/util/wrapped_acked_queue.rb +36 -39
- data/lib/logstash/util/wrapped_synchronous_queue.rb +29 -39
- data/lib/logstash/version.rb +10 -8
- data/locales/en.yml +3 -54
- data/logstash-core.gemspec +8 -35
- data/spec/{logstash/api/modules → api/lib/api}/logging_spec.rb +10 -1
- data/spec/{logstash/api/modules → api/lib/api}/node_plugins_spec.rb +2 -1
- data/spec/{logstash/api/modules → api/lib/api}/node_spec.rb +3 -3
- data/spec/{logstash/api/modules → api/lib/api}/node_stats_spec.rb +3 -7
- data/spec/{logstash/api/modules → api/lib/api}/plugins_spec.rb +3 -4
- data/spec/{logstash/api/modules → api/lib/api}/root_spec.rb +2 -2
- data/spec/api/lib/api/support/resource_dsl_methods.rb +87 -0
- data/spec/{logstash/api/commands/stats_spec.rb → api/lib/commands/stats.rb} +2 -7
- data/spec/{logstash/api → api/lib}/errors_spec.rb +1 -1
- data/spec/{logstash/api → api/lib}/rack_app_spec.rb +0 -0
- data/spec/api/spec_helper.rb +106 -0
- data/spec/logstash/agent/converge_spec.rb +286 -0
- data/spec/logstash/agent/metrics_spec.rb +244 -0
- data/spec/logstash/agent_spec.rb +213 -225
- data/spec/logstash/compiler/compiler_spec.rb +584 -0
- data/spec/logstash/config/config_ast_spec.rb +8 -47
- data/spec/logstash/config/mixin_spec.rb +2 -42
- data/spec/logstash/config/pipeline_config_spec.rb +75 -0
- data/spec/logstash/config/source/local_spec.rb +395 -0
- data/spec/logstash/config/source_loader_spec.rb +122 -0
- data/spec/logstash/converge_result_spec.rb +179 -0
- data/spec/logstash/event_spec.rb +0 -66
- data/spec/logstash/execution_context_spec.rb +8 -12
- data/spec/logstash/filter_delegator_spec.rb +12 -24
- data/spec/logstash/inputs/base_spec.rb +7 -5
- data/spec/logstash/instrument/periodic_poller/cgroup_spec.rb +92 -225
- data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +1 -1
- data/spec/logstash/instrument/periodic_poller/os_spec.rb +32 -29
- data/spec/logstash/instrument/wrapped_write_client_spec.rb +33 -33
- data/spec/logstash/legacy_ruby_event_spec.rb +13 -4
- data/spec/logstash/output_delegator_spec.rb +11 -20
- data/spec/logstash/outputs/base_spec.rb +7 -5
- data/spec/logstash/pipeline_action/create_spec.rb +83 -0
- data/spec/logstash/pipeline_action/reload_spec.rb +83 -0
- data/spec/logstash/pipeline_action/stop_spec.rb +37 -0
- data/spec/logstash/pipeline_pq_file_spec.rb +1 -1
- data/spec/logstash/pipeline_spec.rb +81 -137
- data/spec/logstash/plugin_spec.rb +2 -1
- data/spec/logstash/plugins/hooks_registry_spec.rb +6 -0
- data/spec/logstash/queue_factory_spec.rb +13 -1
- data/spec/logstash/runner_spec.rb +29 -140
- data/spec/logstash/settings/writable_directory_spec.rb +10 -13
- data/spec/logstash/settings_spec.rb +0 -91
- data/spec/logstash/state_resolver_spec.rb +156 -0
- data/spec/logstash/timestamp_spec.rb +2 -6
- data/spec/logstash/util/java_version_spec.rb +22 -0
- data/spec/logstash/util/safe_uri_spec.rb +0 -56
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +22 -0
- data/spec/support/helpers.rb +9 -11
- data/spec/support/matchers.rb +96 -6
- data/spec/support/mocks_classes.rb +80 -0
- data/spec/support/shared_contexts.rb +2 -27
- metadata +100 -149
- data/lib/logstash/config/loader.rb +0 -107
- data/lib/logstash/config/modules_common.rb +0 -103
- data/lib/logstash/config/source/modules.rb +0 -55
- data/lib/logstash/config/string_escape.rb +0 -27
- data/lib/logstash/dependency_report.rb +0 -131
- data/lib/logstash/dependency_report_runner.rb +0 -17
- data/lib/logstash/elasticsearch_client.rb +0 -142
- data/lib/logstash/instrument/global_metrics.rb +0 -13
- data/lib/logstash/instrument/periodic_poller/dlq.rb +0 -24
- data/lib/logstash/modules/cli_parser.rb +0 -74
- data/lib/logstash/modules/elasticsearch_config.rb +0 -22
- data/lib/logstash/modules/elasticsearch_importer.rb +0 -37
- data/lib/logstash/modules/elasticsearch_resource.rb +0 -10
- data/lib/logstash/modules/file_reader.rb +0 -36
- data/lib/logstash/modules/kibana_base.rb +0 -24
- data/lib/logstash/modules/kibana_client.rb +0 -124
- data/lib/logstash/modules/kibana_config.rb +0 -105
- data/lib/logstash/modules/kibana_dashboards.rb +0 -36
- data/lib/logstash/modules/kibana_importer.rb +0 -17
- data/lib/logstash/modules/kibana_resource.rb +0 -10
- data/lib/logstash/modules/kibana_settings.rb +0 -40
- data/lib/logstash/modules/logstash_config.rb +0 -120
- data/lib/logstash/modules/resource_base.rb +0 -38
- data/lib/logstash/modules/scaffold.rb +0 -52
- data/lib/logstash/modules/settings_merger.rb +0 -23
- data/lib/logstash/modules/util.rb +0 -17
- data/lib/logstash/util/dead_letter_queue_manager.rb +0 -61
- data/lib/logstash/util/environment_variables.rb +0 -43
- data/spec/logstash/config/loader_spec.rb +0 -38
- data/spec/logstash/config/string_escape_spec.rb +0 -24
- data/spec/logstash/instrument/periodic_poller/dlq_spec.rb +0 -17
- data/spec/logstash/modules/logstash_config_spec.rb +0 -56
- data/spec/logstash/modules/scaffold_spec.rb +0 -234
- data/spec/logstash/pipeline_dlq_commit_spec.rb +0 -109
- data/spec/logstash/settings/splittable_string_array_spec.rb +0 -51
- data/spec/logstash/util/wrapped_acked_queue_spec.rb +0 -49
- data/versions-gem-copy.yml +0 -12
@@ -0,0 +1,92 @@
|
|
1
|
+
class Treetop::Runtime::SyntaxNode
|
2
|
+
def get_meta(key)
|
3
|
+
@ast_metadata ||= {}
|
4
|
+
return @ast_metadata[key] if @ast_metadata[key]
|
5
|
+
return self.parent.get_meta(key) if self.parent
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def set_meta(key, value)
|
10
|
+
@ast_metadata ||= {}
|
11
|
+
@ast_metadata[key] = value
|
12
|
+
end
|
13
|
+
def compile
|
14
|
+
return "" if elements.nil?
|
15
|
+
return elements.collect(&:compile).reject(&:empty?).join("")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Traverse the syntax tree recursively.
|
19
|
+
# The order should respect the order of the configuration file as it is read
|
20
|
+
# and written by humans (and the order in which it is parsed).
|
21
|
+
def recurse(e, depth=0, &block)
|
22
|
+
r = block.call(e, depth)
|
23
|
+
e.elements.each { |e| recurse(e, depth + 1, &block) } if r && e.elements
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def recursive_inject(results=[], &block)
|
28
|
+
if !elements.nil?
|
29
|
+
elements.each do |element|
|
30
|
+
if block.call(element)
|
31
|
+
results << element
|
32
|
+
else
|
33
|
+
element.recursive_inject(results, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
return results
|
38
|
+
end
|
39
|
+
|
40
|
+
# When Treetop parses the configuration file
|
41
|
+
# it will generate a tree, the generated tree will contain
|
42
|
+
# a few `Empty` nodes to represent the actual space/tab or newline in the file.
|
43
|
+
# Some of theses node will point to our concrete class.
|
44
|
+
# To fetch a specific types of object we need to follow each branch
|
45
|
+
# and ignore the empty nodes.
|
46
|
+
def recursive_select(*klasses)
|
47
|
+
return recursive_inject { |e| klasses.any? {|k| e.is_a?(k)} }
|
48
|
+
end
|
49
|
+
|
50
|
+
def recursive_inject_parent(results=[], &block)
|
51
|
+
if !parent.nil?
|
52
|
+
if block.call(parent)
|
53
|
+
results << parent
|
54
|
+
else
|
55
|
+
parent.recursive_inject_parent(results, &block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
return results
|
59
|
+
end
|
60
|
+
|
61
|
+
def recursive_select_parent(results=[], klass)
|
62
|
+
return recursive_inject_parent(results) { |e| e.is_a?(klass) }
|
63
|
+
end
|
64
|
+
|
65
|
+
# Monkeypatch Treetop::Runtime::SyntaxNode's inspect method to skip
|
66
|
+
# any Whitespace or SyntaxNodes with no children.
|
67
|
+
def _inspect(indent="")
|
68
|
+
em = extension_modules
|
69
|
+
interesting_methods = methods-[em.last ? em.last.methods : nil]-self.class.instance_methods
|
70
|
+
im = interesting_methods.size > 0 ? " (#{interesting_methods.join(",")})" : ""
|
71
|
+
tv = text_value
|
72
|
+
tv = "...#{tv[-20..-1]}" if tv.size > 20
|
73
|
+
|
74
|
+
indent +
|
75
|
+
self.class.to_s.sub(/.*:/,'') +
|
76
|
+
em.map{|m| "+"+m.to_s.sub(/.*:/,'')}*"" +
|
77
|
+
" offset=#{interval.first}" +
|
78
|
+
", #{tv.inspect}" +
|
79
|
+
im +
|
80
|
+
(elements && elements.size > 0 ?
|
81
|
+
":" +
|
82
|
+
(elements.select { |e| !e.is_a?(LogStash::Config::AST::Whitespace) && e.elements && e.elements.size > 0 }||[]).map{|e|
|
83
|
+
begin
|
84
|
+
"\n"+e.inspect(indent+" ")
|
85
|
+
rescue # Defend against inspect not taking a parameter
|
86
|
+
"\n"+indent+" "+e.inspect
|
87
|
+
end
|
88
|
+
}.join("") :
|
89
|
+
""
|
90
|
+
)
|
91
|
+
end
|
92
|
+
end
|
@@ -1,78 +1,10 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'logstash/errors'
|
3
|
-
require "logstash/config/string_escape"
|
4
3
|
require "treetop"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
def compile
|
9
|
-
return "" if elements.nil?
|
10
|
-
return elements.collect(&:compile).reject(&:empty?).join("")
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_meta(key)
|
14
|
-
@ast_metadata ||= {}
|
15
|
-
return @ast_metadata[key] if @ast_metadata[key]
|
16
|
-
return self.parent.get_meta(key) if self.parent
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
|
20
|
-
def set_meta(key, value)
|
21
|
-
@ast_metadata ||= {}
|
22
|
-
@ast_metadata[key] = value
|
23
|
-
end
|
24
|
-
|
25
|
-
# Traverse the syntax tree recursively.
|
26
|
-
# The order should respect the order of the configuration file as it is read
|
27
|
-
# and written by humans (and the order in which it is parsed).
|
28
|
-
def recurse(e, depth=0, &block)
|
29
|
-
r = block.call(e, depth)
|
30
|
-
e.elements.each { |e| recurse(e, depth + 1, &block) } if r && e.elements
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
|
34
|
-
def recursive_inject(results=[], &block)
|
35
|
-
if !elements.nil?
|
36
|
-
elements.each do |element|
|
37
|
-
if block.call(element)
|
38
|
-
results << element
|
39
|
-
else
|
40
|
-
element.recursive_inject(results, &block)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
return results
|
45
|
-
end
|
46
|
-
|
47
|
-
# When Treetop parses the configuration file
|
48
|
-
# it will generate a tree, the generated tree will contain
|
49
|
-
# a few `Empty` nodes to represent the actual space/tab or newline in the file.
|
50
|
-
# Some of theses node will point to our concrete class.
|
51
|
-
# To fetch a specific types of object we need to follow each branch
|
52
|
-
# and ignore the empty nodes.
|
53
|
-
def recursive_select(klass)
|
54
|
-
return recursive_inject { |e| e.is_a?(klass) }
|
55
|
-
end
|
56
|
-
|
57
|
-
def recursive_inject_parent(results=[], &block)
|
58
|
-
if !parent.nil?
|
59
|
-
if block.call(parent)
|
60
|
-
results << parent
|
61
|
-
else
|
62
|
-
parent.recursive_inject_parent(results, &block)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
return results
|
66
|
-
end
|
67
|
-
|
68
|
-
def recursive_select_parent(results=[], klass)
|
69
|
-
return recursive_inject_parent(results) { |e| e.is_a?(klass) }
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
5
|
+
require "logstash/compiler/treetop_monkeypatches"
|
73
6
|
|
74
7
|
module LogStash; module Config; module AST
|
75
|
-
PROCESS_ESCAPE_SEQUENCES = :process_escape_sequences
|
76
8
|
|
77
9
|
def self.deferred_conditionals=(val)
|
78
10
|
@deferred_conditionals = val
|
@@ -105,11 +37,6 @@ module LogStash; module Config; module AST
|
|
105
37
|
end
|
106
38
|
|
107
39
|
class Config < Node
|
108
|
-
def process_escape_sequences=(val)
|
109
|
-
set_meta(PROCESS_ESCAPE_SEQUENCES, val)
|
110
|
-
end
|
111
|
-
|
112
|
-
|
113
40
|
def compile
|
114
41
|
LogStash::Config::AST.deferred_conditionals = []
|
115
42
|
LogStash::Config::AST.deferred_conditionals_index = 0
|
@@ -141,9 +68,8 @@ module LogStash; module Config; module AST
|
|
141
68
|
# of the output/filter function
|
142
69
|
definitions << "define_singleton_method :#{type}_func do |event|"
|
143
70
|
definitions << " targeted_outputs = []" if type == "output"
|
144
|
-
definitions << " events = event" if type == "filter"
|
145
|
-
definitions << " @logger.debug? && @logger.debug(\"#{type} received\", \"event\" => event.to_hash)"
|
146
|
-
definitions << " @logger.debug? && events.each { |e| @logger.debug(\"#{type} received\", \"event\" => e.to_hash)}" if type == "filter"
|
71
|
+
definitions << " events = [event]" if type == "filter"
|
72
|
+
definitions << " @logger.debug? && @logger.debug(\"#{type} received\", \"event\" => event.to_hash)"
|
147
73
|
|
148
74
|
sections.select { |s| s.plugin_type.text_value == type }.each do |s|
|
149
75
|
definitions << s.compile.split("\n", -1).map { |e| " #{e}" }
|
@@ -353,11 +279,7 @@ module LogStash; module Config; module AST
|
|
353
279
|
end
|
354
280
|
class String < Value
|
355
281
|
def compile
|
356
|
-
|
357
|
-
Unicode.wrap(LogStash::Config::StringEscape.process_escapes(text_value[1...-1]))
|
358
|
-
else
|
359
|
-
Unicode.wrap(text_value[1...-1])
|
360
|
-
end
|
282
|
+
return Unicode.wrap(text_value[1...-1])
|
361
283
|
end
|
362
284
|
end
|
363
285
|
class RegExp < Value
|
@@ -33,21 +33,37 @@ LogStash::Environment.load_locale!
|
|
33
33
|
# }
|
34
34
|
#
|
35
35
|
module LogStash::Config::Mixin
|
36
|
-
|
37
|
-
include LogStash::Util::EnvironmentVariables
|
38
|
-
|
39
36
|
attr_accessor :config
|
40
37
|
attr_accessor :original_params
|
41
38
|
|
42
39
|
PLUGIN_VERSION_1_0_0 = LogStash::Util::PluginVersion.new(1, 0, 0)
|
43
40
|
PLUGIN_VERSION_0_9_0 = LogStash::Util::PluginVersion.new(0, 9, 0)
|
44
|
-
|
41
|
+
|
42
|
+
ENV_PLACEHOLDER_REGEX = /\$\{(?<name>\w+)(\:(?<default>[^}]*))?\}/
|
43
|
+
|
45
44
|
# This method is called when someone does 'include LogStash::Config'
|
46
45
|
def self.included(base)
|
47
46
|
# Add the DSL methods to the 'base' given.
|
48
47
|
base.extend(LogStash::Config::Mixin::DSL)
|
49
48
|
end
|
50
|
-
|
49
|
+
|
50
|
+
# Recursive method to replace environment variable references in parameters
|
51
|
+
def deep_replace(value)
|
52
|
+
if (value.is_a?(Hash))
|
53
|
+
value.each do |valueHashKey, valueHashValue|
|
54
|
+
value[valueHashKey.to_s] = deep_replace(valueHashValue)
|
55
|
+
end
|
56
|
+
else
|
57
|
+
if (value.is_a?(Array))
|
58
|
+
value.each_index do | valueArrayIndex|
|
59
|
+
value[valueArrayIndex] = deep_replace(value[valueArrayIndex])
|
60
|
+
end
|
61
|
+
else
|
62
|
+
return replace_env_placeholders(value)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
51
67
|
def config_init(params)
|
52
68
|
# Validation will modify the values inside params if necessary.
|
53
69
|
# For example: converting a string to a number, etc.
|
@@ -60,6 +76,30 @@ module LogStash::Config::Mixin
|
|
60
76
|
# store the plugin type, turns LogStash::Inputs::Base into 'input'
|
61
77
|
@plugin_type = self.class.ancestors.find { |a| a.name =~ /::Base$/ }.config_name
|
62
78
|
|
79
|
+
# warn about deprecated variable use
|
80
|
+
params.each do |name, value|
|
81
|
+
opts = self.class.get_config[name]
|
82
|
+
if opts && opts[:deprecated]
|
83
|
+
extra = opts[:deprecated].is_a?(String) ? opts[:deprecated] : ""
|
84
|
+
extra.gsub!("%PLUGIN%", self.class.config_name)
|
85
|
+
self.logger.warn("You are using a deprecated config setting " +
|
86
|
+
"#{name.inspect} set in #{self.class.config_name}. " +
|
87
|
+
"Deprecated settings will continue to work, " +
|
88
|
+
"but are scheduled for removal from logstash " +
|
89
|
+
"in the future. #{extra} If you have any questions " +
|
90
|
+
"about this, please visit the #logstash channel " +
|
91
|
+
"on freenode irc.", :name => name, :plugin => self)
|
92
|
+
|
93
|
+
end
|
94
|
+
if opts && opts[:obsolete]
|
95
|
+
extra = opts[:obsolete].is_a?(String) ? opts[:obsolete] : ""
|
96
|
+
extra.gsub!("%PLUGIN%", self.class.config_name)
|
97
|
+
raise LogStash::ConfigurationError,
|
98
|
+
I18n.t("logstash.runner.configuration.obsolete", :name => name,
|
99
|
+
:plugin => self.class.config_name, :extra => extra)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
63
103
|
# Set defaults from 'config :foo, :default => somevalue'
|
64
104
|
self.class.get_config.each do |name, opts|
|
65
105
|
next if params.include?(name.to_s)
|
@@ -85,46 +125,17 @@ module LogStash::Config::Mixin
|
|
85
125
|
params[name.to_s] = deep_replace(value)
|
86
126
|
end
|
87
127
|
|
128
|
+
|
88
129
|
if !self.class.validate(params)
|
89
130
|
raise LogStash::ConfigurationError,
|
90
131
|
I18n.t("logstash.runner.configuration.invalid_plugin_settings")
|
91
132
|
end
|
92
133
|
|
93
|
-
# now that we know the parameters are valid, we can obfuscate the original copy
|
94
|
-
# of the parameters before storing them as an instance variable
|
95
|
-
self.class.secure_params!(original_params)
|
96
|
-
@original_params = original_params
|
97
|
-
|
98
|
-
# warn about deprecated variable use
|
99
|
-
original_params.each do |name, value|
|
100
|
-
opts = self.class.get_config[name]
|
101
|
-
if opts && opts[:deprecated]
|
102
|
-
extra = opts[:deprecated].is_a?(String) ? opts[:deprecated] : ""
|
103
|
-
extra.gsub!("%PLUGIN%", self.class.config_name)
|
104
|
-
self.logger.warn("You are using a deprecated config setting " +
|
105
|
-
"#{name.inspect} set in #{self.class.config_name}. " +
|
106
|
-
"Deprecated settings will continue to work, " +
|
107
|
-
"but are scheduled for removal from logstash " +
|
108
|
-
"in the future. #{extra} If you have any questions " +
|
109
|
-
"about this, please visit the #logstash channel " +
|
110
|
-
"on freenode irc.", :name => name, :plugin => self)
|
111
|
-
|
112
|
-
end
|
113
|
-
|
114
|
-
if opts && opts[:obsolete]
|
115
|
-
extra = opts[:obsolete].is_a?(String) ? opts[:obsolete] : ""
|
116
|
-
extra.gsub!("%PLUGIN%", self.class.config_name)
|
117
|
-
raise LogStash::ConfigurationError,
|
118
|
-
I18n.t("logstash.runner.configuration.obsolete", :name => name,
|
119
|
-
:plugin => self.class.config_name, :extra => extra)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
134
|
# We remove any config options marked as obsolete,
|
124
135
|
# no code should be associated to them and their values should not bleed
|
125
136
|
# to the plugin context.
|
126
137
|
#
|
127
|
-
# This need to be done after fetching the options from the parents
|
138
|
+
# This need to be done after fetching the options from the parents classed
|
128
139
|
params.reject! do |name, value|
|
129
140
|
opts = self.class.get_config[name]
|
130
141
|
opts.include?(:obsolete)
|
@@ -139,13 +150,36 @@ module LogStash::Config::Mixin
|
|
139
150
|
instance_variable_set("@#{key}", value)
|
140
151
|
end
|
141
152
|
|
153
|
+
# now that we know the parameters are valid, we can obfuscate the original copy
|
154
|
+
# of the parameters before storing them as an instance variable
|
155
|
+
self.class.secure_params!(original_params)
|
156
|
+
@original_params = original_params
|
157
|
+
|
142
158
|
@config = params
|
143
159
|
end # def config_init
|
144
160
|
|
145
|
-
|
146
|
-
|
147
|
-
|
161
|
+
# Replace all environment variable references in 'value' param by environment variable value and return updated value
|
162
|
+
# Process following patterns : $VAR, ${VAR}, ${VAR:defaultValue}
|
163
|
+
def replace_env_placeholders(value)
|
164
|
+
return value unless value.is_a?(String)
|
165
|
+
|
166
|
+
value.gsub(ENV_PLACEHOLDER_REGEX) do |placeholder|
|
167
|
+
# Note: Ruby docs claim[1] Regexp.last_match is thread-local and scoped to
|
168
|
+
# the call, so this should be thread-safe.
|
169
|
+
#
|
170
|
+
# [1] http://ruby-doc.org/core-2.1.1/Regexp.html#method-c-last_match
|
171
|
+
name = Regexp.last_match(:name)
|
172
|
+
default = Regexp.last_match(:default)
|
173
|
+
|
174
|
+
replacement = ENV.fetch(name, default)
|
175
|
+
if replacement.nil?
|
176
|
+
raise LogStash::ConfigurationError, "Cannot evaluate `#{placeholder}`. Environment variable `#{name}` is not set and there is no default value given."
|
177
|
+
end
|
178
|
+
replacement
|
179
|
+
end
|
180
|
+
end # def replace_env_placeholders
|
148
181
|
|
182
|
+
module DSL
|
149
183
|
attr_accessor :flags
|
150
184
|
|
151
185
|
# If name is given, set the name and return it.
|
@@ -391,8 +425,6 @@ module LogStash::Config::Mixin
|
|
391
425
|
# (see LogStash::Inputs::File for example)
|
392
426
|
result = nil
|
393
427
|
|
394
|
-
value = deep_replace(value)
|
395
|
-
|
396
428
|
if validator.nil?
|
397
429
|
return true, value
|
398
430
|
elsif validator.is_a?(Array)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "digest"
|
3
|
+
|
4
|
+
module LogStash module Config
|
5
|
+
class PipelineConfig
|
6
|
+
include LogStash::Util::Loggable
|
7
|
+
|
8
|
+
attr_reader :source, :pipeline_id, :config_parts, :settings, :read_at
|
9
|
+
|
10
|
+
def initialize(source, pipeline_id, config_parts, settings)
|
11
|
+
@source = source
|
12
|
+
@pipeline_id = pipeline_id
|
13
|
+
# We can't use Array() since config_parts may be a java object!
|
14
|
+
config_parts_array = config_parts.is_a?(Array) ? config_parts : [config_parts]
|
15
|
+
@config_parts = config_parts_array.sort_by { |config_part| [config_part.protocol.to_s, config_part.id] }
|
16
|
+
@settings = settings
|
17
|
+
@read_at = Time.now
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_hash
|
21
|
+
@config_hash ||= Digest::SHA1.hexdigest(config_string)
|
22
|
+
end
|
23
|
+
|
24
|
+
def config_string
|
25
|
+
@config_string = config_parts.collect(&:text).join("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
def system?
|
29
|
+
@settings.get("pipeline.system")
|
30
|
+
end
|
31
|
+
|
32
|
+
def ==(other)
|
33
|
+
config_hash == other.config_hash && pipeline_id == other.pipeline_id
|
34
|
+
end
|
35
|
+
|
36
|
+
def display_debug_information
|
37
|
+
logger.debug("-------- Logstash Config ---------")
|
38
|
+
logger.debug("Config from source", :source => source, :pipeline_id => pipeline_id)
|
39
|
+
|
40
|
+
config_parts.each do |config_part|
|
41
|
+
logger.debug("Config string", :protocol => config_part.protocol, :id => config_part.id)
|
42
|
+
logger.debug("\n\n#{config_part.text}")
|
43
|
+
end
|
44
|
+
logger.debug("Merged config")
|
45
|
+
logger.debug("\n\n#{config_string}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module LogStash module Config module Source
|
3
|
+
class Base
|
4
|
+
def initialize(settings)
|
5
|
+
@settings = settings
|
6
|
+
end
|
7
|
+
|
8
|
+
def pipeline_configs
|
9
|
+
raise NotImplementedError, "`#pipeline_configs` must be implemented!"
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?
|
13
|
+
raise NotImplementedError, "`match?` must be implemented!"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end end end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/config/source/base"
|
3
|
+
require "logstash/config/pipeline_config"
|
4
|
+
require "logstash/util/loggable"
|
5
|
+
require "logstash/errors"
|
6
|
+
require "uri"
|
7
|
+
|
8
|
+
module LogStash module Config module Source
|
9
|
+
# A locally defined configuration source
|
10
|
+
#
|
11
|
+
# Which can aggregate the following config options:
|
12
|
+
# - settings.config_string: "input { stdin {} }"
|
13
|
+
# - settings.config_path: /tmp/logstash/*.conf
|
14
|
+
# - settings.config_path: http://localhost/myconfig.conf
|
15
|
+
#
|
16
|
+
# All theses option will create a unique pipeline, generated parts will be
|
17
|
+
# sorted alphabetically. Se `PipelineConfig` class for the sorting algorithm.
|
18
|
+
#
|
19
|
+
class Local < Base
|
20
|
+
class ConfigStringLoader
|
21
|
+
def self.read(config_string)
|
22
|
+
[org.logstash.common.SourceWithMetadata.new("string", "config_string", config_string)]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class ConfigPathLoader
|
27
|
+
include LogStash::Util::Loggable
|
28
|
+
|
29
|
+
TEMPORARY_FILE_RE = /~$/
|
30
|
+
LOCAL_FILE_URI = /^file:\/\//i
|
31
|
+
|
32
|
+
def initialize(path)
|
33
|
+
@path = normalize_path(path)
|
34
|
+
end
|
35
|
+
|
36
|
+
def read
|
37
|
+
config_parts = []
|
38
|
+
encoding_issue_files = []
|
39
|
+
|
40
|
+
get_files.each do |file|
|
41
|
+
next unless ::File.file?(file) # skip directory
|
42
|
+
|
43
|
+
logger.debug("Reading config file", :config_file => file)
|
44
|
+
|
45
|
+
if temporary_file?(file)
|
46
|
+
logger.warn("NOT reading config file because it is a temp file", :config_file => file)
|
47
|
+
next
|
48
|
+
end
|
49
|
+
|
50
|
+
config_string = ::File.read(file)
|
51
|
+
|
52
|
+
if valid_encoding?(config_string)
|
53
|
+
part = org.logstash.common.SourceWithMetadata.new("file", file, config_string)
|
54
|
+
config_parts << part
|
55
|
+
else
|
56
|
+
encoding_issue_files << file
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
if encoding_issue_files.any?
|
61
|
+
raise LogStash::ConfigLoadingError, "The following config files contains non-ascii characters but are not UTF-8 encoded #{encoding_issue_files}"
|
62
|
+
end
|
63
|
+
|
64
|
+
if config_parts.empty?
|
65
|
+
logger.info("No config files found in path", :path => path)
|
66
|
+
end
|
67
|
+
|
68
|
+
config_parts
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.read(path)
|
72
|
+
ConfigPathLoader.new(path).read
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
def normalize_path(path)
|
77
|
+
path.gsub!(LOCAL_FILE_URI, "")
|
78
|
+
::File.expand_path(path)
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_files
|
82
|
+
Dir.glob(path).sort
|
83
|
+
end
|
84
|
+
|
85
|
+
def path
|
86
|
+
if ::File.directory?(@path)
|
87
|
+
::File.join(@path, "*")
|
88
|
+
else
|
89
|
+
@path
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def valid_encoding?(content)
|
94
|
+
content.ascii_only? && content.valid_encoding?
|
95
|
+
end
|
96
|
+
|
97
|
+
def temporary_file?(filepath)
|
98
|
+
filepath.match(TEMPORARY_FILE_RE)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class ConfigRemoteLoader
|
103
|
+
def self.read(uri)
|
104
|
+
uri = URI.parse(uri)
|
105
|
+
|
106
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == "https") do |http|
|
107
|
+
request = Net::HTTP::Get.new(uri.path)
|
108
|
+
response = http.request(request)
|
109
|
+
|
110
|
+
# since we have fetching config we wont follow any redirection.
|
111
|
+
case response.code.to_i
|
112
|
+
when 200
|
113
|
+
[org.logstash.common.SourceWithMetadata.new(uri.scheme, uri.to_s, response.body)]
|
114
|
+
when 302
|
115
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.runner.configuration.fetch-failed", :path => uri.to_s, :message => "We don't follow redirection for remote configuration")
|
116
|
+
when 404
|
117
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.runner.configuration.fetch-failed", :path => uri.to_s, :message => "File not found")
|
118
|
+
when 403
|
119
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.runner.configuration.fetch-failed", :path => uri.to_s, :message => "Permission denied")
|
120
|
+
when 500
|
121
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.runner.configuration.fetch-failed", :path => uri.to_s, :message => "500 error on remote host")
|
122
|
+
else
|
123
|
+
raise LogStash::ConfigLoadingError, I18n.t("logstash.runner.configuration.fetch-failed", :path => uri.to_s, :message => "code: #{response.code}, message: #{response.class.to_s}")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
PIPELINE_ID = LogStash::SETTINGS.get("pipeline.id").to_sym
|
130
|
+
HTTP_RE = /^http(s)?/
|
131
|
+
INPUT_BLOCK_RE = /input *{/
|
132
|
+
OUTPUT_BLOCK_RE = /output *{/
|
133
|
+
|
134
|
+
def pipeline_configs
|
135
|
+
config_parts = []
|
136
|
+
|
137
|
+
config_parts.concat(ConfigStringLoader.read(config_string)) if config_string?
|
138
|
+
if local_config?
|
139
|
+
local_config_parts = ConfigPathLoader.read(config_path)
|
140
|
+
config_parts.concat(local_config_parts)
|
141
|
+
else
|
142
|
+
local_config_parts = []
|
143
|
+
end
|
144
|
+
|
145
|
+
config_parts.concat(ConfigRemoteLoader.read(config_path)) if remote_config?
|
146
|
+
|
147
|
+
return if config_parts.empty?
|
148
|
+
return if config_string? && config_string.strip.empty? && local_config? && local_config_parts.empty?
|
149
|
+
|
150
|
+
add_missing_default_inputs_or_outputs(config_parts)
|
151
|
+
|
152
|
+
[PipelineConfig.new(self.class, PIPELINE_ID, config_parts, @settings)]
|
153
|
+
end
|
154
|
+
|
155
|
+
def match?
|
156
|
+
config_string? || config_path?
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
# Make sure we have an input and at least 1 output
|
161
|
+
# if its not the case we will add stdin and stdout
|
162
|
+
# this is for backward compatibility reason
|
163
|
+
def add_missing_default_inputs_or_outputs(config_parts)
|
164
|
+
if !config_parts.any? { |part| INPUT_BLOCK_RE.match(part.text) }
|
165
|
+
config_parts << org.logstash.common.SourceWithMetadata.new(self.class.name, "default input", LogStash::Config::Defaults.input)
|
166
|
+
end
|
167
|
+
|
168
|
+
# include a default stdout output if no outputs given
|
169
|
+
if !config_parts.any? { |part| OUTPUT_BLOCK_RE.match(part.text) }
|
170
|
+
config_parts << org.logstash.common.SourceWithMetadata.new(self.class.name, "default output", LogStash::Config::Defaults.output)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def config_string
|
175
|
+
@settings.get("config.string")
|
176
|
+
end
|
177
|
+
|
178
|
+
def config_string?
|
179
|
+
!config_string.nil?
|
180
|
+
end
|
181
|
+
|
182
|
+
def config_path
|
183
|
+
@settings.get("path.config")
|
184
|
+
end
|
185
|
+
|
186
|
+
def config_path?
|
187
|
+
!config_path.nil? && !config_path.empty?
|
188
|
+
end
|
189
|
+
|
190
|
+
def local_config?
|
191
|
+
return false unless config_path?
|
192
|
+
|
193
|
+
begin
|
194
|
+
uri = URI.parse(config_path)
|
195
|
+
uri.scheme == "file" || uri.scheme.nil?
|
196
|
+
rescue URI::InvalidURIError
|
197
|
+
# fallback for windows.
|
198
|
+
# if the parsing of the file failed we assume we can reach it locally.
|
199
|
+
# some relative path on windows arent parsed correctly (.\logstash.conf)
|
200
|
+
true
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def remote_config?
|
205
|
+
return false unless config_path?
|
206
|
+
|
207
|
+
begin
|
208
|
+
uri = URI.parse(config_path)
|
209
|
+
uri.scheme =~ HTTP_RE
|
210
|
+
rescue URI::InvalidURIError
|
211
|
+
false
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end end end
|