fluent-plugin-label-router 0.2.0 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07025a5148e5985c287b5d07e4a8f05c642d650734db78c995be11c2ee478a5e
4
- data.tar.gz: 8e787eacb12b8e12a1e2895f919128d1c755e4c553c9e5b218a7970e89f3564b
3
+ metadata.gz: d2c9fe1a41256dc29a1a7ff87833cfb6f7f4ca6e4ab330b185aa85f66e0e35b3
4
+ data.tar.gz: 2440249e93baffc3de72dd31fe70ef6d83ce5f4832b9af615a338bb855489cb4
5
5
  SHA512:
6
- metadata.gz: 8e116c6ace26a31641f467eed943f5a643c1f4c6737ea602106c43af69f40cac89fe54533b08e596d3c32f9630c5a2d1a9532f37314bdf24081c6b4aeb70a120
7
- data.tar.gz: e8d0c1c3653c047a65fc0642602a7e5e4aef3e3a341653fca64bd7e15323233c31583451591f9b744becd3f54122b55abd0d936ae48d60a63a5fc4dc640695ca
6
+ metadata.gz: 0fc6928ca8716774f8291eb013b737f31d2e6d02b34dee5d473ae644c7898aa8145aca73b3691c9ed4520165d3ee19f63da7dee72d48dc1b416c4fd54e45e79f
7
+ data.tar.gz: cc9afbd8db7ac5c1f10001c6bc91403eb9961b529773f210f3c9b2ac7bf877c792a10e18f6b04cec5b1526762238b3f081f51cce08b4d4a867ebba63f28030d7
data/README.md CHANGED
@@ -74,11 +74,13 @@ Configuration reference
74
74
 
75
75
 
76
76
  #### \<match\>
77
- | Parameter | Description | Type | Default |
78
- |------------|-------------------------------------------------------------------------------|----------|----------|
79
- | labels | Label definition to match record. Example: `app:nginx` | Hash | nil |
80
- | namespaces | Comma separated list of namespaces. Ignored if left empty. | []string | nil |
81
- | negate | Negate the selector meaning to exclude matches | bool | false |
77
+ | Parameter | Description | Type | Default |
78
+ |-----------------|-------------------------------------------------------------------------------|----------|----------|
79
+ | labels | Label definition to match record. Example: `app:nginx` | Hash | nil |
80
+ | namespaces | Comma separated list of namespaces. Ignored if left empty. | []string | nil |
81
+ | hosts | Comma separated list of hosts. Ignored if left empty. | []string | nil |
82
+ | container_names | Comma separated list of container names. Ignored if left empty. | []string | nil |
83
+ | negate | Negate the selector meaning to exclude matches | bool | false |
82
84
 
83
85
  ## Rules of thumb
84
86
 
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "fluent-plugin-label-router"
6
- spec.version = "0.2.0"
6
+ spec.version = "0.2.1"
7
7
  spec.authors = ["Banzai Cloud"]
8
8
  spec.email = ["info@banzaicloud.com"]
9
9
 
@@ -41,11 +41,15 @@ module Fluent
41
41
  desc "New tag if selectors matched"
42
42
  config_param :tag, :string, :default => ""
43
43
 
44
- config_section :match, param_name: :selectors, multi: true do
44
+ config_section :match, param_name: :matches, multi: true do
45
45
  desc "Label definition to match record. Example: app:nginx. You can specify more values as comma separated list: key1:value1,key2:value2"
46
46
  config_param :labels, :hash, :default => {}
47
47
  desc "List of namespace definition to filter the record. Ignored if left empty."
48
48
  config_param :namespaces, :array, :default => [], value_type: :string
49
+ desc "List of hosts definition to filter the record. Ignored if left empty."
50
+ config_param :hosts, :array, :default => [], value_type: :string
51
+ desc "List of container names definition to filter the record. Ignored if left empty."
52
+ config_param :container_names, :array, :default => [], value_type: :string
49
53
  desc "Negate the selection making it an exclude"
50
54
  config_param :negate, :bool, :default => false
51
55
  end
@@ -55,9 +59,9 @@ module Fluent
55
59
 
56
60
 
57
61
  class Route
58
- def initialize(selectors, tag, router)
62
+ def initialize(matches, tag, router)
59
63
  @router = router
