fluent-plugin-kubernetes_metadata_filter 2.5.2 → 2.11.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.
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
5
+ # Kubernetes metadata
6
+ #
7
+ # Copyright 2015 Red Hat, Inc.
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+ class KubernetesMetadataCacheStatsTest < Test::Unit::TestCase
22
+ include KubernetesMetadata::Util
23
+
24
+ def setup
25
+ @time_fields = ['time']
26
+ @internal_time = Time.now
27
+ end
28
+
29
+ test '#create_time_from_record when time is empty' do
30
+ record = { 'time' => ' ' }
31
+ assert_equal(@internal_time.to_i, create_time_from_record(record, @internal_time).to_i)
32
+ end
33
+ test '#create_time_from_record when time is nil' do
34
+ record = {}
35
+ assert_equal(@internal_time.to_i, create_time_from_record(record, @internal_time).to_i)
36
+ end
37
+
38
+ test '#create_time_from_record when time is an integer' do
39
+ exp_time = Time.now
40
+ record = { 'time' => exp_time.to_i }
41
+ assert_equal(exp_time.to_i, create_time_from_record(record, @internal_time).to_i)
42
+ end
43
+
44
+ test '#create_time_from_record when time is a string' do
45
+ exp_time = Time.now
46
+ record = { 'time' => exp_time.to_s }
47
+ assert_equal(exp_time.to_i, create_time_from_record(record, @internal_time).to_i)
48
+ end
49
+
50
+ test '#create_time_from_record when timefields include journal time fields' do
51
+ @time_fields = ['_SOURCE_REALTIME_TIMESTAMP']
52
+ exp_time = Time.now
53
+ record = { '_SOURCE_REALTIME_TIMESTAMP' => exp_time.to_i.to_s }
54
+ assert_equal(Time.at(exp_time.to_i / 1_000_000, exp_time.to_i % 1_000_000).to_i, create_time_from_record(record, @internal_time).to_i)
55
+ end
56
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
3
5
  # Kubernetes metadata
@@ -17,206 +19,227 @@
17
19
  # limitations under the License.
18
20
  #
19
21
  require_relative '../helper'
20
- require 'ostruct'
21
22
  require_relative 'watch_test'
22
23
 
23
24
  class WatchNamespacesTestTest < WatchTest
25
+ include KubernetesMetadata::WatchNamespaces
26
+
27
+ setup do
28
+ @initial = {
29
+ kind: 'NamespaceList',
30
+ metadata: { resourceVersion: '123' },
31
+ items: [
32
+ {
33
+ metadata: {
34
+ name: 'initial',
35
+ uid: 'initial_uid'
36
+ }
37
+ },
38
+ {
39
+ metadata: {
40
+ name: 'modified',
41
+ uid: 'modified_uid'
42
+ }
43
+ }
44
+ ]
45
+ }
46
+
47
+ @created = {
48
+ type: 'CREATED',
49
+ object: {
50
+ metadata: {
51
+ name: 'created',
52
+ uid: 'created_uid'
53
+ }
54
+ }
55
+ }
56
+ @modified = {
57
+ type: 'MODIFIED',
58
+ object: {
59
+ metadata: {
60
+ name: 'foo',
61
+ uid: 'modified_uid'
62
+ }
63
+ }
64
+ }
65
+ @deleted = {
66
+ type: 'DELETED',
67
+ object: {
68
+ metadata: {
69
+ name: 'deleteme',
70
+ uid: 'deleted_uid'
71
+ }
72
+ }
73
+ }
74
+ @error = {
75
+ type: 'ERROR',
76
+ object: {
77
+ message: 'some error message'
78
+ }
79
+ }
80
+ @gone = {
81
+ type: 'ERROR',
82
+ object: {
83
+ code: 410,
84
+ kind: 'Status',
85
+ message: 'too old resource version: 123 (391079)',
86
+ metadata: {
87
+ name: 'gone',
88
+ namespace: 'gone',
89
+ uid: 'gone_uid'
90
+ },
91
+ reason: 'Gone'
92
+ }
93
+ }
94
+ end
95
+
96
+ test 'namespace list caches namespaces' do
97
+ @client.stub :get_namespaces, @initial do
98
+ process_namespace_watcher_notices(start_namespace_watch)
99
+ assert_equal(true, @namespace_cache.key?('initial_uid'))
100
+ assert_equal(true, @namespace_cache.key?('modified_uid'))
101
+ assert_equal(2, @stats[:namespace_cache_host_updates])
102
+ end
103
+ end
24
104
 
