fluent-plugin-kubernetes_metadata_filter_v0.14 0.24.1
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 +7 -0
- data/.gitignore +19 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +201 -0
- data/README.md +141 -0
- data/Rakefile +37 -0
- data/circle.yml +7 -0
- data/fluent-plugin-kubernetes_metadata_filter.gemspec +38 -0
- data/lib/fluent/plugin/filter_kubernetes_metadata.rb +417 -0
- data/test/cassettes/invalid_api_server_config.yml +53 -0
- data/test/cassettes/kubernetes_docker_metadata.yml +180 -0
- data/test/cassettes/kubernetes_docker_metadata_annotations.yml +188 -0
- data/test/cassettes/kubernetes_docker_metadata_dotted_labels.yml +180 -0
- data/test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml +200 -0
- data/test/cassettes/metadata_with_namespace_id.yml +228 -0
- data/test/cassettes/non_kubernetes_docker_metadata.yml +97 -0
- data/test/cassettes/valid_kubernetes_api_server.yml +55 -0
- data/test/helper.rb +63 -0
- data/test/plugin/test.token +1 -0
- data/test/plugin/test_filter_kubernetes_metadata.rb +537 -0
- metadata +270 -0
|
@@ -0,0 +1,55 @@
|
|
|
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:13:54 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:13:54 GMT
|
|
55
|
+
recorded_with: VCR 2.9.3
|
data/test/helper.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
require 'codeclimate-test-reporter'
|
|
20
|
+
SimpleCov.start do
|
|
21
|
+
formatter SimpleCov::Formatter::MultiFormatter.new [
|
|
22
|
+
SimpleCov::Formatter::HTMLFormatter,
|
|
23
|
+
CodeClimate::TestReporter::Formatter
|
|
24
|
+
]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
require 'rr'
|
|
28
|
+
require 'test/unit'
|
|
29
|
+
require 'test/unit/rr'
|
|
30
|
+
require 'fileutils'
|
|
31
|
+
require 'fluent/log'
|
|
32
|
+
require 'fluent/test'
|
|
33
|
+
require 'webmock/test_unit'
|
|
34
|
+
require 'vcr'
|
|
35
|
+
|
|
36
|
+
VCR.configure do |config|
|
|
37
|
+
config.cassette_library_dir = 'test/cassettes'
|
|
38
|
+
config.hook_into :webmock # or :fakeweb
|
|
39
|
+
config.ignore_hosts 'codeclimate.com'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
unless defined?(Test::Unit::AssertionFailedError)
|
|
43
|
+
class Test::Unit::AssertionFailedError < StandardError
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def unused_port
|
|
48
|
+
s = TCPServer.open(0)
|
|
49
|
+
port = s.addr[1]
|
|
50
|
+
s.close
|
|
51
|
+
port
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def ipv6_enabled?
|
|
55
|
+
require 'socket'
|
|
56
|
+
|
|
57
|
+
begin
|
|
58
|
+
TCPServer.open('::1', 0)
|
|
59
|
+
true
|
|
60
|
+
rescue
|
|
61
|
+
false
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
12345
|
|
@@ -0,0 +1,537 @@
|
|
|
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
|
+
require_relative '../helper'
|
|
20
|
+
require 'fluent/plugin/filter_kubernetes_metadata'
|
|
21
|
+
|
|
22
|
+
require 'webmock/test_unit'
|
|
23
|
+
WebMock.disable_net_connect!
|
|
24
|
+
|
|
25
|
+
class KubernetesMetadataFilterTest < Test::Unit::TestCase
|
|
26
|
+
include Fluent
|
|
27
|
+
|
|
28
|
+
setup do
|
|
29
|
+
Fluent::Test.setup
|
|
30
|
+
@time = Fluent::Engine.now
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def create_driver(conf = '')
|
|
34
|
+
Test::FilterTestDriver.new(KubernetesMetadataFilter, 'var.log.containers.fabric8-console-controller-98rqc_default_fabric8-console-container-49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459.log').configure(conf, true)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
sub_test_case 'configure' do
|
|
38
|
+
test 'check default' do
|
|
39
|
+
d = create_driver
|
|
40
|
+
assert_equal(1000, d.instance.cache_size)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test 'kubernetes url' do
|
|
44
|
+
VCR.use_cassette('valid_kubernetes_api_server') do
|
|
45
|
+
d = create_driver('
|
|
46
|
+
kubernetes_url https://localhost:8443
|
|
47
|
+
watch false
|
|
48
|
+
')
|
|
49
|
+
assert_equal('https://localhost:8443', d.instance.kubernetes_url)
|
|
50
|
+
assert_equal(1000, d.instance.cache_size)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
test 'cache size' do
|
|
55
|
+
VCR.use_cassette('valid_kubernetes_api_server') do
|
|
56
|
+
d = create_driver('
|
|
57
|
+
kubernetes_url https://localhost:8443
|
|
58
|
+
watch false
|
|
59
|
+
cache_size 1
|
|
60
|
+
')
|
|
61
|
+
assert_equal('https://localhost:8443', d.instance.kubernetes_url)
|
|
62
|
+
assert_equal(1, d.instance.cache_size)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
test 'invalid API server config' do
|
|
67
|
+
VCR.use_cassette('invalid_api_server_config') do
|
|
68
|
+
assert_raise Fluent::ConfigError do
|
|
69
|
+
create_driver('
|
|
70
|
+
kubernetes_url https://localhost:8443
|
|
71
|
+
bearer_token_file test/plugin/test.token
|
|
72
|
+
watch false
|
|
73
|
+
verify_ssl false
|
|
74
|
+
')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
test 'service account credentials' do
|
|
80
|
+
VCR.use_cassette('valid_kubernetes_api_server') do
|
|
81
|
+
begin
|
|
82
|
+
ENV['KUBERNETES_SERVICE_HOST'] = 'localhost'
|
|
83
|
+
ENV['KUBERNETES_SERVICE_PORT'] = '8443'
|
|
84
|
+
|
|
85
|
+
Dir.mktmpdir { |dir|
|
|
86
|
+
# Fake token file and CA crt.
|
|
87
|
+
expected_cert_path = File.join(dir, KubernetesMetadataFilter::K8_POD_CA_CERT)
|
|
88
|
+
expected_token_path = File.join(dir, KubernetesMetadataFilter::K8_POD_TOKEN)
|
|
89
|
+
|
|
90
|
+
File.open(expected_cert_path, "w") {}
|
|
91
|
+
File.open(expected_token_path, "w") {}
|
|
92
|
+
|
|
93
|
+
d = create_driver("
|
|
94
|
+
watch false
|
|
95
|
+
secret_dir #{dir}
|
|
96
|
+
")
|
|
97
|
+
|
|
98
|
+
assert_equal(d.instance.kubernetes_url, "https://localhost:8443/api")
|
|
99
|
+
assert_equal(d.instance.ca_file, expected_cert_path)
|
|
100
|
+
assert_equal(d.instance.bearer_token_file, expected_token_path)
|
|
101
|
+
}
|
|
102
|
+
ensure
|
|
103
|
+
ENV['KUBERNETES_SERVICE_HOST'] = nil
|
|
104
|
+
ENV['KUBERNETES_SERVICE_PORT'] = nil
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
test 'service account credential files are tested for existence' do
|
|
110
|
+
VCR.use_cassette('valid_kubernetes_api_server') do
|
|
111
|
+
begin
|
|
112
|
+
ENV['KUBERNETES_SERVICE_HOST'] = 'localhost'
|
|
113
|
+
ENV['KUBERNETES_SERVICE_PORT'] = '8443'
|
|
114
|
+
|
|
115
|
+
Dir.mktmpdir { |dir|
|
|
116
|
+
d = create_driver("
|
|
117
|
+
watch false
|
|
118
|
+
secret_dir #{dir}
|
|
119
|
+
")
|
|
120
|
+
assert_equal(d.instance.kubernetes_url, "https://localhost:8443/api")
|
|
121
|
+
assert_false(d.instance.ca_file.present?)
|
|
122
|
+
assert_false(d.instance.bearer_token_file.present?)
|
|
123
|
+
}
|
|
124
|
+
ensure
|
|
125
|
+
ENV['KUBERNETES_SERVICE_HOST'] = nil
|
|
126
|
+
ENV['KUBERNETES_SERVICE_PORT'] = nil
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
sub_test_case 'filter_stream' do
|
|
133
|
+
|
|
134
|
+
def emit(msg={}, config='
|
|
135
|
+
kubernetes_url https://localhost:8443
|
|
136
|
+
watch false
|
|
137
|
+
cache_size 1
|
|
138
|
+
')
|
|
139
|
+
d = create_driver(config)
|
|
140
|
+
d.run {
|
|
141
|
+
d.emit(msg, @time)
|
|
142
|
+
}.filtered
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def emit_with_tag(tag, msg={}, config='
|
|
146
|
+
kubernetes_url https://localhost:8443
|
|
147
|
+
watch false
|
|
148
|
+
cache_size 1
|
|
149
|
+
')
|
|
150
|
+
d = create_driver(config)
|
|
151
|
+
d.run {
|
|
152
|
+
d.emit_with_tag(tag, msg, @time)
|
|
153
|
+
}.filtered
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
test 'with docker & kubernetes metadata' do
|
|
157
|
+
VCR.use_cassette('kubernetes_docker_metadata') do
|
|
158
|
+
es = emit()
|
|
159
|
+
expected_kube_metadata = {
|
|
160
|
+
'docker' => {
|
|
161
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
162
|
+
},
|
|
163
|
+
'kubernetes' => {
|
|
164
|
+
'host' => 'jimmi-redhat.localnet',
|
|
165
|
+
'pod_name' => 'fabric8-console-controller-98rqc',
|
|
166
|
+
'container_name' => 'fabric8-console-container',
|
|
167
|
+
'namespace_name' => 'default',
|
|
168
|
+
'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
|
|
169
|
+
'labels' => {
|
|
170
|
+
'component' => 'fabric8Console'
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
test 'with docker & kubernetes metadata & namespace_id enabled' do
|
|
179
|
+
VCR.use_cassette('metadata_with_namespace_id') do
|
|
180
|
+
es = emit({}, '
|
|
181
|
+
kubernetes_url https://localhost:8443
|
|
182
|
+
watch false
|
|
183
|
+
cache_size 1
|
|
184
|
+
include_namespace_id true
|
|
185
|
+
')
|
|
186
|
+
expected_kube_metadata = {
|
|
187
|
+
'docker' => {
|
|
188
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
189
|
+
},
|
|
190
|
+
'kubernetes' => {
|
|
191
|
+
'host' => 'jimmi-redhat.localnet',
|
|
192
|
+
'pod_name' => 'fabric8-console-controller-98rqc',
|
|
193
|
+
'container_name' => 'fabric8-console-container',
|
|
194
|
+
'namespace_name' => 'default',
|
|
195
|
+
'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
|
|
196
|
+
'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
|
|
197
|
+
'labels' => {
|
|
198
|
+
'component' => 'fabric8Console'
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
test 'with docker & kubernetes metadata using bearer token' do
|
|
207
|
+
VCR.use_cassette('kubernetes_docker_metadata_using_bearer_token') do
|
|
208
|
+
es = emit({}, '
|
|
209
|
+
kubernetes_url https://localhost:8443
|
|
210
|
+
verify_ssl false
|
|
211
|
+
watch false
|
|
212
|
+
bearer_token_file test/plugin/test.token
|
|
213
|
+
')
|
|
214
|
+
expected_kube_metadata = {
|
|
215
|
+
'docker' => {
|
|
216
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
217
|
+
},
|
|
218
|
+
'kubernetes' => {
|
|
219
|
+
'host' => 'jimmi-redhat.localnet',
|
|
220
|
+
'pod_name' => 'fabric8-console-controller-98rqc',
|
|
221
|
+
'container_name' => 'fabric8-console-container',
|
|
222
|
+
'namespace_name' => 'default',
|
|
223
|
+
'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
|
|
224
|
+
'labels' => {
|
|
225
|
+
'component' => 'fabric8Console'
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
test 'with docker & kubernetes metadata but no configured api server' do
|
|
234
|
+
es = emit({}, '')
|
|
235
|
+
expected_kube_metadata = {
|
|
236
|
+
'docker' => {
|
|
237
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
238
|
+
},
|
|
239
|
+
'kubernetes' => {
|
|
240
|
+
'pod_name' => 'fabric8-console-controller-98rqc',
|
|
241
|
+
'container_name' => 'fabric8-console-container',
|
|
242
|
+
'namespace_name' => 'default',
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
test 'with docker & inaccessible kubernetes metadata' do
|
|
249
|
+
stub_request(:any, 'https://localhost:8443/api').to_return(
|
|
250
|
+
'body' => {
|
|
251
|
+
'versions' => ['v1beta3', 'v1']
|
|
252
|
+
}.to_json
|
|
253
|
+
)
|
|
254
|
+
stub_request(:any, 'https://localhost:8443/api/v1/namespaces/default/pods/fabric8-console-controller-98rqc').to_timeout
|
|
255
|
+
es = emit()
|
|
256
|
+
expected_kube_metadata = {
|
|
257
|
+
'docker' => {
|
|
258
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
259
|
+
},
|
|
260
|
+
'kubernetes' => {
|
|
261
|
+
'pod_name' => 'fabric8-console-controller-98rqc',
|
|
262
|
+
'container_name' => 'fabric8-console-container',
|
|
263
|
+
'namespace_name' => 'default'
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
test 'with dot in pod name' do
|
|
270
|
+
stub_request(:any, 'https://localhost:8443/api').to_return(
|
|
271
|
+
'body' => {
|
|
272
|
+
'versions' => ['v1beta3', 'v1']
|
|
273
|
+
}.to_json
|
|
274
|
+
)
|
|
275
|
+
stub_request(:any, 'https://localhost:8443/api/v1/namespaces/default/pods/fabric8-console-controller.98rqc').to_timeout
|
|
276
|
+
es = emit_with_tag('var.log.containers.fabric8-console-controller.98rqc_default_fabric8-console-container-49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459.log', {}, '')
|
|
277
|
+
expected_kube_metadata = {
|
|
278
|
+
'docker' => {
|
|
279
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
280
|
+
},
|
|
281
|
+
'kubernetes' => {
|
|
282
|
+
'pod_name' => 'fabric8-console-controller.98rqc',
|
|
283
|
+
'container_name' => 'fabric8-console-container',
|
|
284
|
+
'namespace_name' => 'default'
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
test 'with docker metadata, non-kubernetes' do
|
|
291
|
+
es = emit_with_tag('non-kubernetes', {}, '')
|
|
292
|
+
assert_false(es.instance_variable_get(:@record_array)[0].has_key?(:kubernetes))
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
test 'merges json log data' do
|
|
296
|
+
json_log = {
|
|
297
|
+
'hello' => 'world'
|
|
298
|
+
}
|
|
299
|
+
msg = {
|
|
300
|
+
'log' => "#{json_log.to_json}"
|
|
301
|
+
}
|
|
302
|
+
es = emit_with_tag('non-kubernetes', msg, '')
|
|
303
|
+
assert_equal(msg.merge(json_log), es.instance_variable_get(:@record_array)[0])
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
test 'merges json log data in MESSAGE' do
|
|
307
|
+
json_log = {
|
|
308
|
+
'hello' => 'world'
|
|
309
|
+
}
|
|
310
|
+
msg = {
|
|
311
|
+
'MESSAGE' => "#{json_log.to_json}"
|
|
312
|
+
}
|
|
313
|
+
es = emit_with_tag('non-kubernetes', msg, 'use_journal true')
|
|
314
|
+
assert_equal(msg.merge(json_log), es.instance_variable_get(:@record_array)[0])
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
test 'merges json log data with message field' do
|
|
318
|
+
json_log = {
|
|
319
|
+
'timeMillis' => 1459853347608,
|
|
320
|
+
'thread' => 'main',
|
|
321
|
+
'level' => 'INFO',
|
|
322
|
+
'loggerName' => 'org.apache.camel.spring.SpringCamelContext',
|
|
323
|
+
'message' => 'Total 1 routes, of which 1 is started.',
|
|
324
|
+
'endOfBatch' => false,
|
|
325
|
+
'loggerFqcn' => 'org.apache.logging.slf4j.Log4jLogger'
|
|
326
|
+
}
|
|
327
|
+
msg = {
|
|
328
|
+
'log' => "#{json_log.to_json}"
|
|
329
|
+
}
|
|
330
|
+
es = emit_with_tag('non-kubernetes', msg, '')
|
|
331
|
+
assert_equal(msg.merge(json_log), es.instance_variable_get(:@record_array)[0])
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
test 'merges json log data with message field in MESSAGE' do
|
|
335
|
+
json_log = {
|
|
336
|
+
'timeMillis' => 1459853347608,
|
|
337
|
+
'thread' => 'main',
|
|
338
|
+
'level' => 'INFO',
|
|
339
|
+
'loggerName' => 'org.apache.camel.spring.SpringCamelContext',
|
|
340
|
+
'message' => 'Total 1 routes, of which 1 is started.',
|
|
341
|
+
'endOfBatch' => false,
|
|
342
|
+
'loggerFqcn' => 'org.apache.logging.slf4j.Log4jLogger'
|
|
343
|
+
}
|
|
344
|
+
msg = {
|
|
345
|
+
'MESSAGE' => "#{json_log.to_json}"
|
|
346
|
+
}
|
|
347
|
+
es = emit_with_tag('non-kubernetes', msg, 'use_journal true')
|
|
348
|
+
assert_equal(msg.merge(json_log), es.instance_variable_get(:@record_array)[0])
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
test 'emit individual fields from json, throw out whole original string' do
|
|
352
|
+
json_log = {
|
|
353
|
+
'hello' => 'world',
|
|
354
|
+
'more' => 'data'
|
|
355
|
+
}
|
|
356
|
+
msg = {
|
|
357
|
+
'log' => "#{json_log.to_json}"
|
|
358
|
+
}
|
|
359
|
+
es = emit_with_tag('non-kubernetes', msg, 'preserve_json_log false')
|
|
360
|
+
assert_equal(json_log, es.instance_variable_get(:@record_array)[0])
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
test 'emit individual fields from json, throw out whole original string in MESSAGE' do
|
|
364
|
+
json_log = {
|
|
365
|
+
'hello' => 'world',
|
|
366
|
+
'more' => 'data'
|
|
367
|
+
}
|
|
368
|
+
msg = {
|
|
369
|
+
'MESSAGE' => "#{json_log.to_json}"
|
|
370
|
+
}
|
|
371
|
+
es = emit_with_tag('non-kubernetes', msg, '
|
|
372
|
+
preserve_json_log false
|
|
373
|
+
use_journal true
|
|
374
|
+
')
|
|
375
|
+
assert_equal(json_log, es.instance_variable_get(:@record_array)[0])
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
test 'with kubernetes dotted labels, de_dot enabled' do
|
|
379
|
+
VCR.use_cassette('kubernetes_docker_metadata_dotted_labels') do
|
|
380
|
+
es = emit()
|
|
381
|
+
expected_kube_metadata = {
|
|
382
|
+
'docker' => {
|
|
383
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
384
|
+
},
|
|
385
|
+
'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',
|
|
391
|
+
'labels' => {
|
|
392
|
+
'kubernetes_io/test' => 'somevalue'
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
test 'with kubernetes dotted labels, de_dot disabled' do
|
|
401
|
+
VCR.use_cassette('kubernetes_docker_metadata_dotted_labels') do
|
|
402
|
+
es = emit({}, '
|
|
403
|
+
kubernetes_url https://localhost:8443
|
|
404
|
+
watch false
|
|
405
|
+
cache_size 1
|
|
406
|
+
de_dot false
|
|
407
|
+
')
|
|
408
|
+
expected_kube_metadata = {
|
|
409
|
+
'docker' => {
|
|
410
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
411
|
+
},
|
|
412
|
+
'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',
|
|
418
|
+
'labels' => {
|
|
419
|
+
'kubernetes.io/test' => 'somevalue'
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
test 'invalid de_dot_separator config' do
|
|
428
|
+
assert_raise Fluent::ConfigError do
|
|
429
|
+
create_driver('
|
|
430
|
+
de_dot_separator contains.
|
|
431
|
+
')
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
test 'with records from journald and docker & kubernetes metadata' do
|
|
436
|
+
# with use_journal true should ignore tags and use CONTAINER_NAME and CONTAINER_ID_FULL
|
|
437
|
+
tag = 'var.log.containers.junk1_junk2_junk3-49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed450.log'
|
|
438
|
+
msg = {
|
|
439
|
+
'CONTAINER_NAME' => 'k8s_fabric8-console-container.db89db89_fabric8-console-controller-98rqc_default_c76927af-f563-11e4-b32d-54ee7527188d_89db89db',
|
|
440
|
+
'CONTAINER_ID_FULL' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459',
|
|
441
|
+
'randomfield' => 'randomvalue'
|
|
442
|
+
}
|
|
443
|
+
VCR.use_cassette('kubernetes_docker_metadata') do
|
|
444
|
+
es = emit_with_tag(tag, msg, '
|
|
445
|
+
kubernetes_url https://localhost:8443
|
|
446
|
+
watch false
|
|
447
|
+
cache_size 1
|
|
448
|
+
use_journal true
|
|
449
|
+
')
|
|
450
|
+
expected_kube_metadata = {
|
|
451
|
+
'docker' => {
|
|
452
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
453
|
+
},
|
|
454
|
+
'kubernetes' => {
|
|
455
|
+
'host' => 'jimmi-redhat.localnet',
|
|
456
|
+
'pod_name' => 'fabric8-console-controller-98rqc',
|
|
457
|
+
'container_name' => 'fabric8-console-container',
|
|
458
|
+
'namespace_name' => 'default',
|
|
459
|
+
'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
|
|
460
|
+
'labels' => {
|
|
461
|
+
'component' => 'fabric8Console'
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}.merge(msg)
|
|
465
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
test 'with records from journald and docker & kubernetes metadata & namespace_id enabled' do
|
|
470
|
+
# with use_journal true should ignore tags and use CONTAINER_NAME and CONTAINER_ID_FULL
|
|
471
|
+
tag = 'var.log.containers.junk1_junk2_junk3-49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed450.log'
|
|
472
|
+
msg = {
|
|
473
|
+
'CONTAINER_NAME' => 'k8s_fabric8-console-container.db89db89_fabric8-console-controller-98rqc_default_c76927af-f563-11e4-b32d-54ee7527188d_89db89db',
|
|
474
|
+
'CONTAINER_ID_FULL' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459',
|
|
475
|
+
'randomfield' => 'randomvalue'
|
|
476
|
+
}
|
|
477
|
+
VCR.use_cassette('metadata_with_namespace_id') do
|
|
478
|
+
es = emit_with_tag(tag, msg, '
|
|
479
|
+
kubernetes_url https://localhost:8443
|
|
480
|
+
watch false
|
|
481
|
+
cache_size 1
|
|
482
|
+
include_namespace_id true
|
|
483
|
+
use_journal true
|
|
484
|
+
')
|
|
485
|
+
expected_kube_metadata = {
|
|
486
|
+
'docker' => {
|
|
487
|
+
'container_id' => '49095a2894da899d3b327c5fde1e056a81376cc9a8f8b09a195f2a92bceed459'
|
|
488
|
+
},
|
|
489
|
+
'kubernetes' => {
|
|
490
|
+
'host' => 'jimmi-redhat.localnet',
|
|
491
|
+
'pod_name' => 'fabric8-console-controller-98rqc',
|
|
492
|
+
'container_name' => 'fabric8-console-container',
|
|
493
|
+
'namespace_name' => 'default',
|
|
494
|
+
'namespace_id' => '898268c8-4a36-11e5-9d81-42010af0194c',
|
|
495
|
+
'pod_id' => 'c76927af-f563-11e4-b32d-54ee7527188d',
|
|
496
|
+
'labels' => {
|
|
497
|
+
'component' => 'fabric8Console'
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}.merge(msg)
|
|
501
|
+
assert_equal(expected_kube_metadata, es.instance_variable_get(:@record_array)[0])
|
|
502
|
+
end
|
|
503
|
+
end
|
|
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
|
+
|
|
536
|
+
end
|
|
537
|
+
end
|