fluent-plugin-kubernetes_metadata_filter 0.26.3 → 0.27.0

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
  SHA1:
3
- metadata.gz: 955084706621e1158ce6950b1afad7702ade679e
4
- data.tar.gz: d179ade18f18f3acfe691b85471a007c1a2f6aa2
3
+ metadata.gz: 168dd4ff037a7da0fc60de77b43784416cf0bf40
4
+ data.tar.gz: 6ecb0b18c7fc0a5883ec4584dd1e7261ae94393e
5
5
  SHA512:
6
- metadata.gz: e9571f194b02beb3374ae37e7321d0c9c7ad1a0cc36d7603e5b146bd4b747b5e41f7916d4f910ad4813697331b66556b07d921dab000253f57b1115d796acc05
7
- data.tar.gz: 24c6addc93de722388f02f1b4a7e0f6031cc134cd421261429618c477e5b71967e26d117b99921db9fe4f906259e071db20762ef30ce3ad7148cbb46d2077cfd
6
+ metadata.gz: 234788bfb4c824714fc56cb165ac74480a78932bbe82f4b4bb5a02e0b491d7cedc7b6e54b23a6fef24be784184684630f5464ae87a20477f58a306a56cce72a0
7
+ data.tar.gz: d25a5dc8846f85c66b8ed99aadbc080d94a770e4cc887dbcf57c326721693cfbc88ed90db87a7a42a4c82182a2eb4974f39077b54f917fa117254d4f0cd2eaef
data/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  Configuration options for fluent.conf are:
13
13
 
14
- * `kubernetes_url` - URL to the API server. Set this to retrieve further kubernetes metadata for logs from kubernetes API server
14
+ * `kubernetes_url` - URL to the API server. Set this to retrieve further kubernetes metadata for logs from kubernetes API server. If not specified, environment variables `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` will be used if both are present which is typically true when running fluentd in a pod.
15
15
  * `apiVersion` - API version to use (default: `v1`)
16
16
  * `ca_file` - path to CA file for Kubernetes server certificate validation
17
17
  * `verify_ssl` - validate SSL certificates (default: `true`)