25
- include KubernetesMetadata::WatchNamespaces
26
-
27
- setup do
28
- @initial = Kubeclient::Common::EntityList.new(
29
- 'NamespaceList',
30
- '123',
31
- [
32
- Kubeclient::Resource.new({
33
- 'metadata' => {
34
- 'name' => 'initial',
35
- 'uid' => 'initial_uid'
36
- }
37
- }),
38
- Kubeclient::Resource.new({
39
- 'metadata' => {
40
- 'name' => 'modified',
41
- 'uid' => 'modified_uid'
42
- }
43
- })
44
- ])
45
-
46
- @created = OpenStruct.new(
47
- type: 'CREATED',
48
- object: {
49
- 'metadata' => {
50
- 'name' => 'created',
51
- 'uid' => 'created_uid'
52
- }
53
- }
54
- )
55
- @modified = OpenStruct.new(
56
- type: 'MODIFIED',
57
- object: {
58
- 'metadata' => {
59
- 'name' => 'foo',
60
- 'uid' => 'modified_uid'
61
- }
62
- }
63
- )
64
- @deleted = OpenStruct.new(
65
- type: 'DELETED',
66
- object: {
67
- 'metadata' => {
68
- 'name' => 'deleteme',
69
- 'uid' => 'deleted_uid'
70
- }
71
- }
72
- )
73
- @error = OpenStruct.new(
74
- type: 'ERROR',
75
- object: {
76
- 'message' => 'some error message'
77
- }
78
- )
79
- @gone = OpenStruct.new(
80
- type: 'ERROR',
81
- object: {
82
- 'code' => 410,
83
- 'kind' => 'Status',
84
- 'message' => 'too old resource version: 123 (391079)',
85
- 'metadata' => {
86
- 'name' => 'gone',
87
- 'namespace' => 'gone',
88
- 'uid' => 'gone_uid'
89
- },
90
- 'reason' => 'Gone'
91
- }
92
- )
93
- end
94
-
95
- test 'namespace list caches namespaces' do
96
- @client.stub :get_namespaces, @initial do
105
+ test 'namespace list caches namespaces and watch updates' do
106
+ orig_env_val = ENV['K8S_NODE_NAME']
107
+ ENV['K8S_NODE_NAME'] = 'aNodeName'
108
+ @client.stub :get_namespaces, @initial do
109
+ @client.stub :watch_namespaces, [@modified] do
97
110
  process_namespace_watcher_notices(start_namespace_watch)
98
- assert_equal(true, @namespace_cache.key?('initial_uid'))
99
- assert_equal(true, @namespace_cache.key?('modified_uid'))
100
111
  assert_equal(2, @stats[:namespace_cache_host_updates])
112
+ assert_equal(1, @stats[:namespace_cache_watch_updates])
101
113
  end
102
114
  end
115
+ ENV['K8S_NODE_NAME'] = orig_env_val
116
+ end
103
117
 
104
- test 'namespace list caches namespaces and watch updates' do
105
- orig_env_val = ENV['K8S_NODE_NAME']
106
- ENV['K8S_NODE_NAME'] = 'aNodeName'
107
- @client.stub :get_namespaces, @initial do
108
- @client.stub :watch_namespaces, [@modified] do
109
- process_namespace_watcher_notices(start_namespace_watch)
110
- assert_equal(2, @stats[:namespace_cache_host_updates])
111
- assert_equal(1, @stats[:namespace_cache_watch_updates])
112
- end
113
- end
114
- ENV['K8S_NODE_NAME'] = orig_env_val
118
+ test 'namespace watch ignores CREATED' do
119
+ @client.stub :watch_namespaces, [@created] do
120
+ process_namespace_watcher_notices(start_namespace_watch)
121
+ assert_equal(false, @namespace_cache.key?('created_uid'))
122
+ assert_equal(1, @stats[:namespace_cache_watch_ignored])
115
123
  end
124
+ end
116
125
 
117
- test 'namespace watch ignores CREATED' do
118
- @client.stub :watch_namespaces, [@created] do
119
- process_namespace_watcher_notices(start_namespace_watch)
120
- assert_equal(false, @namespace_cache.key?('created_uid'))
121
- assert_equal(1, @stats[:namespace_cache_watch_ignored])
122
- end
126
+ test 'namespace watch ignores MODIFIED when info not in cache' do
127
+ @client.stub :watch_namespaces, [@modified] do
128
+ process_namespace_watcher_notices(start_namespace_watch)
129
+ assert_equal(false, @namespace_cache.key?('modified_uid'))
130
+ assert_equal(1, @stats[:namespace_cache_watch_misses])
123
131
  end
132
+ end
124
133
 
125
- test 'namespace watch ignores MODIFIED when info not in cache' do
126
- @client.stub :watch_namespaces, [@modified] do
127
- process_namespace_watcher_notices(start_namespace_watch)
128
- assert_equal(false, @namespace_cache.key?('modified_uid'))
129
- assert_equal(1, @stats[:namespace_cache_watch_misses])
130
- end
134
+ test 'namespace watch updates cache when MODIFIED is received and info is cached' do
135
+ @namespace_cache['modified_uid'] = {}
136
+ @client.stub :watch_namespaces, [@modified] do
137
+ process_namespace_watcher_notices(start_namespace_watch)
138
+ assert_equal(true, @namespace_cache.key?('modified_uid'))
139
+ assert_equal(1, @stats[:namespace_cache_watch_updates])
131
140
  end
