fluent-plugin-k8s-metrics-agg 1.1.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60991c52f3ffacbee65a82a67ccb02903417800ffd74287c0fbf322aa03a318e
4
- data.tar.gz: 4dd9cf5ae9ee3699d27efd4495c8de0a493f8f9ed536fe03b9ee3dcaf269f8fe
3
+ metadata.gz: dafdc24e3159101b532162d528800ee781dc5a10c62824a97cc3b5506c977ae0
4
+ data.tar.gz: d40d159adcac648fee03f13fe88697c5491208ef0557adc4074726be50d88eaa
5
5
  SHA512:
6
- metadata.gz: 2debd68c82b5d490f1d0b73b304bcf49a39555d24f96473845a21358490fb10bef343775d26963cbc652f6f8c72515931a0a7d2f0021ccc28efdb1271b8bec73
7
- data.tar.gz: ad770e300cf2ec07a572c73650b1a06265bb8b0c8d59338535ed45ca4a44655c3dfaecc7acf578233e0273a363e66f80e38cb0710a7e79b358b538300368adb3
6
+ metadata.gz: 7ace62d329f0b1f316563d758e9a7ca045914d37811606ce6e07f9fb807c2b3cf907d3dd025983356097c813308b191b77677ddbfbbba56d50fe9aa5c7744786
7
+ data.tar.gz: 456d5c39db1fc1dc0d159c920dd612dc39f474b6d873b3963ee42dbbc7ade903079b113b844c3ef16e2830b545f583f3383caafccec42943f3d96ed0f6d72c4e
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env bash
2
2
  set -e
3
+ FLUENTD_HEC_GEM_VERSION=`cat docker/FLUENTD_HEC_GEM_VERSION`
3
4
  aws ecr get-login --region $AWS_REGION --no-include-email | bash
4
5
  echo "Building docker image..."
5
6
  cp /tmp/pkg/fluent-plugin-k8s-metrics-agg-*.gem docker
6
- docker build --build-arg VERSION=$FLUENT_SPLUNK_HEC_GEM_VERSION --no-cache -t splunk/fluent-plugin-k8s-metrics-agg:metrics-aggregator ./docker
7
+ docker build --build-arg VERSION=$FLUENTD_HEC_GEM_VERSION --no-cache -t splunk/fluent-plugin-k8s-metrics-agg:metrics-aggregator ./docker
7
8
  docker tag splunk/fluent-plugin-k8s-metrics-agg:metrics-aggregator $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/k8s-ci-metrics-agg:latest
8
9
  echo "Push docker image to ecr..."
9
10
  docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/k8s-ci-metrics-agg:latest | awk 'END{print}'
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env bash
2
2
  set -e
3
+ FLUENTD_HEC_GEM_VERSION=`cat docker/FLUENTD_HEC_GEM_VERSION`
3
4
  echo "Building docker image..."
4
5
  cp /tmp/pkg/fluent-plugin-k8s-metrics-agg-*.gem docker
5
6
  VERSION=`cat VERSION`
6
- docker build --build-arg VERSION=$VERSION --no-cache -t splunk/fluent-plugin-k8s-metrics-agg:metrics-aggregator ./docker
7
+ docker build --build-arg VERSION=$FLUENTD_HEC_GEM_VERSION --no-cache -t splunk/fluent-plugin-k8s-metrics-agg:metrics-aggregator ./docker
7
8
  docker tag splunk/fluent-plugin-k8s-metrics-agg:metrics-aggregator splunk/${DOCKERHUB_REPO_NAME}:${VERSION}
8
9
  echo "Push docker image to splunk dockerhub..."
9
10
  docker login --username=$DOCKERHUB_ACCOUNT_ID --password=$DOCKERHUB_ACCOUNT_PASS
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+
4
+ #!/usr/bin/env bash
5
+ LATEST_COMMIT=$(git rev-parse HEAD)
6
+ VERSION_COMMIT=$(git log -1 --format=format:%H VERSION)
7
+ if [ $VERSION_COMMIT = $LATEST_COMMIT ];
8
+ then
9
+ if [ -s VERSION ] # Check if content is empty
10
+ then
11
+ VERSION=`cat VERSION`
12
+ echo "VERSION is changed to $VERSION"
13
+ else
14
+ echo "[ERROR] VERSION file is empty."
15
+ exit 1
16
+ fi
17
+ git config user.email "splunk-oss-admin@splunk.com"
18
+ git config user.name "splunk-oss-admin"
19
+ git checkout develop
20
+ git pull origin develop
21
+ git checkout -b release/$VERSION origin/develop
22
+ git push https://$RELEASE_GITHUB_USER:$RELEASE_GITHUB_PASS@github.com/splunk/fluent-plugin-k8s-metrics-agg.git release/$VERSION
23
+ git checkout master
24
+ git merge --no-edit release/$VERSION
25
+ git push https://$RELEASE_GITHUB_USER:$RELEASE_GITHUB_PASS@github.com/splunk/fluent-plugin-k8s-metrics-agg.git master
26
+ fi
@@ -82,12 +82,34 @@ jobs:
82
82
  name: Upload gem to Github
83
83
  command: |
84
84
  .circleci/build_and_push_to_github_release.sh
85
+ - run:
86
+ name: Upload gem to Ruby Gem
87
+ command: |
88
+ .circleci/push_gems_to_rubygems.sh
89
+
90
+ check_version:
91
+ docker:
92
+ - image: circleci/ruby:2.6.1-node-browsers
93
+ working_directory: ~/repo
94
+ steps:
95
+ - attach_workspace:
96
+ at: /tmp
97
+ - checkout
98
+ - setup_remote_docker:
99
+ reusable: true
100
+ - run:
101
+ name: Check VERSION file for change
102
+ command: |
103
+ .circleci/check_version_trigger_release.sh
85
104
 
