fluent-plugin-label-router 0.1.3 → 0.2.4
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 +5 -5
- data/README.md +103 -25
- data/fluent-plugin-label-router.gemspec +1 -1
- data/lib/fluent/plugin/out_label_router.rb +104 -30
- data/test/plugin/test_out_label_router.rb +153 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e7a22624dbabbce0daa1bcf3d6845bf15e377d9453a5e733ad6c91b1c9d886d5
|
4
|
+
data.tar.gz: 5cb0f6eed3e37706bd2f09c0f399acd4fb6dc714aadb7d9879309575904dccfe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1240df83181e1e6188121c48dbffc4fbe226c756064155e1457dd2478aae79d6740dcb5b403202fd2ef0d55b7850f1937e6aed9f414dc73615f24f5ae3e0f2a
|
7
|
+
data.tar.gz: 13093eb11d980427a8bc5540612da4bca7a199a6aa848c2054ec157a930b4db372cd6c6ceed4ec854f783e165bfe7448f6ad53add6409f150460b49f522ea1e4
|
data/README.md
CHANGED
@@ -32,7 +32,10 @@ $ bundle
|
|
32
32
|
|
33
33
|
## Configuration
|
34
34
|
|
35
|
-
The configuration builds from `<route>` sections.
|
35
|
+
The configuration builds from `<route>` sections. Each `route` section
|
36
|
+
can have several `<match>` statement. These statements computed in order and
|
37
|
+
positive (or in case of *negate true* negative) results break the evaluation.
|
38
|
+
We can say that the sections are coupled in a **lazy evaluation OR**.
|
36
39
|
|
37
40
|
```
|
38
41
|
<match example.tag**>
|
@@ -41,32 +44,88 @@ The configuration builds from `
|
|
41
44
|
...
|
42
45
|
</route>
|
43
46
|
<route>
|
44
|
-
|
47
|
+
<match>
|
48
|
+
...
|
49
|
+
</match>
|
50
|
+
<match> #Exclude
|
51
|
+
negate true
|
52
|
+
...
|
53
|
+
</match>
|
45
54
|
</route>
|
46
55
|
</match>
|
47
56
|
```
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
|
|
52
|
-
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
Configuration reference
|
59
|
+
|
60
|
+
| Parameter | Description | Type | Default |
|
61
|
+
|---------------|--------------------------------------------------------------------------------------------------------|---------|---------|
|
62
|
+
| emit_mode | Emit mode. If `batch`, the plugin will emit events per labels matched. Enum: record, batch | enum | batch |
|
63
|
+
| sticky_tags | Sticky tags will match only one record from an event stream. The same tag will be treated the same way | bool | true |
|
64
|
+
| default_route | If defined all non-matching record passes to this label. | string | "" |
|
65
|
+
| default_tag | If defined all non-matching record rewrited to this tag. (Can be used with label simoultanesly) | string | "" |
|
66
|
+
| \<route\> | Route the log if match with parameters defined | []route | nil |
|
67
|
+
|
68
|
+
#### \<route\>
|
69
|
+
| Parameter | Description | Type | Default |
|
70
|
+
|---------------|--------------------------------------------------------------------------------------------------------|---------|---------|
|
71
|
+
| @label | Route the matching record to the given `label` | string | "" |
|
72
|
+
| tag | Tag the matching record to the given `tag` | string | "" |
|
73
|
+
| \<match\> | List of match statements. Repeatable. | []match | nil |
|
74
|
+
|
75
|
+
|
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
|
+
| 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 |
|
84
|
+
|
85
|
+
## Rules of thumb
|
86
|
+
|
87
|
+
1. Defining more than one namespace in `namespaces` inside a `match` statement
|
88
|
+
will check whether any of that namespaces matches.
|
89
|
+
|
90
|
+
2. Using `sticky_tags` means that only the **first** record will be analysed per `tag`.
|
91
|
+
Keep that in mind if you are ingesting traffic that is not unique on a per tag bases.
|
92
|
+
Fluentd and fluent-bit tail logs from Kubernetes are unique per container.
|
93
|
+
|
94
|
+
3. The plugin does not check if the configuration is valid so be careful to not define
|
95
|
+
statements like identical `match` statement with negate because the negate rule will never
|
96
|
+
be evaluated.
|
57
97
|
|
58
98
|
## Examples
|
59
99
|
|
60
|
-
### 1. Route specific `labels` and `
|
100
|
+
### 1. Route specific `labels` and `namespaces` to `@label` and new `tag`
|
61
101
|
Configuration to re-tag and re-label all logs from `default` namespace with label `app=nginx` and `env=dev`.
|
62
102
|
```
|
63
103
|
<match example.tag**>
|
64
104
|
@type label_router
|
65
105
|
<route>
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
106
|
+
@label @NGINX
|
107
|
+
tag new_tag
|
108
|
+
<match>
|
109
|
+
labels app:nginx,env:dev
|
110
|
+
namespaces default
|
111
|
+
</match>
|
112
|
+
</route>
|
113
|
+
</match>
|
114
|
+
```
|
115
|
+
|
116
|
+
### 2. Exclude specific `labels` and `namespaces`
|
117
|
+
Configuration to re-tag and re-label all logs that **not** from `default` namespace **and not** have labels `ap=nginx` and `env=dev`
|
118
|
+
```
|
119
|
+
<match example.tag**>
|
120
|
+
@type label_router
|
121
|
+
<route>
|
122
|
+
@label @NGINX
|
123
|
+
tag new_tag
|
124
|
+
<match>
|
125
|
+
negate true
|
126
|
+
labels app:nginx,env:dev
|
127
|
+
namespaces default
|
128
|
+
</match>
|
70
129
|
</route>
|
71
130
|
</match>
|
72
131
|
```
|
@@ -91,9 +150,11 @@ Only `labels`
|
|
91
150
|
<match example.tag**>
|
92
151
|
@type label_router
|
93
152
|
<route>
|
94
|
-
|
95
|
-
|
96
|
-
|
153
|
+
@label @NGINX
|
154
|
+
tag new_tag
|
155
|
+
<match>
|
156
|
+
labels app:nginx
|
157
|
+
</match>
|
97
158
|
</route>
|
98
159
|
</match>
|
99
160
|
```
|
@@ -102,9 +163,11 @@ Only `namespace`
|
|
102
163
|
<match example.tag**>
|
103
164
|
@type label_router
|
104
165
|
<route>
|
105
|
-
|
106
|
-
|
107
|
-
|
166
|
+
@label @NGINX
|
167
|
+
tag new_tag
|
168
|
+
<match>
|
169
|
+
namespaces default
|
170
|
+
</match>
|
108
171
|
</route>
|
109
172
|
</match>
|
110
173
|
```
|
@@ -112,16 +175,31 @@ Rewrite all
|
|
112
175
|
```
|
113
176
|
<match example.tag**>
|
114
177
|
@type label_router
|
115
|
-
<
|
116
|
-
|
117
|
-
|
118
|
-
</
|
178
|
+
<match>
|
179
|
+
@label @NGINX
|
180
|
+
tag new_tag
|
181
|
+
</match>
|
119
182
|
</match>
|
120
183
|
```
|
121
184
|
|
122
185
|
### 3. One of `@label` ot `tag` configuration should be specified
|
123
186
|
If you don't rewrite either of them fluent will **likely to crash** because it will reprocess the same messages again.
|
124
187
|
|
188
|
+
### 4. Default route/tag
|
189
|
+
|
190
|
+
Use `default_label` and/or `default_tag` to route non matching records.
|
191
|
+
|
192
|
+
```
|
193
|
+
<match example.tag**>
|
194
|
+
@type label_router
|
195
|
+
default_route @default_sink
|
196
|
+
<route>
|
197
|
+
...
|
198
|
+
</route>
|
199
|
+
</match>
|
200
|
+
```
|
201
|
+
|
202
|
+
|
125
203
|
## Copyright
|
126
204
|
|
127
205
|
* Copyright(c) 2019- Banzai Cloud
|
@@ -26,33 +26,77 @@ module Fluent
|
|
26
26
|
#record_accessor_create("log")
|
27
27
|
#record_accessor_create("$.key1.key2")
|
28
28
|
#record_accessor_create("$['key1'][0]['key2']")
|
29
|
+
desc "Emit mode. If `batch`, the plugin will emit events per labels matched."
|
30
|
+
config_param :emit_mode, :enum, list: [:record, :batch], default: :batch
|
31
|
+
desc "Sticky tags will match only one record from an event stream. The same tag will be treated the same way"
|
32
|
+
config_param :sticky_tags, :bool, default: true
|
33
|
+
desc "Default label to drain unmatched patterns"
|
34
|
+
config_param :default_route, :string, :default => ""
|
35
|
+
desc "Default tag to drain unmatched patterns"
|
36
|
+
config_param :default_tag, :string, :default => ""
|
29
37
|
|
30
38
|
config_section :route, param_name: :routes, multi: true do
|
31
|
-
desc "Label definition to match record. Example: app:nginx. You can specify more values as comma separated list: key1:value1,key2:value2"
|
32
|
-
config_param :labels, :hash, :default => {}
|
33
|
-
desc "Namespaces definition to filter the record. Ignored if left empty."
|
34
|
-
config_param :namespace, :string, :default => ""
|
35
39
|
desc "New @LABEL if selectors matched"
|
36
40
|
config_param :@label, :string, :default => nil
|
37
41
|
desc "New tag if selectors matched"
|
38
42
|
config_param :tag, :string, :default => ""
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
|
44
|
+
config_section :match, param_name: :matches, multi: true do
|
45
|
+
desc "Label definition to match record. Example: app:nginx. You can specify more values as comma separated list: key1:value1,key2:value2"
|
46
|
+
config_param :labels, :hash, :default => {}
|
47
|
+
desc "List of namespace definition to filter the record. Ignored if left empty."
|
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
|
53
|
+
desc "Negate the selection making it an exclude"
|
54
|
+
config_param :negate, :bool, :default => false
|
55
|
+
end
|
43
56
|
end
|
44
57
|
|
45
58
|
class Route
|
46
|
-
def initialize(
|
59
|
+
def initialize(matches, tag, router)
|
47
60
|
@router = router
|
48
|
-
@
|
49
|
-
@namespace = namespace
|
61
|
+
@matches = matches
|
50
62
|
@tag = tag
|
51
63
|
end
|
52
64
|
|
53
|
-
|
54
|
-
|
55
|
-
|
65
|
+
# Evaluate selectors
|
66
|
+
# We evaluate <match> statements in order:
|
67
|
+
# 1. If match == true and negate == false -> return true
|
68
|
+
# 2. If match == true and negate == true -> return false
|
69
|
+
# 3. If match == false and negate == false -> continue
|
70
|
+
# 4. If match == false and negate == true -> continue
|
71
|
+
# There is no match at all -> return false
|
72
|
+
def match?(metadata)
|
73
|
+
@matches.each do |match|
|
74
|
+
if filter_select(match, metadata) and !match.negate
|
75
|
+
return true
|
76
|
+
end
|
77
|
+
if filter_select(match, metadata) and match.negate
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns true if filter passes (filter match)
|
85
|
+
def filter_select(match, metadata)
|
86
|
+
# Break on container_name mismatch
|
87
|
+
unless match.hosts.empty? || match.hosts.include?(metadata[:host])
|
88
|
+
return false
|
89
|
+
end
|
90
|
+
# Break on host mismatch
|
91
|
+
unless match.container_names.empty? || match.container_names.include?(metadata[:container])
|
92
|
+
return false
|
93
|
+
end
|
94
|
+
# Break if list of namespaces is not empty and does not include actual namespace
|
95
|
+
unless match.namespaces.empty? || match.namespaces.include?(metadata[:namespace])
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
|
99
|
+
match_labels(metadata[:labels], match.labels)
|
56
100
|
end
|
57
101
|
|
58
102
|
def emit(tag, time, record)
|
@@ -70,29 +114,38 @@ module Fluent
|
|
70
114
|
@router.emit_stream(@tag, es)
|
71
115
|
end
|
72
116
|
end
|
117
|
+
|
73
118
|
def match_labels(input, match)
|
74
|
-
|
119
|
+
(match.to_a - input.to_a).empty?
|
75
120
|
end
|
76
121
|
end
|
77
122
|
|
78
123
|
def process(tag, es)
|
79
124
|
if @sticky_tags
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
125
|
+
@mutex.synchronize {
|
126
|
+
if @route_map.has_key?(tag)
|
127
|
+
# We already matched with this tag send events to the routers
|
128
|
+
@route_map[tag].each do |r|
|
129
|
+
r.emit_es(tag, es.dup)
|
130
|
+
end
|
131
|
+
return
|
84
132
|
end
|
85
|
-
|
86
|
-
end
|
133
|
+
}
|
87
134
|
end
|
88
135
|
event_stream = Hash.new {|h, k| h[k] = Fluent::MultiEventStream.new }
|
89
136
|
es.each do |time, record|
|
90
|
-
|
91
|
-
|
137
|
+
input_metadata = { labels: @access_to_labels.call(record).to_h,
|
138
|
+
namespace: @access_to_namespace.call(record).to_s,
|
139
|
+
container: @access_to_container_name.call(record).to_s,
|
140
|
+
host: @access_to_host.call(record).to_s}
|
141
|
+
orphan_record = true
|
92
142
|
@routers.each do |r|
|
93
|
-
if r.match?(
|
143
|
+
if r.match?(input_metadata)
|
144
|
+
orphan_record = false
|
94
145
|
if @sticky_tags
|
95
|
-
@
|
146
|
+
@mutex.synchronize {
|
147
|
+
@route_map[tag].add(r)
|
148
|
+
}
|
96
149
|
end
|
97
150
|
if @batch
|
98
151
|
event_stream[r].add(time, record)
|
@@ -101,25 +154,46 @@ module Fluent
|
|
101
154
|
end
|
102
155
|
end
|
103
156
|
end
|
104
|
-
if
|
105
|
-
|
106
|
-
|
157
|
+
if !@default_router.nil? && orphan_record
|
158
|
+
if @sticky_tags
|
159
|
+
@mutex.synchronize {
|
160
|
+
@route_map[tag].add(@default_router)
|
161
|
+
}
|
162
|
+
end
|
163
|
+
if @batch
|
164
|
+
event_stream[@default_router].add(time, record)
|
165
|
+
else
|
166
|
+
@default_router.emit(tag, time, record.dup)
|
107
167
|
end
|
108
168
|
end
|
109
169
|
end
|
170
|
+
if @batch
|
171
|
+
event_stream.each do |r, es|
|
172
|
+
r.emit_es(tag, es.dup)
|
173
|
+
end
|
174
|
+
end
|
110
175
|
end
|
111
176
|
|
112
177
|
def configure(conf)
|
113
178
|
super
|
114
|
-
@route_map = Hash.new { |h, k| h[k] =
|
179
|
+
@route_map = Hash.new { |h, k| h[k] = Set.new }
|
180
|
+
@mutex = Mutex.new
|
115
181
|
@routers = []
|
182
|
+
@default_router = nil
|
116
183
|
@routes.each do |rule|
|
117
184
|
route_router = event_emitter_router(rule['@label'])
|
118
|
-
|
185
|
+
puts rule
|
186
|
+
@routers << Route.new(rule.matches, rule.tag.to_s, route_router)
|
187
|
+
end
|
188
|
+
|
189
|
+
if @default_route != '' or @default_tag != ''
|
190
|
+
@default_router = Route.new(nil, @default_tag, event_emitter_router(@default_route))
|
119
191
|
end
|
120
192
|
|
121
193
|
@access_to_labels = record_accessor_create("$.kubernetes.labels")
|
122
194
|
@access_to_namespace = record_accessor_create("$.kubernetes.namespace_name")
|
195
|
+
@access_to_host = record_accessor_create("$.kubernetes.host")
|
196
|
+
@access_to_container_name = record_accessor_create("$.kubernetes.container_name")
|
123
197
|
|
124
198
|
@batch = @emit_mode == :batch
|
125
199
|
end
|
@@ -34,11 +34,88 @@ class LabelRouterOutputTest < Test::Unit::TestCase
|
|
34
34
|
d.configure(conf)
|
35
35
|
end
|
36
36
|
|
37
|
+
sub_test_case 'test_routing' do
|
38
|
+
test 'basic configuration' do
|
39
|
+
routing_conf = %(
|
40
|
+
<route>
|
41
|
+
<match>
|
42
|
+
labels app:app1
|
43
|
+
</match>
|
44
|
+
<match>
|
45
|
+
labels app2:app2
|
46
|
+
negate true
|
47
|
+
</match>
|
48
|
+
tag new_app_tag
|
49
|
+
</route>
|
50
|
+
<route>
|
51
|
+
<match>
|
52
|
+
labels app:app1
|
53
|
+
namespaces default,test
|
54
|
+
</match>
|
55
|
+
<match>
|
56
|
+
labels app:app2
|
57
|
+
namespaces system
|
58
|
+
negate true
|
59
|
+
</match>
|
60
|
+
tag new_app_tag
|
61
|
+
</route>
|
62
|
+
<route>
|
63
|
+
<match>
|
64
|
+
labels app:nginx
|
65
|
+
namespaces dev,sandbox
|
66
|
+
</match>
|
67
|
+
</route>
|
68
|
+
<route>
|
69
|
+
<match>
|
70
|
+
labels app:nginx
|
71
|
+
namespaces dev,sandbox
|
72
|
+
container_names mycontainer
|
73
|
+
</match>
|
74
|
+
</route>
|
75
|
+
)
|
76
|
+
d = Fluent::Test::Driver::BaseOwner.new(Fluent::Plugin::LabelRouterOutput)
|
77
|
+
d.configure(routing_conf)
|
78
|
+
|
79
|
+
r1 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[0].matches, d.instance.routes[0].tag,nil)
|
80
|
+
# Selector matched: GO
|
81
|
+
assert_equal(true, r1.match?(labels: { 'app' => 'app1' }, namespace: ''))
|
82
|
+
# Exclude match: NO GO
|
83
|
+
assert_equal(false, r1.match?(labels: { 'app' => 'app2' }, namespace: ''))
|
84
|
+
# Nothing matched: NO GO
|
85
|
+
assert_equal(false, r1.match?(labels: { 'app3' => 'app2' }, namespace: ''))
|
86
|
+
|
87
|
+
r2 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[1].matches, d.instance.routes[1].tag,nil)
|
88
|
+
# Match selector and namespace: GO
|
89
|
+
assert_equal(true, r2.match?(labels: { 'app' => 'app1' }, namespace: 'test'))
|
90
|
+
# Exclude via namespace
|
91
|
+
assert_equal(false, r2.match?(labels: { 'app' => 'app2' }, namespace: 'system'))
|
92
|
+
# Nothing matched: NO GO
|
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'))
|
99
|
+
|
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: '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: 'mycontainer2'))
|
107
|
+
# Wrong label but good namespace and container_name
|
108
|
+
assert_equal(false, r4.match?(labels: { 'app' => 'nginx2' }, namespace: 'sandbox', container_name: 'mycontainer2'))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
37
112
|
sub_test_case 'test_tag' do
|
38
113
|
test 'normal' do
|
39
114
|
CONFIG = %[
|
40
115
|
<route>
|
41
|
-
|
116
|
+
<match>
|
117
|
+
labels app:app1
|
118
|
+
</match>
|
42
119
|
tag new_app_tag
|
43
120
|
</route>
|
44
121
|
]
|
@@ -56,4 +133,79 @@ class LabelRouterOutputTest < Test::Unit::TestCase
|
|
56
133
|
assert_equal ["new_app_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } }], events[0]
|
57
134
|
end
|
58
135
|
end
|
136
|
+
|
137
|
+
|
138
|
+
sub_test_case 'test_multiple_events_batched' do
|
139
|
+
test 'normal' do
|
140
|
+
conf = %[
|
141
|
+
<route>
|
142
|
+
<match>
|
143
|
+
</match>
|
144
|
+
</route>
|
145
|
+
]
|
146
|
+
event_time = event_time("2019-07-17 11:11:11 UTC")
|
147
|
+
d = create_driver(conf)
|
148
|
+
d.run(expect_emits: 1, expect_records: 2) do
|
149
|
+
d.feed("test", [
|
150
|
+
[event_time, {"kubernetes" => {} } ],
|
151
|
+
[event_time, {"kubernetes" => {} } ],
|
152
|
+
])
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
sub_test_case 'test_default_router' do
|
158
|
+
test 'normal' do
|
159
|
+
CONFIG2 = %[
|
160
|
+
<route>
|
161
|
+
<match>
|
162
|
+
labels app:app1
|
163
|
+
</match>
|
164
|
+
tag new_app_tag
|
165
|
+
</route>
|
166
|
+
default_route @default
|
167
|
+
default_tag "new_tag"
|
168
|
+
]
|
169
|
+
event_time = event_time("2019-07-17 11:11:11 UTC")
|
170
|
+
d = create_driver(CONFIG2)
|
171
|
+
d.run() do
|
172
|
+
d.feed("test", [
|
173
|
+
[event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } } ],
|
174
|
+
[event_time, {"kubernetes" => {"labels" => {"app" => "app2"} } } ],
|
175
|
+
])
|
176
|
+
end
|
177
|
+
events = d.events
|
178
|
+
|
179
|
+
assert_equal(2, events.size)
|
180
|
+
assert_equal ["new_app_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } }], events[0]
|
181
|
+
assert_equal ["new_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app2"} } }], events[1]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
sub_test_case 'test_empty_router' do
|
186
|
+
test 'normal' do
|
187
|
+
CONFIG3 = %[
|
188
|
+
<route>
|
189
|
+
tag new_app_tag
|
190
|
+
<match>
|
191
|
+
labels
|
192
|
+
namespaces
|
193
|
+
</match>
|
194
|
+
</route>
|
195
|
+
]
|
196
|
+
event_time = event_time("2019-07-17 11:11:11 UTC")
|
197
|
+
d = create_driver(CONFIG3)
|
198
|
+
d.run(default_tag: 'test') do
|
199
|
+
d.feed(event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } } )
|
200
|
+
end
|
201
|
+
d.run(default_tag: 'test2') do
|
202
|
+
d.feed(event_time, {"kubernetes" => {"labels" => {"app" => "app2"} } } )
|
203
|
+
end
|
204
|
+
events = d.events
|
205
|
+
|
206
|
+
assert_equal(2, events.size)
|
207
|
+
assert_equal ["new_app_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } }], events[0]
|
208
|
+
assert_equal ["new_app_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app2"} } }], events[1]
|
209
|
+
end
|
210
|
+
end
|
59
211
|
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.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Banzai Cloud
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -107,8 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
107
|
- !ruby/object:Gem::Version
|
108
108
|
version: '0'
|
109
109
|
requirements: []
|
110
|
-
|
111
|
-
rubygems_version: 2.5.2.3
|
110
|
+
rubygems_version: 3.0.3
|
112
111
|
signing_key:
|
113
112
|
specification_version: 4
|
114
113
|
summary: Routing records based on Kubernetes labels.
|