141
+ end
132
142
 
133
- test 'namespace watch updates cache when MODIFIED is received and info is cached' do
134
- @namespace_cache['modified_uid'] = {}
135
- @client.stub :watch_namespaces, [@modified] do
136
- process_namespace_watcher_notices(start_namespace_watch)
137
- assert_equal(true, @namespace_cache.key?('modified_uid'))
138
- assert_equal(1, @stats[:namespace_cache_watch_updates])
139
- end
143
+ test 'namespace watch ignores DELETED' do
144
+ @namespace_cache['deleted_uid'] = {}
145
+ @client.stub :watch_namespaces, [@deleted] do
146
+ process_namespace_watcher_notices(start_namespace_watch)
147
+ assert_equal(true, @namespace_cache.key?('deleted_uid'))
148
+ assert_equal(1, @stats[:namespace_cache_watch_deletes_ignored])
140
149
  end
150
+ end
141
151
 
142
- test 'namespace watch ignores DELETED' do
143
- @namespace_cache['deleted_uid'] = {}
144
- @client.stub :watch_namespaces, [@deleted] do
145
- process_namespace_watcher_notices(start_namespace_watch)
146
- assert_equal(true, @namespace_cache.key?('deleted_uid'))
147
- assert_equal(1, @stats[:namespace_cache_watch_deletes_ignored])
152
+ test 'namespace watch raises Fluent::UnrecoverableError when cannot re-establish connection to k8s API server' do
153
+ # Stub start_namespace_watch to simulate initial successful connection to API server
154
+ stub(self).start_namespace_watch
155
+ # Stub watch_namespaces to simluate not being able to set up watch connection to API server
156
+ stub(@client).watch_namespaces { raise }
157
+ @client.stub :get_namespaces, @initial do
158
+ assert_raise Fluent::UnrecoverableError do
159
+ set_up_namespace_thread
148
160
  end
149
161
  end
162
+ assert_equal(3, @stats[:namespace_watch_failures])
163
+ assert_equal(2, Thread.current[:namespace_watch_retry_count])
164
+ assert_equal(4, Thread.current[:namespace_watch_retry_backoff_interval])
165
+ assert_nil(@stats[:namespace_watch_error_type_notices])
166
+ end
150
167
 
151
- test 'namespace watch retries when exceptions are encountered' do
152
- @client.stub :get_namespaces, @initial do
153
- @client.stub :watch_namespaces, [[@created, @exception_raised]] do
154
- assert_raise Fluent::UnrecoverableError do
168
+ test 'namespace watch resets watch retry count when exceptions are encountered and connection to k8s API server is re-established' do
169
+ @client.stub :get_namespaces, @initial do
170
+ @client.stub :watch_namespaces, [[@created, @exception_raised]] do
171
+ # Force the infinite watch loop to exit after 3 seconds. Verifies that
172
+ # no unrecoverable error was thrown during this period of time.
173
+ assert_raise Timeout::Error.new('execution expired') do
174
+ Timeout.timeout(3) do
155
175
  set_up_namespace_thread
156
176
  end
157
- assert_equal(3, @stats[:namespace_watch_failures])
158
- assert_equal(2, Thread.current[:namespace_watch_retry_count])
159
- assert_equal(4, Thread.current[:namespace_watch_retry_backoff_interval])
160
- assert_nil(@stats[:namespace_watch_error_type_notices])
161
177
  end
178
+ assert_operator(@stats[:namespace_watch_failures], :>=, 3)
179
+ assert_operator(Thread.current[:namespace_watch_retry_count], :<=, 1)
180
+ assert_operator(Thread.current[:namespace_watch_retry_backoff_interval], :<=, 1)
162
181
  end
163
182
  end
183
+ end
164
184
 
165
- test 'namespace watch retries when error is received' do
166
- @client.stub :get_namespaces, @initial do
167
- @client.stub :watch_namespaces, [@error] do
168
- assert_raise Fluent::UnrecoverableError do
185
+ test 'namespace watch resets watch retry count when error is received and connection to k8s API server is re-established' do
186
+ @client.stub :get_namespaces, @initial do
187
+ @client.stub :watch_namespaces, [@error] do
188
+ # Force the infinite watch loop to exit after 3 seconds. Verifies that
189
+ # no unrecoverable error was thrown during this period of time.
190
+ assert_raise Timeout::Error.new('execution expired') do
191
+ Timeout.timeout(3) do
169
192
  set_up_namespace_thread
