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
@@ -6,8 +6,6 @@ require "logstash/config/grammar"
6
6
  require "logstash/config/config_ast"
7
7
 
8
8
  describe LogStashConfigParser do
9
- let(:settings) { mock_settings({}) }
10
-
11
9
  context '#parse' do
12
10
  context "valid configuration" do
13
11
  it "should permit single-quoted attribute names" do
@@ -79,7 +77,7 @@ describe LogStashConfigParser do
79
77
  }
80
78
  CONFIG
81
79
  subject { LogStashConfigParser.new }
82
-
80
+
83
81
  it "should compile successfully" do
84
82
  result = subject.parse(config)
85
83
  expect(result).not_to(be_nil)
@@ -144,50 +142,12 @@ describe LogStashConfigParser do
144
142
  expect(config).to be_nil
145
143
  end
146
144
  end
147
-
148
- context "when config.support_escapes" do
149
- let(:parser) { LogStashConfigParser.new }
150
-
151
- let(:processed_value) { 'The computer says, "No"' }
152
-
153
- let(:config) {
154
- parser.parse(%q(
155
- input {
156
- foo {
157
- bar => "The computer says, \"No\""
158
- }
159
- }
160
- ))
161
- }
162
-
163
- let(:compiled_string) { eval(config.recursive_select(LogStash::Config::AST::String).first.compile) }
164
-
165
- before do
166
- config.process_escape_sequences = escapes
167
- end
168
-
169
- context "is enabled" do
170
- let(:escapes) { true }
171
-
172
- it "should process escape sequences" do
173
- expect(compiled_string).to be == processed_value
174
- end
175
- end
176
-
177
- context "is false" do
178
- let(:escapes) { false }
179
-
180
- it "should not process escape sequences" do
181
- expect(compiled_string).not_to be == processed_value
182
- end
183
- end
184
- end
185
145
  end
186
146
 
187
147
  context "when using two plugin sections of the same type" do
188
148
  let(:pipeline_klass) do
189
149
  Class.new do
190
- def initialize(config, settings)
150
+ def initialize(config)
191
151
  grammar = LogStashConfigParser.new
192
152
  @config = grammar.parse(config)
193
153
  @code = @config.compile
@@ -206,7 +166,7 @@ describe LogStashConfigParser do
206
166
 
207
167
 
208
168
  it "should create a pipeline with both sections" do
209
- generated_objects = pipeline_klass.new(config_string, settings).instance_variable_get("@generated_objects")
169
+ generated_objects = pipeline_klass.new(config_string).instance_variable_get("@generated_objects")
210
170
  filters = generated_objects.keys.map(&:to_s).select {|obj_name| obj_name.match(/^filter.+?_\d+$/) }
211
171
  expect(filters.size).to eq(2)
212
172
  end
@@ -221,13 +181,14 @@ describe LogStashConfigParser do
221
181
 
222
182
 
223
183
  it "should create a pipeline with both sections" do
224
- generated_objects = pipeline_klass.new(config_string, settings).instance_variable_get("@generated_objects")
184
+ generated_objects = pipeline_klass.new(config_string).instance_variable_get("@generated_objects")
225
185
  outputs = generated_objects.keys.map(&:to_s).select {|obj_name| obj_name.match(/^output.+?_\d+$/) }
226
186
  expect(outputs.size).to eq(2)
227
187
  end
228
188
  end
229
189
  end
230
190
  context "when creating two instances of the same configuration" do
