logstash-core 1.5.0.rc3.snapshot6-java → 1.5.0.rc4-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of logstash-core might be problematic. Click here for more details.

Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/logstash-core.rb +2 -0
  3. data/lib/logstash/agent.rb +0 -33
  4. data/lib/logstash/config/config_ast.rb +1 -1
  5. data/lib/logstash/environment.rb +8 -30
  6. data/lib/logstash/filters/base.rb +19 -0
  7. data/lib/logstash/namespace.rb +0 -1
  8. data/lib/logstash/runner.rb +3 -51
  9. data/lib/logstash/version.rb +1 -1
  10. data/logstash-core.gemspec +54 -0
  11. data/spec/core/conditionals_spec.rb +428 -0
  12. data/spec/core/config_mixin_spec.rb +99 -0
  13. data/spec/core/config_spec.rb +108 -0
  14. data/spec/core/environment_spec.rb +44 -0
  15. data/spec/core/event_spec.rb +468 -0
  16. data/spec/core/pipeline_spec.rb +198 -0
  17. data/spec/core/plugin_spec.rb +106 -0
  18. data/spec/core/runner_spec.rb +39 -0
  19. data/spec/core/timestamp_spec.rb +83 -0
  20. data/spec/filters/base_spec.rb +318 -0
  21. data/spec/inputs/base_spec.rb +13 -0
  22. data/spec/lib/logstash/bundler_spec.rb +120 -0
  23. data/spec/lib/logstash/java_integration_spec.rb +257 -0
  24. data/spec/logstash/agent_spec.rb +37 -0
  25. data/spec/outputs/base_spec.rb +47 -0
  26. data/spec/spec_helper.rb +1 -0
  27. data/spec/util/accessors_spec.rb +215 -0
  28. data/spec/util/charset_spec.rb +74 -0
  29. data/spec/util/fieldeval_spec.rb +96 -0
  30. data/spec/util/gemfile_spec.rb +212 -0
  31. data/spec/util/json_spec.rb +97 -0
  32. data/spec/util/plugin_version_spec.rb +48 -0
  33. data/spec/util_spec.rb +34 -0
  34. metadata +84 -160
  35. data/lib/logstash-event.rb +0 -2
  36. data/lib/logstash.rb +0 -4
  37. data/lib/logstash/bundler.rb +0 -156
  38. data/lib/logstash/gemfile.rb +0 -193
  39. data/lib/logstash/pluginmanager.rb +0 -17
  40. data/lib/logstash/pluginmanager/command.rb +0 -38
  41. data/lib/logstash/pluginmanager/install.rb +0 -141
  42. data/lib/logstash/pluginmanager/list.rb +0 -44
  43. data/lib/logstash/pluginmanager/main.rb +0 -21
  44. data/lib/logstash/pluginmanager/uninstall.rb +0 -43
  45. data/lib/logstash/pluginmanager/update.rb +0 -105
  46. data/lib/logstash/pluginmanager/util.rb +0 -89
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d21bfcb9c16d7eb882467cb166af49b057bd93e7
4
- data.tar.gz: 21142f47abb49cee9ee5099178e6eb5465626f46
3
+ metadata.gz: 3c6ce351055ad0f687e8fed56a9fa24a26818fa0
4
+ data.tar.gz: fa8e220cc441f294d482435d82ef8c6bb0a26b27
5
5
  SHA512:
6
- metadata.gz: b42403a2e734e88967b1c4a52e1e99382f7127d6dd9252f7511c8c140ee4fa35ab4e8c729f783293d28f48d05741a1dfe5b2d9d5c22a241f2da839c4ffd089b0
7
- data.tar.gz: ba465e71d00caf71d7c21d76b2eb6c9f205e7f2fa8383460c73a662334f999850016dd12f0265eed0de156430a434389e05076322aa79a9872a265dd995d8d93
6
+ metadata.gz: 67733788cb889660c8e6d5f29f7eb98bf2b212972b3e4ae08a02add631a7b0544aceeef4d03b1c09cf5ad83e298d29ba53d2fad9ead467e09335b274dcc20f12
7
+ data.tar.gz: 91c9d0ab6e5fabd7aa93b6880c9a5cafd3125caa9b6d62b4419c1e93bd7392c90cb834f73c4bd69d85986fbb8c1a98a745cec5e9312f6df1f046eb9ae21cd0c5
@@ -0,0 +1,2 @@
1
+ module LogStash
2
+ end
@@ -39,11 +39,6 @@ class LogStash::Agent < Clamp::Command
39
39
  option ["-V", "--version"], :flag,
