fluent-plugin-kubernetes_metadata_filter 0.10.0 → 0.11.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: f2e0964802476e178c9905c6e0cbaba9ffadb7c1
4
- data.tar.gz: 5ccaeb987a53deacc7c93726804737a459582852
3
+ metadata.gz: 4e0fcd32fc3504d09147c16350c4596822151394
4
+ data.tar.gz: d6032d7ec7cd42cf46fcf101e3d8579883502caf
5
5
  SHA512:
6
- metadata.gz: 641df616bdc5284f88d3e363693de7ff996301aef62397d0f44fce6907b7ca602bb9c4b13451be058e8d47c944bb49c9fc22a994c0688520e4db463749ffd213
7
- data.tar.gz: c6054cb7f0184b34ce9c4bee0c665cfda2bfb012e87ac5744eb4664cffe43c2589af046a18de640b86beb2762d05997d1d27a87c0dafce4fb01b291f6e6a6256
6
+ metadata.gz: 606ac89791ceec0de9f1f46d80ced6b126dff9325513c1bc177dcb1cb7f35896f9cdedea4a9aff657f5b0eab1569b0a0eb0143c38c51678cc86cbc5d47c6e1e7
7
+ data.tar.gz: 98c9aa0d292a7dc9d679ab46961136986ecfbfcfdd2c9276ded1bca00c67fa6ca11a52581942ff3a3d10c32267b259d0267efc0db462f2d8331454f3af6f869c
@@ -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.10.0"
7
+ gem.version = "0.11.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}
@@ -34,20 +34,20 @@ module Fluent
34
34
  :default => '\.(?<pod_name>[^\._]+)_(?<namespace>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$'
35
35
  config_param :bearer_token_file, :string, default: ''
36
36
  config_param :merge_json_log, :bool, default: true
37
+ config_param :include_namespace_id, :bool, default: false
37
38
 
38
- def get_metadata(namespace, pod_name, container_name)
39
+ def get_metadata(namespace_name, pod_name, container_name)
39
40
  begin
40
- metadata = @client.get_pod(pod_name, namespace)
41
- if metadata
42
- return {
43
- uid: metadata['metadata']['uid'],
44
- namespace: metadata['metadata']['namespace'],
45
- pod_name: metadata['metadata']['name'],
46
- container_name: container_name,
47
- labels: metadata['metadata']['labels'].to_h,
48
- host: metadata['spec']['host']
49
- }
50
- end
41
+ metadata = @client.get_pod(pod_name, namespace_name)
42
+ return if !metadata
43
+ return {
44
+ namespace_name: namespace_name,
45
+ pod_id: metadata['metadata']['uid'],
46
+ pod_name: pod_name,
47
+ container_name: container_name,
48
+ labels: metadata['metadata']['labels'].to_h,
49
+ host: metadata['spec']['host']
50
+ }
51
51
  rescue KubeException
52
52
  nil
53
53
  end
@@ -67,7 +67,10 @@ module Fluent
67
67
  if @cache_ttl < 0
68
68
  @cache_ttl = :none
69
69
  end
70
- @cache = LruRedux::TTL::ThreadSafeCache.new(@cache_size, @cache_ttl)
70
+ @cache = LruRedux::TTL::ThreadSafeCache.new(@cache_size, @cache_ttl)
71
+ if @include_namespace_id
72
+ @namespace_cache = LruRedux::TTL::ThreadSafeCache.new(@cache_size, @cache_ttl)
73
+ end
71
74
  @tag_to_kubernetes_name_regexp_compiled = Regexp.compile(@tag_to_kubernetes_name_regexp)
72
75
 
73
76
  if @kubernetes_url.present?
@@ -97,10 +100,12 @@ module Fluent
97
100
  end
98
101
 
99
102
  if @watch
100
- thread = Thread.new(self) { |this|
101
- this.start_watch
102
- }
103
+ thread = Thread.new(self) { |this| this.start_watch }
103
104
  thread.abort_on_exception = true
105
+ if @include_namespace_id
106
+ namespace_thread = Thread.new(self) { |this| this.start_namespace_watch }
107
+ namespace_thread.abort_on_exception = true
108
+ end
104
109
  end
105
110
  end
106
111
  end
@@ -116,20 +121,20 @@ module Fluent
116
121
  container_id: match_data['docker_id']
117
122
  },
118
123
  kubernetes: {
119
- namespace: match_data['namespace'],
124
+ namespace_name: match_data['namespace'],
120
125
  pod_name: match_data['pod_name'],
121
126
  container_name: match_data['container_name']
122
127
  }