86
105
  workflows:
87
106
  version: 2
88
107
  build_test_push:
89
108
  jobs:
90
- - build
109
+ - build:
110
+ filters:
111
+ branches:
112
+ ignore: /^release\/.*/
91
113
  - test:
92
114
  requires:
93
115
  - build
@@ -97,9 +119,15 @@ workflows:
97
119
  filters:
98
120
  branches:
99
121
  only: develop
100
- - release:
122
+ - check_version:
101
123
  requires:
102
- - test
124
+ - push
125
+ release:
126
+ jobs:
127
+ - build:
103
128
  filters:
104
129
  branches:
105
- only: master
130
+ only: master
131
+ - release:
132
+ requires:
133
+ - build
@@ -0,0 +1,2 @@
1
+ ---
2
+ :rubygems_api_key: __RUBYGEMS_API_KEY__
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env bash
2
2
  set -e
3
+ sudo apt-get update
3
4
  sudo apt-get install -y python-pip libpython-dev > /dev/null 2>&1
4
5
  echo "Installing aws cli..."
5
6
  sudo pip install awscli > /dev/null 2>&1
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+ echo "Pushing metrics aggr gem to rubygems.org..."
4
+ echo "gem `gem --version`"
5
+ cat .circleci/gem_credentials | sed -e "s/__RUBYGEMS_API_KEY__/${RUBYGEMS_API_KEY}/" > ~/.gem/credentials
6
+ chmod 0600 ~/.gem/credentials
7
+ gem push /tmp/pkg/fluent-plugin-k8s-metrics-agg-*.gem
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report a bug encountered while operating fluent-plugin-k8s-metrics-agg
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ <!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks!
11
+
12
+ Please do not report security vulnerabilities with public GitHub issue reports. Please report security issues here: https://www.splunk.com/goto/report_vulnerabilities_prodsec
13
+ -->
14
+
15
+
16
+ **What happened**:
17
+
18
+ **What you expected to happen**:
19
+
20
+ **How to reproduce it (as minimally and precisely as possible)**:
21
+
22
+ **Anything else we need to know?**:
23
+
24
+ **Environment**:
25
+ - Kubernetes version (use `kubectl version`):
26
+ - Ruby version (use `ruby --version`):
27
+ - OS (e.g: `cat /etc/os-release`):
28
+ - Splunk version:
29
+ - Others:
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: Enhancement Request
3
+ about: Suggest an enhancement to the fluent-plugin-k8s-metrics-agg project
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ <<!-- Please only use this template for submitting enhancement requests -->
11
+
12
+ **What would you like to be added**:
13
+
14
+ **Why is this needed**:
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: Failing Test
3
+ about: Report test failures in fluent-plugin-k8s-metrics-agg
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ <!-- Please only use this template for submitting reports about failing tests -->
11
+
12
+ **Which test(s) are failing**:
13
+
14
+ **Since when has it been failing**:
15
+
16
+ **Reason for failure**:
17
+
18
+ **Anything else we need to know**:
@@ -0,0 +1,23 @@
1
+ ## Proposed changes
2
+
3
+ Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.
4
+
5
+ ## Types of changes
6
+
7
+ What types of changes does your code introduce?
8
+ _Put an `x` in the boxes that apply_
9
+
10
+ - [ ] Bugfix (non-breaking change which fixes an issue)
11
+ - [ ] New feature (non-breaking change which adds functionality)
12
+ - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
13
+
14
+ ## Checklist
15
+
16
+ _Put an `x` in the boxes that apply._
17
+
18
+ - [ ] I have read the [CONTRIBUTING](https://github.com/splunk/fluent-plugin-k8s-metrics-agg/blob/develop/CONTRIBUTING.md) doc
19
+ - [ ] I have read the [CLA](https://github.com/splunk/fluent-plugin-k8s-metrics-agg/blob/develop/CLA.md)
20
+ - [ ] I have added tests that prove my fix is effective or that my feature works
21
+ - [ ] I have added necessary documentation (if appropriate)
22
+ - [ ] Any dependent changes have been merged and published in downstream modules
23
+
data/CLA.md ADDED
@@ -0,0 +1,18 @@
1
+ By submitting a Contribution to this Work, You agree that Your Contribution is made subject to the primary LICENSE
2
+ file applicable to this Work. In addition, You represent that: (i) You are the copyright owner of the Contribution
3
+ or (ii) You have the requisite rights to make the Contribution.
4
+
5
+ Definitions:
6
+
7
+ “You” shall mean: (i) yourself if you are making a Contribution on your own behalf; or (ii) your company,
8
+ if you are making a Contribution on behalf of your company. If you are making a Contribution on behalf of your
9
+ company, you represent that you have the requisite authority to do so.
10
+
11
+ "Contribution" shall mean any original work of authorship, including any modifications or additions to an existing
12
+ work, that is intentionally submitted by You for inclusion in, or documentation of, this project/repository. For the
13
+ purposes of this definition, "submitted" means any form of electronic, verbal, or written communication submitted for
14
+ inclusion in this project/repository, including but not limited to communication on electronic mailing lists, source
15
+ code control systems, and issue tracking systems that are managed by, or on behalf of, the maintainers of
16
+ the project/repository.
17
+
18
+ “Work” shall mean the collective software, content, and documentation in this project/repository.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-k8s-metrics-agg (1.1.0)
4
+ fluent-plugin-k8s-metrics-agg (1.1.1)
5
5
  fluentd (~> 1.3.3)
6
6
  kubeclient (~> 4.2.2)
7
7
  multi_json (~> 1.13.1)
@@ -12,12 +12,12 @@ GEM
12
12
  specs:
13
13
  addressable (2.6.0)
14
14
  public_suffix (>= 2.0.2, < 4.0)
15
- cool.io (1.5.3)
15
+ cool.io (1.5.4)
16
16
  crack (0.4.3)
17
17
  safe_yaml (~> 1.0.0)
18
18
  dig_rb (1.0.1)
19
19
  docile (1.3.1)
20
- domain_name (0.5.20180417)
20
+ domain_name (0.5.20190701)
21
21
  unf (>= 0.0.5, < 1.0.0)
22
22
  fluentd (1.3.3)
23
23
  cool.io (>= 1.4.5, < 2.0.0)
@@ -36,6 +36,7 @@ GEM
36
36
  http-cookie (~> 1.0)
37
37
  http-form_data (~> 2.0)
38
38
  http_parser.rb (~> 0.6.0)
39
+ http-accept (1.7.0)
39
40
  http-cookie (1.0.3)
40
41
  domain_name (~> 0.5)
41
42
  http-form_data (2.1.1)
@@ -45,23 +46,24 @@ GEM
45
46
  http (~> 3.0)
46
47
  recursive-open-struct (~> 1.0, >= 1.0.4)
47
48
  rest-client (~> 2.0)
48
- mime-types (3.2.2)
49
+ mime-types (3.3)
49
50
  mime-types-data (~> 3.2015)
50
- mime-types-data (3.2018.0812)
51
- msgpack (1.2.6)
51
+ mime-types-data (3.2019.1009)
52
+ msgpack (1.3.1)
52
53
  multi_json (1.13.1)
53
54
  netrc (0.11.0)
54
- oj (3.7.9)
55
+ oj (3.7.12)
55
56
  power_assert (1.1.3)
56
57
  public_suffix (3.0.3)
57
58
  rake (12.3.2)
58
59
  recursive-open-struct (1.1.0)
59
- rest-client (2.0.2)
60
+ rest-client (2.1.0)
61
+ http-accept (>= 1.7.0, < 2.0)
60
62
  http-cookie (>= 1.0.2, < 2.0)
61
63
  mime-types (>= 1.16, < 4.0)
62
64
  netrc (~> 0.8)
63
65
  safe_yaml (1.0.4)
64
- serverengine (2.1.0)
66
+ serverengine (2.1.1)
65
67
  sigdump (~> 0.2.2)
66
68
  sigdump (0.2.4)
67
69
  simplecov (0.16.1)
@@ -75,11 +77,11 @@ GEM
75
77
  thread_safe (0.3.6)
76
78
  tzinfo (1.2.5)
77
79
  thread_safe (~> 0.1)
78
- tzinfo-data (1.2018.9)
80
+ tzinfo-data (1.2019.3)
79
81
  tzinfo (>= 1.0.0)
80
82
  unf (0.1.4)
81
83
  unf_ext
82
- unf_ext (0.0.7.5)
84
+ unf_ext (0.0.7.6)
83
85
  webmock (3.5.1)
84
86
  addressable (>= 2.3.6)
85
87
  crack (>= 0.3.2)
@@ -98,4 +100,4 @@ DEPENDENCIES
98
100
  webmock (~> 3.5.1)
99
101
 
100
102
  BUNDLED WITH
101
- 2.0.1
103
+ 2.0.2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.1.1
@@ -0,0 +1 @@
1
+ 1.1.2
@@ -355,7 +355,7 @@ module Fluent
355
355
  begin
356
356
  @client.discover unless @client.discovered
357
357
  @client.rest_client['/pods'].tap do |endpoint|
358
- log.info("Use URL #{endpoint.url} for scraping limits requests metrics")
358
+ log.debug("Use URL #{endpoint.url} for scraping limits requests metrics")
359
359
  end
360
360
  end
361
361
  end
@@ -363,6 +363,9 @@ module Fluent
363
363
  def scrape_limits_requests_metrics
364
364
  response = limits_requests_api.get(@client.headers)
365
365
  handle_limits_requests_res(response)
366
+ rescue StandardError => e
367
+ log.error "Failed to get limit metrics, error=#{$ERROR_INFO}, #{e.inspect}"
368
+ log.error_backtrace
366
369
  end
367
370
 
368
371
  # This method is used to handle responses from the kube apiserver api
@@ -375,7 +378,7 @@ module Fluent
375
378
  log.error "ExMultiJson.load(response.body) expected 2xx from summary API, but got #{response.code}. Response body = #{response.body}"
376
379
  end
377
380
  rescue StandardError => e
378
- log.error "Failed to scrape metrics, error=#{$ERROR_INFO}, #{e.inspect}"
381
+ log.error "Failed to scrape limit metrics, error=#{$ERROR_INFO}, #{e.inspect}"
379
382
  log.error_backtrace
380
383
  end
381
384
 
@@ -420,7 +423,7 @@ module Fluent
420
423
  pod_usage_metrics.add_usage_metrics(cpu_limit, cpu_request, memory_limit, memory_request)
421
424
  end
422
425
 
423
- pod_labels = { 'name' => pod_json['metadata']['name'], 'namespace' => pod_json['metadata']['name'], 'node' => pod_json['spec']['nodeName'] }
426
+ pod_labels = { 'name' => pod_json['metadata']['name'], 'namespace' => pod_json['metadata']['namespace'], 'node' => pod_json['spec']['nodeName'] }
424
427
  emit_limits_requests_metrics(generate_tag('pod'), @scraped_at, pod_labels, pod_usage_metrics)
425
428
  @@namespace_usage_metrics_map[pod_namespace].add_usage_metrics(pod_usage_metrics.instance_variable_get(:@cpu_limit).to_s + ('m'), pod_usage_metrics.instance_variable_get(:@cpu_request).to_s + ('m'),
426
429
  pod_usage_metrics.instance_variable_get(:@memory_limit).to_s + ('Mi'), pod_usage_metrics.instance_variable_get(:@memory_request).to_s + ('Mi'))
@@ -454,7 +457,7 @@ module Fluent
454
457
  begin
455
458
  @client.discover unless @client.discovered
456
459
  @client.rest_client['/nodes'].tap do |endpoint|
457
- log.info("Use URL #{endpoint.url} for scraping node metrics")
460
+ log.debug("Use URL #{endpoint.url} for scraping node metrics")
458
461
  end
459
462
  end
460
463
  end
@@ -462,6 +465,9 @@ module Fluent
462
465
  def scrape_node_metrics
463
466
  response = node_api.get(@client.headers)
464
467
  handle_node_response(response)
468
+ rescue StandardError => e
469
+ log.error "Failed to get node metrics, error=#{$ERROR_INFO}, #{e.inspect}"
470
+ log.error_backtrace
465
471
  end
466
472
 
467
473
  # This method is used to handle responses from the kubeapiserver api
@@ -474,7 +480,7 @@ module Fluent
474
480
  log.error "ExMultiJson.load(response.body) expected 2xx from summary API, but got #{response.code}. Response body = #{response.body}"
475
481
  end
476
482
  rescue StandardError => e
477
- log.error "Failed to scrape metrics, error=#{$ERROR_INFO}, #{e.inspect}"
483
+ log.error "Failed to scrape node metrics, error=#{$ERROR_INFO}, #{e.inspect}"
478
484
  log.error_backtrace
479
485
  end
480
486
 
@@ -527,7 +533,7 @@ module Fluent
527
533
  begin
528
534
  @client.discover unless @client.discovered
529
535
  @client.rest_client['/nodes'].tap do |endpoint|
530
- log.info("Use URL #{endpoint.url} for scraping node metrics")
536
+ log.debug("Use URL #{endpoint.url} for scraping node metrics")
531
537
  end
532
538
  end
533
539
  end
@@ -535,6 +541,9 @@ module Fluent
535
541
  def scrape_resource_usage_metrics
536
542
  response = resource_usage_api.get(@client.headers)
537
543
  handle_resource_usage_response(response)
544
+ rescue StandardError => e
545
+ log.error "Failed to get resource usage metrics, error=#{$ERROR_INFO}, #{e.inspect}"
546
+ log.error_backtrace
538
547
  end
539
548
 
540
549
  # This method is used to handle responses from the kubelet summary api
@@ -547,7 +556,7 @@ module Fluent
547
556
  log.error "ExMultiJson.load(response.body) expected 2xx from summary API, but got #{response.code}. Response body = #{response.body}"
548
557
  end
549
558
  rescue StandardError => e
550
- log.error "Failed to scrape metrics, error=#{$ERROR_INFO}, #{e.inspect}"
559
+ log.error "Failed to scrape resource usage metrics, error=#{$ERROR_INFO}, #{e.inspect}"
551
560
  log.error_backtrace
552
561
  end
553
562
 
@@ -560,13 +569,13 @@ module Fluent
560
569
  begin
561
570
  @client.discover unless @client.discovered
562
571
  @client.rest_client["/nodes/#{node_name}:#{@kubelet_port}/proxy/stats/summary"].tap do |endpoint|
563
- log.info("Use URL #{endpoint.url} for scraping resource usage metrics")
572
+ log.debug("Use URL #{endpoint.url} for scraping resource usage metrics")
564
573
  end
565
574
  end
566
575
 
567
576
  node_response = JSON.parse(node_rest_client.get(@client.headers))
568
577
  Array(node_response['pods']).each do |pod_json|
569
- pod_cpu_usage = pod_json['cpu']['usageNanoCores']
578
+ pod_cpu_usage = pod_json['cpu']['usageNanoCores']/ 1_000_000
570
579
  pod_memory_usage = pod_json['memory']['usageBytes']
571
580
  pod_namespace = pod_json['podRef']['namespace']
572
581
  pod_usage = ResourceUsageMetricsUnit.new
@@ -37,33 +37,16 @@ module PluginTestHelper
37
37
  k8s_url + '/v1/nodes/generics-aws-node-three:10255/proxy/stats/summary'
38
38
  end
39
39
 
40
- def stub_api_port_10250
41
- WebMock.stub_request(:get, 'https://node.fakedestination.com:10250/api')
42
- .with(
43
- headers: {
44
- 'Accept' => '*/*',
45
- 'Accept-Encoding' => 'gzip, deflate',
46
- 'Host' => 'node.fakedestination.com:10250'
47
- }
48
- )
49
- .to_return(status: 200,
50
- body: File.open(File.expand_path('../v1.json', __FILE__)),
51
- headers: {})
52
- end
53
-
54
40
  def stub_api_port_10255
55
41
  WebMock.stub_request(:get,
56
42
  'https://node.fakedestination.com:10255/api')
57
43
  .with(
58
44
  headers: {
59
- 'Accept' => '*/*',
60
- 'Accept-Encoding' => 'gzip, deflate',
61
45
  'Host' => 'node.fakedestination.com:10255'
62
46
  }
63
47
  )
64
48
  .to_return(status: 200,
65
- body: File.open(File.expand_path('../v1.json', __FILE__)),
66
- headers: {})
49
+ body: File.open(File.expand_path('../v1.json', __FILE__)))
67
50
  end
68
51
 
69
52
  def stub_api_v1
@@ -71,29 +54,27 @@ module PluginTestHelper
71
54
  'https://node.fakedestination.com:10255/api/v1')
