378 Commits

Author SHA1 Message Date
skamboj
8d63d44fe2 Merge pull request #162 from skamboj/update-golang
Some checks failed
Helm Publish / helm_publish (push) Failing after 9s
CI / build (push) Successful in 5m56s
Update golang to 1.25 and update all dependencies
2026-01-28 21:12:18 -05:00
Sachin Kamboj
4392ae9f09 Update chart versions as well
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-28 20:37:47 -05:00
Sachin Kamboj
cb9c8ae248 Update goldpinger version
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-28 20:28:04 -05:00
Sachin Kamboj
b54e3feea6 Update dependencies
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-28 20:27:05 -05:00
Sachin Kamboj
0dfa55880c Update to golang 1.25
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-28 20:26:41 -05:00
skamboj
a93c8040a1 Merge pull request #161 from skamboj/update-workflows
All checks were successful
Helm Publish / helm_publish (push) Successful in 52s
CI / build (push) Successful in 6m19s
Update versions of the various actions
2026-01-28 20:11:48 -05:00
Sachin Kamboj
3ce341330b Attempt to fix the bake step
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-28 16:30:22 -05:00
Sachin Kamboj
a85572f799 More updates to the versions
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-28 08:50:01 -05:00
Sachin Kamboj
f29301ed41 Merge remote-tracking branch 'upstream/master' into update-workflows
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-28 08:37:45 -05:00
Sachin Kamboj
7379914781 Update versions of the various actions
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2026-01-27 21:35:26 -05:00
skamboj
52e86c25f5 Merge pull request #152 from Leundai/add-deepwiki
Some checks failed
Helm Publish / helm_publish (push) Successful in 55s
CI / build (push) Failing after 47m53s
feat: Add deepwiki badge
2025-10-04 11:21:14 -04:00
leundai
ba779f50e7 feat: Add deepwiki badge
Small enhancement to improve quick onboarding for the curious

Signed-off-by: leundai <leogalindofrias@gmail.com>
2025-07-12 14:48:02 -04:00
skamboj
02065cf812 Merge pull request #148 from scoof/improvement-metricrelabelings
improvement: support relabelings in ServiceMonitor
2024-11-11 09:30:59 -05:00
skamboj
98bee8cc4e Merge branch 'master' into improvement-metricrelabelings 2024-11-11 09:17:09 -05:00
Sachin Kamboj
41680b856a Up the app version
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-11-11 09:16:18 -05:00
Sachin Kamboj
8db3d2f2de Fix typo
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-11-11 09:14:07 -05:00
skamboj
d1c60472df Merge pull request #147 from avnes/fix/typo-in-chart-description
Fix small typo i Chart description. Change troublshoot to troubleshoot
2024-11-11 09:05:44 -05:00
skamboj
65cf0cab7c Merge branch 'master' into fix/typo-in-chart-description 2024-11-11 09:04:52 -05:00
skamboj
438c5d0739 Merge branch 'master' into improvement-metricrelabelings 2024-11-11 09:02:41 -05:00
skamboj
259ab8f22a Merge pull request #150 from laverya/build-with-go-1.23
build with go 1.23
2024-11-11 09:02:27 -05:00
skamboj
31a851fbb0 Merge branch 'master' into fix/typo-in-chart-description 2024-11-11 08:56:16 -05:00
skamboj
6401b59cb8 Merge branch 'master' into build-with-go-1.23 2024-11-11 08:54:55 -05:00
skamboj
1577ae84b8 Merge pull request #149 from laverya/update-x-image-for-cve-2024-24792
update golang.org/x/image to resolve cve-2024-24792
2024-11-11 08:54:26 -05:00
Andrew Lavery
e1b06a5236 build with go 1.23
Signed-off-by: Andrew Lavery <laverya@umich.edu>
2024-10-11 17:07:24 +02:00
Andrew Lavery
2f77117b89 update golang.org/x/image to resolve cve-2024-24792
Signed-off-by: Andrew Lavery <laverya@umich.edu>
2024-10-11 17:00:52 +02:00
Andreas Plesner
d8819d6d6d Fix datatype
Signed-off-by: Andreas Plesner <apj@mutt.dk>
2024-09-09 20:40:26 +02:00
Sachin Kamboj
f7ab34e462 Update the chart version
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-09-09 13:38:55 -04:00
Andreas Plesner
b07803d8c6 fix: move metricRelabelings to correct section
Signed-off-by: Andreas Plesner <apj@mutt.dk>
2024-08-26 12:24:08 +02:00
Andreas Plesner
876b3f4068 improvement: support relabelings in ServiceMonitor
Signed-Off-By: Andreas Plesner <apj@mutt.dk>
2024-08-12 09:13:29 +02:00
Audun Nes
2addb57cb4 iFix small typo i Chart description. Change troublshoot to troubleshoot
Signed-off-by: Audun Nes <audun.nes@gmail.com>
2024-06-13 13:12:47 +02:00
skamboj
36b0aed3b1 Merge pull request #137 from DerekTBrown/add-helm-chart
feat: add helm chart
2024-05-14 10:46:43 -04:00
Sachin Kamboj
a909e03de9 The appVersion should not have a v
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-05-14 10:33:36 -04:00
Sachin Kamboj
b8035264ed Update the publishing workflow
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-05-14 10:16:45 -04:00
Sachin Kamboj
6a3794f3d6 Secure by default - set the security context and pod security context
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-05-14 10:05:07 -04:00
Sachin Kamboj
f514bac57c Remove kubernetes version to use the default image
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-05-14 10:01:00 -04:00
Sachin Kamboj
a1a481ffe9 Update to kube 1.30 for the kind cluster as well
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-05-14 08:42:55 -04:00
Sachin Kamboj
aed183926e Update the versions to the latest
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-05-14 08:36:28 -04:00
skamboj
dbd1f5f295 Merge branch 'master' into add-helm-chart 2024-05-13 15:41:59 -04:00
skamboj
a8f1a76691 Merge pull request #143 from pettersolberg88/master
Upgrade golang to 1.22 and update dependencies
2024-05-13 14:40:08 -04:00
Sachin Kamboj
f4aa170407 Update the version
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-05-13 14:32:23 -04:00
Petter Solberg
c740646bc2 Upgrade golang to 1.22 and update dependencies
Signed-off-by: Petter Solberg <pettersolberg88@gmail.com>
2024-04-16 21:27:40 +02:00
skamboj
41af078647 Merge pull request #142 from abctaylor/abctaylor-serviceaccount
Add default namespace `default` to ServiceAccount definition in example yaml
2024-04-12 09:21:17 -04:00
ABC Taylor
c70d8a6a8a Merge branch 'master' into abctaylor-serviceaccount 2024-04-11 08:41:04 +01:00
ABC Taylor
562df92c3a Add default namespace default to ServiceAccount definition, to catch case where users find-replace default with another namespace but don't change it for the ServiceAccount
Signed-Off-By: ABC Taylor <abc@abctaylor.com>
2024-04-11 08:37:09 +01:00
skamboj
e22842fbfb Merge pull request #135 from j4ckstraw/use-protobuf
use protobuf and add resourceVersion in listOption
2024-04-08 15:49:26 -04:00
Sachin Kamboj
507a63d8bc Increment the version
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2024-04-08 15:41:55 -04:00
skamboj
9f6de28994 Merge branch 'master' into use-protobuf 2024-04-08 10:45:38 -04:00
skamboj
0b96e45e05 Merge pull request #140 from cloudeteer/feature/windows-build
Provide Windows builds and refactor CI
2023-11-08 20:47:59 -05:00
Jan-Otto Kröpke
fc076f9d71 Use full imags base name as ARG
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
2023-11-03 18:25:42 +01:00
Chris Jedro
166f65fe4d fix dockerfile
Signed-off-by: Chris Jedro <cj@cloudeteer.de>
2023-11-03 11:21:14 +01:00
Jan-Otto Kröpke
e5ca7ec03f Provide Windows builds and refactor CI
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
2023-11-02 20:51:16 +01:00
skamboj
640e4430cf Merge pull request #139 from skamboj/update-golang
Update golang
2023-10-22 19:52:34 -04:00
Sachin Kamboj
2a684a8aef OOPS - accidentally left out the target on doing the update
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2023-10-22 22:13:44 +00:00
Sachin Kamboj
1d9a533433 Update to golang 1.21 in the github workflow as well
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2023-10-22 22:07:16 +00:00
Sachin Kamboj
e59a14d574 Update the builder image and use distroless for the final image
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2023-10-22 22:04:07 +00:00
Sachin Kamboj
9b0b5449d5 :trollface: seriously? how was this broken
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2023-10-22 17:36:32 +00:00
Sachin Kamboj
cd3680af09 Update go.sum
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2023-10-22 17:35:57 +00:00
Sachin Kamboj
84aa0c443d Update all the dependencies...
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2023-10-22 17:35:36 +00:00
Derek Brown
4af6666853 feat: add helm chart
Signed-off-by: Derek Brown <derektbrown@users.noreply.github.com>
2023-09-25 15:51:14 -07:00
skamboj
bd541d4a11 Merge pull request #129 from wedaly/rbac-authorization-version
Remove deprecated rbac.authorization.k8s.io/v1beta1
2023-08-21 21:21:32 -04:00
j4ckstraw
acac9dee8b use protobuf and add resourceVersion in listOption
1. communicate to kube-apiserver with protobuf
2. listOption add resourceVersion=0. without resourceversion,
list will force kube-apiserver retrieve data from etcd.

In a 100+ nodes, 7500+ pods kubernetes cluster, this patch make
kube-apiserver cpu utils reduce 5-10%.

Signed-off-by: j4ckstraw <j4ckstraw@foxmail.com>
2023-06-17 18:42:37 +08:00
Will Daly
1f3ad0acc9 Remove deprecated rbac.authorization.k8s.io/v1beta1
This commit updates the README and examples to use
rbac.authorization.k8s.io/v1 instead, which has been available
since K8s 1.8

rbac.authorization.k8s.io/v1beta1 was deprecated in K8s 1.17
and removed in K8s 1.22.

Reference:
https://kubernetes.io/docs/reference/using-api/deprecation-guide/#rbac-resources-v122

Signed-off-by: Will Daly <widaly@microsoft.com>
2023-05-03 11:29:42 -07:00
Mikolaj Pawlikowski
95363554e4 Merge pull request #124 from maxime1907/feat-config-zap
feat: support advanced zap configuration
2022-10-25 20:37:40 +01:00
Maxime Leroy
a913318ae3 feat: support advanced zap configuration
Signed-off-by: Maxime Leroy <19607336+maxime1907@users.noreply.github.com>
2022-10-25 12:30:35 +02:00
Mikolaj Pawlikowski
2f54105404 Merge pull request #121 from kitfoman/add-missing-dependency
[Bug Fix] add missing dependency
2022-08-29 16:55:12 +01:00
kitfoman
f6dbd2632b add missing dependency
Signed-off-by: kitfoman <thaddeusgetachew@gmail.com>
2022-08-29 10:41:39 -04:00
Mikolaj Pawlikowski
8ad0802439 Merge pull request #115 from kitfoman/add-external-probes
Extend DNS resolver to include TCP and HTTP checks for external targets
2022-08-26 21:05:02 +01:00
Tadewos Getachew
7cd571d15f Merge branch 'master' into add-external-probes 2022-05-08 22:06:35 -04:00
tgetachew
14ea96999a add external probes
Signed-off-by: kitfoman <thaddeusgetachew@gmail.com>

make timeout flags backwards compatible

Signed-off-by: kitfoman <thaddeusgetachew@gmail.com>
2022-05-08 22:02:09 -04:00
Tyler Lloyd
05ab610f10 cleanup IPv6 references
only check node IPs when determining hostIP

IP_VERSIONS not IP_FAMILIES

Signed-off-by: Tyler Lloyd <tyler.lloyd@microsoft.com>
2022-05-08 22:02:03 -04:00
Mikolaj Pawlikowski
1a9ae3a9ba Merge pull request #116 from tyler-lloyd/cleanup-ipv6
Cleanup ipv6
2022-04-15 14:09:45 +01:00
Mikolaj Pawlikowski
d976605bc6 Merge branch 'master' into cleanup-ipv6 2022-04-15 13:37:54 +01:00
Mikolaj Pawlikowski
5cc9bd55ad Merge pull request #119 from XIAOMI-CloudNative/feat/show-nodename
Fix pinger be removed by not found.
2022-04-15 13:36:46 +01:00
wanglijie6
72832bcbc4 Fix pinger be removed by not found.
heatmap will be broken in every refeshPeriod,
I found pinger is be deleted because of exists check faild.

updatePingers will check if a pod still exist or a new one,
and update pingers in every refreshPeriod.

the function exists failed to check pod exist, so fix it.

Signed-off-by: wanglijie6 <wanglijie6@xiaomi.com>
2022-04-15 19:14:53 +08:00
Mikolaj Pawlikowski
a461b0ffd5 Merge pull request #118 from XIAOMI-CloudNative/feat/show-nodename
Display hostName other than podName
2022-04-14 17:15:41 +01:00
wanglijie6
7609a3ab3f Add --display-nodename option to control UI display
Add GoldpingerConfig.DisplayNodeName to control UI display, default is
`false`, which means to display podName

Signed-off-by: wanglijie6 <wanglijie6@xiaomi.com>
2022-04-13 10:54:59 +08:00
wanglijie6
588c1a0173 Show hostName other than podName
Signed-off-by: wanglijie6 <wanglijie6@xiaomi.com>
2022-04-12 20:06:48 +08:00
Tyler Lloyd
ef300d5ca2 cleanup IPv6 references
only check node IPs when determining hostIP

IP_VERSIONS not IP_FAMILIES

Signed-off-by: Tyler Lloyd <tyler.lloyd@microsoft.com>
2022-03-30 17:42:22 +00:00
Mikolaj Pawlikowski
79bb860f11 Merge pull request #114 from bloomberg/seeker89-patch-1
Even more GH action tweaks
2022-02-07 16:38:43 +00:00
Mikolaj Pawlikowski
94965624cf No need for that either, fix vendor tag
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 15:51:52 +00:00
Mikolaj Pawlikowski
c49fc9925c No need for this
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 15:50:53 +00:00
Mikolaj Pawlikowski
114b39a970 Merge pull request #113 from bloomberg/seeker89-patch-1
Trying to get the GH actions right
2022-02-04 15:36:01 +00:00
Mikolaj Pawlikowski
00ca071c22 Remove the GO_MOD_ACTION
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 15:03:56 +00:00
Mikolaj Pawlikowski
0715e438b9 Always vendor
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 15:01:55 +00:00
Mikolaj Pawlikowski
c3a37636c3 Also dockerignore vendor folder
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 11:42:21 +00:00
Mikolaj Pawlikowski
5961c48854 Easier to read
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 11:39:00 +00:00
Mikolaj Pawlikowski
3f4d041c17 Dockerignore the bin folder
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 11:07:28 +00:00
Mikolaj Pawlikowski
9acc894fde Update publish.yml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 11:06:12 +00:00
Mikolaj Pawlikowski
f1ee7f5a49 Merge pull request #112 from bloomberg/seeker89-patch-1
Fix the build badge
2022-02-04 10:56:09 +00:00
Mikolaj Pawlikowski
76f054ba50 Fix the build badge
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 10:51:43 +00:00
Mikolaj Pawlikowski
406f6e0ed0 Merge pull request #111 from bloomberg/seeker89-patch-1
Fix GH image publishing
2022-02-04 10:48:49 +00:00
Mikolaj Pawlikowski
b907f30c2f Update main.yml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 10:44:59 +00:00
Mikolaj Pawlikowski
d304200ede Update publish.yml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-04 10:43:56 +00:00
Mikolaj Pawlikowski
0755c8521f Merge pull request #110 from bloomberg/github-actions
Move onto Github Actions
2022-02-03 16:27:42 +00:00
Mikolaj Pawlikowski
9b1d8f8195 Run the docker image to see it works
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:34:56 +00:00
Mikolaj Pawlikowski
3cda043118 Cleanup the Makefile
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:33:06 +00:00
Mikolaj Pawlikowski
555709de0a Fix the tags and labels for the vendor build
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:28:49 +00:00
Mikolaj Pawlikowski
f89a07a420 Also do multi-arch builds on CI
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:27:30 +00:00
Mikolaj Pawlikowski
30f4d378f5 Delete Dockerfile-vendor
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:21:38 +00:00
Mikolaj Pawlikowski
b4ffe5dea2 Delete Dockerfile-simple
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:21:26 +00:00
Mikolaj Pawlikowski
42632de0cb Backwards compatible
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:17:50 +00:00
Mikolaj Pawlikowski
2f77502b0a Formatting
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:13:10 +00:00
Mikolaj Pawlikowski
46bc22ef0f Re-add basic CI with GH actions
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:12:07 +00:00
Mikolaj Pawlikowski
10277adc58 Update the secret names
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:09:58 +00:00
Mikolaj Pawlikowski
50ac3f0101 Delete .travis.yml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:03:16 +00:00
Mikolaj Pawlikowski
56b438abad Delete docker_deploy.sh
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2022-02-03 12:02:37 +00:00
Mikolaj Pawlikowski
fcc30fbe75 Merge pull request #109 from mtougeron/multi-arch-build
[WORK IN PROGRESS] Multi-architecture builds for goldpinger
2022-02-03 11:58:43 +00:00
Mike Tougeron
6aee150cd0 Multi-arch builds for goldpinger
Signed-off-by: Mike Tougeron <tougeron@adobe.com>
2022-01-15 17:12:42 -08:00
Mikolaj Pawlikowski
f7509473f6 Merge pull request #108 from bloomberg/version3-3-0
Version 3.3.0
2021-11-09 17:00:10 +00:00
Mikolaj Pawlikowski
039362ff78 Version 3.3.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-11-09 16:53:05 +00:00
Mikolaj Pawlikowski
b5f352def1 Merge pull request #107 from rbtr/list-running-pods
only list running pods
2021-11-08 15:41:13 +00:00
Mikolaj Pawlikowski
842dfadeea Merge branch 'master' into list-running-pods 2021-11-08 15:11:18 +00:00
Mikolaj Pawlikowski
ba58fcfaa0 Merge pull request #106 from tyler-lloyd/tyler-lloyd/enable-ipv6
Enable ping traffic over IPv6 via @tyler-lloyd
2021-11-08 15:09:48 +00:00
Tyler Lloyd
34b78537c9 changed return type to IPFamily
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-08 09:38:38 -05:00
Tyler Lloyd
ae61217ead cleanup imports
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-05 10:41:29 -04:00
Tyler Lloyd
cfd26c8d26 changing to IP_VERSIONS
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-05 10:40:37 -04:00
Evan Baker
980a85b04d only list running pods
Signed-off-by: Evan Baker <rbtr@users.noreply.github.com>
2021-11-03 18:06:29 -05:00
Tyler Lloyd
b88d0f3ec5 don't use Sprintf for creating host address
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-03 16:58:38 -04:00
Tyler Lloyd
03dd6706b8 add node IP cache and change to get node
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-03 16:58:38 -04:00
Tyler Lloyd
f76b552c62 reverting to go 1.14
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-03 16:58:38 -04:00
Tyler Lloyd
5b080c7087 update readme for IPv6 example
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-03 16:58:38 -04:00
Tyler Lloyd
5d2070fad1 get pod and host IPv6 IPs when USE_IPV6 is set
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-03 16:58:38 -04:00
Tyler Lloyd
b35d40b7f2 bumping to go 1.16 and updating k8s packages
Signed-off-by: Tyler Lloyd <Tyler.Lloyd@microsoft.com>
2021-11-03 16:58:38 -04:00
Mikolaj Pawlikowski
294b8dda19 Merge pull request #101 from bloomberg/cluster-health
Add a /cluster_health endpoint
2021-03-22 13:26:32 +00:00
Mikolaj Pawlikowski
ed40304dd8 1 when healthy, 0 when unhealthy (bool, not return code)
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-19 14:45:58 +00:00
Mikolaj Pawlikowski
e6aa196232 Compare the actual host ips
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-19 14:26:07 +00:00
Mikolaj Pawlikowski
948b67a09b Break here, continue there
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-19 13:46:37 +00:00
Mikolaj Pawlikowski
d0e2e25ad2 Make it a bit more obvious
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-19 13:43:40 +00:00
Mikolaj Pawlikowski
8d5262d316 Make the naming a little less bad, remove the break statements
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-19 13:25:39 +00:00
Mikolaj Pawlikowski
407d201591 Add an overall metric goldpinger_cluster_health_total (pings + DNS check)
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-19 12:31:49 +00:00
Mikolaj Pawlikowski
1f5589db8c Simplify
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-16 17:24:56 +00:00
Mikolaj Pawlikowski
bc94f4e058 Forgot the set the default to true, if nothing bad happens
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-16 17:21:46 +00:00
Mikolaj Pawlikowski
634e04ec44 Handle the situation when one of the nodes returns an error
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 17:51:12 +00:00
Mikolaj Pawlikowski
13ae09d93e Compare all nodes return the expected nodes that Kubernetes returns
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 17:16:58 +00:00
Mikolaj Pawlikowski
52ff43ec7d Make it return 418 on cluster health problem
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 17:06:57 +00:00
Mikolaj Pawlikowski
bfc4603e45 Always return the DurationNs
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:38:32 +00:00
Mikolaj Pawlikowski
e4d0a6cdf7 Merge branch 'master' into cluster-health 2021-03-12 13:33:33 +00:00
Mikolaj Pawlikowski
ad828cf5a3 And implement it
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:31:39 +00:00
Mikolaj Pawlikowski
5d2ad6ce19 Also add a total number of nodes in a field for convenience
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:31:01 +00:00
Mikolaj Pawlikowski
1310f9b12b Add the generated at field
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:27:19 +00:00
Mikolaj Pawlikowski
f93526c58f Lint
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:27:07 +00:00
Mikolaj Pawlikowski
1f2f00ba35 First draft of implementing it
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:24:58 +00:00
Mikolaj Pawlikowski
807f193b07 Regenerate
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:06:26 +00:00
Mikolaj Pawlikowski
b0730e88df Actually, just keep it simple
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 13:05:53 +00:00
Mikolaj Pawlikowski
e827a8dc67 Regenearte the code
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 12:57:20 +00:00
Mikolaj Pawlikowski
c7a7008bf5 Separately for the pods and hosts
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 12:56:27 +00:00
Mikolaj Pawlikowski
3edecea467 Implement a stub of the new endpoint
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 12:24:42 +00:00
Mikolaj Pawlikowski
bd04fcbc58 Version v3.2.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 11:31:26 +00:00
Mikolaj Pawlikowski
3ff592b1e8 Re-generate using the latest swagger gen cli
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 11:30:53 +00:00
Mikolaj Pawlikowski
8f5c742aed Merge pull request #100 from bloomberg/v3.1.0
Bump up to v3.1.0
2021-03-12 11:22:11 +00:00
Mikolaj Pawlikowski
eb3113aa7f Add the schema for the new endpoint
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 11:21:02 +00:00
Mikolaj Pawlikowski
8865ae1411 Bump up to v3.1.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2021-03-12 11:07:55 +00:00
Mikolaj Pawlikowski
9ad2f6191a Merge pull request #98 from sethp-verica/feat/namespace-config
feat: configurable namespace for pod discovery
2021-03-12 11:05:36 +00:00
Seth Pellegrino
07ef524aed feat: configurable namespace for pod discovery
Adds a configuration option to allow for cross-namespace pings.

Signed-off-by: Seth Pellegrino <seth@verica.io>
2020-11-23 14:01:25 -08:00
Mikolaj Pawlikowski
ca676bcbc2 Merge pull request #91 from johscheuer/correct-readme
Correct example in the readme
2020-07-22 18:51:09 +01:00
Johannes M. Scheuermann
97ec159852 Correct example in the readme
Signed-off-by: Johannes M. Scheuermann <joh.scheuer@gmail.com>
2020-07-22 14:00:45 +02:00
Mikolaj Pawlikowski
bb1a72866d Merge pull request #89 from seeker89/readme3
Refresh the README
2020-06-10 22:30:13 +01:00
Mikolaj Pawlikowski
6e29c16148 Specify the size
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-06-10 22:24:17 +01:00
Mikolaj Pawlikowski
f83c1de387 MOAR hyperlinks
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-06-10 22:22:44 +01:00
Mikolaj Pawlikowski
e24f789b68 Hyperlink all the things
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-06-10 22:22:05 +01:00
Mikolaj Pawlikowski
3a922f4278 Some more polish
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-06-10 22:20:16 +01:00
Mikolaj Pawlikowski
24d74544e0 Well, I clearly don't know my emoticons
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-06-10 22:19:11 +01:00
Mikolaj Pawlikowski
28f7655170 Add a note about Chaos Engineering and the authors
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-06-10 22:17:28 +01:00
Mikolaj Pawlikowski
e9d3f8cd2b Refresh the readme a little bit
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-06-10 22:17:09 +01:00
Mikolaj Pawlikowski
857db0d523 Merge pull request #85 from bloomberg/seeker89-patch-1
Update examples and README to use v3.0.0 of Goldpinger
2020-05-08 13:09:18 +01:00
Mikolaj Pawlikowski
0260da795f Update example-with-kubeconfig.yaml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-05-08 11:44:30 +01:00
Mikolaj Pawlikowski
4f8d872700 Update example-serviceaccounts.yml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-05-08 11:44:30 +01:00
Mikolaj Pawlikowski
8790d3e7c4 Update README to use v3.0.0 of Goldpinger
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-05-08 11:44:30 +01:00
Mikolaj Pawlikowski
a77ad0c3c1 Merge pull request #83 from skamboj/calm-the-thundering-herd
Calm the thundering herd
2020-04-08 13:31:46 +01:00
Sachin Kamboj
7e60ee675a Simplify updateCounters, don't try to maintain a running count
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-08 07:56:04 -04:00
Sachin Kamboj
d68d35bbab Add a ping time that gives the last time a node was pinged
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-07 21:04:43 -04:00
Sachin Kamboj
2a78a9cec5 Don't ping all pods on call, return existing data
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-07 20:49:01 -04:00
Sachin Kamboj
9db241d67d Update the set of pingers at regular intervals from the k8s API server
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-07 19:54:19 -04:00
Sachin Kamboj
bc313a7fbb Merge branch 'master' into calm-the-thundering-herd 2020-04-07 14:18:09 -04:00
Mikolaj Pawlikowski
1a5d07b162 Merge pull request #82 from skamboj/better-logging
Better logging
2020-04-07 17:54:38 +01:00
Mikolaj Pawlikowski
131ea12745 Merge pull request #81 from skamboj/customize-timeouts
Customize timeouts
2020-04-07 14:40:22 +01:00
Sachin Kamboj
40f57b1a4e Get rid of the lock and keep a running count of healthy/unhealthy nodes
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-07 08:45:14 -04:00
Mikolaj Pawlikowski
d5dd96a419 Merge pull request #79 from skamboj/pod-name-instead-of-pod-ip
Pod name instead of pod ip
2020-04-07 13:38:21 +01:00
Sachin Kamboj
8a40aee927 Have the updater continuously ping pods and collate the results
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-07 08:02:36 -04:00
Sachin Kamboj
0690ac21a2 Command line options for adding a jitter-factor
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-07 07:55:48 -04:00
Sachin Kamboj
d0dfd3e493 Add code to continuously ping the pods and send the results over a channel
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-07 07:54:10 -04:00
Sachin Kamboj
cd5316bbb9 Allow debug logging
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 22:50:17 -04:00
Sachin Kamboj
9ae3e78035 Better structured logging
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 22:39:57 -04:00
Sachin Kamboj
2e1c799a25 Replace log statements with zap
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 22:18:04 -04:00
Sachin Kamboj
d33d6d6636 Update dependencies
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 22:17:24 -04:00
Sachin Kamboj
4a7a53603f Configure zap in main to do our logging
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 22:16:20 -04:00
Sachin Kamboj
e3942bd5eb Fix the crashing UI
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 20:33:25 -04:00
Sachin Kamboj
1c6362b2a9 Add a context to the ping results
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 19:43:22 -04:00
Sachin Kamboj
7bbdcacf9b Add a context/timeout to the heatmap
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 19:42:59 -04:00
Sachin Kamboj
3a6ab53ced Add a context to the updater
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 19:41:43 -04:00
Sachin Kamboj
aa7eaca30e Get the context from the request and add overall timeouts
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 19:38:32 -04:00
Sachin Kamboj
86f9f8a1dd Add a context and timeout to the ping and check calls
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 19:36:14 -04:00
Sachin Kamboj
c8fbf618c7 Add flags for custom timeouts for the three operations
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-06 19:32:47 -04:00
Sachin Kamboj
1338f28163 Increment the major version since this is a breaking change
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:31:05 -04:00
Sachin Kamboj
f0c66f29c7 Store results by pod name instead of pod IP
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:22:52 -04:00
Sachin Kamboj
86febf8295 Update the way of selecting pods
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:17:26 -04:00
Sachin Kamboj
aa789fdea8 Add a PodName to the config
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:16:43 -04:00
Sachin Kamboj
a95279ac8e Also remove the PodSelector from the config and main
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:13:53 -04:00
Sachin Kamboj
6ee538549a Simplify and remove the PodSelecter struct
There is currently only a single way to select pods to ping and there is really no way to conifgure alternatives. So this commit removes the struct and simplifes the code.

Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:11:53 -04:00
Sachin Kamboj
7fa3138235 Also store the PodName when fetching from k8s API server. Also map from podName to GoldpingerPod sruct
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:10:36 -04:00
Sachin Kamboj
00cd1e3886 Auto-generated code with the changes to the swagger
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:09:05 -04:00
Sachin Kamboj
4152784d21 Add a PodIP to the results now that we are using PodName as a key
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-03 23:00:48 -04:00
Mikolaj Pawlikowski
c66050e536 Merge pull request #78 from skamboj/migrate-to-go-modules
Migrate to go modules
2020-04-02 20:40:46 +01:00
Mikolaj Pawlikowski
34d84b233c Merge branch 'master' into migrate-to-go-modules 2020-04-02 17:56:00 +01:00
Mikolaj Pawlikowski
e07ae6a64c Merge pull request #75 from ifooth/master
fix prometheus ruler expr
2020-04-02 17:55:47 +01:00
Mikolaj Pawlikowski
6844a8d2b4 Merge branch 'master' into master 2020-04-02 17:36:43 +01:00
Sachin Kamboj
c23112de50 Update the CI
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-01 21:06:01 -04:00
Sachin Kamboj
436c1a7243 Update the README to remove references to dep
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-01 21:00:31 -04:00
Sachin Kamboj
66c8dc0cce Update the version/tag to be compatible with what go expects
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-01 20:53:45 -04:00
Sachin Kamboj
8a7e5a36ba Update the multistage build to use go 1.14 and go modules; Remove dep
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-01 20:26:03 -04:00
Sachin Kamboj
4e508cb8c8 Update the vendoring
Signed-off-by: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-01 20:17:37 -04:00
Sachin Kamboj
536a7ffbbb Remove the dep files
Signed-Off-By: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-01 20:16:47 -04:00
Sachin Kamboj
bf25a51c3e Add a go.mod and go.sum
Signed-Off-By: Sachin Kamboj <skamboj1@bloomberg.net>
2020-04-01 19:48:15 -04:00
Mikolaj Pawlikowski
02b38e3ab7 Merge pull request #77 from sandeepmendiratta/sandeep-heatmap_fix
minor typo correction in heat map page. Also updated version and Read…
2020-03-22 21:36:49 +00:00
Sandeep Mendiratta
0870833cf5 minor typo correction in heat map page. Also updated version and Readme with new version
Signed-off-by: Sandeep Mendiratta <smendiratta@yahoo.com>
2020-03-22 16:28:22 -05:00
Mikolaj Pawlikowski
d5400d6e2e Merge pull request #76 from seeker89/fix-empty-ips
Fix a Goldpinger reporting healthy when kubernetes returns an empty IP field
2020-03-11 14:21:05 +00:00
Mikolaj Pawlikowski
94d4a7c81e Use HostIP as podIP, if the there is no podIP
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:25:12 +00:00
Mikolaj Pawlikowski
94dc18c9c2 Update the version in README
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:05:22 +00:00
Mikolaj Pawlikowski
8964cab729 Bump patch version
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:05:22 +00:00
Mikolaj Pawlikowski
d297e2f3c6 Change CheckAllPods to return an error when can't create a server
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:05:22 +00:00
Mikolaj Pawlikowski
02067f03ab Change PingAllPods to send an error if the client can't be created
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:05:22 +00:00
Mikolaj Pawlikowski
b96cab34ea Change the client builder to fail, if the IP provided is empty, instead of defaulting to localhost
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:05:22 +00:00
Mikolaj Pawlikowski
bc7afb7a17 Return response time on failure to ping
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:05:22 +00:00
Mikolaj Pawlikowski
89a6c76c9c Formatting
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2020-03-11 13:05:22 +00:00
Joe Lei
60436daf18 fix prometheus ruler expr
Signed-off-by: Joe Lei <thezero12@hotmail.com>
2020-02-18 10:59:43 +08:00
Mikolaj Pawlikowski
618369f540 Merge pull request #71 from SuleimanWA/master
prometheus service auto-discovery
2019-11-26 20:13:58 +00:00
suleimanWA
1ab777c3d5 Merge branch 'master' of github.com:SuleimanWA/goldpinger
move scrap annotation from service to pod level

