fluent-plugin-kubernetes_metadata_filter 2.5.0 → 2.7.2

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.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
3
5
  # Kubernetes metadata
@@ -20,6 +22,7 @@
20
22
  require_relative 'kubernetes_metadata_cache_strategy'
21
23
  require_relative 'kubernetes_metadata_common'
22
24
  require_relative 'kubernetes_metadata_stats'
25
+ require_relative 'kubernetes_metadata_util'
23
26
  require_relative 'kubernetes_metadata_watch_namespaces'
24
27
  require_relative 'kubernetes_metadata_watch_pods'
25
28
 
@@ -33,6 +36,7 @@ module Fluent::Plugin
33
36
 
34
37
  include KubernetesMetadata::CacheStrategy
35
38
  include KubernetesMetadata::Common
39
+ include KubernetesMetadata::Util
36
40
  include KubernetesMetadata::WatchNamespaces
37
41
  include KubernetesMetadata::WatchPods
38
42
 
@@ -49,7 +53,7 @@ module Fluent::Plugin
49
53
  config_param :verify_ssl, :bool, default: true
50
54
  config_param :tag_to_kubernetes_name_regexp,
51
55
  :string,
52
- :default => 'var\.log\.containers\.(?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$'
56
+ default: 'var\.log\.containers\.(?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$'
53
57
  config_param :bearer_token_file, :string, default: nil
54
58
  config_param :secret_dir, :string, default: '/var/run/secrets/kubernetes.io/serviceaccount'
55
59
  config_param :de_dot, :bool, default: true
@@ -65,7 +69,7 @@ module Fluent::Plugin
65
69
  # parse format is defined here: https://github.com/kubernetes/kubernetes/blob/release-1.6/pkg/kubelet/dockertools/docker.go#L317
66
70
  config_param :container_name_to_kubernetes_regexp,
67
71
  :string,
68
- :default => '^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'
72
+ default: '^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'
69
73
 
70
74
  config_param :annotation_match, :array, default: []
71
75
  config_param :stats_interval, :integer, default: 30
@@ -81,6 +85,11 @@ module Fluent::Plugin
81
85
  config_param :skip_container_metadata, :bool, default: false
82
86
  config_param :skip_master_url, :bool, default: false
83
87
  config_param :skip_namespace_metadata, :bool, default: false
88
+
89
+ # A classname in the form of Test::APIAdapter which will try
90
+ # to be resolved from a relative named file 'test_api_adapter'
91
+ config_param :test_api_adapter, :string, default: nil
92
+
84
93
  # The time interval in seconds for retry backoffs when watch connections fail.
85
94
  config_param :watch_retry_interval, :integer, default: 1
86
95
  # The base number of exponential backoff for retries.
@@ -90,35 +99,25 @@ module Fluent::Plugin
90
99
 
91
100
  def fetch_pod_metadata(namespace_name, pod_name)
92
101
  log.trace("fetching pod metadata: #{namespace_name}/#{pod_name}") if log.trace?
93
- begin
94
- metadata = @client.get_pod(pod_name, namespace_name)
95
- unless metadata
96
- log.trace("no metadata returned for: #{namespace_name}/#{pod_name}") if log.trace?
97
- @stats.bump(:pod_cache_api_nil_not_found)
98
- else
99
- begin
100
- log.trace("raw metadata for #{namespace_name}/#{pod_name}: #{metadata}") if log.trace?
101
- metadata = parse_pod_metadata(metadata)
102
- @stats.bump(:pod_cache_api_updates)
103
- log.trace("parsed metadata for #{namespace_name}/#{pod_name}: #{metadata}") if log.trace?
104
- @cache[metadata['pod_id']] = metadata
105
- return metadata
106
- rescue Exception=>e
107
- log.debug(e)
108
- @stats.bump(:pod_cache_api_nil_bad_resp_payload)
109
- log.trace("returning empty metadata for #{namespace_name}/#{pod_name} due to error '#{e}'") if log.trace?
110
- end
111
- end
112
- rescue Exception=>e
113
- @stats.bump(:pod_cache_api_nil_error)
114
- log.debug "Exception '#{e}' encountered fetching pod metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
115
- end
102
+ options = {
103
+ resource_version: '0' # Fetch from API server cache instead of etcd quorum read
104
+ }
105
+ pod_object = @client.get_pod(pod_name, namespace_name, options)
106
+ log.trace("raw metadata for #{namespace_name}/#{pod_name}: #{pod_object}") if log.trace?
107
+ metadata = parse_pod_metadata(pod_object)
108
+ @stats.bump(:pod_cache_api_updates)
109
+ log.trace("parsed metadata for #{namespace_name}/#{pod_name}: #{metadata}") if log.trace?
110
+ @cache[metadata['pod_id']] = metadata
111
+ rescue StandardError => e
112
+ @stats.bump(:pod_cache_api_nil_error)
113
+ log.debug "Exception '#{e}' encountered fetching pod metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
116
114
  {}