40
40
  I18n.t("logstash.agent.flag.version")
41
41
 
42
- option ["-p", "--pluginpath"] , "PATH",
43
- I18n.t("logstash.agent.flag.pluginpath"),
44
- :multivalued => true,
45
- :attribute_name => :plugin_paths
46
-
47
42
  option ["-t", "--configtest"], :flag,
48
43
  I18n.t("logstash.agent.flag.configtest"),
49
44
  :attribute_name => :config_test
@@ -207,7 +202,6 @@ class LogStash::Agent < Clamp::Command
207
202
  # Log file stuff, plugin path checking, etc.
208
203
  def configure
209
204
  configure_logging(log_file)
210
- configure_plugin_path(plugin_paths) if !plugin_paths.nil?
211
205
  end # def configure
212
206
 
213
207
  # Point logging at a specific path.
@@ -258,33 +252,6 @@ class LogStash::Agent < Clamp::Command
258
252
  # http://jira.codehaus.org/browse/JRUBY-7003
259
253
  end # def configure_logging
260
254
 
261
- # Validate and add any paths to the list of locations
262
- # logstash will look to find plugins.
263
- def configure_plugin_path(paths)
264
- # Append any plugin paths to the ruby search path
265
- paths.each do |path|
266
- # Verify the path exists
267
- if !Dir.exists?(path)
268
- warn(I18n.t("logstash.agent.configuration.plugin_path_missing",
269
- :path => path))
270
-
271
- end
272
-
273
- # TODO(sissel): Verify the path looks like the correct form.
274
- # aka, there must be file in path/logstash/{inputs,codecs,filters,outputs}/*.rb
275
- plugin_glob = File.join(path, "logstash", "{inputs,codecs,filters,outputs}", "*.rb")
276
- if Dir.glob(plugin_glob).empty?
277
- @logger.warn(I18n.t("logstash.agent.configuration.no_plugins_found",
278
- :path => path, :plugin_glob => plugin_glob))
279
- end
280
-
281
- # We push plugin paths to the front of the LOAD_PATH so that folks
282
- # can override any core logstash plugins if they need to.
283
- @logger.debug("Adding plugin path", :path => path)
284
- $LOAD_PATH.unshift(path)
285
- end
286
- end # def configure_plugin_path
287
-
288
255
  def load_config(path)
289
256
  begin
290
257
  uri = URI.parse(path)
@@ -230,7 +230,7 @@ module LogStash; module Config; module AST
230
230
  return "start_input(#{variable_name})"
231
231
  when "filter"
232
232
  return <<-CODE
233
- #{variable_name}.filter(event) {|new_event| events << new_event }
233
+ events = #{variable_name}.multi_filter(events)
234
234
  CODE
235
235
  when "output"
236
236
  return "#{variable_name}.handle(event)\n"
@@ -5,19 +5,16 @@ module LogStash
5
5
  module Environment
6
6
  extend self
7
7
 
8
- LOGSTASH_HOME = ::File.expand_path(::File.join(::File.dirname(__FILE__), "..", ".."))
9
- BUNDLE_DIR = ::File.join(LOGSTASH_HOME, "vendor", "bundle")
10
- GEMFILE_PATH = ::File.join(LOGSTASH_HOME, "Gemfile")
11
- BUNDLE_CONFIG_PATH = ::File.join(LOGSTASH_HOME, ".bundle", "config")
12
- BOOTSTRAP_GEM_PATH = ::File.join(LOGSTASH_HOME, 'build', 'bootstrap')
13
- LOCAL_GEM_PATH = ::File.join(LOGSTASH_HOME, 'vendor', 'local_gems')
8
+ # rehydrate the bootstrap environment if the startup was not done by executing bootstrap.rb
9
+ # and we are in the context of the logstash package
10
+ if !LogStash::Environment.const_defined?("LOGSTASH_HOME") && !ENV["LOGSTASH_HOME"].to_s.empty?
11
+ $LOAD_PATH << ::File.join(ENV["LOGSTASH_HOME"], "lib")
12
+ require "bootstrap/environment"
13
+ end
14
14
 
15
+ LOGSTASH_CORE = ::File.expand_path(::File.join(::File.dirname(__FILE__), "..", ".."))
15
16
  LOGSTASH_ENV = (ENV["LS_ENV"] || 'production').to_s.freeze
16
17
 
17
- def logstash_gem_home
18
- ::File.join(BUNDLE_DIR, ruby_engine, gem_ruby_version)
19
- end
20
-
21
18
  def env