Signed-off-by: suleimanWA <suleiman-94@hotmail.com>
2019-11-26 20:52:46 +02:00
suleiman abualrob
6315c71a2c Update README.md
Kubernetes master node by most of default installation are taint, so goldPinger DaemonSet will not deployed to master, in order to make it run on master nodes also, you have to tolerate the taint

Signed-off-by: suleimanWA <suleiman-94@hotmail.com>
2019-11-26 20:42:27 +02:00
suleiman abualrob
49a47284b6 Update README.md
Kubernetes master node by most of default installation are taint, so goldPinger DaemonSet will not deployed to master, in order to make it run on master nodes also, you have to tolerate the taint

Signed-off-by: suleimanWA <suleiman-94@hotmail.com>
2019-11-26 20:38:52 +02:00
suleiman abualrob
ec2155878a Update README.md
If you have Prometheus in your environment, adding these annotation will let  Prometheus auto-discovery fetch your metrics automatically from service-name:port/metrics

Signed-off-by: suleimanWA <suleiman-94@hotmail.com>
2019-11-26 19:03:14 +02:00
Mikolaj Pawlikowski
cab268b725 Merge pull request #70 from angelbarrera92/secure-k8s-deployment
Secure k8s deployment
2019-11-14 16:53:06 +00:00
Ángel Barrera Sánchez
e552b236a0 Change documentation example
Signed-off-by: Ángel Barrera Sánchez <angel@sighup.io>
2019-11-14 17:19:42 +01:00
Ángel Barrera Sánchez
8a86a74478 Change dashboard's datasource parameter to be variable
Signed-off-by: Ángel Barrera Sánchez <angel@sighup.io>
2019-11-14 17:19:42 +01:00
Ángel Barrera Sánchez
4dab241ff6 Change daemonset definition to be more secure
Signed-off-by: Ángel Barrera Sánchez <angel@sighup.io>
2019-11-14 17:19:42 +01:00
Mikolaj Pawlikowski
f99ba84d17 Merge pull request #64 from seeker89/bump-major-version
Add info on how to use the DNS features
2019-09-06 15:10:44 +01:00
Mikolaj Pawlikowski
75315a872a Better wording in the README
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-09-06 14:58:10 +01:00
Mikolaj Pawlikowski
ae67cf3594 Add a note about the DNS addresses being space-delimited
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-09-06 14:57:08 +01:00
Mikolaj Pawlikowski
433a6b8b88 Add a note about the DNS usage
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-09-06 14:51:22 +01:00
Mikolaj Pawlikowski
0660db7922 Bump up major version to 2.0.0
Since this is effectively a backwards incompatible change

Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-09-06 14:42:36 +01:00
Mikolaj Pawlikowski
58285945f6 Merge pull request #61 from cgreen12/master
Optionally test DNS resolution for each pod
2019-09-06 12:23:36 +01:00
Mikolaj Pawlikowski
8a014ad7f4 Merge branch 'master' into master 2019-09-05 13:58:20 +01:00
Mikolaj Pawlikowski
096b149afa Merge pull request #63 from ufou/all_relative_paths
make all paths relative to allow for hosting at a sub path of root
2019-09-05 13:56:58 +01:00
Luke Alexander
5840353d9f bump patch version accordingly
Signed-off-by: Luke Alexander <luke.alexander@mixcloud.com>
2019-09-05 11:39:50 +01:00
Luke Alexander
ac9bf4224d make all paths relative to allow for hosting at a sub path of root
Signed-off-by: Luke Alexander <luke.alexander@mixcloud.com>
2019-09-05 11:10:23 +01:00
Chris Green
bcbc2ac6fc :trollface: re-ran swagger
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-08-21 04:53:01 -04:00
Chris Green
192fc433a2 Added metric for DNS failures
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-07-04 03:06:29 -04:00
Chris Green
dc3864f170 Colour the dns nodes red for any failures
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-09 09:11:49 -04:00
Chris Green
8a759433eb Show the info for dns nodes
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-09 08:53:52 -04:00
Chris Green
1b12b7dc6b Version bump
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-09 08:44:49 -04:00
Chris Green
9adf26e2cb Consistency ftw
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-09 08:43:47 -04:00
Chris Green
927125bbc5 slight re-positioning
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-09 07:37:48 -04:00
Chris Green
7585d010a6 Initial UI changes
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-05 14:56:37 -04:00
Chris Green
5e0ecdd8d1 Updates from swagger change
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-05 14:30:53 -04:00
Chris Green
d834433d30 Moved dns check into client
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-05 14:30:11 -04:00
Chris Green
b64f5152f2 Moved DnsResults into CheckResults
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-05 14:28:40 -04:00
Chris Green
bbac97c17e Refactored swagger.yml for fewer dns requests
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-04 02:54:23 -04:00
Chris Green
74ffcc8d2e Do the dns lookup
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-02 13:18:40 -04:00
Chris Green
9586e16237 Updated models from swagger
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-02 13:18:05 -04:00
Chris Green
6541250aa9 Updated swagger.yml for map of dnsresults
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-02 11:54:20 -04:00
Chris Green
31a503d831 Added env-delim for envvar config
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-02 11:18:25 -04:00
Chris Green
195691518b Added DnsHosts to config
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-01 15:18:26 -04:00
Chris Green
aa66c94d47 Initial thoughts on swagger change
Signed-off-by: Chris Green <34572557+cgreen12@users.noreply.github.com>
2019-06-01 11:41:01 -04:00
Mikolaj Pawlikowski
7b2affea29 Merge pull request #59 from kpfleming/travis-deploy-one-version
Ensure that only Golang 1.10 builds are pushed to DockerHub
2019-03-22 15:27:12 +00:00
Kevin P. Fleming
d1a86eae93 Ensure that only Golang 1.10 builds are pushed to DockerHub
Signed-off-by: Kevin P. Fleming <kpfleming@bloomberg.net>
2019-03-21 16:16:22 -04:00
Mikolaj Pawlikowski
a2e5925210 Merge pull request #58 from dannyk81/healthz_readme
Update readme and example with liveness and readiness probes
2019-03-18 09:56:04 +00:00
Danny Kulchinsky
d243f0fb59 update example
Signed-off-by: Danny Kulchinsky <danny.kul@gmail.com>
Signed-off-by: Danny Kulchinsky <dannyk@tuenti.com>
2019-03-17 21:01:15 -04:00
Danny Kulchinsky
477ba69a72 Add livenessProbe and readinessProbe to README
Signed-off-by: Danny Kulchinsky <danny.kul@gmail.com>
Signed-off-by: Danny Kulchinsky <dannyk@tuenti.com>
2019-03-17 21:01:15 -04:00
Mikolaj Pawlikowski
86064f208e Merge pull request #53 from stuartnelson3/stn/rendezvous-hashing
Add rendezvous hash for selecting subset of nodes
2019-03-14 12:24:33 +00:00
Mikolaj Pawlikowski
d8f8c20927 make the graph work with edges to nodes that are not reporting
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-14 08:13:44 -04:00
Mikolaj Pawlikowski
7c43626b1e Minor version bump to 1.5.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-14 11:28:32 +00:00
Mikolaj Pawlikowski
11ec058b3b Add PING_NUMBER envvar support
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-14 11:27:49 +00:00
Mikolaj Pawlikowski
c006eede86 Merge branch 'master' into stn/rendezvous-hashing 2019-03-13 17:11:23 +00:00
Mikolaj Pawlikowski
a585b103f3 Merge pull request #56 from seeker89/docker-push-updates
Updates for the docker images being pushed to docker.io
2019-03-13 17:09:50 +00:00
Mikolaj Pawlikowski
32823fd105 remove the ls and pwd artifacts
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 16:58:42 +00:00
Mikolaj Pawlikowski
87792cffca turns out vendor folder I tried to copy was in gitignore and Travis won't pick it up
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 16:52:23 +00:00
Mikolaj Pawlikowski
369e9ece78 add slashes for the folders to copy
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 16:47:48 +00:00
Mikolaj Pawlikowski
28af41e352 Revert "debugging Travis - see if the ARG makes a difference"
This reverts commit 52ea5546aa.

Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 16:47:08 +00:00
Mikolaj Pawlikowski
52ea5546aa debugging Travis - see if the ARG makes a difference
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 16:41:12 +00:00
Mikolaj Pawlikowski
9040b69933 debug the make vendor-build target
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 16:23:17 +00:00
Mikolaj Pawlikowski
3ce0c46f91 consistenly use COPY over ADD
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 16:15:13 +00:00
Mikolaj Pawlikowski
7b156add72 Revert "fix the path to copy vendor folder from"
This reverts commit 8b1dd49506.

Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 15:53:37 +00:00
Mikolaj Pawlikowski
8b1dd49506 fix the path to copy vendor folder from
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 15:46:22 +00:00
Mikolaj Pawlikowski
bd13d4d673 simplify the vendor building, make it build it with every Travis run
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 14:43:09 +00:00
stuart nelson
895af850a1 Make PodSelecter a member on config struct
Signed-off-by: stuart nelson <stuartnelson3@gmail.com>
2019-03-13 15:30:18 +01:00
stuart nelson
771f303062 Add rendezvous hash for selecting subset of nodes
Select a user-defined number of pods via
rendezvous hash. This is important for larger
clusters, where the metric cardinality explosion
is too much for a single prometheus to handle.

Signed-off-by: stuart nelson <stuartnelson3@gmail.com>
2019-03-13 15:30:18 +01:00
Mikolaj Pawlikowski
b7c1d2dfb4 add extra info in README, about the -vendor image tag
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 14:29:54 +00:00
Mikolaj Pawlikowski
86ddcf9505 push an additional image with -vendor postfix with all the sources
For licensing reasons.

Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 14:26:28 +00:00
Mikolaj Pawlikowski
bf43dcff98 remove the vendor from the standard build
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 14:13:17 +00:00
Mikolaj Pawlikowski
6de72deee0 When building multi-stage, copy over the vendor folder for licensing reasons
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-13 13:59:43 +00:00
Mikolaj Pawlikowski
6cd12ef2d5 Update example-with-kubeconfig.yaml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-12 23:07:54 +00:00
Mikolaj Pawlikowski
8182369c02 Update example-serviceaccounts.yml
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-12 23:07:29 +00:00
Mikolaj Pawlikowski
82a0d6ae8c Merge branch 'master' into docker-push-updates 2019-03-12 23:05:32 +00:00
Mikolaj Pawlikowski
057e360c5b Update README.md
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-03-12 22:59:32 +00:00
Mikolaj Pawlikowski
4cf5dea621 Merge pull request #55 from kpfleming/travis-to-dockerhub
Enable push of images to DockerHub
2019-03-12 22:35:50 +00:00
Kevin P. Fleming
16a1d52741 Deployment improvements
* Only deploy from tags
* Only attempt deployment if DOCKER_PASSWORD has been set in environment
* Don't cleanup working directory before deployment

Signed-off-by: Kevin P. Fleming <kpfleming@bloomberg.net>
2019-03-12 09:15:22 -04:00
Kevin P. Fleming
0472791dae Use a 'deploy' stage and script
Pushing to DockerHub from the 'after_success' phase
was unreliable (triggered by PRs) so this patch changes
the process to use a 'deploy' stage script instead.

Signed-off-by: Kevin P. Fleming <kpfleming@bloomberg.net>
2019-03-11 16:28:16 -04:00
Kevin P. Fleming
84a43a3d28 Enable push of images to DockerHub
This patch will enable pushes of any successful builds (using Travis-CI)
of the 'master' branch to the proper repository on DockerHub. The credentials
necessary are provided via environment variables configured in the
Travis-CI settings.

Addresses issue #27

Signed-off-by: Kevin P. Fleming <kpfleming@bloomberg.net>
2019-03-11 15:29:58 -04:00
Mikolaj Pawlikowski
3f70a24804 Merge pull request #51 from seeker89/heatmap
Add heatmap
2019-03-05 17:48:00 +00:00
Mikolaj Pawlikowski
593307dc01 change the block size to 14 pixels (enough for two digits, so 100 machines cluster)
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-22 17:32:22 +00:00
Mikolaj Pawlikowski
950e2e4ab7 dep ensure
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 18:36:25 +00:00
Mikolaj Pawlikowski
d8f0d696ea add a basic legend to the heatmap image
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 18:34:30 +00:00
Mikolaj Pawlikowski
6deb5c3044 fix static folder when using Dockerfile-simple
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 17:43:54 +00:00
Mikolaj Pawlikowski
767d2dba7f quick test of how to integrate with the UI
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 17:41:19 +00:00
Mikolaj Pawlikowski
2efee0f5e5 read the tresholds from the query params
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 17:40:06 +00:00
Mikolaj Pawlikowski
3a729bf196 minor version bump
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 16:14:48 +00:00
Mikolaj Pawlikowski
fd84599157 remove debug print statements
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 16:13:20 +00:00
Mikolaj Pawlikowski
f5c2763000 add an endpoint for generating a /heatmap.png
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 13:51:20 +00:00
Mikolaj Pawlikowski
22b96d001d add a skeleton for creating a heatmap png
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-21 13:50:59 +00:00
Mikolaj Pawlikowski
1d88367a57 Merge pull request #49 from tylfin/responseTime
Include response time in PodResult
2019-02-20 17:01:45 +00:00
Mikolaj Pawlikowski
06565c4ba8 minor version bump
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-20 16:49:06 +00:00
Mikolaj Pawlikowski
513d8ee489 newer go-swagger has some fancier templates
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-20 16:44:25 +00:00
Mikolaj Pawlikowski
15b4598606 make swagger to update the response-time-ms field
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-20 16:43:42 +00:00
Mikolaj Pawlikowski
2bcff8b2d1 make the response time field explicit in its usage of milliseconds
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-20 16:41:15 +00:00
Mikolaj Pawlikowski
6ba2f7062c Merge branch 'master' into responseTime 2019-02-20 11:55:42 +00:00
Mikolaj Pawlikowski
4ae43b54ad Merge pull request #50 from seeker89/ui-deps-licensing
Comply with the UI dependency licenses when building a docker image
2019-02-19 09:01:07 +00:00
Mikolaj Pawlikowski
4c4c596791 typo
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-18 17:32:45 +00:00
Mikolaj Pawlikowski
0a5d80e2bf remove dependency on lodash
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-18 17:28:24 +00:00
Mikolaj Pawlikowski
d52a850d2e replaced the cnd jquery with https://github.com/jquery/jquery/releases/tag/3.1.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-18 17:06:42 +00:00
Mikolaj Pawlikowski
2465ecf21b replace the cdn bootstrap with the release downloaded from
https://github.com/twbs/bootstrap/releases/tag/v3.3.7:wq

Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-18 17:00:13 +00:00
Mikolaj Pawlikowski
24028c3d55 update index.html to use the downloaded full release
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-18 16:47:12 +00:00
Mikolaj Pawlikowski
4af45574fe Check in a full release of sigma.js 1.1.0 from github from https://github.com/jacomyal/sigma.js/releases/tag/v1.1.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-18 16:43:01 +00:00
Mikolaj Pawlikowski
6a483f2590 delete the cloudflare version of the release of sigma.js
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-02-18 16:41:08 +00:00
Mikolaj Pawlikowski
bf085b884f Merge pull request #44 from jpmondet/master
Allow offline usage of the UI
2019-02-18 16:39:17 +00:00
tfinethy
871b86471d Include response time in PodResult
Signed-off-by: tfinethy <tfinethy@cogolabs.com>

Remove all swagger updates

Change response-time to match status-code formatting

Switch to float64 and use milliseconds as the unit
2019-02-17 12:38:53 -05:00
jpmondet
9c8fbc05ad Update to get the latest changes from Master
Signed-off-by: jpmondet <jp@mondet.org>
2019-02-07 21:58:06 +01:00
Mikolaj Pawlikowski
d483117a28 Merge pull request #48 from ottoyiu/patch-1
fix README.md to point to right metric for AlertManager example
2019-02-06 12:03:00 +00:00
Otto Yiu
2c4e069c08 fix README.md to point to right metric for AlertManager example
Signed-Off-By: Otto Yiu <otto@live.ca>
2019-01-31 09:23:31 -08:00
jpmondet
841fbb49c9 Add remote dependencies and linked them in index.html
Signed-off-by: jpmondet <jp@mondet.org>
2019-01-09 21:22:55 +01:00
Mikolaj Pawlikowski
1b57d76d0c Merge pull request #42 from seeker89/version-bump
Version bump to 1.2.0
2019-01-04 15:36:11 +00:00
Mikolaj Pawlikowski
f42b979e18 version bump to 1.2.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2019-01-03 13:06:02 -05:00
Mikolaj Pawlikowski
8016789f7e Merge pull request #29 from kaduev13/8-healthz-endpoint
Add simple healthz endpoint
2019-01-03 18:04:40 +00:00
Mikolaj Pawlikowski
fe3752e29c Merge branch 'master' into 8-healthz-endpoint 2019-01-03 17:55:53 +00:00
Mikolaj Pawlikowski
f7560dbe62 Merge pull request #41 from dannyk81/patch-1
fix typo in kubeconfig example and version bump
2019-01-02 16:50:31 +01:00
Danny Kulchinsky
1de9257854 fix typo and version bump
Signed-off-by: Danny Kulchinsky <danny.kul@gmail.com>
2019-01-02 10:24:04 -05:00
Mikolaj Pawlikowski
fd4eacda3c Merge branch 'master' into 8-healthz-endpoint 2019-01-02 10:58:21 +01:00
Mikolaj Pawlikowski
ee5679fab5 Merge pull request #38 from marcosdiez/better-serviceaccount-example
More complete example-serviceaccounts.yml, now with rbac rules
2018-12-27 22:36:48 +01:00
Marcos Diez
e23ddf5083 More complete example-serviceaccounts.yml, now with rbac rules
Signed-off-by: Marcos Diez <marcos@unitron.com.br>
2018-12-26 16:55:58 -02:00
Mikolaj Pawlikowski
f48ff97943 Merge branch 'master' into 8-healthz-endpoint 2018-12-21 18:59:29 +01:00
Mikolaj Pawlikowski
fd93440017 Merge pull request #36 from kaduev13/17-add-goos-to-build-process
Fix GOOS problems during simple docker build
2018-12-21 18:58:13 +01:00
Mikolaj Pawlikowski
9185dade92 derp - fixed travis
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-21 18:41:11 +01:00
Mikolaj Pawlikowski
2a692c48b0 Update travis to run locally, and from both docker builders
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-21 18:34:13 +01:00
Mikolaj Pawlikowski
ab1d7558e7 update Makefile, add make version target
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-21 18:28:24 +01:00
Ivan Kalita
f71500b590 Improve GOOS workaround in build.sh
According to #17.

Signed-off-by: Ivan Kalita <kaduev13@gmail.com>
2018-12-21 17:53:42 +01:00
Ivan Kalita
b41d15986c Fix GOOS problems during simple docker build
According to #17.

Signed-off-by: Ivan Kalita <kaduev13@gmail.com>
2018-12-21 16:54:49 +01:00
Mikolaj Pawlikowski
a7bee25a51 Merge pull request #35 from akhy/dockerfile-fix
fix Dockerfile to build from current workspace
2018-12-21 16:36:10 +01:00
Akhyar Amarullah
6604127c13 fix broken simple docker build
Signed-off-by: Akhyar Amarullah <akhyrul@gmail.com>
2018-12-21 21:53:47 +07:00
Akhyar Amarullah
a1cd6d9ac9 fix Dockerfile to build from current workspace
Signed-off-by: Akhyar Amarullah <akhyrul@gmail.com>
2018-12-21 21:23:45 +07:00
Ivan Kalita
8bd1672e07 Remove license header from healthz-related autogenerated files
According to #32.

Signed-off-by: Ivan Kalita <kaduev13@gmail.com>
2018-12-21 14:45:54 +01:00
Mikolaj Pawlikowski
1dc28da389 Merge branch 'master' into 8-healthz-endpoint 2018-12-21 14:42:48 +01:00
Mikolaj Pawlikowski
609eb49149 Merge pull request #34 from kaduev13/32-remove-license-from-autogenerated-files
Remove license header from autogenerated files
2018-12-21 14:42:34 +01:00
Ivan Kalita
1e324f78b9 Remove license header from autogenerated files
According to #32.

Signed-off-by: Ivan Kalita <kaduev13@gmail.com>
2018-12-21 14:28:44 +01:00
Mikolaj Pawlikowski
f9b03c8f13 Merge pull request #33 from seeker89/gopkg-lock
Clean up the Gopkg.lock file
2018-12-21 12:16:15 +01:00
Mikolaj Pawlikowski
1f6ad6752e clean up the Gopkg.lock file
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-21 05:45:18 -05:00
Mikolaj Pawlikowski
f18348fd75 Merge pull request #30 from kaduev13/15-remove-sudo-from-makefile
Remove sudo from docker-related Makefile targets
2018-12-21 10:32:22 +01:00
Mikolaj Pawlikowski
c6b22741d7 Update README.md
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-21 10:18:23 +01:00
Mikolaj Pawlikowski
9b30561ccb Add a note about sudo usage for beginners
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-20 21:34:14 +01:00
Mikolaj Pawlikowski
74e30c1e9a Merge branch 'master' into 15-remove-sudo-from-makefile 2018-12-20 21:20:26 +01:00
Mikolaj Pawlikowski
b9233122fd Merge pull request #31 from seeker89/screenshot
Cosmetic tweaks to the README
2018-12-20 21:20:02 +01:00
Mikolaj Pawlikowski
ea46c35f71 Merge branch 'master' into 15-remove-sudo-from-makefile 2018-12-20 21:06:21 +01:00
Mikolaj Pawlikowski
23a8216e6d Merge branch 'master' into screenshot 2018-12-20 21:05:59 +01:00
Mikolaj Pawlikowski
d93a43d68b Merge pull request #28 from twexler/dynamic-label-selector
Use a configuration value for the label selector when discovering goldpinger pods
2018-12-20 19:11:35 +01:00
Mikolaj Pawlikowski
7eec26b194 Add a large size screenshot
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-20 18:52:44 +01:00
Mikolaj Pawlikowski
97808d9365 Update README.md
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-20 18:51:11 +01:00
Ivan Kalita
d780fcaa4a Remove sudo from docker-related Makefile targets
According to #15.

Signed-off-by: Ivan Kalita <kaduev13@gmail.com>
2018-12-20 18:30:45 +01:00
Ted Wexler
38f409b7bd Fix merge issue
Signed-off-by: Ted Wexler <twexler@bloomberg.net>
2018-12-20 17:26:46 +00:00
Mikolaj Pawlikowski
083b4ef962 Merge branch 'master' into dynamic-label-selector 2018-12-20 18:20:38 +01:00
Mikolaj Pawlikowski
0060f82c02 Merge pull request #20 from blakebarnett/bdb__limit_pod_list_by_namespace
Limit Pod.List calls by namespace
2018-12-20 18:19:01 +01:00
Ivan Kalita
d40bed4d3e Fix of the healthz endpoint handler
According to #8.

Signed-off-by: Ivan Kalita <kaduev13@gmail.com>
2018-12-20 18:17:09 +01:00
Ivan Kalita
ebbe41f4ef Add simple healthz endpoint
According to #8.

Signed-off-by: Ivan Kalita <kaduev13@gmail.com>
2018-12-20 18:12:18 +01:00
Mikolaj Pawlikowski
5bad42922e Explicitly return empty string on error reading namespace
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-20 18:03:17 +01:00
Ted Wexler
6f0dab4dfd Merge branch 'master' into dynamic-label-selector 2018-12-20 09:54:25 -05:00
Ted Wexler
4cddd3b5f8 Use a configuration value for the label selector when discovering goldpinger pods
Signed-off-by: Ted Wexler <twexler@bloomberg.net>
2018-12-20 14:53:59 +00:00
Mikolaj Pawlikowski
8a2d9e6f37 Fix indentation
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-20 15:42:47 +01:00
Mikolaj Pawlikowski
a8aa0cee74 Merge branch 'master' into bdb__limit_pod_list_by_namespace 2018-12-20 15:35:29 +01:00
Mikolaj Pawlikowski
33655dd9d8 Merge branch 'master' into bdb__limit_pod_list_by_namespace 2018-12-20 11:00:04 +00:00
Mikolaj Pawlikowski
e4eaca592a Merge branch 'master' into bdb__limit_pod_list_by_namespace 2018-12-19 13:31:29 +00:00
Mikolaj Pawlikowski
63e7820b1d Bump minor version to 1.1.0
Signed-off-by: Mikolaj Pawlikowski <mikolaj@pawlikowski.pl>
2018-12-19 10:27:11 +00:00
Blake
7612a46029 Limit the list of Pod.List calls by namespace
On larger clusters with thousands of pods listing all pods is too expensive.

Signed-off-by: Blake <blake.barnett@postmates.com>
2018-12-18 14:45:43 -08:00
147 changed files with 58516 additions and 1792 deletions

3
.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
.git/
bin/
vendor/

33
.github/workflows/helm-publish.yaml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Helm Publish
on:
push:
branches:
- master
jobs:
helm_publish:
# depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions
# see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- name: Install Helm
uses: azure/setup-helm@v4
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.7.0
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

74
.github/workflows/helm-test.yaml vendored Normal file
View File

@@ -0,0 +1,74 @@
name: Helm Test
on:
pull_request:
jobs:
helm_test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install Tools
shell: bash
id: tool-versions
env:
TILT_TOOL_CTLPTL_VERSION: "0.8.28"
TILT_TOOL_KIND_VERSION: "0.23.0"
TILT_TOOL_KUBECTL_VERSION: "1.30.0"
TILT_TOOL_HELM_VERSION: "3.14.4"
TILT_TOOL_TILT_VERSION: "0.33.13"
run: |
# Create Tools Directory
TOOLS_DIR=/opt/helm_tools
mkdir -p "${TOOLS_DIR}"
# Download ctlptl
echo "Downloading ctlptl"
curl -fsSL https://github.com/tilt-dev/ctlptl/releases/download/v${TILT_TOOL_CTLPTL_VERSION}/ctlptl.${TILT_TOOL_CTLPTL_VERSION}.linux.x86_64.tar.gz | sudo tar -xzv -C "${TOOLS_DIR}" ctlptl
# Download kind
echo "Downloading kind"
curl -fsSL https://kind.sigs.k8s.io/dl/v${TILT_TOOL_KIND_VERSION}/kind-linux-amd64 -o "${TOOLS_DIR}/kind"
# Download kubectl
echo "Downloading kubectl"
curl -fsSL https://dl.k8s.io/release/v${TILT_TOOL_KUBECTL_VERSION}/bin/linux/amd64/kubectl -o "${TOOLS_DIR}/kubectl"
# Download helm
echo "Downloading helm"
curl -fsSL https://get.helm.sh/helm-v${TILT_TOOL_HELM_VERSION}-linux-amd64.tar.gz | tar -xzv -C "${TOOLS_DIR}" --strip-components=1 linux-amd64/helm
# Download tilt
echo "Downloading tilt"
curl -fsSL https://github.com/tilt-dev/tilt/releases/download/v${TILT_TOOL_TILT_VERSION}/tilt.${TILT_TOOL_TILT_VERSION}.linux.x86_64.tar.gz | tar -xzv -C "${TOOLS_DIR}" tilt
# Make the binaries runnable
echo "Making binaries executable"
sudo chmod -R +x "${TOOLS_DIR}"
# Add tools to path
echo "PATH=${PATH}:${TOOLS_DIR}" >> $GITHUB_ENV
- name: Start Kind Cluster
shell: bash
run: |
ctlptl apply -f kind.yaml
- name: Run Tilt Tests
shell: bash
run: |
tilt ci --debug --output-snapshot-on-exit=/tmp/tilt-snapshot.json
- name: Upload Tilt Snapshot
if: success() || failure()
uses: actions/upload-artifact@v6
with:
name: tilt-snapshot
path: |
/tmp/tilt-snapshot.json

82
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: CI
on:
push:
branches: [ main, master ]
tags:
- v*
pull_request:
branches: [ main, master ]
workflow_dispatch:
jobs:
build:
permissions:
contents: write
packages: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
# local build
- name: Compile the binary
run: |
make bin/goldpinger
./bin/goldpinger -h
# simple Docker build
- name: Build the Docker image
run: |
make build
docker run `make version` --help
- name: Login to DockerHub
uses: docker/login-action@v3
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# multi-arch build
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
bake-target: docker-metadata-action
images: |
${{ github.repository_owner }}/goldpinger
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
labels: |
org.opencontainers.image.title=${{ github.repository }}
org.opencontainers.image.description=Goldpinger makes calls between its instances to monitor your networking. It runs as a DaemonSet on Kubernetes and produces Prometheus metrics that can be scraped, visualised and alerted on.
org.opencontainers.image.vendor=${{ github.repository_owner }}
- name: Build regular image
uses: docker/bake-action@v6
with:
targets: ci
push: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
files: |
./docker-bake.hcl
cwd://${{ steps.meta.outputs.bake-file }}
# https://github.com/docker/buildx/issues/2105
- name: Create manifest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
run: |
set -xe
for image in $images; do
docker buildx imagetools create -t "${image}" "${image}-linux" "${image}-windows-ltsc2019" "${image}-windows-ltsc2022"
done
env:
images: "${{ join( steps.meta.outputs.tags, ' ') }}"

1
.gitignore vendored
View File

@@ -91,3 +91,4 @@ ENV/
# Rope project settings
.ropeproject
.secrets

View File

@@ -1,15 +0,0 @@
language: go
services:
- docker
go:
- "1.10.x"
- master
script:
- docker --version
- go get -u github.com/golang/dep/cmd/dep && make vendor && make && make build
- docker images
- make build-multistage
- docker images

View File

@@ -1,27 +1,33 @@
FROM golang:1.11-alpine as builder
ARG WINDOWS_BASE_IMAGE=mcr.microsoft.com/windows/nanoserver:ltcs2022
# Install our build tools
FROM --platform=$BUILDPLATFORM golang:1.25 as builder
ARG TARGETARCH
ARG TARGETOS
RUN apk add --update git make bash
RUN go get -u github.com/golang/dep/cmd/dep
# Get sources
RUN go get github.com/bloomberg/goldpinger/cmd/goldpinger
WORKDIR /go/src/github.com/bloomberg/goldpinger
# Install our dependencies
RUN make vendor
# Get dependencies
WORKDIR /w
COPY go.mod go.sum ./
RUN go mod download
# Build goldpinger
RUN make bin/goldpinger
COPY . ./
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH make bin/goldpinger
# Create vendor folder
RUN go mod vendor
# Build the asset container, copy over goldpinger
FROM scratch
COPY --from=builder /go/src/github.com/bloomberg/goldpinger/bin/goldpinger /goldpinger
FROM gcr.io/distroless/static:nonroot as simple
COPY --from=builder /w/bin/goldpinger /goldpinger
COPY ./static /static
COPY ./config /config
ENTRYPOINT ["/goldpinger", "--static-file-path", "/static"]
FROM $WINDOWS_BASE_IMAGE AS windows
COPY --from=builder /w/bin/goldpinger /goldpinger.exe
COPY ./static /static
COPY ./config /config
ENTRYPOINT ["/goldpinger.exe", "--static-file-path=/static"]
# For vendor builds, use the simple build and add the vendor'd files
FROM simple as vendor
COPY --from=builder /w/vendor /goldpinger-vendor-sources

658
Gopkg.lock generated
View File