117
115
  end
118
116
 
119
117
  def dump_stats
120
118
  @curr_time = Time.now
121
119
  return if @curr_time.to_i - @prev_time.to_i < @stats_interval
120
+
122
121
  @prev_time = @curr_time
123
122
  @stats.set(:pod_cache_size, @cache.count)
124
123
  @stats.set(:namespace_cache_size, @namespace_cache.count) if @namespace_cache
@@ -132,29 +131,18 @@ module Fluent::Plugin
132
131
 
133
132
  def fetch_namespace_metadata(namespace_name)
134
133
  log.trace("fetching namespace metadata: #{namespace_name}") if log.trace?
135
- begin
136
- metadata = @client.get_namespace(namespace_name)
137
- unless metadata
138
- log.trace("no metadata returned for: #{namespace_name}") if log.trace?
139
- @stats.bump(:namespace_cache_api_nil_not_found)
140
- else
141
- begin
142
- log.trace("raw metadata for #{namespace_name}: #{metadata}") if log.trace?
143
- metadata = parse_namespace_metadata(metadata)
144
- @stats.bump(:namespace_cache_api_updates)
145
- log.trace("parsed metadata for #{namespace_name}: #{metadata}") if log.trace?
146
- @namespace_cache[metadata['namespace_id']] = metadata
147
- return metadata
148
- rescue Exception => e
149
- log.debug(e)
150
- @stats.bump(:namespace_cache_api_nil_bad_resp_payload)
151
- log.trace("returning empty metadata for #{namespace_name} due to error '#{e}'") if log.trace?
152
- end
153
- end
154
- rescue Exception => kube_error
155
- @stats.bump(:namespace_cache_api_nil_error)
156
- log.debug "Exception '#{kube_error}' encountered fetching namespace metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
157
- end
134
+ options = {
135
+ resource_version: '0' # Fetch from API server cache instead of etcd quorum read
136
+ }
137
+ namespace_object = @client.get_namespace(namespace_name, nil, options)
138
+ log.trace("raw metadata for #{namespace_name}: #{namespace_object}") if log.trace?
139
+ metadata = parse_namespace_metadata(namespace_object)
140
+ @stats.bump(:namespace_cache_api_updates)
141
+ log.trace("parsed metadata for #{namespace_name}: #{metadata}") if log.trace?
142
+ @namespace_cache[metadata['namespace_id']] = metadata
143
+ rescue StandardError => e
144
+ @stats.bump(:namespace_cache_api_nil_error)
145
+ log.debug "Exception '#{e}' encountered fetching namespace metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}"
158
146
  {}
159
147
  end
160
148
 
@@ -174,12 +162,12 @@ module Fluent::Plugin
174
162
  require 'lru_redux'
175
163
  @stats = KubernetesMetadata::Stats.new
176
164
 
177
- if @de_dot && (@de_dot_separator =~ /\./).present?
165
+ if @de_dot && @de_dot_separator.include?('.')
178
166
  raise Fluent::ConfigError, "Invalid de_dot_separator: cannot be or contain '.'"
179
167
  end
180
168
 
181
169
  if @cache_ttl < 0
182
- log.info "Setting the cache TTL to :none because it was <= 0"
170
+ log.info 'Setting the cache TTL to :none because it was <= 0'
183
171
  @cache_ttl = :none
184
172
  end
185
173
 
@@ -197,11 +185,11 @@ module Fluent::Plugin
197
185
 
198
186
  # Use Kubernetes default service account if we're in a pod.
199
187
  if @kubernetes_url.nil?
200
- log.debug "Kubernetes URL is not set - inspecting environ"
188
+ log.debug 'Kubernetes URL is not set - inspecting environ'
201
189
 