60
- @selectors = selectors
64
+ @matches = matches
61
65
  @tag = tag
62
66
  end
63
67
 
@@ -68,12 +72,12 @@ module Fluent
68
72
  # 3. If match == false and negate == false -> continue
69
73
  # 4. If match == false and negate == true -> continue
70
74
  # There is no match at all -> return false
71
- def match?(labels, namespace)
72
- @selectors.each do |selector|
73
- if (filter_select(selector, labels, namespace) and !selector.negate)
75
+ def match?(metadata)
76
+ @matches.each do |match|
77
+ if filter_select(match, metadata) and !match.negate
74
78
  return true
75
79
  end
76
- if (filter_select(selector, labels, namespace) and selector.negate)
80
+ if filter_select(match, metadata) and match.negate
77
81
  return false
78
82
  end
79
83
  end
@@ -81,12 +85,21 @@ module Fluent
81
85
  end
82
86
 
83
87
  # Returns true if filter passes (filter match)
84
- def filter_select(selector, labels, namespace)
88
+ def filter_select(match, metadata)
89
+ # Break on container_name mismatch
90
+ unless match.hosts.empty? || match.hosts.include?(metadata[:host])
91
+ return false
92
+ end
93
+ # Break on host mismatch
94
+ unless match.container_names.empty? || match.container_names.include?(metadata[:container_name])
95
+ return false
96
+ end
85
97
  # Break if list of namespaces is not empty and does not include actual namespace
86
- unless selector.namespaces.empty? or selector.namespaces.include?(namespace)
98
+ unless match.namespaces.empty? || match.namespaces.include?(metadata[:namespace])
87
99
  return false
88
100
  end
89
- match_labels(labels, selector.labels)
101
+
102
+ match_labels(metadata[:labels], match.labels)
90
103
  end
91
104
 
92
105
  def emit(tag, time, record)
@@ -104,8 +117,9 @@ module Fluent
104
117
  @router.emit_stream(@tag, es)
105
118
  end
106
119
  end
120
+
107
121
  def match_labels(input, match)
108
- return (match.to_a - input.to_a).empty?
122
+ (match.to_a - input.to_a).empty?
109
123
  end
110
124
  end
111
125
 
@@ -121,11 +135,13 @@ module Fluent
121
135
  end
122
136
  event_stream = Hash.new {|h, k| h[k] = Fluent::MultiEventStream.new }
123
137
  es.each do |time, record|
124
- input_labels = @access_to_labels.call(record).to_h
125
- input_namespace = @access_to_namespace.call(record).to_s
138
+ input_metadata = { labels: @access_to_labels.call(record).to_h,
139
+ namespace: @access_to_namespace.call(record).to_s,
140
+ container: @access_to_container_name.call(record).to_s,
141
+ host: @access_to_host.call(record).to_s}
126
142
  orphan_record = true
127
143
  @routers.each do |r|
128
- if r.match?(input_labels, input_namespace)
144
+ if r.match?(input_metadata)
129
145
  orphan_record = false
130
146
  if @sticky_tags
131
147
  @route_map[tag].push(r)
@@ -163,7 +179,7 @@ module Fluent
163
179
  @routes.each do |rule|
164
180
  route_router = event_emitter_router(rule['@label'])
165
181
  puts rule
166
- @routers << Route.new(rule.selectors, rule.tag.to_s, route_router)
182
+ @routers << Route.new(rule.matches, rule.tag.to_s, route_router)
167
183
  end
168
184
 
169
185
  if @default_route != '' or @default_tag != ''
@@ -172,6 +188,8 @@ module Fluent
172
188
 
173
189
  @access_to_labels = record_accessor_create("$.kubernetes.labels")
174
190
  @access_to_namespace = record_accessor_create("$.kubernetes.namespace_name")
191
+ @access_to_host = record_accessor_create("$.kubernetes.host")
192
+ @access_to_container_name = record_accessor_create("$.kubernetes.container_name")
175
193
 
176
194
  @batch = @emit_mode == :batch
177
195
  end
@@ -65,29 +65,47 @@ class LabelRouterOutputTest < Test::Unit::TestCase
65
65
  namespaces dev,sandbox