@@ -1,658 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:d1665c44bd5db19aaee18d1b6233c99b0b9a986e8bccb24ef54747547a48027f"
name = "github.com/PuerkitoBio/purell"
packages = ["."]
pruneopts = "UT"
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
version = "v1.1.0"
[[projects]]
branch = "master"
digest = "1:c739832d67eb1e9cc478a19cc1a1ccd78df0397bf8a32978b759152e205f644b"
name = "github.com/PuerkitoBio/urlesc"
packages = ["."]
pruneopts = "UT"
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
[[projects]]
digest = "1:320e7ead93de9fd2b0e59b50fd92a4d50c1f8ab455d96bc2eb083267453a9709"
name = "github.com/asaskevich/govalidator"
packages = ["."]
pruneopts = "UT"
revision = "ccb8e960c48f04d6935e72476ae4a51028f9e22f"
version = "v9"
[[projects]]
branch = "master"
digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d"
name = "github.com/beorn7/perks"
packages = ["quantile"]
pruneopts = "UT"
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
[[projects]]
branch = "master"
digest = "1:d76f06183572b1eabc33c586fae00b16430091ca48300ec9fdc8450f88df4c35"
name = "github.com/bloomberg/goldpinger"
packages = [
"pkg/client",
"pkg/client/operations",
"pkg/goldpinger",
"pkg/models",
"pkg/restapi",
"pkg/restapi/operations",
]
pruneopts = "UT"
revision = "0ebc4eecfa001237308b3c148619ec0f22f21ea1"
[[projects]]
digest = "1:6f82cacd0af5921e99bf3f46748705239b36489464f4529a1589bc895764fb18"
name = "github.com/docker/go-units"
packages = ["."]
pruneopts = "UT"
revision = "47565b4f722fb6ceae66b95f853feed578a4a51c"
version = "v0.3.3"
[[projects]]
digest = "1:c45cef8e0074ea2f8176a051df38553ba997a3616f1ec2d35222b1cf9864881e"
name = "github.com/ghodss/yaml"
packages = ["."]
pruneopts = "UT"
revision = "73d445a93680fa1a78ae23a5839bad48f32ba1ee"
[[projects]]
branch = "master"
digest = "1:7fb51688eadf38272411852d7a2b3538c7caff53309abee6c0964a83c00fe69e"
name = "github.com/globalsign/mgo"
packages = [
"bson",
"internal/json",
]
pruneopts = "UT"
revision = "eeefdecb41b842af6dc652aaea4026e8403e62df"
[[projects]]
digest = "1:c49164b7b1e34324258ae61deef2cba7912005ba9cb7a9ee4930fe6bdfec7b5d"
name = "github.com/go-openapi/analysis"
packages = [
".",
"internal",
]
pruneopts = "UT"
revision = "c701774f4e604d952e4e8c56dee260be696e33c3"
version = "v0.17.2"
[[projects]]
digest = "1:ac4b35a4bba11edb2110fca0707bae03ae92fbd8222e6b483465d98efaabfb97"
name = "github.com/go-openapi/errors"
packages = ["."]
pruneopts = "UT"
revision = "d9664f9fab8994271e573ed69cf2adfc09b7a800"
version = "v0.17.2"
[[projects]]
digest = "1:953a2628e4c5c72856b53f5470ed5e071c55eccf943d798d42908102af2a610f"
name = "github.com/go-openapi/jsonpointer"
packages = ["."]
pruneopts = "UT"
revision = "ef5f0afec364d3b9396b7b77b43dbe26bf1f8004"
version = "v0.17.2"
[[projects]]
digest = "1:81210e0af657a0fb3638932ec68e645236bceefa4c839823db0c4d918f080895"
name = "github.com/go-openapi/jsonreference"
packages = ["."]
pruneopts = "UT"
revision = "8483a886a90412cd6858df4ea3483dce9c8e35a3"
version = "v0.17.2"
[[projects]]
digest = "1:a20e8bf0e58e2010677432ffbe5533c1e83bdf368ba5b057f3e00e2071ca8b09"
name = "github.com/go-openapi/loads"
packages = ["."]
pruneopts = "UT"
revision = "150d36912387ec2f607be674c5be309ddccc0eed"
version = "v0.17.2"
[[projects]]
digest = "1:76b781f51e08cc0494b4abacf70d4b9da0a4732e270b7f2045ca9f0f875ad6d1"
name = "github.com/go-openapi/runtime"
packages = [
".",
"client",
"flagext",
"logger",
"middleware",
"middleware/denco",
"middleware/header",
"middleware/untyped",
"security",
]
pruneopts = "UT"
revision = "231d7876b7019dbcbfc97a7ba764379497b67c1d"
version = "v0.17.2"
[[projects]]
digest = "1:394fed5c0425fe01da3a34078adaa1682e4deaea6e5d232dde25c4034004c151"
name = "github.com/go-openapi/spec"
packages = ["."]
pruneopts = "UT"
revision = "5bae59e25b21498baea7f9d46e9c147ec106a42e"
version = "v0.17.2"
[[projects]]
digest = "1:ffa79f4705a3a85f2412d2d163c37acdf60d128c679e641c323a5de712e23d27"
name = "github.com/go-openapi/strfmt"
packages = ["."]
pruneopts = "UT"
revision = "edab9990ffc9b4a428f3306ecf4d18a069ca3317"
version = "v0.17.2"
[[projects]]
digest = "1:32f3d2e7f343de7263c550d696fb8a64d3c49d8df16b1ddfc8e80e1e4b3233ce"
name = "github.com/go-openapi/swag"
packages = ["."]
pruneopts = "UT"
revision = "5899d5c5e619fda5fa86e14795a835f473ca284c"
version = "v0.17.2"
[[projects]]
digest = "1:58541fddf3f4ec485710f1b346e7f647baf09a878a604e47e3668c600fe44076"
name = "github.com/go-openapi/validate"
packages = ["."]
pruneopts = "UT"
revision = "d2eab7d93009e9215fc85b2faa2c2f2a98c2af48"
version = "v0.17.2"
[[projects]]
digest = "1:f83d740263b44fdeef3e1bce6147b5d7283fcad1a693d39639be33993ecf3db1"
name = "github.com/gogo/protobuf"
packages = [
"proto",
"sortkeys",
]
pruneopts = "UT"
revision = "c0656edd0d9eab7c66d1eb0c568f9039345796f7"
[[projects]]
digest = "1:2edd2416f89b4e841df0e4a78802ce14d2bc7ad79eba1a45986e39f0f8cb7d87"
name = "github.com/golang/glog"
packages = ["."]
pruneopts = "UT"
revision = "44145f04b68cf362d9c4df2182967c2275eaefed"
[[projects]]
digest = "1:4c0989ca0bcd10799064318923b9bc2db6b4d6338dd75f3f2d86c3511aaaf5cf"
name = "github.com/golang/protobuf"
packages = [
"proto",
"ptypes",
"ptypes/any",
"ptypes/duration",
"ptypes/timestamp",
]
pruneopts = "UT"
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:0bfbe13936953a98ae3cfe8ed6670d396ad81edf069a806d2f6515d7bb6950df"
name = "github.com/google/btree"
packages = ["."]
pruneopts = "UT"
revision = "4030bb1f1f0c35b30ca7009e9ebd06849dd45306"
[[projects]]
digest = "1:41bfd4219241b7f7d6e6fdb13fc712576f1337e68e6b895136283b76928fdd66"
name = "github.com/google/gofuzz"
packages = ["."]
pruneopts = "UT"
revision = "44d81051d367757e1c7c6a5a86423ece9afcf63c"
[[projects]]
digest = "1:75eb87381d25cc75212f52358df9c3a2719584eaa9685cd510ce28699122f39d"
name = "github.com/googleapis/gnostic"
packages = [
"OpenAPIv2",
"compiler",
"extensions",
]
pruneopts = "UT"
revision = "0c5108395e2debce0d731cf0287ddf7242066aba"
[[projects]]
digest = "1:878f0defa9b853f9acfaf4a162ba450a89d0050eff084f9fe7f5bd15948f172a"
name = "github.com/gregjones/httpcache"
packages = [
".",
"diskcache",
]
pruneopts = "UT"
revision = "787624de3eb7bd915c329cba748687a3b22666a6"
[[projects]]
digest = "1:3e260afa138eab6492b531a3b3d10ab4cb70512d423faa78b8949dec76e66a21"
name = "github.com/imdario/mergo"
packages = ["."]
pruneopts = "UT"
revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58"
version = "v0.3.5"
[[projects]]
digest = "1:a2cff208d4759f6ba1b1cd228587b0a1869f95f22542ec9cd17fff64430113c7"
name = "github.com/jessevdk/go-flags"
packages = ["."]
pruneopts = "UT"
revision = "c6ca198ec95c841fdb89fc0de7496fed11ab854e"
version = "v1.4.0"
[[projects]]
digest = "1:bb3cc4c1b21ea18cfa4e3e47440fc74d316ab25b0cf42927e8c1274917bd9891"
name = "github.com/json-iterator/go"
packages = ["."]
pruneopts = "UT"
revision = "f2b4162afba35581b6d4a50d3b8f34e33c144682"
[[projects]]
branch = "master"
digest = "1:84a5a2b67486d5d67060ac393aa255d05d24ed5ee41daecd5635ec22657b6492"
name = "github.com/mailru/easyjson"
packages = [
"buffer",
"jlexer",
"jwriter",
]
pruneopts = "UT"
revision = "60711f1a8329503b04e1c88535f419d0bb440bff"
[[projects]]
digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"]
pruneopts = "UT"
revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
version = "v1.0.1"
[[projects]]
digest = "1:53bc4cd4914cd7cd52139990d5170d6dc99067ae31c56530621b18b35fc30318"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
pruneopts = "UT"
revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe"
version = "v1.1.2"
[[projects]]
digest = "1:33422d238f147d247752996a26574ac48dcf472976eda7f5134015f06bf16563"
name = "github.com/modern-go/concurrent"
packages = ["."]
pruneopts = "UT"
revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94"
version = "1.0.3"
[[projects]]
digest = "1:e32bdbdb7c377a07a9a46378290059822efdce5c8d96fe71940d87cb4f918855"
name = "github.com/modern-go/reflect2"
packages = ["."]
pruneopts = "UT"
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
version = "1.0.1"
[[projects]]
branch = "master"
digest = "1:3bf17a6e6eaa6ad24152148a631d18662f7212e21637c2699bff3369b7f00fa2"
name = "github.com/petar/GoLLRB"
packages = ["llrb"]
pruneopts = "UT"
revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
[[projects]]
digest = "1:0e7775ebbcf00d8dd28ac663614af924411c868dca3d5aa762af0fae3808d852"
name = "github.com/peterbourgon/diskv"
packages = ["."]
pruneopts = "UT"
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
version = "v2.0.1"
[[projects]]
digest = "1:26663fafdea73a38075b07e8e9d82fc0056379d2be8bb4e13899e8fda7c7dd23"
name = "github.com/prometheus/client_golang"
packages = [
"prometheus",
"prometheus/internal",
"prometheus/promhttp",
]
pruneopts = "UT"
revision = "abad2d1bd44235a26707c172eab6bca5bf2dbad3"
version = "v0.9.1"
[[projects]]
branch = "master"
digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
name = "github.com/prometheus/client_model"
packages = ["go"]
pruneopts = "UT"
revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f"
[[projects]]
branch = "master"
digest = "1:db712fde5d12d6cdbdf14b777f0c230f4ff5ab0be8e35b239fc319953ed577a4"
name = "github.com/prometheus/common"
packages = [
"expfmt",
"internal/bitbucket.org/ww/goautoneg",
"model",
]
pruneopts = "UT"
revision = "7e9e6cabbd393fc208072eedef99188d0ce788b6"
[[projects]]
branch = "master"
digest = "1:ef74914912f99c79434d9c09658274678bc85080ebe3ab32bec3940ebce5e1fc"
name = "github.com/prometheus/procfs"
packages = [
".",
"internal/util",
"nfs",
"xfs",
]
pruneopts = "UT"
revision = "185b4288413d2a0dd0806f78c90dde719829e5ae"
[[projects]]
digest = "1:9424f440bba8f7508b69414634aef3b2b3a877e522d8a4624692412805407bb7"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = "UT"
revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.1"
[[projects]]
digest = "1:3f3a05ae0b95893d90b9b3b5afdb79a9b3d96e4e36e099d841ae602e4aca0da8"
name = "golang.org/x/crypto"
packages = ["ssh/terminal"]
pruneopts = "UT"
revision = "de0752318171da717af4ce24d0a2e8626afaeb11"
[[projects]]
branch = "master"
digest = "1:eb8583d4582ffbc5c6d3ec00132cd0835101edde42b6f24eaafa628d1596f881"
name = "golang.org/x/net"
packages = [
"context",
"http/httpguts",
"http2",
"http2/hpack",
"idna",
"netutil",
]
pruneopts = "UT"
revision = "10aee181995363b41f712a55844a0dd52ea04646"
[[projects]]
digest = "1:9359217acc6040b4be710ce34473acef28023ad39bfafecea34ffaea7f1e1890"
name = "golang.org/x/oauth2"
packages = [
".",
"internal",
]
pruneopts = "UT"
revision = "a6bd8cefa1811bd24b86f8902872e4e8225f74c4"
[[projects]]
branch = "master"
digest = "1:509feef845f6af582cb82caad5eb176016b30714facdc754d84869ca31305b59"
name = "golang.org/x/sys"
packages = [
"unix",
"windows",
]
pruneopts = "UT"
revision = "7155702f2d47d94b134229da97195d0130cab001"
[[projects]]
digest = "1:0c56024909189aee3364b7f21a95a27459f718aa7c199a5c111c36cfffd9eaef"
name = "golang.org/x/text"
packages = [
"collate",
"collate/build",
"internal/colltab",
"internal/gen",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"secure/bidirule",
"transform",
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable",
"width",
]
pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
digest = "1:d37b0ef2944431fe9e8ef35c6fffc8990d9e2ca300588df94a6890f3649ae365"
name = "golang.org/x/time"
packages = ["rate"]
pruneopts = "UT"
revision = "f51c12702a4d776e4c1fa9b0fabab841babae631"
[[projects]]
digest = "1:08206298775e5b462e6c0333f4471b44e63f1a70e42952b6ede4ecc9572281eb"
name = "google.golang.org/appengine"
packages = [
"internal",
"internal/base",
"internal/datastore",
"internal/log",
"internal/remote_api",
"internal/urlfetch",
"urlfetch",
]
pruneopts = "UT"
revision = "4a4468ece617fc8205e99368fa2200e9d1fad421"
version = "v1.3.0"
[[projects]]
digest = "1:ef72505cf098abdd34efeea032103377bec06abb61d8a06f002d5d296a4b1185"
name = "gopkg.in/inf.v0"
packages = ["."]
pruneopts = "UT"
revision = "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4"
version = "v0.9.0"
[[projects]]
digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = "UT"
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
version = "v2.2.1"
[[projects]]
digest = "1:910ec974550174f4ca48b9f4a3caec16b693e584c3762dc726dc0dcf28f8e318"
name = "k8s.io/api"
packages = [
"admissionregistration/v1alpha1",
"admissionregistration/v1beta1",
"apps/v1",
"apps/v1beta1",
"apps/v1beta2",
"authentication/v1",
"authentication/v1beta1",
"authorization/v1",
"authorization/v1beta1",
"autoscaling/v1",
"autoscaling/v2beta1",
"autoscaling/v2beta2",
"batch/v1",
"batch/v1beta1",
"batch/v2alpha1",
"certificates/v1beta1",
"coordination/v1beta1",
"core/v1",
"events/v1beta1",
"extensions/v1beta1",
"networking/v1",
"policy/v1beta1",
"rbac/v1",
"rbac/v1alpha1",
"rbac/v1beta1",
"scheduling/v1alpha1",
"scheduling/v1beta1",
"settings/v1alpha1",
"storage/v1",
"storage/v1alpha1",
"storage/v1beta1",
]
pruneopts = "UT"
revision = "fd83cbc87e7632ccd8bbab63d2b673d4e0c631cc"
version = "kubernetes-1.12.0"
[[projects]]
digest = "1:18f352651d6e8578fdbaf29c68334b042439b288b8ae4112c2b2ba9a6e35ced0"
name = "k8s.io/apimachinery"
packages = [
"pkg/api/errors",
"pkg/api/meta",
"pkg/api/resource",
"pkg/apis/meta/v1",
"pkg/apis/meta/v1/unstructured",
"pkg/apis/meta/v1beta1",
"pkg/conversion",
"pkg/conversion/queryparams",
"pkg/fields",
"pkg/labels",
"pkg/runtime",
"pkg/runtime/schema",
"pkg/runtime/serializer",
"pkg/runtime/serializer/json",
"pkg/runtime/serializer/protobuf",
"pkg/runtime/serializer/recognizer",
"pkg/runtime/serializer/streaming",
"pkg/runtime/serializer/versioning",
"pkg/selection",
"pkg/types",
"pkg/util/clock",
"pkg/util/errors",
"pkg/util/framer",
"pkg/util/intstr",
"pkg/util/json",
"pkg/util/naming",
"pkg/util/net",
"pkg/util/runtime",
"pkg/util/sets",
"pkg/util/validation",
"pkg/util/validation/field",
"pkg/util/yaml",
"pkg/version",
"pkg/watch",
"third_party/forked/golang/reflect",
]
pruneopts = "UT"
revision = "6dd46049f39503a1fc8d65de4bd566829e95faff"
version = "kubernetes-1.12.0"
[[projects]]
digest = "1:51fd9ac9f2be10d79f5af101a7a1d758ef283fdb028a0d11198754bd3d4a6020"
name = "k8s.io/client-go"
packages = [
"discovery",
"kubernetes",
"kubernetes/scheme",
"kubernetes/typed/admissionregistration/v1alpha1",
"kubernetes/typed/admissionregistration/v1beta1",
"kubernetes/typed/apps/v1",
"kubernetes/typed/apps/v1beta1",
"kubernetes/typed/apps/v1beta2",
"kubernetes/typed/authentication/v1",
"kubernetes/typed/authentication/v1beta1",
"kubernetes/typed/authorization/v1",
"kubernetes/typed/authorization/v1beta1",
"kubernetes/typed/autoscaling/v1",
"kubernetes/typed/autoscaling/v2beta1",
"kubernetes/typed/autoscaling/v2beta2",
"kubernetes/typed/batch/v1",
"kubernetes/typed/batch/v1beta1",
"kubernetes/typed/batch/v2alpha1",
"kubernetes/typed/certificates/v1beta1",
"kubernetes/typed/coordination/v1beta1",
"kubernetes/typed/core/v1",
"kubernetes/typed/events/v1beta1",
"kubernetes/typed/extensions/v1beta1",
"kubernetes/typed/networking/v1",
"kubernetes/typed/policy/v1beta1",
"kubernetes/typed/rbac/v1",
"kubernetes/typed/rbac/v1alpha1",
"kubernetes/typed/rbac/v1beta1",
"kubernetes/typed/scheduling/v1alpha1",
"kubernetes/typed/scheduling/v1beta1",
"kubernetes/typed/settings/v1alpha1",
"kubernetes/typed/storage/v1",
"kubernetes/typed/storage/v1alpha1",
"kubernetes/typed/storage/v1beta1",
"pkg/apis/clientauthentication",
"pkg/apis/clientauthentication/v1alpha1",
"pkg/apis/clientauthentication/v1beta1",
"pkg/version",
"plugin/pkg/client/auth/exec",
"rest",
"rest/watch",
"tools/auth",
"tools/clientcmd",
"tools/clientcmd/api",
"tools/clientcmd/api/latest",
"tools/clientcmd/api/v1",
"tools/metrics",
"tools/reference",
"transport",
"util/cert",
"util/connrotation",
"util/flowcontrol",
"util/homedir",
"util/integer",
]
pruneopts = "UT"
revision = "1638f8970cefaa404ff3a62950f88b08292b2696"
version = "v9.0.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/bloomberg/goldpinger/pkg/client",
"github.com/bloomberg/goldpinger/pkg/client/operations",
"github.com/bloomberg/goldpinger/pkg/goldpinger",
"github.com/bloomberg/goldpinger/pkg/models",
"github.com/bloomberg/goldpinger/pkg/restapi",
"github.com/bloomberg/goldpinger/pkg/restapi/operations",
"github.com/go-openapi/errors",
"github.com/go-openapi/loads",
"github.com/go-openapi/runtime",
"github.com/go-openapi/runtime/client",
"github.com/go-openapi/runtime/flagext",
"github.com/go-openapi/runtime/middleware",
"github.com/go-openapi/runtime/security",
"github.com/go-openapi/spec",
"github.com/go-openapi/strfmt",
"github.com/go-openapi/swag",
"github.com/go-openapi/validate",
"github.com/jessevdk/go-flags",
"github.com/prometheus/client_golang/prometheus",
"github.com/prometheus/client_golang/prometheus/promhttp",
"golang.org/x/net/context",
"golang.org/x/net/netutil",
"k8s.io/apimachinery/pkg/apis/meta/v1",
"k8s.io/client-go/kubernetes",
"k8s.io/client-go/rest",
"k8s.io/client-go/tools/clientcmd",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,78 +0,0 @@
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
name = "github.com/go-openapi/errors"
version = "0.17.2"
[[constraint]]
name = "github.com/go-openapi/loads"
version = "0.17.2"
[[constraint]]
name = "github.com/go-openapi/runtime"
version = "0.17.2"
[[constraint]]
name = "github.com/go-openapi/spec"
version = "0.17.2"
[[constraint]]
name = "github.com/go-openapi/strfmt"
version = "0.17.2"
[[constraint]]
name = "github.com/go-openapi/swag"
version = "0.17.2"
[[constraint]]
name = "github.com/go-openapi/validate"
version = "0.17.2"
[[constraint]]
name = "github.com/jessevdk/go-flags"
version = "1.4.0"
[[constraint]]
name = "github.com/prometheus/client_golang"
version = "0.9.1"
[[constraint]]
branch = "master"
name = "golang.org/x/net"
[[constraint]]
name = "k8s.io/apimachinery"
version = "kubernetes-1.12.0"
[[constraint]]
name = "k8s.io/client-go"
version = "9.0.0"
[prune]
go-tests = true
unused-packages = true

View File

@@ -1,14 +1,16 @@
name ?= goldpinger
version ?= 1.0.3
version ?= v3.10.3
bin ?= goldpinger
pkg ?= "github.com/bloomberg/goldpinger"
tag = $(name):$(version)
namespace ?= ""
goos ?= ${GOOS}
goarch ?= ${GOARCH}
namespace ?= "bloomberg/"
files = $(shell find . -iname "*.go")
bin/$(bin): $(files)
PKG=${pkg} ARCH=amd64 VERSION=${version} BIN=${bin} ./build/build.sh
GOOS=${goos} PKG=${pkg} ARCH=${goarch} VERSION=${version} BIN=${bin} ./build/build.sh
clean:
rm -rf ./vendor
@@ -16,25 +18,28 @@ clean:
vendor:
rm -rf ./vendor
dep ensure -v
go mod vendor
# Download the latest swagger releases from: https://github.com/go-swagger/go-swagger/releases/
swagger:
swagger generate server -t pkg -f ./swagger.yml --exclude-main -A goldpinger && \
swagger generate client -t pkg -f ./swagger.yml -A goldpinger
build-multistage:
sudo docker build -t $(tag) -f ./Dockerfile .
build: bin/$(bin)
sudo docker build -t $(tag) -f ./build/Dockerfile-simple .
tag:
sudo docker tag $(tag) $(namespace)$(tag)
push:
sudo docker push $(namespace)$(tag)
run:
go run ./cmd/goldpinger/main.go
.PHONY: clean vendor build-swagger build tag push run
build:
docker build -t $(namespace)$(tag) --target simple -f ./Dockerfile .
build-vendor:
docker build -t $(namespace)$(tag)-vendor --target vendor -f ./Dockerfile .
build-release:
docker buildx build --push --platform linux/amd64,linux/arm64 --target simple -t $(namespace)$(tag) -f ./Dockerfile .
docker buildx build --push --platform linux/amd64,linux/arm64 --target vendor -t $(namespace)$(tag)-vendor -f ./Dockerfile .
version:
@echo $(namespace)$(tag)
.PHONY: clean vendor swagger build build-release build-vendor run version

245
README.md
View File