202
190
  env_host = ENV['KUBERNETES_SERVICE_HOST']
203
191
  env_port = ENV['KUBERNETES_SERVICE_PORT']
204
- if env_host.present? && env_port.present?
192
+ if present?(env_host) && present?(env_port)
205
193
  if env_host =~ Resolv::IPv6::Regex
206
194
  # Brackets are needed around IPv6 addresses
207
195
  env_host = "[#{env_host}]"
@@ -209,7 +197,7 @@ module Fluent::Plugin
209
197
  @kubernetes_url = "https://#{env_host}:#{env_port}/api"
210
198
  log.debug "Kubernetes URL is now '#{@kubernetes_url}'"
211
199
  else
212
- log.debug "No Kubernetes URL could be found in config or environ"
200
+ log.debug 'No Kubernetes URL could be found in config or environ'
213
201
  end
214
202
  end
215
203
 
@@ -219,24 +207,23 @@ module Fluent::Plugin
219
207
  ca_cert = File.join(@secret_dir, K8_POD_CA_CERT)
220
208
  pod_token = File.join(@secret_dir, K8_POD_TOKEN)
221
209
 
222
- if !@ca_file.present? and File.exist?(ca_cert)
210
+ if !present?(@ca_file) && File.exist?(ca_cert)
223
211
  log.debug "Found CA certificate: #{ca_cert}"
224
212
  @ca_file = ca_cert
225
213
  end
226
214
 
227
- if !@bearer_token_file.present? and File.exist?(pod_token)
215
+ if !present?(@bearer_token_file) && File.exist?(pod_token)
228
216
  log.debug "Found pod token: #{pod_token}"
229
217
  @bearer_token_file = pod_token
230
218
  end
231
219
  end
232
220
 
233
- if @kubernetes_url.present?
234
-
221
+ if present?(@kubernetes_url)
235
222
  ssl_options = {
236
- client_cert: @client_cert.present? ? OpenSSL::X509::Certificate.new(File.read(@client_cert)) : nil,
237
- client_key: @client_key.present? ? OpenSSL::PKey::RSA.new(File.read(@client_key)) : nil,
238
- ca_file: @ca_file,
239
- verify_ssl: @verify_ssl ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
223
+ client_cert: present?(@client_cert) ? OpenSSL::X509::Certificate.new(File.read(@client_cert)) : nil,
224
+ client_key: present?(@client_key) ? OpenSSL::PKey::RSA.new(File.read(@client_key)) : nil,
225
+ ca_file: @ca_file,
226
+ verify_ssl: @verify_ssl ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
240
227
  }
241
228
 
242
229
  if @ssl_partial_chain
@@ -244,39 +231,53 @@ module Fluent::Plugin
244
231
  require 'openssl'
245
232
  ssl_store = OpenSSL::X509::Store.new
246
233
  ssl_store.set_default_paths
247
- if defined? OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
248
- flagval = OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
249
- else
250
- # this version of ruby does not define OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
251
- flagval = 0x80000
252
- end
234
+ flagval = if defined? OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
235
+ OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
236
+ else
237
+ # this version of ruby does not define OpenSSL::X509::V_FLAG_PARTIAL_CHAIN
238
+ 0x80000
239
+ end
253
240
  ssl_store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL | flagval
254
241
  ssl_options[:cert_store] = ssl_store
255
242
  end
256
243
 
257
244
  auth_options = {}
258
245
 
259
- if @bearer_token_file.present?
246
+ if present?(@bearer_token_file)
260
247
  bearer_token = File.read(@bearer_token_file)
261
248
  auth_options[:bearer_token] = bearer_token
262
249
  end
263
250
 
264
- log.debug "Creating K8S client"
265
- @client = Kubeclient::Client.new @kubernetes_url, @apiVersion,
266
- ssl_options: ssl_options,
267
- auth_options: auth_options
251
+ log.debug 'Creating K8S client'
252
+ @client = Kubeclient::Client.new(
253
+ @kubernetes_url,
254
+ @apiVersion,
255
+ ssl_options: ssl_options,
256
+ auth_options: auth_options,
257
+ as: :parsed_symbolized
258
+ )
259
+
260
+ if @test_api_adapter
261
+ log.info "Extending client with test api adaper #{@test_api_adapter}"
262
+ require_relative @test_api_adapter.underscore
263
+ @client.extend(eval(@test_api_adapter))
264
+ end
268
265
 