72
55
  .with(
73
56
  headers: {
74
- 'Accept' => '*/*',
75
- 'Accept-Encoding' => 'gzip, deflate',
76
57
  'Host' => 'node.fakedestination.com:10255'
77
58
  }
78
59
  )
79
60
  .to_return(status: 200,
80
- body: File.open(File.expand_path('../v1.json', __FILE__)),
81
- headers: {})
82
- end
61
+ body: File.open(File.expand_path('../v1.json', __FILE__)))
62
+ end
63
+
64
+ def stub_api_pods(timeout=false)
65
+ get_pods = WebMock.stub_request(:get,
66
+ 'https://node.fakedestination.com:10255/api/v1/pods')
67
+ .with(
68
+ headers: {
69
+ 'Host' => 'node.fakedestination.com:10255'
70
+ }
71
+ )
72
+ if timeout
73
+ get_pods = get_pods.to_timeout.then
74
+ end
83
75
 
84
- def stub_api_pods
85
- WebMock.stub_request(:get,
86
- 'https://node.fakedestination.com:10255/api/v1/pods')
87
- .with(
88
- headers: {
89
- 'Accept' => '*/*',
90
- 'Accept-Encoding' => 'gzip, deflate',
91
- 'Host' => 'node.fakedestination.com:10255'
92
- }
93
- )
94
- .to_return(status: 200,
95
- body: File.open(File.expand_path('../pods.json', __FILE__)),
96
- headers: {})
76
+ get_pods.to_return(status: 200,
77
+ body: File.open(File.expand_path('../pods.json', __FILE__)))
97
78
  end