@@ -1,158 +1,221 @@
# Goldpinger [![Build Status](https://travis-ci.com/bloomberg/goldpinger.svg?branch=master)](https://travis-ci.com/bloomberg/goldpinger)
# Goldpinger
__Goldpinger__ makes calls between its instances for visibility and alerting.
It runs as a `DaemonSet` on `Kubernetes` and produces `Prometheus` metrics that can be scraped, visualised and alerted on.
[![Publish](https://github.com/bloomberg/goldpinger/actions/workflows/publish.yml/badge.svg)](https://github.com/bloomberg/goldpinger/actions/workflows/publish.yml)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/bloomberg/goldpinger)
__Goldpinger__ makes calls between its instances to monitor your networking.
It runs as a [`DaemonSet`](#example-yaml) on `Kubernetes` and produces `Prometheus` metrics that can be [scraped](#prometheus), [visualised](#grafana) and [alerted](#alert-manager) on.
Oh, and it gives you the graph below for your cluster. Check out the [video explainer](https://youtu.be/DSFxRz_0TU4).
![](./extras/screenshot.png)
[:tada: 1M+ pulls from docker hub!](https://hub.docker.com/r/bloomberg/goldpinger/tags)
## On the menu
- [Rationale](#rationale)
- [Quick start](#quick-start)
- [Building](#building)
- [Compiling using a multi-stage Dockerfile](#compiling-using-a-multi-stage-dockerfile)
- [Compiling locally](#compiling-locally)
- [Installation](#installation)
- [Authentication with Kubernetes API](#authentication-with-kubernetes-api)
- [Example YAML](#example-yaml)
- [Usage](#usage)
- [UI](#ui)
- [API](#api)
- [Prometheus](#prometheus)
- [Grafana](#grafana)
- [Alert Manager](#alert-manager)
- [Contributions](#contributions)
- [License](#license)
- [Goldpinger](#goldpinger)
- [On the menu](#on-the-menu)
- [Rationale](#rationale)
- [Quick start](#quick-start)
- [Building](#building)
- [Compiling using a multi-stage Dockerfile](#compiling-using-a-multi-stage-dockerfile)
- [Compiling locally](#compiling-locally)
- [Installation](#installation)
- [Authentication with Kubernetes API](#authentication-with-kubernetes-api)
- [Example YAML](#example-yaml)
- [Note on DNS](#note-on-dns)
- [Usage](#usage)
- [UI](#ui)
- [API](#api)
- [Prometheus](#prometheus)
- [Grafana](#grafana)
- [Alert Manager](#alert-manager)
- [Chaos Engineering](#chaos-engineering)
- [Authors](#authors)
- [Contributions](#contributions)
- [License](#license)
## Rationale
We built __Goldpinger__ to troubleshoot, visualise and alert on our networking layer while adopting `Kubernetes` at Bloomberg. It has since become the go-to tool to see connectivity and slowness issues.
It's small, simple and you'll wonder why you hadn't had it before.
It's small (~16MB), simple and you'll wonder why you hadn't had it before.
If you'd like to know more, you can watch [our presentation at Kubecon 2018 Seattle](https://youtu.be/DSFxRz_0TU4).
## Quick start
Getting from sources:
```sh
go get github.com/bloomberg/goldpinger/cmd/goldpinger
goldpinger --help
```
Note, that in order to guarantee correct versions of dependencies, the project [uses `dep`](./Makefile).
Getting from [docker hub](https://hub.docker.com/r/bloomberg/goldpinger):
```sh
# get from docker hub
docker pull bloomberg/goldpinger:v3.0.0
```
## Building
The repo comes with two ways of building a `docker` image: compiling locally, and compiling using a multi-stage `Dockerfile` image.
The repo comes with two ways of building a `docker` image: compiling locally, and compiling using a multi-stage `Dockerfile` image. :warning: Depending on your `docker` setup, you might need to prepend the commands below with `sudo`.
### Compiling using a multi-stage Dockerfile
You will need `docker` version 17.05+ installed to support multi-stage builds.
```sh
# step 1: launch the build
make build-multistage
# Build a local container without publishing
make build
# step 2: push the image somewhere
namespace="docker.io/myhandle/" make tag
namespace="docker.io/myhandle/" make push
# Build & push the image somewhere
namespace="docker.io/myhandle/" make build-release
```
This was contributed via [@michiel](https://github.com/michiel) - kudos !
### Compiling locally
In order to build `Goldpinger`, you are going to need `go` version 1.10+, `dep`, and `docker`.
In order to build `Goldpinger`, you are going to need `go` version 1.15+ and `docker`.
Building from source code consists of compiling the binary and building a [Docker image](./build/Dockerfile-simple):
Building from source code consists of compiling the binary and building a [Docker image](./Dockerfile):
```sh
# step 0: check out the code into your $GOPATH
go get github.com/bloomberg/goldpinger/cmd/goldpinger
cd $GOPATH/src/github.com/bloomberg/goldpinger
# step 0: check out the code
git clone https://github.com/bloomberg/goldpinger.git
cd goldpinger
# step 1: download the dependencies via dep ensure
make vendor
# step 2: compile the binary for the desired architecture
# step 1: compile the binary for the desired architecture
make bin/goldpinger
# at this stage you should be able to run the binary
./bin/goldpinger --help
# step 3: build the docker image containing the binary
make build
# step 2: build the docker image containing the binary
namespace="docker.io/myhandle/" make build
# step 4: push the image somewhere
namespace="docker.io/myhandle/" make tag
namespace="docker.io/myhandle/" make push
# step 3: push the image somewhere
docker push $(namespace="docker.io/myhandle/" make version)
```
## Installation
`Goldpinger` works by asking `Kubernetes` for pods with particular labels (`app=goldpinger`). While you can deploy `Goldpinger` in a variety of ways, it works very nicely as a `DaemonSet` out of the box.
### Authentication with Kubernetes API
### Helm Installation
Goldpinger can be installed via [Helm](https://helm.sh/) using the following:
```
helm repo add goldpinger https://bloomberg.github.io/goldpinger
helm repo update
helm install goldpinger goldpinger/goldpinger
```
### Manual Installation
`Goldpinger` can be installed manually via configuration similar to the following:
#### Authentication with Kubernetes API
`Goldpinger` supports using a `kubeconfig` (specify with `--kubeconfig-path`) or service accounts.
### Example YAML
#### Example YAML
Here's an example of what you can do (using the in-cluster authentication to `Kubernetes` apiserver).
:warning: Replace `docker.io/mynamespace-replaceme/goldpinger:1.0.0` with the actual tag you built.
Here's an example of what you can do (using the in-cluster authentication to `Kubernetes` apiserver).
```yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: goldpinger-serviceaccount
namespace: default
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: goldpinger
namespace: default
labels:
app: goldpinger
spec:
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: goldpinger
version: "1.0.0"
template:
metadata:
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '8080'
labels:
app: goldpinger
version: "1.0.0"
spec:
serviceAccount: goldpinger-serviceaccount
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: goldpinger
env:
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "80"
value: "8080"
# injecting real hostname will make for easier to understand graphs/metrics
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
image: "docker.io/mynamespace-replaceme/goldpinger:1.0.0"
# podIP is used to select a randomized subset of nodes to ping.
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
image: "docker.io/bloomberg/goldpinger:v3.0.0"
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
resources:
limits:
memory: 80Mi
requests:
cpu: 1m
memory: 40Mi
ports:
- containerPort: 80
- containerPort: 8080
name: http
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: goldpinger
namespace: default
labels:
app: goldpinger
spec:
type: NodePort
ports:
- port: 80
- port: 8080
nodePort: 30080
name: http
selector:
@@ -163,7 +226,7 @@ Note, that you will also need to add an RBAC rule to allow `Goldpinger` to list
```yaml
---
apiVersion: rbac.authorization.k8s.io/v1beta1
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: default
@@ -173,25 +236,74 @@ roleRef:
name: view
subjects:
- kind: ServiceAccount
name: default
name: goldpinger-serviceaccount
namespace: default
```
You can also see [an example of using `kubeconfig` in the `./extras`](./extras/example-with-kubeconfig.yaml).
### Using with IPv4/IPv6 dual-stack
If your cluster IPv4/IPv6 dual-stack and you want to force IPv6, you can set the `IP_VERSIONS` environment variable to "6" (default is "4") which will use the IPv6 address on the pod and host.
![ipv6](./extras/screenshot-ipv6.png)
### Note on DNS
Note, that on top of resolving the other pods, all instances can also try to resolve arbitrary DNS. This allows you to test your DNS setup.
From `--help`:
```sh
--host-to-resolve= A host to attempt dns resolve on (space delimited) [$HOSTS_TO_RESOLVE]
```
So in order to test two domains, we could add an extra env var to the example above:
```yaml
- name: HOSTS_TO_RESOLVE
value: "www.bloomberg.com one.two.three"
```
and `goldpinger` should show something like this:
![screenshot-DNS-resolution](./extras/dns-screenshot.png)
### TCP and HTTP checks to external targets
Instances can also be configured to do simple TCP or HTTP checks on external targets. This is useful for visualizing more nuanced connectivity flows.
```sh
--tcp-targets= A list of external targets(<host>:<port> or <ip>:<port>) to attempt a TCP check on (space delimited) [$TCP_TARGETS]
--http-targets= A list of external targets(<http or https>://<url>) to attempt an HTTP{S} check on. A 200 HTTP code is considered successful. (space delimited) [$HTTP_TARGETS]
--tcp-targets-timeout= The timeout for a tcp check on the provided tcp-targets (default: 500) [$TCP_TARGETS_TIMEOUT]
--dns-targets-timeout= The timeout for a tcp check on the provided udp-targets (default: 500) [$DNS_TARGETS_TIMEOUT]
```
```yaml
- name: HTTP_TARGETS
value: http://bloomberg.com
- name: TCP_TARGETS
value: 10.34.5.141:5000 10.34.195.193:6442
```
the timeouts for the TCP, DNS and HTTP checks can be configured via `TCP_TARGETS_TIMEOUT`, `DNS_TARGETS_TIMEOUT` and `HTTP_TARGETS_TIMEOUT` respectively.
![screenshot-tcp-http-checks](./extras/tcp-checks-screenshot.png)
## Usage
### UI
Once you have it running, you can hit any of the nodes (port 30080 in the example above) and see the UI.
![](./extras/screenshot.png)
![](./extras/screenshot-big.png)
You can click on various nodes to gray out the clutter and see more information.
### API
The API exposed is via a well-defined [`Swagger` spec](./swagger.yml).
The API exposed is via a well-defined [`Swagger` spec](./swagger.yml).
The spec is used to generate both the server and the client of `Goldpinger`. If you make changes, you can re-generate them using [go-swagger](https://github.com/go-swagger/go-swagger) via [`make swagger`](./Makefile)
@@ -223,8 +335,8 @@ To get you started, here's a rule that will trigger an alert if there are any no
```yaml
alert: goldpinger_nodes_unhealthy
expr: sum(goldpinger_nodes_healthy_total{status="unhealthy"})
BY (goldpinger_instance) > 0
expr: sum(goldpinger_nodes_health_total{status="unhealthy"})
BY (instance, goldpinger_instance) > 0
for: 5m
annotations:
description: |
@@ -234,6 +346,15 @@ annotations:
Similarly, why not :heart: contribute some amazing alerts for others to use ?
### Chaos Engineering
Goldpinger also makes for a pretty good monitoring tool in when practicing Chaos Engineering. Check out [PowerfulSeal](https://github.com/bloomberg/powerfulseal), if you'd like to do some Chaos Engineering for Kubernetes.
## Authors
Goldpinger was created by [Mikolaj Pawlikowski](https://github.com/seeker89) and ported to Go by Chris Green.
## Contributions
We :heart: contributions.
@@ -247,3 +368,5 @@ Before you create that PR, please make sure you read [CONTRIBUTING](./CONTRIBUTI
## License
Please read the [LICENSE](./LICENSE) file here.
For each version built by travis, there is also an additional version, appended with `-vendor`, which contains all source code of the dependencies used in `goldpinger`.

30
Tiltfile Normal file
View File

@@ -0,0 +1,30 @@
# -*- mode: bazel-starlark -*-
# Build the image
docker_build('goldpinger-local', '.')
# Deploy with Helm
k8s_yaml(
helm(
'charts/goldpinger',
set = [
# Set the image to the one built by Tilt
'image.repository=goldpinger-local',
],
)
)
# Track Goldpinger Resource
k8s_resource(
'chart-goldpinger',
port_forwards = [8080],
)
# Validate that all 2 nodes can talk to eachother
local_resource(
'check_reachability',
cmd='./extras/check_reachability.sh 2',
resource_deps = [
'chart-goldpinger',
],
)

View File

@@ -1,6 +0,0 @@
FROM scratch
ADD bin/goldpinger /goldpinger
COPY static/index.html /static/index.html
ENTRYPOINT ["/goldpinger", "--static-file-path", "/static"]

View File

@@ -24,17 +24,14 @@ if [ -z "${PKG}" ]; then
echo "PKG must be set"
exit 1
fi
if [ -z "${ARCH}" ]; then
echo "ARCH must be set"
exit 1
fi
if [ -z "${VERSION}" ]; then
echo "VERSION must be set"
exit 1
fi
export CGO_ENABLED=0
export GOARCH="${ARCH}"
export GOARCH="${ARCH:-amd64}"
export GOOS=${GOOS:-linux}
go build \
-ldflags "-X 'main.Version=${VERSION}' -X 'main.Build=`date`'" \

View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj
OWNERS

View File

@@ -0,0 +1,8 @@
apiVersion: v1
name: goldpinger
appVersion: "3.10.3"
version: 1.0.2
description: Goldpinger is a tool to help debug, troubleshoot and visualize network connectivity and slowness issues.
home: https://github.com/bloomberg/goldpinger
sources:
- https://github.com/bloomberg/goldpinger

View File

@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "goldpinger.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "goldpinger.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "goldpinger.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "goldpinger.labels" -}}
helm.sh/chart: {{ include "goldpinger.chart" . }}
{{ include "goldpinger.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "goldpinger.selectorLabels" -}}
app.kubernetes.io/name: {{ include "goldpinger.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "goldpinger.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "goldpinger.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,12 @@
{{- if and .Values.rbac.create .Values.rbac.clusterscoped }}
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "goldpinger.fullname" . }}-clusterrole
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list"]
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- if and .Values.rbac.create .Values.rbac.clusterscoped }}
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "goldpinger.fullname" . }}-clusterrolebinding
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
subjects:
- kind: ServiceAccount
name: {{ include "goldpinger.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: {{ include "goldpinger.fullname" . }}-clusterrole
apiGroup: rbac.authorization.k8s.io
{{- end }}

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "goldpinger.fullname" . }}-zap
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
data:
zap.json: {{ .Values.goldpinger.zapConfig | toJson }}

View File

@@ -0,0 +1,103 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: {{ include "goldpinger.fullname" . }}
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
spec:
{{- with .Values.updateStrategy }}
updateStrategy:
{{- toYaml . | nindent 4 }}
{{- end }}
selector:
matchLabels:
{{- include "goldpinger.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{ toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "goldpinger.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{ toYaml . | nindent 8 }}
{{- end }}
spec:
priorityClassName: {{ .Values.priorityClassName }}
serviceAccountName: {{ include "goldpinger.serviceAccountName" . }}
{{- if .Values.image.pullSecrets }}
imagePullSecrets:
{{- range .Values.image.pullSecrets }}
- name: {{ . }}
{{- end }}
{{- end }}
containers:
- name: goldpinger-daemon
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
volumeMounts:
- name: zap
mountPath: /config
env:
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "{{ .Values.goldpinger.port }}"
- name: LABEL_SELECTOR
value: "app.kubernetes.io/name={{ include "goldpinger.name" . }}"
{{- if .Values.extraEnv -}}
{{ toYaml .Values.extraEnv | nindent 12 }}
{{- end }}
{{- with .Values.containerSecurityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
ports:
- name: http
containerPort: {{ .Values.goldpinger.port }}
protocol: TCP
{{- range $k := .Values.extraEnv }}
{{- if and (eq $k.name "USE_HOST_IP") (eq $k.value "true") }}
hostPort: {{ $.Values.goldpinger.port }}
{{- end }}
{{- end }}
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumes:
- name: zap
configMap:
name: {{ include "goldpinger.fullname" . }}-zap
{{- range $k := .Values.extraEnv }}
{{- if and (eq $k.name "USE_HOST_IP") (eq $k.value "true") }}
hostNetwork: true
{{- end }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.podSecurityContext }}
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,61 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "goldpinger.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,19 @@
{{- if .Values.prometheusRule.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: {{ template "goldpinger.fullname" . }}
{{- if .Values.prometheusRule.namespace }}
namespace: {{ .Values.prometheusRule.namespace }}
{{- else }}
namespace: {{ .Release.Namespace | quote }}
{{- end }}
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
spec:
{{- with .Values.prometheusRule.rules }}
groups:
- name: {{ template "goldpinger.name" $ }}
rules: {{- tpl (toYaml .) $ | nindent 8 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,20 @@
{{- if or .Values.podSecurityPolicy.enabled (not .Values.rbac.clusterscoped) }}
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "goldpinger.fullname" . }}-pod-security-policy
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
rules:
{{- if not .Values.rbac.clusterscoped }}
- apiGroups: [""]
resources: ["pods"]
verbs: ["list"]
{{- end }}
{{- if .Values.podSecurityPolicy.enabled }}
- apiGroups: ["extensions"]
resources: ["podsecuritypolicies"]
resourceNames: [{{ .Values.podSecurityPolicy.policyName | quote }}]
verbs: ["use"]
{{- end }}
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- if or .Values.podSecurityPolicy.enabled (not .Values.rbac.clusterscoped) }}
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "goldpinger.fullname" . }}-pod-security-policy
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
roleRef:
kind: Role
name: {{ include "goldpinger.fullname" . }}-pod-security-policy
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: {{ include "goldpinger.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "goldpinger.fullname" . }}
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
{{- with .Values.service.labels }}
{{ toYaml . | indent 4 }}
{{- end }}
{{- with .Values.service.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.goldpinger.port }}
protocol: TCP
name: http
selector:
{{- include "goldpinger.selectorLabels" . | nindent 4 }}
{{- if .Values.service.loadBalancerSourceRanges }}
loadBalancerSourceRanges:
{{- toYaml .Values.service.loadBalancerSourceRanges | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,8 @@
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "goldpinger.serviceAccountName" . }}
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,32 @@
{{- if .Values.serviceMonitor.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "goldpinger.fullname" . }}
{{- if .Values.serviceMonitor.namespace }}
namespace: {{ .Values.serviceMonitor.namespace }}
{{- end }}
labels:
{{- include "goldpinger.labels" . | nindent 4 }}
{{- range $key, $value := .Values.serviceMonitor.selector }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
endpoints:
- port: http
interval: {{ .Values.serviceMonitor.interval }}
{{- if .Values.serviceMonitor.honorLabels }}
honorLabels: true
{{- end }}
{{- with .Values.serviceMonitor.metricRelabelings }}
metricRelabelings:
{{- toYaml . | nindent 8 }}
{{- end }}
jobLabel: name
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}
selector:
matchLabels:
{{- include "goldpinger.selectorLabels" . | nindent 6 }}
{{- end -}}

View File

@@ -0,0 +1,166 @@
# Default values for goldpinger.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
repository: bloomberg/goldpinger
# Overrides the image tag whose default is the chart appVersion.
tag: ""
pullPolicy: IfNotPresent
## Optionally specify an array of imagePullSecrets.
## Secrets must be manually created in the namespace.
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
##
# pullSecrets:
# - myRegistryKeySecretName
rbac:
create: true
clusterscoped: true
serviceAccount:
create: true
name:
goldpinger:
port: 8080
zapConfig: |
{
"level": "info",
"encoding": "json",
"outputPaths": [
"stdout"
],
"errorOutputPaths": [
"stderr"
],
"initialFields": {
},
"encoderConfig": {
"messageKey": "message",
"levelKey": "level",
"levelEncoder": "lowercase",
"timeKey": "ts",
"timeEncoder": "ISO8601",
"callerKey": "caller",
"callerEncoder": "Short"
}
}
extraEnv: []
service:
type: ClusterIP
port: 8081
annotations: {}
labels: {}
loadBalancerSourceRanges: {}
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
## Set a priorityClassName for the pod. If left blank a default priority will be set.
priorityClassName:
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
podAnnotations: {}
podLabels: {}
updateStrategy: {}
# type: RollingUpdate
# rollingUpdate:
# maxUnavailable: 1
## Node labels for pod assignment
## Ref: https://kubernetes.io/docs/user-guide/node-selection/
##
nodeSelector: {}
## Tolerations for pod assignment
## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []
## Affinity for pod assignment
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
##
affinity: {}
## Enable this if pod security policy enabled in your cluster
## It will bind ServiceAccount with unrestricted podSecurityPolicy
## Ref: https://kubernetes.io/docs/concepts/policy/pod-security-policy/
podSecurityPolicy:
enabled: false
policyName: unrestricted-psp
## Set security context of the goldpinger container
## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
containerSecurityContext:
capabilities:
drop:
- ALL
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
## Set security context of the pod
## Ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
serviceMonitor:
enabled: false
selector:
prometheus: "kube-prometheus"
# namespace: monitoring
interval: 30s
# honorLabels: true
metricRelabelings: []
# - action: drop
# source_labels: [__name__]
# regex: goldpinger_peers_response_time_s_bucket
## Custom PrometheusRule to be defined
## ref: https://github.com/coreos/prometheus-operator#customresourcedefinitions
prometheusRule:
enabled: false
rules:
- alert: goldpinger_nodes_unhealthy
expr: |
sum(goldpinger_nodes_health_total{job="{{ template "goldpinger.fullname" . }}", status="unhealthy"})
BY (instance, goldpinger_instance) > 0
for: 5m
annotations:
description: |
Goldpinger instance {{ "{{ $labels.goldpinger_instance }}" }} has been reporting unhealthy nodes for at least 5 minutes.
summary: Instance {{ "{{ $labels.instance }}" }} down
labels:
severity: warning

View File

@@ -15,17 +15,25 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
"strings"
"time"
"github.com/go-openapi/loads"
"go.uber.org/zap"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/utils/net"
"github.com/bloomberg/goldpinger/pkg/goldpinger"
"github.com/bloomberg/goldpinger/pkg/restapi"
"github.com/bloomberg/goldpinger/pkg/restapi/operations"
"github.com/bloomberg/goldpinger/v3/pkg/goldpinger"
"github.com/bloomberg/goldpinger/v3/pkg/restapi"
"github.com/bloomberg/goldpinger/v3/pkg/restapi/operations"
flags "github.com/jessevdk/go-flags"
)
@@ -34,14 +42,32 @@ var (
Version, Build string
)
func getLogger(zapconfigpath string) (*zap.Logger, error) {
var logger *zap.Logger
var err error
zapconfigJSON, err := ioutil.ReadFile(zapconfigpath)
if err != nil {
return nil, fmt.Errorf("Could not read zap config file: %w", err)
}
var cfg zap.Config
if err := json.Unmarshal(zapconfigJSON, &cfg); err != nil {
return nil, fmt.Errorf("Could not read zap config as json: %w", err)
}
logger, err = cfg.Build()
if err != nil {
return nil, fmt.Errorf("Could not build zap config: %w", err)
}
return logger, nil
}
func main() {
log.Println("Goldpinger version:", Version, "build:", Build)
// load embedded swagger file
swaggerSpec, err := loads.Analyzed(restapi.SwaggerJSON, "")
if err != nil {
log.Fatalln(err)
log.Fatalf("Could not parse swagger: %v", err)
}
// create new service API
@@ -58,7 +84,7 @@ func main() {
for _, optsGroup := range api.CommandLineOptionsGroups {
_, err := parser.AddGroup(optsGroup.ShortDescription, optsGroup.LongDescription, optsGroup.Options)
if err != nil {
log.Fatalln(err)
log.Fatalf("Could not add flag group: %v", err)
}
}
@@ -72,22 +98,49 @@ func main() {
os.Exit(code)
}
// Configure logger
logger, err := getLogger(goldpinger.GoldpingerConfig.ZapConfigPath)
if err != nil {
var errDev error
logger, errDev = zap.NewDevelopment()
if errDev != nil {
log.Fatalf("Could not build a development logger: %v", errDev)
}
logger.Warn("Logger could not be built, defaulting to development settings", zap.String("error", fmt.Sprintf("%v", err)))
}
defer logger.Sync()
undo := zap.RedirectStdLog(logger)
defer undo()
logger.Info("Goldpinger", zap.String("version", Version), zap.String("build", Build))
if goldpinger.GoldpingerConfig.Namespace == nil {
goldpinger.GoldpingerConfig.Namespace = &goldpinger.PodNamespace
} else {
logger.Info("Using configured namespace", zap.String("namespace", *goldpinger.GoldpingerConfig.Namespace))
}
// make a kubernetes client
var config *rest.Config
if goldpinger.GoldpingerConfig.KubeConfigPath == "" {
log.Println("Kubeconfig not specified, trying to use in cluster config")
logger.Info("Kubeconfig not specified, trying to use in cluster config")
config, err = rest.InClusterConfig()
} else {
log.Println("Kubeconfig specified in ", goldpinger.GoldpingerConfig.KubeConfigPath)
logger.Info("Kubeconfig specified", zap.String("path", goldpinger.GoldpingerConfig.KubeConfigPath))
config, err = clientcmd.BuildConfigFromFlags("", goldpinger.GoldpingerConfig.KubeConfigPath)
}
if err != nil {
log.Fatalln("Error getting config ", err.Error())
logger.Fatal("Error getting config ", zap.Error(err))
}
// communicate to kube-apiserver with protobuf
config.AcceptContentTypes = strings.Join([]string{runtime.ContentTypeProtobuf, runtime.ContentTypeJSON}, ",")
config.ContentType = runtime.ContentTypeProtobuf
// create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatalln("kubernetes.NewForConfig error ", err.Error())
logger.Fatal("kubernetes.NewForConfig error ", zap.Error(err))
}
goldpinger.GoldpingerConfig.KubernetesClient = clientset
@@ -96,13 +149,47 @@ func main() {
goldpinger.GoldpingerConfig.Port = server.Port
}
if goldpinger.GoldpingerConfig.PodIP == "" {
logger.Info("PodIP not set: pinging all pods")
}
if goldpinger.GoldpingerConfig.PingNumber == 0 {
logger.Info("--ping-number set to 0: pinging all pods")
}
if goldpinger.GoldpingerConfig.IPVersions == nil || len(goldpinger.GoldpingerConfig.IPVersions) == 0 {
logger.Info("IPVersions not set: settings to 4 (IPv4)")
goldpinger.GoldpingerConfig.IPVersions = []string{"4"}
}
if len(goldpinger.GoldpingerConfig.IPVersions) > 1 {
logger.Warn("Multiple IP versions not supported. Will use first version specified as default", zap.Strings("IPVersions", goldpinger.GoldpingerConfig.IPVersions))
}
if goldpinger.GoldpingerConfig.IPVersions[0] != string(net.IPv4) && goldpinger.GoldpingerConfig.IPVersions[0] != string(net.IPv6) {
logger.Error("Unknown IP version specified: expected values are 4 or 6", zap.Strings("IPVersions", goldpinger.GoldpingerConfig.IPVersions))
}
// Handle deprecated flags
if int(goldpinger.GoldpingerConfig.PingTimeout) == 0 {
logger.Warn("ping-timeout-ms is deprecated in favor of ping-timeout and will be removed in the future",
zap.Int64("ping-timeout-ms", goldpinger.GoldpingerConfig.PingTimeoutMs))
goldpinger.GoldpingerConfig.PingTimeout = time.Duration(goldpinger.GoldpingerConfig.PingTimeoutMs) * time.Millisecond
}
if int(goldpinger.GoldpingerConfig.CheckTimeout) == 0 {
logger.Warn("check-timeout-ms is deprecated in favor of check-timeout and will be removed in the future",
zap.Int64("check-timeout-ms", goldpinger.GoldpingerConfig.CheckTimeoutMs))
goldpinger.GoldpingerConfig.CheckTimeout = time.Duration(goldpinger.GoldpingerConfig.CheckTimeoutMs) * time.Millisecond
}
if int(goldpinger.GoldpingerConfig.CheckAllTimeout) == 0 {
logger.Warn("check-all-timeout-ms is deprecated in favor of check-all-timeout will be removed in the future",
zap.Int64("check-all-timeout-ms", goldpinger.GoldpingerConfig.CheckAllTimeoutMs))
goldpinger.GoldpingerConfig.CheckAllTimeout = time.Duration(goldpinger.GoldpingerConfig.CheckAllTimeoutMs) * time.Millisecond
}
server.ConfigureAPI()
goldpinger.StartUpdater()
log.Println("All good, starting serving the API")
logger.Info("All good, starting serving the API")
// serve API
if err := server.Serve(); err != nil {
log.Fatalln(err)
logger.Fatal("Error serving the API", zap.Error(err))
}
}

21
config/zap.json Normal file
View File

@@ -0,0 +1,21 @@
{
"level": "info",
"encoding": "json",
"outputPaths": [
"stdout"
],
"errorOutputPaths": [
"stderr"
],
"initialFields": {
},
"encoderConfig": {
"messageKey": "message",
"levelKey": "level",
"levelEncoder": "lowercase",
"timeKey": "ts",
"timeEncoder": "ISO8601",
"callerKey": "caller",
"callerEncoder": "Short"
}
}

52
docker-bake.hcl Normal file
View File

@@ -0,0 +1,52 @@
# ref: https://docs.docker.com/build/bake/reference/
# ref: https://github.com/docker/metadata-action?tab=readme-ov-file#bake-definition
target "docker-metadata-action" {
tags = ["goldpinger:latest"]
}
group "default" {
targets = ["linux-simple"]
}
group "ci" {
targets = ["linux-simple", "linux-vendor", "windows-nanoserver-ltsc2019", "windows-nanoserver-ltsc2022"]
}
target "linux-simple" {
inherits = ["docker-metadata-action"]
tags = "${formatlist("%s-linux", target.docker-metadata-action.tags)}"
platforms = ["linux/amd64", "linux/arm64"]
target = "simple"
}
target "linux-vendor" {
inherits = ["docker-metadata-action"]
tags = "${formatlist("%s-vendor", target.docker-metadata-action.tags)}"
platforms = ["linux/amd64", "linux/arm64"]
target = "vendor"
}
target "windows-nanoserver-ltsc2019" {
inherits = ["docker-metadata-action"]
tags = "${formatlist("%s-windows-ltsc2019", target.docker-metadata-action.tags)}"
platforms = ["windows/amd64"]
target = "windows"
args = {
WINDOWS_BASE_IMAGE = "mcr.microsoft.com/windows/nanoserver:ltsc2019"
}
}
target "windows-nanoserver-ltsc2022" {
inherits = ["docker-metadata-action"]
tags = "${formatlist("%s-windows-ltsc2022", target.docker-metadata-action.tags)}"
platforms = ["windows/amd64"]
target = "windows"
args = {
WINDOWS_BASE_IMAGE = "mcr.microsoft.com/windows/nanoserver:ltsc2022"
}
}

84
extras/check_reachability.sh Executable file
View File

@@ -0,0 +1,84 @@
#!/bin/bash
# This is a simple script, used in the Tilt GitHub Action
# to validate that all worker nodes can inter-communicate.
function print_help() {
echo "Usage: $0 [EXPECTED_HOST_COUNT]"
echo "Arguments:"
echo " EXPECTED_HOST_COUNT: The number of expected hosts in the Goldpinger output."
echo "Examples:"
echo " $0 2"
}
if [ "$#" -ne 1 ]; then
echo "Error: Invalid number of arguments."
print_help
exit 1
fi
if ! [[ $1 =~ ^[0-9]+$ ]]; then
echo "Error: EXPECTED_HOST_COUNT must be a number."
print_help
exit 1
fi
expected_host_count=$1
goldpinger_output=""
retry_count=0
host_count=0
while :; do
if [ "$retry_count" -ge 20 ]; then
echo "Error: Failed to fetch Goldpinger output after 10 attempts."
exit 1
fi
echo "Sleeping for 8s..."
let retry_count++
sleep 8
echo "Attempt $((retry_count)) to fetch Goldpinger output."
goldpinger_output=$(curl -s http://localhost:8080/check_all)
echo "Goldpinger output: $goldpinger_output"
if [ "$goldpinger_output" == "null" ] || [ -z "$goldpinger_output" ]; then
echo "Goldpinger output is null or empty, retrying..."
continue
fi
host_count=$(echo "$goldpinger_output" | jq '.hosts | length')
if [ "$host_count" -ne "$expected_host_count" ]; then
echo "Goldpinger has not identified all hosts, retrying..."
continue
fi
for host in $(echo $goldpinger_output | jq -r '.responses | keys[]'); do
checksForPod=$(echo "$goldpinger_output" | jq -r --arg host "$host" '.responses[$host].response.podResults | length')
if [ "$checksForPod" -ne "$expected_host_count" ]; then
echo "Check for $host is not OK, retrying..."
continue 2
fi
done
break
done
all_hosts_can_talk=true
for host in $(echo $goldpinger_output | jq -r '.responses | keys[]'); do
for target in $(echo $goldpinger_output | jq -r --arg host $host '.responses[$host].response.podResults | keys[]'); do
ok=$(echo $goldpinger_output | jq -r --arg host $host --arg target $target '.responses[$host].response.podResults[$target].OK')
if [ "$ok" != "true" ]; then
all_hosts_can_talk=false
break 2
fi
done
done
if [[ $host_count -eq $expected_host_count ]] && [[ $all_hosts_can_talk == "true" ]]; then
echo "Validation successful. There are $expected_host_count hosts and they can talk to each other."
else
echo "Validation failed. Expected $expected_host_count hosts but found $host_count, or not all hosts can talk to each other."
echo "Goldpinger Output: $goldpinger_output"
exit 1
fi

BIN
extras/dns-screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

View File

@@ -1,49 +1,117 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: goldpinger-serviceaccount
namespace: default
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: goldpinger
namespace: default
labels:
app: goldpinger
spec:
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: goldpinger
version: "1.0.0"
template:
metadata:
labels:
app: goldpinger
version: "1.0.0"
spec:
serviceAccount: "goldpinger-serviceaccount"
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: goldpinger
env:
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "80"
value: "8080"
# injecting real hostname will make for easier to understand graphs/metrics
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
image: "docker.io/mynamespace-replaceme/goldpinger:1.0.0"
# podIP is used to select a randomized subset of nodes to ping.
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
image: "docker.io/bloomberg/goldpinger:v3.0.0"
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
resources:
limits:
memory: 80Mi
requests:
cpu: 1m
memory: 40Mi
ports:
- containerPort: 80
- containerPort: 8080
name: http
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: goldpinger
namespace: default
labels:
app: goldpinger
spec:
type: NodePort
ports:
- port: 80
- port: 8080
nodePort: 30080
name: http
selector:
app: goldpinger
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: goldpinger-clusterrole
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- list
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: goldpinger-clusterrolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: goldpinger-clusterrole
subjects:
- kind: ServiceAccount
name: goldpinger-serviceaccount
namespace: default

View File

@@ -5,20 +5,21 @@ metadata:
name: goldpinger
labels:
app: goldpinger
version: "1.0.0"
spec:
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: goldpinger
version: "1.0.0"
template:
metadata:
labels:
app: goldpinger
version: "1.0.0"
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
# if you'd like to use a secret to inject a kubeconfig, you can do it like this
volumes:
- name: kubeconfig
@@ -30,11 +31,11 @@ spec:
- name: HOST
value: "0.0.0.0"
- name: PORT
value: "80"
value: "8080"
# kubeconfig needs to match the location of what's injected in the secret
# if not specified goldpinger will default to using in-cluster config
- name: KUBECONFIG
value: "./kube/config"
value: "/.kube/config"
# refresh interval (seconds) tells goldpinger to call every other instance with that frequency (set to 0 to disable)
- name: REFRESH_INTERVAL
value: "30"
@@ -43,10 +44,37 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
image: "docker.io/mynamespace-replaceme/goldpinger:1.0.0"
# podIP is used to select randomized subset of nodes to ping.
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
image: "docker.io/bloomberg/goldpinger:v3.0.0"
imagePullPolicy: Always
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
resources:
limits:
memory: 80Mi
requests:
cpu: 1m
memory: 40Mi
ports:
- containerPort: 80
- containerPort: 8080
name: http
readinessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
volumeMounts:
- mountPath: /.kube/
name: kubeconfig
@@ -61,7 +89,7 @@ metadata:
spec:
type: NodePort
ports:
- port: 80
- port: 8080
nodePort: 30080
name: http
selector:

View File

@@ -33,7 +33,7 @@
"rgba(237, 129, 40, 0.89)",
"rgba(245, 54, 54, 0.9)"
],
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"format": "none",
@@ -113,7 +113,7 @@
"rgba(237, 129, 40, 0.89)",
"rgba(245, 54, 54, 0.9)"
],
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"format": "none",
@@ -199,7 +199,7 @@
"value": "avg"
}
],
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fontSize": "100%",
@@ -256,7 +256,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -340,7 +340,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -436,7 +436,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -519,7 +519,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -602,7 +602,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -697,7 +697,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -781,7 +781,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -865,7 +865,7 @@
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "K8S",
"datasource": "$datasource",
"editable": true,
"error": false,
"fill": 1,
@@ -958,10 +958,25 @@
"tags": [],
"templating": {
"list": [
{
"current": {
"text": "prometheus",
"value": "prometheus"
},
"hide": 0,
"label": "datasource",
"name": "datasource",
"options": [],
"query": "prometheus",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"allValue": ".*",
"current": {},
"datasource": "K8S",
"datasource": "$datasource",
"hide": 0,
"includeAll": true,
"label": "Instance",
@@ -981,7 +996,7 @@
{
"allValue": ".*",
"current": {},
"datasource": "K8S",
"datasource": "$datasource",
"hide": 0,
"includeAll": true,
"label": "Call Type",

BIN
extras/screenshot-big.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 KiB

BIN
extras/screenshot-ipv6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 KiB

97
go.mod Normal file
View File

@@ -0,0 +1,97 @@
module github.com/bloomberg/goldpinger/v3
go 1.25.0
require (
github.com/cespare/xxhash v1.1.0
github.com/go-openapi/errors v0.22.6
github.com/go-openapi/loads v0.23.2
github.com/go-openapi/runtime v0.29.2
github.com/go-openapi/spec v0.22.3
github.com/go-openapi/strfmt v0.25.0
github.com/go-openapi/swag v0.25.4
github.com/go-openapi/validate v0.25.1
github.com/jessevdk/go-flags v1.6.1
github.com/prometheus/client_golang v1.23.2
github.com/stuartnelson3/go-rendezvous v0.2.0
go.uber.org/zap v1.27.1
golang.org/x/image v0.35.0
golang.org/x/net v0.49.0
k8s.io/api v0.35.0
k8s.io/apimachinery v0.35.0
k8s.io/client-go v0.35.0
k8s.io/utils v0.0.0-20260108192941-914a6e750570
)
require (
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.24.2 // indirect
github.com/go-openapi/jsonpointer v0.22.4 // indirect
github.com/go-openapi/jsonreference v0.21.4 // indirect
github.com/go-openapi/swag/cmdutils v0.25.4 // indirect
github.com/go-openapi/swag/conv v0.25.4 // indirect
github.com/go-openapi/swag/fileutils v0.25.4 // indirect
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
github.com/go-openapi/swag/loading v0.25.4 // indirect
github.com/go-openapi/swag/mangling v0.25.4 // indirect
github.com/go-openapi/swag/netutils v0.25.4 // indirect
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.7.1 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.9.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.19.2 // indirect
github.com/spf13/pflag v1.0.10 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.mongodb.org/mongo-driver v1.17.7 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.39.0 // indirect
go.opentelemetry.io/otel/metric v1.39.0 // indirect
go.opentelemetry.io/otel/trace v1.39.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/oauth2 v0.34.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/term v0.39.0 // indirect
golang.org/x/text v0.33.0 // indirect
golang.org/x/time v0.14.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)

337
go.sum Normal file
View File

@@ -0,0 +1,337 @@
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/emicklei/go-restful/v3 v3.12.0 h1:y2DdzBAURM29NFF94q6RaY4vjIH1rtwDapwQtU84iWk=
github.com/emicklei/go-restful/v3 v3.12.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/analysis v0.24.2 h1:6p7WXEuKy1llDgOH8FooVeO+Uq2za9qoAOq4ZN08B50=
github.com/go-openapi/analysis v0.24.2/go.mod h1:x27OOHKANE0lutg2ml4kzYLoHGMKgRm1Cj2ijVOjJuE=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
github.com/go-openapi/errors v0.22.6 h1:eDxcf89O8odEnohIXwEjY1IB4ph5vmbUsBMsFNwXWPo=
github.com/go-openapi/errors v0.22.6/go.mod h1:z9S8ASTUqx7+CP1Q8dD8ewGH/1JWFFLX/2PmAYNQLgk=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4=
github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8=
github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4=
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
github.com/go-openapi/loads v0.23.2 h1:rJXAcP7g1+lWyBHC7iTY+WAF0rprtM+pm8Jxv1uQJp4=
github.com/go-openapi/loads v0.23.2/go.mod h1:IEVw1GfRt/P2Pplkelxzj9BYFajiWOtY2nHZNj4UnWY=
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
github.com/go-openapi/runtime v0.29.2 h1:UmwSGWNmWQqKm1c2MGgXVpC2FTGwPDQeUsBMufc5Yj0=
github.com/go-openapi/runtime v0.29.2/go.mod h1:biq5kJXRJKBJxTDJXAa00DOTa/anflQPhT0/wmjuy+0=
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
github.com/go-openapi/spec v0.22.3 h1:qRSmj6Smz2rEBxMnLRBMeBWxbbOvuOoElvSvObIgwQc=
github.com/go-openapi/spec v0.22.3/go.mod h1:iIImLODL2loCh3Vnox8TY2YWYJZjMAKYyLH2Mu8lOZs=
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
github.com/go-openapi/strfmt v0.25.0 h1:7R0RX7mbKLa9EYCTHRcCuIPcaqlyQiWNPTXwClK0saQ=
github.com/go-openapi/strfmt v0.25.0/go.mod h1:nNXct7OzbwrMY9+5tLX4I21pzcmE6ccMGXl3jFdPfn8=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/swag v0.25.4 h1:OyUPUFYDPDBMkqyxOTkqDYFnrhuhi9NR6QVUvIochMU=
github.com/go-openapi/swag v0.25.4/go.mod h1:zNfJ9WZABGHCFg2RnY0S4IOkAcVTzJ6z2Bi+Q4i6qFQ=
github.com/go-openapi/swag/cmdutils v0.25.4 h1:8rYhB5n6WawR192/BfUu2iVlxqVR9aRgGJP6WaBoW+4=
github.com/go-openapi/swag/cmdutils v0.25.4/go.mod h1:pdae/AFo6WxLl5L0rq87eRzVPm/XRHM3MoYgRMvG4A0=
github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4=
github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU=
github.com/go-openapi/swag/fileutils v0.25.4 h1:2oI0XNW5y6UWZTC7vAxC8hmsK/tOkWXHJQH4lKjqw+Y=
github.com/go-openapi/swag/fileutils v0.25.4/go.mod h1:cdOT/PKbwcysVQ9Tpr0q20lQKH7MGhOEb6EwmHOirUk=
github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI=
github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA=
github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY=
github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s=
github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE=
github.com/go-openapi/swag/mangling v0.25.4 h1:2b9kBJk9JvPgxr36V23FxJLdwBrpijI26Bx5JH4Hp48=
github.com/go-openapi/swag/mangling v0.25.4/go.mod h1:6dxwu6QyORHpIIApsdZgb6wBk/DPU15MdyYj/ikn0Hg=
github.com/go-openapi/swag/netutils v0.25.4 h1:Gqe6K71bGRb3ZQLusdI8p/y1KLgV4M/k+/HzVSqT8H0=
github.com/go-openapi/swag/netutils v0.25.4/go.mod h1:m2W8dtdaoX7oj9rEttLyTeEFFEBvnAx9qHd5nJEBzYg=
github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8=
github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw=
github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw=
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/go-openapi/validate v0.25.1 h1:sSACUI6Jcnbo5IWqbYHgjibrhhmt3vR6lCzKZnmAgBw=
github.com/go-openapi/validate v0.25.1/go.mod h1:RMVyVFYte0gbSTaZ0N4KmTn6u/kClvAFp+mAVfS/DQc=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c=
github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8=
github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.52.3 h1:5f8uj6ZwHSscOGNdIQg6OiZv/ybiK2CO2q2drVZAQSA=
github.com/prometheus/common v0.52.3/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.13.0 h1:GqzLlQyfsPbaEHaQkO7tbDlriv/4o5Hudv6OXHGKX7o=
github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43ZKY6tow0Y1g=
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stuartnelson3/go-rendezvous v0.2.0 h1:H5IexrsptBzCMQEjTRrNH20MVXGqpFf1JUCPglaxd6I=
github.com/stuartnelson3/go-rendezvous v0.2.0/go.mod h1:njfgP6zISyRnZ3iQN13NSEILfSNLN4ysxBoGxHs5PJ0=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc=
go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.mongodb.org/mongo-driver v1.17.7 h1:a9w+U3Vt67eYzcfq3k/OAv284/uUUkL0uP75VE5rCOU=
go.mongodb.org/mongo-driver v1.17.7/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k=
go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg=
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA=
go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s=
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM=
go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I=
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I=
golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY=
k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA=
k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8=
k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE=
k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3 h1:SbdLaI6mM6ffDSJCadEaD4IkuPzepLDGlkd2xV0t1uA=
k8s.io/kube-openapi v0.0.0-20240411171206-dc4e619f62f3/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4 h1:HhDfevmPS+OalTjQRKbTHppRIz01AWi8s45TMXStgYY=
k8s.io/kube-openapi v0.0.0-20260127142750-a19766b6e2d4/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY=
k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20260108192941-914a6e750570 h1:JT4W8lsdrGENg9W+YwwdLJxklIuKWdRm+BC+xt33FOY=
k8s.io/utils v0.0.0-20260108192941-914a6e750570/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
sigs.k8s.io/structured-merge-diff/v6 v6.3.1 h1:JrhdFMqOd/+3ByqlP2I45kTOZmTRLBUm5pvRjeheg7E=
sigs.k8s.io/structured-merge-diff/v6 v6.3.1/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=

17
kind.yaml Normal file
View File

@@ -0,0 +1,17 @@
apiVersion: ctlptl.dev/v1alpha1
kind: Registry
name: ctlptl-registry
port: 20021
---
apiVersion: ctlptl.dev/v1alpha1
kind: Cluster
product: kind
registry: ctlptl-registry
kindV1Alpha4Cluster:
name: goldpinger-test
nodes:
- role: control-plane
- role: worker
- role: worker
networking:
apiServerPort: 30022

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package client
@@ -20,12 +6,10 @@ package client
// Editing this file might prove futile when you re-run the swagger generate command
import (
"github.com/bloomberg/goldpinger/v3/pkg/client/operations"
"github.com/go-openapi/runtime"
httptransport "github.com/go-openapi/runtime/client"
strfmt "github.com/go-openapi/strfmt"
"github.com/bloomberg/goldpinger/pkg/client/operations"
"github.com/go-openapi/strfmt"
)
// Default goldpinger HTTP client.
@@ -70,9 +54,7 @@ func New(transport runtime.ClientTransport, formats strfmt.Registry) *Goldpinger
cli := new(Goldpinger)
cli.Transport = transport
cli.Operations = operations.New(transport, formats)
return cli
}
@@ -117,7 +99,7 @@ func (cfg *TransportConfig) WithSchemes(schemes []string) *TransportConfig {
// Goldpinger is a client for goldpinger
type Goldpinger struct {
Operations *operations.Client
Operations operations.ClientService
Transport runtime.ClientTransport
}
@@ -125,7 +107,5 @@ type Goldpinger struct {
// SetTransport changes the transport on the client and all its subresources
func (c *Goldpinger) SetTransport(transport runtime.ClientTransport) {
c.Transport = transport
c.Operations.SetTransport(transport)
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -20,59 +6,56 @@ package operations
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"golang.org/x/net/context"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
strfmt "github.com/go-openapi/strfmt"
"github.com/go-openapi/strfmt"
)
// NewCheckAllPodsParams creates a new CheckAllPodsParams object
// with the default values initialized.
// NewCheckAllPodsParams creates a new CheckAllPodsParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewCheckAllPodsParams() *CheckAllPodsParams {
return &CheckAllPodsParams{
timeout: cr.DefaultTimeout,
}
}
// NewCheckAllPodsParamsWithTimeout creates a new CheckAllPodsParams object
// with the default values initialized, and the ability to set a timeout on a request
// with the ability to set a timeout on a request.
func NewCheckAllPodsParamsWithTimeout(timeout time.Duration) *CheckAllPodsParams {
return &CheckAllPodsParams{
timeout: timeout,
}
}
// NewCheckAllPodsParamsWithContext creates a new CheckAllPodsParams object
// with the default values initialized, and the ability to set a context for a request
// with the ability to set a context for a request.
func NewCheckAllPodsParamsWithContext(ctx context.Context) *CheckAllPodsParams {
return &CheckAllPodsParams{
Context: ctx,
}
}
// NewCheckAllPodsParamsWithHTTPClient creates a new CheckAllPodsParams object
// with the default values initialized, and the ability to set a custom HTTPClient for a request
// with the ability to set a custom HTTPClient for a request.
func NewCheckAllPodsParamsWithHTTPClient(client *http.Client) *CheckAllPodsParams {
return &CheckAllPodsParams{
HTTPClient: client,
}
}
/*CheckAllPodsParams contains all the parameters to send to the API endpoint
for the check all pods operation typically these are written to a http.Request
/* CheckAllPodsParams contains all the parameters to send to the API endpoint
for the check all pods operation.
Typically these are written to a http.Request.
*/
type CheckAllPodsParams struct {
timeout time.Duration
@@ -80,6 +63,21 @@ type CheckAllPodsParams struct {
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the check all pods params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *CheckAllPodsParams) WithDefaults() *CheckAllPodsParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the check all pods params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *CheckAllPodsParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the check all pods params
func (o *CheckAllPodsParams) WithTimeout(timeout time.Duration) *CheckAllPodsParams {
o.SetTimeout(timeout)

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -24,10 +10,9 @@ import (
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
strfmt "github.com/go-openapi/strfmt"
models "github.com/bloomberg/goldpinger/pkg/models"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// CheckAllPodsReader is a Reader for the CheckAllPods structure.
@@ -38,16 +23,14 @@ type CheckAllPodsReader struct {
// ReadResponse reads a server response into the received o.
func (o *CheckAllPodsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewCheckAllPodsOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
default:
return nil, runtime.NewAPIError("unknown error", response, response.Code())
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
}
@@ -56,7 +39,7 @@ func NewCheckAllPodsOK() *CheckAllPodsOK {
return &CheckAllPodsOK{}
}
/*CheckAllPodsOK handles this case with default header values.
/* CheckAllPodsOK describes a response with status code 200, with default header values.
Success, return response
*/
@@ -67,6 +50,9 @@ type CheckAllPodsOK struct {
func (o *CheckAllPodsOK) Error() string {
return fmt.Sprintf("[GET /check_all][%d] checkAllPodsOK %+v", 200, o.Payload)
}
func (o *CheckAllPodsOK) GetPayload() *models.CheckAllResults {
return o.Payload
}
func (o *CheckAllPodsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -20,59 +6,56 @@ package operations
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"golang.org/x/net/context"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
strfmt "github.com/go-openapi/strfmt"
"github.com/go-openapi/strfmt"
)
// NewCheckServicePodsParams creates a new CheckServicePodsParams object
// with the default values initialized.
// NewCheckServicePodsParams creates a new CheckServicePodsParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewCheckServicePodsParams() *CheckServicePodsParams {
return &CheckServicePodsParams{
timeout: cr.DefaultTimeout,
}
}
// NewCheckServicePodsParamsWithTimeout creates a new CheckServicePodsParams object
// with the default values initialized, and the ability to set a timeout on a request
// with the ability to set a timeout on a request.
func NewCheckServicePodsParamsWithTimeout(timeout time.Duration) *CheckServicePodsParams {
return &CheckServicePodsParams{
timeout: timeout,
}
}
// NewCheckServicePodsParamsWithContext creates a new CheckServicePodsParams object
// with the default values initialized, and the ability to set a context for a request
// with the ability to set a context for a request.
func NewCheckServicePodsParamsWithContext(ctx context.Context) *CheckServicePodsParams {
return &CheckServicePodsParams{
Context: ctx,
}
}
// NewCheckServicePodsParamsWithHTTPClient creates a new CheckServicePodsParams object
// with the default values initialized, and the ability to set a custom HTTPClient for a request
// with the ability to set a custom HTTPClient for a request.
func NewCheckServicePodsParamsWithHTTPClient(client *http.Client) *CheckServicePodsParams {
return &CheckServicePodsParams{
HTTPClient: client,
}
}
/*CheckServicePodsParams contains all the parameters to send to the API endpoint
for the check service pods operation typically these are written to a http.Request
/* CheckServicePodsParams contains all the parameters to send to the API endpoint
for the check service pods operation.
Typically these are written to a http.Request.
*/
type CheckServicePodsParams struct {
timeout time.Duration
@@ -80,6 +63,21 @@ type CheckServicePodsParams struct {
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the check service pods params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *CheckServicePodsParams) WithDefaults() *CheckServicePodsParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the check service pods params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *CheckServicePodsParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the check service pods params
func (o *CheckServicePodsParams) WithTimeout(timeout time.Duration) *CheckServicePodsParams {
o.SetTimeout(timeout)

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -24,10 +10,9 @@ import (
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
strfmt "github.com/go-openapi/strfmt"
models "github.com/bloomberg/goldpinger/pkg/models"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// CheckServicePodsReader is a Reader for the CheckServicePods structure.
@@ -38,16 +23,14 @@ type CheckServicePodsReader struct {
// ReadResponse reads a server response into the received o.
func (o *CheckServicePodsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewCheckServicePodsOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
default:
return nil, runtime.NewAPIError("unknown error", response, response.Code())
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
}
@@ -56,22 +39,27 @@ func NewCheckServicePodsOK() *CheckServicePodsOK {
return &CheckServicePodsOK{}
}
/*CheckServicePodsOK handles this case with default header values.
/* CheckServicePodsOK describes a response with status code 200, with default header values.
Success, return response
*/
type CheckServicePodsOK struct {
Payload models.CheckResults
Payload *models.CheckResults
}
func (o *CheckServicePodsOK) Error() string {
return fmt.Sprintf("[GET /check][%d] checkServicePodsOK %+v", 200, o.Payload)
}
func (o *CheckServicePodsOK) GetPayload() *models.CheckResults {
return o.Payload
}
func (o *CheckServicePodsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.CheckResults)
// response payload
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}

View File

@@ -0,0 +1,126 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
)
// NewClusterHealthParams creates a new ClusterHealthParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewClusterHealthParams() *ClusterHealthParams {
return &ClusterHealthParams{
timeout: cr.DefaultTimeout,
}
}
// NewClusterHealthParamsWithTimeout creates a new ClusterHealthParams object
// with the ability to set a timeout on a request.
func NewClusterHealthParamsWithTimeout(timeout time.Duration) *ClusterHealthParams {
return &ClusterHealthParams{
timeout: timeout,
}
}
// NewClusterHealthParamsWithContext creates a new ClusterHealthParams object
// with the ability to set a context for a request.
func NewClusterHealthParamsWithContext(ctx context.Context) *ClusterHealthParams {
return &ClusterHealthParams{
Context: ctx,
}
}
// NewClusterHealthParamsWithHTTPClient creates a new ClusterHealthParams object
// with the ability to set a custom HTTPClient for a request.
func NewClusterHealthParamsWithHTTPClient(client *http.Client) *ClusterHealthParams {
return &ClusterHealthParams{
HTTPClient: client,
}
}
/* ClusterHealthParams contains all the parameters to send to the API endpoint
for the cluster health operation.
Typically these are written to a http.Request.
*/
type ClusterHealthParams struct {
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the cluster health params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *ClusterHealthParams) WithDefaults() *ClusterHealthParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the cluster health params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *ClusterHealthParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the cluster health params
func (o *ClusterHealthParams) WithTimeout(timeout time.Duration) *ClusterHealthParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the cluster health params
func (o *ClusterHealthParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the cluster health params
func (o *ClusterHealthParams) WithContext(ctx context.Context) *ClusterHealthParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the cluster health params
func (o *ClusterHealthParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the cluster health params
func (o *ClusterHealthParams) WithHTTPClient(client *http.Client) *ClusterHealthParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the cluster health params
func (o *ClusterHealthParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WriteToRequest writes these params to a swagger request
func (o *ClusterHealthParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,105 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// ClusterHealthReader is a Reader for the ClusterHealth structure.
type ClusterHealthReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *ClusterHealthReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewClusterHealthOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 418:
result := NewClusterHealthIMATeapot()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
}
// NewClusterHealthOK creates a ClusterHealthOK with default headers values
func NewClusterHealthOK() *ClusterHealthOK {
return &ClusterHealthOK{}
}
/* ClusterHealthOK describes a response with status code 200, with default header values.
Healthy cluster
*/
type ClusterHealthOK struct {
Payload *models.ClusterHealthResults
}
func (o *ClusterHealthOK) Error() string {
return fmt.Sprintf("[GET /cluster_health][%d] clusterHealthOK %+v", 200, o.Payload)
}
func (o *ClusterHealthOK) GetPayload() *models.ClusterHealthResults {
return o.Payload
}
func (o *ClusterHealthOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.ClusterHealthResults)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewClusterHealthIMATeapot creates a ClusterHealthIMATeapot with default headers values
func NewClusterHealthIMATeapot() *ClusterHealthIMATeapot {
return &ClusterHealthIMATeapot{}
}
/* ClusterHealthIMATeapot describes a response with status code 418, with default header values.
Unhealthy cluster
*/
type ClusterHealthIMATeapot struct {
Payload *models.ClusterHealthResults
}
func (o *ClusterHealthIMATeapot) Error() string {
return fmt.Sprintf("[GET /cluster_health][%d] clusterHealthIMATeapot %+v", 418, o.Payload)
}
func (o *ClusterHealthIMATeapot) GetPayload() *models.ClusterHealthResults {
return o.Payload
}
func (o *ClusterHealthIMATeapot) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.ClusterHealthResults)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}

View File

@@ -0,0 +1,126 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
)
// NewHealthzParams creates a new HealthzParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewHealthzParams() *HealthzParams {
return &HealthzParams{
timeout: cr.DefaultTimeout,
}
}
// NewHealthzParamsWithTimeout creates a new HealthzParams object
// with the ability to set a timeout on a request.
func NewHealthzParamsWithTimeout(timeout time.Duration) *HealthzParams {
return &HealthzParams{
timeout: timeout,
}
}
// NewHealthzParamsWithContext creates a new HealthzParams object
// with the ability to set a context for a request.
func NewHealthzParamsWithContext(ctx context.Context) *HealthzParams {
return &HealthzParams{
Context: ctx,
}
}
// NewHealthzParamsWithHTTPClient creates a new HealthzParams object
// with the ability to set a custom HTTPClient for a request.
func NewHealthzParamsWithHTTPClient(client *http.Client) *HealthzParams {
return &HealthzParams{
HTTPClient: client,
}
}
/* HealthzParams contains all the parameters to send to the API endpoint
for the healthz operation.
Typically these are written to a http.Request.
*/
type HealthzParams struct {
timeout time.Duration
Context context.Context
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the healthz params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *HealthzParams) WithDefaults() *HealthzParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the healthz params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *HealthzParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the healthz params
func (o *HealthzParams) WithTimeout(timeout time.Duration) *HealthzParams {
o.SetTimeout(timeout)
return o
}
// SetTimeout adds the timeout to the healthz params
func (o *HealthzParams) SetTimeout(timeout time.Duration) {
o.timeout = timeout
}
// WithContext adds the context to the healthz params
func (o *HealthzParams) WithContext(ctx context.Context) *HealthzParams {
o.SetContext(ctx)
return o
}
// SetContext adds the context to the healthz params
func (o *HealthzParams) SetContext(ctx context.Context) {
o.Context = ctx
}
// WithHTTPClient adds the HTTPClient to the healthz params
func (o *HealthzParams) WithHTTPClient(client *http.Client) *HealthzParams {
o.SetHTTPClient(client)
return o
}
// SetHTTPClient adds the HTTPClient to the healthz params
func (o *HealthzParams) SetHTTPClient(client *http.Client) {
o.HTTPClient = client
}
// WriteToRequest writes these params to a swagger request
func (o *HealthzParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
if err := r.SetTimeout(o.timeout); err != nil {
return err
}
var res []error
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,105 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"fmt"
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// HealthzReader is a Reader for the Healthz structure.
type HealthzReader struct {
formats strfmt.Registry
}
// ReadResponse reads a server response into the received o.
func (o *HealthzReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewHealthzOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
case 503:
result := NewHealthzServiceUnavailable()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return nil, result
default:
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
}
// NewHealthzOK creates a HealthzOK with default headers values
func NewHealthzOK() *HealthzOK {
return &HealthzOK{}
}
/* HealthzOK describes a response with status code 200, with default header values.
Health check report
*/
type HealthzOK struct {
Payload *models.HealthCheckResults
}
func (o *HealthzOK) Error() string {
return fmt.Sprintf("[GET /healthz][%d] healthzOK %+v", 200, o.Payload)
}
func (o *HealthzOK) GetPayload() *models.HealthCheckResults {
return o.Payload
}
func (o *HealthzOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.HealthCheckResults)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}
// NewHealthzServiceUnavailable creates a HealthzServiceUnavailable with default headers values
func NewHealthzServiceUnavailable() *HealthzServiceUnavailable {
return &HealthzServiceUnavailable{}
}
/* HealthzServiceUnavailable describes a response with status code 503, with default header values.
Unhealthy service
*/
type HealthzServiceUnavailable struct {
Payload *models.HealthCheckResults
}
func (o *HealthzServiceUnavailable) Error() string {
return fmt.Sprintf("[GET /healthz][%d] healthzServiceUnavailable %+v", 503, o.Payload)
}
func (o *HealthzServiceUnavailable) GetPayload() *models.HealthCheckResults {
return o.Payload
}
func (o *HealthzServiceUnavailable) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
o.Payload = new(models.HealthCheckResults)
// response payload
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
return err
}
return nil
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -20,13 +6,14 @@ package operations
// Editing this file might prove futile when you re-run the swagger generate command
import (
"github.com/go-openapi/runtime"
"fmt"
strfmt "github.com/go-openapi/strfmt"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
)
// New creates a new operations API client.
func New(transport runtime.ClientTransport, formats strfmt.Registry) *Client {
func New(transport runtime.ClientTransport, formats strfmt.Registry) ClientService {
return &Client{transport: transport, formats: formats}
}
@@ -38,88 +25,212 @@ type Client struct {
formats strfmt.Registry
}
// ClientOption is the option for Client methods
type ClientOption func(*runtime.ClientOperation)
// ClientService is the interface for Client methods
type ClientService interface {
CheckAllPods(params *CheckAllPodsParams, opts ...ClientOption) (*CheckAllPodsOK, error)
CheckServicePods(params *CheckServicePodsParams, opts ...ClientOption) (*CheckServicePodsOK, error)
ClusterHealth(params *ClusterHealthParams, opts ...ClientOption) (*ClusterHealthOK, error)
Healthz(params *HealthzParams, opts ...ClientOption) (*HealthzOK, error)
Ping(params *PingParams, opts ...ClientOption) (*PingOK, error)
SetTransport(transport runtime.ClientTransport)
}
/*
CheckAllPods Queries the API server for all other pods in this service, and makes all of them query all of their neighbours, using their pods IPs. Calls their /check endpoint.
CheckAllPods Queries the API server for all other pods in this service, and makes all of them query all of their neighbours, using their pods IPs. Calls their /check endpoint.
*/
func (a *Client) CheckAllPods(params *CheckAllPodsParams) (*CheckAllPodsOK, error) {
func (a *Client) CheckAllPods(params *CheckAllPodsParams, opts ...ClientOption) (*CheckAllPodsOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewCheckAllPodsParams()
}
result, err := a.transport.Submit(&runtime.ClientOperation{
op := &runtime.ClientOperation{
ID: "checkAllPods",
Method: "GET",
PathPattern: "/check_all",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{""},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http"},
Params: params,
Reader: &CheckAllPodsReader{formats: a.formats},
Context: params.Context,
Client: params.HTTPClient,
})
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
return result.(*CheckAllPodsOK), nil
success, ok := result.(*CheckAllPodsOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for checkAllPods: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
CheckServicePods Queries the API server for all other pods in this service, and pings them via their pods IPs. Calls their /ping endpoint
CheckServicePods Queries the API server for all other pods in this service, and pings them via their pods IPs. Calls their /ping endpoint
*/
func (a *Client) CheckServicePods(params *CheckServicePodsParams) (*CheckServicePodsOK, error) {
func (a *Client) CheckServicePods(params *CheckServicePodsParams, opts ...ClientOption) (*CheckServicePodsOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewCheckServicePodsParams()
}
result, err := a.transport.Submit(&runtime.ClientOperation{
op := &runtime.ClientOperation{
ID: "checkServicePods",
Method: "GET",
PathPattern: "/check",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{""},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http"},
Params: params,
Reader: &CheckServicePodsReader{formats: a.formats},
Context: params.Context,
Client: params.HTTPClient,
})
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
return result.(*CheckServicePodsOK), nil
success, ok := result.(*CheckServicePodsOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for checkServicePods: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
Ping return query stats
ClusterHealth Checks the full graph. Returns a binary OK or not OK.
*/
func (a *Client) Ping(params *PingParams) (*PingOK, error) {
func (a *Client) ClusterHealth(params *ClusterHealthParams, opts ...ClientOption) (*ClusterHealthOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewClusterHealthParams()
}
op := &runtime.ClientOperation{
ID: "clusterHealth",
Method: "GET",
PathPattern: "/cluster_health",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http"},
Params: params,
Reader: &ClusterHealthReader{formats: a.formats},
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*ClusterHealthOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for clusterHealth: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
Healthz The healthcheck endpoint provides detailed information about the health of a web service. If each of the components required by the service are healthy, then the service is considered healthy and will return a 200 OK response. If any of the components needed by the service are unhealthy, then a 503 Service Unavailable response will be provided.
*/
func (a *Client) Healthz(params *HealthzParams, opts ...ClientOption) (*HealthzOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewHealthzParams()
}
op := &runtime.ClientOperation{
ID: "healthz",
Method: "GET",
PathPattern: "/healthz",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http"},
Params: params,
Reader: &HealthzReader{formats: a.formats},
Context: params.Context,
Client: params.HTTPClient,
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
success, ok := result.(*HealthzOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for healthz: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
/*
Ping return query stats
*/
func (a *Client) Ping(params *PingParams, opts ...ClientOption) (*PingOK, error) {
// TODO: Validate the params before sending
if params == nil {
params = NewPingParams()
}
result, err := a.transport.Submit(&runtime.ClientOperation{
op := &runtime.ClientOperation{
ID: "ping",
Method: "GET",
PathPattern: "/ping",
ProducesMediaTypes: []string{"application/json"},
ConsumesMediaTypes: []string{""},
ConsumesMediaTypes: []string{"application/json"},
Schemes: []string{"http"},
Params: params,
Reader: &PingReader{formats: a.formats},
Context: params.Context,
Client: params.HTTPClient,
})
}
for _, opt := range opts {
opt(op)
}
result, err := a.transport.Submit(op)
if err != nil {
return nil, err
}
return result.(*PingOK), nil
success, ok := result.(*PingOK)
if ok {
return success, nil
}
// unexpected success response
// safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue
msg := fmt.Sprintf("unexpected success response for ping: API contract not enforced by server. Client expected to get an error, but got: %T", result)
panic(msg)
}
// SetTransport changes the transport on the client

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -20,59 +6,56 @@ package operations
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"net/http"
"time"
"golang.org/x/net/context"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
cr "github.com/go-openapi/runtime/client"
strfmt "github.com/go-openapi/strfmt"
"github.com/go-openapi/strfmt"
)
// NewPingParams creates a new PingParams object
// with the default values initialized.
// NewPingParams creates a new PingParams object,
// with the default timeout for this client.
//
// Default values are not hydrated, since defaults are normally applied by the API server side.
//
// To enforce default values in parameter, use SetDefaults or WithDefaults.
func NewPingParams() *PingParams {
return &PingParams{
timeout: cr.DefaultTimeout,
}
}
// NewPingParamsWithTimeout creates a new PingParams object
// with the default values initialized, and the ability to set a timeout on a request
// with the ability to set a timeout on a request.
func NewPingParamsWithTimeout(timeout time.Duration) *PingParams {
return &PingParams{
timeout: timeout,
}
}
// NewPingParamsWithContext creates a new PingParams object
// with the default values initialized, and the ability to set a context for a request
// with the ability to set a context for a request.
func NewPingParamsWithContext(ctx context.Context) *PingParams {
return &PingParams{
Context: ctx,
}
}
// NewPingParamsWithHTTPClient creates a new PingParams object
// with the default values initialized, and the ability to set a custom HTTPClient for a request
// with the ability to set a custom HTTPClient for a request.
func NewPingParamsWithHTTPClient(client *http.Client) *PingParams {
return &PingParams{
HTTPClient: client,
}
}
/*PingParams contains all the parameters to send to the API endpoint
for the ping operation typically these are written to a http.Request
/* PingParams contains all the parameters to send to the API endpoint
for the ping operation.
Typically these are written to a http.Request.
*/
type PingParams struct {
timeout time.Duration
@@ -80,6 +63,21 @@ type PingParams struct {
HTTPClient *http.Client
}
// WithDefaults hydrates default values in the ping params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *PingParams) WithDefaults() *PingParams {
o.SetDefaults()
return o
}
// SetDefaults hydrates default values in the ping params (not the query body).
//
// All values with no default are reset to their zero value.
func (o *PingParams) SetDefaults() {
// no default values defined for this parameter
}
// WithTimeout adds the timeout to the ping params
func (o *PingParams) WithTimeout(timeout time.Duration) *PingParams {
o.SetTimeout(timeout)

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -24,10 +10,9 @@ import (
"io"
"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
strfmt "github.com/go-openapi/strfmt"
models "github.com/bloomberg/goldpinger/pkg/models"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// PingReader is a Reader for the Ping structure.
@@ -38,16 +23,14 @@ type PingReader struct {
// ReadResponse reads a server response into the received o.
func (o *PingReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
switch response.Code() {
case 200:
result := NewPingOK()
if err := result.readResponse(response, consumer, o.formats); err != nil {
return nil, err
}
return result, nil
default:
return nil, runtime.NewAPIError("unknown error", response, response.Code())
return nil, runtime.NewAPIError("response status code does not match any response statuses defined for this endpoint in the swagger spec", response, response.Code())
}
}
@@ -56,7 +39,7 @@ func NewPingOK() *PingOK {
return &PingOK{}
}
/*PingOK handles this case with default header values.
/* PingOK describes a response with status code 200, with default header values.
return success
*/
@@ -67,6 +50,9 @@ type PingOK struct {
func (o *PingOK) Error() string {
return fmt.Sprintf("[GET /ping][%d] pingOK %+v", 200, o.Payload)
}
func (o *PingOK) GetPayload() *models.PingResults {
return o.Payload
}
func (o *PingOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {

View File

@@ -15,31 +15,106 @@
package goldpinger
import (
"fmt"
"context"
"errors"
"net"
"sort"
"strconv"
"sync"
"time"
apiclient "github.com/bloomberg/goldpinger/pkg/client"
"github.com/bloomberg/goldpinger/pkg/models"
apiclient "github.com/bloomberg/goldpinger/v3/pkg/client"
"github.com/bloomberg/goldpinger/v3/pkg/client/operations"
"github.com/bloomberg/goldpinger/v3/pkg/models"
httptransport "github.com/go-openapi/runtime/client"
"github.com/go-openapi/strfmt"
"go.uber.org/zap"
)
// CheckNeighbours queries the kubernetes API server for all other goldpinger pods
// then calls Ping() on each one
func CheckNeighbours() models.CheckResults {
return PingAllPods(GetAllPods())
func CheckNeighbours(ctx context.Context) *models.CheckResults {
// Mux to prevent concurrent map address
checkResultsMux.Lock()
defer checkResultsMux.Unlock()
final := models.CheckResults{}
final.PodResults = make(map[string]models.PodResult)
for podName, podResult := range checkResults.PodResults {
final.PodResults[podName] = podResult
}
final.ProbeResults = checkTargets()
return &final
}
// CheckNeighboursNeighbours queries the kubernetes API server for all other goldpinger
// pods then calls Check() on each one
func CheckNeighboursNeighbours() *models.CheckAllResults {
return CheckAllPods(GetAllPods())
func CheckNeighboursNeighbours(ctx context.Context) *models.CheckAllResults {
return CheckAllPods(ctx, SelectPods())
}
// CheckCluster does a CheckNeighboursNeighbours and analyses results to produce a binary OK or not OK
func CheckCluster(ctx context.Context) *models.ClusterHealthResults {
start := time.Now()
output := models.ClusterHealthResults{
GeneratedAt: strfmt.DateTime(start),
OK: true,
}
selectedPods := SelectPods()
// precompute the expected set of nodes
expectedNodes := []string{}
for _, peer := range selectedPods {
expectedNodes = append(expectedNodes, peer.HostIP)
}
sort.Strings(expectedNodes)
// get the response we serve for check_all
checkAll := CheckAllPods(ctx, selectedPods)
// we should at the very least have a response from ourselves
if len(checkAll.Responses) < 1 {
output.OK = false
}
for _, resp := range checkAll.Responses {
// 1. check that all nodes report OK
if *resp.OK {
output.NodesHealthy = append(output.NodesHealthy, resp.HostIP.String())
} else {
output.NodesUnhealthy = append(output.NodesUnhealthy, resp.HostIP.String())
output.OK = false
}
output.NodesTotal++
// 2. check that all nodes report the expected peers
// on error, there might be no response from the node
if resp.Response == nil {
output.OK = false
continue
}
// if we get a response, let's check we get the expected nodes
observedNodes := []string{}
for _, peer := range resp.Response.PodResults {
observedNodes = append(observedNodes, string(peer.HostIP))
}
sort.Strings(observedNodes)
if len(observedNodes) != len(expectedNodes) {
output.OK = false
}
for i, val := range observedNodes {
if val != expectedNodes[i] {
output.OK = false
break
}
}
}
output.DurationNs = time.Since(start).Nanoseconds()
return &output
}
// PingAllPodsResult holds results from pinging all nodes
type PingAllPodsResult struct {
podName string
podResult models.PodResult
hostIPv4 strfmt.IPv4
podIP string
deleted bool
}
func pickPodHostIP(podIP, hostIP string) string {
@@ -49,124 +124,188 @@ func pickPodHostIP(podIP, hostIP string) string {
return podIP
}
func PingAllPods(pods map[string]string) models.CheckResults {
func checkTargets() models.ProbeResults {
results := make(map[string][]models.ProbeResult)
probes := []struct {
protocol string
hosts []string
probeFn func(addr string, timeout time.Duration) error
statFn func(host string)
timeout time.Duration
}{
{
protocol: "dns",
hosts: GoldpingerConfig.DnsHosts,
probeFn: doDNSProbe,
statFn: CountDnsError,
timeout: GoldpingerConfig.DnsCheckTimeout,
},
{
protocol: "http",
hosts: GoldpingerConfig.HTTPTargets,
probeFn: doHTTPProbe,
statFn: CountHttpError,
timeout: GoldpingerConfig.HTTPCheckTimeout,
},
{
protocol: "tcp",
hosts: GoldpingerConfig.TCPTargets,
probeFn: doTCPProbe,
statFn: CountTcpError,
timeout: GoldpingerConfig.TCPCheckTimeout,
},
}
result := models.CheckResults{}
ch := make(chan PingAllPodsResult, len(pods))
wg := sync.WaitGroup{}
wg.Add(len(pods))
for podIP, hostIP := range pods {
go func(podIP string, hostIP string) {
var channelResult PingAllPodsResult
CountCall("made", "ping")
timer := GetLabeledPeersCallsTimer("ping", hostIP, podIP)
resp, err := getClient(pickPodHostIP(podIP, hostIP)).Operations.Ping(nil)
channelResult.hostIPv4.UnmarshalText([]byte(hostIP))
var OK = (err == nil)
if OK {
channelResult.podResult = models.PodResult{HostIP: channelResult.hostIPv4, OK: &OK, Response: resp.Payload, StatusCode: 200}
timer.ObserveDuration()
} else {
channelResult.podResult = models.PodResult{HostIP: channelResult.hostIPv4, OK: &OK, Error: err.Error(), StatusCode: 500}
CountError("ping")
for _, probe := range probes {
for _, host := range probe.hosts {
if _, ok := results[host]; !ok {
results[host] = []models.ProbeResult{}
}
channelResult.podIP = podIP
ch <- channelResult
wg.Done()
}(podIP, hostIP)
}
wg.Wait()
close(ch)
res := models.ProbeResult{Protocol: probe.protocol}
start := time.Now()
err := probe.probeFn(host, probe.timeout)
if err != nil {
res.Error = err.Error()
probe.statFn(host)
}
counterHealthy, counterUnhealthy := 0.0, 0.0
for response := range ch {
var podIPv4 strfmt.IPv4
podIPv4.UnmarshalText([]byte(response.podIP))
if *response.podResult.OK {
counterHealthy++
} else {
counterUnhealthy++
res.ResponseTimeMs = time.Since(start).Milliseconds()
results[host] = append(results[host], res)
}
result[response.podIP] = response.podResult
}
CountHealthyUnhealthyNodes(counterHealthy, counterUnhealthy)
return result
return results
}
// CheckServicePodsResult results of the /check operation
type CheckServicePodsResult struct {
podName string
checkAllPodResult models.CheckAllPodResult
hostIPv4 strfmt.IPv4
podIP string
podIPv4 strfmt.IPv4
}
func CheckAllPods(pods map[string]string) *models.CheckAllResults {
// CheckAllPods calls all neighbours and returns a detailed report
func CheckAllPods(checkAllCtx context.Context, pods map[string]*GoldpingerPod) *models.CheckAllResults {
result := models.CheckAllResults{Responses: make(map[string]models.CheckAllPodResult)}
ch := make(chan CheckServicePodsResult, len(pods))
wg := sync.WaitGroup{}
wg.Add(len(pods))
for podIP, hostIP := range pods {
go func(podIP string, hostIP string) {
var channelResult CheckServicePodsResult
for _, pod := range pods {
go func(pod *GoldpingerPod) {
// logger
logger := zap.L().With(
zap.String("op", "check"),
zap.String("name", pod.Name),
zap.String("hostIP", pod.HostIP),
zap.String("podIP", pod.PodIP),
)
// stats
CountCall("made", "check")
timer := GetLabeledPeersCallsTimer("check", hostIP, podIP)
resp, err := getClient(pickPodHostIP(podIP, hostIP)).Operations.CheckServicePods(nil)
timer := GetLabeledPeersCallsTimer("check", pod.HostIP, pod.PodIP)
channelResult.hostIPv4.UnmarshalText([]byte(hostIP))
var OK = (err == nil)
if OK {
channelResult.checkAllPodResult = models.CheckAllPodResult{
OK: &OK,
HostIP: channelResult.hostIPv4,
Response: resp.Payload,
}
timer.ObserveDuration()
} else {
// setup
var channelResult CheckServicePodsResult
channelResult.podName = pod.Name
channelResult.hostIPv4.UnmarshalText([]byte(pod.HostIP))
channelResult.podIPv4.UnmarshalText([]byte(pod.PodIP))
client, err := getClient(pickPodHostIP(pod.PodIP, pod.HostIP))
OK := false
if err != nil {
logger.Warn("Couldn't get a client for Check", zap.Error(err))
channelResult.checkAllPodResult = models.CheckAllPodResult{
OK: &OK,
PodIP: channelResult.podIPv4,
HostIP: channelResult.hostIPv4,
Error: err.Error(),
}
CountError("checkAll")
} else {
checkCtx, cancel := context.WithTimeout(
checkAllCtx,
GoldpingerConfig.CheckTimeout,
)
defer cancel()
params := operations.NewCheckServicePodsParamsWithContext(checkCtx)
resp, err := client.Operations.CheckServicePods(params)
OK = (err == nil)
if OK {
logger.Debug("Check Ok")
channelResult.checkAllPodResult = models.CheckAllPodResult{
OK: &OK,
PodIP: channelResult.podIPv4,
HostIP: channelResult.hostIPv4,
Response: resp.Payload,
}
timer.ObserveDuration()
} else {
logger.Warn("Check returned error", zap.Error(err))
channelResult.checkAllPodResult = models.CheckAllPodResult{
OK: &OK,
PodIP: channelResult.podIPv4,
HostIP: channelResult.hostIPv4,
Error: err.Error(),
}
CountError("checkAll")
}
}
channelResult.podIP = podIP
ch <- channelResult
wg.Done()
}(podIP, hostIP)
}(pod)
}
wg.Wait()
close(ch)
for response := range ch {
var podIPv4 strfmt.IPv4
podIPv4.UnmarshalText([]byte(response.podIP))
result.Responses[response.podIP] = response.checkAllPodResult
result.Responses[response.podName] = response.checkAllPodResult
result.Hosts = append(result.Hosts, &models.CheckAllResultsHostsItems0{
HostIP: response.hostIPv4,
PodIP: podIPv4,
PodName: response.podName,
HostIP: response.hostIPv4,
PodIP: response.podIPv4,
})
if response.checkAllPodResult.Response != nil &&
response.checkAllPodResult.Response.ProbeResults != nil {
if result.ProbeResults == nil {
result.ProbeResults = make(map[string]models.ProbeResults)
}
for host := range response.checkAllPodResult.Response.ProbeResults {
if result.ProbeResults[host] == nil {
result.ProbeResults[host] = make(map[string][]models.ProbeResult)
}
result.ProbeResults[host][response.podName] = response.checkAllPodResult.Response.ProbeResults[host]
}
}
}
return &result
}
func getClient(hostIP string) *apiclient.Goldpinger {
host := fmt.Sprintf("%s:%d", hostIP, GoldpingerConfig.Port)
// HealthCheck returns a simple 200 OK response to verify the API is up
func HealthCheck() *models.HealthCheckResults {
ok := true
start := time.Now()
result := models.HealthCheckResults{
OK: &ok,
DurationNs: time.Since(start).Nanoseconds(),
GeneratedAt: strfmt.DateTime(start),
}
return &result
}
func getClient(hostIP string) (*apiclient.Goldpinger, error) {
if hostIP == "" {
return nil, errors.New("Host or pod IP empty, can't make a call")
}
host := net.JoinHostPort(hostIP, strconv.Itoa(GoldpingerConfig.Port))
transport := httptransport.New(host, "", nil)
client := apiclient.New(transport, strfmt.Default)
apiclient.Default.SetTransport(transport)
return client
return client, nil
}

View File

@@ -15,16 +15,43 @@
package goldpinger
import (
"time"
"k8s.io/client-go/kubernetes"
)
// GoldpingerConfig represents the configuration for goldpinger
var GoldpingerConfig = struct {
StaticFilePath string `long:"static-file-path" description:"Folder for serving static files" env:"STATIC_FILE_PATH"`
KubeConfigPath string `long:"kubeconfig" description:"Path to kubeconfig file" env:"KUBECONFIG"`
RefreshInterval int `long:"refresh-interval" description:"If > 0, will create a thread and collect stats every n seconds" env:"REFRESH_INTERVAL" default:"30"`
Hostname string `long:"hostname" description:"Hostname to use" env:"HOSTNAME"`
Port int `long:"client-port-override" description:"(for testing) use this port when calling other instances" env:"CLIENT_PORT_OVERRIDE"`
UseHostIP bool `long:"use-host-ip" description:"When making the calls, use host ip (defaults to pod ip)" env:"USE_HOST_IP"`
StaticFilePath string `long:"static-file-path" description:"Folder for serving static files" env:"STATIC_FILE_PATH"`
ZapConfigPath string `long:"zap-config" description:"Path to zap config file" env:"ZAP_CONFIG" default:"/config/zap.json"`
KubeConfigPath string `long:"kubeconfig" description:"Path to kubeconfig file" env:"KUBECONFIG"`
RefreshInterval int `long:"refresh-interval" description:"If > 0, will create a thread and collect stats every n seconds" env:"REFRESH_INTERVAL" default:"30"`
JitterFactor float64 `long:"jitter-factor" description:"The amount of jitter to add while pinging clients" env:"JITTER_FACTOR" default:"0.05"`
Hostname string `long:"hostname" description:"Hostname to use" env:"HOSTNAME"`
PodIP string `long:"pod-ip" description:"Pod IP to use" env:"POD_IP"`
PodName string `long:"pod-name" description:"The name of this pod - used to select --ping-number of pods using rendezvous hashing" env:"POD_NAME"`
PingNumber uint `long:"ping-number" description:"Number of peers to ping. A value of 0 indicates all peers should be pinged." default:"0" env:"PING_NUMBER"`
Port int `long:"client-port-override" description:"(for testing) use this port when calling other instances" env:"CLIENT_PORT_OVERRIDE"`
UseHostIP bool `long:"use-host-ip" description:"When making the calls, use host ip (defaults to pod ip)" env:"USE_HOST_IP"`
LabelSelector string `long:"label-selector" description:"label selector to use to discover goldpinger pods in the cluster" env:"LABEL_SELECTOR" default:"app=goldpinger"`
Namespace *string `long:"namespace" description:"namespace to use to discover goldpinger pods in the cluster (empty for all). Defaults to discovering the namespace for the current pod" env:"NAMESPACE"`
DisplayNodeName bool `long:"display-nodename" description:"Display nodename other than podname in UI (defaults is podname)." env:"DISPLAY_NODENAME"`
KubernetesClient *kubernetes.Clientset
DnsHosts []string `long:"host-to-resolve" description:"A host to attempt dns resolve on (space delimited)" env:"HOSTS_TO_RESOLVE" env-delim:" "`
TCPTargets []string `long:"tcp-targets" description:"A list of external targets(<host>:<port> or <ip>:<port>) to attempt a TCP check on (space delimited)" env:"TCP_TARGETS" env-delim:" "`
HTTPTargets []string `long:"http-targets" description:"A list of external targets(<http or https>://<url>) to attempt an HTTP{S} check on. A 200 HTTP code is considered successful.(space delimited)" env:"HTTP_TARGETS" env-delim:" "`
IPVersions []string `long:"ip-versions" description:"The IP versions to use (space delimited). Possible values are 4 and 6 (defaults to 4)." env:"IP_VERSIONS" env-delim:" "`
// Timeouts
PingTimeoutMs int64 `long:"ping-timeout-ms" description:"The timeout in milliseconds for a ping call to other goldpinger pods(deprecated)" env:"PING_TIMEOUT_MS" default:"300"`
CheckTimeoutMs int64 `long:"check-timeout-ms" description:"The timeout in milliseconds for a check call to other goldpinger pods(deprecated)" env:"CHECK_TIMEOUT_MS" default:"1000"`
CheckAllTimeoutMs int64 `long:"check-all-timeout-ms" description:"The timeout in milliseconds for a check-all call to other goldpinger pods(deprecated)" env:"CHECK_ALL_TIMEOUT_MS" default:"5000"`
PingTimeout time.Duration `long:"ping-timeout" description:"The timeout for a ping call to other goldpinger pods" env:"PING_TIMEOUT" default:"300ms"`
CheckTimeout time.Duration `long:"check-timeout" description:"The timeout for a check call to other goldpinger pods" env:"CHECK_TIMEOUT" default:"1000ms"`
CheckAllTimeout time.Duration `long:"check-all-timeout" description:"The timeout for a check-all call to other goldpinger pods" env:"CHECK_ALL_TIMEOUT" default:"5000ms"`
TCPCheckTimeout time.Duration `long:"tcp-targets-timeout" description:"The timeout for a tcp check on the provided tcp-targets" env:"TCP_TARGETS_TIMEOUT" default:"500ms"`
DnsCheckTimeout time.Duration `long:"dns-targets-timeout" description:"The timeout for a dns check on the provided dns-targets" env:"DNS_TARGETS_TIMEOUT" default:"500ms"`
HTTPCheckTimeout time.Duration `long:"http-targets-timeout" description:"The timeout for a http check on the provided http-targets" env:"HTTP_TARGETS_TIMEOUT" default:"500ms"`
}{}

153
pkg/goldpinger/heatmap.go Normal file
View File

@@ -0,0 +1,153 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file is safe to edit. Once it exists it will not be overwritten
package goldpinger
import (
"bytes"
"context"
"fmt"
"image"
"image/color"
"image/png"
"net/http"
"sort"
"strconv"
"go.uber.org/zap"
"golang.org/x/image/font"
"golang.org/x/image/font/basicfont"
"golang.org/x/image/math/fixed"
)
func addLabel(img *image.RGBA, x, y int, text string) {
drawer := &font.Drawer{
Dst: img,
Src: image.NewUniform(color.RGBA{25, 200, 25, 255}),
Face: basicfont.Face7x13,
Dot: fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)},
}
drawer.DrawString(text)
}
// Calculates the color of the box to draw based on the latency and tresholds
// We are aiming at slightly more palatable colors than just moving from 255 green to 255 red,
// so we will use 25B, and then move from (25R, 200G) to (200R, 25G), so our scale is effectively 350 points
func getPingBoxColor(latency int64, tresholdLatencies [3]int64) *color.RGBA {
var red, green uint8 = 25, 200
if latency > tresholdLatencies[2] {
red, green = 200, 25
} else if latency >= tresholdLatencies[1] {
red, green = 200, 200
diff := (float32(latency-tresholdLatencies[1]) / float32(tresholdLatencies[2]-tresholdLatencies[1])) * 175
green = green - uint8(diff)
} else if latency >= tresholdLatencies[0] {
red, green = 25, 200
diff := (float32(latency-tresholdLatencies[0]) / float32(tresholdLatencies[1]-tresholdLatencies[0])) * 175
red = red + uint8(diff)
}
return &color.RGBA{red, green, 25, 255}
}
func drawPingBox(img *image.RGBA, _x, _y, size int, color *color.RGBA) {
for x := _x; x < _x+size; x++ {
for y := _y; y < _y+size; y++ {
img.Set(x, y, *color)
}
}
}
func getPingBoxCoordinates(col, row, boxSize, padding int) (int, int) {
return col * (boxSize + padding), row * (boxSize + padding)
}
// HeatmapHandler returns a PNG with a heatmap representation
func HeatmapHandler(w http.ResponseWriter, r *http.Request) {
// parse the query to set the parameters
query := r.URL.Query()
ctx, cancel := context.WithTimeout(
r.Context(),
GoldpingerConfig.CheckAllTimeout,
)
defer cancel()
// get the results
checkResults := CheckAllPods(ctx, GetAllPods())
// set some sizes
numberOfPods := len(checkResults.Responses)
legendSize := 200
boxSize := 14
paddingSize := 1
heatmapSize := numberOfPods*(boxSize+paddingSize) + boxSize*2
tresholdLatencies := [3]int64{1, 10, 100}
for index := range tresholdLatencies {
stringValue := query["t"+fmt.Sprintf("%d", index)]
if len(stringValue) == 0 {
continue
}
if v, err := strconv.ParseInt(stringValue[0], 0, 64); err == nil && v >= 0 {
tresholdLatencies[index] = v
}
}
canvas := image.NewRGBA(image.Rect(0, 0, heatmapSize+legendSize, heatmapSize))
// establish an order and fix the max delay
var keys []string
for sourceIP := range checkResults.Responses {
keys = append(keys, sourceIP)
}
sort.Strings(keys)
order := make(map[string]int)
for index, key := range keys {
order[key] = index
}
// draw all the boxes
for sourceIP, results := range checkResults.Responses {
if *results.OK {
for destinationIP, response := range results.Response.PodResults {
x, y := getPingBoxCoordinates(order[sourceIP], order[destinationIP], boxSize, paddingSize)
color := getPingBoxColor(response.ResponseTimeMs, tresholdLatencies)
drawPingBox(canvas, boxSize+x, boxSize+y, boxSize, color)
}
}
}
// draw the legend
for index, ip := range keys {
// ip
addLabel(canvas, heatmapSize, (index+1)*(boxSize+paddingSize)+13, fmt.Sprintf("%d", index)+": "+ip)
// rows
addLabel(canvas, 0, (index+1)*(boxSize+paddingSize)+13, fmt.Sprintf("%d", index))
// columns
addLabel(canvas, (index+1)*(boxSize+paddingSize), 13, fmt.Sprintf("%d", index))
}
buffer := new(bytes.Buffer)
if err := png.Encode(buffer, canvas); err != nil {
zap.L().Error("error encoding png", zap.Error(err))
}
w.Header().Set("Content-Type", "image/png")
w.Header().Set("Content-Length", strconv.Itoa(len(buffer.Bytes())))
if _, err := w.Write(buffer.Bytes()); err != nil {
zap.L().Error("error writing heatmap buffer out", zap.Error(err))
}
}

View File

@@ -15,25 +15,138 @@
package goldpinger
import (
"log"
"context"
"io/ioutil"
"go.uber.org/zap"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8snet "k8s.io/utils/net"
)
func GetAllPods() map[string]string {
var nodeIPMap = make(map[string]string)
// PodNamespace is the auto-detected namespace for this goldpinger pod
var PodNamespace = getPodNamespace()
// GoldpingerPod contains just the basic info needed to ping and keep track of a given goldpinger pod
type GoldpingerPod struct {
Name string // Name is the name of the pod
PodIP string // PodIP is the IP address of the pod
HostIP string // HostIP is the IP address of the host where the pod lives
}
func getPodNamespace() string {
b, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
if err != nil {
zap.L().Warn("Unable to determine namespace", zap.Error(err))
return ""
}
namespace := string(b)
return namespace
}
// getHostIP gets the IP of the host where the pod is scheduled. If UseIPv6 is enabled then we need to check
// the node IPs since HostIP will only list the default IP version one.
func getHostIP(p v1.Pod) string {
if ipMatchesConfig(p.Status.HostIP) {
return p.Status.HostIP
}
if addr, ok := nodeIPMap[p.Spec.NodeName]; ok {
return addr
}
timer := GetLabeledKubernetesCallsTimer()
pods, err := GoldpingerConfig.KubernetesClient.CoreV1().Pods("").List(metav1.ListOptions{LabelSelector: "app=goldpinger"})
node, err := GoldpingerConfig.KubernetesClient.CoreV1().Nodes().Get(context.TODO(), p.Spec.NodeName, metav1.GetOptions{})
if err != nil {
log.Println("Error getting pods for selector: ", err.Error())
zap.L().Error("error getting node", zap.Error(err))
CountError("kubernetes_api")
return p.Status.HostIP
} else {
timer.ObserveDuration()
}
var hostIP string
for _, addr := range node.Status.Addresses {
if (addr.Type == v1.NodeInternalIP || addr.Type == v1.NodeExternalIP) &&
ipMatchesConfig(addr.Address) {
hostIP = addr.Address
}
}
nodeIPMap[p.Spec.NodeName] = hostIP
return hostIP
}
// getPodIP will get an IPv6 IP from PodIPs if the UseIPv6 config is set, otherwise just return the object PodIP
func getPodIP(p v1.Pod) string {
if ipMatchesConfig(p.Status.PodIP) {
return p.Status.PodIP
}
var podIP string
if p.Status.PodIPs != nil {
for _, ip := range p.Status.PodIPs {
if ipMatchesConfig(ip.IP) {
podIP = ip.IP
}
}
}
return podIP
}
func getPodNodeName(p v1.Pod) string {
if GoldpingerConfig.DisplayNodeName {
return p.Spec.NodeName
}
return p.Name
}
// GetAllPods returns a mapping from a pod name to a pointer to a GoldpingerPod(s)
func GetAllPods() map[string]*GoldpingerPod {
timer := GetLabeledKubernetesCallsTimer()
listOpts := metav1.ListOptions{
ResourceVersion: "0",
LabelSelector: GoldpingerConfig.LabelSelector,
FieldSelector: "status.phase=Running", // only select Running pods, otherwise we will get them before they have IPs
}
pods, err := GoldpingerConfig.KubernetesClient.CoreV1().Pods(*GoldpingerConfig.Namespace).List(context.TODO(), listOpts)
if err != nil {
zap.L().Error("Error getting pods for selector", zap.String("selector", GoldpingerConfig.LabelSelector), zap.Error(err))
CountError("kubernetes_api")
} else {
timer.ObserveDuration()
}
var podsreturn = make(map[string]string)
podMap := make(map[string]*GoldpingerPod)
for _, pod := range pods.Items {
podsreturn[pod.Status.PodIP] = pod.Status.HostIP
podMap[pod.Name] = &GoldpingerPod{
Name: getPodNodeName(pod),
PodIP: getPodIP(pod),
HostIP: getHostIP(pod),
}
}
return podsreturn
return podMap
}
// ipMatchesConfig checks if the input IP family matches the first entry in the IPVersions config.
// TODO update to check all config versions to support dual-stack pinging.
func ipMatchesConfig(ip string) bool {
ipFamily := getIPFamily(ip)
return GoldpingerConfig.IPVersions[0] == string(ipFamily)
}
// getIPFamily returns the IP family of the input IP.
// Possible values are 4 and 6.
func getIPFamily(ip string) k8snet.IPFamily {
if k8snet.IsIPv4String(ip) {
return k8snet.IPv4
}
if k8snet.IsIPv6String(ip) {
return k8snet.IPv6
}
zap.L().Error("Error determining IP family", zap.String("IP", ip))
return ""
}

176
pkg/goldpinger/pinger.go Normal file
View File

@@ -0,0 +1,176 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package goldpinger
import (
"context"
"time"
"go.uber.org/zap"
apiclient "github.com/bloomberg/goldpinger/v3/pkg/client"
"github.com/bloomberg/goldpinger/v3/pkg/client/operations"
"github.com/bloomberg/goldpinger/v3/pkg/models"
"github.com/go-openapi/strfmt"
"github.com/prometheus/client_golang/prometheus"
"k8s.io/apimachinery/pkg/util/wait"
)
// Pinger contains all the info needed by a goroutine to continuously ping a pod
type Pinger struct {
pod *GoldpingerPod
client *apiclient.Goldpinger
timeout time.Duration
histogram prometheus.Observer
hostIPv4 strfmt.IPv4
podIPv4 strfmt.IPv4
resultsChan chan<- PingAllPodsResult
stopChan chan struct{}
logger *zap.Logger
}
// NewPinger constructs and returns a Pinger object responsible for pinging a single
// goldpinger pod
func NewPinger(pod *GoldpingerPod, resultsChan chan<- PingAllPodsResult) *Pinger {
p := Pinger{
pod: pod,
timeout: GoldpingerConfig.PingTimeout,
resultsChan: resultsChan,
stopChan: make(chan struct{}),
histogram: goldpingerResponseTimePeersHistogram.WithLabelValues(
GoldpingerConfig.Hostname,
"ping",
pod.HostIP,
pod.PodIP,
),
logger: zap.L().With(
zap.String("op", "pinger"),
zap.String("name", pod.Name),
zap.String("hostIP", pod.HostIP),
zap.String("podIP", pod.PodIP),
),
}
// Initialize the host/pod IPv4
p.hostIPv4.UnmarshalText([]byte(pod.HostIP))
p.podIPv4.UnmarshalText([]byte(pod.PodIP))
return &p
}
// getClient returns a client that can be used to ping the given pod
// On error, it returns a static result
func (p *Pinger) getClient() (*apiclient.Goldpinger, error) {
if p.client != nil {
return p.client, nil
}
client, err := getClient(pickPodHostIP(p.pod.PodIP, p.pod.HostIP))
if err != nil {
p.logger.Warn("Could not get client", zap.Error(err))
OK := false
p.resultsChan <- PingAllPodsResult{
podName: p.pod.Name,
podResult: models.PodResult{
PingTime: strfmt.DateTime(time.Now()),
PodIP: p.podIPv4,
HostIP: p.hostIPv4,
OK: &OK,
Error: err.Error(),
StatusCode: 500,
ResponseTimeMs: 0,
},
}
return nil, err
}
p.client = client
return p.client, nil
}
// Ping makes a single ping request to the given pod
func (p *Pinger) Ping() {
client, err := p.getClient()
if err != nil {
return
}
CountCall("made", "ping")
start := time.Now()
ctx, cancel := context.WithTimeout(context.Background(), p.timeout)
defer cancel()
params := operations.NewPingParamsWithContext(ctx)
resp, err := client.Operations.Ping(params)
responseTime := time.Since(start)
responseTimeMs := responseTime.Nanoseconds() / int64(time.Millisecond)
p.histogram.Observe(responseTime.Seconds())
OK := (err == nil)
if OK {
p.resultsChan <- PingAllPodsResult{
podName: p.pod.Name,
podResult: models.PodResult{
PingTime: strfmt.DateTime(start),
PodIP: p.podIPv4,
HostIP: p.hostIPv4,
OK: &OK,
Response: resp.Payload,
StatusCode: 200,
ResponseTimeMs: responseTimeMs,
},
}
p.logger.Debug("Success pinging pod", zap.Duration("responseTime", responseTime))
} else {
p.resultsChan <- PingAllPodsResult{
podName: p.pod.Name,
podResult: models.PodResult{
PingTime: strfmt.DateTime(start),
PodIP: p.podIPv4,
HostIP: p.hostIPv4,
OK: &OK,
Error: err.Error(),
StatusCode: 504,
ResponseTimeMs: responseTimeMs,
},
}
p.logger.Warn("Ping returned error", zap.Duration("responseTime", responseTime), zap.Error(err))
CountError("ping")
}
}
// PingContinuously continuously pings the given pod with a delay between
// `period` and `period + jitterFactor * period`
func (p *Pinger) PingContinuously(initialWait time.Duration, period time.Duration, jitterFactor float64) {
p.logger.Info(
"Starting pinger",
zap.Duration("period", period),
zap.Duration("initialWait", initialWait),
zap.Float64("jitterFactor", jitterFactor),
)
timer := time.NewTimer(initialWait)
select {
case <-timer.C:
wait.JitterUntil(p.Ping, period, jitterFactor, false, p.stopChan)
case <-p.stopChan:
// Do nothing
}
// We are done, send a message on the results channel to delete this
p.resultsChan <- PingAllPodsResult{podName: p.pod.Name, deleted: true}
}

View File

@@ -0,0 +1,40 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package goldpinger
import (
"github.com/cespare/xxhash"
rendezvous "github.com/stuartnelson3/go-rendezvous"
)
// SelectPods selects a set of pods from the results of GetAllPods
// depending on the count according to a rendezvous hash
func SelectPods() map[string]*GoldpingerPod {
allPods := GetAllPods()
if GoldpingerConfig.PingNumber <= 0 || int(GoldpingerConfig.PingNumber) >= len(allPods) {
return allPods
}
rzv := rendezvous.New([]string{}, rendezvous.Hasher(xxhash.Sum64String))
for podName := range allPods {
rzv.Add(podName)
}
matches := rzv.LookupN(GoldpingerConfig.PodName, GoldpingerConfig.PingNumber)
toPing := make(map[string]*GoldpingerPod)
for _, podName := range matches {
toPing[podName] = allPods[podName]
}
return toPing
}

72
pkg/goldpinger/probes.go Normal file
View File

@@ -0,0 +1,72 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package goldpinger
import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"net/url"
"time"
)
func doDNSProbe(addr string, timeout time.Duration) error {
resolver := net.Resolver{}
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
ips, err := resolver.LookupHost(ctx, addr)
if len(ips) == 0 {
return fmt.Errorf("%s was resolved to 0 ips", addr)
}
return err
}
func doTCPProbe(addr string, timeout time.Duration) error {
conn, err := net.DialTimeout("tcp", addr, timeout)
if conn != nil {
defer conn.Close()
}
return err
}
func doHTTPProbe(addr string, timeout time.Duration) error {
client := http.Client{Timeout: timeout}
u, err := url.Parse(addr)
if err != nil {
return err
}
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("invalid url scheme: '%s' in address", u.Scheme)
}
if u.Scheme == "https" {
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
}
resp, err := client.Get(addr)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("%s returned non-200 resp: %d", addr, resp.StatusCode)
}
return err
}

View File

@@ -15,12 +15,13 @@
package goldpinger
import (
"log"
"context"
"time"
"github.com/bloomberg/goldpinger/pkg/models"
"github.com/bloomberg/goldpinger/v3/pkg/models"
"github.com/go-openapi/strfmt"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
)
var (
@@ -47,6 +48,16 @@ var (
},
)
goldpingerClusterHealthGauge = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "goldpinger_cluster_health_total",
Help: "1 if all check pass, 0 otherwise",
},
[]string{
"goldpinger_instance",
},
)
goldpingerResponseTimePeersHistogram = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "goldpinger_peers_response_time_s",
@@ -82,20 +93,53 @@ var (
"type",
},
)
goldpingerDnsErrorsCounter = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "goldpinger_dns_errors_total",
Help: "Statistics of DNS errors per instance",
},
[]string{
"goldpinger_instance",
"host",
},
)
goldPingerTcpErrorsCounter = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "goldpinger_tcp_errors_total",
Help: "Statistics of TCP probe errors per instance",
},
[]string{
"goldpinger_instance",
"host",
},
)
goldPingerHttpErrorsCounter = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "goldpinger_http_errors_total",
Help: "Statistics of HTTP probe errors per instance",
},
[]string{
"goldpinger_instance",
"host",
},
)
bootTime = time.Now()
)
func init() {
prometheus.MustRegister(goldpingerStatsCounter)
prometheus.MustRegister(goldpingerNodesHealthGauge)
prometheus.MustRegister(goldpingerClusterHealthGauge)
prometheus.MustRegister(goldpingerResponseTimePeersHistogram)
prometheus.MustRegister(goldpingerResponseTimeKubernetesHistogram)
prometheus.MustRegister(goldpingerErrorsCounter)
log.Println("Metrics setup - see /metrics")
prometheus.MustRegister(goldpingerDnsErrorsCounter)
prometheus.MustRegister(goldPingerHttpErrorsCounter)
prometheus.MustRegister(goldPingerTcpErrorsCounter)
zap.L().Info("Metrics setup - see /metrics")
}
func GetStats() *models.PingResults {
func GetStats(ctx context.Context) *models.PingResults {
// GetStats no longer populates the received and made calls - use metrics for that instead
return &models.PingResults{
BootTime: strfmt.DateTime(bootTime),
@@ -123,6 +167,17 @@ func CountHealthyUnhealthyNodes(healthy, unhealthy float64) {
).Set(unhealthy)
}
// SetClusterHealth sets the cluster health gauge to 1 (healthy) or 0 (unhealthy)
func SetClusterHealth(healthy bool) {
value := 1.0
if !healthy {
value = 0
}
goldpingerClusterHealthGauge.WithLabelValues(
GoldpingerConfig.Hostname,
).Set(value)
}
// counts instances of various errors
func CountError(errorType string) {
goldpingerErrorsCounter.WithLabelValues(
@@ -131,6 +186,30 @@ func CountError(errorType string) {
).Inc()
}
// counts instances of dns errors
func CountDnsError(host string) {
goldpingerDnsErrorsCounter.WithLabelValues(
GoldpingerConfig.Hostname,
host,
).Inc()
}
// CountTcpError counts instances of tcp errors for prober
func CountTcpError(host string) {
goldPingerTcpErrorsCounter.WithLabelValues(
GoldpingerConfig.Hostname,
host,
).Inc()
}
// CountHttpError counts instances of tcp errors for prober
func CountHttpError(host string) {
goldPingerHttpErrorsCounter.WithLabelValues(
GoldpingerConfig.Hostname,
host,
).Inc()
}
// returns a timer for easy observing of the durations of calls to kubernetes API
func GetLabeledKubernetesCallsTimer() *prometheus.Timer {
return prometheus.NewTimer(

View File

@@ -15,31 +15,195 @@
package goldpinger
import (
"fmt"
"log"
"sync"
"time"
"go.uber.org/zap"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
func StartUpdater() {
// checkResults holds the latest results of checking the pods
var checkResults = models.CheckResults{PodResults: make(map[string]models.PodResult)}
if GoldpingerConfig.RefreshInterval <= 0 {
log.Println("Not creating updater, period is 0")
// checkResultsMux controls concurrent access to checkResults
var checkResultsMux = sync.Mutex{}
// exists checks whether there is an existing pinger for the given pod
// returns true if:
// - there is already a pinger with the same name
// - the pinger has the same podIP
// - the pinger has the same hostIP
func exists(existingPods map[string]*GoldpingerPod, podName string, new *GoldpingerPod) bool {
old, exists := existingPods[podName]
return exists && (old.PodIP == new.PodIP) && (old.HostIP == new.HostIP)
}
// updatePingers calls SelectPods() at regular intervals to get a new list of goldpinger pods to ping
// For each goldpinger pod, it then creates a pinger responsible for pinging it and returning the
// results on the result channel
func updatePingers(resultsChan chan<- PingAllPodsResult) {
// Important: This is the only goroutine that should have access to
// these maps since there is nothing controlling concurrent access
pingers := make(map[string]*Pinger)
existingPods := make(map[string]*GoldpingerPod)
refreshPeriod := time.Duration(GoldpingerConfig.RefreshInterval) * time.Second
for {
// Initialize deletedPods to all existing pods, we will remove
// any pods that should still exist from this list after we are done
// NOTE: This is *NOT* a copy of existingPods just a new variable name
// to make the intention/code clear and cleaner
deletedPods := existingPods
// New pods are brand new and haven't been seen before
newPods := make(map[string]*GoldpingerPod)
latest := SelectPods()
for podName, pod := range latest {
if exists(existingPods, podName, pod) {
// This pod continues to exist in the latest iteration of the update
// without any changes
// Delete it from the set of pods that we wish to delete
delete(deletedPods, podName)
} else {
// This pod is brand new and has never been seen before
// Add it to the list of newPods
newPods[podName] = pod
}
}
// deletedPods now contains any pods that have either been deleted from the api-server
// *OR* weren't selected by our rendezvous hash
// *OR* had their host/pod IP changed. Remove those pingers
destroyPingers(pingers, deletedPods)
// Next create pingers for new pods
createPingers(pingers, newPods, resultsChan, refreshPeriod)
// Finally, just set existingPods to the latest and collect garbage
existingPods = latest
deletedPods = nil
newPods = nil
// Wait the given time before pinging
time.Sleep(refreshPeriod)
}
}
// createPingers allocates a new pinger object for each new goldpinger Pod that's been discovered
// It also:
// (a) initializes a result object in checkResults to store info on that pod
// (b) starts a new goroutines to continuously ping the given pod.
// Each new goroutine waits for a given time before starting the continuous ping
// to prevent a thundering herd
func createPingers(pingers map[string]*Pinger, newPods map[string]*GoldpingerPod, resultsChan chan<- PingAllPodsResult, refreshPeriod time.Duration) {
if len(newPods) == 0 {
// I have nothing to do
return
}
// start the updater
go func() {
for {
results := PingAllPods(GetAllPods())
var troublemakers []string
for podIP, value := range results {
if *value.OK != true {
troublemakers = append(troublemakers, fmt.Sprintf("%s (%s)", podIP, value.HostIP.String()))
waitBetweenPods := refreshPeriod / time.Duration(len(newPods))
zap.L().Info(
"Starting pingers for new pods",
zap.Int("numNewPods", len(newPods)),
zap.Duration("refreshPeriod", refreshPeriod),
zap.Duration("waitPeriod", waitBetweenPods),
zap.Float64("JitterFactor", GoldpingerConfig.JitterFactor),
)
initialWait := time.Duration(0)
for podName, pod := range newPods {
pinger := NewPinger(pod, resultsChan)
pingers[podName] = pinger
go pinger.PingContinuously(initialWait, refreshPeriod, GoldpingerConfig.JitterFactor)
initialWait += waitBetweenPods
}
}
// destroyPingers takes a list of deleted pods and then for each pod in the list, it stops
// the goroutines that continuously pings that pod and then deletes the pod from the list of pingers
func destroyPingers(pingers map[string]*Pinger, deletedPods map[string]*GoldpingerPod) {
for podName, pod := range deletedPods {
zap.L().Info(
"Deleting pod from pingers",
zap.String("name", podName),
zap.String("podIP", pod.PodIP),
zap.String("hostIP", pod.HostIP),
)
pinger := pingers[podName]
// Close the channel to stop pinging
close(pinger.stopChan)
// delete from pingers
delete(pingers, podName)
}
}
// updateCounters updates the count of health and unhealthy nodes
func updateCounters() {
checkResultsMux.Lock()
defer checkResultsMux.Unlock()
var counterHealthy float64
for _, result := range checkResults.PodResults {
if result.OK != nil && *result.OK {
counterHealthy++
}
}
CountHealthyUnhealthyNodes(counterHealthy, float64(len(checkResults.PodResults))-counterHealthy)
// check external targets, don't block the access to checkResultsMux
nodesHealthy := int(counterHealthy) == len(checkResults.PodResults)
go func(healthySoFar bool) {
if healthySoFar {
probeResults := checkTargets()
for host := range probeResults {
for _, response := range probeResults[host] {
if response.Error != "" {
healthySoFar = false
break
}
}
}
if len(troublemakers) > 0 {
log.Println("Updater ran into trouble with these peers: ", troublemakers)
}
time.Sleep(time.Duration(GoldpingerConfig.RefreshInterval) * time.Second)
}
}()
SetClusterHealth(healthySoFar)
}(nodesHealthy)
}
// collectResults simply reads results from the results channel and saves them in a map
func collectResults(resultsChan <-chan PingAllPodsResult) {
refreshPeriod := time.Duration(GoldpingerConfig.RefreshInterval) * time.Second
updateTicker := time.NewTicker(refreshPeriod)
for {
select {
case <-updateTicker.C:
// Every time our update ticker ticks, update the count of healthy/unhealthy nodes
updateCounters()
case response := <-resultsChan:
// On getting a ping response, if the pinger is not being deleted,
// simply save it for later
checkResultsMux.Lock()
if response.deleted {
delete(checkResults.PodResults, response.podName)
} else {
checkResults.PodResults[response.podName] = response.podResult
}
checkResultsMux.Unlock()
}
}
}
func StartUpdater() {
if GoldpingerConfig.RefreshInterval <= 0 {
zap.L().Info("Not creating updater, refresh interval is negative", zap.Int("RefreshInterval", GoldpingerConfig.RefreshInterval))
return
}
pods := SelectPods()
// Create a channel for the results
resultsChan := make(chan PingAllPodsResult, len(pods))
go updatePingers(resultsChan)
go collectResults(resultsChan)
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package models
@@ -20,12 +6,14 @@ package models
// Editing this file might prove futile when you re-run the swagger generate command
import (
strfmt "github.com/go-openapi/strfmt"
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// CallStats call stats
//
// swagger:model CallStats
type CallStats struct {
@@ -44,6 +32,11 @@ func (m *CallStats) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this call stats based on context it is used
func (m *CallStats) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *CallStats) MarshalBinary() ([]byte, error) {
if m == nil {

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package models
@@ -20,14 +6,16 @@ package models
// Editing this file might prove futile when you re-run the swagger generate command
import (
strfmt "github.com/go-openapi/strfmt"
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// CheckAllPodResult check all pod result
//
// swagger:model CheckAllPodResult
type CheckAllPodResult struct {
@@ -38,11 +26,15 @@ type CheckAllPodResult struct {
// o k
OK *bool `json:"OK,omitempty"`
// pod IP
// Format: ipv4
PodIP strfmt.IPv4 `json:"PodIP,omitempty"`
// error
Error string `json:"error,omitempty"`
// response
Response CheckResults `json:"response,omitempty"`
Response *CheckResults `json:"response,omitempty"`
// status code
StatusCode int32 `json:"status-code,omitempty"`
@@ -56,6 +48,10 @@ func (m *CheckAllPodResult) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validatePodIP(formats); err != nil {
res = append(res, err)
}
if err := m.validateResponse(formats); err != nil {
res = append(res, err)
}
@@ -67,7 +63,6 @@ func (m *CheckAllPodResult) Validate(formats strfmt.Registry) error {
}
func (m *CheckAllPodResult) validateHostIP(formats strfmt.Registry) error {
if swag.IsZero(m.HostIP) { // not required
return nil
}
@@ -79,17 +74,62 @@ func (m *CheckAllPodResult) validateHostIP(formats strfmt.Registry) error {
return nil
}
func (m *CheckAllPodResult) validateResponse(formats strfmt.Registry) error {
func (m *CheckAllPodResult) validatePodIP(formats strfmt.Registry) error {
if swag.IsZero(m.PodIP) { // not required
return nil
}
if err := validate.FormatOf("PodIP", "body", "ipv4", m.PodIP.String(), formats); err != nil {
return err
}
return nil
}
func (m *CheckAllPodResult) validateResponse(formats strfmt.Registry) error {
if swag.IsZero(m.Response) { // not required
return nil
}
if err := m.Response.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("response")
if m.Response != nil {
if err := m.Response.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("response")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("response")
}
return err
}
}
return nil
}
// ContextValidate validate this check all pod result based on the context it is used
func (m *CheckAllPodResult) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateResponse(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *CheckAllPodResult) contextValidateResponse(ctx context.Context, formats strfmt.Registry) error {
if m.Response != nil {
if err := m.Response.ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("response")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("response")
}
return err
}
return err
}
return nil

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package models
@@ -20,16 +6,17 @@ package models
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"strconv"
strfmt "github.com/go-openapi/strfmt"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// CheckAllResults check all results
//
// swagger:model CheckAllResults
type CheckAllResults struct {
@@ -45,6 +32,9 @@ type CheckAllResults struct {
// hosts number
HostsNumber int32 `json:"hosts-number,omitempty"`
// probe results
ProbeResults map[string]ProbeResults `json:"probeResults,omitempty"`
// responses
Responses map[string]CheckAllPodResult `json:"responses,omitempty"`
}
@@ -57,6 +47,10 @@ func (m *CheckAllResults) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validateProbeResults(formats); err != nil {
res = append(res, err)
}
if err := m.validateResponses(formats); err != nil {
res = append(res, err)
}
@@ -68,7 +62,6 @@ func (m *CheckAllResults) Validate(formats strfmt.Registry) error {
}
func (m *CheckAllResults) validateHosts(formats strfmt.Registry) error {
if swag.IsZero(m.Hosts) { // not required
return nil
}
@@ -82,6 +75,8 @@ func (m *CheckAllResults) validateHosts(formats strfmt.Registry) error {
if err := m.Hosts[i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("hosts" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("hosts" + "." + strconv.Itoa(i))
}
return err
}
@@ -92,8 +87,25 @@ func (m *CheckAllResults) validateHosts(formats strfmt.Registry) error {
return nil
}
func (m *CheckAllResults) validateResponses(formats strfmt.Registry) error {
func (m *CheckAllResults) validateProbeResults(formats strfmt.Registry) error {
if swag.IsZero(m.ProbeResults) { // not required
return nil
}
for k := range m.ProbeResults {
if val, ok := m.ProbeResults[k]; ok {
if err := val.Validate(formats); err != nil {
return err
}
}
}
return nil
}
func (m *CheckAllResults) validateResponses(formats strfmt.Registry) error {
if swag.IsZero(m.Responses) { // not required
return nil
}
@@ -105,6 +117,83 @@ func (m *CheckAllResults) validateResponses(formats strfmt.Registry) error {
}
if val, ok := m.Responses[k]; ok {
if err := val.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("responses" + "." + k)
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("responses" + "." + k)
}
return err
}
}
}
return nil
}
// ContextValidate validate this check all results based on the context it is used
func (m *CheckAllResults) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateHosts(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateProbeResults(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateResponses(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *CheckAllResults) contextValidateHosts(ctx context.Context, formats strfmt.Registry) error {
for i := 0; i < len(m.Hosts); i++ {
if m.Hosts[i] != nil {
if err := m.Hosts[i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("hosts" + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("hosts" + "." + strconv.Itoa(i))
}
return err
}
}
}
return nil
}
func (m *CheckAllResults) contextValidateProbeResults(ctx context.Context, formats strfmt.Registry) error {
for k := range m.ProbeResults {
if val, ok := m.ProbeResults[k]; ok {
if err := val.ContextValidate(ctx, formats); err != nil {
return err
}
}
}
return nil
}
func (m *CheckAllResults) contextValidateResponses(ctx context.Context, formats strfmt.Registry) error {
for k := range m.Responses {
if val, ok := m.Responses[k]; ok {
if err := val.ContextValidate(ctx, formats); err != nil {
return err
}
}
@@ -133,6 +222,7 @@ func (m *CheckAllResults) UnmarshalBinary(b []byte) error {
}
// CheckAllResultsHostsItems0 check all results hosts items0
//
// swagger:model CheckAllResultsHostsItems0
type CheckAllResultsHostsItems0 struct {
@@ -143,6 +233,9 @@ type CheckAllResultsHostsItems0 struct {
// pod IP
// Format: ipv4
PodIP strfmt.IPv4 `json:"podIP,omitempty"`
// pod name
PodName string `json:"podName,omitempty"`
}
// Validate validates this check all results hosts items0
@@ -164,7 +257,6 @@ func (m *CheckAllResultsHostsItems0) Validate(formats strfmt.Registry) error {
}
func (m *CheckAllResultsHostsItems0) validateHostIP(formats strfmt.Registry) error {
if swag.IsZero(m.HostIP) { // not required
return nil
}
@@ -177,7 +269,6 @@ func (m *CheckAllResultsHostsItems0) validateHostIP(formats strfmt.Registry) err
}
func (m *CheckAllResultsHostsItems0) validatePodIP(formats strfmt.Registry) error {
if swag.IsZero(m.PodIP) { // not required
return nil
}
@@ -189,6 +280,11 @@ func (m *CheckAllResultsHostsItems0) validatePodIP(formats strfmt.Registry) erro
return nil
}
// ContextValidate validates this check all results hosts items0 based on context it is used
func (m *CheckAllResultsHostsItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *CheckAllResultsHostsItems0) MarshalBinary() ([]byte, error) {
if m == nil {

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package models
@@ -20,31 +6,36 @@ package models
// Editing this file might prove futile when you re-run the swagger generate command
import (
strfmt "github.com/go-openapi/strfmt"
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// CheckResults check results
//
// swagger:model CheckResults
type CheckResults map[string]PodResult
type CheckResults struct {
// pod results
PodResults map[string]PodResult `json:"podResults,omitempty"`
// probe results
ProbeResults ProbeResults `json:"probeResults,omitempty"`
}
// Validate validates this check results
func (m CheckResults) Validate(formats strfmt.Registry) error {
func (m *CheckResults) Validate(formats strfmt.Registry) error {
var res []error
for k := range m {
if err := validate.Required(k, "body", m[k]); err != nil {
return err
}
if val, ok := m[k]; ok {
if err := val.Validate(formats); err != nil {
return err
}
}
if err := m.validatePodResults(formats); err != nil {
res = append(res, err)
}
if err := m.validateProbeResults(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
@@ -52,3 +43,113 @@ func (m CheckResults) Validate(formats strfmt.Registry) error {
}
return nil
}
func (m *CheckResults) validatePodResults(formats strfmt.Registry) error {
if swag.IsZero(m.PodResults) { // not required
return nil
}
for k := range m.PodResults {
if err := validate.Required("podResults"+"."+k, "body", m.PodResults[k]); err != nil {
return err
}
if val, ok := m.PodResults[k]; ok {
if err := val.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("podResults" + "." + k)
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("podResults" + "." + k)
}
return err
}
}
}
return nil
}
func (m *CheckResults) validateProbeResults(formats strfmt.Registry) error {
if swag.IsZero(m.ProbeResults) { // not required
return nil
}
if m.ProbeResults != nil {
if err := m.ProbeResults.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("probeResults")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("probeResults")
}
return err
}
}
return nil
}
// ContextValidate validate this check results based on the context it is used
func (m *CheckResults) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidatePodResults(ctx, formats); err != nil {
res = append(res, err)
}
if err := m.contextValidateProbeResults(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *CheckResults) contextValidatePodResults(ctx context.Context, formats strfmt.Registry) error {
for k := range m.PodResults {
if val, ok := m.PodResults[k]; ok {
if err := val.ContextValidate(ctx, formats); err != nil {
return err
}
}
}
return nil
}
func (m *CheckResults) contextValidateProbeResults(ctx context.Context, formats strfmt.Registry) error {
if err := m.ProbeResults.ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("probeResults")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("probeResults")
}
return err
}
return nil
}
// MarshalBinary interface implementation
func (m *CheckResults) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *CheckResults) UnmarshalBinary(b []byte) error {
var res CheckResults
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,103 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// ClusterHealthResults cluster health results
//
// swagger:model ClusterHealthResults
type ClusterHealthResults struct {
// o k
// Required: true
OK bool `json:"OK"`
// duration ns
DurationNs int64 `json:"duration-ns,omitempty"`
// generated at
// Format: date-time
GeneratedAt strfmt.DateTime `json:"generated-at,omitempty"`
// nodes healthy
NodesHealthy []string `json:"nodesHealthy"`
// nodes total
NodesTotal int64 `json:"nodesTotal,omitempty"`
// nodes unhealthy
NodesUnhealthy []string `json:"nodesUnhealthy"`
}
// Validate validates this cluster health results
func (m *ClusterHealthResults) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateOK(formats); err != nil {
res = append(res, err)
}
if err := m.validateGeneratedAt(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *ClusterHealthResults) validateOK(formats strfmt.Registry) error {
if err := validate.Required("OK", "body", bool(m.OK)); err != nil {
return err
}
return nil
}
func (m *ClusterHealthResults) validateGeneratedAt(formats strfmt.Registry) error {
if swag.IsZero(m.GeneratedAt) { // not required
return nil
}
if err := validate.FormatOf("generated-at", "body", "date-time", m.GeneratedAt.String(), formats); err != nil {
return err
}
return nil
}
// ContextValidate validates this cluster health results based on context it is used
func (m *ClusterHealthResults) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *ClusterHealthResults) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ClusterHealthResults) UnmarshalBinary(b []byte) error {
var res ClusterHealthResults
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

53
pkg/models/dns_result.go Normal file
View File

@@ -0,0 +1,53 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// DNSResult Dns result
//
// swagger:model DnsResult
type DNSResult struct {
// error
Error string `json:"error,omitempty"`
// response time ms
ResponseTimeMs int64 `json:"response-time-ms,omitempty"`
}
// Validate validates this Dns result
func (m *DNSResult) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this Dns result based on context it is used
func (m *DNSResult) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *DNSResult) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *DNSResult) UnmarshalBinary(b []byte) error {
var res DNSResult
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

62
pkg/models/dns_results.go Normal file
View File

@@ -0,0 +1,62 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/validate"
)
// DNSResults Dns results
//
// swagger:model DnsResults
type DNSResults map[string]DNSResult
// Validate validates this Dns results
func (m DNSResults) Validate(formats strfmt.Registry) error {
var res []error
for k := range m {
if err := validate.Required(k, "body", m[k]); err != nil {
return err
}
if val, ok := m[k]; ok {
if err := val.Validate(formats); err != nil {
return err
}
}
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// ContextValidate validate this Dns results based on the context it is used
func (m DNSResults) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
for k := range m {
if val, ok := m[k]; ok {
if err := val.ContextValidate(ctx, formats); err != nil {
return err
}
}
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,80 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// HealthCheckResults health check results
//
// swagger:model HealthCheckResults
type HealthCheckResults struct {
// o k
OK *bool `json:"OK,omitempty"`
// duration ns
DurationNs int64 `json:"duration-ns,omitempty"`
// generated at
// Format: date-time
GeneratedAt strfmt.DateTime `json:"generated-at,omitempty"`
}
// Validate validates this health check results
func (m *HealthCheckResults) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateGeneratedAt(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *HealthCheckResults) validateGeneratedAt(formats strfmt.Registry) error {
if swag.IsZero(m.GeneratedAt) { // not required
return nil
}
if err := validate.FormatOf("generated-at", "body", "date-time", m.GeneratedAt.String(), formats); err != nil {
return err
}
return nil
}
// ContextValidate validates this health check results based on context it is used
func (m *HealthCheckResults) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *HealthCheckResults) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *HealthCheckResults) UnmarshalBinary(b []byte) error {
var res HealthCheckResults
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package models
@@ -20,14 +6,16 @@ package models
// Editing this file might prove futile when you re-run the swagger generate command
import (
strfmt "github.com/go-openapi/strfmt"
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// PingResults ping results
//
// swagger:model PingResults
type PingResults struct {
@@ -58,7 +46,6 @@ func (m *PingResults) Validate(formats strfmt.Registry) error {
}
func (m *PingResults) validateBootTime(formats strfmt.Registry) error {
if swag.IsZero(m.BootTime) { // not required
return nil
}
@@ -71,7 +58,6 @@ func (m *PingResults) validateBootTime(formats strfmt.Registry) error {
}
func (m *PingResults) validateReceived(formats strfmt.Registry) error {
if swag.IsZero(m.Received) { // not required
return nil
}
@@ -80,6 +66,38 @@ func (m *PingResults) validateReceived(formats strfmt.Registry) error {
if err := m.Received.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("received")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("received")
}
return err
}
}
return nil
}
// ContextValidate validate this ping results based on the context it is used
func (m *PingResults) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateReceived(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *PingResults) contextValidateReceived(ctx context.Context, formats strfmt.Registry) error {
if m.Received != nil {
if err := m.Received.ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("received")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("received")
}
return err
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package models
@@ -20,14 +6,16 @@ package models
// Editing this file might prove futile when you re-run the swagger generate command
import (
strfmt "github.com/go-openapi/strfmt"
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// PodResult pod result
//
// swagger:model PodResult
type PodResult struct {
@@ -38,12 +26,23 @@ type PodResult struct {
// o k
OK *bool `json:"OK,omitempty"`
// ping time
// Format: date-time
PingTime strfmt.DateTime `json:"PingTime,omitempty"`
// pod IP
// Format: ipv4
PodIP strfmt.IPv4 `json:"PodIP,omitempty"`
// error
Error string `json:"error,omitempty"`
// response
Response *PingResults `json:"response,omitempty"`
// wall clock time in milliseconds
ResponseTimeMs int64 `json:"response-time-ms,omitempty"`
// status code
StatusCode int32 `json:"status-code,omitempty"`
}
@@ -56,6 +55,14 @@ func (m *PodResult) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
if err := m.validatePingTime(formats); err != nil {
res = append(res, err)
}
if err := m.validatePodIP(formats); err != nil {
res = append(res, err)
}
if err := m.validateResponse(formats); err != nil {
res = append(res, err)
}
@@ -67,7 +74,6 @@ func (m *PodResult) Validate(formats strfmt.Registry) error {
}
func (m *PodResult) validateHostIP(formats strfmt.Registry) error {
if swag.IsZero(m.HostIP) { // not required
return nil
}
@@ -79,8 +85,31 @@ func (m *PodResult) validateHostIP(formats strfmt.Registry) error {
return nil
}
func (m *PodResult) validateResponse(formats strfmt.Registry) error {
func (m *PodResult) validatePingTime(formats strfmt.Registry) error {
if swag.IsZero(m.PingTime) { // not required
return nil
}
if err := validate.FormatOf("PingTime", "body", "date-time", m.PingTime.String(), formats); err != nil {
return err
}
return nil
}
func (m *PodResult) validatePodIP(formats strfmt.Registry) error {
if swag.IsZero(m.PodIP) { // not required
return nil
}
if err := validate.FormatOf("PodIP", "body", "ipv4", m.PodIP.String(), formats); err != nil {
return err
}
return nil
}
func (m *PodResult) validateResponse(formats strfmt.Registry) error {
if swag.IsZero(m.Response) { // not required
return nil
}
@@ -89,6 +118,38 @@ func (m *PodResult) validateResponse(formats strfmt.Registry) error {
if err := m.Response.Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("response")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("response")
}
return err
}
}
return nil
}
// ContextValidate validate this pod result based on the context it is used
func (m *PodResult) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
if err := m.contextValidateResponse(ctx, formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *PodResult) contextValidateResponse(ctx context.Context, formats strfmt.Registry) error {
if m.Response != nil {
if err := m.Response.ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName("response")
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName("response")
}
return err
}

View File

@@ -0,0 +1,56 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
// ProbeResult probe result
//
// swagger:model ProbeResult
type ProbeResult struct {
// error
Error string `json:"error,omitempty"`
// protocol
Protocol string `json:"protocol,omitempty"`
// response time ms
ResponseTimeMs int64 `json:"response-time-ms,omitempty"`
}
// Validate validates this probe result
func (m *ProbeResult) Validate(formats strfmt.Registry) error {
return nil
}
// ContextValidate validates this probe result based on context it is used
func (m *ProbeResult) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *ProbeResult) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *ProbeResult) UnmarshalBinary(b []byte) error {
var res ProbeResult
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View File

@@ -0,0 +1,78 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"strconv"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/validate"
)
// ProbeResults probe results
//
// swagger:model ProbeResults
type ProbeResults map[string][]ProbeResult
// Validate validates this probe results
func (m ProbeResults) Validate(formats strfmt.Registry) error {
var res []error
for k := range m {
if err := validate.Required(k, "body", m[k]); err != nil {
return err
}
for i := 0; i < len(m[k]); i++ {
if err := m[k][i].Validate(formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName(k + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName(k + "." + strconv.Itoa(i))
}
return err
}
}
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// ContextValidate validate this probe results based on the context it is used
func (m ProbeResults) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
var res []error
for k := range m {
for i := 0; i < len(m[k]); i++ {
if err := m[k][i].ContextValidate(ctx, formats); err != nil {
if ve, ok := err.(*errors.Validation); ok {
return ve.ValidateName(k + "." + strconv.Itoa(i))
} else if ce, ok := err.(*errors.CompositeError); ok {
return ce.ValidateName(k + "." + strconv.Itoa(i))
}
return err
}
}
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -17,8 +17,8 @@
package restapi
import (
"context"
"crypto/tls"
"log"
"net/http"
"strings"
@@ -26,9 +26,10 @@ import (
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"go.uber.org/zap"
"github.com/bloomberg/goldpinger/pkg/goldpinger"
"github.com/bloomberg/goldpinger/pkg/restapi/operations"
"github.com/bloomberg/goldpinger/v3/pkg/goldpinger"
"github.com/bloomberg/goldpinger/v3/pkg/restapi/operations"
"github.com/go-openapi/swag"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
@@ -47,6 +48,7 @@ func configureFlags(api *operations.GoldpingerAPI) {
func configureAPI(api *operations.GoldpingerAPI) http.Handler {
// configure the api here
api.Logger = zap.S().Infof
api.ServeError = errors.ServeError
api.JSONConsumer = runtime.JSONConsumer()
@@ -55,19 +57,69 @@ func configureAPI(api *operations.GoldpingerAPI) http.Handler {
api.PingHandler = operations.PingHandlerFunc(
func(params operations.PingParams) middleware.Responder {
goldpinger.CountCall("received", "ping")
return operations.NewPingOK().WithPayload(goldpinger.GetStats())
ctx, cancel := context.WithTimeout(
params.HTTPRequest.Context(),
goldpinger.GoldpingerConfig.PingTimeout,
)
defer cancel()
return operations.NewPingOK().WithPayload(goldpinger.GetStats(ctx))
})
api.CheckServicePodsHandler = operations.CheckServicePodsHandlerFunc(
func(params operations.CheckServicePodsParams) middleware.Responder {
goldpinger.CountCall("received", "check")
return operations.NewCheckServicePodsOK().WithPayload(goldpinger.CheckNeighbours())
ctx, cancel := context.WithTimeout(
params.HTTPRequest.Context(),
goldpinger.GoldpingerConfig.CheckTimeout,
)
defer cancel()
return operations.NewCheckServicePodsOK().WithPayload(goldpinger.CheckNeighbours(ctx))
})
api.CheckAllPodsHandler = operations.CheckAllPodsHandlerFunc(
func(params operations.CheckAllPodsParams) middleware.Responder {
goldpinger.CountCall("received", "check_all")
return operations.NewCheckAllPodsOK().WithPayload(goldpinger.CheckNeighboursNeighbours())
ctx, cancel := context.WithTimeout(
params.HTTPRequest.Context(),
goldpinger.GoldpingerConfig.CheckAllTimeout,
)
defer cancel()
return operations.NewCheckAllPodsOK().WithPayload(goldpinger.CheckNeighboursNeighbours(ctx))
})
api.ClusterHealthHandler = operations.ClusterHealthHandlerFunc(
func(params operations.ClusterHealthParams) middleware.Responder {
goldpinger.CountCall("received", "cluster_health")
ctx, cancel := context.WithTimeout(
params.HTTPRequest.Context(),
goldpinger.GoldpingerConfig.CheckAllTimeout,
)
defer cancel()
payload := goldpinger.CheckCluster(ctx)
if payload.OK {
return operations.NewClusterHealthOK().WithPayload(payload)
} else {
return operations.NewClusterHealthIMATeapot().WithPayload(payload)
}
})
api.HealthzHandler = operations.HealthzHandlerFunc(
func(params operations.HealthzParams) middleware.Responder {
goldpinger.CountCall("received", "healthz")
healthResult := goldpinger.HealthCheck()
if *healthResult.OK {
return operations.NewHealthzOK().WithPayload(healthResult)
} else {
return operations.NewHealthzServiceUnavailable().WithPayload(healthResult)
}
})
api.ServerShutdown = func() {}
@@ -94,11 +146,13 @@ func setupMiddlewares(handler http.Handler) http.Handler {
}
func fileServerMiddleware(next http.Handler) http.Handler {
log.Println("Added the static middleware")
zap.L().Info("Added the static middleware")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fileServer := http.FileServer(http.Dir(goldpinger.GoldpingerConfig.StaticFilePath))
if r.URL.Path == "/" {
http.StripPrefix("/", fileServer).ServeHTTP(w, r)
} else if r.URL.Path == "/heatmap.png" {
goldpinger.HeatmapHandler(w, r)
} else if strings.HasPrefix(r.URL.Path, "/static/") {
http.StripPrefix("/static/", fileServer).ServeHTTP(w, r)
} else {
@@ -109,7 +163,7 @@ func fileServerMiddleware(next http.Handler) http.Handler {
}
func prometheusMetricsMiddleware(next http.Handler) http.Handler {
log.Println("Added the prometheus middleware")
zap.L().Info("Added the prometheus middleware")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/metrics" {
http.StripPrefix("/metrics", promhttp.Handler()).ServeHTTP(w, r)

View File

@@ -1,34 +1,18 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
/*
Package restapi Goldpinger
Schemes:
http
Host: localhost
BasePath: /
Version: 1.0.0
Consumes:
- application/json
Produces:
- application/json
swagger:meta
*/
// Package restapi Goldpinger
//
// Schemes:
// http
// Host: localhost
// BasePath: /
// Version: 3.0.0
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// swagger:meta
package restapi

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package restapi
@@ -35,7 +21,7 @@ func init() {
"swagger": "2.0",
"info": {
"title": "Goldpinger",
"version": "1.0.0"
"version": "3.0.0"
},
"paths": {
"/check": {
@@ -72,6 +58,52 @@ func init() {
}
}
},
"/cluster_health": {
"get": {
"description": "Checks the full graph. Returns a binary OK or not OK.",
"produces": [
"application/json"
],
"operationId": "clusterHealth",
"responses": {
"200": {
"description": "Healthy cluster",
"schema": {
"$ref": "#/definitions/ClusterHealthResults"
}
},
"418": {
"description": "Unhealthy cluster",
"schema": {
"$ref": "#/definitions/ClusterHealthResults"
}
}
}
}
},
"/healthz": {
"get": {
"description": "The healthcheck endpoint provides detailed information about the health of a web service. If each of the components required by the service are healthy, then the service is considered healthy and will return a 200 OK response. If any of the components needed by the service are unhealthy, then a 503 Service Unavailable response will be provided.",
"produces": [
"application/json"
],
"operationId": "healthz",
"responses": {
"200": {
"description": "Health check report",
"schema": {
"$ref": "#/definitions/HealthCheckResults"
}
},
"503": {
"description": "Unhealthy service",
"schema": {
"$ref": "#/definitions/HealthCheckResults"
}
}
}
}
},
"/ping": {
"get": {
"description": "return query stats",
@@ -115,6 +147,10 @@ func init() {
"type": "boolean",
"default": false
},
"PodIP": {
"type": "string",
"format": "ipv4"
},
"error": {
"type": "string"
},
@@ -134,6 +170,12 @@ func init() {
"type": "boolean",
"default": false
},
"dnsResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/DnsResults"
}
},
"hosts": {
"type": "array",
"items": {
@@ -146,6 +188,9 @@ func init() {
"podIP": {
"type": "string",
"format": "ipv4"
},
"podName": {
"type": "string"
}
}
}
@@ -158,18 +203,109 @@ func init() {
"type": "integer",
"format": "int32"
},
"httpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/HttpResults"
}
},
"responses": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/CheckAllPodResult"
}
},
"tcpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/TcpResults"
}
}
}
},
"CheckResults": {
"type": "object",
"properties": {
"dnsResults": {
"$ref": "#/definitions/DnsResults"
},
"httpResults": {
"$ref": "#/definitions/HttpResults"
},
"podResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/PodResult"
}
},
"tcpResults": {
"$ref": "#/definitions/TcpResults"
}
}
},
"ClusterHealthResults": {
"type": "object",
"required": [
"OK"
],
"properties": {
"OK": {
"type": "boolean",
"default": false
},
"duration-ns": {
"type": "integer",
"format": "int64"
},
"generated-at": {
"type": "string",
"format": "date-time"
},
"nodesHealthy": {
"type": "array",
"items": {
"type": "string"
}
},
"nodesTotal": {
"type": "integer",
"format": "int64"
},
"nodesUnhealthy": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"DnsResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/PodResult"
"$ref": "#/definitions/ProbeResult"
}
},
"HealthCheckResults": {
"type": "object",
"properties": {
"OK": {
"type": "boolean",
"default": false
},
"duration-ns": {
"type": "integer",
"format": "int64"
},
"generated-at": {
"type": "string",
"format": "date-time"
}
}
},
"HttpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/ProbeResult"
}
},
"PingResults": {
@@ -195,17 +331,47 @@ func init() {
"type": "boolean",
"default": false
},
"PingTime": {
"type": "string",
"format": "date-time"
},
"PodIP": {
"type": "string",
"format": "ipv4"
},
"error": {
"type": "string"
},
"response": {
"$ref": "#/definitions/PingResults"
},
"response-time-ms": {
"description": "wall clock time in milliseconds",
"type": "number",
"format": "int64"
},
"status-code": {
"type": "integer",
"format": "int32"
}
}
},
"ProbeResult": {
"properties": {
"error": {
"type": "string"
},
"response-time-ms": {
"type": "number",
"format": "int64"
}
}
},
"TcpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/ProbeResult"
}
}
}
}`))
@@ -213,7 +379,7 @@ func init() {
"swagger": "2.0",
"info": {
"title": "Goldpinger",
"version": "1.0.0"
"version": "3.0.0"
},
"paths": {
"/check": {
@@ -250,6 +416,52 @@ func init() {
}
}
},
"/cluster_health": {
"get": {
"description": "Checks the full graph. Returns a binary OK or not OK.",
"produces": [
"application/json"
],
"operationId": "clusterHealth",
"responses": {
"200": {
"description": "Healthy cluster",
"schema": {
"$ref": "#/definitions/ClusterHealthResults"
}
},
"418": {
"description": "Unhealthy cluster",
"schema": {
"$ref": "#/definitions/ClusterHealthResults"
}
}
}
}
},
"/healthz": {
"get": {
"description": "The healthcheck endpoint provides detailed information about the health of a web service. If each of the components required by the service are healthy, then the service is considered healthy and will return a 200 OK response. If any of the components needed by the service are unhealthy, then a 503 Service Unavailable response will be provided.",
"produces": [
"application/json"
],
"operationId": "healthz",
"responses": {
"200": {
"description": "Health check report",
"schema": {
"$ref": "#/definitions/HealthCheckResults"
}
},
"503": {
"description": "Unhealthy service",
"schema": {
"$ref": "#/definitions/HealthCheckResults"
}
}
}
}
},
"/ping": {
"get": {
"description": "return query stats",
@@ -293,6 +505,10 @@ func init() {
"type": "boolean",
"default": false
},
"PodIP": {
"type": "string",
"format": "ipv4"
},
"error": {
"type": "string"
},
@@ -312,20 +528,16 @@ func init() {
"type": "boolean",
"default": false
},
"dnsResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/DnsResults"
}
},
"hosts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"hostIP": {
"type": "string",
"format": "ipv4"
},
"podIP": {
"type": "string",
"format": "ipv4"
}
}
"$ref": "#/definitions/CheckAllResultsHostsItems0"
}
},
"hosts-healthy": {
@@ -336,18 +548,125 @@ func init() {
"type": "integer",
"format": "int32"
},
"httpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/HttpResults"
}
},
"responses": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/CheckAllPodResult"
}
},
"tcpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/TcpResults"
}
}
}
},
"CheckAllResultsHostsItems0": {
"type": "object",
"properties": {
"hostIP": {
"type": "string",
"format": "ipv4"
},
"podIP": {
"type": "string",
"format": "ipv4"
},
"podName": {
"type": "string"
}
}
},
"CheckResults": {
"type": "object",
"properties": {
"dnsResults": {
"$ref": "#/definitions/DnsResults"
},
"httpResults": {
"$ref": "#/definitions/HttpResults"
},
"podResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/PodResult"
}
},
"tcpResults": {
"$ref": "#/definitions/TcpResults"
}
}
},
"ClusterHealthResults": {
"type": "object",
"required": [
"OK"
],
"properties": {
"OK": {
"type": "boolean",
"default": false
},
"duration-ns": {
"type": "integer",
"format": "int64"
},
"generated-at": {
"type": "string",
"format": "date-time"
},
"nodesHealthy": {
"type": "array",
"items": {
"type": "string"
}
},
"nodesTotal": {
"type": "integer",
"format": "int64"
},
"nodesUnhealthy": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"DnsResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/PodResult"
"$ref": "#/definitions/ProbeResult"
}
},
"HealthCheckResults": {
"type": "object",
"properties": {
"OK": {
"type": "boolean",
"default": false
},
"duration-ns": {
"type": "integer",
"format": "int64"
},
"generated-at": {
"type": "string",
"format": "date-time"
}
}
},
"HttpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/ProbeResult"
}
},
"PingResults": {
@@ -373,17 +692,47 @@ func init() {
"type": "boolean",
"default": false
},
"PingTime": {
"type": "string",
"format": "date-time"
},
"PodIP": {
"type": "string",
"format": "ipv4"
},
"error": {
"type": "string"
},
"response": {
"$ref": "#/definitions/PingResults"
},
"response-time-ms": {
"description": "wall clock time in milliseconds",
"type": "number",
"format": "int64"
},
"status-code": {
"type": "integer",
"format": "int32"
}
}
},
"ProbeResult": {
"properties": {
"error": {
"type": "string"
},
"response-time-ms": {
"type": "number",
"format": "int64"
}
}
},
"TcpResults": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/ProbeResult"
}
}
}
}`))

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -22,7 +8,7 @@ package operations
import (
"net/http"
middleware "github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/runtime/middleware"
)
// CheckAllPodsHandlerFunc turns a function with the right signature into a check all pods handler
@@ -43,7 +29,7 @@ func NewCheckAllPods(ctx *middleware.Context, handler CheckAllPodsHandler) *Chec
return &CheckAllPods{Context: ctx, Handler: handler}
}
/*CheckAllPods swagger:route GET /check_all checkAllPods
/* CheckAllPods swagger:route GET /check_all checkAllPods
Queries the API server for all other pods in this service, and makes all of them query all of their neighbours, using their pods IPs. Calls their /check endpoint.
@@ -56,17 +42,15 @@ type CheckAllPods struct {
func (o *CheckAllPods) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
r = rCtx
*r = *rCtx
}
var Params = NewCheckAllPodsParams()
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -27,7 +13,8 @@ import (
)
// NewCheckAllPodsParams creates a new CheckAllPodsParams object
// no default values defined in spec.
//
// There are no default values defined in the spec.
func NewCheckAllPodsParams() CheckAllPodsParams {
return CheckAllPodsParams{}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -24,7 +10,7 @@ import (
"github.com/go-openapi/runtime"
models "github.com/bloomberg/goldpinger/pkg/models"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// CheckAllPodsOKCode is the HTTP code returned for type CheckAllPodsOK

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -47,14 +33,14 @@ func (o *CheckAllPodsURL) SetBasePath(bp string) {
// Build a url path and query string
func (o *CheckAllPodsURL) Build() (*url.URL, error) {
var result url.URL
var _result url.URL
var _path = "/check_all"
_basePath := o._basePath
result.Path = golangswaggerpaths.Join(_basePath, _path)
_result.Path = golangswaggerpaths.Join(_basePath, _path)
return &result, nil
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -22,7 +8,7 @@ package operations
import (
"net/http"
middleware "github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/runtime/middleware"
)
// CheckServicePodsHandlerFunc turns a function with the right signature into a check service pods handler
@@ -43,7 +29,7 @@ func NewCheckServicePods(ctx *middleware.Context, handler CheckServicePodsHandle
return &CheckServicePods{Context: ctx, Handler: handler}
}
/*CheckServicePods swagger:route GET /check checkServicePods
/* CheckServicePods swagger:route GET /check checkServicePods
Queries the API server for all other pods in this service, and pings them via their pods IPs. Calls their /ping endpoint
@@ -56,17 +42,15 @@ type CheckServicePods struct {
func (o *CheckServicePods) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
r = rCtx
*r = *rCtx
}
var Params = NewCheckServicePodsParams()
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -27,7 +13,8 @@ import (
)
// NewCheckServicePodsParams creates a new CheckServicePodsParams object
// no default values defined in spec.
//
// There are no default values defined in the spec.
func NewCheckServicePodsParams() CheckServicePodsParams {
return CheckServicePodsParams{}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -24,7 +10,7 @@ import (
"github.com/go-openapi/runtime"
models "github.com/bloomberg/goldpinger/pkg/models"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// CheckServicePodsOKCode is the HTTP code returned for type CheckServicePodsOK
@@ -39,7 +25,7 @@ type CheckServicePodsOK struct {
/*
In: Body
*/
Payload models.CheckResults `json:"body,omitempty"`
Payload *models.CheckResults `json:"body,omitempty"`
}
// NewCheckServicePodsOK creates CheckServicePodsOK with default headers values
@@ -49,13 +35,13 @@ func NewCheckServicePodsOK() *CheckServicePodsOK {
}
// WithPayload adds the payload to the check service pods o k response
func (o *CheckServicePodsOK) WithPayload(payload models.CheckResults) *CheckServicePodsOK {
func (o *CheckServicePodsOK) WithPayload(payload *models.CheckResults) *CheckServicePodsOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the check service pods o k response
func (o *CheckServicePodsOK) SetPayload(payload models.CheckResults) {
func (o *CheckServicePodsOK) SetPayload(payload *models.CheckResults) {
o.Payload = payload
}
@@ -63,9 +49,10 @@ func (o *CheckServicePodsOK) SetPayload(payload models.CheckResults) {
func (o *CheckServicePodsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(200)
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -47,14 +33,14 @@ func (o *CheckServicePodsURL) SetBasePath(bp string) {
// Build a url path and query string
func (o *CheckServicePodsURL) Build() (*url.URL, error) {
var result url.URL
var _result url.URL
var _path = "/check"
_basePath := o._basePath
result.Path = golangswaggerpaths.Join(_basePath, _path)
_result.Path = golangswaggerpaths.Join(_basePath, _path)
return &result, nil
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error

View File

@@ -0,0 +1,56 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"net/http"
"github.com/go-openapi/runtime/middleware"
)
// ClusterHealthHandlerFunc turns a function with the right signature into a cluster health handler
type ClusterHealthHandlerFunc func(ClusterHealthParams) middleware.Responder
// Handle executing the request and returning a response
func (fn ClusterHealthHandlerFunc) Handle(params ClusterHealthParams) middleware.Responder {
return fn(params)
}
// ClusterHealthHandler interface for that can handle valid cluster health params
type ClusterHealthHandler interface {
Handle(ClusterHealthParams) middleware.Responder
}
// NewClusterHealth creates a new http.Handler for the cluster health operation
func NewClusterHealth(ctx *middleware.Context, handler ClusterHealthHandler) *ClusterHealth {
return &ClusterHealth{Context: ctx, Handler: handler}
}
/* ClusterHealth swagger:route GET /cluster_health clusterHealth
Checks the full graph. Returns a binary OK or not OK.
*/
type ClusterHealth struct {
Context *middleware.Context
Handler ClusterHealthHandler
}
func (o *ClusterHealth) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
*r = *rCtx
}
var Params = NewClusterHealthParams()
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View File

@@ -0,0 +1,46 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
)
// NewClusterHealthParams creates a new ClusterHealthParams object
//
// There are no default values defined in the spec.
func NewClusterHealthParams() ClusterHealthParams {
return ClusterHealthParams{}
}
// ClusterHealthParams contains all the bound params for the cluster health operation
// typically these are obtained from a http.Request
//
// swagger:parameters clusterHealth
type ClusterHealthParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
// for simple values it will use straight method calls.
//
// To ensure default values, the struct must have been initialized with NewClusterHealthParams() beforehand.
func (o *ClusterHealthParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,102 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// ClusterHealthOKCode is the HTTP code returned for type ClusterHealthOK
const ClusterHealthOKCode int = 200
/*ClusterHealthOK Healthy cluster
swagger:response clusterHealthOK
*/
type ClusterHealthOK struct {
/*
In: Body
*/
Payload *models.ClusterHealthResults `json:"body,omitempty"`
}
// NewClusterHealthOK creates ClusterHealthOK with default headers values
func NewClusterHealthOK() *ClusterHealthOK {
return &ClusterHealthOK{}
}
// WithPayload adds the payload to the cluster health o k response
func (o *ClusterHealthOK) WithPayload(payload *models.ClusterHealthResults) *ClusterHealthOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the cluster health o k response
func (o *ClusterHealthOK) SetPayload(payload *models.ClusterHealthResults) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ClusterHealthOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(200)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}
// ClusterHealthIMATeapotCode is the HTTP code returned for type ClusterHealthIMATeapot
const ClusterHealthIMATeapotCode int = 418
/*ClusterHealthIMATeapot Unhealthy cluster
swagger:response clusterHealthIMATeapot
*/
type ClusterHealthIMATeapot struct {
/*
In: Body
*/
Payload *models.ClusterHealthResults `json:"body,omitempty"`
}
// NewClusterHealthIMATeapot creates ClusterHealthIMATeapot with default headers values
func NewClusterHealthIMATeapot() *ClusterHealthIMATeapot {
return &ClusterHealthIMATeapot{}
}
// WithPayload adds the payload to the cluster health i m a teapot response
func (o *ClusterHealthIMATeapot) WithPayload(payload *models.ClusterHealthResults) *ClusterHealthIMATeapot {
o.Payload = payload
return o
}
// SetPayload sets the payload to the cluster health i m a teapot response
func (o *ClusterHealthIMATeapot) SetPayload(payload *models.ClusterHealthResults) {
o.Payload = payload
}
// WriteResponse to the client
func (o *ClusterHealthIMATeapot) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(418)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View File

@@ -0,0 +1,84 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"errors"
"net/url"
golangswaggerpaths "path"
)
// ClusterHealthURL generates an URL for the cluster health operation
type ClusterHealthURL struct {
_basePath string
}
// WithBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *ClusterHealthURL) WithBasePath(bp string) *ClusterHealthURL {
o.SetBasePath(bp)
return o
}
// SetBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *ClusterHealthURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *ClusterHealthURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/cluster_health"
_basePath := o._basePath
_result.Path = golangswaggerpaths.Join(_basePath, _path)
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error
func (o *ClusterHealthURL) Must(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
if u == nil {
panic("url can't be nil")
}
return u
}
// String returns the string representation of the path with query string
func (o *ClusterHealthURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *ClusterHealthURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on ClusterHealthURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on ClusterHealthURL")
}
base, err := o.Build()
if err != nil {
return nil, err
}
base.Scheme = scheme
base.Host = host
return base, nil
}
// StringFull returns the string representation of a complete url
func (o *ClusterHealthURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -24,13 +10,13 @@ import (
"net/http"
"strings"
errors "github.com/go-openapi/errors"
loads "github.com/go-openapi/loads"
runtime "github.com/go-openapi/runtime"
middleware "github.com/go-openapi/runtime/middleware"
security "github.com/go-openapi/runtime/security"
spec "github.com/go-openapi/spec"
strfmt "github.com/go-openapi/strfmt"
"github.com/go-openapi/errors"
"github.com/go-openapi/loads"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/runtime/security"
"github.com/go-openapi/spec"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
)
@@ -43,20 +29,31 @@ func NewGoldpingerAPI(spec *loads.Document) *GoldpingerAPI {
defaultProduces: "application/json",
customConsumers: make(map[string]runtime.Consumer),
customProducers: make(map[string]runtime.Producer),
PreServerShutdown: func() {},
ServerShutdown: func() {},
spec: spec,
useSwaggerUI: false,
ServeError: errors.ServeError,
BasicAuthenticator: security.BasicAuth,
APIKeyAuthenticator: security.APIKeyAuth,
BearerAuthenticator: security.BearerAuth,
JSONConsumer: runtime.JSONConsumer(),
JSONProducer: runtime.JSONProducer(),
JSONConsumer: runtime.JSONConsumer(),
JSONProducer: runtime.JSONProducer(),
CheckAllPodsHandler: CheckAllPodsHandlerFunc(func(params CheckAllPodsParams) middleware.Responder {
return middleware.NotImplemented("operation CheckAllPods has not yet been implemented")
}),
CheckServicePodsHandler: CheckServicePodsHandlerFunc(func(params CheckServicePodsParams) middleware.Responder {
return middleware.NotImplemented("operation CheckServicePods has not yet been implemented")
}),
ClusterHealthHandler: ClusterHealthHandlerFunc(func(params ClusterHealthParams) middleware.Responder {
return middleware.NotImplemented("operation ClusterHealth has not yet been implemented")
}),
HealthzHandler: HealthzHandlerFunc(func(params HealthzParams) middleware.Responder {
return middleware.NotImplemented("operation Healthz has not yet been implemented")
}),
PingHandler: PingHandlerFunc(func(params PingParams) middleware.Responder {
return middleware.NotImplemented("operation Ping has not yet been implemented")
}),
@@ -74,27 +71,36 @@ type GoldpingerAPI struct {
defaultConsumes string
defaultProduces string
Middleware func(middleware.Builder) http.Handler
useSwaggerUI bool
// BasicAuthenticator generates a runtime.Authenticator from the supplied basic auth function.
// It has a default implemention in the security package, however you can replace it for your particular usage.
// It has a default implementation in the security package, however you can replace it for your particular usage.
BasicAuthenticator func(security.UserPassAuthentication) runtime.Authenticator
// APIKeyAuthenticator generates a runtime.Authenticator from the supplied token auth function.
// It has a default implemention in the security package, however you can replace it for your particular usage.
// It has a default implementation in the security package, however you can replace it for your particular usage.
APIKeyAuthenticator func(string, string, security.TokenAuthentication) runtime.Authenticator
// BearerAuthenticator generates a runtime.Authenticator from the supplied bearer token auth function.
// It has a default implemention in the security package, however you can replace it for your particular usage.
// It has a default implementation in the security package, however you can replace it for your particular usage.
BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator
// JSONConsumer registers a consumer for a "application/json" mime type
// JSONConsumer registers a consumer for the following mime types:
// - application/json
JSONConsumer runtime.Consumer
// JSONProducer registers a producer for a "application/json" mime type
// JSONProducer registers a producer for the following mime types:
// - application/json
JSONProducer runtime.Producer
// CheckAllPodsHandler sets the operation handler for the check all pods operation
CheckAllPodsHandler CheckAllPodsHandler
// CheckServicePodsHandler sets the operation handler for the check service pods operation
CheckServicePodsHandler CheckServicePodsHandler
// ClusterHealthHandler sets the operation handler for the cluster health operation
ClusterHealthHandler ClusterHealthHandler
// HealthzHandler sets the operation handler for the healthz operation
HealthzHandler HealthzHandler
// PingHandler sets the operation handler for the ping operation
PingHandler PingHandler
@@ -102,6 +108,10 @@ type GoldpingerAPI struct {
// but you can set your own with this
ServeError func(http.ResponseWriter, *http.Request, error)
// PreServerShutdown is called before the HTTP(S) server is shutdown
// This allows for custom functions to get executed before the HTTP(S) server stops accepting traffic
PreServerShutdown func()
// ServerShutdown is called when the HTTP(S) server is shut down and done
// handling all active connections and does not accept connections any more
ServerShutdown func()
@@ -113,6 +123,16 @@ type GoldpingerAPI struct {
Logger func(string, ...interface{})
}
// UseRedoc for documentation at /docs
func (o *GoldpingerAPI) UseRedoc() {
o.useSwaggerUI = false
}
// UseSwaggerUI for documentation at /docs
func (o *GoldpingerAPI) UseSwaggerUI() {
o.useSwaggerUI = true
}
// SetDefaultProduces sets the default produces media type
func (o *GoldpingerAPI) SetDefaultProduces(mediaType string) {
o.defaultProduces = mediaType
@@ -163,11 +183,15 @@ func (o *GoldpingerAPI) Validate() error {
if o.CheckAllPodsHandler == nil {
unregistered = append(unregistered, "CheckAllPodsHandler")
}
if o.CheckServicePodsHandler == nil {
unregistered = append(unregistered, "CheckServicePodsHandler")
}
if o.ClusterHealthHandler == nil {
unregistered = append(unregistered, "ClusterHealthHandler")
}
if o.HealthzHandler == nil {
unregistered = append(unregistered, "HealthzHandler")
}
if o.PingHandler == nil {
unregistered = append(unregistered, "PingHandler")
}
@@ -186,28 +210,22 @@ func (o *GoldpingerAPI) ServeErrorFor(operationID string) func(http.ResponseWrit
// AuthenticatorsFor gets the authenticators for the specified security schemes
func (o *GoldpingerAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator {
return nil
}
// Authorizer returns the registered authorizer
func (o *GoldpingerAPI) Authorizer() runtime.Authorizer {
return nil
}
// ConsumersFor gets the consumers for the specified media types
// ConsumersFor gets the consumers for the specified media types.
// MIME type parameters are ignored here.
func (o *GoldpingerAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
result := make(map[string]runtime.Consumer)
result := make(map[string]runtime.Consumer, len(mediaTypes))
for _, mt := range mediaTypes {
switch mt {
case "application/json":
result["application/json"] = o.JSONConsumer
}
if c, ok := o.customConsumers[mt]; ok {
@@ -215,19 +233,16 @@ func (o *GoldpingerAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Con
}
}
return result
}
// ProducersFor gets the producers for the specified media types
// ProducersFor gets the producers for the specified media types.
// MIME type parameters are ignored here.
func (o *GoldpingerAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
result := make(map[string]runtime.Producer)
result := make(map[string]runtime.Producer, len(mediaTypes))
for _, mt := range mediaTypes {
switch mt {
case "application/json":
result["application/json"] = o.JSONProducer
}
if p, ok := o.customProducers[mt]; ok {
@@ -235,7 +250,6 @@ func (o *GoldpingerAPI) ProducersFor(mediaTypes []string) map[string]runtime.Pro
}
}
return result
}
// HandlerFor gets a http.Handler for the provided operation method and path
@@ -265,7 +279,6 @@ func (o *GoldpingerAPI) Context() *middleware.Context {
func (o *GoldpingerAPI) initHandlerCache() {
o.Context() // don't care about the result, just that the initialization happened
if o.handlers == nil {
o.handlers = make(map[string]map[string]http.Handler)
}
@@ -274,17 +287,22 @@ func (o *GoldpingerAPI) initHandlerCache() {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/check_all"] = NewCheckAllPods(o.context, o.CheckAllPodsHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/check"] = NewCheckServicePods(o.context, o.CheckServicePodsHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/cluster_health"] = NewClusterHealth(o.context, o.ClusterHealthHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/healthz"] = NewHealthz(o.context, o.HealthzHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/ping"] = NewPing(o.context, o.PingHandler)
}
// Serve creates a http handler to serve the API over HTTP
@@ -295,6 +313,9 @@ func (o *GoldpingerAPI) Serve(builder middleware.Builder) http.Handler {
if o.Middleware != nil {
return o.Middleware(builder)
}
if o.useSwaggerUI {
return o.context.APIHandlerSwaggerUI(builder)
}
return o.context.APIHandler(builder)
}
@@ -314,3 +335,15 @@ func (o *GoldpingerAPI) RegisterConsumer(mediaType string, consumer runtime.Cons
func (o *GoldpingerAPI) RegisterProducer(mediaType string, producer runtime.Producer) {
o.customProducers[mediaType] = producer
}
// AddMiddlewareFor adds a http middleware to existing handler
func (o *GoldpingerAPI) AddMiddlewareFor(method, path string, builder middleware.Builder) {
um := strings.ToUpper(method)
if path == "/" {
path = ""
}
o.Init()
if h, ok := o.handlers[um][path]; ok {
o.handlers[method][path] = builder(h)
}
}

View File

@@ -0,0 +1,56 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"net/http"
"github.com/go-openapi/runtime/middleware"
)
// HealthzHandlerFunc turns a function with the right signature into a healthz handler
type HealthzHandlerFunc func(HealthzParams) middleware.Responder
// Handle executing the request and returning a response
func (fn HealthzHandlerFunc) Handle(params HealthzParams) middleware.Responder {
return fn(params)
}
// HealthzHandler interface for that can handle valid healthz params
type HealthzHandler interface {
Handle(HealthzParams) middleware.Responder
}
// NewHealthz creates a new http.Handler for the healthz operation
func NewHealthz(ctx *middleware.Context, handler HealthzHandler) *Healthz {
return &Healthz{Context: ctx, Handler: handler}
}
/* Healthz swagger:route GET /healthz healthz
The healthcheck endpoint provides detailed information about the health of a web service. If each of the components required by the service are healthy, then the service is considered healthy and will return a 200 OK response. If any of the components needed by the service are unhealthy, then a 503 Service Unavailable response will be provided.
*/
type Healthz struct {
Context *middleware.Context
Handler HealthzHandler
}
func (o *Healthz) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
*r = *rCtx
}
var Params = NewHealthzParams()
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View File

@@ -0,0 +1,46 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
)
// NewHealthzParams creates a new HealthzParams object
//
// There are no default values defined in the spec.
func NewHealthzParams() HealthzParams {
return HealthzParams{}
}
// HealthzParams contains all the bound params for the healthz operation
// typically these are obtained from a http.Request
//
// swagger:parameters healthz
type HealthzParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
// for simple values it will use straight method calls.
//
// To ensure default values, the struct must have been initialized with NewHealthzParams() beforehand.
func (o *HealthzParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}

View File

@@ -0,0 +1,102 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// HealthzOKCode is the HTTP code returned for type HealthzOK
const HealthzOKCode int = 200
/*HealthzOK Health check report
swagger:response healthzOK
*/
type HealthzOK struct {
/*
In: Body
*/
Payload *models.HealthCheckResults `json:"body,omitempty"`
}
// NewHealthzOK creates HealthzOK with default headers values
func NewHealthzOK() *HealthzOK {
return &HealthzOK{}
}
// WithPayload adds the payload to the healthz o k response
func (o *HealthzOK) WithPayload(payload *models.HealthCheckResults) *HealthzOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the healthz o k response
func (o *HealthzOK) SetPayload(payload *models.HealthCheckResults) {
o.Payload = payload
}
// WriteResponse to the client
func (o *HealthzOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(200)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}
// HealthzServiceUnavailableCode is the HTTP code returned for type HealthzServiceUnavailable
const HealthzServiceUnavailableCode int = 503
/*HealthzServiceUnavailable Unhealthy service
swagger:response healthzServiceUnavailable
*/
type HealthzServiceUnavailable struct {
/*
In: Body
*/
Payload *models.HealthCheckResults `json:"body,omitempty"`
}
// NewHealthzServiceUnavailable creates HealthzServiceUnavailable with default headers values
func NewHealthzServiceUnavailable() *HealthzServiceUnavailable {
return &HealthzServiceUnavailable{}
}
// WithPayload adds the payload to the healthz service unavailable response
func (o *HealthzServiceUnavailable) WithPayload(payload *models.HealthCheckResults) *HealthzServiceUnavailable {
o.Payload = payload
return o
}
// SetPayload sets the payload to the healthz service unavailable response
func (o *HealthzServiceUnavailable) SetPayload(payload *models.HealthCheckResults) {
o.Payload = payload
}
// WriteResponse to the client
func (o *HealthzServiceUnavailable) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(503)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View File

@@ -0,0 +1,84 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"errors"
"net/url"
golangswaggerpaths "path"
)
// HealthzURL generates an URL for the healthz operation
type HealthzURL struct {
_basePath string
}
// WithBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *HealthzURL) WithBasePath(bp string) *HealthzURL {
o.SetBasePath(bp)
return o
}
// SetBasePath sets the base path for this url builder, only required when it's different from the
// base path specified in the swagger spec.
// When the value of the base path is an empty string
func (o *HealthzURL) SetBasePath(bp string) {
o._basePath = bp
}
// Build a url path and query string
func (o *HealthzURL) Build() (*url.URL, error) {
var _result url.URL
var _path = "/healthz"
_basePath := o._basePath
_result.Path = golangswaggerpaths.Join(_basePath, _path)
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error
func (o *HealthzURL) Must(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
if u == nil {
panic("url can't be nil")
}
return u
}
// String returns the string representation of the path with query string
func (o *HealthzURL) String() string {
return o.Must(o.Build()).String()
}
// BuildFull builds a full url with scheme, host, path and query string
func (o *HealthzURL) BuildFull(scheme, host string) (*url.URL, error) {
if scheme == "" {
return nil, errors.New("scheme is required for a full url on HealthzURL")
}
if host == "" {
return nil, errors.New("host is required for a full url on HealthzURL")
}
base, err := o.Build()
if err != nil {
return nil, err
}
base.Scheme = scheme
base.Host = host
return base, nil
}
// StringFull returns the string representation of a complete url
func (o *HealthzURL) StringFull(scheme, host string) string {
return o.Must(o.BuildFull(scheme, host)).String()
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -22,7 +8,7 @@ package operations
import (
"net/http"
middleware "github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/runtime/middleware"
)
// PingHandlerFunc turns a function with the right signature into a ping handler
@@ -43,7 +29,7 @@ func NewPing(ctx *middleware.Context, handler PingHandler) *Ping {
return &Ping{Context: ctx, Handler: handler}
}
/*Ping swagger:route GET /ping ping
/* Ping swagger:route GET /ping ping
return query stats
@@ -56,17 +42,15 @@ type Ping struct {
func (o *Ping) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
r = rCtx
*r = *rCtx
}
var Params = NewPingParams()
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -27,7 +13,8 @@ import (
)
// NewPingParams creates a new PingParams object
// no default values defined in spec.
//
// There are no default values defined in the spec.
func NewPingParams() PingParams {
return PingParams{}

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -24,7 +10,7 @@ import (
"github.com/go-openapi/runtime"
models "github.com/bloomberg/goldpinger/pkg/models"
"github.com/bloomberg/goldpinger/v3/pkg/models"
)
// PingOKCode is the HTTP code returned for type PingOK

View File

@@ -1,17 +1,3 @@
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by go-swagger; DO NOT EDIT.
package operations
@@ -47,14 +33,14 @@ func (o *PingURL) SetBasePath(bp string) {
// Build a url path and query string
func (o *PingURL) Build() (*url.URL, error) {
var result url.URL
var _result url.URL
var _path = "/ping"
_basePath := o._basePath
result.Path = golangswaggerpaths.Join(_basePath, _path)
_result.Path = golangswaggerpaths.Join(_basePath, _path)
return &result, nil
return &_result, nil
}
// Must is a helper function to panic when the url builder returns an error

Some files were not shown because too many files have changed in this diff Show More