fluent-plugin-uuid2podname 0.0.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/Gemfile +3 -0
- data/README.md +43 -0
- data/Rakefile +13 -0
- data/fluent-plugin-uuid2podname.gemspec +27 -0
- data/lib/fluent/plugin/filter_uuid2podname.rb +195 -0
- data/test/helper.rb +8 -0
- data/test/plugin/test_filter_uuid2podname.rb +18 -0
- metadata +115 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 2760530a2419309be346b3d0531f020e92be9f8a35fafcd082426d5f042d59eb
|
|
4
|
+
data.tar.gz: 5d3a96095809d20da23eec232e162cb958ae924ee2e4fc6a82b118525cdf7002
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 655ae58ca351ae95c4c93de51d3fcea4b01b11a7934cd955338610235a277a308f7209b6b986a11cea0ea6fb822e833616ea84e999ea832ba7299c76e9333137
|
|
7
|
+
data.tar.gz: b6e880b4070dd6ddabe17ae77fb780b5394f86dbfaab80c944d45d5458cc27165be440d23dd6fb4798b1ce0e9fa3b5885f41487773886b33c4ddac1bc3fcd52a
|
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# fluent-plugin-uuid2podname
|
|
2
|
+
|
|
3
|
+
[Fluentd](https://fluentd.org/) filter plugin to do something.
|
|
4
|
+
|
|
5
|
+
TODO: write description for you plugin.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### RubyGems
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
$ gem install fluent-plugin-uuid2podname
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Bundler
|
|
16
|
+
|
|
17
|
+
Add following line to your Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem "fluent-plugin-uuid2podname"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
And then execute:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
$ bundle
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Configuration
|
|
30
|
+
|
|
31
|
+
You can generate configuration template:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
$ fluent-plugin-config-format filter uuid2podname
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
You can copy and paste generated documents here.
|
|
38
|
+
|
|
39
|
+
## Copyright
|
|
40
|
+
|
|
41
|
+
* Copyright(c) 2018- SaintLiber
|
|
42
|
+
* License
|
|
43
|
+
*
|
data/Rakefile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "bundler"
|
|
2
|
+
Bundler::GemHelper.install_tasks
|
|
3
|
+
|
|
4
|
+
require "rake/testtask"
|
|
5
|
+
|
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
|
7
|
+
t.libs.push("lib", "test")
|
|
8
|
+
t.test_files = FileList["test/**/test_*.rb"]
|
|
9
|
+
t.verbose = true
|
|
10
|
+
t.warning = true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
task default: [:test]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
|
|
4
|
+
Gem::Specification.new do |spec|
|
|
5
|
+
spec.name = "fluent-plugin-uuid2podname"
|
|
6
|
+
spec.version = "0.0.1"
|
|
7
|
+
spec.authors = ["geovisor"]
|
|
8
|
+
spec.email = ["geovisor@163.com"]
|
|
9
|
+
|
|
10
|
+
spec.summary = "geovis.com.cn"
|
|
11
|
+
spec.description = "a fluent plugin by geovisor"
|
|
12
|
+
spec.homepage = "http://geovis.com.cn"
|
|
13
|
+
spec.license = ""
|
|
14
|
+
|
|
15
|
+
test_files, files = `git ls-files -z`.split("\x0").partition do |f|
|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
|
17
|
+
end
|
|
18
|
+
spec.files = files
|
|
19
|
+
spec.executables = files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
20
|
+
spec.test_files = test_files
|
|
21
|
+
spec.require_paths = ["lib"]
|
|
22
|
+
|
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.14"
|
|
24
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
|
25
|
+
spec.add_development_dependency "test-unit", "~> 3.0"
|
|
26
|
+
spec.add_runtime_dependency "fluentd", [">= 0.14.10", "< 2"]
|
|
27
|
+
end
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
require "fluent/plugin/filter"
|
|
4
|
+
|
|
5
|
+
module Fluent
|
|
6
|
+
module Plugin
|
|
7
|
+
class Uuid2podnameFilter < Fluent::Plugin::Filter
|
|
8
|
+
Fluent::Plugin.register_filter("uuid2podname", self)
|
|
9
|
+
|
|
10
|
+
K8_POD_CA_CERT = 'ca.crt'
|
|
11
|
+
K8_POD_TOKEN = 'token'
|
|
12
|
+
desc 'use the k8s insecure port,like 8080,if true then init the http kubeclient'
|
|
13
|
+
config_param :insecure, :bool, default: false
|
|
14
|
+
desc 'the kube-apiserver restful url'
|
|
15
|
+
config_param :kubernetes_url, :string, default: nil
|
|
16
|
+
desc 'the k8s serviceAccount for comunicating with kube-apiserver'
|
|
17
|
+
config_param :secret_dir, :string, default: '/var/run/secrets/kubernetes.io/serviceaccount'
|
|
18
|
+
|
|
19
|
+
config_param :apiVersion, :string, default: 'v1'
|
|
20
|
+
config_param :client_cert, :string, default: nil
|
|
21
|
+
config_param :client_key, :string, default: nil
|
|
22
|
+
config_param :ca_file, :string, default: nil
|
|
23
|
+
config_param :verify_ssl, :bool, default: true
|
|
24
|
+
config_param :bearer_token_file, :string, default: nil
|
|
25
|
+
|
|
26
|
+
def configure(conf)
|
|
27
|
+
super
|
|
28
|
+
|
|
29
|
+
def log.trace?
|
|
30
|
+
level == Fluent::Log::LEVEL_TRACE
|
|
31
|
+
end
|
|
32
|
+
require 'kubeclient'
|
|
33
|
+
|
|
34
|
+
log.debug "Uuid2podname Filter configure"
|
|
35
|
+
|
|
36
|
+
# Use Kubernetes default service account if we're in a pod.
|
|
37
|
+
if @kubernetes_url.nil?
|
|
38
|
+
log.debug "Kubernetes URL is not set - inspecting environment"
|
|
39
|
+
|
|
40
|
+
env_host = ENV['KUBERNETES_SERVICE_HOST']
|
|
41
|
+
env_port = ENV['KUBERNETES_SERVICE_PORT']
|
|
42
|
+
if !env_host.nil? && !env_port.nil?
|
|
43
|
+
if insecure
|
|
44
|
+
@kubernetes_url = "http://#{env_host}:#{env_port}/api"
|
|
45
|
+
else
|
|
46
|
+
@kubernetes_url = "https://#{env_host}:#{env_port}/api"
|
|
47
|
+
end
|
|
48
|
+
log.debug "Kubernetes URL is now '#{@kubernetes_url}'"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Use SSL certificate and bearer token from Kubernetes service account.
|
|
53
|
+
if Dir.exist?(@secret_dir)
|
|
54
|
+
log.debug "Found directory with secrets: #{@secret_dir}"
|
|
55
|
+
ca_cert = File.join(@secret_dir, K8_POD_CA_CERT)
|
|
56
|
+
pod_token = File.join(@secret_dir, K8_POD_TOKEN)
|
|
57
|
+
|
|
58
|
+
if @ca_file.nil? and File.exist?(ca_cert)
|
|
59
|
+
log.debug "Found CA certificate: #{ca_cert}"
|
|
60
|
+
@ca_file = ca_cert
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if @bearer_token_file.nil? and File.exist?(pod_token)
|
|
64
|
+
log.debug "Found pod token: #{pod_token}"
|
|
65
|
+
@bearer_token_file = pod_token
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if !@kubernetes_url.nil?
|
|
70
|
+
if insecure
|
|
71
|
+
log.debug "Creating insecure K8S client"
|
|
72
|
+
@client = Kubeclient::Client.new @kubernetes_url, @apiVersion
|
|
73
|
+
else
|
|
74
|
+
ssl_options = {
|
|
75
|
+
client_cert: !@client_cert.nil? ? OpenSSL::X509::Certificate.new(File.read(@client_cert)) : nil,
|
|
76
|
+
client_key: !@client_key.nil? ? OpenSSL::PKey::RSA.new(File.read(@client_key)) : nil,
|
|
77
|
+
ca_file: @ca_file,
|
|
78
|
+
verify_ssl: @verify_ssl ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
auth_options = {}
|
|
82
|
+
|
|
83
|
+
if !@bearer_token_file.nil?
|
|
84
|
+
bearer_token = File.read(@bearer_token_file)
|
|
85
|
+
auth_options[:bearer_token] = bearer_token
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
log.debug "Creating secure K8S client"
|
|
89
|
+
@client = Kubeclient::Client.new @kubernetes_url, @apiVersion,
|
|
90
|
+
ssl_options: ssl_options,
|
|
91
|
+
auth_options: auth_options
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
begin
|
|
95
|
+
@client.api_valid?
|
|
96
|
+
rescue KubeException => kube_error
|
|
97
|
+
raise Fluent::ConfigError, "Invalid Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{kube_error.message}"
|
|
98
|
+
end
|
|
99
|
+
@podsHash = {}
|
|
100
|
+
fetch_pods
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def filter_stream(tag, es)
|
|
105
|
+
log.debug "Uuid2podname Filter filter"
|
|
106
|
+
return es if (es.respond_to?(:empty?) && es.empty?) || !es.is_a?(Fluent::EventStream)
|
|
107
|
+
new_es = Fluent::MultiEventStream.new
|
|
108
|
+
es.each do |time, record|
|
|
109
|
+
metadata = nil
|
|
110
|
+
if @podsHash.has_key?(record['uuid'])
|
|
111
|
+
metadata = @podsHash[record['uuid']]
|
|
112
|
+
log.debug "find pod for uuid: #{record['uuid']}"
|
|
113
|
+
else
|
|
114
|
+
fetch_pods
|
|
115
|
+
if @podsHash.has_key?(record['uuid'])
|
|
116
|
+
metadata = @podsHash[record['uuid']]
|
|
117
|
+
else
|
|
118
|
+
log.error "pod does not exist: #{record['uuid']}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
record = record.merge(metadata) if metadata
|
|
122
|
+
new_es.add(time, record)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
new_es
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def fetch_pods()
|
|
129
|
+
log.debug "Uuid2podname Filter fetch_pods"
|
|
130
|
+
newPodsHash = {}
|
|
131
|
+
@client.get_pods.each do |pod_object|
|
|
132
|
+
kubernetes_metadata = parse_pod_metadata(pod_object)
|
|
133
|
+
newPodsHash[kubernetes_metadata['kubernetes']['pod_id']] = kubernetes_metadata
|
|
134
|
+
end
|
|
135
|
+
@podsHash = newPodsHash.merge @podsHash
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def parse_pod_metadata(pod_object)
|
|
139
|
+
labels = syms_to_strs(pod_object['metadata']['labels'].to_h)
|
|
140
|
+
if @de_dot
|
|
141
|
+
self.de_dot!(labels)
|
|
142
|
+
self.de_dot!(annotations)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# collect container informations
|
|
146
|
+
container_meta = {}
|
|
147
|
+
begin
|
|
148
|
+
pod_object['status']['containerStatuses'].each do|container_status|
|
|
149
|
+
# get plain container id (eg. docker://hash -> hash)
|
|
150
|
+
container_id = container_status['containerID'].sub /^[-_a-zA-Z0-9]+:\/\//, ''
|
|
151
|
+
container_meta[container_id] = {
|
|
152
|
+
'name' => container_status['name'],
|
|
153
|
+
'image' => container_status['image'],
|
|
154
|
+
'image_id' => container_status['imageID']
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
rescue
|
|
158
|
+
log.debug("parsing container meta information failed for: #{pod_object['metadata']['namespace']}/#{pod_object['metadata']['name']} ")
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
kubernetes_metadata = {
|
|
162
|
+
'namespace_name' => pod_object['metadata']['namespace'],
|
|
163
|
+
'pod_id' => pod_object['metadata']['uid'],
|
|
164
|
+
'pod_name' => pod_object['metadata']['name'],
|
|
165
|
+
'containers' => syms_to_strs(container_meta),
|
|
166
|
+
'labels' => labels,
|
|
167
|
+
'host' => pod_object['spec']['nodeName'],
|
|
168
|
+
'master_url' => @kubernetes_url
|
|
169
|
+
}
|
|
170
|
+
metadata = {
|
|
171
|
+
'kubernetes' => kubernetes_metadata
|
|
172
|
+
}
|
|
173
|
+
return metadata
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def syms_to_strs(hsh)
|
|
177
|
+
newhsh = {}
|
|
178
|
+
hsh.each_pair do |kk,vv|
|
|
179
|
+
if vv.is_a?(Hash)
|
|
180
|
+
vv = syms_to_strs(vv)
|
|
181
|
+
end
|
|
182
|
+
if kk.is_a?(Symbol)
|
|
183
|
+
newhsh[kk.to_s] = vv
|
|
184
|
+
else
|
|
185
|
+
newhsh[kk] = vv
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
newhsh
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
|
data/test/helper.rb
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path("../../", __FILE__))
|
|
2
|
+
require "test-unit"
|
|
3
|
+
require "fluent/test"
|
|
4
|
+
require "fluent/test/driver/filter"
|
|
5
|
+
require "fluent/test/helpers"
|
|
6
|
+
|
|
7
|
+
Test::Unit::TestCase.include(Fluent::Test::Helpers)
|
|
8
|
+
Test::Unit::TestCase.extend(Fluent::Test::Helpers)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require "helper"
|
|
2
|
+
require "fluent/plugin/filter_uuid2podname.rb"
|
|
3
|
+
|
|
4
|
+
class Uuid2podnameFilterTest < Test::Unit::TestCase
|
|
5
|
+
setup do
|
|
6
|
+
Fluent::Test.setup
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
test "failure" do
|
|
10
|
+
flunk
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def create_driver(conf)
|
|
16
|
+
Fluent::Test::Driver::Filter.new(Fluent::Plugin::Uuid2podnameFilter).configure(conf)
|
|
17
|
+
end
|
|
18
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fluent-plugin-uuid2podname
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- geovisor
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-11-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.14'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.14'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '12.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '12.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: test-unit
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: fluentd
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 0.14.10
|
|
62
|
+
- - "<"
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: '2'
|
|
65
|
+
type: :runtime
|
|
66
|
+
prerelease: false
|
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
68
|
+
requirements:
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: 0.14.10
|
|
72
|
+
- - "<"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '2'
|
|
75
|
+
description: a fluent plugin by geovisor
|
|
76
|
+
email:
|
|
77
|
+
- geovisor@163.com
|
|
78
|
+
executables: []
|
|
79
|
+
extensions: []
|
|
80
|
+
extra_rdoc_files: []
|
|
81
|
+
files:
|
|
82
|
+
- Gemfile
|
|
83
|
+
- README.md
|
|
84
|
+
- Rakefile
|
|
85
|
+
- fluent-plugin-uuid2podname.gemspec
|
|
86
|
+
- lib/fluent/plugin/filter_uuid2podname.rb
|
|
87
|
+
- test/helper.rb
|
|
88
|
+
- test/plugin/test_filter_uuid2podname.rb
|
|
89
|
+
homepage: http://geovis.com.cn
|
|
90
|
+
licenses:
|
|
91
|
+
- ''
|
|
92
|
+
metadata: {}
|
|
93
|
+
post_install_message:
|
|
94
|
+
rdoc_options: []
|
|
95
|
+
require_paths:
|
|
96
|
+
- lib
|
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - ">="
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '0'
|
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
|
+
requirements:
|
|
104
|
+
- - ">="
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '0'
|
|
107
|
+
requirements: []
|
|
108
|
+
rubyforge_project:
|
|
109
|
+
rubygems_version: 2.7.8
|
|
110
|
+
signing_key:
|
|
111
|
+
specification_version: 4
|
|
112
|
+
summary: geovis.com.cn
|
|
113
|
+
test_files:
|
|
114
|
+
- test/helper.rb
|
|
115
|
+
- test/plugin/test_filter_uuid2podname.rb
|