98
79
 
99
80
  def stub_api_node_1
@@ -101,29 +82,28 @@ module PluginTestHelper
101
82
  'https://node.fakedestination.com:10255/api/v1/nodes/generics-aws-node-one:10255/proxy/stats/summary')
102
83
  .with(
103
84
  headers: {
104
- 'Accept' => '*/*',
105
- 'Accept-Encoding' => 'gzip, deflate',
106
85
  'Host' => 'node.fakedestination.com:10255'
107
86
  }
108
87
  )
109
88
  .to_return(status: 200,
110
- body: File.open(File.expand_path('../node1.json', __FILE__)),
111
- headers: {})
89
+ body: File.open(File.expand_path('../node1.json', __FILE__)))
112
90
  end
113
91
 
114
- def stub_api_node_2
115
- WebMock.stub_request(:get,
116
- 'https://node.fakedestination.com:10255/api/v1/nodes/generics-aws-node-two:10255/proxy/stats/summary')
92
+ def stub_api_node_2(timeout=false)
93
+ get_node_summary = WebMock.stub_request(:get,
94
+ 'https://node.fakedestination.com:10255/api/v1/nodes/generics-aws-node-two:10255/proxy/stats/summary')
117
95
  .with(
118
96
  headers: {
119
- 'Accept' => '*/*',
120
- 'Accept-Encoding' => 'gzip, deflate',
121
97
  'Host' => 'node.fakedestination.com:10255'
122
98
  }
123
99
  )
