fluent-plugin-kubernetes_metadata_filter 0.23.0 → 0.24.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: ad94cfeef2063842b127dcd7717b96951b35c6e4
4
- data.tar.gz: 9ba28aa2447189ed598de36c64f6776c381f090c
3
+ metadata.gz: 718b00c62d8a5f40dd763c50b34ddc7ab4106a98
4
+ data.tar.gz: 4368cdeb4409e1416c7dfe12ab75b7c604c9f5a5
5
5
  SHA512:
6
- metadata.gz: 2930f99ff2db361b6492504da2a032d0148213fe11e33c44fd29e78f7d73a96a867259d618522ef1002b7adfa5a9c323349e34cc25ae2e085f27667d4fab3f50
7
- data.tar.gz: 150b250919002593405ee18de5024b146c4438ce4bf5a631912b85031847d6b8e97567df9c75df2a9278bfd96cd98916440ad8c7c9f9df59bd26b67f2a001895
6
+ metadata.gz: 6f30bf120124b195306ab89945ecc415edd773d362b830213dade8968daa2fba48df54941a13db1eba83e778057d46319af0d3e9c329776205633e8c4d4a0a5d
7
+ data.tar.gz: 589952266c386bf83792e58dd404826357232ac68f798cb700ad5942c6e05f04b4c3848de3e575c6ff0782ab26ce8057060c3f8b7d06ec95328e95938cf93951
data/README.md CHANGED
@@ -29,6 +29,7 @@ This must used named capture groups for `container_name`, `pod_name` & `namespac
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
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})$'`)
32
+ * `annotation_match` - Array of regular expressions matching annotation field names. Matched annotations are added to a log record.
32
33
 
33
34
  Reading from the JSON formatted log files with `in_tail` and wildcard filenames:
34
35
  ```
@@ -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.23.0"
7
+ gem.version = "0.24.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}
@@ -54,6 +54,8 @@ module Fluent
54
54
  :string,
55
55
  :default => '^k8s_(?<container_name>[^\.]+)\.[^_]+_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[a-f0-9]{8}$'
56
56
 
57
+ config_param :annotation_match, :array, default: []
58
+
57
59
  def syms_to_strs(hsh)
58
60
  newhsh = {}
59
61
  hsh.each_pair do |kk,vv|
@@ -74,10 +76,11 @@ module Fluent
74
76
  metadata = @client.get_pod(pod_name, namespace_name)
75
77
  return if !metadata
76
78
  labels = syms_to_strs(metadata['metadata']['labels'].to_h)
79
+ annotations = match_annotations(syms_to_strs(metadata['metadata']['annotations'].to_h))
77
80
  if @de_dot
78
81
  self.de_dot!(labels)
79
82
  end
80
- return {
83
+ kubernetes_metadata = {
81
84
  'namespace_name' => namespace_name,
82
85
  'pod_id' => metadata['metadata']['uid'],
83
86
  'pod_name' => pod_name,
@@ -85,6 +88,8 @@ module Fluent
85
88
  'labels' => labels,
86
89
  'host' => metadata['spec']['nodeName']
87
90
  }
91
+ kubernetes_metadata['annotations'] = annotations unless annotations.empty?
92
+ return kubernetes_metadata
88
93
  rescue KubeException
89
94
  nil
90
95
  end
@@ -180,6 +185,16 @@ module Fluent
180
185
  @merge_json_log_key = 'log'
181
186
  self.class.class_eval { alias_method :filter_stream, :filter_stream_from_files }
182
187
  end
188
+
189
+ @annotations_regexps = []
190
+ @annotation_match.each do |regexp|
191
+ begin
192
+ @annotations_regexps << Regexp.compile(regexp)
193
+ rescue RegexpError => e
194
+ log.error "Error: invalid regular expression in annotation_match: #{e}"
195
+ end
196
+ end
197
+
183
198
  end
184
199
 
185
200
  def filter_stream_from_files(tag, es)
@@ -324,6 +339,18 @@ module Fluent
324
339
  end
325
340
  end
326
341
 
342
+ def match_annotations(annotations)
343
+ result = {}
344
+ @annotations_regexps.each do |regexp|
345
+ annotations.each do |key, value|
346
+ if ::Fluent::StringUtil.match_regexp(regexp, key.to_s)
347
+ result[key] = value
348
+ end
349
+ end
350
+ end
351
+ result
352
+ end
353
+
327
354
  def start_watch
328
355
  begin
329
356
  resource_version = @client.get_pods.resourceVersion
@@ -341,13 +368,15 @@ module Fluent
341
368
  cache_key = "#{pod_cache_key}_#{container_status['name']}"
342
369
  cached = @cache[cache_key]
343
370
  if cached
344
- # Only thing that can be modified is labels
371
+ # Only thing that can be modified is labels and (possibly) annotations
345
372
  labels = syms_to_strs(notice.object.metadata.labels.to_h)
373
+ annotations = match_annotations(syms_to_strs(notice.object.metadata.annotations.to_h))
346
374
  if @de_dot
347
375
  self.de_dot!(labels)
348
376
  end
349
377
  cached['kubernetes']['labels'] = labels
350
- @cache[cache_key] = cached
378
+ cached['kubernetes']['annotations'] = annotations unless annotations.empty?
379
+ @cache[cache_key] = cached
351
380
  end
352
381
  }
353
382
  end
@@ -0,0 +1,188 @@
1
+ #
2
+ # Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
3
+ # Kubernetes metadata
4
+ #
5
+ # Copyright 2015 Red Hat, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ---
20
+ http_interactions:
21
+ - request:
22
+ method: get
23
+ uri: https://localhost:8443/api
24
+ body:
25
+ encoding: US-ASCII
26
+ string: ''
27
+ headers:
28
+ Accept:
29
+ - "*/*; q=0.5, application/xml"
30
+ Accept-Encoding:
31
+ - gzip, deflate
32
+ User-Agent:
33
+ - Ruby
34
+ response:
35
+ status:
36
+ code: 200
37
+ message: OK
38
+ headers:
39
+ Content-Type:
40
+ - application/json
41
+ Date:
42
+ - Fri, 08 May 2015 10:35:37 GMT
43
+ Content-Length:
44
+ - '67'
45
+ body:
46
+ encoding: UTF-8
47
+ string: |-
48
+ {
49
+ "versions": [
50
+ "v1"
51
+ ]
52
+ }
53
+ http_version:
54
+ recorded_at: Fri, 08 May 2015 10:35:37 GMT
55
+ - request:
56
+ method: get
57
+ uri: https://localhost:8443/api/v1/namespaces/default/pods/fabric8-console-controller-98rqc
58
+ body:
59
+ encoding: US-ASCII
60
+ string: ''
61
+ headers:
62
+ Accept:
63
+ - "*/*; q=0.5, application/xml"
64
+ Accept-Encoding:
65
+ - gzip, deflate
66
+ User-Agent:
67
+ - Ruby
68
+ response:
69
+ status:
70
+ code: 200
71
+ message: OK
72
+ headers:
73
+ Content-Type:
74
+ - application/json
75
+ Date:
76
+ - Fri, 08 May 2015 10:35:37 GMT
77
+ Transfer-Encoding:
78
+ - chunked
79
+ body:
80
+ encoding: UTF-8
81
+ string: |-
82
+ {
83
+ "kind": "Pod",
84
+ "apiVersion": "v1",
85
+ "metadata": {
86
+ "name": "fabric8-console-controller-98rqc",
87
+ "generateName": "fabric8-console-controller-",
88
+ "namespace": "default",
89
+ "selfLink": "/api/v1/namespaces/default/pods/fabric8-console-controller-98rqc",
90
+ "uid": "c76927af-f563-11e4-b32d-54ee7527188d",
91
+ "resourceVersion": "122",
92
+ "creationTimestamp": "2015-05-08T09:22:42Z",
93
+ "labels": {
94
+ "component": "fabric8Console"
95
+ },
96
+ "annotations": {
97
+ "kubernetes.io/config.hash": "c171c44f5b9345c6dc17b0e95030318c",
98
+ "kubernetes.io/config.mirror": "c171c44f5b9345c6dc17b0e95030318c",
99
+ "kubernetes.io/config.seen": "2016-06-06T08:08:35.680437994Z",
100
+ "kubernetes.io/config.source": "file",
101
+ "custom.field1": "hello_kitty",
102
+ "field.two": "value"
103
+ }
104
+ },
105
+ "spec": {
106
+ "volumes": [
107
+ {
108
+ "name": "openshift-cert-secrets",
109
+ "hostPath": null,
110
+ "emptyDir": null,
111
+ "gcePersistentDisk": null,
112
+ "gitRepo": null,
113
+ "secret": {
114
+ "secretName": "openshift-cert-secrets"
115
+ },
116
+ "nfs": null,
117
+ "iscsi": null,
118
+ "glusterfs": null
119
+ }
120
+ ],
121
+ "containers": [
122
+ {
123
+ "name": "fabric8-console-container",
124
+ "image": "fabric8/hawtio-kubernetes:latest",
125
+ "ports": [
126
+ {
127
+ "containerPort": 9090,
128
+ "protocol": "TCP"
129
+ }
130
+ ],
131
+ "env": [
132
+ {
133
+ "name": "OAUTH_CLIENT_ID",
134
+ "value": "fabric8-console"
135
+ },
136
+ {
137
+ "name": "OAUTH_AUTHORIZE_URI",
138
+ "value": "https://localhost:8443/oauth/authorize"
139
+ }
140
+ ],
141
+ "resources": {},
142
+ "volumeMounts": [
143
+ {
144
+ "name": "openshift-cert-secrets",
145
+ "readOnly": true,
146
+ "mountPath": "/etc/secret-volume"
147
+ }
148
+ ],
149
+ "terminationMessagePath": "/dev/termination-log",
150
+ "imagePullPolicy": "IfNotPresent",
151
+ "capabilities": {}
152
+ }
153
+ ],
154
+ "restartPolicy": "Always",
155
+ "dnsPolicy": "ClusterFirst",
156
+ "nodeName": "jimmi-redhat.localnet"
157
+ },
158
+ "status": {
159
+ "phase": "Running",
160
+ "Condition": [
161
+ {
162
+ "type": "Ready",
163
+ "status": "True"
164
+ }
165
+ ],
166
+ "hostIP": "172.17.42.1",
167
+ "podIP": "172.17.0.8",
168
+ "containerStatuses": [
169
+ {
170
+ "name": "fabric8-console-container",
171
+ "state": {
172
+ "running": {
173
+ "startedAt": "2015-05-08T09:22:44Z"
174
+ }
175
+ },
176
+ "lastState": {},
177
+ "ready": true,
178
+ "restartCount": 0,
179
+ "image": "fabric8/hawtio-kubernetes:latest",
180
+ "imageID": "docker://b2bd1a24a68356b2f30128e6e28e672c1ef92df0d9ec01ec0c7faea5d77d2303",
181
+ "containerID": "docker://49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459"
182
+ }
183
+ ]
184
+ }
185
+ }
186
+ http_version:
187
+ recorded_at: Fri, 08 May 2015 10:35:37 GMT
188
+ recorded_with: VCR 2.9.3
@@ -502,5 +502,36 @@ use_journal true
502
502
  end
503
503
  end
504
504
 
505
+ test 'with kubernetes annotations' do
506
+ VCR.use_cassette('kubernetes_docker_metadata_annotations') do
507
+ es = emit({},'
508
+ kubernetes_url https://localhost:8443
509
+ watch false
510
+ cache_size 1
511
+ annotation_match [ "^custom.+", "two"]
512
+ ')
513
+ expected_kube_metadata = {
514
+ 'docker' => {
515
+ 'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
516
+ },
517
+ 'kubernetes' => {
518
+ 'host' => 'jimmi-redhat.localnet',
519
+ 'pod_name' => 'fabric8-console-controller-98rqc',
520
+ 'container_name' => 'fabric8-console-container',
521
+ 'namespace_name' => 'default',
522
+ 'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
523
+ 'labels' => {
524
+ 'component' => 'fabric8Console'
525
+ },
526
+ 'annotations' => {
527
+ 'custom.field1' => 'hello_kitty',
528
+ 'field.two' => 'value'
529
+ }
530
+ }
531
+ }
532
+ assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
533
+ end
534
+ end
535
+
505
536
  end
506
537
  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.23.0
4
+ version: 0.24.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: 2016-06-14 00:00:00.000000000 Z
11
+ date: 2016-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -223,6 +223,7 @@ files:
223
223
  - lib/fluent/plugin/filter_kubernetes_metadata.rb
224
224
  - test/cassettes/invalid_api_server_config.yml
225
225
  - test/cassettes/kubernetes_docker_metadata.yml
226
+ - test/cassettes/kubernetes_docker_metadata_annotations.yml
226
227
  - test/cassettes/kubernetes_docker_metadata_dotted_labels.yml
227
228
  - test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml
228
229
  - test/cassettes/metadata_with_namespace_id.yml
@@ -251,13 +252,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
251
252
  version: '0'
252
253
  requirements: []
253
254
  rubyforge_project:
254
- rubygems_version: 2.4.8
255
+ rubygems_version: 2.5.1
255
256
  signing_key:
256
257
  specification_version: 4
257
258
  summary: Filter plugin to add Kubernetes metadata
258
259
  test_files:
259
260
  - test/cassettes/invalid_api_server_config.yml
260
261
  - test/cassettes/kubernetes_docker_metadata.yml
262
+ - test/cassettes/kubernetes_docker_metadata_annotations.yml
261
263
  - test/cassettes/kubernetes_docker_metadata_dotted_labels.yml
262
264
  - test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml
263
265
  - test/cassettes/metadata_with_namespace_id.yml