123
128
  }
124
129
 
125
130
  if @kubernetes_url.present?
126
- cache_key = "#{metadata[:kubernetes][:namespace]}_#{metadata[:kubernetes][:pod_name]}_#{metadata[:kubernetes][:container_name]}"
131
+ cache_key = "#{metadata[:kubernetes][:namespace_name]}_#{metadata[:kubernetes][:pod_name]}_#{metadata[:kubernetes][:container_name]}"
127
132
 
128
133
  this = self
129
134
  metadata = @cache.getset(cache_key) {
130
135
  if metadata
131
136
  kubernetes_metadata = this.get_metadata(
132
- metadata[:kubernetes][:namespace],
137
+ metadata[:kubernetes][:namespace_name],
133
138
  metadata[:kubernetes][:pod_name],
134
139
  metadata[:kubernetes][:container_name]
135
140
  )
@@ -137,6 +142,14 @@ module Fluent
137
142
  metadata
138
143
  end
139
144
  }
145
+ if @include_namespace_id
146
+ namespace_name = metadata[:kubernetes][:namespace_name]
147
+ namespace_id = @namespace_cache.getset(namespace_name) {
148
+ namespace = @client.get_namespace(namespace_name)
149
+ namespace['metadata']['uid'] if namespace
150
+ }
151
+ metadata[:kubernetes][:namespace_id] = namespace_id if namespace_id
152
+ end
140
153
  end
141
154
  end
142
155
 
@@ -196,7 +209,23 @@ module Fluent
196
209
  }
197
210
  end
198
211
  else
199
- # ignoring...
212
+ # Don't pay attention to creations, since the created pod may not
213
+ # end up on this node.
214
+ end
215
+ end
216
+ end
217
+
218
+ def start_namespace_watch
219
+ resource_version = @client.get_namespaces.resourceVersion
220
+ watcher = @client.watch_namespaces(resource_version)
221
+ watcher.each do |notice|
222
+ puts notice
223
+ case notice.type
224
+ when 'DELETED'
225
+ @namespace_cache.delete(notice.object['metadata']['uid'])
226
+ else
227
+ # We only care about each namespace's name and UID, neither of which
228
+ # is modifiable, so we only have to care about deletions.
200
229
  end
201
230
  end
202
231
  end
@@ -0,0 +1,228 @@
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
+ },
97
+ "spec": {
98
+ "volumes": [
99
+ {
100
+ "name": "openshift-cert-secrets",
101
+ "hostPath": null,
102
+ "emptyDir": null,
103
+ "gcePersistentDisk": null,
104
+ "gitRepo": null,
105
+ "secret": {
106
+ "secretName": "openshift-cert-secrets"
107
+ },
108
+ "nfs": null,
109
+ "iscsi": null,
110
+ "glusterfs": null
111
+ }
112
+ ],
113
+ "containers": [
114
+ {
115
+ "name": "fabric8-console-container",
116
+ "image": "fabric8/hawtio-kubernetes:latest",
117
+ "ports": [
118
+ {
119
+ "containerPort": 9090,
120
+ "protocol": "TCP"
121
+ }
122
+ ],
123
+ "env": [
124
+ {
125
+ "name": "OAUTH_CLIENT_ID",
126
+ "value": "fabric8-console"
127
+ },
128
+ {
129
+ "name": "OAUTH_AUTHORIZE_URI",
130
+ "value": "https://localhost:8443/oauth/authorize"
131
+ }
132
+ ],
133
+ "resources": {},
134
+ "volumeMounts": [
135
+ {
136
+ "name": "openshift-cert-secrets",
137
+ "readOnly": true,
138
+ "mountPath": "/etc/secret-volume"
139
+ }
140
+ ],
141
+ "terminationMessagePath": "/dev/termination-log",
142
+ "imagePullPolicy": "IfNotPresent",
143
+ "capabilities": {}
144
+ }
145
+ ],
146
+ "restartPolicy": "Always",
147
+ "dnsPolicy": "ClusterFirst",
148
+ "host": "jimmi-redhat.localnet"
149
+ },
150
+ "status": {
151
+ "phase": "Running",
152
+ "Condition": [
153
+ {
154
+ "type": "Ready",
155
+ "status": "True"
156
+ }
157
+ ],
158
+ "hostIP": "172.17.42.1",
159
+ "podIP": "172.17.0.8",
160
+ "containerStatuses": [
161
+ {
162
+ "name": "fabric8-console-container",
163
+ "state": {
164
+ "running": {
165
+ "startedAt": "2015-05-08T09:22:44Z"
166
+ }
167
+ },
168
+ "lastState": {},
169
+ "ready": true,
170
+ "restartCount": 0,
171
+ "image": "fabric8/hawtio-kubernetes:latest",
172
+ "imageID": "docker://b2bd1a24a68356b2f30128e6e28e672c1ef92df0d9ec01ec0c7faea5d77d2303",
173
+ "containerID": "docker://49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459"
174
+ }
175
+ ]
176
+ }
177
+ }
178
+ http_version:
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
228
+ recorded_with: VCR 2.9.3
@@ -112,8 +112,36 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
112
112
  host: 'jimmi-redhat.localnet',