22
19
  LOGSTASH_ENV
23
20
  end
@@ -75,21 +72,6 @@ module LogStash
75
72
  ENV["USE_RUBY"] == "1" ? "ruby" : File.join("vendor", "jruby", "bin", "jruby")
76
73
  end
77
74
 
78
- # @return [String] major.minor ruby version, ex 1.9
79
- def ruby_abi_version
80
- RUBY_VERSION[/(\d+\.\d+)(\.\d+)*/, 1]
81
- end
82
-
83
- # @return [String] the ruby version string bundler uses to craft its gem path
84
- def gem_ruby_version
85
- RbConfig::CONFIG["ruby_version"]
86
- end
87
-
88
- # @return [String] jruby, ruby, rbx, ...
89
- def ruby_engine
90
- RUBY_ENGINE
91
- end
92
-
93
75
  def jruby?
94
76
  @jruby ||= !!(RUBY_PLATFORM == "java")
95
77
  end
@@ -102,16 +84,12 @@ module LogStash
102
84
  return ::File.join(LOGSTASH_HOME, "vendor", path)
103
85
  end
104
86
 
105
- def plugin_path(path)
106
- return ::File.join(LOGSTASH_HOME, "lib", "logstash", path)
107
- end
108
-
109
87
  def pattern_path(path)
110
88
  return ::File.join(LOGSTASH_HOME, "patterns", path)
111
89
  end
112
90
 
113
91
  def locales_path(path)
114
- return ::File.join(LOGSTASH_HOME, "locales", path)
92
+ return ::File.join(LOGSTASH_CORE, "locales", path)
115
93
  end
116
94
 
117
95
  def load_locale!
@@ -146,6 +146,25 @@ class LogStash::Filters::Base < LogStash::Plugin
146
146
  raise "#{self.class}#filter must be overidden"
147
147
  end # def filter
148
148
 
149
+ # in 1.5.0 multi_filter is meant to be used in the generated filter function in LogStash::Config::AST::Plugin only
150
+ # and is temporary until we refactor the filter method interface to accept events list and return events list,
151
+ # just list in multi_filter see https://github.com/elastic/logstash/issues/2872.
152
+ # refactoring the filter method will mean updating all plugins which we want to avoid doing for 1.5.0.
153
+ #
154
+ # @param events [Array<LogStash::Event] list of events to filter
155
+ # @return [Array<LogStash::Event] filtered events and any new events generated by the filter
156
+ public
157
+ def multi_filter(events)
158
+ result = []
159
+ events.each do |event|
160
+ unless event.cancelled?
161
+ result << event
162
+ filter(event){|new_event| result << new_event}
163
+ end
164
+ end
165
+ result
166
+ end
167
+
149
168
  public
150
169
  def execute(event, &block)
151
170
  filter(event, &block)
@@ -1,5 +1,4 @@
1
1
  # encoding: utf-8
2
- #$: << File.join(File.dirname(__FILE__), "..", "..", "vendor", "bundle")
3
2
 
4
3
  module LogStash
5
4
  module Inputs; end
@@ -1,34 +1,16 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  Thread.abort_on_exception = true
4
-
5
4
  Encoding.default_external = Encoding::UTF_8
6
- $START = Time.now
7
5
  $DEBUGLIST = (ENV["DEBUG"] || "").split(",")
8
6
 
9
- require "logstash/bundler"
10
- LogStash::Bundler.setup!
11
-
12
7
  require "logstash/environment"
8
+
13
9
  LogStash::Environment.load_locale!
14
10
 
15
11
  require "logstash/namespace"
16
12
  require "logstash/program"
17
13
 
18
- class LogStash::RSpecsRunner
19
- def initialize(args)
20
- @args = args
21
- end
22
-
23
- def run
24
- @result = RSpec::Core::Runner.run(@args)
25
- end
26
-
27
- def wait
28
- return @result
29
- end
30
- end
31
-
32
14
  class LogStash::Runner
33
15
  include LogStash::Program
34
16
 
@@ -39,7 +21,6 @@ class LogStash::Runner
39
21
  @startup_interruption_trap = Stud::trap("INT") { puts "Interrupted"; exit 0 }
40
22
 
41
23
  LogStash::Util::set_thread_name(self.class.name)
42
- #$LOAD_PATH << File.join(File.dirname(__FILE__), "..")
43
24
 
44
25
  if RUBY_VERSION < "1.9.2"
45
26
  $stderr.puts "Ruby 1.9.2 or later is required. (You are running: " + RUBY_VERSION + ")"
