fluent-plugin-kubernetes_metadata_filter 3.7.0 → 3.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|