logstash-mixin-ecs_compatibility_support 1.1.0-java → 1.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/README.md +19 -2
- data/lib/logstash/plugin_mixins/ecs_compatibility_support.rb +4 -0
- data/lib/logstash/plugin_mixins/ecs_compatibility_support/selector.rb +55 -6
- data/lib/logstash/plugin_mixins/ecs_compatibility_support/spec_helper.rb +3 -5
- data/spec/logstash/plugin_mixins/ecs_compatibility_support/selector_spec.rb +34 -0
- data/spec/logstash/plugin_mixins/ecs_compatibility_support/spec_helper_spec.rb +2 -2
- data/spec/logstash/plugin_mixins/ecs_compatibility_support_spec.rb +7 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6ff73bf503783cc17b6fbc2ebebcf23398d52ffa01cfc2a9d397566833f9706
|
4
|
+
data.tar.gz: 69d950da27ad60c8fdb09a08e72f7a4ffce9ede7e85cad0bfb130854cf40a07b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5334c125b5e9b24567500ae94546b3acd5260d7f83232eaa173439d68e8d974ca294f4a3f5b0c33d0d760ac4d843ea67bcb920b0713f480848e6d5044a43895b
|
7
|
+
data.tar.gz: 3b5bddca9732f6f03f79d4bf8ebf0dbeedb120dd7b23703f68c7e8410f5896e7124e343a2a843ce0346eeee6463c02bf738d1add11fed102f7c12e4147707e8f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
-
# 1.
|
1
|
+
# 1.2.0
|
2
|
+
- Added support for resolution aliases, allowing a plugin that uses `ecs_select` to support multiple ECS versions with a single declaration.
|
3
|
+
|
4
|
+
# 1.1.0
|
5
|
+
- Added support for `ecs_select` helper, allowing plugins to declare mappings that are selected during plugin instantiation.
|
2
6
|
|
7
|
+
# 1.0.0
|
3
8
|
- Support Mixin for ensuring a plugin has an `ecs_compatibility` method that is configurable from an `ecs_compatibility` option that accepts the literal `disabled` or a v-prefixed integer representing a major ECS version (e.g., `v1`), using the implementation from Logstash core if available.
|
data/README.md
CHANGED
@@ -67,13 +67,13 @@ during initialization based on the instantiated plugin's effective
|
|
67
67
|
mappings, because it allows those mappings to be side-by-side where they are
|
68
68
|
unlikely to diverge and introduce bugs.
|
69
69
|
|
70
|
-
1. Add version `~>1.
|
70
|
+
1. Add version `~>1.2` of this gem as a runtime dependency of your Logstash plugin's `gemspec`:
|
71
71
|
|
72
72
|
~~~ ruby
|
73
73
|
Gem::Specification.new do |s|
|
74
74
|
# ...
|
75
75
|
|
76
|
-
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.
|
76
|
+
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.2'
|
77
77
|
end
|
78
78
|
~~~
|
79
79
|
|
@@ -95,6 +95,20 @@ unlikely to diverge and introduce bugs.
|
|
95
95
|
whether that mode was explicitly defined for the plugin instance or implictly
|
96
96
|
defined by the pipeline in which the plugin is run.
|
97
97
|
|
98
|
+
You can also optionally provide an alias mapping, for when your plugin supports
|
99
|
+
multiple versions of ECS that are largely identical to each other. This can be
|
100
|
+
especially helpful when using `ecs_select`.
|
101
|
+
|
102
|
+
~~~ ruby
|
103
|
+
require 'logstash/plugin_mixins/ecs_compatibility_support'
|
104
|
+
|
105
|
+
class LogStash::Inputs::Foo < Logstash::Inputs::Base
|
106
|
+
include LogStash::PluginMixins::ECSCompatibilitySupport(:disabled,:v1,:v8 => :v1)
|
107
|
+
|
108
|
+
# ...
|
109
|
+
end
|
110
|
+
~~~
|
111
|
+
|
98
112
|
3. As in the simple usage example, you can use the `ecs_compatibility` method.
|
99
113
|
|
100
114
|
But when supported versions are specified, you can also use the `ecs_select`
|
@@ -108,6 +122,9 @@ unlikely to diverge and introduce bugs.
|
|
108
122
|
end
|
109
123
|
~~~
|
110
124
|
|
125
|
+
If you initialized the mixin with an alias mapping, missing values will
|
126
|
+
be resolved by their alias.
|
127
|
+
|
111
128
|
NOTE: `ecs_select` should only be used during plugin initialization and
|
112
129
|
not during event-by-event processing.
|
113
130
|
|
@@ -101,6 +101,10 @@ module LogStash
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
+
##
|
105
|
+
# @override ECSCompatibilitySupport(*supported_versions, alias_map={})
|
106
|
+
# @param supported_versions [Array[Symbol]]: the supported ECS versions
|
107
|
+
# @param alias_map [Hash{Symbol=>Symbol}]: an optional mapping of aliases (keys) to supported version (values)
|
104
108
|
def self.ECSCompatibilitySupport(*supported_versions)
|
105
109
|
return ECSCompatibilitySupport if supported_versions.empty?
|
106
110
|
|
@@ -26,14 +26,31 @@ module LogStash
|
|
26
26
|
base.include(ECSCompatibilitySupport)
|
27
27
|
end
|
28
28
|
|
29
|
+
EMPTY_HASH = {}.freeze
|
30
|
+
private_constant :EMPTY_HASH
|
31
|
+
|
29
32
|
##
|
30
33
|
# @api private
|
31
34
|
# @see ECSCompatibilitySupport()
|
32
35
|
# @param ecs_modes_supported
|
33
|
-
def initialize(*
|
36
|
+
def initialize(*ecs_modes_and_optional_alias_map)
|
37
|
+
selector_module = self
|
38
|
+
|
39
|
+
alias_mapping = ecs_modes_and_optional_alias_map.last.kind_of?(Hash) ? ecs_modes_and_optional_alias_map.pop.dup.freeze : EMPTY_HASH
|
40
|
+
ecs_modes_supported = ecs_modes_and_optional_alias_map.dup
|
41
|
+
|
34
42
|
fail(ArgumentError, "one or more ecs_modes_supported required") if ecs_modes_supported.empty?
|
35
43
|
fail(ArgumentError, "ecs_modes_supported must only contain symbols") unless ecs_modes_supported.all? { |s| s.kind_of?(Symbol) }
|
36
44
|
|
45
|
+
fail(ArgumentError, "alias names must be symbols") unless alias_mapping.keys.all? { |v| v.kind_of?(Symbol) }
|
46
|
+
fail(ArgumentError, "alias targets must be symbols") unless alias_mapping.values.all? { |v| v.kind_of?(Symbol) }
|
47
|
+
fail(ArgumentError, "alias must not redefine") if alias_mapping.keys.any? {|v| ecs_modes_supported.include?(v) }
|
48
|
+
fail(ArgumentError, "alias map must not have circular references") if circular_references_present?(alias_mapping)
|
49
|
+
|
50
|
+
ecs_modes_supported |= alias_mapping.keys
|
51
|
+
|
52
|
+
fail(ArgumentError, "alias target doesn't exist") if alias_mapping.values.any? { |v| !ecs_modes_supported.include?(v) }
|
53
|
+
|
37
54
|
ecs_modes_supported.freeze
|
38
55
|
|
39
56
|
##
|
@@ -49,7 +66,7 @@ module LogStash
|
|
49
66
|
"Supported modes are: #{ecs_modes_supported}"
|
50
67
|
fail(LogStash::ConfigurationError, message)
|
51
68
|
end
|
52
|
-
@_ecs_select =
|
69
|
+
@_ecs_select = selector_module.state_for(effective_ecs_mode)
|
53
70
|
end
|
54
71
|
|
55
72
|
##
|
@@ -58,6 +75,13 @@ module LogStash
|
|
58
75
|
define_method(:ecs_select) { @_ecs_select }
|
59
76
|
|
60
77
|
define_singleton_method(:ecs_modes_supported) { ecs_modes_supported }
|
78
|
+
|
79
|
+
define_singleton_method(:state_for) do |selected_value|
|
80
|
+
unless ecs_modes_supported.include?(selected_value)
|
81
|
+
fail(NotImplementedError, "Unsupported state `#{selected_value}` (expected one of #{ecs_modes_supported})")
|
82
|
+
end
|
83
|
+
State.new(ecs_modes_supported, selected_value, alias_mapping)
|
84
|
+
end
|
61
85
|
end
|
62
86
|
|
63
87
|
##
|
@@ -66,6 +90,21 @@ module LogStash
|
|
66
90
|
"#{Selector}(#{ecs_modes_supported.join(',')})"
|
67
91
|
end
|
68
92
|
|
93
|
+
private
|
94
|
+
|
95
|
+
def circular_references_present?(alias_candidates)
|
96
|
+
alias_candidates.each do |candidate, target|
|
97
|
+
current = target
|
98
|
+
(alias_candidates.size + 1).times do
|
99
|
+
return true if current == candidate
|
100
|
+
break unless alias_candidates.include?(current)
|
101
|
+
current = alias_candidates.fetch(current)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
false
|
106
|
+
end
|
107
|
+
|
69
108
|
##
|
70
109
|
# A `State` contains the active mode and a list of all supported modes.
|
71
110
|
#
|
@@ -77,12 +116,15 @@ module LogStash
|
|
77
116
|
# @api private
|
78
117
|
class State
|
79
118
|
##
|
80
|
-
# @api private
|
119
|
+
# @api private -- Use Selector#state_for(current_value)
|
81
120
|
# @param supported_modes [Array<Symbol>]
|
82
121
|
# @param active_mode [Symbol]
|
83
|
-
def initialize(supported_modes, active_mode)
|
122
|
+
def initialize(supported_modes, active_mode, alias_map=EMPTY_HASH)
|
123
|
+
fail(ArgumentError, "invalid alias mapping") unless alias_map.flatten.all? {|v| supported_modes.include?(v) }
|
124
|
+
|
84
125
|
@supported_modes = supported_modes
|
85
126
|
@active_mode = active_mode
|
127
|
+
@alias_map = alias_map
|
86
128
|
end
|
87
129
|
|
88
130
|
attr_reader :active_mode
|
@@ -102,13 +144,20 @@ module LogStash
|
|
102
144
|
|
103
145
|
fail(ArgumentError, "at least one choice must be defined") if defined_choices.empty?
|
104
146
|
|
105
|
-
missing = @supported_modes - defined_choices.keys
|
147
|
+
missing = @supported_modes - (defined_choices.keys + @alias_map.keys)
|
106
148
|
fail(ArgumentError, "missing one or more required choice definition #{missing}") if missing.any?
|
107
149
|
|
108
150
|
unknown = defined_choices.keys - @supported_modes
|
109
151
|
fail(ArgumentError, "unknown choices #{unknown}; valid choices are #{@supported_modes}") if unknown.any?
|
110
152
|
|
111
|
-
|
153
|
+
# resolve aliases of missing choices
|
154
|
+
effective_mode = @active_mode
|
155
|
+
@alias_map.size.times do # theoretical upper limit of alias chain
|
156
|
+
break if defined_choices.include?(effective_mode)
|
157
|
+
effective_mode = @alias_map.fetch(effective_mode)
|
158
|
+
end
|
159
|
+
|
160
|
+
defined_choices.fetch(effective_mode)
|
112
161
|
end
|
113
162
|
alias_method :[], :value_from
|
114
163
|
end
|
@@ -28,15 +28,13 @@ module LogStash
|
|
28
28
|
# ~~~
|
29
29
|
module SpecHelper
|
30
30
|
def ecs_compatibility_matrix(*supported_modes,&block)
|
31
|
-
|
32
|
-
fail(ArgumentError, "ecs_compatibility_matrix(*supported_modes) requires one or more symbol supported_modes")
|
33
|
-
end
|
31
|
+
ecs_selector = Selector.new(*supported_modes)
|
34
32
|
|
35
|
-
|
33
|
+
ecs_selector.ecs_modes_supported.each do |active_mode|
|
36
34
|
context "`ecs_compatibility => #{active_mode}`" do
|
37
35
|
let(:ecs_compatibility) { active_mode }
|
38
36
|
|
39
|
-
ecs_select =
|
37
|
+
ecs_select = ecs_selector.state_for(active_mode)
|
40
38
|
instance_exec(ecs_select, &block)
|
41
39
|
end
|
42
40
|
end
|
@@ -34,6 +34,27 @@ describe LogStash::PluginMixins::ECSCompatibilitySupport::Selector do
|
|
34
34
|
expect(selector_mod.name).to include('v1')
|
35
35
|
end
|
36
36
|
end
|
37
|
+
it 'accepts an alias list' do
|
38
|
+
selector_mod = described_class.new(:disabled, :v1, :v8 => :v1)
|
39
|
+
aggregate_failures do
|
40
|
+
expect(selector_mod.ecs_modes_supported).to contain_exactly(:disabled, :v1, :v8)
|
41
|
+
expect(selector_mod.name).to include('disabled')
|
42
|
+
expect(selector_mod.name).to include('v1')
|
43
|
+
expect(selector_mod.name).to include('v8')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
it 'rejects alias list that doesnt resolve' do
|
47
|
+
expect { described_class.new(:disabled, :v1, :v8 => :v2) }.to raise_error(ArgumentError, /alias target/)
|
48
|
+
end
|
49
|
+
it 'rejects tight circular aliases' do
|
50
|
+
expect { described_class.new(:disabled, :v1, :v8 => :v8) }.to raise_error(ArgumentError, /circular/)
|
51
|
+
end
|
52
|
+
it 'rejects loose circular aliases' do
|
53
|
+
expect { described_class.new(:disabled, :v1, :v8 => :v7, :v7 => :v6, :v6 => :v8) }.to raise_error(ArgumentError, /circular/)
|
54
|
+
end
|
55
|
+
it 'rejects alias that redefines concrete definition' do
|
56
|
+
expect { described_class.new(:disabled, :v1, :v1 => :disabled) }.to raise_error(ArgumentError, /redefine/)
|
57
|
+
end
|
37
58
|
end
|
38
59
|
context 'included into a class' do
|
39
60
|
let(:ecs_compatibility_support) { LogStash::PluginMixins::ECSCompatibilitySupport }
|
@@ -111,6 +132,19 @@ describe LogStash::PluginMixins::ECSCompatibilitySupport::Selector do
|
|
111
132
|
it 'selects the correct effective value' do
|
112
133
|
expect(ecs_select[disabled: "nope", v1: "winner"]).to eq("winner")
|
113
134
|
end
|
135
|
+
context 'when aliases are given' do
|
136
|
+
let(:ecs_supported_modes) { [:disabled, :v1, :v8 => :v2, :v2 => :v1 ] }
|
137
|
+
let(:ecs_effective_mode) { :v8 }
|
138
|
+
it 'selects a given value' do
|
139
|
+
expect(ecs_select[disabled: "nope", v1: "nah", v8: "hooray"]).to eq("hooray")
|
140
|
+
end
|
141
|
+
it 'resolves the deepest alias of a missing value' do
|
142
|
+
expect(ecs_select[disabled: "sad-trombone", v1: "wahoo"]).to eq("wahoo")
|
143
|
+
end
|
144
|
+
it 'resolves the intermediate alias of a missing value' do
|
145
|
+
expect(ecs_select[disabled: "sad-trombone", v1: "oh-no", v2: "nice"]).to eq("nice")
|
146
|
+
end
|
147
|
+
end
|
114
148
|
end
|
115
149
|
end
|
116
150
|
end
|
@@ -6,14 +6,14 @@ require "logstash/plugin_mixins/ecs_compatibility_support/spec_helper"
|
|
6
6
|
|
7
7
|
describe LogStash::PluginMixins::ECSCompatibilitySupport::SpecHelper, :ecs_compatibility_support do
|
8
8
|
context '::ecs_compatibility_matrix(*modes)' do
|
9
|
-
ecs_compatibility_matrix(:disabled,:v1) do |ecs_select|
|
9
|
+
ecs_compatibility_matrix(:disabled,:v1,:v8 => :v1) do |ecs_select|
|
10
10
|
it("sets `ecs_compatibility` with the current active mode `#{ecs_select.active_mode}`") do
|
11
11
|
expect(ecs_compatibility).to eq(ecs_select.active_mode)
|
12
12
|
end
|
13
13
|
context 'the yielded value' do
|
14
14
|
subject { ecs_select }
|
15
15
|
it { is_expected.to be_a_kind_of LogStash::PluginMixins::ECSCompatibilitySupport::Selector::State }
|
16
|
-
its(:supported_modes) { is_expected.to contain_exactly(:disabled,:v1) }
|
16
|
+
its(:supported_modes) { is_expected.to contain_exactly(:disabled,:v1,:v8) }
|
17
17
|
its(:active_mode) { is_expected.to be ecs_compatibility }
|
18
18
|
end
|
19
19
|
end
|
@@ -155,5 +155,12 @@ describe 'LogStash::PluginMixins::ECSCompatibilitySupport()' do
|
|
155
155
|
expect(selector_module.ecs_modes_supported).to contain_exactly(:disabled,:v1)
|
156
156
|
end
|
157
157
|
end
|
158
|
+
context 'with symbol arguments and alias mapping' do
|
159
|
+
it 'returns a properly-configured LogStash::PluginMixins::ECSCompatibilitySupport::Selector' do
|
160
|
+
selector_module = LogStash::PluginMixins::ECSCompatibilitySupport(:disabled,:v1,:v8 => :v1)
|
161
|
+
expect(selector_module).to be_a_kind_of(LogStash::PluginMixins::ECSCompatibilitySupport::Selector)
|
162
|
+
expect(selector_module.ecs_modes_supported).to contain_exactly(:disabled,:v1,:v8)
|
163
|
+
end
|
164
|
+
end
|
158
165
|
end
|
159
166
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-mixin-ecs_compatibility_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|