@@ -63,15 +44,6 @@ class LogStash::Runner
63
44
  end
64
45
  return LogStash::Agent.run($0, agent_args)
65
46
  end,
66
- "rspec" => lambda do
67
- require "rspec/core/runner"
68
- require "rspec"
69
- spec_path = File.expand_path(File.join(File.dirname(__FILE__), "/../../spec"))
70
- $LOAD_PATH << spec_path
71
- all_specs = Dir.glob(File.join(spec_path, "/**/*_spec.rb"))
72
- rspec = LogStash::RSpecsRunner.new(args.empty? ? all_specs : args)
73
- return rspec.run
74
- end,
75
47
  "irb" => lambda do
76
48
  require "irb"
77
49
  return IRB.start(__FILE__)
@@ -96,21 +68,10 @@ class LogStash::Runner
96
68
  end
97
69
  return 0
98
70
  end,
99
- "plugin" => lambda do
100
- require 'logstash/pluginmanager'
101
- plugin_manager = LogStash::PluginManager::Main.new($0)
102
- begin
103
- plugin_manager.parse(args)
104
- return plugin_manager.execute
105
- rescue Clamp::HelpWanted => e
106
- show_help(e.command)
107
- return 0
108
- end
109
- end,
110
71
  "agent" => lambda do
111
72
  require "logstash/agent"
112
73
  # Hack up a runner
113
- agent = LogStash::Agent.new($0)
74
+ agent = LogStash::Agent.new("/bin/logstash agent", $0)
114
75
  begin
115
76
  agent.parse(args)
116
77
  rescue Clamp::HelpWanted => e
@@ -146,24 +107,15 @@ For example: logstash agent --help
146
107
  Available commands:
147
108
  agent - runs the logstash agent
148
109
  version - emits version info about this logstash
149
- rspec - runs tests
150
- ]
110
+ ]
151
111
  #$stderr.puts commands.keys.map { |s| " #{s}" }.join("\n")
152
112
  return Stud::Task.new { 1 }
153
113
  end
154
114
  end # def run
155
115
 
156
- # @return true if this file is the main file being run and not via rspec
157
- def self.autorun?
158
- # caller is the current execution stack
159
- $0 == __FILE__ && caller.none?{|entry| entry =~ /rspec/}
160
- end
161
-
162
116
  private
163
117
 
164
118
  def show_help(command)
165
119
  puts command.help
166
120
  end
167
121
  end # class LogStash::Runner
168
-
169
- LogStash::Runner.new.main(ARGV) if LogStash::Runner.autorun?
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # The version of logstash.
3
- LOGSTASH_VERSION = "1.5.0-rc3.snapshot6"
3
+ LOGSTASH_VERSION = "1.5.0.rc4"
4
4
 
5
5
  # Note to authors: this should not include dashes because 'gem' barfs if
6
6
  # you include a dash in the version string.
