logstash-core 5.6.16-java → 6.0.0.alpha1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/gemspec_jars.rb +4 -7
  3. data/lib/logstash-core/logstash-core.jar +0 -0
  4. data/lib/logstash-core/version.rb +4 -8
  5. data/lib/logstash-core_jars.rb +12 -26
  6. data/lib/logstash/agent.rb +261 -246
  7. data/lib/logstash/api/commands/default_metadata.rb +1 -1
  8. data/lib/logstash/api/commands/hot_threads_reporter.rb +5 -11
  9. data/lib/logstash/api/commands/node.rb +3 -2
  10. data/lib/logstash/api/commands/stats.rb +3 -2
  11. data/lib/logstash/bootstrap_check/bad_java.rb +16 -0
  12. data/lib/logstash/bootstrap_check/bad_ruby.rb +12 -0
  13. data/lib/logstash/bootstrap_check/default_config.rb +17 -0
  14. data/lib/logstash/compiler.rb +38 -0
  15. data/lib/logstash/compiler/lscl.rb +566 -0
  16. data/lib/logstash/compiler/lscl/lscl_grammar.rb +3503 -0
  17. data/lib/logstash/compiler/treetop_monkeypatches.rb +92 -0
  18. data/lib/logstash/config/config_ast.rb +4 -82
  19. data/lib/logstash/config/mixin.rb +73 -41
  20. data/lib/logstash/config/pipeline_config.rb +48 -0
  21. data/lib/logstash/config/source/base.rb +16 -0
  22. data/lib/logstash/config/source/local.rb +215 -0
  23. data/lib/logstash/config/source_loader.rb +125 -0
  24. data/lib/logstash/converge_result.rb +103 -0
  25. data/lib/logstash/environment.rb +6 -19
  26. data/lib/logstash/errors.rb +2 -0
  27. data/lib/logstash/execution_context.rb +4 -7
  28. data/lib/logstash/filter_delegator.rb +6 -9
  29. data/lib/logstash/inputs/base.rb +0 -2
  30. data/lib/logstash/instrument/collector.rb +5 -7
  31. data/lib/logstash/instrument/metric_store.rb +12 -12
  32. data/lib/logstash/instrument/metric_type/mean.rb +0 -5
  33. data/lib/logstash/instrument/namespaced_metric.rb +0 -4
  34. data/lib/logstash/instrument/namespaced_null_metric.rb +0 -4
  35. data/lib/logstash/instrument/null_metric.rb +0 -10
  36. data/lib/logstash/instrument/periodic_poller/cgroup.rb +85 -168
  37. data/lib/logstash/instrument/periodic_poller/jvm.rb +5 -5
  38. data/lib/logstash/instrument/periodic_poller/pq.rb +3 -7
  39. data/lib/logstash/instrument/periodic_pollers.rb +1 -3
  40. data/lib/logstash/instrument/wrapped_write_client.rb +24 -33
  41. data/lib/logstash/logging/logger.rb +15 -47
  42. data/lib/logstash/namespace.rb +0 -1
  43. data/lib/logstash/output_delegator.rb +5 -7
  44. data/lib/logstash/outputs/base.rb +0 -2
  45. data/lib/logstash/pipeline.rb +159 -87
  46. data/lib/logstash/pipeline_action.rb +13 -0
  47. data/lib/logstash/pipeline_action/base.rb +29 -0
  48. data/lib/logstash/pipeline_action/create.rb +47 -0
  49. data/lib/logstash/pipeline_action/reload.rb +48 -0
  50. data/lib/logstash/pipeline_action/stop.rb +23 -0
  51. data/lib/logstash/plugin.rb +0 -1
  52. data/lib/logstash/plugins/hooks_registry.rb +6 -0
  53. data/lib/logstash/plugins/registry.rb +0 -1
  54. data/lib/logstash/program.rb +14 -0
  55. data/lib/logstash/queue_factory.rb +5 -1
  56. data/lib/logstash/runner.rb +58 -80
  57. data/lib/logstash/settings.rb +3 -27
  58. data/lib/logstash/state_resolver.rb +41 -0
  59. data/lib/logstash/util/java_version.rb +6 -0
  60. data/lib/logstash/util/safe_uri.rb +12 -148
  61. data/lib/logstash/util/thread_dump.rb +4 -7
  62. data/lib/logstash/util/wrapped_acked_queue.rb +36 -39
  63. data/lib/logstash/util/wrapped_synchronous_queue.rb +29 -39
  64. data/lib/logstash/version.rb +10 -8
  65. data/locales/en.yml +3 -54
  66. data/logstash-core.gemspec +8 -35
  67. data/spec/{logstash/api/modules → api/lib/api}/logging_spec.rb +10 -1
  68. data/spec/{logstash/api/modules → api/lib/api}/node_plugins_spec.rb +2 -1
  69. data/spec/{logstash/api/modules → api/lib/api}/node_spec.rb +3 -3
  70. data/spec/{logstash/api/modules → api/lib/api}/node_stats_spec.rb +3 -7
  71. data/spec/{logstash/api/modules → api/lib/api}/plugins_spec.rb +3 -4
  72. data/spec/{logstash/api/modules → api/lib/api}/root_spec.rb +2 -2
  73. data/spec/api/lib/api/support/resource_dsl_methods.rb +87 -0
  74. data/spec/{logstash/api/commands/stats_spec.rb → api/lib/commands/stats.rb} +2 -7
  75. data/spec/{logstash/api → api/lib}/errors_spec.rb +1 -1
  76. data/spec/{logstash/api → api/lib}/rack_app_spec.rb +0 -0
  77. data/spec/api/spec_helper.rb +106 -0
  78. data/spec/logstash/agent/converge_spec.rb +286 -0
  79. data/spec/logstash/agent/metrics_spec.rb +244 -0
  80. data/spec/logstash/agent_spec.rb +213 -225
  81. data/spec/logstash/compiler/compiler_spec.rb +584 -0
  82. data/spec/logstash/config/config_ast_spec.rb +8 -47
  83. data/spec/logstash/config/mixin_spec.rb +2 -42
  84. data/spec/logstash/config/pipeline_config_spec.rb +75 -0
  85. data/spec/logstash/config/source/local_spec.rb +395 -0
  86. data/spec/logstash/config/source_loader_spec.rb +122 -0
  87. data/spec/logstash/converge_result_spec.rb +179 -0
  88. data/spec/logstash/event_spec.rb +0 -66
  89. data/spec/logstash/execution_context_spec.rb +8 -12
  90. data/spec/logstash/filter_delegator_spec.rb +12 -24
  91. data/spec/logstash/inputs/base_spec.rb +7 -5
  92. data/spec/logstash/instrument/periodic_poller/cgroup_spec.rb +92 -225
  93. data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +1 -1
  94. data/spec/logstash/instrument/periodic_poller/os_spec.rb +32 -29
  95. data/spec/logstash/instrument/wrapped_write_client_spec.rb +33 -33
  96. data/spec/logstash/legacy_ruby_event_spec.rb +13 -4
  97. data/spec/logstash/output_delegator_spec.rb +11 -20
  98. data/spec/logstash/outputs/base_spec.rb +7 -5
  99. data/spec/logstash/pipeline_action/create_spec.rb +83 -0
  100. data/spec/logstash/pipeline_action/reload_spec.rb +83 -0
  101. data/spec/logstash/pipeline_action/stop_spec.rb +37 -0
  102. data/spec/logstash/pipeline_pq_file_spec.rb +1 -1
  103. data/spec/logstash/pipeline_spec.rb +81 -137
  104. data/spec/logstash/plugin_spec.rb +2 -1
  105. data/spec/logstash/plugins/hooks_registry_spec.rb +6 -0
  106. data/spec/logstash/queue_factory_spec.rb +13 -1
  107. data/spec/logstash/runner_spec.rb +29 -140
  108. data/spec/logstash/settings/writable_directory_spec.rb +10 -13
  109. data/spec/logstash/settings_spec.rb +0 -91
  110. data/spec/logstash/state_resolver_spec.rb +156 -0
  111. data/spec/logstash/timestamp_spec.rb +2 -6
  112. data/spec/logstash/util/java_version_spec.rb +22 -0
  113. data/spec/logstash/util/safe_uri_spec.rb +0 -56
  114. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +22 -0
  115. data/spec/support/helpers.rb +9 -11
  116. data/spec/support/matchers.rb +96 -6
  117. data/spec/support/mocks_classes.rb +80 -0
  118. data/spec/support/shared_contexts.rb +2 -27
  119. metadata +100 -149
  120. data/lib/logstash/config/loader.rb +0 -107
  121. data/lib/logstash/config/modules_common.rb +0 -103
  122. data/lib/logstash/config/source/modules.rb +0 -55
  123. data/lib/logstash/config/string_escape.rb +0 -27
  124. data/lib/logstash/dependency_report.rb +0 -131
  125. data/lib/logstash/dependency_report_runner.rb +0 -17
  126. data/lib/logstash/elasticsearch_client.rb +0 -142
  127. data/lib/logstash/instrument/global_metrics.rb +0 -13
  128. data/lib/logstash/instrument/periodic_poller/dlq.rb +0 -24
  129. data/lib/logstash/modules/cli_parser.rb +0 -74
  130. data/lib/logstash/modules/elasticsearch_config.rb +0 -22
  131. data/lib/logstash/modules/elasticsearch_importer.rb +0 -37
  132. data/lib/logstash/modules/elasticsearch_resource.rb +0 -10
  133. data/lib/logstash/modules/file_reader.rb +0 -36
  134. data/lib/logstash/modules/kibana_base.rb +0 -24
  135. data/lib/logstash/modules/kibana_client.rb +0 -124
  136. data/lib/logstash/modules/kibana_config.rb +0 -105
  137. data/lib/logstash/modules/kibana_dashboards.rb +0 -36
  138. data/lib/logstash/modules/kibana_importer.rb +0 -17
  139. data/lib/logstash/modules/kibana_resource.rb +0 -10
  140. data/lib/logstash/modules/kibana_settings.rb +0 -40
  141. data/lib/logstash/modules/logstash_config.rb +0 -120
  142. data/lib/logstash/modules/resource_base.rb +0 -38
  143. data/lib/logstash/modules/scaffold.rb +0 -52
  144. data/lib/logstash/modules/settings_merger.rb +0 -23
  145. data/lib/logstash/modules/util.rb +0 -17
  146. data/lib/logstash/util/dead_letter_queue_manager.rb +0 -61
  147. data/lib/logstash/util/environment_variables.rb +0 -43
  148. data/spec/logstash/config/loader_spec.rb +0 -38
  149. data/spec/logstash/config/string_escape_spec.rb +0 -24
  150. data/spec/logstash/instrument/periodic_poller/dlq_spec.rb +0 -17
  151. data/spec/logstash/modules/logstash_config_spec.rb +0 -56
  152. data/spec/logstash/modules/scaffold_spec.rb +0 -234
  153. data/spec/logstash/pipeline_dlq_commit_spec.rb +0 -109
  154. data/spec/logstash/settings/splittable_string_array_spec.rb +0 -51
  155. data/spec/logstash/util/wrapped_acked_queue_spec.rb +0 -49
  156. 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
- class Treetop::Runtime::SyntaxNode
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)" if type == "output"
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
- if get_meta(PROCESS_ESCAPE_SEQUENCES)
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 class
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
- module DSL
146
-
147
- include LogStash::Util::EnvironmentVariables
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