66
66
  </match>
67
67
  </route>
68
+ <route>
69
+ <match>
70
+ labels app:nginx
71
+ namespaces dev,sandbox
72
+ container_names mycontainer
73
+ </match>
74
+ </route>
68
75
  )
69
76
  d = Fluent::Test::Driver::BaseOwner.new(Fluent::Plugin::LabelRouterOutput)
70
77
  d.configure(routing_conf)
71
78
 
72
- r1 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[0].selectors, "",nil)
79
+ r1 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[0].matches, d.instance.routes[0].tag,nil)
73
80
  # Selector matched: GO
74
- assert_equal(true, r1.match?({'app' => 'app1'},""))
81
+ assert_equal(true, r1.match?(labels: { 'app' => 'app1' }, namespace: ''))
75
82
  # Exclude match: NO GO
76
- assert_equal(false, r1.match?({"app" => "app2"},""))
83
+ assert_equal(false, r1.match?(labels: { 'app' => 'app2' }, namespace: ''))
77
84
  # Nothing matched: NO GO
78
- assert_equal(false, r1.match?({"app3" => "app2"},""))
85
+ assert_equal(false, r1.match?(labels: { 'app3' => 'app2' }, namespace: ''))
79
86
 
80
- r2 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[1].selectors, "",nil)
87
+ r2 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[1].matches, d.instance.routes[1].tag,nil)
81
88
  # Match selector and namespace: GO
82
- assert_equal(true, r2.match?({"app" => "app1"},"test"))
89
+ assert_equal(true, r2.match?(labels: { 'app' => 'app1' }, namespace: 'test'))
83
90
  # Exclude via namespace
84
- assert_equal(false, r2.match?({"app" => "app2"},"system"))
91
+ assert_equal(false, r2.match?(labels: { 'app' => 'app2' }, namespace: 'system'))
85
92
  # Nothing matched: NO GO
86
- assert_equal(false, r2.match?({"app3" => "app"},"system"))
93
+ assert_equal(false, r2.match?(labels: { 'app3' => 'app' }, namespace: 'system'))
94
+
95
+ r3 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[2].matches, d.instance.routes[2].tag,nil)
96
+ assert_equal(true, r3.match?(labels: { 'app' => 'nginx' }, namespace: 'dev'))
97
+ assert_equal(true, r3.match?(labels: { 'app' => 'nginx' }, namespace: 'sandbox'))
98
+ assert_equal(false, r3.match?(labels: { 'app' => 'nginx2' }, namespace: 'sandbox'))
87
99
 
88
- r3 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[2].selectors, "",nil)
89
- assert_equal(true, r3.match?({"app" => "nginx"},"dev"))
90
- assert_equal(true, r3.match?({"app" => "nginx"},"sandbox"))
100
+ r4 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[3].matches, d.instance.routes[3].tag,nil)
101
+ # Matching container name
102
+ assert_equal(true, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'dev', container_name: 'mycontainer'))
103
+ # Missing container name is equal to wrong container
104
+ assert_equal(false, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'sandbox'))
105
+ # Wrong container name
106
+ assert_equal(false, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'dev', container_name: 'mycontainer2'))
107
+ # Wrong label but good namespace and container_name
108
+ assert_equal(false, r4.match?(labels: { 'app' => 'nginx2' }, namespace: 'sandbox', container_name: 'mycontainer2'))
91
109
  end
92
110
  end
93
111
 
@@ -146,7 +164,7 @@ default_tag "new_tag"
146
164
 
147
165
  sub_test_case 'test_empty_router' do
148
166
  test 'normal' do
149
- CONFIG2 = %[
167
+ CONFIG3 = %[
150
168
  <route>
151
169
  tag new_app_tag
152
170
  <match>
@@ -156,7 +174,7 @@ default_tag "new_tag"
156
174
  </route>
157
175
  ]
158
176
  event_time = event_time("2019-07-17 11:11:11 UTC")
159
- d = create_driver(CONFIG2)
177
+ d = create_driver(CONFIG3)
160
178
  d.run(default_tag: 'test') do
161
179
  d.feed(event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } } )
162
180
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-label-router
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Banzai Cloud
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-18 00:00:00.000000000 Z
11
+ date: 2020-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler