fluent-plugin-kubernetes_metadata_filter 3.7.0 → 3.7.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 +4 -4
- data/README.md +2 -1
- data/Rakefile +3 -4
- data/lib/fluent/plugin/filter_kubernetes_metadata.rb +307 -279
- data/lib/fluent/plugin/kubernetes_metadata_cache_strategy.rb +15 -11
- data/lib/fluent/plugin/kubernetes_metadata_common.rb +38 -40
- data/lib/fluent/plugin/kubernetes_metadata_stats.rb +4 -6
- data/lib/fluent/plugin/kubernetes_metadata_test_api_adapter.rb +39 -36
- data/lib/fluent/plugin/kubernetes_metadata_watch_namespaces.rb +15 -12
- data/lib/fluent/plugin/kubernetes_metadata_watch_pods.rb +18 -17
- metadata +2 -172
- data/.circleci/config.yml +0 -48
- data/.gitignore +0 -18
- data/.rubocop.yml +0 -57
- data/Gemfile +0 -9
- data/Gemfile.lock +0 -172
- data/fluent-plugin-kubernetes_metadata_filter.gemspec +0 -34
- data/lib/fluent/plugin/kubernetes_metadata_util.rb +0 -33
- data/test/cassettes/invalid_api_server_config.yml +0 -53
- data/test/cassettes/kubernetes_docker_metadata_annotations.yml +0 -205
- data/test/cassettes/kubernetes_docker_metadata_dotted_slashed_labels.yml +0 -197
- data/test/cassettes/kubernetes_get_api_v1.yml +0 -193
- data/test/cassettes/kubernetes_get_api_v1_using_token.yml +0 -195
- data/test/cassettes/kubernetes_get_namespace_default.yml +0 -72
- data/test/cassettes/kubernetes_get_namespace_default_using_token.yml +0 -71
- data/test/cassettes/kubernetes_get_pod.yml +0 -146
- data/test/cassettes/kubernetes_get_pod_container_init.yml +0 -145
- data/test/cassettes/kubernetes_get_pod_using_token.yml +0 -148
- data/test/cassettes/kubernetes_get_pod_with_ownerrefs.yml +0 -156
- data/test/cassettes/metadata_from_tag_and_journald_fields.yml +0 -153
- data/test/cassettes/metadata_from_tag_journald_and_kubernetes_fields.yml +0 -285
- data/test/cassettes/valid_kubernetes_api_server.yml +0 -55
- data/test/cassettes/valid_kubernetes_api_server_using_token.yml +0 -57
- data/test/helper.rb +0 -82
- data/test/plugin/test.token +0 -1
- data/test/plugin/test_cache_stats.rb +0 -33
- data/test/plugin/test_cache_strategy.rb +0 -194
- data/test/plugin/test_filter_kubernetes_metadata.rb +0 -851
- data/test/plugin/test_watch_namespaces.rb +0 -245
- data/test/plugin/test_watch_pods.rb +0 -344
- data/test/plugin/watch_test.rb +0 -76
@@ -18,14 +18,17 @@
|
|
18
18
|
# See the License for the specific language governing permissions and
|
19
19
|
# limitations under the License.
|
20
20
|
#
|
21
|
+
|
21
22
|
module KubernetesMetadata
|
22
23
|
module CacheStrategy
|
23
|
-
def get_pod_metadata(key, namespace_name, pod_name, time, batch_miss_cache)
|
24
|
+
def get_pod_metadata(key, namespace_name, pod_name, time, batch_miss_cache) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
24
25
|
metadata = {}
|
25
26
|
ids = @id_cache[key]
|
26
27
|
if ids.nil?
|
27
28
|
@stats.bump(:id_cache_miss)
|
28
|
-
|
29
|
+
if batch_miss_cache.key?("#{namespace_name}_#{pod_name}")
|
30
|
+
return batch_miss_cache["#{namespace_name}_#{pod_name}"]
|
31
|
+
end
|
29
32
|
|
30
33
|
pod_metadata = fetch_pod_metadata(namespace_name, pod_name)
|
31
34
|
if @skip_namespace_metadata
|
@@ -33,27 +36,27 @@ module KubernetesMetadata
|
|
33
36
|
@id_cache[key] = ids
|
34
37
|
return pod_metadata
|
35
38
|
end
|
39
|
+
|
36
40
|
namespace_metadata = fetch_namespace_metadata(namespace_name)
|
37
41
|
ids = { pod_id: pod_metadata['pod_id'], namespace_id: namespace_metadata['namespace_id'] }
|
38
42
|
if !ids[:pod_id].nil? && !ids[:namespace_id].nil?
|
39
43
|
# pod found and namespace found
|
40
|
-
metadata = pod_metadata
|
41
|
-
metadata.merge!(namespace_metadata)
|
44
|
+
metadata = pod_metadata.merge(namespace_metadata)
|
42
45
|
else
|
43
|
-
if ids[:pod_id].nil? && !ids[:namespace_id].nil?
|
46
|
+
if ids[:pod_id].nil? && !ids[:namespace_id].nil? # rubocop:disable Style/IfInsideElse
|
44
47
|
# pod not found, but namespace found
|
45
48
|
@stats.bump(:id_cache_pod_not_found_namespace)
|
46
49
|
ns_time = Time.parse(namespace_metadata['creation_timestamp'])
|
47
|
-
if ns_time <= Time.at(time.to_f)
|
50
|
+
if ns_time <= Time.at(time.to_f) # rubocop:disable Metrics/BlockNesting
|
48
51
|
# namespace is older then record for pod
|
49
52
|
ids[:pod_id] = key
|
50
53
|
metadata = @cache.fetch(ids[:pod_id]) do
|
51
54
|
{ 'pod_id' => ids[:pod_id] }
|
52
55
|
end
|
53
56
|
end
|
54
|
-
metadata.merge
|
57
|
+
metadata = metadata.merge(namespace_metadata)
|
55
58
|
else
|
56
|
-
if !ids[:pod_id].nil? && ids[:namespace_id].nil?
|
59
|
+
if !ids[:pod_id].nil? && ids[:namespace_id].nil? # rubocop:disable Metrics/BlockNesting
|
57
60
|
# pod found, but namespace NOT found
|
58
61
|
# this should NEVER be possible since pod meta can
|
59
62
|
# only be retrieved with a namespace
|
@@ -62,7 +65,7 @@ module KubernetesMetadata
|
|
62
65
|
# nothing found
|
63
66
|
@stats.bump(:id_cache_orphaned_record)
|
64
67
|
end
|
65
|
-
if @allow_orphans
|
68
|
+
if @allow_orphans # rubocop:disable Metrics/BlockNesting
|
66
69
|
log.trace("orphaning message for: #{namespace_name}/#{pod_name} ")
|
67
70
|
metadata = {
|
68
71
|
'orphaned_namespace' => namespace_name,
|
@@ -83,13 +86,14 @@ module KubernetesMetadata
|
|
83
86
|
m = fetch_pod_metadata(namespace_name, pod_name)
|
84
87
|
m.nil? || m.empty? ? { 'pod_id' => ids[:pod_id] } : m
|
85
88
|
end
|
86
|
-
|
89
|
+
namespace_metadata = @namespace_cache.fetch(ids[:namespace_id]) do
|
87
90
|
m = unless @skip_namespace_metadata
|
88
91
|
@stats.bump(:namespace_cache_miss)
|
89
92
|
fetch_namespace_metadata(namespace_name)
|
90
93
|
end
|
91
94
|
m.nil? || m.empty? ? { 'namespace_id' => ids[:namespace_id] } : m
|
92
|
-
end
|
95
|
+
end
|
96
|
+
metadata = metadata.merge(namespace_metadata)
|
93
97
|
end
|
94
98
|
|
95
99
|
# remove namespace info that is only used for comparison
|
@@ -18,6 +18,7 @@
|
|
18
18
|
# See the License for the specific language governing permissions and
|
19
19
|
# limitations under the License.
|
20
20
|
#
|
21
|
+
|
21
22
|
module KubernetesMetadata
|
22
23
|
module Common
|
23
24
|
class GoneError < StandardError
|
@@ -30,18 +31,15 @@ module KubernetesMetadata
|
|
30
31
|
result = {}
|
31
32
|
@annotations_regexps.each do |regexp|
|
32
33
|
annotations.each do |key, value|
|
33
|
-
if ::Fluent::StringUtil.match_regexp(regexp, key.to_s)
|
34
|
-
result[key] = value
|
35
|
-
end
|
34
|
+
result[key] = value if ::Fluent::StringUtil.match_regexp(regexp, key.to_s)
|
36
35
|
end
|
37
36
|
end
|
38
37
|
result
|
39
38
|
end
|
40
39
|
|
41
|
-
def parse_namespace_metadata(namespace_object)
|
40
|
+
def parse_namespace_metadata(namespace_object) # rubocop:disable Metrics/AbcSize
|
42
41
|
labels = ''
|
43
|
-
labels = syms_to_strs(namespace_object[:metadata][:labels].to_h) unless
|
44
|
-
|
42
|
+
labels = syms_to_strs(namespace_object[:metadata][:labels].to_h) unless @skip_labels || @skip_namespace_labels
|
45
43
|
annotations = match_annotations(syms_to_strs(namespace_object[:metadata][:annotations].to_h))
|
46
44
|
|
47
45
|
kubernetes_metadata = {
|
@@ -53,46 +51,48 @@ module KubernetesMetadata
|
|
53
51
|
kubernetes_metadata
|
54
52
|
end
|
55
53
|
|
56
|
-
def parse_pod_metadata(pod_object)
|
54
|
+
def parse_pod_metadata(pod_object) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
57
55
|
labels = ''
|
58
|
-
labels = syms_to_strs(pod_object[:metadata][:labels].to_h) unless
|
59
|
-
|
56
|
+
labels = syms_to_strs(pod_object[:metadata][:labels].to_h) unless @skip_labels || @skip_pod_labels
|
60
57
|
annotations = match_annotations(syms_to_strs(pod_object[:metadata][:annotations].to_h))
|
61
58
|
|
62
59
|
# collect container information
|
63
60
|
container_meta = {}
|
64
61
|
begin
|
65
|
-
pod_object[:status][:containerStatuses]
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
62
|
+
if pod_object[:status] && pod_object[:status][:containerStatuses]
|
63
|
+
pod_object[:status][:containerStatuses].each do |container_status|
|
64
|
+
container_id = (container_status[:containerID] || '').sub(%r{^[-_a-zA-Z0-9]+://}, '')
|
65
|
+
key = container_status[:name]
|
66
|
+
container_meta[key] = if @skip_container_metadata
|
67
|
+
{
|
68
|
+
'name' => container_status[:name]
|
69
|
+
}
|
70
|
+
else
|
71
|
+
{
|
72
|
+
'name' => container_status[:name],
|
73
|
+
'image' => container_status[:image],
|
74
|
+
'image_id' => container_status[:imageID],
|
75
|
+
:containerID => container_id
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
rescue StandardError => e
|
81
|
+
log.warn("parsing container meta information failed for: #{pod_object[:metadata][:namespace]}/#{pod_object[:metadata][:name]}: #{e}") # rubocop:disable Layout/LineLength
|
83
82
|
end
|
84
83
|
|
85
84
|
ownerrefs_meta = []
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
'kind' => owner_reference[:kind],
|
90
|
-
|
91
|
-
|
85
|
+
if @include_ownerrefs_metadata && pod_object[:metadata][:ownerReferences]
|
86
|
+
begin
|
87
|
+
pod_object[:metadata][:ownerReferences].each do |owner_reference|
|
88
|
+
ownerrefs_meta.append({ 'kind' => owner_reference[:kind], 'name' => owner_reference[:name] })
|
89
|
+
end
|
90
|
+
rescue StandardError => e
|
91
|
+
log.warn(
|
92
|
+
"parsing ownerrefs meta information failed for: #{pod_object[:metadata][:namespace]}/#{pod_object[:metadata][:name]}: #{e}" # rubocop:disable Layout/LineLength
|
93
|
+
)
|
92
94
|
end
|
93
|
-
|
94
|
-
log.warn("parsing ownerrefs meta information failed for: #{pod_object[:metadata][:namespace]}/#{pod_object[:metadata][:name]}: #{e}")
|
95
|
-
end if @include_ownerrefs_metadata && pod_object[:metadata][:ownerReferences]
|
95
|
+
end
|
96
96
|
|
97
97
|
kubernetes_metadata = {
|
98
98
|
'namespace_name' => pod_object[:metadata][:namespace],
|
@@ -103,8 +103,8 @@ module KubernetesMetadata
|
|
103
103
|
'host' => pod_object[:spec][:nodeName],
|
104
104
|
'ownerrefs' => (ownerrefs_meta if @include_ownerrefs_metadata)
|
105
105
|
}.compact
|
106
|
-
kubernetes_metadata['annotations'] = annotations unless annotations.empty?
|
107
106
|
kubernetes_metadata['labels'] = labels unless labels.empty?
|
107
|
+
kubernetes_metadata['annotations'] = annotations unless annotations.empty?
|
108
108
|
kubernetes_metadata['master_url'] = @kubernetes_url unless @skip_master_url
|
109
109
|
kubernetes_metadata
|
110
110
|
end
|
@@ -112,9 +112,7 @@ module KubernetesMetadata
|
|
112
112
|
def syms_to_strs(hsh)
|
113
113
|
newhsh = {}
|
114
114
|
hsh.each_pair do |kk, vv|
|
115
|
-
if vv.is_a?(Hash)
|
116
|
-
vv = syms_to_strs(vv)
|
117
|
-
end
|
115
|
+
vv = syms_to_strs(vv) if vv.is_a?(Hash)
|
118
116
|
if kk.is_a?(Symbol)
|
119
117
|
newhsh[kk.to_s] = vv
|
120
118
|
else
|
@@ -18,7 +18,9 @@
|
|
18
18
|
# See the License for the specific language governing permissions and
|
19
19
|
# limitations under the License.
|
20
20
|
#
|
21
|
+
|
21
22
|
require 'lru_redux'
|
23
|
+
|
22
24
|
module KubernetesMetadata
|
23
25
|
class Stats
|
24
26
|
def initialize
|
@@ -38,15 +40,11 @@ module KubernetesMetadata
|
|
38
40
|
end
|
39
41
|
|
40
42
|
def to_s
|
41
|
-
|
42
|
-
@stats.each { |k, v| a << "#{k}: #{v}" }
|
43
|
-
end.join(', ')
|
43
|
+
"stats - #{@stats.to_a.map { |k, v| "#{k}: #{v}" }.join(', ')}"
|
44
44
|
end
|
45
45
|
end
|
46
|
-
class NoOpStats
|
47
|
-
def initialize
|
48
|
-
end
|
49
46
|
|
47
|
+
class NoOpStats
|
50
48
|
def bump(key)
|
51
49
|
end
|
52
50
|
|
@@ -18,51 +18,54 @@
|
|
18
18
|
# See the License for the specific language governing permissions and
|
19
19
|
# limitations under the License.
|
20
20
|
#
|
21
|
+
|
21
22
|
require 'kubeclient'
|
22
23
|
|
23
24
|
module KubernetesMetadata
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
25
|
+
module TestApiAdapter
|
26
|
+
def api_valid?
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_namespace(namespace_name, _unused, _options)
|
31
|
+
{
|
32
|
+
metadata: {
|
33
|
+
name: namespace_name,
|
34
|
+
uid: "#{namespace_name}uuid",
|
35
|
+
labels: {
|
36
|
+
foo_ns: 'bar_ns'
|
37
37
|
}
|
38
38
|
}
|
39
|
-
|
39
|
+
}
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
42
|
+
def get_pod(pod_name, namespace_name, _options) # rubocop:disable Metrics/MethodLength
|
43
|
+
{
|
44
|
+
metadata: {
|
45
|
+
name: pod_name,
|
46
|
+
namespace: namespace_name,
|
47
|
+
uid: "#{namespace_name}#{namespace_name}uuid",
|
48
|
+
labels: {
|
49
|
+
foo: 'bar'
|
50
|
+
}
|
51
|
+
},
|
52
|
+
spec: {
|
53
|
+
nodeName: 'aNodeName',
|
54
|
+
containers: [
|
55
|
+
{
|
54
56
|
name: 'foo',
|
55
57
|
image: 'bar'
|
56
|
-
},
|
58
|
+
},
|
59
|
+
{
|
57
60
|
name: 'bar',
|
58
61
|
image: 'foo'
|
59
|
-
}
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
}
|
63
|
+
]
|
64
|
+
},
|
65
|
+
status: {
|
66
|
+
podIP: '172.17.0.8'
|
64
67
|
}
|
65
|
-
|
66
|
-
|
68
|
+
}
|
67
69
|
end
|
68
|
-
end
|
70
|
+
end
|
71
|
+
end
|
@@ -18,14 +18,15 @@
|
|
18
18
|
# See the License for the specific language governing permissions and
|
19
19
|
# limitations under the License.
|
20
20
|
#
|
21
|
+
|
21
22
|
# TODO: this is mostly copy-paste from kubernetes_metadata_watch_pods.rb unify them
|
22
23
|
require_relative 'kubernetes_metadata_common'
|
23
24
|
|
24
25
|
module KubernetesMetadata
|
25
|
-
module WatchNamespaces
|
26
|
+
module WatchNamespaces # rubocop:disable Metrics/ModuleLength
|
26
27
|
include ::KubernetesMetadata::Common
|
27
28
|
|
28
|
-
def set_up_namespace_thread
|
29
|
+
def set_up_namespace_thread # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
|
29
30
|
# Any failures / exceptions in the initial setup should raise
|
30
31
|
# Fluent:ConfigError, so that users can inspect potential errors in
|
31
32
|
# the configuration.
|
@@ -37,7 +38,7 @@ module KubernetesMetadata
|
|
37
38
|
# processing will be swallowed and retried. These failures /
|
38
39
|
# exceptions could be caused by Kubernetes API being temporarily
|
39
40
|
# down. We assume the configuration is correct at this point.
|
40
|
-
loop do
|
41
|
+
loop do # rubocop:disable Metrics/BlockLength
|
41
42
|
namespace_watcher ||= get_namespaces_and_start_watcher
|
42
43
|
process_namespace_watcher_notices(namespace_watcher)
|
43
44
|
rescue GoneError => e
|
@@ -50,7 +51,7 @@ module KubernetesMetadata
|
|
50
51
|
if e.error_code == 401
|
51
52
|
# recreate client to refresh token
|
52
53
|
log.info("Encountered '401 Unauthorized' exception in watch, recreating client to refresh token")
|
53
|
-
create_client
|
54
|
+
create_client
|
54
55
|
namespace_watcher = nil
|
55
56
|
else
|
56
57
|
# treat all other errors the same as StandardError, log, swallow and reset
|
@@ -62,7 +63,8 @@ module KubernetesMetadata
|
|
62
63
|
'Exception encountered parsing namespace watch event. ' \
|
63
64
|
'The connection might have been closed. Sleeping for ' \
|
64
65
|
"#{Thread.current[:namespace_watch_retry_backoff_interval]} " \
|
65
|
-
'seconds and resetting the namespace watcher.',
|
66
|
+
'seconds and resetting the namespace watcher.',
|
67
|
+
e
|
66
68
|
)
|
67
69
|
sleep(Thread.current[:namespace_watch_retry_backoff_interval])
|
68
70
|
Thread.current[:namespace_watch_retry_count] += 1
|
@@ -88,7 +90,8 @@ module KubernetesMetadata
|
|
88
90
|
'Exception encountered parsing namespace watch event. ' \
|
89
91
|
'The connection might have been closed. Sleeping for ' \
|
90
92
|
"#{Thread.current[:namespace_watch_retry_backoff_interval]} " \
|
91
|
-
'seconds and resetting the namespace watcher.',
|
93
|
+
'seconds and resetting the namespace watcher.',
|
94
|
+
e
|
92
95
|
)
|
93
96
|
sleep(Thread.current[:namespace_watch_retry_backoff_interval])
|
94
97
|
Thread.current[:namespace_watch_retry_count] += 1
|
@@ -121,11 +124,11 @@ module KubernetesMetadata
|
|
121
124
|
|
122
125
|
# List all namespaces, record the resourceVersion and return a watcher
|
123
126
|
# starting from that resourceVersion.
|
124
|
-
def get_namespaces_and_start_watcher
|
127
|
+
def get_namespaces_and_start_watcher # rubocop:disable Metrics/MethodLength, Naming/AccessorMethodName
|
125
128
|
options = {
|
126
129
|
resource_version: '0' # Fetch from API server cache instead of etcd quorum read
|
127
130
|
}
|
128
|
-
namespaces = @client.get_namespaces(options)
|
131
|
+
namespaces = @client.get_namespaces(**options)
|
129
132
|
namespaces[:items].each do |namespace|
|
130
133
|
cache_key = namespace[:metadata][:uid]
|
131
134
|
@namespace_cache[cache_key] = parse_namespace_metadata(namespace)
|
@@ -135,7 +138,7 @@ module KubernetesMetadata
|
|
135
138
|
# continue watching from most recent resourceVersion
|
136
139
|
options[:resource_version] = namespaces[:metadata][:resourceVersion]
|
137
140
|
|
138
|
-
watcher = @client.watch_namespaces(options)
|
141
|
+
watcher = @client.watch_namespaces(**options)
|
139
142
|
reset_namespace_watch_retry_stats
|
140
143
|
watcher
|
141
144
|
end
|
@@ -148,13 +151,13 @@ module KubernetesMetadata
|
|
148
151
|
end
|
149
152
|
|
150
153
|
# Process a watcher notice and potentially raise an exception.
|
151
|
-
def process_namespace_watcher_notices(watcher)
|
152
|
-
watcher.each do |notice|
|
154
|
+
def process_namespace_watcher_notices(watcher) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
155
|
+
watcher.each do |notice| # rubocop:disable Metrics/BlockLength
|
153
156
|
case notice[:type]
|
154
157
|
when 'MODIFIED'
|
155
158
|
reset_namespace_watch_retry_stats
|
156
159
|
cache_key = notice[:object][:metadata][:uid]
|
157
|
-
cached
|
160
|
+
cached = @namespace_cache[cache_key]
|
158
161
|
if cached
|
159
162
|
@namespace_cache[cache_key] = parse_namespace_metadata(notice[:object])
|
160
163
|
@stats.bump(:namespace_cache_watch_updates)
|
@@ -18,14 +18,15 @@
|
|
18
18
|
# See the License for the specific language governing permissions and
|
19
19
|
# limitations under the License.
|
20
20
|
#
|
21
|
+
|
21
22
|
# TODO: this is mostly copy-paste from kubernetes_metadata_watch_namespaces.rb unify them
|
22
23
|
require_relative 'kubernetes_metadata_common'
|
23
24
|
|
24
25
|
module KubernetesMetadata
|
25
|
-
module WatchPods
|
26
|
+
module WatchPods # rubocop:disable Metrics/ModuleLength
|
26
27
|
include ::KubernetesMetadata::Common
|
27
28
|
|
28
|
-
def set_up_pod_thread
|
29
|
+
def set_up_pod_thread # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
|
29
30
|
# Any failures / exceptions in the initial setup should raise
|
30
31
|
# Fluent:ConfigError, so that users can inspect potential errors in
|
31
32
|
# the configuration.
|
@@ -38,7 +39,7 @@ module KubernetesMetadata
|
|
38
39
|
# processing will be swallowed and retried. These failures /
|
39
40
|
# exceptions could be caused by Kubernetes API being temporarily
|
40
41
|
# down. We assume the configuration is correct at this point.
|
41
|
-
loop do
|
42
|
+
loop do # rubocop:disable Metrics/BlockLength
|
42
43
|
pod_watcher ||= get_pods_and_start_watcher
|
43
44
|
process_pod_watcher_notices(pod_watcher)
|
44
45
|
rescue GoneError => e
|
@@ -51,7 +52,7 @@ module KubernetesMetadata
|
|
51
52
|
if e.error_code == 401
|
52
53
|
# recreate client to refresh token
|
53
54
|
log.info("Encountered '401 Unauthorized' exception in watch, recreating client to refresh token")
|
54
|
-
create_client
|
55
|
+
create_client
|
55
56
|
pod_watcher = nil
|
56
57
|
else
|
57
58
|
# treat all other errors the same as StandardError, log, swallow and reset
|
@@ -63,7 +64,8 @@ module KubernetesMetadata
|
|
63
64
|
'Exception encountered parsing pod watch event. The ' \
|
64
65
|
'connection might have been closed. Sleeping for ' \
|
65
66
|
"#{Thread.current[:pod_watch_retry_backoff_interval]} " \
|
66
|
-
'seconds and resetting the pod watcher.',
|
67
|
+
'seconds and resetting the pod watcher.',
|
68
|
+
e
|
67
69
|
)
|
68
70
|
sleep(Thread.current[:pod_watch_retry_backoff_interval])
|
69
71
|
Thread.current[:pod_watch_retry_count] += 1
|
@@ -89,7 +91,8 @@ module KubernetesMetadata
|
|
89
91
|
'Exception encountered parsing pod watch event. The ' \
|
90
92
|
'connection might have been closed. Sleeping for ' \
|
91
93
|
"#{Thread.current[:pod_watch_retry_backoff_interval]} " \
|
92
|
-
'seconds and resetting the pod watcher.',
|
94
|
+
'seconds and resetting the pod watcher.',
|
95
|
+
e
|
93
96
|
)
|
94
97
|
sleep(Thread.current[:pod_watch_retry_backoff_interval])
|
95
98
|
Thread.current[:pod_watch_retry_count] += 1
|
@@ -122,17 +125,15 @@ module KubernetesMetadata
|
|
122
125
|
|
123
126
|
# List all pods, record the resourceVersion and return a watcher starting
|
124
127
|
# from that resourceVersion.
|
125
|
-
def get_pods_and_start_watcher
|
128
|
+
def get_pods_and_start_watcher # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Naming/AccessorMethodName
|
126
129
|
options = {
|
127
130
|
resource_version: '0' # Fetch from API server cache instead of etcd quorum read
|
128
131
|
}
|
129
|
-
if ENV['K8S_NODE_NAME']
|
130
|
-
options[:field_selector] = 'spec.nodeName=' + ENV['K8S_NODE_NAME']
|
131
|
-
end
|
132
|
+
options[:field_selector] = "spec.nodeName=#{ENV['K8S_NODE_NAME']}" if ENV['K8S_NODE_NAME']
|
132
133
|
if @last_seen_resource_version
|
133
134
|
options[:resource_version] = @last_seen_resource_version
|
134
135
|
else
|
135
|
-
pods = @client.get_pods(options)
|
136
|
+
pods = @client.get_pods(**options)
|
136
137
|
pods[:items].each do |pod|
|
137
138
|
cache_key = pod[:metadata][:uid]
|
138
139
|
@cache[cache_key] = parse_pod_metadata(pod)
|
@@ -143,7 +144,7 @@ module KubernetesMetadata
|
|
143
144
|
options[:resource_version] = pods[:metadata][:resourceVersion]
|
144
145
|
end
|
145
146
|
|
146
|
-
watcher = @client.watch_pods(options)
|
147
|
+
watcher = @client.watch_pods(**options)
|
147
148
|
reset_pod_watch_retry_stats
|
148
149
|
watcher
|
149
150
|
end
|
@@ -156,19 +157,19 @@ module KubernetesMetadata
|
|
156
157
|
end
|
157
158
|
|
158
159
|
# Process a watcher notice and potentially raise an exception.
|
159
|
-
def process_pod_watcher_notices(watcher)
|
160
|
-
watcher.each do |notice|
|
160
|
+
def process_pod_watcher_notices(watcher) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
161
|
+
watcher.each do |notice| # rubocop:disable Metrics/BlockLength
|
161
162
|
# store version we processed to not reprocess it ... do not unset when there is no version in response
|
162
|
-
version =
|
163
|
+
version = # TODO: replace with &.dig once we are on ruby 2.5+
|
163
164
|
notice[:object] && notice[:object][:metadata] && notice[:object][:metadata][:resourceVersion]
|
164
|
-
|
165
|
+
|
165
166
|
@last_seen_resource_version = version if version
|
166
167
|
|
167
168
|
case notice[:type]
|
168
169
|
when 'MODIFIED'
|
169
170
|
reset_pod_watch_retry_stats
|
170
171
|
cache_key = notice.dig(:object, :metadata, :uid)
|
171
|
-
cached
|
172
|
+
cached = @cache[cache_key]
|
172
173
|
if cached
|
173
174
|
@cache[cache_key] = parse_pod_metadata(notice[:object])
|
174
175
|
@stats.bump(:pod_cache_watch_updates)
|