170
193
  end
171
- assert_equal(3, @stats[:namespace_watch_failures])
172
- assert_equal(2, Thread.current[:namespace_watch_retry_count])
173
- assert_equal(4, Thread.current[:namespace_watch_retry_backoff_interval])
174
- assert_equal(3, @stats[:namespace_watch_error_type_notices])
175
194
  end
195
+ assert_operator(@stats[:namespace_watch_failures], :>=, 3)
196
+ assert_operator(Thread.current[:namespace_watch_retry_count], :<=, 1)
197
+ assert_operator(Thread.current[:namespace_watch_retry_backoff_interval], :<=, 1)
176
198
  end
177
199
  end
200
+ end
178
201
 
179
- test 'namespace watch continues after retries succeed' do
180
- @client.stub :get_namespaces, @initial do
181
- @client.stub :watch_namespaces, [@modified, @error, @modified] do
182
- # Force the infinite watch loop to exit after 3 seconds. Verifies that
183
- # no unrecoverable error was thrown during this period of time.
184
- assert_raise Timeout::Error.new('execution expired') do
185
- Timeout.timeout(3) do
186
- set_up_namespace_thread
187
- end
202
+ test 'namespace watch continues after retries succeed' do
203
+ @client.stub :get_namespaces, @initial do
204
+ @client.stub :watch_namespaces, [@modified, @error, @modified] do
205
+ # Force the infinite watch loop to exit after 3 seconds. Verifies that
206
+ # no unrecoverable error was thrown during this period of time.
207
+ assert_raise Timeout::Error.new('execution expired') do
208
+ Timeout.timeout(3) do
209
+ set_up_namespace_thread
188
210
  end
189
- assert_operator(@stats[:namespace_watch_failures], :>=, 3)
190
- assert_operator(Thread.current[:namespace_watch_retry_count], :<=, 1)
191
- assert_operator(Thread.current[:namespace_watch_retry_backoff_interval], :<=, 1)
192
- assert_operator(@stats[:namespace_watch_error_type_notices], :>=, 3)
193
211
  end
212
+ assert_operator(@stats[:namespace_watch_failures], :>=, 3)
213
+ assert_operator(Thread.current[:namespace_watch_retry_count], :<=, 1)
214
+ assert_operator(Thread.current[:namespace_watch_retry_backoff_interval], :<=, 1)
215
+ assert_operator(@stats[:namespace_watch_error_type_notices], :>=, 3)
194
216
  end
195
217
  end
218
+ end
196
219
 
197
- test 'namespace watch raises a GoneError when a 410 Gone error is received' do
198
- @cache['gone_uid'] = {}
199
- @client.stub :watch_namespaces, [@gone] do
200
- assert_raise KubernetesMetadata::Common::GoneError do
201
- process_namespace_watcher_notices(start_namespace_watch)
202
- end
203
- assert_equal(1, @stats[:namespace_watch_gone_notices])
220
+ test 'namespace watch raises a GoneError when a 410 Gone error is received' do
221
+ @cache['gone_uid'] = {}
222
+ @client.stub :watch_namespaces, [@gone] do
223
+ assert_raise KubernetesMetadata::Common::GoneError do
224
+ process_namespace_watcher_notices(start_namespace_watch)
204
225
  end
226
+ assert_equal(1, @stats[:namespace_watch_gone_notices])
205
227
  end
228
+ end
206
229
 
207
- test 'namespace watch retries when 410 Gone errors are encountered' do
208
- @client.stub :get_namespaces, @initial do
209
- @client.stub :watch_namespaces, [@created, @gone, @modified] do
210
- # Force the infinite watch loop to exit after 3 seconds. Verifies that
211
- # no unrecoverable error was thrown during this period of time.
212
- assert_raise Timeout::Error.new('execution expired') do
213
- Timeout.timeout(3) do
214
- set_up_namespace_thread
215
- end
230
+ test 'namespace watch retries when 410 Gone errors are encountered' do
231
+ @client.stub :get_namespaces, @initial do
232
+ @client.stub :watch_namespaces, [@created, @gone, @modified] do
233
+ # Force the infinite watch loop to exit after 3 seconds. Verifies that
234
+ # no unrecoverable error was thrown during this period of time.
235
+ assert_raise Timeout::Error.new('execution expired') do
236
+ Timeout.timeout(3) do
237
+ set_up_namespace_thread
216
238
  end
217
- assert_operator(@stats[:namespace_watch_gone_errors], :>=, 3)
218
- assert_operator(@stats[:namespace_watch_gone_notices], :>=, 3)
219
239
  end
240
+ assert_operator(@stats[:namespace_watch_gone_errors], :>=, 3)
241
+ assert_operator(@stats[:namespace_watch_gone_notices], :>=, 3)
220
242
  end
221
243
  end
244
+ end
222
245
  end