fluent-plugin-kubernetes_metadata_filter 2.5.0 → 2.7.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b1991a6b8cd09f65728588401e697dda36954b94cf75b625789c6e7773d50ccf
4
- data.tar.gz: df46f28a113c17aa3e2174d3ad23edb0b5b93fb6d65d5f02787d6ac83ac129a2
3
+ metadata.gz: aa36ffbcd940e1dbb15d59f6d1e331091aa44611fbbaf3e19f562dec80b8fa42
4
+ data.tar.gz: e9e3bc68ab9e2f5ed6e88ed42d609aa583d3a2fbe34cd1e10e826ad4a32b8f5b
5
5
  SHA512:
6
- metadata.gz: 1a41d498af8a2e92723c05679608294d07acf2cf7a87dfdf5921fe3a385df6369003eef939dd5aeabf970c67f31eb319ac1485d566ac110bcbe6b79f5acc392a
7
- data.tar.gz: e62c355dbdb0ac1e89e43534c5929c80e82b166f5c614b1967d6ff79658835881a9c6803d5072e85a41c83fbefc8db326ba95c6d2f1c5a20ca1b8a0f18ce3cf1
6
+ metadata.gz: 6fa67fa39f78c33377c5eab486d1cd4f24b38e5e81769a5a9e27c87c6002e5fecfe0f43da56302d798a31d69d83b14b9f56f684c0e2c729735669c0c9fa326db
7
+ data.tar.gz: 5c94737a18204e093672471b7f1b31221794a2aced8d5f65099aab1e97f1937635d4957b2f36406bf8ef43f4bd874e004a460a8b92ff7cc999299fa701d67f42
data/.circleci/config.yml CHANGED
@@ -14,21 +14,21 @@ missingdeps: &missingdeps
14
14
  sudo cp /tmp/sources.list /etc/apt/sources.list
15
15
  sudo apt-get update
16
16
  sudo apt-get install cmake libicu-dev libssl-dev
17
-
17
+
18
18
  test: &test
19
19
  name: Test bundle
20
- command: bundle exec rake test
20
+ command: bundle exec rake test --trace
21
21
 
22
22
  executors:
23
- ruby-2-4:
24
- docker:
25
- - image: circleci/ruby:2.4.6
26
23
  ruby-2-5:
27
24
  docker:
28
25
  - image: circleci/ruby:2.5.5
29
26
  ruby-2-6:
30
27
  docker:
31
28
  - image: circleci/ruby:2.6.3
29
+ ruby-2-7:
30
+ docker:
31
+ - image: circleci/ruby:2.7.1
32
32
  jobs:
33
33
  "ruby-test":
34
34
  parameters:
@@ -49,9 +49,9 @@ jobs:
49
49
  workflows:
50
50
  "test_multiple_ruby_versions":
51
51
  jobs:
52
- - ruby-test:
53
- ruby-version: ruby-2-4
54
52
  - ruby-test:
55
53
  ruby-version: ruby-2-5
56
54
  - ruby-test:
57
55
  ruby-version: ruby-2-6
56
+ - ruby-test:
57
+ ruby-version: ruby-2-7
data/.rubocop.yml ADDED
@@ -0,0 +1,57 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5 # keep in sync with .circleci/config.yml and gemspec
3
+ NewCops: enable
4
+
5
+ Style/EmptyMethod:
6
+ Enabled: false
7
+
8
+ Metrics:
9
+ Enabled: false
10
+
11
+ # not safe ... needs require 'English'
12
+ Style/SpecialGlobalVars:
13
+ Enabled: false
14
+
15
+ Layout/LineLength:
16
+ Max: 205 # TODO: lower
17
+
18
+ Style/Documentation:
19
+ Enabled: false
20
+
21
+ Naming/AccessorMethodName:
22
+ Enabled: false
23
+
24
+ Naming/MethodParameterName:
25
+ Enabled: false
26
+
27
+ Style/IfInsideElse:
28
+ Enabled: false
29
+
30
+ Style/GuardClause:
31
+ Enabled: false
32
+
33
+ Lint/NestedMethodDefinition:
34
+ Enabled: false
35
+
36
+ # TODO: fix
37
+ Style/StringConcatenation:
38
+ Enabled: false
39
+
40
+ Style/NumericPredicate:
41
+ EnforcedStyle: comparison
42
+
43
+ Style/IfUnlessModifier:
44
+ Enabled: false
45
+
46
+ Style/ClassAndModuleChildren:
47
+ Enabled: false
48
+
49
+ # TODO: enable ... somehow breaks tests
50
+ Style/HashEachMethods:
51
+ Enabled: false
52
+
53
+ Style/WordArray:
54
+ EnforcedStyle: brackets
55
+
56
+ Style/SymbolArray:
57
+ EnforcedStyle: brackets
data/Gemfile CHANGED
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
- gem 'codeclimate-test-reporter', '<1.0.0', :group => :test, :require => nil
4
- gem 'rubocop', require: false
5
+ gem 'codeclimate-test-reporter', '<1.0.0', group: :test, require: nil
6
+ gem 'rubocop'
5
7
 
