fluent-plugin-kubernetes-objects 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -2
- data/Gemfile.lock +38 -30
- data/README.md +1 -1
- data/Rakefile +6 -6
- data/fluent-plugin-kubernetes-objects.gemspec +23 -23
- data/lib/fluent/plugin/in_kubernetes_objects.rb +79 -79
- data/test/fluent/plugin/in_kubernetes_objects_test.rb +29 -20
- data/test/test_helper.rb +47 -36
- metadata +22 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cfb891f22b53744c43fc6c2e1518d84a6b9f777715b8e76cdf6203d060dfebb
|
4
|
+
data.tar.gz: 33e009c355bddf26ab670daf63891344edcba1e25cc449f482fd4021ff9537f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16d37fd0ff1778a2f02d60bb08fb45137fd18bacd4484add87df8d7d6fbda0a231225dcc443dc20d93df7ce6aee1bc03e22f08020260eb80af413959f693529d
|
7
|
+
data.tar.gz: 66ccb72b7b271c55d67e573fbb614a57e7c6a4fa1bc8755d2eb47d09af3e5481865219c3e8ee3a291416365f53d5d3341b4cc510f32f4418be8ae9915f7a0aab
|
data/Gemfile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
|
3
|
+
group :test do
|
4
|
+
gem 'simplecov', require: false
|
5
|
+
end
|
6
|
+
|
7
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
8
|
|
5
9
|
# Specify your gem's dependencies in fluent-plugin-kubernetes_objects_input.gemspec
|
6
10
|
gemspec
|
data/Gemfile.lock
CHANGED
@@ -2,21 +2,22 @@ PATH
|
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
4
|
fluent-plugin-kubernetes-objects (1.0.0)
|
5
|
-
fluentd (~> 1.
|
6
|
-
kubeclient (~>
|
5
|
+
fluentd (~> 1.3)
|
6
|
+
kubeclient (~> 4.2)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
addressable (2.
|
11
|
+
addressable (2.6.0)
|
12
12
|
public_suffix (>= 2.0.2, < 4.0)
|
13
13
|
cool.io (1.5.3)
|
14
14
|
crack (0.4.3)
|
15
15
|
safe_yaml (~> 1.0.0)
|
16
16
|
dig_rb (1.0.1)
|
17
|
-
|
17
|
+
docile (1.3.1)
|
18
|
+
domain_name (0.5.20180417)
|
18
19
|
unf (>= 0.0.5, < 1.0.0)
|
19
|
-
fluentd (1.
|
20
|
+
fluentd (1.3.3)
|
20
21
|
cool.io (>= 1.4.5, < 2.0.0)
|
21
22
|
dig_rb (~> 1.0.0)
|
22
23
|
http_parser.rb (>= 0.5.1, < 0.7.0)
|
@@ -27,65 +28,72 @@ GEM
|
|
27
28
|
tzinfo (~> 1.0)
|
28
29
|
tzinfo-data (~> 1.0)
|
29
30
|
yajl-ruby (~> 1.0)
|
30
|
-
hashdiff (0.3.
|
31
|
-
http (
|
31
|
+
hashdiff (0.3.8)
|
32
|
+
http (3.3.0)
|
32
33
|
addressable (~> 2.3)
|
33
34
|
http-cookie (~> 1.0)
|
34
|
-
http-form_data (~>
|
35
|
+
http-form_data (~> 2.0)
|
35
36
|
http_parser.rb (~> 0.6.0)
|
36
37
|
http-cookie (1.0.3)
|
37
38
|
domain_name (~> 0.5)
|
38
|
-
http-form_data (1.
|
39
|
+
http-form_data (2.1.1)
|
39
40
|
http_parser.rb (0.6.0)
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
json (2.1.0)
|
42
|
+
kubeclient (4.2.2)
|
43
|
+
http (~> 3.0)
|
44
|
+
recursive-open-struct (~> 1.0, >= 1.0.4)
|
43
45
|
rest-client (~> 2.0)
|
44
|
-
mime-types (3.
|
46
|
+
mime-types (3.2.2)
|
45
47
|
mime-types-data (~> 3.2015)
|
46
|
-
mime-types-data (3.
|
48
|
+
mime-types-data (3.2018.0812)
|
47
49
|
minitest (5.11.3)
|
48
|
-
msgpack (1.2.
|
50
|
+
msgpack (1.2.6)
|
49
51
|
netrc (0.11.0)
|
50
|
-
power_assert (1.1.
|
51
|
-
public_suffix (3.0.
|
52
|
-
rake (
|
53
|
-
recursive-open-struct (1.0
|
52
|
+
power_assert (1.1.3)
|
53
|
+
public_suffix (3.0.3)
|
54
|
+
rake (12.3.2)
|
55
|
+
recursive-open-struct (1.1.0)
|
54
56
|
rest-client (2.0.2)
|
55
57
|
http-cookie (>= 1.0.2, < 2.0)
|
56
58
|
mime-types (>= 1.16, < 4.0)
|
57
59
|
netrc (~> 0.8)
|
58
60
|
safe_yaml (1.0.4)
|
59
|
-
serverengine (2.0
|
61
|
+
serverengine (2.1.0)
|
60
62
|
sigdump (~> 0.2.2)
|
61
63
|
sigdump (0.2.4)
|
64
|
+
simplecov (0.16.1)
|
65
|
+
docile (~> 1.1)
|
66
|
+
json (>= 1.8, < 3)
|
67
|
+
simplecov-html (~> 0.10.0)
|
68
|
+
simplecov-html (0.10.2)
|
62
69
|
strptime (0.2.3)
|
63
|
-
test-unit (3.
|
70
|
+
test-unit (3.3.0)
|
64
71
|
power_assert
|
65
72
|
thread_safe (0.3.6)
|
66
73
|
tzinfo (1.2.5)
|
67
74
|
thread_safe (~> 0.1)
|
68
|
-
tzinfo-data (1.2018.
|
75
|
+
tzinfo-data (1.2018.9)
|
69
76
|
tzinfo (>= 1.0.0)
|
70
77
|
unf (0.1.4)
|
71
78
|
unf_ext
|
72
79
|
unf_ext (0.0.7.5)
|
73
|
-
webmock (3.
|
80
|
+
webmock (3.5.1)
|
74
81
|
addressable (>= 2.3.6)
|
75
82
|
crack (>= 0.3.2)
|
76
83
|
hashdiff
|
77
|
-
yajl-ruby (1.
|
84
|
+
yajl-ruby (1.4.1)
|
78
85
|
|
79
86
|
PLATFORMS
|
80
87
|
ruby
|
81
88
|
|
82
89
|
DEPENDENCIES
|
83
|
-
bundler (~>
|
90
|
+
bundler (~> 2.0)
|
84
91
|
fluent-plugin-kubernetes-objects!
|
85
|
-
minitest (~> 5.
|
86
|
-
rake (~>
|
87
|
-
|
88
|
-
|
92
|
+
minitest (~> 5.11)
|
93
|
+
rake (~> 12.3)
|
94
|
+
simplecov
|
95
|
+
test-unit (~> 3.3)
|
96
|
+
webmock (~> 3.5)
|
89
97
|
|
90
98
|
BUNDLED WITH
|
91
|
-
|
99
|
+
2.0.1
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[
|
1
|
+
[![CircleCI](https://circleci.com/gh/git-lfs/git-lfs.svg?style=shield&circle-token=856152c2b02bfd236f54d21e1f581f3e4ebf47ad)](https://circleci.com/gh/splunk/fluent-plugin-kubernetes-objects)
|
2
2
|
# fluent-plugin-kubernetes-objects
|
3
3
|
|
4
4
|
[Fluentd](https://fluentd.org/) input plugin to collect [objects](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/) in a kubernetes cluster.
|
data/Rakefile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
3
|
|
4
4
|
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs <<
|
6
|
-
t.libs <<
|
7
|
-
t.test_files = FileList[
|
5
|
+
t.libs << 'test'
|
6
|
+
t.libs << 'lib'
|
7
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
8
|
end
|
9
9
|
|
10
|
-
task :
|
10
|
+
task default: :test
|
@@ -1,24 +1,24 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
|
-
spec.name =
|
3
|
-
spec.version =
|
4
|
-
spec.authors = [
|
5
|
-
spec.email = [
|
2
|
+
spec.name = 'fluent-plugin-kubernetes-objects'
|
3
|
+
spec.version = File.read('VERSION')
|
4
|
+
spec.authors = ['Splunk Inc.']
|
5
|
+
spec.email = ['DataEdge@splunk.com']
|
6
6
|
|
7
|
-
spec.summary =
|
8
|
-
spec.description =
|
9
|
-
spec.homepage =
|
10
|
-
spec.license =
|
7
|
+
spec.summary = 'Fluentd Plugin for Kubernetes Objects.'
|
8
|
+
spec.description = 'A Fluentd input plugin for collecting Kubernetes objects, e.g. pods, namespaces, events, etc. by pulling or watching.'
|
9
|
+
spec.homepage = 'https://github.com/splunk/fluent-plugin-kubernetes-objects'
|
10
|
+
spec.license = 'Apache-2.0'
|
11
11
|
|
12
12
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
13
13
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
14
|
+
#if spec.respond_to?(:metadata)
|
15
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
16
|
+
#else
|
17
|
+
# raise 'RubyGems 2.0 or newer is required to protect against ' \
|
18
|
+
# 'public gem pushes.'
|
19
|
+
#end
|
20
20
|
|
21
|
-
spec.require_paths = [
|
21
|
+
spec.require_paths = ['lib']
|
22
22
|
spec.test_files = Dir.glob('test/**/**.rb')
|
23
23
|
spec.files = %w[
|
24
24
|
CODE_OF_CONDUCT.md README.md LICENSE
|
@@ -27,17 +27,17 @@ Gem::Specification.new do |spec|
|
|
27
27
|
Rakefile
|
28
28
|
] + Dir.glob('lib/**/**').reject(&File.method(:directory?))
|
29
29
|
|
30
|
-
spec.bindir =
|
30
|
+
spec.bindir = 'exe'
|
31
31
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
32
32
|
|
33
33
|
spec.required_ruby_version = '>= 2.3.0'
|
34
34
|
|
35
|
-
spec.add_runtime_dependency
|
36
|
-
spec.add_runtime_dependency
|
35
|
+
spec.add_runtime_dependency 'fluentd', '~> 1.3'
|
36
|
+
spec.add_runtime_dependency 'kubeclient', '~> 4.2'
|
37
37
|
|
38
|
-
spec.add_development_dependency
|
39
|
-
spec.add_development_dependency
|
40
|
-
spec.add_development_dependency
|
41
|
-
spec.add_development_dependency
|
42
|
-
spec.add_development_dependency
|
38
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
39
|
+
spec.add_development_dependency 'minitest', '~> 5.11'
|
40
|
+
spec.add_development_dependency 'rake', '~> 12.3'
|
41
|
+
spec.add_development_dependency 'test-unit', '~> 3.3' # required by fluent/test.rb
|
42
|
+
spec.add_development_dependency 'webmock', '~> 3.5'
|
43
43
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'fluent/plugin/input'
|
4
4
|
require 'kubeclient'
|
5
5
|
|
6
6
|
module Fluent::Plugin
|
7
7
|
class KubernetesObjectsInput < Fluent::Plugin::Input
|
8
|
-
VERSION =
|
8
|
+
VERSION = '1.1.0'.freeze
|
9
9
|
|
10
10
|
Fluent::Plugin.register_input('kubernetes_objects', self)
|
11
11
|
|
@@ -76,17 +76,17 @@ module Fluent::Plugin
|
|
76
76
|
|
77
77
|
config_section :storage do
|
78
78
|
# use memory by default
|
79
|
-
config_set_default :usage,
|
80
|
-
config_set_default :@type,
|
79
|
+
config_set_default :usage, 'checkpoints'
|
80
|
+
config_set_default :@type, 'local'
|
81
81
|
config_set_default :persistent, false
|
82
82
|
end
|
83
83
|
|
84
84
|
def configure(conf)
|
85
85
|
super
|
86
86
|
|
87
|
-
raise Fluent::ConfigError,
|
87
|
+
raise Fluent::ConfigError, 'At least one <pull> or <watch> is required, but found none.' if @pull_objects.empty? && @watch_objects.empty?
|
88
88
|
|
89
|
-
@storage = storage_create usage:
|
89
|
+
@storage = storage_create usage: 'checkpoints'
|
90
90
|
|
91
91
|
parse_tag
|
92
92
|
initialize_client
|
@@ -118,51 +118,51 @@ module Fluent::Plugin
|
|
118
118
|
def initialize_client
|
119
119
|
# mostly borrowed from Fluentd Kubernetes Metadata Filter Plugin
|
120
120
|
if @kubernetes_url.nil?
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
121
|
+
# Use Kubernetes default service account if we're in a pod.
|
122
|
+
env_host = ENV['KUBERNETES_SERVICE_HOST']
|
123
|
+
env_port = ENV['KUBERNETES_SERVICE_PORT']
|
124
|
+
if env_host && env_port
|
125
|
+
@kubernetes_url = "https://#{env_host}:#{env_port}/#{@api_version == 'v1' ? 'api' : 'apis'}"
|
126
|
+
end
|
127
127
|
end
|
128
128
|
|
129
|
-
raise Fluent::ConfigError,
|
129
|
+
raise Fluent::ConfigError, 'kubernetes url is not set' unless @kubernetes_url
|
130
130
|
|
131
131
|
# Use SSL certificate and bearer token from Kubernetes service account.
|
132
132
|
if Dir.exist?(@secret_dir)
|
133
|
-
|
134
|
-
|
133
|
+
secret_ca_file = File.join(@secret_dir, 'ca.crt')
|
134
|
+
secret_token_file = File.join(@secret_dir, 'token')
|
135
135
|
|
136
|
-
|
137
|
-
|
138
|
-
|
136
|
+
if @ca_file.nil? && File.exist?(secret_ca_file)
|
137
|
+
@ca_file = secret_ca_file
|
138
|
+
end
|
139
139
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
140
|
+
if @bearer_token_file.nil? && File.exist?(secret_token_file)
|
141
|
+
@bearer_token_file = secret_token_file
|
142
|
+
end
|
143
|
+
end
|
144
144
|
|
145
145
|
ssl_options = {
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
146
|
+
client_cert: @client_cert && OpenSSL::X509::Certificate.new(File.read(@client_cert)),
|
147
|
+
client_key: @client_key && OpenSSL::PKey::RSA.new(File.read(@client_key)),
|
148
|
+
ca_file: @ca_file,
|
149
|
+
verify_ssl: @insecure_ssl ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
150
150
|
}
|
151
151
|
|
152
152
|
auth_options = {}
|
153
153
|
auth_options[:bearer_token] = File.read(@bearer_token_file) if @bearer_token_file
|
154
154
|
|
155
155
|
@client = Kubeclient::Client.new(
|
156
|
-
|
157
|
-
|
158
|
-
|
156
|
+
@kubernetes_url, @api_version,
|
157
|
+
ssl_options: ssl_options,
|
158
|
+
auth_options: auth_options
|
159
159
|
)
|
160
160
|
|
161
161
|
begin
|
162
|
-
|
162
|
+
@client.api_valid?
|
163
163
|
rescue KubeException => kube_error
|
164
|
-
|
165
|
-
|
164
|
+
raise Fluent::ConfigError, "Invalid Kubernetes API #{@api_version} endpoint #{@kubernetes_url}: #{kube_error.message}"
|
165
|
+
end
|
166
166
|
end
|
167
167
|
|
168
168
|
def start_pullers
|
@@ -171,14 +171,14 @@ module Fluent::Plugin
|
|
171
171
|
|
172
172
|
def start_watchers
|
173
173
|
@watchers = @watch_objects.map do |o|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
174
|
+
o = o.to_h.dup
|
175
|
+
o[:as] = :raw
|
176
|
+
resource_name = o.delete(:resource_name)
|
177
|
+
version = @storage.get(resource_name)
|
178
|
+
o[:resource_version] = version if version
|
179
|
+
@client.public_send("watch_#{resource_name}", o).tap do |watcher|
|
180
|
+
create_watcher_thread resource_name, watcher
|
181
|
+
end
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
@@ -189,49 +189,49 @@ module Fluent::Plugin
|
|
189
189
|
pull_interval = options.delete :interval
|
190
190
|
|
191
191
|
thread_create :"pull_#{resource_name}" do
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
192
|
+
tag = generate_tag resource_name
|
193
|
+
while thread_current_running?
|
194
|
+
log.debug "Going to pull #{resource_name}"
|
195
|
+
response = @client.public_send "get_#{resource_name}", options
|
196
|
+
now = Fluent::Engine.now
|
197
|
+
es = Fluent::MultiEventStream.new
|
198
|
+
|
199
|
+
# code copied from kubeclient
|
200
|
+
# kubeclient will create one open struct object for each item in the response,
|
201
|
+
# but this is totally unecessary in this plugin, thus we use as: :raw.
|
202
|
+
result = JSON.parse(response)
|
203
|
+
|
204
|
+
resource_version = result.fetch('resourceVersion') do
|
205
|
+
result.fetch('metadata', {})['resourceVersion']
|
206
|
+
end
|
207
|
+
|
208
|
+
update_op = if resource_version
|
209
|
+
->(item) { item['metadata'].update requestResourceVersion: resource_version }
|
210
|
+
else
|
211
|
+
->(item) {}
|
212
|
+
end
|
213
|
+
|
214
|
+
# result['items'] might be nil due to https://github.com/kubernetes/kubernetes/issues/13096
|
215
|
+
items = result['items'].to_a
|
216
|
+
log.debug { "Received #{items.size} #{resource_name}" }
|
217
|
+
items.each { |item| es.add now, item.tap(&update_op) }
|
218
|
+
router.emit_stream(tag, es)
|
219
|
+
|
220
|
+
sleep(pull_interval)
|
221
|
+
end
|
222
222
|
end
|
223
223
|
end
|
224
224
|
|
225
225
|
def create_watcher_thread(object_name, watcher)
|
226
|
-
thread_create(:"watch_#{object_name}")
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
226
|
+
thread_create(:"watch_#{object_name}") do
|
227
|
+
tag = generate_tag "#{object_name}.watch"
|
228
|
+
watcher.each do |entity|
|
229
|
+
log.trace { "Received new object from watching #{object_name}" }
|
230
|
+
entity = JSON.parse(entity)
|
231
|
+
router.emit tag, Fluent::Engine.now, entity
|
232
|
+
@storage.put object_name, entity['object']['metadata']['resourceVersion']
|
233
|
+
end
|
234
|
+
end
|
235
235
|
end
|
236
236
|
end
|
237
237
|
end
|
@@ -10,8 +10,10 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
10
10
|
}
|
11
11
|
|
12
12
|
it { expect(::Fluent::Plugin::KubernetesObjectsInput::VERSION).wont_be_nil }
|
13
|
+
puts 'Test: Version will not be nil'
|
13
14
|
|
14
15
|
it "should require at least one <pull> or <watch> section" do
|
16
|
+
puts 'Test: should require at least one <pull> or <watch> section'
|
15
17
|
expect{create_input_driver("kubernetes_url #{k8s_url}")}.must_raise Fluent::ConfigError
|
16
18
|
expect(create_input_driver(<<~CONF)).wont_be_nil
|
17
19
|
kubernetes_url #{k8s_url}
|
@@ -29,6 +31,7 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
29
31
|
|
30
32
|
describe "config: kubernetes_url" do
|
31
33
|
it "should read from environment variables by default" do
|
34
|
+
puts 'Test: should read from environment variables by default'
|
32
35
|
ENV['KUBERNETES_SERVICE_HOST'] = k8s_host
|
33
36
|
ENV['KUBERNETES_SERVICE_PORT'] = k8s_port
|
34
37
|
expect(create_input_driver(<<~CONF).instance.kubernetes_url).must_equal k8s_url
|
@@ -39,6 +42,7 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
39
42
|
end
|
40
43
|
|
41
44
|
it "should panic if not set" do
|
45
|
+
puts 'Test: should panic if not set'
|
42
46
|
ENV['KUBERNETES_SERVICE_HOST'] = nil
|
43
47
|
ENV['KUBERNETES_SERVICE_PORT'] = nil
|
44
48
|
expect{ create_input_driver(<<~CONF) }.must_raise Fluent::ConfigError
|
@@ -49,6 +53,7 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
49
53
|
end
|
50
54
|
|
51
55
|
it "should use pick the right path" do
|
56
|
+
puts 'Test: should use pick the right path'
|
52
57
|
ENV['KUBERNETES_SERVICE_HOST'] = k8s_host
|
53
58
|
ENV['KUBERNETES_SERVICE_PORT'] = k8s_port
|
54
59
|
expect(create_input_driver(<<~CONF).instance.kubernetes_url).must_equal k8s_url('apis')
|
@@ -62,6 +67,7 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
62
67
|
|
63
68
|
describe "emit events" do
|
64
69
|
it "can pull one resource" do
|
70
|
+
puts 'Test: can pull one resource'
|
65
71
|
d = create_input_driver(<<~CONF)
|
66
72
|
kubernetes_url #{k8s_url}
|
67
73
|
<pull>
|
@@ -76,6 +82,7 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
76
82
|
end
|
77
83
|
|
78
84
|
it "can pull multiple resources" do
|
85
|
+
puts 'Test: can pull multiple resources'
|
79
86
|
d = create_input_driver(<<~CONF)
|
80
87
|
kubernetes_url #{k8s_url}
|
81
88
|
<pull>
|
@@ -94,6 +101,7 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
94
101
|
end
|
95
102
|
|
96
103
|
it "can watch resources" do
|
104
|
+
puts 'Test: can watch resources'
|
97
105
|
d = create_input_driver(<<~CONF)
|
98
106
|
kubernetes_url #{k8s_url}
|
99
107
|
<watch>
|
@@ -107,27 +115,28 @@ describe Fluent::Plugin::KubernetesObjectsInput do
|
|
107
115
|
end
|
108
116
|
|
109
117
|
it "should use checkpoints for watching" do
|
118
|
+
puts 'Test: should use checkpoints for watching'
|
110
119
|
begin
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
120
|
+
require 'tempfile'
|
121
|
+
f = Tempfile.new("fluentd-k8s-objects-test", encoding: 'utf-8')
|
122
|
+
f.write('{"events": "123456"}')
|
123
|
+
f.close
|
124
|
+
|
125
|
+
d = create_input_driver(<<~CONF)
|
126
|
+
kubernetes_url #{k8s_url}
|
127
|
+
<storage>
|
128
|
+
path #{f.path}
|
129
|
+
</storage>
|
130
|
+
<watch>
|
131
|
+
resource_name events
|
132
|
+
</watch>
|
133
|
+
CONF
|
134
|
+
|
135
|
+
stub_k8s_events params: {resourceVersion: "123456"}
|
136
|
+
|
137
|
+
d.run expect_emits: 1, timeout: 3
|
138
|
+
ensure
|
139
|
+
f.unlink
|
131
140
|
end
|
132
141
|
end
|
133
142
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
3
|
|
4
|
-
|
4
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
5
|
+
|
6
|
+
# suppress warning, when require the 'http' library shows circle require warning
|
5
7
|
# which is pretty annoying (kubeclient depends on http for watch_stream)
|
6
8
|
_verbose = $VERBOSE
|
7
9
|
$VERBOSE = nil
|
8
|
-
require
|
10
|
+
require 'fluent/plugin/in_kubernetes_objects'
|
9
11
|
$VERBOSE = _verbose
|
10
12
|
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
13
|
+
require 'fluent/test'
|
14
|
+
require 'fluent/test/driver/input'
|
15
|
+
require 'fluent/test/helpers'
|
16
|
+
require 'minitest/autorun'
|
17
|
+
require 'webmock/minitest'
|
16
18
|
|
17
19
|
# make assertions from webmock available in minitest/spec
|
18
20
|
module Minitest::Expectations
|
@@ -21,20 +23,27 @@ module Minitest::Expectations
|
|
21
23
|
end
|
22
24
|
|
23
25
|
module PluginTestHelper
|
24
|
-
def k8s_host
|
25
|
-
|
26
|
-
|
26
|
+
def k8s_host
|
27
|
+
'127.0.0.1'
|
28
|
+
end
|
29
|
+
|
30
|
+
def k8s_port
|
31
|
+
'8001'
|
32
|
+
end
|
33
|
+
|
34
|
+
def k8s_url(path = 'api')
|
35
|
+
"https://#{k8s_host}:#{k8s_port}/#{path}"
|
36
|
+
end
|
27
37
|
|
28
38
|
def fluentd_conf_for(*lines)
|
29
|
-
basic_config = [
|
30
|
-
]
|
39
|
+
basic_config = []
|
31
40
|
(basic_config + lines).join("\n")
|
32
41
|
end
|
33
42
|
|
34
43
|
def create_input_driver(*configs)
|
35
|
-
Fluent::Test::Driver::Input.new(Fluent::Plugin::KubernetesObjectsInput).tap
|
44
|
+
Fluent::Test::Driver::Input.new(Fluent::Plugin::KubernetesObjectsInput).tap do |d|
|
36
45
|
d.configure(fluentd_conf_for(*configs))
|
37
|
-
|
46
|
+
end
|
38
47
|
end
|
39
48
|
|
40
49
|
def stub_k8s_requests
|
@@ -49,47 +58,49 @@ module PluginTestHelper
|
|
49
58
|
end
|
50
59
|
|
51
60
|
def stub_k8s_api
|
52
|
-
open(File.expand_path('
|
61
|
+
File.open(File.expand_path('api.json', __dir__)).tap do |f|
|
53
62
|
stub_request(:get, k8s_url).to_return(body: f.read)
|
54
|
-
|
63
|
+
end.close
|
55
64
|
end
|
56
65
|
|
57
66
|
def stub_k8s_apis
|
58
|
-
open(File.expand_path('
|
67
|
+
File.open(File.expand_path('apis.json', __dir__)).tap do |f|
|
59
68
|
stub_request(:get, k8s_url('apis')).to_return(body: f.read)
|
60
|
-
|
69
|
+
end.close
|
61
70
|
end
|
62
71
|
|
63
72
|
def stub_k8s_v1
|
64
|
-
open(File.expand_path('
|
73
|
+
File.open(File.expand_path('v1.json', __dir__)).tap do |f|
|
65
74
|
stub_request(:get, "#{k8s_url}/v1").to_return(body: f.read)
|
66
|
-
|
75
|
+
end.close
|
67
76
|
end
|
68
77
|
|
69
78
|
def stub_k8s_namespaces
|
70
|
-
open(File.expand_path('
|
71
|
-
stub_request(:get, "#{k8s_url}/v1/namespaces").to_return(body: f.read
|
72
|
-
|
79
|
+
File.open(File.expand_path('namespaces.json', __dir__)).tap do |f|
|
80
|
+
stub_request(:get, "#{k8s_url}/v1/namespaces").to_return(body: f.read)
|
81
|
+
end.close
|
73
82
|
end
|
74
83
|
|
75
84
|
def stub_k8s_nodes
|
76
|
-
open(File.expand_path('
|
77
|
-
stub_request(:get, "#{k8s_url}/v1/nodes").to_return(body: f.read
|
78
|
-
|
85
|
+
File.open(File.expand_path('nodes.json', __dir__)).tap do |f|
|
86
|
+
stub_request(:get, "#{k8s_url}/v1/nodes").to_return(body: f.read)
|
87
|
+
end.close
|
79
88
|
end
|
80
89
|
|
81
90
|
def stub_k8s_pods
|
82
|
-
open(File.expand_path('
|
83
|
-
stub_request(:get, "#{k8s_url}/v1/pods").to_return(body: f.read
|
84
|
-
|
91
|
+
File.open(File.expand_path('pods.json', __dir__)).tap do |f|
|
92
|
+
stub_request(:get, "#{k8s_url}/v1/pods").to_return(body: f.read)
|
93
|
+
end.close
|
85
94
|
end
|
86
95
|
|
87
96
|
def stub_k8s_events(params: nil)
|
88
|
-
open(File.expand_path('
|
97
|
+
File.open(File.expand_path('events.json', __dir__)).tap do |f|
|
89
98
|
url = "#{k8s_url}/v1/watch/events"
|
90
|
-
url << '?' << params.map { |k, v|
|
91
|
-
stub_request(:get, url)
|
92
|
-
|
93
|
-
|
99
|
+
url << '?' << params.map { |k, v| "#{k}=#{v}" }.join('&') if params
|
100
|
+
stub_request(:get, url)
|
101
|
+
.to_return(body: f.read,
|
102
|
+
headers: { 'Content-Type' => 'application/json',
|
103
|
+
'Transfer-Encoding' => 'chunked' })
|
104
|
+
end.close
|
94
105
|
end
|
95
106
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-kubernetes-objects
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Splunk Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -16,102 +16,102 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1.
|
19
|
+
version: '1.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1.
|
26
|
+
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: kubeclient
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '4.2'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '4.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '2.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: minitest
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '5.11'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '5.11'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3
|
75
|
+
version: '12.3'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '3
|
82
|
+
version: '12.3'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: test-unit
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '3.3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '3.3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: webmock
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '3.
|
103
|
+
version: '3.5'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '3.
|
110
|
+
version: '3.5'
|
111
111
|
description: A Fluentd input plugin for collecting Kubernetes objects, e.g. pods,
|
112
112
|
namespaces, events, etc. by pulling or watching.
|
113
113
|
email:
|
114
|
-
-
|
114
|
+
- DataEdge@splunk.com
|
115
115
|
executables: []
|
116
116
|
extensions: []
|
117
117
|
extra_rdoc_files: []
|
@@ -152,8 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
152
|
- !ruby/object:Gem::Version
|
153
153
|
version: '0'
|
154
154
|
requirements: []
|
155
|
-
|
156
|
-
rubygems_version: 2.7.6
|
155
|
+
rubygems_version: 3.0.1
|
157
156
|
signing_key:
|
158
157
|
specification_version: 4
|
159
158
|
summary: Fluentd Plugin for Kubernetes Objects.
|