124
- .to_return(status: 200,
125
- body: File.open(File.expand_path('../node2.json', __FILE__)),
126
- headers: {})
100
+
101
+ if timeout
102
+ get_node_summary = get_node_summary.to_timeout
103
+ end
104
+
105
+ get_node_summary.to_return(status: 200,
106
+ body: File.open(File.expand_path('../node2.json', __FILE__)))
127
107
  end
128
108
 
129
109
  def stub_api_node_3
@@ -131,40 +111,45 @@ module PluginTestHelper
131
111
  'https://node.fakedestination.com:10255/api/v1/nodes/generics-aws-node-three:10255/proxy/stats/summary')
132
112
  .with(
133
113
  headers: {
134
- 'Accept' => '*/*',
135
- 'Accept-Encoding' => 'gzip, deflate',
136
114
  'Host' => 'node.fakedestination.com:10255'
137
115
  }
138
116
  )
139
117
  .to_return(status: 200,
140
- body: File.open(File.expand_path('../node3.json', __FILE__)),
141
- headers: {})
118
+ body: File.open(File.expand_path('../node3.json', __FILE__)))
142
119
  end
143
120
 
144
- def stub_api_nodes
145
- WebMock.stub_request(:get,
146
- 'https://node.fakedestination.com:10255/api/v1/nodes')
147
- .with(
148
- headers: {
149
- 'Accept' => '*/*',
150
- 'Accept-Encoding' => 'gzip, deflate',
151
- 'Host' => 'node.fakedestination.com:10255'
152
- }
153
- )
154
- .to_return(status: 200,
155
- body: File.open(File.expand_path('../nodes.json', __FILE__)),
156
- headers: {})
121
+ def stub_api_nodes(timeout=false)
122
+ get_nodes = WebMock.stub_request(:get, 'https://node.fakedestination.com:10255/api/v1/nodes')
123
+ .with(
124
+ headers: {
125
+ 'Host' => 'node.fakedestination.com:10255'
126
+ }
127
+ )
128
+
129
+ if timeout
130
+ get_nodes = get_nodes.to_timeout.times(2) # Nodes endpoint is called from two timers so must fail in both cases
131
+ end
132
+
133
+ get_nodes.to_return(status: 200,
134
+ body: File.open(File.expand_path('../nodes.json', __FILE__)))
157
135
  end
158
136
 
159
- def stub_k8s_requests
160
- stub_api_port_10250
137
+ def stub_k8s_init_requests
138
+ WebMock.reset!
139
+
140
+ stub_api_port_10255
141
+ end
142
+
143
+ def stub_k8s_requests(nodes_timeout: false, node_summary_timeout: false, pods_timeout: false)
144
+ WebMock.reset!
145
+
161
146
  stub_api_port_10255
162
147
  stub_api_v1
163
- stub_api_pods
164
- stub_api_nodes
148
+ stub_api_pods(pods_timeout)
149
+ stub_api_nodes(nodes_timeout)
165
150
  stub_api_node_1
151
+ stub_api_node_2(node_summary_timeout)
166
152
  stub_api_node_3
167
- stub_api_node_2
168
153
  end
169
154
 
170
155
  def get_parsed_file(file_name)
@@ -5,10 +5,6 @@ class KubernetesMetricsAggInputTest < Test::Unit::TestCase
5
5
  include Fluent::Test::Helpers