6
8
  # Specify your gem's dependencies in fluent-plugin-add.gemspec
7
9
  gemspec
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-kubernetes_metadata_filter (2.5.0)
5
- fluentd (>= 0.14.0, < 1.12)
4
+ fluent-plugin-kubernetes_metadata_filter (2.7.0)
5
+ fluentd (>= 0.14.0, < 1.13)
6
6
  kubeclient (< 5)
7
7
  lru_redux
8
8
 
@@ -12,36 +12,38 @@ GEM
12
12
  addressable (2.7.0)
13
13
  public_suffix (>= 2.0.2, < 5.0)
14
14
  ast (2.4.1)
15
- bump (0.9.0)
15
+ bump (0.10.0)
16
16
  charlock_holmes (0.7.7)
17
17
  codeclimate-test-reporter (0.6.0)
18
18
  simplecov (>= 0.7.1, < 1.0.0)
19
- concurrent-ruby (1.1.6)
20
- cool.io (1.6.0)
19
+ concurrent-ruby (1.1.8)
20
+ cool.io (1.7.1)
21
21
  copyright-header (1.0.22)
22
22
  github-linguist
23
- crack (0.4.3)
24
- safe_yaml (~> 1.0.0)
25
- docile (1.3.2)
23
+ crack (0.4.5)
24
+ rexml
25
+ docile (1.3.5)
26
26
  domain_name (0.5.20190701)
27
27
  unf (>= 0.0.5, < 1.0.0)
28
28
  escape_utils (1.2.1)
29
- ffi (1.13.1)
29
+ ffi (1.15.0)
30
30
  ffi-compiler (1.0.1)
31
31
  ffi (>= 1.0.0)
32
32
  rake
33
- fluentd (1.11.1)
33
+ fluentd (1.12.3)
34
+ bundler
34
35
  cool.io (>= 1.4.5, < 2.0.0)
35
36
  http_parser.rb (>= 0.5.1, < 0.7.0)
36
37
  msgpack (>= 1.3.1, < 2.0.0)
37
- serverengine (>= 2.0.4, < 3.0.0)
38
+ serverengine (>= 2.2.2, < 3.0.0)
38
39
  sigdump (~> 0.2.2)
39
40
  strptime (>= 0.2.2, < 1.0.0)
40
41
  tzinfo (>= 1.0, < 3.0)
41
42
  tzinfo-data (~> 1.0)
43
+ webrick (>= 1.4.2, < 1.8.0)
42
44
  yajl-ruby (~> 1.0)
43
- github-linguist (7.9.0)
44
- charlock_holmes (~> 0.7.6)
45
+ github-linguist (7.12.2)
46
+ charlock_holmes (~> 0.7.7)
45
47
  escape_utils (~> 1.2.0)
46
48
  mini_mime (~> 1.0)
47
49
  rugged (>= 0.25.1)
@@ -55,77 +57,83 @@ GEM
55
57
  http-cookie (1.0.3)
56
58
  domain_name (~> 0.5)
57
59
  http-form_data (2.3.0)
58
- http-parser (1.2.1)
60
+ http-parser (1.2.3)
59
61
  ffi-compiler (>= 1.0, < 2.0)
60
62
  http_parser.rb (0.6.0)
61
- kubeclient (4.7.0)
63
+ jsonpath (1.1.0)
64
+ multi_json
65
+ kubeclient (4.9.1)
62
66
  http (>= 3.0, < 5.0)
67
+ jsonpath (~> 1.0)
63
68
  recursive-open-struct (~> 1.1, >= 1.1.1)
64
69
  rest-client (~> 2.0)
65
70
  lru_redux (1.1.0)
66
71
  mime-types (3.3.1)
67
72
  mime-types-data (~> 3.2015)