113
113
  pod_name: 'fabric8-console-controller-98rqc',
114
114
  container_name: 'fabric8-console-container',
115
- namespace: 'default',
116
- uid: 'c76927af-f563-11e4-b32d-54ee7527188d',
115
+ namespace_name: 'default',
116
+ pod_id: 'c76927af-f563-11e4-b32d-54ee7527188d',
117
+ labels: {
118
+ component: 'fabric8Console'
119
+ }
120
+ }
121
+ }
122
+ assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
123
+ end
124
+ end
125
+
126
+ test 'with docker & kubernetes metadata & namespace_id enabled' do
127
+ VCR.use_cassette('metadata_with_namespace_id') do
128
+ es = emit({}, '
129
+ kubernetes_url https://localhost:8443
130
+ watch false
131
+ cache_size 1
132
+ include_namespace_id true
133
+ ')
134
+ expected_kube_metadata = {
135
+ docker: {
136
+ container_id: '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
137
+ },
138
+ kubernetes: {
139
+ host: 'jimmi-redhat.localnet',
140
+ pod_name: 'fabric8-console-controller-98rqc',
141
+ container_name: 'fabric8-console-container',
142
+ namespace_name: 'default',
143
+ namespace_id: '898268c8-4a36-11e5-9d81-42010af0194c',
144
+ pod_id: 'c76927af-f563-11e4-b32d-54ee7527188d',
117
145
  labels: {
118
146
  component: 'fabric8Console'
119
147
  }
@@ -139,8 +167,8 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
139
167
  host: 'jimmi-redhat.localnet',
140
168
  pod_name: 'fabric8-console-controller-98rqc',
141
169
  container_name: 'fabric8-console-container',
142
- namespace: 'default',
143
- uid: 'c76927af-f563-11e4-b32d-54ee7527188d',
170
+ namespace_name: 'default',
171
+ pod_id: 'c76927af-f563-11e4-b32d-54ee7527188d',
144
172
  labels: {
145
173
  component: 'fabric8Console'
146
174
  }
@@ -159,7 +187,7 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
159
187
  kubernetes: {
160
188
  pod_name: 'fabric8-console-controller-98rqc',
161
189
  container_name: 'fabric8-console-container',
162
- namespace: 'default',
190
+ namespace_name: 'default',
163
191
  }
164
192
  }
165
193
  assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
@@ -180,7 +208,7 @@ class KubernetesMetadataFilterTest < Test::Unit::TestCase
180
208
  kubernetes: {
181
209
  pod_name: 'fabric8-console-controller-98rqc',
182
210
  container_name: 'fabric8-console-container',
183
- namespace: 'default'
211
+ namespace_name: 'default'
184
212
  }
185
213
  }
186
214
  assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
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.10.0
4
+ version: 0.11.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: 2015-09-01 00:00:00.000000000 Z
11
+ date: 2015-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -225,6 +225,7 @@ files:
225
225
  - test/cassettes/invalid_api_server_config.yml
226
226
  - test/cassettes/kubernetes_docker_metadata.yml
227
227
  - test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml
228
+ - test/cassettes/metadata_with_namespace_id.yml
228
229
  - test/cassettes/non_kubernetes_docker_metadata.yml
229
230
  - test/cassettes/valid_kubernetes_api_server.yml
230
231
  - test/helper.rb
@@ -258,6 +259,7 @@ test_files:
258
259
  - test/cassettes/invalid_api_server_config.yml
259
260
  - test/cassettes/kubernetes_docker_metadata.yml
260
261
  - test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml
262
+ - test/cassettes/metadata_with_namespace_id.yml
261
263
  - test/cassettes/non_kubernetes_docker_metadata.yml
262
264
  - test/cassettes/valid_kubernetes_api_server.yml
263
265
  - test/helper.rb