fluent-plugin-label-router 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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