269
266
  begin
270
267
  @client.api_valid?
271
- rescue KubeException => kube_error
272
- raise Fluent::ConfigError, "Invalid Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{kube_error.message}"
268
+ rescue KubeException => e
269
+ raise Fluent::ConfigError, "Invalid Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{e.message}"
273
270
  end
274
271
 
275
272
  if @watch
276
- pod_thread = Thread.new(self) { |this| this.set_up_pod_thread }
273
+ if ENV['K8S_NODE_NAME'].nil? || ENV['K8S_NODE_NAME'].strip.empty?
274
+ log.warn("!! The environment variable 'K8S_NODE_NAME' is not set to the node name which can affect the API server and watch efficiency !!")
275
+ end
276
+
277
+ pod_thread = Thread.new(self, &:set_up_pod_thread)
277
278
  pod_thread.abort_on_exception = true
278
279
 
279
- namespace_thread = Thread.new(self) { |this| this.set_up_namespace_thread }
280
+ namespace_thread = Thread.new(self, &:set_up_namespace_thread)
280
281
  namespace_thread.abort_on_exception = true
281
282
  end
282
283
  end
@@ -287,25 +288,22 @@ module Fluent::Plugin
287
288
 
288
289
  @annotations_regexps = []
289
290
  @annotation_match.each do |regexp|
290
- begin
291
- @annotations_regexps << Regexp.compile(regexp)
292
- rescue RegexpError => e
293
- log.error "Error: invalid regular expression in annotation_match: #{e}"
294
- end
291
+ @annotations_regexps << Regexp.compile(regexp)
292
+ rescue RegexpError => e
293
+ log.error "Error: invalid regular expression in annotation_match: #{e}"
295
294
  end
296
-
297
295
  end
298
296
 
299
297
  def get_metadata_for_record(namespace_name, pod_name, container_name, container_id, create_time, batch_miss_cache)
300
298
  metadata = {
301
- 'docker' => {'container_id' => container_id},
299
+ 'docker' => { 'container_id' => container_id },
302
300
  'kubernetes' => {
303
- 'container_name' => container_name,
304
- 'namespace_name' => namespace_name,
305
- 'pod_name' => pod_name
301
+ 'container_name' => container_name,
302
+ 'namespace_name' => namespace_name,
303
+ 'pod_name' => pod_name
306
304
  }
307
305
  }
308
- if @kubernetes_url.present?
306
+ if present?(@kubernetes_url)
309
307
  pod_metadata = get_pod_metadata(container_id, namespace_name, pod_name, create_time, batch_miss_cache)
310
308
 
311
309
  if (pod_metadata.include? 'containers') && (pod_metadata['containers'].include? container_id) && !@skip_container_metadata
@@ -319,22 +317,9 @@ module Fluent::Plugin
319
317
  metadata
320
318
  end
321
319
 
322
- def create_time_from_record(record, internal_time)
323
- time_key = @time_fields.detect{ |ii| record.has_key?(ii) }
324
- time = record[time_key]
325
- if time.nil? || time.chop.empty?
326
- # `internal_time` is a Fluent::EventTime, it can't compare with Time.
327
- return Time.at(internal_time.to_f)
328
- end
329
- if ['_SOURCE_REALTIME_TIMESTAMP', '__REALTIME_TIMESTAMP'].include?(time_key)
330
- timei= time.to_i
331
- return Time.at(timei / 1000000, timei % 1000000)
332
- end
333
- return Time.parse(time)
334
- end
335
-
336
320
  def filter_stream(tag, es)
337
321
  return es if (es.respond_to?(:empty?) && es.empty?) || !es.is_a?(Fluent::EventStream)
322
+
338
323
  new_es = Fluent::MultiEventStream.new
339
324
  tag_match_data = tag.match(@tag_to_kubernetes_name_regexp_compiled) unless @use_journal
340
325
  tag_metadata = nil
@@ -342,23 +327,23 @@ module Fluent::Plugin
342
327
  es.each do |time, record|
343
328
  if tag_match_data && tag_metadata.nil?
