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.
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