191
+
231
192
  let(:config_string) {
232
193
  "input { generator { } }
233
194
  filter {
@@ -240,7 +201,7 @@ describe LogStashConfigParser do
240
201
 
241
202
  let(:pipeline_klass) do
242
203
  Class.new do
243
- def initialize(config, settings)
204
+ def initialize(config)
244
205
  grammar = LogStashConfigParser.new
245
206
  @config = grammar.parse(config)
246
207
  @code = @config.compile
@@ -252,8 +213,8 @@ describe LogStashConfigParser do
252
213
 
253
214
  describe "generated conditional functionals" do
254
215
  it "should be created per instance" do
255
- instance_1 = pipeline_klass.new(config_string, settings)
256
- instance_2 = pipeline_klass.new(config_string, settings)
216
+ instance_1 = pipeline_klass.new(config_string)
217
+ instance_2 = pipeline_klass.new(config_string)
257
218
  generated_method_1 = instance_1.instance_variable_get("@generated_objects")[:cond_func_1]
258
219
  generated_method_2 = instance_2.instance_variable_get("@generated_objects")[:cond_func_1]
259
220
  expect(generated_method_1).to_not be(generated_method_2)
@@ -3,34 +3,6 @@ require "spec_helper"
3
3
  require "logstash/config/mixin"
4
4
 
5
5
  describe LogStash::Config::Mixin do
6
- context "when encountering a deprecated option" do
7
- let(:password) { "sekret" }
8
- let(:double_logger) { double("logger").as_null_object }
9
-
10
- subject do
11
- Class.new(LogStash::Filters::Base) do
12
- include LogStash::Config::Mixin
13
- config_name "test_deprecated"
14
- milestone 1
15
- config :old_opt, :validate => :string, :deprecated => "this is old school"
16
- config :password, :validate => :password
17
- end.new({
18
- "old_opt" => "whut",
19
- "password" => password
20
- })
21
- end
22
-
23
- it "should not log the password" do
24
- expect(LogStash::Logging::Logger).to receive(:new).with(anything).and_return(double_logger)
25
- expect(double_logger).to receive(:warn) do |arg1,arg2|
26
- message = 'You are using a deprecated config setting "old_opt" set in test_deprecated. Deprecated settings will continue to work, but are scheduled for removal from logstash in the future. this is old school If you have any questions about this, please visit the #logstash channel on freenode irc.'
27
- expect(arg1).to eq(message)
28
- expect(arg2[:plugin].to_s).to include('"password"=><password>')
29
- end.once
30
- subject
31
- end
32
- end
33
-
34
6
  context "when validating :bytes successfully" do
35
7
  subject do
36
8
  local_num_bytes = num_bytes # needs to be locally scoped :(
@@ -220,8 +192,8 @@ describe LogStash::Config::Mixin do
220
192
  expect(clone.uri.to_s).to eql(uri_hidden)
221
193
  end
222
194
 
223
- it "should make the real java.net.URI object available under #uri" do
224
- expect(subject.uri.uri).to be_a(java.net.URI)
195
+ it "should make the real URI object available under #uri" do
196
+ expect(subject.uri.uri).to be_a(::URI)
225
197
  end
226
198
 
227
199
  it "should obfuscate original_params" do
@@ -397,13 +369,11 @@ describe LogStash::Config::Mixin do
397
369
  before do
398
370
  ENV["FunString"] = "fancy"
399
371
  ENV["FunBool"] = "true"
400
- ENV["SERVER_LS_TEST_ADDRESS"] = "some.host.address.tld"
401
372
  end
402
373
 
403
374
  after do
404
375
  ENV.delete("FunString")
405
376
  ENV.delete("FunBool")
406
- ENV.delete("SERVER_LS_TEST_ADDRESS")
407
377
  end
408
378
 
409
379
  subject do
@@ -427,16 +397,6 @@ describe LogStash::Config::Mixin do
427
397
  expect(subject.nestedArray).to(be == { "level1" => [{ "key1" => "http://fancy:8080/blah.txt" }, { "key2" => "http://fancy:8080/foo.txt" }] })
428
398
  expect(subject.deepHash).to(be == { "level1" => { "level2" => { "level3" => { "key1" => "http://fancy:8080/blah.txt" } } } })
429
399
  end
430
-
431
- it "should validate settings after interpolating ENV variables" do
432
- expect {
433
- Class.new(LogStash::Filters::Base) do
434
- include LogStash::Config::Mixin
435
- config_name "test"
436
- config :server_address, :validate => :uri
437
- end.new({"server_address" => "${SERVER_LS_TEST_ADDRESS}"})
438
- }.not_to raise_error
439
- end
440
400
  end
441
401
 
442
402
  context "should support $ in values" do
@@ -0,0 +1,75 @@
1
+ # encoding: utf-8
2
+ require "logstash/config/pipeline_config"
3
+ require "logstash/config/source/local"
4
+
5
+ describe LogStash::Config::PipelineConfig do
6
+ let(:source) { LogStash::Config::Source::Local }
7
+ let(:pipeline_id) { :main }
8
+ let(:ordered_config_parts) do
9
+ [
10
+ org.logstash.common.SourceWithMetadata.new("file", "/tmp/1", "input { generator1 }"),
11
+ org.logstash.common.SourceWithMetadata.new("file", "/tmp/2", "input { generator2 }"),
12
+ org.logstash.common.SourceWithMetadata.new("file", "/tmp/3", "input { generator3 }"),
13
+ org.logstash.common.SourceWithMetadata.new("file", "/tmp/4", "input { generator4 }"),
14
+ org.logstash.common.SourceWithMetadata.new("file", "/tmp/5", "input { generator5 }"),
15
+ org.logstash.common.SourceWithMetadata.new("file", "/tmp/6", "input { generator6 }"),
16
+ org.logstash.common.SourceWithMetadata.new("string", "config_string", "input { generator1 }"),
17
+ ]
18
+ end
19
+
20
+ let(:unordered_config_parts) { ordered_config_parts.shuffle }
21
+ let(:settings) { LogStash::SETTINGS }
22
+
23
+ subject { described_class.new(source, pipeline_id, unordered_config_parts, settings) }
24
+
25
+ it "returns the source" do
26
+ expect(subject.source).to eq(source)
27
+ end
28
+
29
+ it "returns the pipeline id" do
30
+ expect(subject.pipeline_id).to eq(pipeline_id)
31
+ end
32
+
33
+ it "returns the sorted config parts" do
34
+ expect(subject.config_parts).to eq(ordered_config_parts)
35
+ end
36
+
37
+ it "returns the config_hash" do
38
+ expect(subject.config_hash).not_to be_nil
39
+ end
40
+
41
+ it "returns the merged `ConfigPart#config_string`" do
42
+ expect(subject.config_string).to eq(ordered_config_parts.collect(&:text).join("\n"))
43
+ end
44
+
45
+ it "records when the config was read" do
46
+ expect(subject.read_at).to be <= Time.now
47
+ end
48
+
49
+ it "does object equality on config_hash and pipeline_id" do
50
+ another_exact_pipeline = described_class.new(source, pipeline_id, ordered_config_parts, settings)
51
+ expect(subject).to eq(another_exact_pipeline)
52
+
53
+ not_matching_pipeline = described_class.new(source, pipeline_id, [], settings)
54
+ expect(subject).not_to eq(not_matching_pipeline)
55
+
56
+ not_same_pipeline_id = described_class.new(source, :another_pipeline, unordered_config_parts, settings)
57
+ expect(subject).not_to eq(not_same_pipeline_id)
58
+ end
59
+
60
+ describe "#system?" do
61
+ context "when the pipeline is a system pipeline" do
62
+ let(:settings) { mock_settings({ "pipeline.system" => true })}
63
+
64
+ it "returns true if the pipeline is a system pipeline" do
65
+ expect(subject.system?).to be_truthy
66
+ end
67
+ end
68
+
69
+ context "when is not a system pipeline" do
70
+ it "returns false if the pipeline is not a system pipeline" do
71
+ expect(subject.system?).to be_falsey
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,395 @@
1
+ # encoding: utf-8
2
+ require "logstash/config/source/local"
3
+ require "rspec/expectations"
4
+ require "stud/temporary"
5
+ require "fileutils"
6
+ require "pathname"
7
+ require_relative "../../../support/helpers"
8
+ require_relative "../../../support/matchers"
9
+ require "spec_helper"
10
+ require "webmock/rspec"
11
+
12
+ describe LogStash::Config::Source::Local::ConfigStringLoader do
13
+ subject { described_class }
14
+ let(:config_string) { "input { generator {} } output { stdout {} }"}
15
+
16
+ it "returns one config_parts" do
17
+ expect(subject.read(config_string).size).to eq(1)
18
+ end
19
+
20
+ it "returns a valid config part" do
21
+ config_part = subject.read(config_string).first
22
+ expect(config_part).to be_a_source_with_metadata("string", "config_string", config_string)
23
+ end
24
+ end
25
+
26
+ describe LogStash::Config::Source::Local::ConfigPathLoader do
27
+ subject { described_class }
28
+
29
+ context "no configs" do
30
+ context "in the directory" do
31
+ let(:directory) do
32
+ p = Stud::Temporary.pathname
33
+ FileUtils.mkdir_p(p)
34
+ p
35
+ end
36
+
37
+ it "returns an empty array" do
38
+ expect(subject.read(directory)).to be_empty
39
+ end
40
+ end
41
+
42
+ context "target file doesn't exist" do
43
+ let(:directory) do
44
+ p = Stud::Temporary.pathname
45
+ FileUtils.mkdir_p(p)
46
+ ::File.join(p, "ls.conf")
47
+ end
48
+
49
+ it "returns an empty array" do
50
+ expect(subject.read(directory)).to be_empty
51
+ end
52
+ end
53
+ end
54
+
55
+ context "when it exist" do
56
+ shared_examples "read config from files" do
57
+ let(:directory) { Stud::Temporary.pathname }
58
+
59
+ before do
60
+ files.each do |file, content|
61
+ temporary_file(content, file, directory)
62
+ end
63
+
64
+ expect(files.size).to be >= 1
65
+ expect(Dir.glob(::File.join(directory, "*")).size).to eq(files.size)
66
+ end
67
+
68
+ it "returns a `config_parts` per file" do
69
+ expect(subject.read(reader_config).size).to eq(files.size)
70
+ end
71
+
72
+ it "returns alphabetically sorted parts" do
73
+ parts = subject.read(reader_config)
74
+ expect(parts.collect { |part| ::File.basename(part.id) }).to eq(files.keys.sort)
75
+ end
76
+
77
+ it "returns valid `config_parts`" do
78
+ parts = subject.read(reader_config)
79
+
80
+ parts.each do |part|
81
+ basename = ::File.basename(part.id)
82
+ file_path = ::File.join(directory, basename)
83
+ content = files[basename]
84
+ expect(part).to be_a_source_with_metadata("file", file_path, content)
85
+ end
86
+ end
87
+ end
88
+
89
+ context "when the files have invalid encoding" do
90
+ let(:config_string) { "\x80" }
91
+ let(:file_path) { Stud::Temporary.pathname }
92
+ let(:file) { ::File.join(file_path, "wrong_encoding.conf") }
93
+
94
+ before do
95
+ FileUtils.mkdir_p(file_path)
96
+ f = File.open(file, "wb") do |file|
97
+ file.write(config_string)
98
+ end
99
+ end
100
+
101
+ it "raises an exception" do
102
+ expect { subject.read(file_path) }.to raise_error LogStash::ConfigLoadingError, /#{file_path}/
103
+ end
104
+ end
105
+
106
+ context "when we target one file" do
107
+ let(:reader_config) { ::File.join(directory, files.keys.first) }
108
+ let(:files) {
109
+ {
110
+ "config1.conf" => "input1",
111
+ }
112
+ }
113
+
114
+ include_examples "read config from files"
115
+ end
116
+
117
+ context "when we target a path with multiples files" do
118
+ let(:reader_config) { directory }
119
+
120
+ let(:files) {
121
+ {
122
+ "config1.conf" => "input1",
123
+ "config2.conf" => "input2",
124
+ "config3.conf" => "input3",
125
+ "config4.conf" => "input4"
126
+ }
127
+ }
128
+
129
+ include_examples "read config from files"
130
+ end
131
+
132
+ context "when there temporary files in the directory" do
133
+ let(:reader_config) { ::File.join(directory, "conf*.conf") }
134
+
135
+ let(:files) {
136
+ {
137
+ "config1.conf" => "input1",
138
+ "config2.conf" => "input2",
139
+ "config3.conf" => "input3",
140
+ "config4.conf" => "input4"
141
+ }
142
+ }
143
+
144
+ let(:other_files) do
145
+ {
146
+ "config1.conf~" => "input1",
147
+ "config2.conf~" => "input2",
148
+ "config3.conf~" => "input3",
149
+ "config4.conf~" => "input4"
150
+ }
151
+ end
152
+
153
+ include_examples "read config from files" do
154
+ before do
155
+ other_files.keys.shuffle.each do |file|
156
+ content = files[file]
157
+ temporary_file(content, file, directory)
158
+ end
159
+
160
+ # make sure we actually do some filtering
161
+ expect(Dir.glob(::File.join(directory, "*")).size).to eq(other_files.size + files.size)
162
+ end
163
+ end
164
+ end
165
+
166
+ context "when the path is a wildcard" do
167
+ let(:reader_config) { ::File.join(directory, "conf*.conf") }
168
+
169
+ let(:files) {
170
+ {
171
+ "config1.conf" => "input1",
172
+ "config2.conf" => "input2",
173
+ "config3.conf" => "input3",
174
+ "config4.conf" => "input4"
175
+ }
176
+ }
177
+
178
+ let(:other_files) do
179
+ {
180
+ "bad1.conf" => "input1",
181
+ "bad2.conf" => "input2",
182
+ "bad3.conf" => "input3",
183
+ "bad4.conf" => "input4"
184
+ }
185
+ end
186
+
187
+ include_examples "read config from files" do
188
+ before do
189
+ other_files.keys.shuffle.each do |file|
190
+ content = files[file]
191
+ temporary_file(content, file, directory)
192
+ end
193
+
194
+ # make sure we actually do some filtering
195
+ expect(Dir.glob(::File.join(directory, "*")).size).to eq(other_files.size + files.size)
196
+ end
197
+ end
198
+ end
199
+
200
+ context "URI defined path (file://..)" do
201
+ let(:reader_config) { "file://#{::File.join(directory, files.keys.first)}" }
202
+ let(:files) {
203
+ {
204
+ "config1.conf" => "input1",
205
+ }
206
+ }
207
+
208
+ include_examples "read config from files"
209
+ end
210
+
211
+ context "relative path" do
212
+ let(:reader_config) do
213
+ FileUtils.mkdir_p(::File.join(directory, "inside"))
214
+ ::File.join(directory, "inside", "../")
215
+ end
216
+
217
+ let(:files) {
218
+ {
219
+ "config2.conf" => "input1",
220
+ "config1.conf" => "input2",
221
+ }
222
+ }
223
+
224
+ include_examples "read config from files"
225
+ end
226
+ end
227
+ end
228
+
229
+ describe LogStash::Config::Source::Local::ConfigRemoteLoader do
230
+ before :all do
231
+ WebMock.disable_net_connect!
232
+ end
233
+
234
+ after :all do
235
+ WebMock.allow_net_connect!
236
+ end
237
+
238
+ subject { described_class }
239
+
240
+ let(:remote_url) { "http://test.dev/superconfig.conf" }
241
+
242
+ context "when the remote configuration exist" do
243
+ let(:config_string) { "input { generator {} } output { stdout {} }"}
244
+
245
+ before do
246
+ stub_request(:get, remote_url)
247
+ .to_return({
248
+ :body => config_string,
249
+ :status => 200
250
+ })
251
+ end
252
+
253
+ it "returns one config_parts" do
254
+ expect(subject.read(remote_url).size).to eq(1)
255
+ end
256
+
257
+ it "returns a valid config part" do
258
+ config_part = subject.read(remote_url).first
259
+ expect(config_part).to be_a_source_with_metadata("http", remote_url, config_string)
260
+ end
261
+ end
262
+
263
+ # I am aware that 656 http doesn't exist I am just testing the
264
+ # catch all block
265
+ [302, 404, 500, 403, 656].each do |code|
266
+ context "when the remote return an error code: #{code}" do
267
+ before do
268
+ stub_request(:get, remote_url)
269
+ .to_return({ :status => code })
270
+ end
271
+
272
+ it "raises the exception up" do
273
+ expect { subject.read(remote_url) }.to raise_error LogStash::ConfigLoadingError
274
+ end
275
+ end
276
+ end
277
+ end
278
+
279
+ describe LogStash::Config::Source::Local do
280
+ let(:input_block) { "input { generator {} }" }
281
+ let(:filter_block) { "filter { mutate {} } " }
282
+ let(:output_block) { "output { elasticsearch {}}" }
283
+ subject { described_class.new(settings) }
284
+
285
+ context "when `config.string` and `config.path` are set`" do
286
+ let(:config_file) { temporary_file(input_block) }
287
+
288
+ let(:settings) do
289
+ mock_settings(
290
+ "config.string" => "#{filter_block} #{output_block}",
291
+ "path.config" => config_file
292
+ )
293
+ end
294
+
295
+ it "returns a merged config" do
296
+ expect(subject.pipeline_configs.first.config_string).to include(input_block, output_block, filter_block)
297
+ end
298
+ end
299
+
300
+ context "when only the `config.string` is set" do
301
+ let(:settings) do
302
+ mock_settings( "config.string" => filter_block)
303
+ end
304
+
305
+ it "returns a config" do
306
+ expect(subject.pipeline_configs.first.config_string).to include(filter_block)
307
+ end
308
+ end
309
+
310
+ context "when only the `path.config` is set" do
311
+ let(:config_file) { temporary_file(input_block) }
312
+ let(:settings) do
313
+ mock_settings( "path.config" => config_file)
314
+ end
315
+
316
+ it "returns a config" do
317
+ expect(subject.pipeline_configs.first.config_string).to include(input_block)
318
+ end
319
+ end
320
+
321
+ context "when the `path.config` is an url" do
322
+ let(:remote_url) { "http://test.dev/superconfig.conf" }
323
+
324
+ before :all do
325
+ WebMock.disable_net_connect!
326
+ end
327
+
328
+ after :all do
329
+ WebMock.allow_net_connect!
330
+ end
331
+
332
+ before do
333
+ stub_request(:get, remote_url)
334
+ .to_return({
335
+ :body => input_block,
336
+ :status => 200
337
+ })
338
+ end
339
+
340
+ let(:settings) do
341
+ mock_settings( "path.config" => remote_url)
342
+ end
343
+
344
+ it "returns a config" do
345
+ expect(subject.pipeline_configs.first.config_string).to include(input_block)
346
+ end
347
+
348
+ context "when `config.string` is set" do
349
+ let(:settings) do
350
+ mock_settings(
351
+ "path.config" => remote_url,
352
+ "config.string" => filter_block
353
+ )
354
+ end
355
+
356
+ it "returns a merged config" do
357
+ expect(subject.pipeline_configs.first.config_string).to include(input_block, filter_block)
358
+ end
359
+ end
360
+ end
361
+
362
+ context "incomplete configuration" do
363
+ context "when the input block is missing" do
364
+ let(:settings) { mock_settings( "config.string" => "#{filter_block} #{output_block}") }
365
+
366
+ it "add stdin input" do
367
+ expect(subject.pipeline_configs.first.config_string).to include(LogStash::Config::Defaults.input)
368
+ end
369
+ end
370
+
371
+ context "when the output block is missing" do
372
+ let(:settings) { mock_settings( "config.string" => "#{input_block} #{filter_block}") }
373
+
374
+ it "add stdout output" do
375
+ expect(subject.pipeline_configs.first.config_string).to include(LogStash::Config::Defaults.output)
376
+ end
377
+ end
378
+
379
+ context "when both the output block and input block are missing" do
380
+ let(:settings) { mock_settings( "config.string" => "#{filter_block}") }
381
+
382
+ it "add stdin and output" do
383
+ expect(subject.pipeline_configs.first.config_string).to include(LogStash::Config::Defaults.output, LogStash::Config::Defaults.input)
384
+ end
385
+ end
386
+
387
+ context "when it has an input and an output" do
388
+ let(:settings) { mock_settings( "config.string" => "#{input_block} #{filter_block} #{output_block}") }
389
+
390
+ it "doesn't add anything" do
391
+ expect(subject.pipeline_configs.first.config_string).not_to include(LogStash::Config::Defaults.output, LogStash::Config::Defaults.input)
392
+ end
393
+ end
394
+ end
395
+ end