68
- mime-types-data (3.2020.0512)
73
+ mime-types-data (3.2021.0225)
69
74
  mini_mime (1.0.2)
70
75
  minitest (4.7.5)
71
- msgpack (1.3.3)
76
+ msgpack (1.4.2)
77
+ multi_json (1.15.0)
72
78
  netrc (0.11.0)
73
- parallel (1.19.2)
74
- parser (2.7.1.4)
79
+ parallel (1.20.1)
80
+ parser (3.0.0.0)
75
81
  ast (~> 2.4.1)
76
82
  power_assert (1.2.0)
77
- public_suffix (4.0.5)
83
+ public_suffix (4.0.6)
78
84
  rainbow (3.0.0)
79
- rake (13.0.1)
80
- recursive-open-struct (1.1.2)
81
- regexp_parser (1.7.1)
85
+ rake (13.0.3)
86
+ recursive-open-struct (1.1.3)
87
+ regexp_parser (2.0.3)
82
88
  rest-client (2.1.0)
83
89
  http-accept (>= 1.7.0, < 2.0)
84
90
  http-cookie (>= 1.0.2, < 2.0)
85
91
  mime-types (>= 1.16, < 4.0)
86
92
  netrc (~> 0.8)
87
- rexml (3.2.4)
93
+ rexml (3.2.5)
88
94
  rr (1.2.1)
89
- rubocop (0.86.0)
95
+ rubocop (1.8.1)
90
96
  parallel (~> 1.10)
91
- parser (>= 2.7.0.1)
97
+ parser (>= 3.0.0.0)
92
98
  rainbow (>= 2.2.2, < 4.0)
93
- regexp_parser (>= 1.7)
99
+ regexp_parser (>= 1.8, < 3.0)
94
100
  rexml
95
- rubocop-ast (>= 0.0.3, < 1.0)
101
+ rubocop-ast (>= 1.2.0, < 2.0)
96
102
  ruby-progressbar (~> 1.7)
97
- unicode-display_width (>= 1.4.0, < 2.0)
98
- rubocop-ast (0.1.0)
99
- parser (>= 2.7.0.1)
100
- ruby-progressbar (1.10.1)
101
- rugged (1.0.1)
102
- safe_yaml (1.0.5)
103
- serverengine (2.2.1)
103
+ unicode-display_width (>= 1.4.0, < 3.0)
104
+ rubocop-ast (1.4.0)
105
+ parser (>= 2.7.1.5)
106
+ ruby-progressbar (1.11.0)
107
+ rugged (1.1.0)
108
+ serverengine (2.2.3)
104
109
  sigdump (~> 0.2.2)
105
110
  sigdump (0.2.4)
106
- simplecov (0.18.5)
111
+ simplecov (0.21.2)
107
112
  docile (~> 1.1)
108
113
  simplecov-html (~> 0.11)
109
- simplecov-html (0.12.2)
110
- strptime (0.2.4)
114
+ simplecov_json_formatter (~> 0.1)
115
+ simplecov-html (0.12.3)
116
+ simplecov_json_formatter (0.1.2)
117
+ strptime (0.2.5)
111
118
  test-unit (3.0.9)
112
119
  power_assert
113
120
  test-unit-rr (1.0.5)
114
121
  rr (>= 1.1.1)
115
122
  test-unit (>= 2.5.2)
116
- tzinfo (2.0.2)
123
+ tzinfo (2.0.4)
117
124
  concurrent-ruby (~> 1.0)
118
- tzinfo-data (1.2020.1)
125
+ tzinfo-data (1.2021.1)
119
126
  tzinfo (>= 1.0.0)
120
127
  unf (0.1.4)
121
128
  unf_ext
122
129
  unf_ext (0.0.7.7)
123
- unicode-display_width (1.7.0)
130
+ unicode-display_width (2.0.0)
124
131
  vcr (6.0.0)
125
- webmock (3.8.3)
132
+ webmock (3.11.1)
126
133
  addressable (>= 2.3.6)
127
134
  crack (>= 0.3.2)
128
135
  hashdiff (>= 0.4.0, < 2.0.0)
136
+ webrick (1.7.0)
129
137
  yajl-ruby (1.4.1)
130
138
 