6
6
  include PluginTestHelper
7
7
 
8
- @driver = nil
9
- @driver_test = nil
10
- @@hash_map_test = {}
11
-
12
8
  ZERO_CONFIG = %([
13
9
  ]).freeze
14
10
 
@@ -34,20 +30,22 @@ class KubernetesMetricsAggInputTest < Test::Unit::TestCase
34
30
  METRIC_TEST_CONFIG = %([
35
31
  kubernetes_url https://node.fakedestination.com
36
32
  kubelet_port 10255
33
+ interval 5s
34
+ tag kube.*
35
+ ]).freeze
36
+
37
+ TIMEOUT_TEST_CONFIG = %([
38
+ kubernetes_url https://node.fakedestination.com
39
+ kubelet_port 10255
40
+ interval 5s
37
41
  tag kube.*
38
42
  ]).freeze
39
43
 
40
44
  setup do
41
45
  Fluent::Test.setup
46
+
42
47
  ENV['KUBERNETES_SERVICE_HOST'] = "node.fakedestination.com"
43
48
  ENV['KUBERNETES_SERVICE_PORT'] = "10255"
44
- stub_k8s_requests
45
- @driver = create_driver(METRIC_TEST_CONFIG)
46
- @driver.run timeout: 20, expect_emits: 200, shutdown: false
47
-
48
- @driver.events.each do |tag, time, record|
49
- @@hash_map_test[tag] = tag, time, record
50
- end
51
49
  end
52
50
 
53
51
  def create_driver(conf = BASIC_CONFIG)
@@ -60,6 +58,8 @@ class KubernetesMetricsAggInputTest < Test::Unit::TestCase
60
58
 
61
59
  sub_test_case 'default parameter configuration' do
62
60
  test 'test default params' do
61
+ stub_k8s_init_requests
62
+
63
63
  d = create_driver(ZERO_CONFIG)
64
64
  assert_equal 10_250, d.instance.kubelet_port
65
65
  assert_equal 'kubernetes.metrics.*', d.instance.tag
@@ -78,141 +78,174 @@ class KubernetesMetricsAggInputTest < Test::Unit::TestCase
78
78
 
79
79
  sub_test_case 'modify parameter changes' do
80
80
  test 'test kubelet_port and supplied kubernetes URL parameters' do
81
+ stub_k8s_init_requests
82
+
81
83
  d = create_driver(ADVANCED_CONFIG_NO_CERTS)
82
84
  assert_equal 'https://node.fakedestination.com', d.instance.kubernetes_url
83
85
  assert_equal 10_255, d.instance.kubelet_port
84
86
  end
85
87
 
86
88
  test 'test tag and interval parameters' do
89
+ stub_k8s_init_requests
90
+
87
91
  d = create_driver(ADVANCED_CONFIG_NO_CERTS)
88
92
  assert_equal 'test.tag.check', d.instance.tag
89
93
  assert_equal 120, d.instance.interval
90
94
  end
91
95
 
92
96
  test 'test insecure_ssl and cluster_name parameters ' do
97
+ stub_k8s_init_requests
98
+
93
99
  d = create_driver(ADVANCED_CONFIG_NO_CERTS)
94
100
  assert_true d.instance.insecure_ssl
95
101
  assert_equal 'awesome_cluster', d.instance.cluster_name
96
102
  end
97
103
  end
98
104
 
99
- sub_test_case 'Test metrics exist, limits_request_scraper - limits' do
100
- test 'Testing kube.container.memory.limit' do
101
- assert_true @@hash_map_test.key?('kube.container.memory.limit')
102
- end
103
-
104
- test 'Testing kube.namespace.cpu.limit' do
105
- assert_true @@hash_map_test.key?('kube.namespace.cpu.limit')
106
- end
107
-
108
- test 'Testing kube.namespace.memory.limit ' do
109
- assert_true @@hash_map_test.key?('kube.namespace.memory.limit')
110
- end
111
-
112
- test 'Testing kube.container.cpu.limit' do
113
- assert_true @@hash_map_test.key?('kube.container.cpu.limit')
114
- end
115
-
116
- test 'Testing kube.pod.cpu.limit' do
117
- assert_true @@hash_map_test.key?('kube.pod.cpu.limit')
118
- end
119
-
120
- test 'Testing kube.cluster.memory.limit ' do
121
- assert_true @@hash_map_test.key?('kube.cluster.memory.limit')
122
- end
123
-
124
- test 'Testing kube.pod.memory.limit ' do
125
- assert_true @@hash_map_test.key?('kube.pod.memory.limit')
126
- end
127
-
128
- test 'Testing kube.cluster.cpu.limit' do
129
- assert_true @@hash_map_test.key?('kube.cluster.cpu.limit')
105
+ sub_test_case 'Test metrics exist' do
106
+ test 'Testing all expected metrics are emitted' do
107
+ stub_k8s_requests
108
+
109
+ hash_map_test = {}
110
+
111
+ d = create_driver(METRIC_TEST_CONFIG)
112
+ d.run timeout: 12, expect_emits: 200, shutdown: false
113
+
114
+ d.events.each do |tag, time, record|
115
+ hash_map_test[tag] = tag, time, record
116
+ end
117
+
118
+ # Test metrics exist, limits_request_scraper - limits
119
+ assert_true hash_map_test.key?('kube.namespace.cpu.limit')
120
+ assert_true hash_map_test.key?('kube.namespace.memory.limit')
121
+ assert_true hash_map_test.key?('kube.container.cpu.limit')
122
+ assert_true hash_map_test.key?('kube.pod.cpu.limit')
123
+ assert_true hash_map_test.key?('kube.cluster.memory.limit')
124
+ assert_true hash_map_test.key?('kube.pod.memory.limit')
125
+ assert_true hash_map_test.key?('kube.cluster.cpu.limit')
126
+
127
+ # Test metrics exist, limits_request_scraper - request
128
+ assert_true hash_map_test.key?('kube.cluster.memory.request')
129
+ assert_true hash_map_test.key?('kube.container.memory.request')
130
+ assert_true hash_map_test.key?('kube.pod.memory.request')
131
+ assert_true hash_map_test.key?('kube.namespace.memory.request')
132
+ assert_true hash_map_test.key?('kube.container.cpu.request')
133
+ assert_true hash_map_test.key?('kube.namespace.cpu.request')
134
+ assert_true hash_map_test.key?('kube.pod.cpu.request')
135
+ assert_true hash_map_test.key?('kube.cluster.cpu.request')
136
+
137
+ # Test metrics exist, node_scraper/resource_usage_scraper 1
138
+ assert_true hash_map_test.key?('kube.node.cpu.capacity')
139
+ assert_true hash_map_test.key?('kube.node.memory.capacity')
140
+ assert_true hash_map_test.key?('kube.node.memory.allocatable')
141
+ assert_true hash_map_test.key?('kube.node.cpu.utilization')
142
+ assert_true hash_map_test.key?('kube.node.memory.reservation')
143
+ assert_true hash_map_test.key?('kube.node.memory.utilization')
144
+
145
+ # Test metrics exist, node_scraper/resource_usage_scraper 2
146
+ assert_true hash_map_test.key?('kube.namespace.memory.usage')
147
+ assert_true hash_map_test.key?('kube.cluster.memory.usage')
148
+ assert_true hash_map_test.key?('kube.namespace.cpu.usage')
149
+ assert_true hash_map_test.key?('kube.node.cpu.allocatable')
150
+ assert_true hash_map_test.key?('kube.node.cpu.reservation')
151
+ assert_true hash_map_test.key?('kube.cluster.cpu.usage')
152
+
153
+ d.instance_shutdown
130
154
  end