@@ -0,0 +1,54 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'logstash/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.authors = ["Jordan Sissel", "Pete Fritchman", "Elasticsearch"]
8
+ gem.email = ["jls@semicomplete.com", "petef@databits.net", "info@elasticsearch.com"]
9
+ gem.description = %q{The core components of logstash, the scalable log and event management tool}
10
+ gem.summary = %q{logstash-core - The core components of logstash}
11
+ gem.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
12
+ gem.license = "Apache License (2.0)"
13
+
14
+ gem.files = Dir.glob(["logstash-core.gemspec", "lib/logstash-core.rb", "lib/logstash/**/*.rb", "spec/**/*.rb", "locales/*"])
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.name = "logstash-core"
17
+ gem.require_paths = ["lib"]
18
+ gem.version = LOGSTASH_VERSION.gsub(/-/, '.')
19
+
20
+ gem.add_runtime_dependency "cabin", "~> 0.7.0" #(Apache 2.0 license)
21
+ gem.add_runtime_dependency "pry", "~> 0.10.1" #(Ruby license)
22
+ gem.add_runtime_dependency "stud", "~> 0.0.19" #(Apache 2.0 license)
23
+ gem.add_runtime_dependency "clamp", "~> 0.6.5" #(MIT license) for command line args/flags
24
+ gem.add_runtime_dependency "filesize", "0.0.4" #(MIT license) for :bytes config validator
25
+
26
+ # TODO(sissel): Treetop 1.5.x doesn't seem to work well, but I haven't
27
+ # investigated what the cause might be. -Jordan
28
+ gem.add_runtime_dependency "treetop", "< 1.5.0" #(MIT license)
29
+
30
+ # upgrade i18n only post 0.6.11, see https://github.com/svenfuchs/i18n/issues/270
31
+ gem.add_runtime_dependency "i18n", "= 0.6.9" #(MIT license)
32
+
33
+ # filetools and rakelib
34
+ gem.add_runtime_dependency "minitar", "~> 0.5.4"
35
+
36
+ if RUBY_PLATFORM == 'java'
37
+ gem.platform = RUBY_PLATFORM
38
+ gem.add_runtime_dependency "jrjackson", "~> 0.2.8" #(Apache 2.0 license)
39
+ else
40
+ gem.add_runtime_dependency "oj" #(MIT-style license)
41
+ end
42
+
43
+ if RUBY_ENGINE == "rbx"
44
+ # rubinius puts the ruby stdlib into gems.
45
+ gem.add_runtime_dependency "rubysl"
46
+
47
+ # Include racc to make the xml tests pass.
48
+ # https://github.com/rubinius/rubinius/issues/2632#issuecomment-26954565
49
+ gem.add_runtime_dependency "racc"
50
+ end
51
+
52
+ gem.add_development_dependency "rspec", "~> 2.14" #(MIT license)
53
+ gem.add_development_dependency "logstash-devutils", "~> 0"
54
+ end
@@ -0,0 +1,428 @@
1
+ require 'spec_helper'
2
+
3
+ module ConditionalFanciness
4
+ def description
5
+ return example.metadata[:example_group][:description_args][0]
6
+ end
7
+
8
+ def conditional(expression, &block)
9
+ describe(expression) do
10
+ config <<-CONFIG
11
+ filter {
12
+ if #{expression} {
13
+ mutate { add_tag => "success" }
14
+ } else {
15
+ mutate { add_tag => "failure" }
16
+ }
17
+ }
18
+ CONFIG
19
+ instance_eval(&block)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "conditionals in output" do
25
+ extend ConditionalFanciness
26
+
27
+ describe "simple" do
28
+ config <<-CONFIG
29
+ input {
30
+ generator {
31
+ message => '{"foo":{"bar"},"baz": "quux"}'
32
+ count => 1
33
+ }
34
+ }
35
+ output {
36
+ if [foo] == "bar" {
37
+ stdout { }
38
+ }
39
+ }
40
+ CONFIG
41
+
42
+ agent do
43
+ #LOGSTASH-2288, should not fail raising an exception
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "conditionals in filter" do
49
+ extend ConditionalFanciness
50
+
51
+ describe "simple" do
52
+ config <<-CONFIG
53
+ filter {
54
+ mutate { add_field => { "always" => "awesome" } }
55
+ if [foo] == "bar" {
56
+ mutate { add_field => { "hello" => "world" } }
57
+ } else if [bar] == "baz" {
58
+ mutate { add_field => { "fancy" => "pants" } }
59
+ } else {
60
+ mutate { add_field => { "free" => "hugs" } }
61
+ }
62
+ }
63
+ CONFIG
64
+
65
+ sample({"foo" => "bar"}) do
66
+ expect(subject["always"]).to eq("awesome")
67
+ expect(subject["hello"]).to eq("world")
68
+ expect(subject["fancy"]).to be_nil
69
+ expect(subject["free"]).to be_nil
70
+ end
71
+
72
+ sample({"notfoo" => "bar"}) do
73
+ expect(subject["always"]).to eq("awesome")
74
+ expect(subject["hello"]).to be_nil
75
+ expect(subject["fancy"]).to be_nil
76
+ expect(subject["free"]).to eq("hugs")
77
+ end
78
+
79
+ sample({"bar" => "baz"}) do
80
+ expect(subject["always"]).to eq("awesome")
81
+ expect(subject["hello"]).to be_nil
82
+ expect(subject["fancy"]).to eq("pants")
83
+ expect(subject["free"]).to be_nil
84
+ end
85
+ end
86
+
87
+ describe "nested" do
88
+ config <<-CONFIG
89
+ filter {
90
+ if [nest] == 123 {
91
+ mutate { add_field => { "always" => "awesome" } }
92
+ if [foo] == "bar" {
93
+ mutate { add_field => { "hello" => "world" } }
94
+ } else if [bar] == "baz" {
95
+ mutate { add_field => { "fancy" => "pants" } }
96
+ } else {
97
+ mutate { add_field => { "free" => "hugs" } }
98
+ }
99
+ }
100
+ }
101
+ CONFIG
102
+
103
+ sample("foo" => "bar", "nest" => 124) do
104
+ expect(subject["always"]).to be_nil
105
+ expect(subject["hello"]).to be_nil
106
+ expect(subject["fancy"]).to be_nil
107
+ expect(subject["free"]).to be_nil
108
+ end
109
+
110
+ sample("foo" => "bar", "nest" => 123) do
111
+ expect(subject["always"]).to eq("awesome")
112
+ expect(subject["hello"]).to eq("world")
113
+ expect(subject["fancy"]).to be_nil
114
+ expect(subject["free"]).to be_nil
115
+ end
116
+
117
+ sample("notfoo" => "bar", "nest" => 123) do
118
+ expect(subject["always"]).to eq("awesome")
119
+ expect(subject["hello"]).to be_nil
120
+ expect(subject["fancy"]).to be_nil
121
+ expect(subject["free"]).to eq("hugs")
122
+ end
123
+
124
+ sample("bar" => "baz", "nest" => 123) do
125
+ expect(subject["always"]).to eq("awesome")
126
+ expect(subject["hello"]).to be_nil
127
+ expect(subject["fancy"]).to eq("pants")
128
+ expect(subject["free"]).to be_nil
129
+ end
130
+ end
131
+
132
+ describe "comparing two fields" do
133
+ config <<-CONFIG
134
+ filter {
135
+ if [foo] == [bar] {
136
+ mutate { add_tag => woot }
137
+ }
138
+ }
139
+ CONFIG
140
+
141
+ sample("foo" => 123, "bar" => 123) do
142
+ expect(subject["tags"] ).to include("woot")
143
+ end
144
+ end
145
+
146
+ describe "the 'in' operator" do
147
+ config <<-CONFIG
148
+ filter {
149
+ if [foo] in [foobar] {
150
+ mutate { add_tag => "field in field" }
151
+ }
152
+ if [foo] in "foo" {
153
+ mutate { add_tag => "field in string" }
154
+ }
155
+ if "hello" in [greeting] {
156
+ mutate { add_tag => "string in field" }
157
+ }
158
+ if [foo] in ["hello", "world", "foo"] {
159
+ mutate { add_tag => "field in list" }
160
+ }
161
+ if [missing] in [alsomissing] {
162
+ mutate { add_tag => "shouldnotexist" }
163
+ }
164
+ if !("foo" in ["hello", "world"]) {
165
+ mutate { add_tag => "shouldexist" }
166
+ }
167
+ }
168
+ CONFIG
169
+
170
+ sample("foo" => "foo", "foobar" => "foobar", "greeting" => "hello world") do
171
+ expect(subject["tags"]).to include("field in field")
172
+ expect(subject["tags"]).to include("field in string")
173
+ expect(subject["tags"]).to include("string in field")
174
+ expect(subject["tags"]).to include("field in list")
175
+ expect(subject["tags"]).not_to include("shouldnotexist")
176
+ expect(subject["tags"]).to include("shouldexist")
177
+ end
178
+ end
179
+
180
+ describe "the 'not in' operator" do
181
+ config <<-CONFIG
182
+ filter {
183
+ if "foo" not in "baz" { mutate { add_tag => "baz" } }
184
+ if "foo" not in "foo" { mutate { add_tag => "foo" } }
185
+ if !("foo" not in "foo") { mutate { add_tag => "notfoo" } }
186
+ if "foo" not in [somelist] { mutate { add_tag => "notsomelist" } }
187
+ if "one" not in [somelist] { mutate { add_tag => "somelist" } }
188
+ if "foo" not in [alsomissing] { mutate { add_tag => "no string in missing field" } }
189
+ }
190
+ CONFIG
191
+
192
+ sample("foo" => "foo", "somelist" => [ "one", "two" ], "foobar" => "foobar", "greeting" => "hello world", "tags" => [ "fancypantsy" ]) do
193
+ # verify the original exists
194
+ expect(subject["tags"]).to include("fancypantsy")
195
+
196
+ expect(subject["tags"]).to include("baz")
197
+ expect(subject["tags"]).not_to include("foo")
198
+ expect(subject["tags"]).to include("notfoo")
199
+ expect(subject["tags"]).to include("notsomelist")
200
+ expect(subject["tags"]).not_to include("somelist")
201
+ expect(subject["tags"]).to include("no string in missing field")
202
+ end
203
+ end
204
+
205
+ describe "operators" do
206
+ conditional "[message] == 'sample'" do
207
+ sample("sample") { expect(subject["tags"] ).to include("success") }
208
+ sample("different") { expect(subject["tags"] ).to include("failure") }
209
+ end
210
+
211
+ conditional "[message] != 'sample'" do
212
+ sample("sample") { expect(subject["tags"] ).to include("failure") }
213
+ sample("different") { expect(subject["tags"] ).to include("success") }
214
+ end
215
+
216
+ conditional "[message] < 'sample'" do
217
+ sample("apple") { expect(subject["tags"] ).to include("success") }
218
+ sample("zebra") { expect(subject["tags"] ).to include("failure") }
219
+ end
220
+
221
+ conditional "[message] > 'sample'" do
222
+ sample("zebra") { expect(subject["tags"] ).to include("success") }
223
+ sample("apple") { expect(subject["tags"] ).to include("failure") }
224
+ end
225
+
226
+ conditional "[message] <= 'sample'" do
227
+ sample("apple") { expect(subject["tags"] ).to include("success") }
228
+ sample("zebra") { expect(subject["tags"] ).to include("failure") }
229
+ sample("sample") { expect(subject["tags"] ).to include("success") }
230
+ end
231
+
232
+ conditional "[message] >= 'sample'" do
233
+ sample("zebra") { expect(subject["tags"] ).to include("success") }
234
+ sample("sample") { expect(subject["tags"] ).to include("success") }
235
+ sample("apple") { expect(subject["tags"] ).to include("failure") }
236
+ end
237
+
238
+ conditional "[message] =~ /sample/" do
239
+ sample("apple") { expect(subject["tags"] ).to include("failure") }
240
+ sample("sample") { expect(subject["tags"] ).to include("success") }
241
+ sample("some sample") { expect(subject["tags"] ).to include("success") }
242
+ end
243
+
244
+ conditional "[message] !~ /sample/" do
245
+ sample("apple") { expect(subject["tags"]).to include("success") }
246
+ sample("sample") { expect(subject["tags"]).to include("failure") }
247
+ sample("some sample") { expect(subject["tags"]).to include("failure") }
248
+ end
249
+
250
+ end
251
+
252
+ describe "negated expressions" do
253
+ conditional "!([message] == 'sample')" do
254
+ sample("sample") { expect(subject["tags"]).not_to include("success") }
255
+ sample("different") { expect(subject["tags"]).not_to include("failure") }
256
+ end
257
+
258
+ conditional "!([message] != 'sample')" do
259
+ sample("sample") { expect(subject["tags"]).not_to include("failure") }
260
+ sample("different") { expect(subject["tags"]).not_to include("success") }
261
+ end
262
+
263
+ conditional "!([message] < 'sample')" do
264
+ sample("apple") { expect(subject["tags"]).not_to include("success") }
265
+ sample("zebra") { expect(subject["tags"]).not_to include("failure") }
266
+ end
267
+
268
+ conditional "!([message] > 'sample')" do
269
+ sample("zebra") { expect(subject["tags"]).not_to include("success") }
270
+ sample("apple") { expect(subject["tags"]).not_to include("failure") }
271
+ end
272
+
273
+ conditional "!([message] <= 'sample')" do
274
+ sample("apple") { expect(subject["tags"]).not_to include("success") }
275
+ sample("zebra") { expect(subject["tags"]).not_to include("failure") }
276
+ sample("sample") { expect(subject["tags"]).not_to include("success") }
277
+ end
278
+
279
+ conditional "!([message] >= 'sample')" do
280
+ sample("zebra") { expect(subject["tags"]).not_to include("success") }
281
+ sample("sample") { expect(subject["tags"]).not_to include("success") }
282
+ sample("apple") { expect(subject["tags"]).not_to include("failure") }
283
+ end
284
+
285
+ conditional "!([message] =~ /sample/)" do
286
+ sample("apple") { expect(subject["tags"]).not_to include("failure") }
287
+ sample("sample") { expect(subject["tags"]).not_to include("success") }
288
+ sample("some sample") { expect(subject["tags"]).not_to include("success") }
289
+ end
290
+
291
+ conditional "!([message] !~ /sample/)" do
292
+ sample("apple") { expect(subject["tags"]).not_to include("success") }
293
+ sample("sample") { expect(subject["tags"]).not_to include("failure") }
294
+ sample("some sample") { expect(subject["tags"]).not_to include("failure") }
295
+ end
296
+
297
+ end
298
+
299
+ describe "value as an expression" do
300
+ # testing that a field has a value should be true.
301
+ conditional "[message]" do
302
+ sample("apple") { expect(subject["tags"]).to include("success") }
303
+ sample("sample") { expect(subject["tags"]).to include("success") }
304
+ sample("some sample") { expect(subject["tags"]).to include("success") }
305
+ end
306
+
307
+ # testing that a missing field has a value should be false.
308
+ conditional "[missing]" do
309
+ sample("apple") { expect(subject["tags"]).to include("failure") }
310
+ sample("sample") { expect(subject["tags"]).to include("failure") }
311
+ sample("some sample") { expect(subject["tags"]).to include("failure") }
312
+ end
313
+ end
314
+
315
+ describe "logic operators" do
316
+ describe "and" do
317
+ conditional "[message] and [message]" do
318
+ sample("whatever") { expect(subject["tags"]).to include("success") }
319
+ end
320
+ conditional "[message] and ![message]" do
321
+ sample("whatever") { expect(subject["tags"]).to include("failure") }
322
+ end
323
+ conditional "![message] and [message]" do
324
+ sample("whatever") { expect(subject["tags"]).to include("failure") }
325
+ end
326
+ conditional "![message] and ![message]" do
327
+ sample("whatever") { expect(subject["tags"]).to include("failure") }
328
+ end
329
+ end
330
+
331
+ describe "or" do
332
+ conditional "[message] or [message]" do
333
+ sample("whatever") { expect(subject["tags"]).to include("success") }
334
+ end
335
+ conditional "[message] or ![message]" do
336
+ sample("whatever") { expect(subject["tags"]).to include("success") }
337
+ end
338
+ conditional "![message] or [message]" do
339
+ sample("whatever") { expect(subject["tags"]).to include("success") }
340
+ end
341
+ conditional "![message] or ![message]" do
342
+ sample("whatever") { expect(subject["tags"]).to include("failure") }
343
+ end
344
+ end
345
+ end
346
+
347
+ describe "field references" do
348
+ conditional "[field with space]" do
349
+ sample("field with space" => "hurray") do
350
+ expect(subject["tags"]).to include("success")
351
+ end
352
+ end
353
+
354
+ conditional "[field with space] == 'hurray'" do
355
+ sample("field with space" => "hurray") do
356
+ expect(subject["tags"]).to include("success")
357
+ end
358
+ end
359
+
360
+ conditional "[nested field][reference with][some spaces] == 'hurray'" do
361
+ sample({"nested field" => { "reference with" => { "some spaces" => "hurray" } } }) do
362
+ expect(subject["tags"]).to include("success")
363
+ end
364
+ end
365
+ end
366
+
367
+ describe "new events from root" do
368
+ config <<-CONFIG
369
+ filter {
370
+ if [type] == "original" {
371
+ clone {
372
+ clones => ["clone"]
373
+ }
374
+ }
375
+ if [type] == "original" {
376
+ mutate { add_field => { "cond1" => "true" } }
377
+ } else {
378
+ mutate { add_field => { "cond2" => "true" } }
379
+ }
380
+ }
381
+ CONFIG
382
+
383
+ sample({"type" => "original"}) do
384
+ expect(subject).to be_an(Array)
385
+ expect(subject.length).to eq(2)
386
+
387
+ expect(subject[0]["type"]).to eq("original")
388
+ expect(subject[0]["cond1"]).to eq("true")
389
+ expect(subject[0]["cond2"]).to eq(nil)
390
+
391
+ expect(subject[1]["type"]).to eq("clone")
392
+ # expect(subject[1]["cond1"]).to eq(nil)
393
+ # expect(subject[1]["cond2"]).to eq("true")
394
+ end
395
+ end
396
+
397
+ describe "multiple new events from root" do
398
+ config <<-CONFIG
399
+ filter {
400
+ if [type] == "original" {
401
+ clone {
402
+ clones => ["clone1", "clone2"]
403
+ }
404
+ }
405
+ if [type] == "clone1" {
406
+ mutate { add_field => { "cond1" => "true" } }
407
+ } else if [type] == "clone2" {
408
+ mutate { add_field => { "cond2" => "true" } }
409
+ }
410
+ }
411
+ CONFIG
412
+
413
+ sample({"type" => "original"}) do
414
+ # puts subject.inspect
415
+ expect(subject[0]["cond1"]).to eq(nil)
416
+ expect(subject[0]["cond2"]).to eq(nil)
417
+
418
+ expect(subject[1]["type"]).to eq("clone1")
419
+ expect(subject[1]["cond1"]).to eq("true")
420
+ expect(subject[1]["cond2"]).to eq(nil)
421
+
422
+ expect(subject[2]["type"]).to eq("clone2")
423
+ expect(subject[2]["cond1"]).to eq(nil)
424
+ expect(subject[2]["cond2"]).to eq("true")
425
+ end
426
+ end
427
+
428
+ end