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

Sign up to get free protection for your applications and to get access to all the features.

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