131
155
  end
132
156
 
133
- sub_test_case 'Test metrics exist, limits_request_scraper - request' do
134
- test 'Testing kube.cluster.memory.request ' do
135
- assert_true @@hash_map_test.key?('kube.cluster.memory.request')
136
- end
157
+ sub_test_case 'Test handles request timeouts' do
137
158
 
138
- test 'Testing kube.container.memory.request' do
139
- assert_true @@hash_map_test.key?('kube.container.memory.request')
140
- end
159
+ test 'Testing event count with nodes call timeout' do
160
+ stub_k8s_requests(nodes_timeout: true)
141
161
 
142
- test 'Testing kube.pod.memory.request' do
143
- assert_true @@hash_map_test.key?('kube.pod.memory.request')
144
- end
162
+ namespace_event_count = 0
163
+ pod_event_count = 0
164
+ node_event_count = 0
145
165
 
146
- test 'Testing kube.namespace.memory.request ' do
147
- assert_true @@hash_map_test.key?('kube.namespace.memory.request')
148
- end
166
+ d = create_driver(TIMEOUT_TEST_CONFIG)
167
+ # Should run for two intervals, the first call to node 1 which has the only 'default' namespace pod should timeout the first time
168
+ d.run timeout: 12, expect_emits: 500, shutdown: false
149
169
 
150
- test 'Testing kube.container.cpu.request' do
151
- assert_true @@hash_map_test.key?('kube.container.cpu.request')
152
- end
170
+ d.events.each do |tag, _time, record|
171
+ # Limit to one events that should be emitted once per interval
172
+ if tag == 'kube.pod.cpu.limit' && record['name'] == 'new-metrics-test-final-splunk-kubernetes-metrics-fgszl'
173
+ pod_event_count += 1
174
+ end
175
+ if tag == 'kube.namespace.cpu.usage' && record['name'] == 'kube-system'
176
+ namespace_event_count += 1
177
+ end
178
+ if tag == 'kube.node.cpu.capacity' && record['node'] == 'generics-aws-node-one'
179
+ node_event_count += 1
180
+ end
181
+ end
153
182
 
154
- test 'Testing kube.namespace.cpu.request' do
155
- assert_true @@hash_map_test.key?('kube.namespace.cpu.request')
156
- end
183
+ # 2 intervals - first call times out but timer continues emitting successfully next interval
184
+ assert_equal 1, node_event_count, 'Number of node events emitted was wrong'
185
+ # 2 intervals - first call times out but timer continues emitting successfully next interval
186
+ assert_equal 1, namespace_event_count, 'Number of namespace events emitted was wrong'
187
+ # 2 intervals - not timeouts
188
+ assert_equal 2, pod_event_count, 'Number of pod events emitted was wrong'
157
189
 
158
- test 'Testing kube.pod.cpu.request' do
159
- assert_true @@hash_map_test.key?('kube.pod.cpu.request')
190
+ d.instance_shutdown
160
191
  end
161
192
 
162
- test 'Testing kube.cluster.cpu.request' do
163
- assert_true @@hash_map_test.key?('kube.cluster.cpu.request')
164
- end
165
- end
193
+ test 'Testing event count with pods call timeout' do
194
+ stub_k8s_requests(pods_timeout: true)
166
195
 
167
- sub_test_case 'Test metrics exist, node_scraper/resource_usage_scraper 1' do
168
- test 'Testing kube.node.cpu.capacity' do
169
- assert_true @@hash_map_test.key?('kube.node.cpu.capacity')
170
- end
196
+ pod_event_count = 0
197
+ node_event_count = 0
171
198
 
172
- test 'Testing kube.node.memory.capacity ' do
173
- assert_true @@hash_map_test.key?('kube.node.memory.capacity')
174
- end
199
+ d = create_driver(TIMEOUT_TEST_CONFIG)
200
+ # Should run for two intervals, the first call to node 1 which has the only 'default' namespace pod should timeout the first time
201
+ d.run timeout: 12, expect_emits: 500, shutdown: false
175
202
 