344
329
  tag_metadata = get_metadata_for_record(tag_match_data['namespace'], tag_match_data['pod_name'], tag_match_data['container_name'],
345
- tag_match_data['docker_id'], create_time_from_record(record, time), batch_miss_cache)
330
+ tag_match_data['docker_id'], create_time_from_record(record, time), batch_miss_cache)
346
331
  end
347
332
  metadata = Marshal.load(Marshal.dump(tag_metadata)) if tag_metadata
348
333
  if (@use_journal || @use_journal.nil?) &&
349
- (j_metadata = get_metadata_for_journal_record(record, time, batch_miss_cache))
334
+ (j_metadata = get_metadata_for_journal_record(record, time, batch_miss_cache))
350
335
  metadata = j_metadata
351
336
  end
352
- if @lookup_from_k8s_field && record.has_key?('kubernetes') && record.has_key?('docker') &&
353
- record['kubernetes'].respond_to?(:has_key?) && record['docker'].respond_to?(:has_key?) &&
354
- record['kubernetes'].has_key?('namespace_name') &&
355
- record['kubernetes'].has_key?('pod_name') &&
356
- record['kubernetes'].has_key?('container_name') &&
357
- record['docker'].has_key?('container_id') &&
358
- (k_metadata = get_metadata_for_record(record['kubernetes']['namespace_name'], record['kubernetes']['pod_name'],
359
- record['kubernetes']['container_name'], record['docker']['container_id'],
360
- create_time_from_record(record, time), batch_miss_cache))
361
- metadata = k_metadata
337
+ if @lookup_from_k8s_field && record.key?('kubernetes') && record.key?('docker') &&
338
+ record['kubernetes'].respond_to?(:has_key?) && record['docker'].respond_to?(:has_key?) &&
339
+ record['kubernetes'].key?('namespace_name') &&
340
+ record['kubernetes'].key?('pod_name') &&
341
+ record['kubernetes'].key?('container_name') &&
342
+ record['docker'].key?('container_id') &&
343
+ (k_metadata = get_metadata_for_record(record['kubernetes']['namespace_name'], record['kubernetes']['pod_name'],
344
+ record['kubernetes']['container_name'], record['docker']['container_id'],
345
+ create_time_from_record(record, time), batch_miss_cache))
346
+ metadata = k_metadata
362
347
  end
363
348
 
364
349
  record = record.merge(metadata) if metadata
@@ -370,16 +355,16 @@ module Fluent::Plugin
370
355
 
371
356
  def get_metadata_for_journal_record(record, time, batch_miss_cache)
372
357
  metadata = nil
373
- if record.has_key?('CONTAINER_NAME') && record.has_key?('CONTAINER_ID_FULL')
358
+ if record.key?('CONTAINER_NAME') && record.key?('CONTAINER_ID_FULL')
374
359
  metadata = record['CONTAINER_NAME'].match(@container_name_to_kubernetes_regexp_compiled) do |match_data|
375
360
  get_metadata_for_record(match_data['namespace'], match_data['pod_name'], match_data['container_name'],
376
- record['CONTAINER_ID_FULL'], create_time_from_record(record, time), batch_miss_cache)
361
+ record['CONTAINER_ID_FULL'], create_time_from_record(record, time), batch_miss_cache)
377
362
  end
378
363
  unless metadata
379
364
  log.debug "Error: could not match CONTAINER_NAME from record #{record}"
380
365
  @stats.bump(:container_name_match_failed)
381
366
  end
382
- elsif record.has_key?('CONTAINER_NAME') && record['CONTAINER_NAME'].start_with?('k8s_')
367
+ elsif record.key?('CONTAINER_NAME') && record['CONTAINER_NAME'].start_with?('k8s_')
383
368
  log.debug "Error: no container name and id in record #{record}"
384
369
  @stats.bump(:container_name_id_missing)
385
370
  end
@@ -388,13 +373,17 @@ module Fluent::Plugin
388
373
 
389
374
  def de_dot!(h)
390
375
  h.keys.each do |ref|
391
- if h[ref] && ref =~ /\./
392
- v = h.delete(ref)
393
- newref = ref.to_s.gsub('.', @de_dot_separator)
394
- h[newref] = v
395
- end
376
+ next unless h[ref] && ref =~ /\./
377
+
378
+ v = h.delete(ref)
379
+ newref = ref.to_s.gsub('.', @de_dot_separator)
380
+ h[newref] = v
396
381
  end