131
139
  PLATFORMS
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
  [![Circle CI](https://circleci.com/gh/fabric8io/fluent-plugin-kubernetes_metadata_filter.svg?style=svg)](https://circleci.com/gh/fabric8io/fluent-plugin-kubernetes_metadata_filter)
3
3
  [![Code Climate](https://codeclimate.com/github/fabric8io/fluent-plugin-kubernetes_metadata_filter/badges/gpa.svg)](https://codeclimate.com/github/fabric8io/fluent-plugin-kubernetes_metadata_filter)
4
4
  [![Test Coverage](https://codeclimate.com/github/fabric8io/fluent-plugin-kubernetes_metadata_filter/badges/coverage.svg)](https://codeclimate.com/github/fabric8io/fluent-plugin-kubernetes_metadata_filter)
5
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop-hq/rubocop)
6
+ [![Ruby Style Guide](https://img.shields.io/badge/code_style-community-brightgreen.svg)](https://rubystyle.guide)
5
7
 
6
8
  The Kubernetes metadata plugin filter enriches container log records with pod and namespace metadata.
7
9
 
@@ -39,7 +41,7 @@ Configuration options for fluent.conf are:
39
41
  * `client_key` - path to a client key file to authenticate to the API server
40
42
  * `bearer_token_file` - path to a file containing the bearer token to use for authentication
41
43
  * `tag_to_kubernetes_name_regexp` - the regular expression used to extract kubernetes metadata (pod name, container name, namespace) from the current fluentd tag.
42
- This must used named capture groups for `container_name`, `pod_name` & `namespace` (default: `\.(?<pod_name>[^\._]+)_(?<namespace>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$</pod>)`)
44
+ This must used named capture groups for `container_name`, `pod_name` & `namespace` default: See [code](https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter/blob/master/lib/fluent/plugin/filter_kubernetes_metadata.rb#L52)
43
45
  * `cache_size` - size of the cache of Kubernetes metadata to reduce requests to the API server (default: `1000`)
44
46
  * `cache_ttl` - TTL in seconds of each cached element. Set to negative value to disable TTL eviction (default: `3600` - 1 hour)
45
47
  * `watch` - set up a watch on pods on the API server for updates to metadata (default: `true`)
@@ -47,7 +49,7 @@ This must used named capture groups for `container_name`, `pod_name` & `namespac
47
49
  * `de_dot_separator` - separator to use if `de_dot` is enabled (default: `_`)
48
50
  * *DEPRECATED* `use_journal` - If false, messages are expected to be formatted and tagged as if read by the fluentd in\_tail plugin with wildcard filename. If true, messages are expected to be formatted as if read from the systemd journal. The `MESSAGE` field has the full message. The `CONTAINER_NAME` field has the encoded k8s metadata (see below). The `CONTAINER_ID_FULL` field has the full container uuid. This requires docker to use the `--log-driver=journald` log driver. If unset (the default), the plugin will use the `CONTAINER_NAME` and `CONTAINER_ID_FULL` fields
49
51
  if available, otherwise, will use the tag in the `tag_to_kubernetes_name_regexp` format.
50
- * `container_name_to_kubernetes_regexp` - The regular expression used to extract the k8s metadata encoded in the journal `CONTAINER_NAME` field (default: `'^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'`
52
+ * `container_name_to_kubernetes_regexp` - The regular expression used to extract the k8s metadata encoded in the journal `CONTAINER_NAME` field default: See [code](https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter/blob/master/lib/fluent/plugin/filter_kubernetes_metadata.rb#L68)
51
53
  * This corresponds to the definition [in the source](https://github.com/kubernetes/kubernetes/blob/release-1.6/pkg/kubelet/dockertools/docker.go#L317)
52
54
  * `annotation_match` - Array of regular expressions matching annotation field names. Matched annotations are added to a log record.
53
55
  * `allow_orphans` - Modify the namespace and namespace id to the values of `orphaned_namespace_name` and `orphaned_namespace_id`
data/Rakefile CHANGED
@@ -1,10 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
1
4
  require 'bundler/gem_tasks'
2
5
  require 'rake/testtask'
3
6
  require 'bump/tasks'
7
+ require 'rubocop/rake_task'
4
8
 
5
- task :test => [:base_test]
9
+ task test: [:base_test]
10
+ task default: [:test, :build, :rubocop]
6
11
 
7
- task :default => [:test, :build]
12
+ RuboCop::RakeTask.new
8
13
 
9
14
  desc 'Run test_unit based test'
10
15
  Rake::TestTask.new(:base_test) do |t|
@@ -13,7 +18,6 @@ Rake::TestTask.new(:base_test) do |t|
13
18
  # $ bundle exec rake base_test TEST=test/test_*.rb
14
19
  t.libs << 'test'
15
20
  t.test_files = Dir['test/**/test_*.rb'].sort
16
- #t.verbose = true
17
21
  t.warning = false
18
22
  end
19
23
 
@@ -23,15 +27,15 @@ task :headers do
23
27
  require 'copyright_header'
24
28
 
25
29
  args = {
26
- :license => 'Apache-2.0',
27
- :copyright_software => 'Fluentd Kubernetes Metadata Filter Plugin',
28
- :copyright_software_description => 'Enrich Fluentd events with Kubernetes metadata',
29
- :copyright_holders => ['Red Hat, Inc.'],
30
- :copyright_years => ['2015-2017'],
31
- :add_path => 'lib:test',
32
- :output_dir => '.'
30
+ license: 'Apache-2.0',
31
+ copyright_software: 'Fluentd Kubernetes Metadata Filter Plugin',
32
+ copyright_software_description: 'Enrich Fluentd events with Kubernetes metadata',
33
+ copyright_holders: ['Red Hat, Inc.'],
34
+ copyright_years: ['2015-2021'],
35
+ add_path: 'lib:test',
36
+ output_dir: '.'
33
37
  }
34
38
 
35
- command_line = CopyrightHeader::CommandLine.new( args )
39
+ command_line = CopyrightHeader::CommandLine.new(args)
36
40
  command_line.execute
37
41
  end
@@ -1,36 +1,34 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
 
5
6
  Gem::Specification.new do |gem|
6
- gem.name = "fluent-plugin-kubernetes_metadata_filter"
7
- gem.version = "2.5.0"
8
- gem.authors = ["Jimmi Dyson"]
9
- gem.email = ["jimmidyson@gmail.com"]
10
- gem.description = %q{Filter plugin to add Kubernetes metadata}
11
- gem.summary = %q{Fluentd filter plugin to add Kubernetes metadata}
12
- gem.homepage = "https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter"
13
- gem.license = "Apache-2.0"
7
+ gem.name = 'fluent-plugin-kubernetes_metadata_filter'
8
+ gem.version = '2.7.0'
9
+ gem.authors = ['Jimmi Dyson']
10
+ gem.email = ['jimmidyson@gmail.com']
11
+ gem.description = 'Filter plugin to add Kubernetes metadata'
12
+ gem.summary = 'Fluentd filter plugin to add Kubernetes metadata'
13
+ gem.homepage = 'https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter'
14
+ gem.license = 'Apache-2.0'
14
15
 
15
16
  gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
19
17
 
20
- gem.required_ruby_version = '>= 2.1.0'
18
+ gem.required_ruby_version = '>= 2.5.0'
21
19
 
22
- gem.add_runtime_dependency 'fluentd', ['>= 0.14.0', '< 1.12']
23
- gem.add_runtime_dependency "lru_redux"
24
- gem.add_runtime_dependency "kubeclient", '< 5'
20
+ gem.add_runtime_dependency 'fluentd', ['>= 0.14.0', '< 1.13']
21
+ gem.add_runtime_dependency 'kubeclient', '< 5'
22
+ gem.add_runtime_dependency 'lru_redux'
25
23
 
26
- gem.add_development_dependency "bundler", "~> 2.0"
27
- gem.add_development_dependency "rake"
28
- gem.add_development_dependency "minitest", "~> 4.0"
29
- gem.add_development_dependency "test-unit", "~> 3.0.2"
30
- gem.add_development_dependency "test-unit-rr", "~> 1.0.3"
31
- gem.add_development_dependency "copyright-header"
32
- gem.add_development_dependency "webmock"
33
- gem.add_development_dependency "vcr"
34
- gem.add_development_dependency "bump"
35
- gem.add_development_dependency "yajl-ruby"
24
+ gem.add_development_dependency 'bump'
25
+ gem.add_development_dependency 'bundler', '~> 2.0'
26
+ gem.add_development_dependency 'copyright-header'
27
+ gem.add_development_dependency 'minitest', '~> 4.0'
28
+ gem.add_development_dependency 'rake'
29
+ gem.add_development_dependency 'test-unit', '~> 3.0.2'
30
+ gem.add_development_dependency 'test-unit-rr', '~> 1.0.3'
31
+ gem.add_development_dependency 'vcr'
32
+ gem.add_development_dependency 'webmock'
33
+ gem.add_development_dependency 'yajl-ruby'
36
34
  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
@@ -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