fluent-plugin-kubernetes_metadata_filter 0.10.0 → 0.11.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: 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