397
382
  end
398
383
 
384
+ # copied from activesupport
385
+ def present?(object)
386
+ object.respond_to?(:empty?) ? !object.empty? : !!object
387
+ end
399
388
  end
400
389
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
3
5
  # Kubernetes metadata
@@ -21,31 +23,20 @@ module KubernetesMetadata
21
23
  def get_pod_metadata(key, namespace_name, pod_name, record_create_time, batch_miss_cache)
22
24
  metadata = {}
23
25
  ids = @id_cache[key]
24
- if !ids.nil?
26
+ if ids.nil?
25
27
  # FAST PATH
26
28
  # Cache hit, fetch metadata from the cache
27
- metadata = @cache.fetch(ids[:pod_id]) do
28
- @stats.bump(:pod_cache_miss)
29
- m = fetch_pod_metadata(namespace_name, pod_name)
30
- (m.nil? || m.empty?) ? {'pod_id'=>ids[:pod_id]} : m
31
- end
32
- metadata.merge!(@namespace_cache.fetch(ids[:namespace_id]) do
33
- @stats.bump(:namespace_cache_miss)
34
- m = fetch_namespace_metadata(namespace_name) unless @skip_namespace_metadata
35
- (m.nil? || m.empty?) ? {'namespace_id'=>ids[:namespace_id]} : m
36
- end)
37
- else
38
- # SLOW PATH
39
29
  @stats.bump(:id_cache_miss)
40
30
  return batch_miss_cache["#{namespace_name}_#{pod_name}"] if batch_miss_cache.key?("#{namespace_name}_#{pod_name}")
31
+
41
32
  pod_metadata = fetch_pod_metadata(namespace_name, pod_name)
42
33
  if @skip_namespace_metadata
43
- ids = { :pod_id=> pod_metadata['pod_id'] }
34
+ ids = { pod_id: pod_metadata['pod_id'] }
44
35
  @id_cache[key] = ids
45
36
  return pod_metadata
46
37
  end
47
38
  namespace_metadata = fetch_namespace_metadata(namespace_name)
48
- ids = { :pod_id=> pod_metadata['pod_id'], :namespace_id => namespace_metadata['namespace_id'] }
39
+ ids = { pod_id: pod_metadata['pod_id'], namespace_id: namespace_metadata['namespace_id'] }
49
40
  if !ids[:pod_id].nil? && !ids[:namespace_id].nil?
50
41
  # pod found and namespace found
51
42
  metadata = pod_metadata
@@ -59,7 +50,7 @@ module KubernetesMetadata
59
50
  # namespace is older then record for pod
60
51
  ids[:pod_id] = key
61
52
  metadata = @cache.fetch(ids[:pod_id]) do
62
- m = { 'pod_id' => ids[:pod_id] }
53
+ { 'pod_id' => ids[:pod_id] }
63
54
  end
64
55
  end
65
56
  metadata.merge!(namespace_metadata)
@@ -87,12 +78,25 @@ module KubernetesMetadata
87
78
  end
88
79
  end
89
80
  @id_cache[key] = ids unless batch_miss_cache.key?("#{namespace_name}_#{pod_name}")
81
+ else
82
+ # SLOW PATH
83
+ metadata = @cache.fetch(ids[:pod_id]) do
84
+ @stats.bump(:pod_cache_miss)
85
+ m = fetch_pod_metadata(namespace_name, pod_name)
86
+ m.nil? || m.empty? ? { 'pod_id' => ids[:pod_id] } : m
87
+ end
88
+ metadata.merge!(@namespace_cache.fetch(ids[:namespace_id]) do
89
+ m = unless @skip_namespace_metadata
90
+ @stats.bump(:namespace_cache_miss)
91
+ fetch_namespace_metadata(namespace_name)
92
+ end
93
+ m.nil? || m.empty? ? { 'namespace_id' => ids[:namespace_id] } : m
94
+ end)
90
95
  end
91
96
 
92
97
  # remove namespace info that is only used for comparison
93
98
  metadata.delete('creation_timestamp')
94
- metadata.delete_if{|k,v| v.nil?}
99
+ metadata.delete_if { |_k, v| v.nil? }
95
100
  end
96
-
97
101
  end
98
102
  end