@@ -28,7 +28,8 @@ This must used named capture groups for `container_name`, `pod_name` & `namespac
28
28
  * `de_dot` - replace dots in labels with configured `de_dot_separator`, required for ElasticSearch 2.x compatibility (default: `true`)
29
29
  * `de_dot_separator` - separator to use if `de_dot` is enabled (default: `_`)
30
30
  * `use_journal` - If false (default), messages are expected to be formatted and tagged as if read by the fluentd in\_tail plugin with wildcard filename. If true, messages are expected to be formatted as if read from the systemd journal. The `MESSAGE` field has the full message. The `CONTAINER_NAME` field has the encoded k8s metadata (see below). The `CONTAINER_ID_FULL` field has the full container uuid. This requires docker to use the `--log-driver=journald` log driver.
31
- * `container_name_to_kubernetes_regexp` - The regular expression used to extract the k8s metadata encoded in the journal `CONTAINER_NAME` field (default: `'^k8s_(?<container_name>[^\.]+)\.(?<container_hash>[a-z0-9]{8})_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_(?<pod_id>[^_]+)_(?<pod_randhex>[a-z0-9]{8})$'`)
31
+ * `container_name_to_kubernetes_regexp` - The regular expression used to extract the k8s metadata encoded in the journal `CONTAINER_NAME` field (default: `'^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'`
32
+ * This corresponds to the definition [in the source](https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/dockertools/docker.go#L317)
32
33
  * `annotation_match` - Array of regular expressions matching annotation field names. Matched annotations are added to a log record.
33
34
 
34
35
  Reading from the JSON formatted log files with `in_tail` and wildcard filenames:
@@ -43,7 +44,7 @@ Reading from the JSON formatted log files with `in_tail` and wildcard filenames:
43
44
  read_from_head true
44
45
  </source>
45
46
 
46
- <filter kubernetes.var.log.containers.*.log>
47
+ <filter kubernetes.var.log.containers.**.log>
47
48
  type kubernetes_metadata
48
49
  </filter>
49
50
 
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "fluent-plugin-kubernetes_metadata_filter"
7
- gem.version = "0.26.3"
7
+ gem.version = "0.27.0"
8
8
  gem.authors = ["Jimmi Dyson"]
9
9
  gem.email = ["jimmidyson@gmail.com"]
10
10
  gem.description = %q{Filter plugin to add Kubernetes metadata}
@@ -39,6 +39,7 @@ module Fluent
39
39
  config_param :merge_json_log, :bool, default: true
40
40
  config_param :preserve_json_log, :bool, default: true
41
41
  config_param :include_namespace_id, :bool, default: false
42
+ config_param :include_namespace_metadata, :bool, default: false
42
43
  config_param :secret_dir, :string, default: '/var/run/secrets/kubernetes.io/serviceaccount'
43
44
  config_param :de_dot, :bool, default: true
44
45
  config_param :de_dot_separator, :string, default: '_'
@@ -50,9 +51,10 @@ module Fluent
50
51
  # Field 2 is the container_hash, field 5 is the pod_id, and field 6 is the pod_randhex
51
52
  # I would have included them as named groups, but you can't have named groups that are
52
53
  # non-capturing :P
54
+ # parse format is defined here: https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/dockertools/docker.go#L317
53
55
  config_param :container_name_to_kubernetes_regexp,
54
56
  :string,
55
- :default => '^k8s_(?<container_name>[^\.]+)\.[^_]+_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[a-f0-9]{8}$'
57
+ :default => '^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'
56
58
 
57
59
  config_param :annotation_match, :array, default: []
58
60
 
@@ -71,25 +73,45 @@ module Fluent
71
73
  newhsh
72
74
  end
73
75
 
74
- def get_metadata(namespace_name, pod_name)
76
+ def parse_pod_metadata(pod_object)
77
+ labels = syms_to_strs(pod_object['metadata']['labels'].to_h)
78
+ annotations = match_annotations(syms_to_strs(pod_object['metadata']['annotations'].to_h))
79
+ if @de_dot
80
+ self.de_dot!(labels)
81
+ self.de_dot!(annotations)
82
+ end
83
+ kubernetes_metadata = {
84
+ 'namespace_name' => pod_object['metadata']['namespace'],
85
+ 'pod_id' => pod_object['metadata']['uid'],
86
+ 'pod_name' => pod_object['metadata']['name'],
87
+ 'labels' => labels,
88
+ 'host' => pod_object['spec']['nodeName'],
89
+ 'master_url' => @kubernetes_url
90
+ }
91
+ kubernetes_metadata['annotations'] = annotations unless annotations.empty?
92
+ return kubernetes_metadata
93
+ end
94
+
95
+ def parse_namespace_metadata(namespace_object)
96
+ labels = syms_to_strs(namespace_object['metadata']['labels'].to_h)
97
+ annotations = match_annotations(syms_to_strs(namespace_object['metadata']['annotations'].to_h))
98
+ if @de_dot
99
+ self.de_dot!(labels)
100
+ self.de_dot!(annotations)
101
+ end
102
+ kubernetes_metadata = {
103
+ 'namespace_id' => namespace_object['metadata']['uid']
104
+ }
105
+ kubernetes_metadata['namespace_labels'] = labels unless labels.empty?
106
+ kubernetes_metadata['namespace_annotations'] = annotations unless annotations.empty?
107
+ return kubernetes_metadata
108
+ end
109
+
110
+ def get_pod_metadata(namespace_name, pod_name)
75
111
  begin
76
112
  metadata = @client.get_pod(pod_name, namespace_name)
77
113
  return if !metadata
78
- labels = syms_to_strs(metadata['metadata']['labels'].to_h)
79
- annotations = match_annotations(syms_to_strs(metadata['metadata']['annotations'].to_h))
80
- if @de_dot
81
- self.de_dot!(labels)
82
- self.de_dot!(annotations)
83
- end
84
- kubernetes_metadata = {
85
- 'namespace_name' => namespace_name,
86
- 'pod_id' => metadata['metadata']['uid'],
87
- 'pod_name' => pod_name,
88
- 'labels' => labels,
89
- 'host' => metadata['spec']['nodeName']
90
- }
91
- kubernetes_metadata['annotations'] = annotations unless annotations.empty?
92
- return kubernetes_metadata
114
+ return parse_pod_metadata(metadata)
93
115
  rescue KubeException
94
116
  nil
95
117
  end
@@ -110,11 +132,16 @@ module Fluent
110
132
  raise Fluent::ConfigError, "Invalid de_dot_separator: cannot be or contain '.'"
111
133
  end
112
134
 
135
+ if @include_namespace_id
136
+ # For compatibility, use include_namespace_metadata instead
137
+ @include_namespace_metadata = true
138
+ end
139
+
113
140
  if @cache_ttl < 0
114
141
  @cache_ttl = :none
115
142
  end
116
143
  @cache = LruRedux::TTL::ThreadSafeCache.new(@cache_size, @cache_ttl)
117
- if @include_namespace_id
144
+ if @include_namespace_metadata
118
145
  @namespace_cache = LruRedux::TTL::ThreadSafeCache.new(@cache_size, @cache_ttl)
119
146
  end
120
147
  @tag_to_kubernetes_name_regexp_compiled = Regexp.compile(@tag_to_kubernetes_name_regexp)
@@ -172,7 +199,7 @@ module Fluent
172
199
  if @watch
173
200
  thread = Thread.new(self) { |this| this.start_watch }
174
201
  thread.abort_on_exception = true
175
- if @include_namespace_id
202
+ if @include_namespace_metadata
176
203
  namespace_thread = Thread.new(self) { |this| this.start_namespace_watch }
177
204
  namespace_thread.abort_on_exception = true
178
205
  end
@@ -197,6 +224,42 @@ module Fluent
197
224
 
198
225
  end
199
226
 
227
+ def get_metadata_for_record(namespace_name, pod_name, container_name)
228
+ metadata = {
229
+ 'container_name' => container_name,
230
+ 'namespace_name' => namespace_name,
231
+ 'pod_name' => pod_name,
232
+ }
233
+ if @kubernetes_url.present?
234
+ cache_key = "#{namespace_name}_#{pod_name}"
235
+
236
+ this = self
237
+ pod_metadata = @cache.getset(cache_key) {
238
+ md = this.get_pod_metadata(
239
+ namespace_name,
240
+ pod_name,
241
+ )
242
+ md
243
+ }
244
+ metadata.merge!(pod_metadata) if pod_metadata
245
+
246
+ if @include_namespace_metadata
247
+ namespace_metadata = @namespace_cache.getset(namespace_name) {
248
+ begin
249
+ namespace = @client.get_namespace(namespace_name)
250
+ if namespace
251
+ parse_namespace_metadata(namespace)
252
+ end
253
+ rescue KubeException
254
+ nil
255
+ end
256
+ }
257
+ metadata.merge!(namespace_metadata) if namespace_metadata
258
+ end
259
+ end
260
+ metadata
261
+ end
262
+
200
263
  def filter_stream(tag, es)
201
264
  es
202
265
  end
@@ -211,38 +274,12 @@ module Fluent
211
274
  'docker' => {
212
275
  'container_id' => match_data['docker_id']
213
276
  },
214
- 'kubernetes' => {
215
- 'namespace_name' => match_data['namespace'],
216
- 'pod_name' => match_data['pod_name'],
217
- }
277
+ 'kubernetes' => get_metadata_for_record(
278
+ match_data['namespace'],
279
+ match_data['pod_name'],
280
+ match_data['container_name'],
281
+ ),
218
282
  }
219
-
220
- if @kubernetes_url.present?
221
- cache_key = "#{metadata['kubernetes']['namespace_name']}_#{metadata['kubernetes']['pod_name']}"
222
-
223
- this = self
224
- kubernetes_metadata = @cache.getset(cache_key) {
225
- if metadata
226
- md = this.get_metadata(
227
- metadata['kubernetes']['namespace_name'],
228
- metadata['kubernetes']['pod_name']
229
- )
230
- md
231
- end
232
- }
233
- metadata['kubernetes'].merge!(kubernetes_metadata) if kubernetes_metadata
234
-
235
- if @include_namespace_id
236
- namespace_name = metadata['kubernetes']['namespace_name']
237
- namespace_id = @namespace_cache.getset(namespace_name) {
238
- namespace = @client.get_namespace(namespace_name)
239
- namespace['metadata']['uid'] if namespace
240
- }
241
- metadata['kubernetes']['namespace_id'] = namespace_id if namespace_id
242
- end
243
- end
244
-
245
- metadata['kubernetes']['container_name'] = match_data['container_name']
246
283
  end
247
284
 
248
285
  es.each { |time, record|
@@ -269,36 +306,13 @@ module Fluent
269
306
  'docker' => {
270
307
  'container_id' => record['CONTAINER_ID_FULL']
271
308
  },
272
- 'kubernetes' => {
273
- 'namespace_name' => match_data['namespace'],
274
- 'pod_name' => match_data['pod_name']
275
- }
309
+ 'kubernetes' => get_metadata_for_record(
310
+ match_data['namespace'],
311
+ match_data['pod_name'],
312
+ match_data['container_name'],
313
+ )
276
314
  }
277
- if @kubernetes_url.present?
278
- cache_key = "#{metadata['kubernetes']['namespace_name']}_#{metadata['kubernetes']['pod_name']}"
279
-
280
- this = self
281
- kubernetes_metadata = @cache.getset(cache_key) {
282
- if metadata
283
- md = this.get_metadata(
284
- metadata['kubernetes']['namespace_name'],
285
- metadata['kubernetes']['pod_name']
286
- )
287
- md
288
- end
289
- }
290
- metadata['kubernetes'].merge!(kubernetes_metadata) if kubernetes_metadata
291
-
292
- if @include_namespace_id
293
- namespace_name = metadata['kubernetes']['namespace_name']
294
- namespace_id = @namespace_cache.getset(namespace_name) {
295
- namespace = @client.get_namespace(namespace_name)
296
- namespace['metadata']['uid'] if namespace
297
- }
298
- metadata['kubernetes']['namespace_id'] = namespace_id if namespace_id
299
- end
300
- end
301
- metadata['kubernetes']['container_name'] = match_data['container_name']
315
+
302
316
  metadata
303
317
  end
304
318
  unless metadata
@@ -361,7 +375,12 @@ module Fluent
361
375
  resource_version = @client.get_pods.resourceVersion
362
376
  watcher = @client.watch_pods(resource_version)
363
377
  rescue Exception => e
364
- raise Fluent::ConfigError, "Exception encountered fetching metadata from Kubernetes API endpoint: #{e.message}"
378
+ message = "Exception encountered fetching metadata from Kubernetes API endpoint: #{e.message}"
379
+ if e.respond_to?(:response)
380
+ message += " (#{e.response})"
381
+ end
382
+
383
+ raise Fluent::ConfigError, message
365
384
  end
366
385
 
367
386
  watcher.each do |notice|
@@ -370,16 +389,7 @@ module Fluent
370
389
  cache_key = "#{notice.object['metadata']['namespace']}_#{notice.object['metadata']['name']}"
371
390
  cached = @cache[cache_key]
372
391
  if cached
373
- # Only thing that can be modified is labels and (possibly) annotations
374
- labels = syms_to_strs(notice.object.metadata.labels.to_h)
375
- annotations = match_annotations(syms_to_strs(notice.object.metadata.annotations.to_h))
376
- if @de_dot
377
- self.de_dot!(labels)
378
- self.de_dot!(annotations)
379
- end
380
- cached['labels'] = labels
381
- cached['annotations'] = annotations
382
- @cache[cache_key] = cached
392
+ @cache[cache_key] = parse_pod_metadata(notice.object)
383
393
  end
384
394
  when 'DELETED'
385
395
  cache_key = "#{notice.object['metadata']['namespace']}_#{notice.object['metadata']['name']}"
@@ -397,11 +407,17 @@ module Fluent
397
407
  watcher.each do |notice|
398
408
  puts notice
399
409
  case notice.type
410
+ when 'MODIFIED'
411
+ cache_key = notice.object['metadata']['name']
412
+ cached = @namespace_cache[cache_key]
413
+ if cached
414
+ @namespace_cache[cache_key] = parse_namespace_metadata(notice.object)
415
+ end
400
416
  when 'DELETED'
401
417
  @namespace_cache.delete(notice.object['metadata']['name'])
402
418
  else
403
- # We only care about each namespace's name and UID, neither of which
404
- # is modifiable, so we only have to care about deletions.
419
+ # Don't pay attention to creations, since the created namespace may not
420
+ # be used by any pod on this node.
405
421
  end
406
422
  end
407
423
  end
@@ -177,4 +177,52 @@ http_interactions:
177
177
  }
178
178
  http_version:
179
179
  recorded_at: Fri, 08 May 2015 10:35:37 GMT
180
+ - request:
181
+ method: get
182
+ uri: https://localhost:8443/api/v1/namespaces/default
183
+ body:
184
+ encoding: US-ASCII
185
+ string: ''
186
+ headers:
187
+ Accept:
188
+ - "*/*; q=0.5, application/xml"
189
+ Accept-Encoding:
190
+ - gzip, deflate
191
+ User-Agent:
192
+ - Ruby
193
+ response:
194
+ status:
195
+ code: 200
196
+ message: OK
197
+ headers:
198
+ Content-Type:
199
+ - application/json
200
+ Date:
201
+ - Fri, 08 May 2015 10:35:37 GMT
202
+ Transfer-Encoding:
203
+ - chunked
204
+ body:
205
+ encoding: UTF-8
206
+ string: |-
207
+ {
208
+ "kind": "Namespace",
209
+ "apiVersion": "v1",
210
+ "metadata": {
211
+ "name": "default",
212
+ "selfLink": "/api/v1/namespaces/default",
213
+ "uid": "898268c8-4a36-11e5-9d81-42010af0194c",
214
+ "resourceVersion": "6",
215
+ "creationTimestamp": "2015-05-08T09:22:01Z"
216
+ },
217
+ "spec": {
218
+ "finalizers": [
219
+ "kubernetes"
220
+ ]
221
+ },
222
+ "status": {
223
+ "phase": "Active"
224
+ }
225
+ }
226
+ http_version:
227
+ recorded_at: Fri, 08 May 2015 10:35:37 GMT
180
228
  recorded_with: VCR 2.9.3
@@ -185,4 +185,55 @@ http_interactions:
185
185
  }
186
186
  http_version:
187
187
  recorded_at: Fri, 08 May 2015 10:35:37 GMT
188
+ - request:
189
+ method: get
190
+ uri: https://localhost:8443/api/v1/namespaces/default
191
+ body:
192
+ encoding: US-ASCII
193
+ string: ''
194
+ headers:
195
+ Accept:
196
+ - "*/*; q=0.5, application/xml"
197
+ Accept-Encoding:
198
+ - gzip, deflate
199
+ User-Agent:
200
+ - Ruby
201
+ response:
202
+ status:
203
+ code: 200
204
+ message: OK
205
+ headers:
206
+ Content-Type:
207
+ - application/json
208
+ Date:
209
+ - Fri, 08 May 2015 10:35:37 GMT
210
+ Transfer-Encoding:
211
+ - chunked
212
+ body:
213
+ encoding: UTF-8
214
+ string: |-
215
+ {
216
+ "kind": "Namespace",
217
+ "apiVersion": "v1",
218
+ "metadata": {
219
+ "name": "default",
220
+ "selfLink": "/api/v1/namespaces/default",
221
+ "uid": "898268c8-4a36-11e5-9d81-42010af0194c",
222
+ "resourceVersion": "6",
223
+ "creationTimestamp": "2015-05-08T09:22:01Z",
224
+ "annotations": {
225
+ "workspaceId": "myWorkspaceName"
226
+ }
227
+ },
228
+ "spec": {
229
+ "finalizers": [
230
+ "kubernetes"
231
+ ]
232
+ },
233
+ "status": {
234
+ "phase": "Active"
235
+ }
236
+ }
237
+ http_version:
238
+ recorded_at: Fri, 08 May 2015 10:35:37 GMT
188
239
  recorded_with: VCR 2.9.3
@@ -177,4 +177,55 @@ http_interactions:
177
177
  }
178
178
  http_version:
179
179
  recorded_at: Fri, 08 May 2015 10:35:37 GMT
180
+ - request:
181
+ method: get
182
+ uri: https://localhost:8443/api/v1/namespaces/default
183
+ body:
184
+ encoding: US-ASCII
185
+ string: ''
186
+ headers:
187
+ Accept:
188
+ - "*/*; q=0.5, application/xml"
189
+ Accept-Encoding:
190
+ - gzip, deflate
191
+ User-Agent:
192
+ - Ruby
193
+ response:
194
+ status:
195
+ code: 200
196
+ message: OK
197
+ headers:
198
+ Content-Type:
199
+ - application/json
200
+ Date:
201
+ - Fri, 08 May 2015 10:35:37 GMT
202
+ Transfer-Encoding:
203
+ - chunked
204
+ body:
205
+ encoding: UTF-8
206
+ string: |-
207
+ {
208
+ "kind": "Namespace",
209
+ "apiVersion": "v1",
210
+ "metadata": {
211
+ "name": "default",
212
+ "selfLink": "/api/v1/namespaces/default",
213
+ "uid": "898268c8-4a36-11e5-9d81-42010af0194c",
214
+ "resourceVersion": "6",
215
+ "creationTimestamp": "2015-05-08T09:22:01Z",
216
+ "labels": {
217
+ "kubernetes.io/namespacetest": "somevalue"
218
+ }
219
+ },
220
+ "spec": {
221
+ "finalizers": [
222
+ "kubernetes"
223
+ ]
224
+ },
225
+ "status": {
226
+ "phase": "Active"
227
+ }
228
+ }
229
+ http_version:
230
+ recorded_at: Fri, 08 May 2015 10:35:37 GMT
180
231
  recorded_with: VCR 2.9.3
@@ -197,4 +197,52 @@ http_interactions:
197
197
  }
198
198
  http_version:
199
199
  recorded_at: Sat, 09 May 2015 13:51:07 GMT
200
+ - request:
201
+ method: get
202
+ uri: https://localhost:8443/api/v1/namespaces/default
203
+ body:
204
+ encoding: US-ASCII
205
+ string: ''
206
+ headers:
207
+ Accept:
208
+ - "*/*; q=0.5, application/xml"
209
+ Accept-Encoding:
210
+ - gzip, deflate
211
+ User-Agent:
212
+ - Ruby
213
+ response:
214
+ status:
215
+ code: 200
216
+ message: OK
217
+ headers:
218
+ Content-Type:
219
+ - application/json
220
+ Date:
221
+ - Fri, 08 May 2015 10:35:37 GMT
222
+ Transfer-Encoding:
223
+ - chunked
224
+ body:
225
+ encoding: UTF-8
226
+ string: |-
227
+ {
228
+ "kind": "Namespace",
229
+ "apiVersion": "v1",
230
+ "metadata": {
231
+ "name": "default",
232
+ "selfLink": "/api/v1/namespaces/default",
233
+ "uid": "898268c8-4a36-11e5-9d81-42010af0194c",
234
+ "resourceVersion": "6",
235
+ "creationTimestamp": "2015-05-08T09:22:01Z"
236
+ },
237
+ "spec": {
238
+ "finalizers": [
239
+ "kubernetes"
240
+ ]
241
+ },
242
+ "status": {
243
+ "phase": "Active"
244
+ }
245
+ }
246
+ http_version:
247
+ recorded_at: Fri, 08 May 2015 10:35:37 GMT
200
248
  recorded_with: VCR 2.9.3
@@ -225,4 +225,52 @@ http_interactions:
225
225
  }
226
226
  http_version:
227
227
  recorded_at: Fri, 08 May 2015 10:35:37 GMT
228
+ - request:
229
+ method: get
230
+ uri: https://localhost:8443/api/v1/namespaces/default
231
+ body:
232
+ encoding: US-ASCII
233
+ string: ''
234
+ headers:
235
+ Accept:
236
+ - "*/*; q=0.5, application/xml"
237
+ Accept-Encoding:
238
+ - gzip, deflate
239
+ User-Agent:
240
+ - Ruby
241
+ response:
242
+ status:
243
+ code: 200
244
+ message: OK
245
+ headers:
246
+ Content-Type:
247
+ - application/json
248
+ Date:
249
+ - Fri, 08 May 2015 10:35:37 GMT
250
+ Transfer-Encoding:
251
+ - chunked
252
+ body:
253
+ encoding: UTF-8
254
+ string: |-
255
+ {
256
+ "kind": "Namespace",
257
+ "apiVersion": "v1",
258
+ "metadata": {
259
+ "name": "default",
260
+ "selfLink": "/api/v1/namespaces/default",
261
+ "uid": "898268c8-4a36-11e5-9d81-42010af0194c",
262
+ "resourceVersion": "6",
263
+ "creationTimestamp": "2015-05-08T09:22:01Z"
264
+ },
265
+ "spec": {
266
+ "finalizers": [
267
+ "kubernetes"
268
+ ]
269
+ },
270
+ "status": {
271
+ "phase": "Active"
272
+ }
273
+ }
274
+ http_version:
275
+ recorded_at: Fri, 08 May 2015 10:35:37 GMT
228
276
  recorded_with: VCR 2.9.3
@@ -166,6 +166,7 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
166
166
  'container_name' => 'fabric8-console-container',
167
167
  'namespace_name' => 'default',
168
168
  'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
169
+ 'master_url' => 'https://localhost:8443',
169
170
  'labels' => {
170
171
  'component' => 'fabric8Console'
171
172
  }
@@ -194,6 +195,7 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
194
195
  'namespace_name' => 'default',
195
196
  'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
196
197
  'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
198
+ 'master_url' => 'https://localhost:8443',
197
199
  'labels' => {
198
200
  'component' => 'fabric8Console'
199
201
  }
@@ -221,6 +223,7 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
221
223
  'container_name' => 'fabric8-console-container',
222
224
  'namespace_name' => 'default',
223
225
  'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
226
+ 'master_url' => 'https://localhost:8443',
224
227
  'labels' => {
225
228
  'component' => 'fabric8Console'
226
229
  }
@@ -377,17 +380,27 @@ use_journal true
377
380
 
378
381
  test 'with kubernetes dotted labels, de_dot enabled' do
379
382
  VCR.use_cassette('kubernetes_docker_metadata_dotted_labels') do
380
- es = emit()
383
+ es = emit({}, '
384
+ kubernetes_url https://localhost:8443
385
+ watch false
386
+ cache_size 1
387
+ include_namespace_metadata true
388
+ ')
381
389
  expected_kube_metadata = {
382
390
  'docker' => {
383
391
  'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
384
392
  },
385
393
  'kubernetes' => {
386
- 'host' => 'jimmi-redhat.localnet',
387
- 'pod_name' => 'fabric8-console-controller-98rqc',
388
- 'container_name' => 'fabric8-console-container',
389
- 'namespace_name' => 'default',
390
- 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
394
+ 'host' => 'jimmi-redhat.localnet',
395
+ 'pod_name' => 'fabric8-console-controller-98rqc',
396
+ 'container_name' => 'fabric8-console-container',
397
+ 'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
398
+ 'namespace_labels' => {
399
+ 'kubernetes_io/namespacetest' => 'somevalue'
400
+ },
401
+ 'namespace_name' => 'default',
402
+ 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
403
+ 'master_url' => 'https://localhost:8443',
391
404
  'labels' => {
392
405
  'kubernetes_io/test' => 'somevalue'
393
406
  }
@@ -404,17 +417,23 @@ use_journal true
404
417
  watch false
405
418
  cache_size 1
406
419
  de_dot false
420
+ include_namespace_metadata true
407
421
  ')
408
422
  expected_kube_metadata = {
409
423
  'docker' => {
410
424
  'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
411
425
  },
412
426
  'kubernetes' => {
413
- 'host' => 'jimmi-redhat.localnet',
414
- 'pod_name' => 'fabric8-console-controller-98rqc',
415
- 'container_name' => 'fabric8-console-container',
416
- 'namespace_name' => 'default',
417
- 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
427
+ 'host' => 'jimmi-redhat.localnet',
428
+ 'pod_name' => 'fabric8-console-controller-98rqc',
429
+ 'container_name' => 'fabric8-console-container',
430
+ 'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
431
+ 'namespace_labels' => {
432
+ 'kubernetes.io/namespacetest' => 'somevalue'
433
+ },
434
+ 'namespace_name' => 'default',
435
+ 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
436
+ 'master_url' => 'https://localhost:8443',
418
437
  'labels' => {
419
438
  'kubernetes.io/test' => 'somevalue'
420
439
  }
@@ -457,6 +476,7 @@ use_journal true
457
476
  'container_name' => 'fabric8-console-container',
458
477
  'namespace_name' => 'default',
459
478
  'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
479
+ 'master_url' => 'https://localhost:8443',
460
480
  'labels' => {
461
481
  'component' => 'fabric8Console'
462
482
  }
@@ -493,6 +513,7 @@ use_journal true
493
513
  'namespace_name' => 'default',
494
514
  'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
495
515
  'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
516
+ 'master_url' => 'https://localhost:8443',
496
517
  'labels' => {
497
518
  'component' => 'fabric8Console'
498
519
  }
@@ -520,6 +541,7 @@ use_journal true
520
541
  'container_name' => 'fabric8-console-container',
521
542
  'namespace_name' => 'default',
522
543
  'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
544
+ 'master_url' => 'https://localhost:8443',
523
545
  'labels' => {
524
546
  'component' => 'fabric8Console'
525
547
  },
@@ -533,5 +555,107 @@ use_journal true
533
555
  end
534
556
  end
535
557
 
558
+ test 'with records from journald and docker & kubernetes metadata, alternate form' do
559
+ # with use_journal true should ignore tags and use CONTAINER_NAME and CONTAINER_ID_FULL
560
+ tag = 'var.log.containers.junk1_junk2_junk3-49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed450.log'
561
+ msg = {
562
+ 'CONTAINER_NAME' => 'alt_fabric8-console-container_fabric8-console-controller-98rqc_default_c76927af-f563-11e4-b32d-54ee7527188d_0',
563
+ 'CONTAINER_ID_FULL' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459',
564
+ 'randomfield' => 'randomvalue'
565
+ }
566
+ VCR.use_cassette('kubernetes_docker_metadata') do
567
+ es = emit_with_tag(tag, msg, '
568
+ kubernetes_url https://localhost:8443
569
+ watch false
570
+ cache_size 1
571
+ use_journal true
572
+ ')
573
+ expected_kube_metadata = {
574
+ 'docker' => {
575
+ 'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
576
+ },
577
+ 'kubernetes' => {
578
+ 'host' => 'jimmi-redhat.localnet',
579
+ 'pod_name' => 'fabric8-console-controller-98rqc',
580
+ 'container_name' => 'fabric8-console-container',
581
+ 'namespace_name' => 'default',
582
+ 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
583
+ 'master_url' => 'https://localhost:8443',
584
+ 'labels' => {
585
+ 'component' => 'fabric8Console'
586
+ }
587
+ }
588
+ }.merge(msg)
589
+ assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
590
+ end
591
+ end
592
+
593
+ test 'with kubernetes namespace annotations' do
594
+ VCR.use_cassette('kubernetes_docker_metadata_annotations') do
595
+ es = emit({},'
596
+ kubernetes_url https://localhost:8443
597
+ watch false
598
+ cache_size 1
599
+ include_namespace_metadata true
600
+ annotation_match [ "^custom.+", "two", "workspace*"]
601
+ ')
602
+ expected_kube_metadata = {
603
+ 'docker' => {
604
+ 'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
605
+ },
606
+ 'kubernetes' => {
607
+ 'host' => 'jimmi-redhat.localnet',
608
+ 'pod_name' => 'fabric8-console-controller-98rqc',
609
+ 'container_name' => 'fabric8-console-container',
610
+ 'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
611
+ 'namespace_name' => 'default',
612
+ 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
613
+ 'master_url' => 'https://localhost:8443',
614
+ 'labels' => {
615
+ 'component' => 'fabric8Console'
616
+ },
617
+ 'annotations' => {
618
+ 'custom_field1' => 'hello_kitty',
619
+ 'field_two' => 'value'
620
+ },
621
+ 'namespace_annotations' => {
622
+ 'workspaceId' => 'myWorkspaceName'
623
+ }
624
+ }
625
+ }
626
+ assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
627
+ end
628
+ end
629
+
630
+ test 'with kubernetes namespace annotations no match' do
631
+ VCR.use_cassette('kubernetes_docker_metadata_annotations') do
632
+ es = emit({},'
633
+ kubernetes_url https://localhost:8443
634
+ watch false
635
+ cache_size 1
636
+ include_namespace_metadata true
637
+ annotation_match [ "noMatch*"]
638
+ ')
639
+ expected_kube_metadata = {
640
+ 'docker' => {
641
+ 'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
642
+ },
643
+ 'kubernetes' => {
644
+ 'host' => 'jimmi-redhat.localnet',
645
+ 'pod_name' => 'fabric8-console-controller-98rqc',
646
+ 'container_name' => 'fabric8-console-container',
647
+ 'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
648
+ 'namespace_name' => 'default',
649
+ 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
650
+ 'master_url' => 'https://localhost:8443',
651
+ 'labels' => {
652
+ 'component' => 'fabric8Console'
653
+ }
654
+ }
655
+ }
656
+ assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
657
+ end
658
+ end
659
+
536
660
  end
537
661
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-kubernetes_metadata_filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.26.3
4
+ version: 0.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jimmi Dyson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-27 00:00:00.000000000 Z
11
+ date: 2017-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -238,7 +238,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
238
  version: '0'
239
239
  requirements: []
240
240
  rubyforge_project:
241
- rubygems_version: 2.6.8
241
+ rubygems_version: 2.6.12
242
242
  signing_key:
243
243
  specification_version: 4
244
244
  summary: Filter plugin to add Kubernetes metadata