176
- test 'Testing kube.node.memory.allocatable' do
177
- assert_true @@hash_map_test.key?('kube.node.memory.allocatable')
178
- end
203
+ d.events.each do |tag, _time, record|
204
+ # Limit to one events that should be emitted once per interval
205
+ if tag == 'kube.pod.cpu.limit' && record['name'] == 'new-metrics-test-final-splunk-kubernetes-metrics-fgszl'
206
+ pod_event_count += 1
207
+ end
179
208
 
180
- test 'Testing kube.node.cpu.utilization ' do
181
- assert_true @@hash_map_test.key?('kube.node.cpu.utilization')
182
- end
209
+ if tag == 'kube.node.cpu.utilization' && record['node'] == 'generics-aws-node-one'
210
+ node_event_count += 1
211
+ end
212
+ end
183
213
 
184
- test 'Testing kube.node.memory.reservation' do
185
- assert_true @@hash_map_test.key?('kube.node.memory.reservation')
186
- end
214
+ # 2 intervals - first call times out but timer continues emitting successfully next interval
215
+ assert_equal 1, pod_event_count, 'Number of pod events emitted was wrong'
216
+ # 2 intervals - not timeouts
217
+ assert_equal 2, node_event_count, 'Number of namespace events emitted was wrong'
187
218
 
188
- test 'Testing kube.node.memory.utilization' do
189
- assert_true @@hash_map_test.key?('kube.node.memory.utilization')
219
+ d.instance_shutdown
190
220
  end
191
- end
192
221
 
193
- sub_test_case 'Test metrics exist, node_scraper/resource_usage_scraper 2' do
194
- test 'Testing kube.namespace.memory.usage ' do
195
- assert_true @@hash_map_test.key?('kube.namespace.memory.usage')
196
- end
222
+ test 'Testing event count with node summary call timeout' do
223
+ stub_k8s_requests(node_summary_timeout: true)
197
224
 
198
- test 'Testing kube.cluster.memory.usage' do
199
- assert_true @@hash_map_test.key?('kube.cluster.memory.usage')
200
- end
225
+ namespace_event_count = 0
226
+ pod_event_count = 0
201
227
 
202
- test 'Testing kube.namespace.cpu.usage' do
203
- assert_true @@hash_map_test.key?('kube.namespace.cpu.usage')
204
- end
228
+ d = create_driver(TIMEOUT_TEST_CONFIG)
229
+ # Should run for two intervals, the first call to node 1 which has the only 'default' namespace pod should timeout the first time
230
+ d.run timeout: 12, expect_emits: 500, shutdown: false
205
231
 
206
- test 'Testing kube.node.cpu.allocatable ' do
207
- assert_true @@hash_map_test.key?('kube.node.cpu.allocatable')
208
- end
232
+ d.events.each do |tag, _time, record|
233
+ # Limit to one events that should be emitted once per interval
234
+ if tag == 'kube.namespace.cpu.usage' && record['name'] == 'kube-system'
235
+ namespace_event_count += 1
236
+ end
237
+ if tag == 'kube.pod.cpu.limit' && record['name'] == 'new-metrics-test-final-splunk-kubernetes-metrics-fgszl'
238
+ pod_event_count += 1
239
+ end
240
+ end
209
241
 
210
- test 'Testing kube.node.cpu.reservation ' do
211
- assert_true @@hash_map_test.key?('kube.node.cpu.reservation')
212
- end
242
+ # 2 intervals - first call times out but timer continues emitting successfully next interval
243
+ assert_equal 1, namespace_event_count, 'Number of namespace events emitted was wrong'
244
+ # 2 intervals - not timeouts
245
+ assert_equal 2, pod_event_count, 'Number of pod events emitted was wrong'
213
246
 
214
- test 'Testing kube.cluster.cpu.usage' do
215
- assert_true @@hash_map_test.key?('kube.cluster.cpu.usage')
247
+ d.instance_shutdown
216
248
  end
249
+
217
250
  end
218
251
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-k8s-metrics-agg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Splunk Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-07 00:00:00.000000000 Z
11
+ date: 2019-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -147,10 +147,18 @@ files:
147
147
  - ".circleci/build_and_push.sh"
148
148
  - ".circleci/build_and_push_to_dockerhub.sh"
149
149
  - ".circleci/build_and_push_to_github_release.sh"
150
+ - ".circleci/check_version_trigger_release.sh"
150
151
  - ".circleci/config.yml"
152
+ - ".circleci/gem_credentials"
151
153
  - ".circleci/install_dep.sh"
152
154
  - ".circleci/push_gem.sh"
155
+ - ".circleci/push_gem_to_rubygems.sh"
156
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
157
+ - ".github/ISSUE_TEMPLATE/enhancement_request.md"
158
+ - ".github/ISSUE_TEMPLATE/failing_test.md"
159
+ - ".github/PULL_REQUEST_TEMPLATE.md"
153
160
  - ".gitignore"
161
+ - CLA.md
154
162
  - CONTRIBUTING.md
155
163
  - CONTRIBUTORS.md
156
164
  - Gemfile
@@ -161,6 +169,7 @@ files:
161
169
  - VERSION
162
170
  - docker/CONTRIBUTING.md
163
171
  - docker/Dockerfile
172
+ - docker/FLUENTD_HEC_GEM_VERSION
164
173
  - docker/LICENSE
165
174
  - docker/README.md
166
175
  - docker/entrypoint.sh
@@ -194,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
203
  - !ruby/object:Gem::Version
195
204
  version: '0'
196
205
  requirements: []
197
- rubygems_version: 3.0.1
206
+ rubygems_version: 3.0.3
198
207
  signing_key:
199
208
  specification_version: 4
200
209
  summary: A fluentd input plugin that collects kubernetes cluster metrics.