fluent-plugin-kubernetes_metadata_filter 0.26.3 → 0.27.0

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
  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