mirror of
https://github.com/bloomberg/goldpinger.git
synced 2026-02-14 09:59:50 +00:00
Initial commit
This commit is contained in:
93
.gitignore
vendored
Normal file
93
.gitignore
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
vendor/
|
||||
bin/
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
.hypothesis/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# IPython Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# celery beat schedule file
|
||||
celerybeat-schedule
|
||||
|
||||
# dotenv
|
||||
.env
|
||||
|
||||
# virtualenv
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
23
CONTRIBUTING.md
Normal file
23
CONTRIBUTING.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Contributing to `Goldpinger`
|
||||
|
||||
If you'd like to help us improve and extend this project, then we welcome your contributions!
|
||||
|
||||
Below you will find some basic steps required to be able to contribute to the project. If you have any questions about this process or any other aspect of contributing to a Bloomberg open source project, feel free to send an email to opensource@bloomberg.net and we'll get your questions answered as quickly as we can.
|
||||
|
||||
Pull Requests are always welcome, however they will only be accepted if they provide a reasonably test coverage.
|
||||
|
||||
## Contribution Licensing
|
||||
|
||||
Since `Goldpinger` is distributed under the terms of the [Apache Version 2 license](LICENSE), contributions that you make are licensed under the same terms. In order for us to be able to accept your contributions, we will need explicit confirmation from you that you are able and willing to provide them under these terms, and the mechanism we use to do this is called a Developer's Certificate of Origin [DCO](DCO.md). This is very similar to the process used by the Linux(R) kernel, Samba, and many other major open source projects.
|
||||
|
||||
To participate under these terms, all that you must do is include a line like the following as the last line of the commit message for each commit in your contribution:
|
||||
|
||||
Signed-Off-By: Random J. Developer <random@developer.example.org>
|
||||
|
||||
The simplest way to accomplish this is to add `-s` or `--signoff` to your `git commit` command.
|
||||
|
||||
You must use your real name (sorry, no pseudonyms, and no anonymous contributions).
|
||||
|
||||
## Help / Documentation
|
||||
|
||||
The [README](README.md) is the best place to start.
|
||||
25
DCO.md
Normal file
25
DCO.md
Normal file
@@ -0,0 +1,25 @@
|
||||
Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
1. The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
2. The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
3. The contribution was provided directly to me by some other
|
||||
person who certified (1), (2) or (3) and I have not modified
|
||||
it.
|
||||
|
||||
4. I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
636
Gopkg.lock
generated
Normal file
636
Gopkg.lock
generated
Normal file
@@ -0,0 +1,636 @@
|
||||
# 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]]
|
||||
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/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/tools/clientcmd",
|
||||
]
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
78
Gopkg.toml
Normal file
78
Gopkg.toml
Normal file
@@ -0,0 +1,78 @@
|
||||
# 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
|
||||
202
LICENSE
Normal file
202
LICENSE
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2017 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.
|
||||
36
Makefile
Normal file
36
Makefile
Normal file
@@ -0,0 +1,36 @@
|
||||
name ?= goldpinger
|
||||
version ?= 1.0.1
|
||||
bin ?= goldpinger
|
||||
pkg ?= "github.com/bloomberg/goldpinger.git"
|
||||
tag = $(name):$(version)
|
||||
namespace ?= ""
|
||||
files = $(shell find . -iname "*.go")
|
||||
|
||||
clean:
|
||||
rm -rf ./vendor
|
||||
rm -f ./bin/$(bin)
|
||||
|
||||
vendor:
|
||||
rm -rf ./vendor
|
||||
dep ensure -v
|
||||
|
||||
swagger:
|
||||
swagger generate server -t pkg -f ./swagger.yml --exclude-main -A goldpinger && \
|
||||
swagger generate client -t pkg -f ./swagger.yml -A goldpinger
|
||||
|
||||
bin/$(bin): $(files)
|
||||
PKG=${pkg} ARCH=amd64 VERSION=${version} BIN=${bin} ./build/build.sh
|
||||
|
||||
build: bin/$(bin)
|
||||
sudo docker build -t $(tag) -f ./build/Dockerfile .
|
||||
|
||||
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
|
||||
196
README.md
Normal file
196
README.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# 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 scaped, visualised and alerted on.
|
||||
|
||||
Oh, and it gives you the graph below for your cluster.
|
||||
|
||||

|
||||
|
||||
|
||||
## On the menu
|
||||
|
||||
- [Rationale](#rationale)
|
||||
- [Building](#building)
|
||||
- [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)
|
||||
|
||||
## Rationale
|
||||
|
||||
We built __Goldpinger__ to troubleshoot, visualise and alert on our networking layer, while adopting `Kubernetes` at Bloomberg. It has since become the goto tool to see connectivity and slowness issues.
|
||||
|
||||
It's small, simple and you'll wonder why you hadn't had it before.
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
In order to build `Goldpinger`, you are going to need `go` version 1.10+, `dep`, and `docker`.
|
||||
|
||||
Building from source code consists of compiling the binary and building a [Docker image](./build/Dockerfile):
|
||||
|
||||
```sh
|
||||
# step 0: check out the code into your $GOPATH
|
||||
|
||||
# step 1: download the dependencies via dep ensure
|
||||
make vendor
|
||||
|
||||
# step 2: compile the binary
|
||||
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 4: push the image somewhere
|
||||
namespace="docker.io/myhandle/" make tag
|
||||
namespace="docker.io/myhandle/" make push
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
`Goldpinger` works by asking `Kubernetes` for pods with particular labels (`app=goldpinger`). While you can deploy `Golpinger` in a variety of ways, it works very nicely as a `DaemonSet` out of the box.
|
||||
|
||||
### Authentication with Kubernetes API
|
||||
|
||||
`Goldpinger` supports using a `kubeconfig` (specify with `--kubeconfig-path`) or service accounts.
|
||||
|
||||
### Example YAML
|
||||
|
||||
|
||||
Here's an example of what you can do (using the in-cluster authentication to `Kubernetes` apiserver):
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: goldpinger
|
||||
spec:
|
||||
updateStrategy:
|
||||
type: RollingUpdate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: goldpinger
|
||||
version: "1.0.0"
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: goldpinger
|
||||
version: "1.0.0"
|
||||
spec:
|
||||
containers:
|
||||
- name: goldpinger
|
||||
env:
|
||||
- name: HOST
|
||||
value: "0.0.0.0"
|
||||
- name: PORT
|
||||
value: "80"
|
||||
# refresh interval (seconds) tells goldpinger to call every other instance with that frequency (set to 0 to disable)
|
||||
- name: REFRESH_INTERVAL
|
||||
value: "30"
|
||||
# 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"
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: goldpinger
|
||||
labels:
|
||||
app: goldpinger
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
nodePort: 30080
|
||||
name: http
|
||||
selector:
|
||||
app: goldpinger
|
||||
```
|
||||
|
||||
You can also see [an example of using `kubeconfig` in the `./extras`](./extras/example-with-kubeconfig.yaml).
|
||||
|
||||
## Usage
|
||||
|
||||
### UI
|
||||
|
||||
Once you have it running, you can hit any of the nodes (port 30080 in the example above) and see the UI.
|
||||
|
||||

|
||||
|
||||
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 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)
|
||||
|
||||
### Prometheus
|
||||
|
||||
Once running, `Goldpinger` exposes `Prometheus` metrics at `/metrics`. All the metrics are prefixed with `goldpinger_` for easy identification.
|
||||
|
||||
You can see the metrics by doing a `curl http://$POD_ID:80/metrics`.
|
||||
|
||||
These are probably the droids you are looking for:
|
||||
|
||||
```sh
|
||||
goldpinger_peers_response_time_s_*
|
||||
goldpinger_peers_response_time_s_*
|
||||
goldpinger_nodes_health_total
|
||||
goldpinger_stats_total
|
||||
goldpinger_errors_total
|
||||
```
|
||||
|
||||
### Grafana
|
||||
|
||||
You can find an example of a `Grafana` dashboard that shows what's going on in your cluster in [extras](./extras/goldpinger-dashboard.json). This should get you started, and once you're on the roll, why not :heart: contribute some kickass dashboards for others to use ?
|
||||
|
||||
### Alert Manager
|
||||
|
||||
Once you've gotten your metrics into `Prometheus`, you have all you need to set useful alerts.
|
||||
|
||||
To get you started, here's a rule that will trigger an alert if there are any nodes reported as unhealthy by any instance of `Goldpinger`.
|
||||
|
||||
```yaml
|
||||
alert: goldpinger_nodes_unhealthy
|
||||
expr: sum(goldpinger_nodes_healthy_total{status="unhealthy"})
|
||||
BY (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
|
||||
```
|
||||
|
||||
Similarly, why not :heart: contribute some amazing alerts for others to use ?
|
||||
|
||||
## Contributions
|
||||
|
||||
We :heart: contributions.
|
||||
|
||||
Have you had a good experience with `Goldpinger` ? Why not share some love and contribute code, dashboards and alerts ?
|
||||
|
||||
If you're thinking of making some code changes, please be aware that most of the code is auto-generated from the `Swagger` spec. 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).
|
||||
|
||||
Before you create that PR, please make sure you read [CONTRIBUTING](./CONTRIBUTING.md) and [DCO](./DCO.md).
|
||||
|
||||
## License
|
||||
|
||||
Please read the [LICENSE](./LICENSE) file here.
|
||||
100
cmd/goldpinger/main.go
Normal file
100
cmd/goldpinger/main.go
Normal file
@@ -0,0 +1,100 @@
|
||||
// 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 main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
"github.com/bloomberg/goldpinger/pkg/goldpinger"
|
||||
"github.com/bloomberg/goldpinger/pkg/restapi"
|
||||
"github.com/bloomberg/goldpinger/pkg/restapi/operations"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// load embedded swagger file
|
||||
swaggerSpec, err := loads.Analyzed(restapi.SwaggerJSON, "")
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
|
||||
// create new service API
|
||||
api := operations.NewGoldpingerAPI(swaggerSpec)
|
||||
server := restapi.NewServer(api)
|
||||
defer server.Shutdown()
|
||||
|
||||
parser := flags.NewParser(server, flags.Default)
|
||||
parser.ShortDescription = "Goldpinger"
|
||||
parser.LongDescription = swaggerSpec.Spec().Info.Description
|
||||
|
||||
// parse flags
|
||||
server.ConfigureFlags()
|
||||
for _, optsGroup := range api.CommandLineOptionsGroups {
|
||||
_, err := parser.AddGroup(optsGroup.ShortDescription, optsGroup.LongDescription, optsGroup.Options)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := parser.Parse(); err != nil {
|
||||
code := 1
|
||||
if fe, ok := err.(*flags.Error); ok {
|
||||
if fe.Type == flags.ErrHelp {
|
||||
code = 0
|
||||
}
|
||||
}
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
// make a kubernetes client
|
||||
var config *rest.Config
|
||||
if goldpinger.GoldpingerConfig.KubeConfigPath == "" {
|
||||
log.Println("Kubeconfig not specified, trying to use in cluster config")
|
||||
config, err = rest.InClusterConfig()
|
||||
} else {
|
||||
log.Println("Kubeconfig specified in ", goldpinger.GoldpingerConfig.KubeConfigPath)
|
||||
config, err = clientcmd.BuildConfigFromFlags("", goldpinger.GoldpingerConfig.KubeConfigPath)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalln("Error getting config ", err.Error())
|
||||
}
|
||||
// create the clientset
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
log.Fatalln("kubernetes.NewForConfig error ", err.Error())
|
||||
}
|
||||
goldpinger.GoldpingerConfig.KubernetesClient = clientset
|
||||
|
||||
// Check if we have an override for the client, default to own port
|
||||
if goldpinger.GoldpingerConfig.Port == 0 {
|
||||
goldpinger.GoldpingerConfig.Port = server.Port
|
||||
}
|
||||
|
||||
server.ConfigureAPI()
|
||||
goldpinger.StartUpdater()
|
||||
|
||||
log.Println("All good, starting serving the API")
|
||||
|
||||
// serve API
|
||||
if err := server.Serve(); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}
|
||||
4
extras/README.md
Normal file
4
extras/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Extras
|
||||
|
||||
|
||||
You will find here examples of how to use and configure `Goldpinger`.
|
||||
68
extras/example-with-kubeconfig.yaml
Normal file
68
extras/example-with-kubeconfig.yaml
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
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:
|
||||
# if you'd like to use a secret to inject a kubeconfig, you can do it like this
|
||||
volumes:
|
||||
- name: kubeconfig
|
||||
secret:
|
||||
secretName: goldpinger-kubeconfig
|
||||
containers:
|
||||
- name: goldpinger
|
||||
env:
|
||||
- name: HOST
|
||||
value: "0.0.0.0"
|
||||
- name: PORT
|
||||
value: "80"
|
||||
# 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"
|
||||
# refresh interval (seconds) tells goldpinger to call every other instance with that frequency (set to 0 to disable)
|
||||
- name: REFRESH_INTERVAL
|
||||
value: "30"
|
||||
# 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"
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: http
|
||||
volumeMounts:
|
||||
- mountPath: /.kube/
|
||||
name: kubeconfig
|
||||
readOnly: true
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: goldpinger
|
||||
labels:
|
||||
app: goldpinger
|
||||
spec:
|
||||
type: NodePort
|
||||
ports:
|
||||
- port: 80
|
||||
nodePort: 30080
|
||||
name: http
|
||||
selector:
|
||||
app: goldpinger
|
||||
919
extras/goldpinger-dashboard.json
Normal file
919
extras/goldpinger-dashboard.json
Normal file
@@ -0,0 +1,919 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"hideControls": false,
|
||||
"id": 1,
|
||||
"links": [],
|
||||
"refresh": "10s",
|
||||
"rows": [
|
||||
{
|
||||
"collapse": false,
|
||||
"height": 166,
|
||||
"panels": [
|
||||
{
|
||||
"cacheTimeout": null,
|
||||
"colorBackground": false,
|
||||
"colorValue": true,
|
||||
"colors": [
|
||||
"rgba(245, 54, 54, 0.9)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(55, 174, 50, 0.97)"
|
||||
],
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"format": "none",
|
||||
"gauge": {
|
||||
"maxValue": 100,
|
||||
"minValue": 0,
|
||||
"show": false,
|
||||
"thresholdLabels": false,
|
||||
"thresholdMarkers": true
|
||||
},
|
||||
"id": 9,
|
||||
"interval": null,
|
||||
"links": [],
|
||||
"mappingType": 1,
|
||||
"mappingTypes": [
|
||||
{
|
||||
"name": "value to text",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "range to text",
|
||||
"value": 2
|
||||
}
|
||||
],
|
||||
"maxDataPoints": 100,
|
||||
"nullPointMode": "connected",
|
||||
"nullText": null,
|
||||
"postfix": "",
|
||||
"postfixFontSize": "50%",
|
||||
"prefix": "",
|
||||
"prefixFontSize": "50%",
|
||||
"rangeMaps": [
|
||||
{
|
||||
"from": "null",
|
||||
"text": "N/A",
|
||||
"to": "null"
|
||||
}
|
||||
],
|
||||
"span": 4,
|
||||
"sparkline": {
|
||||
"fillColor": "rgba(31, 118, 189, 0.18)",
|
||||
"full": false,
|
||||
"lineColor": "rgb(31, 120, 193)",
|
||||
"show": true
|
||||
},
|
||||
"tableColumn": "",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "(count(goldpinger_nodes_health_total{status='healthy'}) + count(goldpinger_nodes_health_total{status='unhealthy'})) /2",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "",
|
||||
"metric": "goldpinger_nodes_health",
|
||||
"refId": "A",
|
||||
"step": 600
|
||||
}
|
||||
],
|
||||
"thresholds": "31,32",
|
||||
"title": "Goldpinger Nodes",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "150%",
|
||||
"valueMaps": [
|
||||
{
|
||||
"op": "=",
|
||||
"text": "N/A",
|
||||
"value": "null"
|
||||
}
|
||||
],
|
||||
"valueName": "avg"
|
||||
},
|
||||
{
|
||||
"columns": [
|
||||
{
|
||||
"text": "Current",
|
||||
"value": "current"
|
||||
},
|
||||
{
|
||||
"text": "Max",
|
||||
"value": "max"
|
||||
},
|
||||
{
|
||||
"text": "Avg",
|
||||
"value": "avg"
|
||||
}
|
||||
],
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fontSize": "100%",
|
||||
"id": 11,
|
||||
"links": [],
|
||||
"pageSize": null,
|
||||
"scroll": true,
|
||||
"showHeader": true,
|
||||
"sort": {
|
||||
"col": null,
|
||||
"desc": false
|
||||
},
|
||||
"span": 8,
|
||||
"styles": [
|
||||
{
|
||||
"dateFormat": "YYYY-MM-DD HH:mm:ss",
|
||||
"pattern": "Time",
|
||||
"type": "date"
|
||||
},
|
||||
{
|
||||
"colorMode": "value",
|
||||
"colors": [
|
||||
"rgba(50, 172, 45, 0.97)",
|
||||
"rgba(237, 129, 40, 0.89)",
|
||||
"rgba(245, 54, 54, 0.9)"
|
||||
],
|
||||
"decimals": 2,
|
||||
"pattern": "/.*/",
|
||||
"thresholds": [
|
||||
"1",
|
||||
"2"
|
||||
],
|
||||
"type": "number",
|
||||
"unit": "short"
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(goldpinger_nodes_health_total{status='unhealthy'}) by (goldpinger_instance)",
|
||||
"format": "table",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{ goldpinger_instance }}",
|
||||
"refId": "A",
|
||||
"step": 40
|
||||
}
|
||||
],
|
||||
"title": "Unhealthy seen by instance",
|
||||
"transform": "table",
|
||||
"type": "table"
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"id": 10,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "null as zero",
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": true,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "goldpinger_nodes_health_total{status=\"unhealthy\"}",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "{{ goldpinger_instance }}",
|
||||
"metric": "goldpinger_nodes_health",
|
||||
"refId": "A",
|
||||
"step": 60
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Unhealthy nodes reported",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"id": 12,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "increase(goldpinger_nodes_health_total{status=\"unhealthy\"}[30m])",
|
||||
"format": "time_series",
|
||||
"interval": "5m",
|
||||
"intervalFactor": 1,
|
||||
"legendFormat": "{{ goldpinger_instance }}",
|
||||
"metric": "goldpinger_nodes_health",
|
||||
"refId": "A",
|
||||
"step": 300
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Unhealthy nodes increase [30m]",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": true,
|
||||
"title": "Overall Health",
|
||||
"titleSize": "h6"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"height": "200",
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"id": 6,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(increase(goldpinger_peers_response_time_s_sum[30m])) by (host_ip)",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{ host_ip }}",
|
||||
"refId": "A",
|
||||
"step": 120
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Increase in response time from node [30m]",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"id": 1,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "avg(goldpinger_peers_response_time_s_sum{call_type=\"ping\"}/goldpinger_peers_response_time_s_count{call_type=\"ping\"}) by (host_ip)",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{ host_ip }}",
|
||||
"refId": "A",
|
||||
"step": 30
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Response time from node (AVG)",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"id": 5,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "max(goldpinger_peers_response_time_s_sum{call_type=\"ping\"}/goldpinger_peers_response_time_s_count{call_type=\"ping\"}) by (host_ip)",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{ host_ip }}",
|
||||
"refId": "A",
|
||||
"step": 30
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Response time from node (MAX)",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": true,
|
||||
"title": "Connections to peers",
|
||||
"titleSize": "h6"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"height": 209,
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"height": "",
|
||||
"id": 13,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "sum(increase(goldpinger_kube_master_response_time_s_sum[30m])) by (host_ip)",
|
||||
"format": "time_series",
|
||||
"interval": "1m",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{ host_ip }}",
|
||||
"refId": "A",
|
||||
"step": 120
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Increase in response time from k8s api [30m]",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"height": "",
|
||||
"id": 14,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "avg(goldpinger_kube_master_response_time_s_sum/goldpinger_kube_master_response_time_s_count) by (host_ip)",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{ host_ip }}",
|
||||
"refId": "A",
|
||||
"step": 30
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Response time from k8s (AVG)",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": "K8S",
|
||||
"editable": true,
|
||||
"error": false,
|
||||
"fill": 1,
|
||||
"grid": {},
|
||||
"id": 15,
|
||||
"legend": {
|
||||
"alignAsTable": true,
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"rightSide": true,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"links": [],
|
||||
"nullPointMode": "connected",
|
||||
"percentage": false,
|
||||
"pointradius": 5,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"span": 12,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "max(goldpinger_kube_master_response_time_s_sum/goldpinger_kube_master_response_time_s_count) by (host_ip)",
|
||||
"format": "time_series",
|
||||
"intervalFactor": 2,
|
||||
"legendFormat": "{{ host_ip }}",
|
||||
"refId": "A",
|
||||
"step": 30
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Response time from k8s (MAX)",
|
||||
"tooltip": {
|
||||
"msResolution": true,
|
||||
"shared": false,
|
||||
"sort": 0,
|
||||
"value_type": "cumulative"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "s",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": true,
|
||||
"title": "Connections to Kubernetes API",
|
||||
"titleSize": "h6"
|
||||
},
|
||||
{
|
||||
"collapse": false,
|
||||
"height": 250,
|
||||
"panels": [],
|
||||
"repeat": null,
|
||||
"repeatIteration": null,
|
||||
"repeatRowId": null,
|
||||
"showTitle": false,
|
||||
"title": "Dashboard Row",
|
||||
"titleSize": "h6"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 14,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-1h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"5s",
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
],
|
||||
"time_options": [
|
||||
"5m",
|
||||
"15m",
|
||||
"1h",
|
||||
"6h",
|
||||
"12h",
|
||||
"24h",
|
||||
"2d",
|
||||
"7d",
|
||||
"30d"
|
||||
]
|
||||
},
|
||||
"timezone": "browser",
|
||||
"title": "Cluster: Goldpinger",
|
||||
"version": 3
|
||||
}
|
||||
BIN
extras/screenshot.png
Normal file
BIN
extras/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
131
pkg/client/goldpinger_client.go
Normal file
131
pkg/client/goldpinger_client.go
Normal file
@@ -0,0 +1,131 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
// Default goldpinger HTTP client.
|
||||
var Default = NewHTTPClient(nil)
|
||||
|
||||
const (
|
||||
// DefaultHost is the default Host
|
||||
// found in Meta (info) section of spec file
|
||||
DefaultHost string = "localhost"
|
||||
// DefaultBasePath is the default BasePath
|
||||
// found in Meta (info) section of spec file
|
||||
DefaultBasePath string = "/"
|
||||
)
|
||||
|
||||
// DefaultSchemes are the default schemes found in Meta (info) section of spec file
|
||||
var DefaultSchemes = []string{"http"}
|
||||
|
||||
// NewHTTPClient creates a new goldpinger HTTP client.
|
||||
func NewHTTPClient(formats strfmt.Registry) *Goldpinger {
|
||||
return NewHTTPClientWithConfig(formats, nil)
|
||||
}
|
||||
|
||||
// NewHTTPClientWithConfig creates a new goldpinger HTTP client,
|
||||
// using a customizable transport config.
|
||||
func NewHTTPClientWithConfig(formats strfmt.Registry, cfg *TransportConfig) *Goldpinger {
|
||||
// ensure nullable parameters have default
|
||||
if cfg == nil {
|
||||
cfg = DefaultTransportConfig()
|
||||
}
|
||||
|
||||
// create transport and client
|
||||
transport := httptransport.New(cfg.Host, cfg.BasePath, cfg.Schemes)
|
||||
return New(transport, formats)
|
||||
}
|
||||
|
||||
// New creates a new goldpinger client
|
||||
func New(transport runtime.ClientTransport, formats strfmt.Registry) *Goldpinger {
|
||||
// ensure nullable parameters have default
|
||||
if formats == nil {
|
||||
formats = strfmt.Default
|
||||
}
|
||||
|
||||
cli := new(Goldpinger)
|
||||
cli.Transport = transport
|
||||
|
||||
cli.Operations = operations.New(transport, formats)
|
||||
|
||||
return cli
|
||||
}
|
||||
|
||||
// DefaultTransportConfig creates a TransportConfig with the
|
||||
// default settings taken from the meta section of the spec file.
|
||||
func DefaultTransportConfig() *TransportConfig {
|
||||
return &TransportConfig{
|
||||
Host: DefaultHost,
|
||||
BasePath: DefaultBasePath,
|
||||
Schemes: DefaultSchemes,
|
||||
}
|
||||
}
|
||||
|
||||
// TransportConfig contains the transport related info,
|
||||
// found in the meta section of the spec file.
|
||||
type TransportConfig struct {
|
||||
Host string
|
||||
BasePath string
|
||||
Schemes []string
|
||||
}
|
||||
|
||||
// WithHost overrides the default host,
|
||||
// provided by the meta section of the spec file.
|
||||
func (cfg *TransportConfig) WithHost(host string) *TransportConfig {
|
||||
cfg.Host = host
|
||||
return cfg
|
||||
}
|
||||
|
||||
// WithBasePath overrides the default basePath,
|
||||
// provided by the meta section of the spec file.
|
||||
func (cfg *TransportConfig) WithBasePath(basePath string) *TransportConfig {
|
||||
cfg.BasePath = basePath
|
||||
return cfg
|
||||
}
|
||||
|
||||
// WithSchemes overrides the default schemes,
|
||||
// provided by the meta section of the spec file.
|
||||
func (cfg *TransportConfig) WithSchemes(schemes []string) *TransportConfig {
|
||||
cfg.Schemes = schemes
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Goldpinger is a client for goldpinger
|
||||
type Goldpinger struct {
|
||||
Operations *operations.Client
|
||||
|
||||
Transport runtime.ClientTransport
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
}
|
||||
128
pkg/client/operations/check_all_pods_parameters.go
Normal file
128
pkg/client/operations/check_all_pods_parameters.go
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
"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"
|
||||
)
|
||||
|
||||
// NewCheckAllPodsParams creates a new CheckAllPodsParams object
|
||||
// with the default values initialized.
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
*/
|
||||
type CheckAllPodsParams struct {
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the check all pods params
|
||||
func (o *CheckAllPodsParams) WithTimeout(timeout time.Duration) *CheckAllPodsParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the check all pods params
|
||||
func (o *CheckAllPodsParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the check all pods params
|
||||
func (o *CheckAllPodsParams) WithContext(ctx context.Context) *CheckAllPodsParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the check all pods params
|
||||
func (o *CheckAllPodsParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the check all pods params
|
||||
func (o *CheckAllPodsParams) WithHTTPClient(client *http.Client) *CheckAllPodsParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the check all pods params
|
||||
func (o *CheckAllPodsParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *CheckAllPodsParams) 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
|
||||
}
|
||||
81
pkg/client/operations/check_all_pods_responses.go
Normal file
81
pkg/client/operations/check_all_pods_responses.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
models "github.com/bloomberg/goldpinger/pkg/models"
|
||||
)
|
||||
|
||||
// CheckAllPodsReader is a Reader for the CheckAllPods structure.
|
||||
type CheckAllPodsReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
}
|
||||
|
||||
// NewCheckAllPodsOK creates a CheckAllPodsOK with default headers values
|
||||
func NewCheckAllPodsOK() *CheckAllPodsOK {
|
||||
return &CheckAllPodsOK{}
|
||||
}
|
||||
|
||||
/*CheckAllPodsOK handles this case with default header values.
|
||||
|
||||
Success, return response
|
||||
*/
|
||||
type CheckAllPodsOK struct {
|
||||
Payload *models.CheckAllResults
|
||||
}
|
||||
|
||||
func (o *CheckAllPodsOK) Error() string {
|
||||
return fmt.Sprintf("[GET /check_all][%d] checkAllPodsOK %+v", 200, o.Payload)
|
||||
}
|
||||
|
||||
func (o *CheckAllPodsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
o.Payload = new(models.CheckAllResults)
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
128
pkg/client/operations/check_service_pods_parameters.go
Normal file
128
pkg/client/operations/check_service_pods_parameters.go
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
"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"
|
||||
)
|
||||
|
||||
// NewCheckServicePodsParams creates a new CheckServicePodsParams object
|
||||
// with the default values initialized.
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
*/
|
||||
type CheckServicePodsParams struct {
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the check service pods params
|
||||
func (o *CheckServicePodsParams) WithTimeout(timeout time.Duration) *CheckServicePodsParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the check service pods params
|
||||
func (o *CheckServicePodsParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the check service pods params
|
||||
func (o *CheckServicePodsParams) WithContext(ctx context.Context) *CheckServicePodsParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the check service pods params
|
||||
func (o *CheckServicePodsParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the check service pods params
|
||||
func (o *CheckServicePodsParams) WithHTTPClient(client *http.Client) *CheckServicePodsParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the check service pods params
|
||||
func (o *CheckServicePodsParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *CheckServicePodsParams) 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
|
||||
}
|
||||
79
pkg/client/operations/check_service_pods_responses.go
Normal file
79
pkg/client/operations/check_service_pods_responses.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
models "github.com/bloomberg/goldpinger/pkg/models"
|
||||
)
|
||||
|
||||
// CheckServicePodsReader is a Reader for the CheckServicePods structure.
|
||||
type CheckServicePodsReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
}
|
||||
|
||||
// NewCheckServicePodsOK creates a CheckServicePodsOK with default headers values
|
||||
func NewCheckServicePodsOK() *CheckServicePodsOK {
|
||||
return &CheckServicePodsOK{}
|
||||
}
|
||||
|
||||
/*CheckServicePodsOK handles this case with default header values.
|
||||
|
||||
Success, return response
|
||||
*/
|
||||
type CheckServicePodsOK struct {
|
||||
Payload models.CheckResults
|
||||
}
|
||||
|
||||
func (o *CheckServicePodsOK) Error() string {
|
||||
return fmt.Sprintf("[GET /check][%d] checkServicePodsOK %+v", 200, o.Payload)
|
||||
}
|
||||
|
||||
func (o *CheckServicePodsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
128
pkg/client/operations/operations_client.go
Normal file
128
pkg/client/operations/operations_client.go
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/runtime"
|
||||
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// New creates a new operations API client.
|
||||
func New(transport runtime.ClientTransport, formats strfmt.Registry) *Client {
|
||||
return &Client{transport: transport, formats: formats}
|
||||
}
|
||||
|
||||
/*
|
||||
Client for operations API
|
||||
*/
|
||||
type Client struct {
|
||||
transport runtime.ClientTransport
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
/*
|
||||
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) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewCheckAllPodsParams()
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(&runtime.ClientOperation{
|
||||
ID: "checkAllPods",
|
||||
Method: "GET",
|
||||
PathPattern: "/check_all",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{""},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &CheckAllPodsReader{formats: a.formats},
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*CheckAllPodsOK), nil
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
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) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewCheckServicePodsParams()
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(&runtime.ClientOperation{
|
||||
ID: "checkServicePods",
|
||||
Method: "GET",
|
||||
PathPattern: "/check",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{""},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &CheckServicePodsReader{formats: a.formats},
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*CheckServicePodsOK), nil
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Ping return query stats
|
||||
*/
|
||||
func (a *Client) Ping(params *PingParams) (*PingOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewPingParams()
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(&runtime.ClientOperation{
|
||||
ID: "ping",
|
||||
Method: "GET",
|
||||
PathPattern: "/ping",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{""},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &PingReader{formats: a.formats},
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*PingOK), nil
|
||||
|
||||
}
|
||||
|
||||
// SetTransport changes the transport on the client
|
||||
func (a *Client) SetTransport(transport runtime.ClientTransport) {
|
||||
a.transport = transport
|
||||
}
|
||||
128
pkg/client/operations/ping_parameters.go
Normal file
128
pkg/client/operations/ping_parameters.go
Normal file
@@ -0,0 +1,128 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
"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"
|
||||
)
|
||||
|
||||
// NewPingParams creates a new PingParams object
|
||||
// with the default values initialized.
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
*/
|
||||
type PingParams struct {
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the ping params
|
||||
func (o *PingParams) WithTimeout(timeout time.Duration) *PingParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the ping params
|
||||
func (o *PingParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the ping params
|
||||
func (o *PingParams) WithContext(ctx context.Context) *PingParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the ping params
|
||||
func (o *PingParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the ping params
|
||||
func (o *PingParams) WithHTTPClient(client *http.Client) *PingParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the ping params
|
||||
func (o *PingParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *PingParams) 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
|
||||
}
|
||||
81
pkg/client/operations/ping_responses.go
Normal file
81
pkg/client/operations/ping_responses.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
models "github.com/bloomberg/goldpinger/pkg/models"
|
||||
)
|
||||
|
||||
// PingReader is a Reader for the Ping structure.
|
||||
type PingReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// 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())
|
||||
}
|
||||
}
|
||||
|
||||
// NewPingOK creates a PingOK with default headers values
|
||||
func NewPingOK() *PingOK {
|
||||
return &PingOK{}
|
||||
}
|
||||
|
||||
/*PingOK handles this case with default header values.
|
||||
|
||||
return success
|
||||
*/
|
||||
type PingOK struct {
|
||||
Payload *models.PingResults
|
||||
}
|
||||
|
||||
func (o *PingOK) Error() string {
|
||||
return fmt.Sprintf("[GET /ping][%d] pingOK %+v", 200, o.Payload)
|
||||
}
|
||||
|
||||
func (o *PingOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
o.Payload = new(models.PingResults)
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
172
pkg/goldpinger/client.go
Normal file
172
pkg/goldpinger/client.go
Normal file
@@ -0,0 +1,172 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
apiclient "github.com/bloomberg/goldpinger/pkg/client"
|
||||
"github.com/bloomberg/goldpinger/pkg/models"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// CheckNeighbours queries the kubernetes API server for all other goldpinger pods
|
||||
// then calls Ping() on each one
|
||||
func CheckNeighbours() models.CheckResults {
|
||||
return PingAllPods(GetAllPods())
|
||||
}
|
||||
|
||||
// CheckNeighboursNeighbours queries the kubernetes API server for all other goldpinger
|
||||
// pods then calls Check() on each one
|
||||
func CheckNeighboursNeighbours() *models.CheckAllResults {
|
||||
return CheckAllPods(GetAllPods())
|
||||
}
|
||||
|
||||
type PingAllPodsResult struct {
|
||||
podResult models.PodResult
|
||||
hostIPv4 strfmt.IPv4
|
||||
podIP string
|
||||
}
|
||||
|
||||
func pickPodHostIP(podIP, hostIP string) string {
|
||||
if GoldpingerConfig.UseHostIP {
|
||||
return hostIP
|
||||
}
|
||||
return podIP
|
||||
}
|
||||
|
||||
func PingAllPods(pods map[string]string) models.CheckResults {
|
||||
|
||||
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")
|
||||
}
|
||||
channelResult.podIP = podIP
|
||||
|
||||
ch <- channelResult
|
||||
wg.Done()
|
||||
}(podIP, hostIP)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
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++
|
||||
}
|
||||
result[response.podIP] = response.podResult
|
||||
}
|
||||
CountHealthyUnhealthyNodes(counterHealthy, counterUnhealthy)
|
||||
return result
|
||||
}
|
||||
|
||||
type CheckServicePodsResult struct {
|
||||
checkAllPodResult models.CheckAllPodResult
|
||||
hostIPv4 strfmt.IPv4
|
||||
podIP string
|
||||
}
|
||||
|
||||
func CheckAllPods(pods map[string]string) *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
|
||||
|
||||
CountCall("made", "check")
|
||||
timer := GetLabeledPeersCallsTimer("check", hostIP, podIP)
|
||||
resp, err := getClient(pickPodHostIP(podIP, hostIP)).Operations.CheckServicePods(nil)
|
||||
|
||||
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 {
|
||||
channelResult.checkAllPodResult = models.CheckAllPodResult{
|
||||
OK: &OK,
|
||||
HostIP: channelResult.hostIPv4,
|
||||
Error: err.Error(),
|
||||
}
|
||||
CountError("checkAll")
|
||||
}
|
||||
channelResult.podIP = podIP
|
||||
|
||||
ch <- channelResult
|
||||
wg.Done()
|
||||
}(podIP, hostIP)
|
||||
}
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
|
||||
for response := range ch {
|
||||
var podIPv4 strfmt.IPv4
|
||||
podIPv4.UnmarshalText([]byte(response.podIP))
|
||||
|
||||
result.Responses[response.podIP] = response.checkAllPodResult
|
||||
result.Hosts = append(result.Hosts, &models.CheckAllResultsHostsItems0{
|
||||
HostIP: response.hostIPv4,
|
||||
PodIP: podIPv4,
|
||||
})
|
||||
}
|
||||
return &result
|
||||
}
|
||||
|
||||
func getClient(hostIP string) *apiclient.Goldpinger {
|
||||
host := fmt.Sprintf("%s:%d", hostIP, GoldpingerConfig.Port)
|
||||
transport := httptransport.New(host, "", nil)
|
||||
client := apiclient.New(transport, strfmt.Default)
|
||||
apiclient.Default.SetTransport(transport)
|
||||
|
||||
return client
|
||||
}
|
||||
29
pkg/goldpinger/config.go
Normal file
29
pkg/goldpinger/config.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// 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 (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
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"`
|
||||
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"`
|
||||
KubernetesClient *kubernetes.Clientset
|
||||
}{}
|
||||
39
pkg/goldpinger/k8s.go
Normal file
39
pkg/goldpinger/k8s.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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 (
|
||||
"log"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func GetAllPods() map[string]string {
|
||||
|
||||
timer := GetLabeledKubernetesCallsTimer()
|
||||
pods, err := GoldpingerConfig.KubernetesClient.CoreV1().Pods("").List(metav1.ListOptions{LabelSelector: "app=goldpinger"})
|
||||
if err != nil {
|
||||
log.Println("Error getting pods for selector: ", err.Error())
|
||||
CountError("kubernetes_api")
|
||||
} else {
|
||||
timer.ObserveDuration()
|
||||
}
|
||||
|
||||
var podsreturn = make(map[string]string)
|
||||
for _, pod := range pods.Items {
|
||||
podsreturn[pod.Status.PodIP] = pod.Status.HostIP
|
||||
}
|
||||
return podsreturn
|
||||
}
|
||||
173
pkg/goldpinger/stats.go
Normal file
173
pkg/goldpinger/stats.go
Normal file
@@ -0,0 +1,173 @@
|
||||
// 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 (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/bloomberg/goldpinger/pkg/models"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var (
|
||||
goldpingerStatsCounter = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "goldpinger_stats_total",
|
||||
Help: "Statistics of calls made in goldpinger instances",
|
||||
},
|
||||
[]string{
|
||||
"goldpinger_instance",
|
||||
"group",
|
||||
"action",
|
||||
},
|
||||
)
|
||||
|
||||
goldpingerNodesHealthGauge = prometheus.NewGaugeVec(
|
||||
prometheus.GaugeOpts{
|
||||
Name: "goldpinger_nodes_health_total",
|
||||
Help: "Number of nodes seen as healthy/unhealthy from this instance's POV",
|
||||
},
|
||||
[]string{
|
||||
"goldpinger_instance",
|
||||
"status",
|
||||
},
|
||||
)
|
||||
|
||||
goldpingerResponseTimePeersHistogram = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "goldpinger_peers_response_time_s",
|
||||
Help: "Histogram of response times from other hosts, when making peer calls",
|
||||
Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 30},
|
||||
},
|
||||
[]string{
|
||||
"goldpinger_instance",
|
||||
"call_type",
|
||||
"host_ip",
|
||||
"pod_ip",
|
||||
},
|
||||
)
|
||||
|
||||
goldpingerResponseTimeKubernetesHistogram = prometheus.NewHistogramVec(
|
||||
prometheus.HistogramOpts{
|
||||
Name: "goldpinger_kube_master_response_time_s",
|
||||
Help: "Histogram of response times from kubernetes API server, when listing other instances",
|
||||
Buckets: []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10, 30},
|
||||
},
|
||||
[]string{
|
||||
"goldpinger_instance",
|
||||
},
|
||||
)
|
||||
|
||||
goldpingerErrorsCounter = prometheus.NewCounterVec(
|
||||
prometheus.CounterOpts{
|
||||
Name: "goldpinger_errors_total",
|
||||
Help: "Statistics of errors per instance",
|
||||
},
|
||||
[]string{
|
||||
"goldpinger_instance",
|
||||
"type",
|
||||
},
|
||||
)
|
||||
|
||||
groups = map[string]map[string]int64{
|
||||
"received": map[string]int64{
|
||||
"ping": 0,
|
||||
"check": 0,
|
||||
"check_all": 0,
|
||||
},
|
||||
"made": map[string]int64{
|
||||
"ping": 0,
|
||||
"check": 0,
|
||||
"check_all": 0,
|
||||
},
|
||||
}
|
||||
|
||||
bootTime = time.Now()
|
||||
)
|
||||
|
||||
func init() {
|
||||
prometheus.MustRegister(goldpingerStatsCounter)
|
||||
prometheus.MustRegister(goldpingerNodesHealthGauge)
|
||||
prometheus.MustRegister(goldpingerResponseTimePeersHistogram)
|
||||
prometheus.MustRegister(goldpingerResponseTimeKubernetesHistogram)
|
||||
prometheus.MustRegister(goldpingerErrorsCounter)
|
||||
log.Println("Metrics setup - see /metrics")
|
||||
}
|
||||
|
||||
func GetStats() *models.PingResults {
|
||||
var result models.PingResults
|
||||
var calls models.CallStats
|
||||
|
||||
calls.Check = groups["received"]["check"]
|
||||
calls.CheckAll = groups["received"]["check_all"]
|
||||
calls.Ping = groups["received"]["ping"]
|
||||
result.BootTime = strfmt.DateTime(bootTime)
|
||||
result.Received = &calls
|
||||
return &result
|
||||
}
|
||||
|
||||
// counts various calls received and made
|
||||
func CountCall(group string, call string) {
|
||||
groups[group][call]++
|
||||
|
||||
goldpingerStatsCounter.WithLabelValues(
|
||||
GoldpingerConfig.Hostname,
|
||||
group,
|
||||
call,
|
||||
).Inc()
|
||||
}
|
||||
|
||||
// counts healthy and unhealthy nodes
|
||||
func CountHealthyUnhealthyNodes(healthy, unhealthy float64) {
|
||||
goldpingerNodesHealthGauge.WithLabelValues(
|
||||
GoldpingerConfig.Hostname,
|
||||
"healthy",
|
||||
).Set(healthy)
|
||||
goldpingerNodesHealthGauge.WithLabelValues(
|
||||
GoldpingerConfig.Hostname,
|
||||
"unhealthy",
|
||||
).Set(unhealthy)
|
||||
}
|
||||
|
||||
// counts instances of various errors
|
||||
func CountError(errorType string) {
|
||||
goldpingerErrorsCounter.WithLabelValues(
|
||||
GoldpingerConfig.Hostname,
|
||||
errorType,
|
||||
).Inc()
|
||||
}
|
||||
|
||||
// returns a timer for easy observing of the durations of calls to kubernetes API
|
||||
func GetLabeledKubernetesCallsTimer() *prometheus.Timer {
|
||||
return prometheus.NewTimer(
|
||||
goldpingerResponseTimeKubernetesHistogram.WithLabelValues(
|
||||
GoldpingerConfig.Hostname,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// returns a timer for easy observing of the duration of calls to peers
|
||||
func GetLabeledPeersCallsTimer(callType, hostIP, podIP string) *prometheus.Timer {
|
||||
return prometheus.NewTimer(
|
||||
goldpingerResponseTimePeersHistogram.WithLabelValues(
|
||||
GoldpingerConfig.Hostname,
|
||||
callType,
|
||||
hostIP,
|
||||
podIP,
|
||||
),
|
||||
)
|
||||
}
|
||||
45
pkg/goldpinger/updater.go
Normal file
45
pkg/goldpinger/updater.go
Normal file
@@ -0,0 +1,45 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
func StartUpdater() {
|
||||
|
||||
if GoldpingerConfig.RefreshInterval <= 0 {
|
||||
log.Println("Not creating updater, period is 0")
|
||||
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()))
|
||||
}
|
||||
}
|
||||
if len(troublemakers) > 0 {
|
||||
log.Println("Updater ran into trouble with these peers: ", troublemakers)
|
||||
}
|
||||
time.Sleep(time.Duration(GoldpingerConfig.RefreshInterval) * time.Second)
|
||||
}
|
||||
}()
|
||||
}
|
||||
63
pkg/models/call_stats.go
Normal file
63
pkg/models/call_stats.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/swag"
|
||||
)
|
||||
|
||||
// CallStats call stats
|
||||
// swagger:model CallStats
|
||||
type CallStats struct {
|
||||
|
||||
// check
|
||||
Check int64 `json:"check,omitempty"`
|
||||
|
||||
// check all
|
||||
CheckAll int64 `json:"check_all,omitempty"`
|
||||
|
||||
// ping
|
||||
Ping int64 `json:"ping,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this call stats
|
||||
func (m *CallStats) Validate(formats strfmt.Registry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *CallStats) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *CallStats) UnmarshalBinary(b []byte) error {
|
||||
var res CallStats
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
114
pkg/models/check_all_pod_result.go
Normal file
114
pkg/models/check_all_pod_result.go
Normal file
@@ -0,0 +1,114 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// CheckAllPodResult check all pod result
|
||||
// swagger:model CheckAllPodResult
|
||||
type CheckAllPodResult struct {
|
||||
|
||||
// host IP
|
||||
// Format: ipv4
|
||||
HostIP strfmt.IPv4 `json:"HostIP,omitempty"`
|
||||
|
||||
// o k
|
||||
OK *bool `json:"OK,omitempty"`
|
||||
|
||||
// error
|
||||
Error string `json:"error,omitempty"`
|
||||
|
||||
// response
|
||||
Response CheckResults `json:"response,omitempty"`
|
||||
|
||||
// status code
|
||||
StatusCode int32 `json:"status-code,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this check all pod result
|
||||
func (m *CheckAllPodResult) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateHostIP(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateResponse(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CheckAllPodResult) validateHostIP(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.HostIP) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validate.FormatOf("HostIP", "body", "ipv4", m.HostIP.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")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *CheckAllPodResult) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *CheckAllPodResult) UnmarshalBinary(b []byte) error {
|
||||
var res CheckAllPodResult
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
208
pkg/models/check_all_results.go
Normal file
208
pkg/models/check_all_results.go
Normal file
@@ -0,0 +1,208 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// CheckAllResults check all results
|
||||
// swagger:model CheckAllResults
|
||||
type CheckAllResults struct {
|
||||
|
||||
// o k
|
||||
OK *bool `json:"OK,omitempty"`
|
||||
|
||||
// hosts
|
||||
Hosts []*CheckAllResultsHostsItems0 `json:"hosts"`
|
||||
|
||||
// hosts healthy
|
||||
HostsHealthy int32 `json:"hosts-healthy,omitempty"`
|
||||
|
||||
// hosts number
|
||||
HostsNumber int32 `json:"hosts-number,omitempty"`
|
||||
|
||||
// responses
|
||||
Responses map[string]CheckAllPodResult `json:"responses,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this check all results
|
||||
func (m *CheckAllResults) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateHosts(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateResponses(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CheckAllResults) validateHosts(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Hosts) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(m.Hosts); i++ {
|
||||
if swag.IsZero(m.Hosts[i]) { // not required
|
||||
continue
|
||||
}
|
||||
|
||||
if m.Hosts[i] != nil {
|
||||
if err := m.Hosts[i].Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("hosts" + "." + strconv.Itoa(i))
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CheckAllResults) validateResponses(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Responses) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
for k := range m.Responses {
|
||||
|
||||
if err := validate.Required("responses"+"."+k, "body", m.Responses[k]); err != nil {
|
||||
return err
|
||||
}
|
||||
if val, ok := m.Responses[k]; ok {
|
||||
if err := val.Validate(formats); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *CheckAllResults) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *CheckAllResults) UnmarshalBinary(b []byte) error {
|
||||
var res CheckAllResults
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckAllResultsHostsItems0 check all results hosts items0
|
||||
// swagger:model CheckAllResultsHostsItems0
|
||||
type CheckAllResultsHostsItems0 struct {
|
||||
|
||||
// host IP
|
||||
// Format: ipv4
|
||||
HostIP strfmt.IPv4 `json:"hostIP,omitempty"`
|
||||
|
||||
// pod IP
|
||||
// Format: ipv4
|
||||
PodIP strfmt.IPv4 `json:"podIP,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this check all results hosts items0
|
||||
func (m *CheckAllResultsHostsItems0) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateHostIP(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validatePodIP(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CheckAllResultsHostsItems0) validateHostIP(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.HostIP) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validate.FormatOf("hostIP", "body", "ipv4", m.HostIP.String(), formats); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CheckAllResultsHostsItems0) 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
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *CheckAllResultsHostsItems0) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *CheckAllResultsHostsItems0) UnmarshalBinary(b []byte) error {
|
||||
var res CheckAllResultsHostsItems0
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
54
pkg/models/check_results.go
Normal file
54
pkg/models/check_results.go
Normal file
@@ -0,0 +1,54 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// CheckResults check results
|
||||
// swagger:model CheckResults
|
||||
type CheckResults map[string]PodResult
|
||||
|
||||
// Validate validates this check results
|
||||
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 len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
107
pkg/models/ping_results.go
Normal file
107
pkg/models/ping_results.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// PingResults ping results
|
||||
// swagger:model PingResults
|
||||
type PingResults struct {
|
||||
|
||||
// boot time
|
||||
// Format: date-time
|
||||
BootTime strfmt.DateTime `json:"boot_time,omitempty"`
|
||||
|
||||
// received
|
||||
Received *CallStats `json:"received,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this ping results
|
||||
func (m *PingResults) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateBootTime(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateReceived(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PingResults) validateBootTime(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.BootTime) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validate.FormatOf("boot_time", "body", "date-time", m.BootTime.String(), formats); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PingResults) validateReceived(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.Received) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.Received != nil {
|
||||
if err := m.Received.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("received")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *PingResults) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *PingResults) UnmarshalBinary(b []byte) error {
|
||||
var res PingResults
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
116
pkg/models/pod_result.go
Normal file
116
pkg/models/pod_result.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
strfmt "github.com/go-openapi/strfmt"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/go-openapi/validate"
|
||||
)
|
||||
|
||||
// PodResult pod result
|
||||
// swagger:model PodResult
|
||||
type PodResult struct {
|
||||
|
||||
// host IP
|
||||
// Format: ipv4
|
||||
HostIP strfmt.IPv4 `json:"HostIP,omitempty"`
|
||||
|
||||
// o k
|
||||
OK *bool `json:"OK,omitempty"`
|
||||
|
||||
// error
|
||||
Error string `json:"error,omitempty"`
|
||||
|
||||
// response
|
||||
Response *PingResults `json:"response,omitempty"`
|
||||
|
||||
// status code
|
||||
StatusCode int32 `json:"status-code,omitempty"`
|
||||
}
|
||||
|
||||
// Validate validates this pod result
|
||||
func (m *PodResult) Validate(formats strfmt.Registry) error {
|
||||
var res []error
|
||||
|
||||
if err := m.validateHostIP(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if err := m.validateResponse(formats); err != nil {
|
||||
res = append(res, err)
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PodResult) validateHostIP(formats strfmt.Registry) error {
|
||||
|
||||
if swag.IsZero(m.HostIP) { // not required
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := validate.FormatOf("HostIP", "body", "ipv4", m.HostIP.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
|
||||
}
|
||||
|
||||
if m.Response != nil {
|
||||
if err := m.Response.Validate(formats); err != nil {
|
||||
if ve, ok := err.(*errors.Validation); ok {
|
||||
return ve.ValidateName("response")
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalBinary interface implementation
|
||||
func (m *PodResult) MarshalBinary() ([]byte, error) {
|
||||
if m == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return swag.WriteJSON(m)
|
||||
}
|
||||
|
||||
// UnmarshalBinary interface implementation
|
||||
func (m *PodResult) UnmarshalBinary(b []byte) error {
|
||||
var res PodResult
|
||||
if err := swag.ReadJSON(b, &res); err != nil {
|
||||
return err
|
||||
}
|
||||
*m = res
|
||||
return nil
|
||||
}
|
||||
126
pkg/restapi/configure_goldpinger.go
Normal file
126
pkg/restapi/configure_goldpinger.go
Normal file
@@ -0,0 +1,126 @@
|
||||
// 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 restapi
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
|
||||
"github.com/bloomberg/goldpinger/pkg/goldpinger"
|
||||
"github.com/bloomberg/goldpinger/pkg/restapi/operations"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
//go:generate swagger generate server --target ../goldpinger --name Goldpinger --spec ../swagger.yml --exclude-main
|
||||
|
||||
func configureFlags(api *operations.GoldpingerAPI) {
|
||||
api.CommandLineOptionsGroups = []swag.CommandLineOptionsGroup{
|
||||
swag.CommandLineOptionsGroup{
|
||||
ShortDescription: "Goldpinger Config",
|
||||
LongDescription: "",
|
||||
Options: &goldpinger.GoldpingerConfig,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func configureAPI(api *operations.GoldpingerAPI) http.Handler {
|
||||
// configure the api here
|
||||
api.ServeError = errors.ServeError
|
||||
|
||||
api.JSONConsumer = runtime.JSONConsumer()
|
||||
api.JSONProducer = runtime.JSONProducer()
|
||||
|
||||
api.PingHandler = operations.PingHandlerFunc(
|
||||
func(params operations.PingParams) middleware.Responder {
|
||||
goldpinger.CountCall("received", "ping")
|
||||
return operations.NewPingOK().WithPayload(goldpinger.GetStats())
|
||||
})
|
||||
|
||||
api.CheckServicePodsHandler = operations.CheckServicePodsHandlerFunc(
|
||||
func(params operations.CheckServicePodsParams) middleware.Responder {
|
||||
goldpinger.CountCall("received", "check")
|
||||
return operations.NewCheckServicePodsOK().WithPayload(goldpinger.CheckNeighbours())
|
||||
})
|
||||
|
||||
api.CheckAllPodsHandler = operations.CheckAllPodsHandlerFunc(
|
||||
func(params operations.CheckAllPodsParams) middleware.Responder {
|
||||
goldpinger.CountCall("received", "check_all")
|
||||
return operations.NewCheckAllPodsOK().WithPayload(goldpinger.CheckNeighboursNeighbours())
|
||||
})
|
||||
|
||||
api.ServerShutdown = func() {}
|
||||
|
||||
return setupGlobalMiddleware(api.Serve(setupMiddlewares))
|
||||
}
|
||||
|
||||
// The TLS configuration before HTTPS server starts.
|
||||
func configureTLS(tlsConfig *tls.Config) {
|
||||
// Make all necessary changes to the TLS configuration here.
|
||||
}
|
||||
|
||||
// As soon as server is initialized but not run yet, this function will be called.
|
||||
// If you need to modify a config, store server instance to stop it individually later, this is the place.
|
||||
// This function can be called multiple times, depending on the number of serving schemes.
|
||||
// scheme value will be set accordingly: "http", "https" or "unix"
|
||||
func configureServer(s *http.Server, scheme, addr string) {
|
||||
}
|
||||
|
||||
// The middleware configuration is for the handler executors. These do not apply to the swagger.json document.
|
||||
// The middleware executes after routing but before authentication, binding and validation
|
||||
func setupMiddlewares(handler http.Handler) http.Handler {
|
||||
return handler
|
||||
}
|
||||
|
||||
func fileServerMiddleware(next http.Handler) http.Handler {
|
||||
log.Println("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 strings.HasPrefix(r.URL.Path, "/static/") {
|
||||
http.StripPrefix("/static/", fileServer).ServeHTTP(w, r)
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func prometheusMetricsMiddleware(next http.Handler) http.Handler {
|
||||
log.Println("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)
|
||||
} else {
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document.
|
||||
// So this is a good place to plug in a panic handling middleware, logging and metrics
|
||||
func setupGlobalMiddleware(handler http.Handler) http.Handler {
|
||||
return prometheusMetricsMiddleware(fileServerMiddleware(handler))
|
||||
}
|
||||
34
pkg/restapi/doc.go
Normal file
34
pkg/restapi/doc.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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
|
||||
390
pkg/restapi/embedded_spec.go
Normal file
390
pkg/restapi/embedded_spec.go
Normal file
@@ -0,0 +1,390 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
var (
|
||||
// SwaggerJSON embedded version of the swagger document used at generation time
|
||||
SwaggerJSON json.RawMessage
|
||||
// FlatSwaggerJSON embedded flattened version of the swagger document used at generation time
|
||||
FlatSwaggerJSON json.RawMessage
|
||||
)
|
||||
|
||||
func init() {
|
||||
SwaggerJSON = json.RawMessage([]byte(`{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "Goldpinger",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/check": {
|
||||
"get": {
|
||||
"description": "Queries the API server for all other pods in this service, and pings them via their pods IPs. Calls their /ping endpoint",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "checkServicePods",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success, return response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/CheckResults"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/check_all": {
|
||||
"get": {
|
||||
"description": "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.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "checkAllPods",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success, return response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/CheckAllResults"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ping": {
|
||||
"get": {
|
||||
"description": "return query stats",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "ping",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "return success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PingResults"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"CallStats": {
|
||||
"properties": {
|
||||
"check": {
|
||||
"type": "integer"
|
||||
},
|
||||
"check_all": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ping": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CheckAllPodResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"HostIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
},
|
||||
"OK": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "#/definitions/CheckResults"
|
||||
},
|
||||
"status-code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CheckAllResults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"OK": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"hosts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hostIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
},
|
||||
"podIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"hosts-healthy": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"hosts-number": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"responses": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/CheckAllPodResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CheckResults": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/PodResult"
|
||||
}
|
||||
},
|
||||
"PingResults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"boot_time": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"received": {
|
||||
"$ref": "#/definitions/CallStats"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PodResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"HostIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
},
|
||||
"OK": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "#/definitions/PingResults"
|
||||
},
|
||||
"status-code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`))
|
||||
FlatSwaggerJSON = json.RawMessage([]byte(`{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "Goldpinger",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/check": {
|
||||
"get": {
|
||||
"description": "Queries the API server for all other pods in this service, and pings them via their pods IPs. Calls their /ping endpoint",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "checkServicePods",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success, return response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/CheckResults"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/check_all": {
|
||||
"get": {
|
||||
"description": "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.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "checkAllPods",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Success, return response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/CheckAllResults"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ping": {
|
||||
"get": {
|
||||
"description": "return query stats",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"operationId": "ping",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "return success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/PingResults"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"CallStats": {
|
||||
"properties": {
|
||||
"check": {
|
||||
"type": "integer"
|
||||
},
|
||||
"check_all": {
|
||||
"type": "integer"
|
||||
},
|
||||
"ping": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CheckAllPodResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"HostIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
},
|
||||
"OK": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "#/definitions/CheckResults"
|
||||
},
|
||||
"status-code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CheckAllResults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"OK": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"hosts": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"hostIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
},
|
||||
"podIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"hosts-healthy": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"hosts-number": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"responses": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/CheckAllPodResult"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CheckResults": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/PodResult"
|
||||
}
|
||||
},
|
||||
"PingResults": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"boot_time": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"received": {
|
||||
"$ref": "#/definitions/CallStats"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PodResult": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"HostIP": {
|
||||
"type": "string",
|
||||
"format": "ipv4"
|
||||
},
|
||||
"OK": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"response": {
|
||||
"$ref": "#/definitions/PingResults"
|
||||
},
|
||||
"status-code": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}`))
|
||||
}
|
||||
72
pkg/restapi/operations/check_all_pods.go
Normal file
72
pkg/restapi/operations/check_all_pods.go
Normal 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.
|
||||
|
||||
// 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"
|
||||
|
||||
middleware "github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// CheckAllPodsHandlerFunc turns a function with the right signature into a check all pods handler
|
||||
type CheckAllPodsHandlerFunc func(CheckAllPodsParams) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn CheckAllPodsHandlerFunc) Handle(params CheckAllPodsParams) middleware.Responder {
|
||||
return fn(params)
|
||||
}
|
||||
|
||||
// CheckAllPodsHandler interface for that can handle valid check all pods params
|
||||
type CheckAllPodsHandler interface {
|
||||
Handle(CheckAllPodsParams) middleware.Responder
|
||||
}
|
||||
|
||||
// NewCheckAllPods creates a new http.Handler for the check all pods operation
|
||||
func NewCheckAllPods(ctx *middleware.Context, handler CheckAllPodsHandler) *CheckAllPods {
|
||||
return &CheckAllPods{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*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.
|
||||
|
||||
*/
|
||||
type CheckAllPods struct {
|
||||
Context *middleware.Context
|
||||
Handler CheckAllPodsHandler
|
||||
}
|
||||
|
||||
func (o *CheckAllPods) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
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)
|
||||
|
||||
}
|
||||
59
pkg/restapi/operations/check_all_pods_parameters.go
Normal file
59
pkg/restapi/operations/check_all_pods_parameters.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
// NewCheckAllPodsParams creates a new CheckAllPodsParams object
|
||||
// no default values defined in spec.
|
||||
func NewCheckAllPodsParams() CheckAllPodsParams {
|
||||
|
||||
return CheckAllPodsParams{}
|
||||
}
|
||||
|
||||
// CheckAllPodsParams contains all the bound params for the check all pods operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters checkAllPods
|
||||
type CheckAllPodsParams 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 NewCheckAllPodsParams() beforehand.
|
||||
func (o *CheckAllPodsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
72
pkg/restapi/operations/check_all_pods_responses.go
Normal file
72
pkg/restapi/operations/check_all_pods_responses.go
Normal 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.
|
||||
|
||||
// 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"
|
||||
|
||||
models "github.com/bloomberg/goldpinger/pkg/models"
|
||||
)
|
||||
|
||||
// CheckAllPodsOKCode is the HTTP code returned for type CheckAllPodsOK
|
||||
const CheckAllPodsOKCode int = 200
|
||||
|
||||
/*CheckAllPodsOK Success, return response
|
||||
|
||||
swagger:response checkAllPodsOK
|
||||
*/
|
||||
type CheckAllPodsOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.CheckAllResults `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewCheckAllPodsOK creates CheckAllPodsOK with default headers values
|
||||
func NewCheckAllPodsOK() *CheckAllPodsOK {
|
||||
|
||||
return &CheckAllPodsOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the check all pods o k response
|
||||
func (o *CheckAllPodsOK) WithPayload(payload *models.CheckAllResults) *CheckAllPodsOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the check all pods o k response
|
||||
func (o *CheckAllPodsOK) SetPayload(payload *models.CheckAllResults) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *CheckAllPodsOK) 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
|
||||
}
|
||||
}
|
||||
}
|
||||
98
pkg/restapi/operations/check_all_pods_urlbuilder.go
Normal file
98
pkg/restapi/operations/check_all_pods_urlbuilder.go
Normal file
@@ -0,0 +1,98 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
// CheckAllPodsURL generates an URL for the check all pods operation
|
||||
type CheckAllPodsURL 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 *CheckAllPodsURL) WithBasePath(bp string) *CheckAllPodsURL {
|
||||
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 *CheckAllPodsURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *CheckAllPodsURL) Build() (*url.URL, error) {
|
||||
var result url.URL
|
||||
|
||||
var _path = "/check_all"
|
||||
|
||||
_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 *CheckAllPodsURL) 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 *CheckAllPodsURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *CheckAllPodsURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on CheckAllPodsURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on CheckAllPodsURL")
|
||||
}
|
||||
|
||||
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 *CheckAllPodsURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
72
pkg/restapi/operations/check_service_pods.go
Normal file
72
pkg/restapi/operations/check_service_pods.go
Normal 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.
|
||||
|
||||
// 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"
|
||||
|
||||
middleware "github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// CheckServicePodsHandlerFunc turns a function with the right signature into a check service pods handler
|
||||
type CheckServicePodsHandlerFunc func(CheckServicePodsParams) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn CheckServicePodsHandlerFunc) Handle(params CheckServicePodsParams) middleware.Responder {
|
||||
return fn(params)
|
||||
}
|
||||
|
||||
// CheckServicePodsHandler interface for that can handle valid check service pods params
|
||||
type CheckServicePodsHandler interface {
|
||||
Handle(CheckServicePodsParams) middleware.Responder
|
||||
}
|
||||
|
||||
// NewCheckServicePods creates a new http.Handler for the check service pods operation
|
||||
func NewCheckServicePods(ctx *middleware.Context, handler CheckServicePodsHandler) *CheckServicePods {
|
||||
return &CheckServicePods{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*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
|
||||
|
||||
*/
|
||||
type CheckServicePods struct {
|
||||
Context *middleware.Context
|
||||
Handler CheckServicePodsHandler
|
||||
}
|
||||
|
||||
func (o *CheckServicePods) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
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)
|
||||
|
||||
}
|
||||
59
pkg/restapi/operations/check_service_pods_parameters.go
Normal file
59
pkg/restapi/operations/check_service_pods_parameters.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
// NewCheckServicePodsParams creates a new CheckServicePodsParams object
|
||||
// no default values defined in spec.
|
||||
func NewCheckServicePodsParams() CheckServicePodsParams {
|
||||
|
||||
return CheckServicePodsParams{}
|
||||
}
|
||||
|
||||
// CheckServicePodsParams contains all the bound params for the check service pods operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters checkServicePods
|
||||
type CheckServicePodsParams 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 NewCheckServicePodsParams() beforehand.
|
||||
func (o *CheckServicePodsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
71
pkg/restapi/operations/check_service_pods_responses.go
Normal file
71
pkg/restapi/operations/check_service_pods_responses.go
Normal file
@@ -0,0 +1,71 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
|
||||
models "github.com/bloomberg/goldpinger/pkg/models"
|
||||
)
|
||||
|
||||
// CheckServicePodsOKCode is the HTTP code returned for type CheckServicePodsOK
|
||||
const CheckServicePodsOKCode int = 200
|
||||
|
||||
/*CheckServicePodsOK Success, return response
|
||||
|
||||
swagger:response checkServicePodsOK
|
||||
*/
|
||||
type CheckServicePodsOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload models.CheckResults `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewCheckServicePodsOK creates CheckServicePodsOK with default headers values
|
||||
func NewCheckServicePodsOK() *CheckServicePodsOK {
|
||||
|
||||
return &CheckServicePodsOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the check service pods o k response
|
||||
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) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
98
pkg/restapi/operations/check_service_pods_urlbuilder.go
Normal file
98
pkg/restapi/operations/check_service_pods_urlbuilder.go
Normal file
@@ -0,0 +1,98 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
// CheckServicePodsURL generates an URL for the check service pods operation
|
||||
type CheckServicePodsURL 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 *CheckServicePodsURL) WithBasePath(bp string) *CheckServicePodsURL {
|
||||
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 *CheckServicePodsURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *CheckServicePodsURL) Build() (*url.URL, error) {
|
||||
var result url.URL
|
||||
|
||||
var _path = "/check"
|
||||
|
||||
_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 *CheckServicePodsURL) 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 *CheckServicePodsURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *CheckServicePodsURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on CheckServicePodsURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on CheckServicePodsURL")
|
||||
}
|
||||
|
||||
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 *CheckServicePodsURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
316
pkg/restapi/operations/goldpinger_api.go
Normal file
316
pkg/restapi/operations/goldpinger_api.go
Normal file
@@ -0,0 +1,316 @@
|
||||
// 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
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"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/swag"
|
||||
)
|
||||
|
||||
// NewGoldpingerAPI creates a new Goldpinger instance
|
||||
func NewGoldpingerAPI(spec *loads.Document) *GoldpingerAPI {
|
||||
return &GoldpingerAPI{
|
||||
handlers: make(map[string]map[string]http.Handler),
|
||||
formats: strfmt.Default,
|
||||
defaultConsumes: "application/json",
|
||||
defaultProduces: "application/json",
|
||||
customConsumers: make(map[string]runtime.Consumer),
|
||||
customProducers: make(map[string]runtime.Producer),
|
||||
ServerShutdown: func() {},
|
||||
spec: spec,
|
||||
ServeError: errors.ServeError,
|
||||
BasicAuthenticator: security.BasicAuth,
|
||||
APIKeyAuthenticator: security.APIKeyAuth,
|
||||
BearerAuthenticator: security.BearerAuth,
|
||||
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")
|
||||
}),
|
||||
PingHandler: PingHandlerFunc(func(params PingParams) middleware.Responder {
|
||||
return middleware.NotImplemented("operation Ping has not yet been implemented")
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/*GoldpingerAPI the goldpinger API */
|
||||
type GoldpingerAPI struct {
|
||||
spec *loads.Document
|
||||
context *middleware.Context
|
||||
handlers map[string]map[string]http.Handler
|
||||
formats strfmt.Registry
|
||||
customConsumers map[string]runtime.Consumer
|
||||
customProducers map[string]runtime.Producer
|
||||
defaultConsumes string
|
||||
defaultProduces string
|
||||
Middleware func(middleware.Builder) http.Handler
|
||||
|
||||
// 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.
|
||||
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.
|
||||
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.
|
||||
BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator
|
||||
|
||||
// JSONConsumer registers a consumer for a "application/json" mime type
|
||||
JSONConsumer runtime.Consumer
|
||||
|
||||
// JSONProducer registers a producer for a "application/json" mime type
|
||||
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
|
||||
// PingHandler sets the operation handler for the ping operation
|
||||
PingHandler PingHandler
|
||||
|
||||
// ServeError is called when an error is received, there is a default handler
|
||||
// but you can set your own with this
|
||||
ServeError func(http.ResponseWriter, *http.Request, error)
|
||||
|
||||
// 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()
|
||||
|
||||
// Custom command line argument groups with their descriptions
|
||||
CommandLineOptionsGroups []swag.CommandLineOptionsGroup
|
||||
|
||||
// User defined logger function.
|
||||
Logger func(string, ...interface{})
|
||||
}
|
||||
|
||||
// SetDefaultProduces sets the default produces media type
|
||||
func (o *GoldpingerAPI) SetDefaultProduces(mediaType string) {
|
||||
o.defaultProduces = mediaType
|
||||
}
|
||||
|
||||
// SetDefaultConsumes returns the default consumes media type
|
||||
func (o *GoldpingerAPI) SetDefaultConsumes(mediaType string) {
|
||||
o.defaultConsumes = mediaType
|
||||
}
|
||||
|
||||
// SetSpec sets a spec that will be served for the clients.
|
||||
func (o *GoldpingerAPI) SetSpec(spec *loads.Document) {
|
||||
o.spec = spec
|
||||
}
|
||||
|
||||
// DefaultProduces returns the default produces media type
|
||||
func (o *GoldpingerAPI) DefaultProduces() string {
|
||||
return o.defaultProduces
|
||||
}
|
||||
|
||||
// DefaultConsumes returns the default consumes media type
|
||||
func (o *GoldpingerAPI) DefaultConsumes() string {
|
||||
return o.defaultConsumes
|
||||
}
|
||||
|
||||
// Formats returns the registered string formats
|
||||
func (o *GoldpingerAPI) Formats() strfmt.Registry {
|
||||
return o.formats
|
||||
}
|
||||
|
||||
// RegisterFormat registers a custom format validator
|
||||
func (o *GoldpingerAPI) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) {
|
||||
o.formats.Add(name, format, validator)
|
||||
}
|
||||
|
||||
// Validate validates the registrations in the GoldpingerAPI
|
||||
func (o *GoldpingerAPI) Validate() error {
|
||||
var unregistered []string
|
||||
|
||||
if o.JSONConsumer == nil {
|
||||
unregistered = append(unregistered, "JSONConsumer")
|
||||
}
|
||||
|
||||
if o.JSONProducer == nil {
|
||||
unregistered = append(unregistered, "JSONProducer")
|
||||
}
|
||||
|
||||
if o.CheckAllPodsHandler == nil {
|
||||
unregistered = append(unregistered, "CheckAllPodsHandler")
|
||||
}
|
||||
|
||||
if o.CheckServicePodsHandler == nil {
|
||||
unregistered = append(unregistered, "CheckServicePodsHandler")
|
||||
}
|
||||
|
||||
if o.PingHandler == nil {
|
||||
unregistered = append(unregistered, "PingHandler")
|
||||
}
|
||||
|
||||
if len(unregistered) > 0 {
|
||||
return fmt.Errorf("missing registration: %s", strings.Join(unregistered, ", "))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ServeErrorFor gets a error handler for a given operation id
|
||||
func (o *GoldpingerAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) {
|
||||
return o.ServeError
|
||||
}
|
||||
|
||||
// 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
|
||||
func (o *GoldpingerAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer {
|
||||
|
||||
result := make(map[string]runtime.Consumer)
|
||||
for _, mt := range mediaTypes {
|
||||
switch mt {
|
||||
|
||||
case "application/json":
|
||||
result["application/json"] = o.JSONConsumer
|
||||
|
||||
}
|
||||
|
||||
if c, ok := o.customConsumers[mt]; ok {
|
||||
result[mt] = c
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
// ProducersFor gets the producers for the specified media types
|
||||
func (o *GoldpingerAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer {
|
||||
|
||||
result := make(map[string]runtime.Producer)
|
||||
for _, mt := range mediaTypes {
|
||||
switch mt {
|
||||
|
||||
case "application/json":
|
||||
result["application/json"] = o.JSONProducer
|
||||
|
||||
}
|
||||
|
||||
if p, ok := o.customProducers[mt]; ok {
|
||||
result[mt] = p
|
||||
}
|
||||
}
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
// HandlerFor gets a http.Handler for the provided operation method and path
|
||||
func (o *GoldpingerAPI) HandlerFor(method, path string) (http.Handler, bool) {
|
||||
if o.handlers == nil {
|
||||
return nil, false
|
||||
}
|
||||
um := strings.ToUpper(method)
|
||||
if _, ok := o.handlers[um]; !ok {
|
||||
return nil, false
|
||||
}
|
||||
if path == "/" {
|
||||
path = ""
|
||||
}
|
||||
h, ok := o.handlers[um][path]
|
||||
return h, ok
|
||||
}
|
||||
|
||||
// Context returns the middleware context for the goldpinger API
|
||||
func (o *GoldpingerAPI) Context() *middleware.Context {
|
||||
if o.context == nil {
|
||||
o.context = middleware.NewRoutableContext(o.spec, o, nil)
|
||||
}
|
||||
|
||||
return o.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)
|
||||
}
|
||||
|
||||
if o.handlers["GET"] == nil {
|
||||
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"]["/ping"] = NewPing(o.context, o.PingHandler)
|
||||
|
||||
}
|
||||
|
||||
// Serve creates a http handler to serve the API over HTTP
|
||||
// can be used directly in http.ListenAndServe(":8000", api.Serve(nil))
|
||||
func (o *GoldpingerAPI) Serve(builder middleware.Builder) http.Handler {
|
||||
o.Init()
|
||||
|
||||
if o.Middleware != nil {
|
||||
return o.Middleware(builder)
|
||||
}
|
||||
return o.context.APIHandler(builder)
|
||||
}
|
||||
|
||||
// Init allows you to just initialize the handler cache, you can then recompose the middleware as you see fit
|
||||
func (o *GoldpingerAPI) Init() {
|
||||
if len(o.handlers) == 0 {
|
||||
o.initHandlerCache()
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterConsumer allows you to add (or override) a consumer for a media type.
|
||||
func (o *GoldpingerAPI) RegisterConsumer(mediaType string, consumer runtime.Consumer) {
|
||||
o.customConsumers[mediaType] = consumer
|
||||
}
|
||||
|
||||
// RegisterProducer allows you to add (or override) a producer for a media type.
|
||||
func (o *GoldpingerAPI) RegisterProducer(mediaType string, producer runtime.Producer) {
|
||||
o.customProducers[mediaType] = producer
|
||||
}
|
||||
72
pkg/restapi/operations/ping.go
Normal file
72
pkg/restapi/operations/ping.go
Normal 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.
|
||||
|
||||
// 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"
|
||||
|
||||
middleware "github.com/go-openapi/runtime/middleware"
|
||||
)
|
||||
|
||||
// PingHandlerFunc turns a function with the right signature into a ping handler
|
||||
type PingHandlerFunc func(PingParams) middleware.Responder
|
||||
|
||||
// Handle executing the request and returning a response
|
||||
func (fn PingHandlerFunc) Handle(params PingParams) middleware.Responder {
|
||||
return fn(params)
|
||||
}
|
||||
|
||||
// PingHandler interface for that can handle valid ping params
|
||||
type PingHandler interface {
|
||||
Handle(PingParams) middleware.Responder
|
||||
}
|
||||
|
||||
// NewPing creates a new http.Handler for the ping operation
|
||||
func NewPing(ctx *middleware.Context, handler PingHandler) *Ping {
|
||||
return &Ping{Context: ctx, Handler: handler}
|
||||
}
|
||||
|
||||
/*Ping swagger:route GET /ping ping
|
||||
|
||||
return query stats
|
||||
|
||||
*/
|
||||
type Ping struct {
|
||||
Context *middleware.Context
|
||||
Handler PingHandler
|
||||
}
|
||||
|
||||
func (o *Ping) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
route, rCtx, _ := o.Context.RouteInfo(r)
|
||||
if rCtx != nil {
|
||||
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)
|
||||
|
||||
}
|
||||
59
pkg/restapi/operations/ping_parameters.go
Normal file
59
pkg/restapi/operations/ping_parameters.go
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
// NewPingParams creates a new PingParams object
|
||||
// no default values defined in spec.
|
||||
func NewPingParams() PingParams {
|
||||
|
||||
return PingParams{}
|
||||
}
|
||||
|
||||
// PingParams contains all the bound params for the ping operation
|
||||
// typically these are obtained from a http.Request
|
||||
//
|
||||
// swagger:parameters ping
|
||||
type PingParams 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 NewPingParams() beforehand.
|
||||
func (o *PingParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
|
||||
var res []error
|
||||
|
||||
o.HTTPRequest = r
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
72
pkg/restapi/operations/ping_responses.go
Normal file
72
pkg/restapi/operations/ping_responses.go
Normal 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.
|
||||
|
||||
// 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"
|
||||
|
||||
models "github.com/bloomberg/goldpinger/pkg/models"
|
||||
)
|
||||
|
||||
// PingOKCode is the HTTP code returned for type PingOK
|
||||
const PingOKCode int = 200
|
||||
|
||||
/*PingOK return success
|
||||
|
||||
swagger:response pingOK
|
||||
*/
|
||||
type PingOK struct {
|
||||
|
||||
/*
|
||||
In: Body
|
||||
*/
|
||||
Payload *models.PingResults `json:"body,omitempty"`
|
||||
}
|
||||
|
||||
// NewPingOK creates PingOK with default headers values
|
||||
func NewPingOK() *PingOK {
|
||||
|
||||
return &PingOK{}
|
||||
}
|
||||
|
||||
// WithPayload adds the payload to the ping o k response
|
||||
func (o *PingOK) WithPayload(payload *models.PingResults) *PingOK {
|
||||
o.Payload = payload
|
||||
return o
|
||||
}
|
||||
|
||||
// SetPayload sets the payload to the ping o k response
|
||||
func (o *PingOK) SetPayload(payload *models.PingResults) {
|
||||
o.Payload = payload
|
||||
}
|
||||
|
||||
// WriteResponse to the client
|
||||
func (o *PingOK) 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
|
||||
}
|
||||
}
|
||||
}
|
||||
98
pkg/restapi/operations/ping_urlbuilder.go
Normal file
98
pkg/restapi/operations/ping_urlbuilder.go
Normal file
@@ -0,0 +1,98 @@
|
||||
// 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
|
||||
|
||||
// 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"
|
||||
)
|
||||
|
||||
// PingURL generates an URL for the ping operation
|
||||
type PingURL 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 *PingURL) WithBasePath(bp string) *PingURL {
|
||||
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 *PingURL) SetBasePath(bp string) {
|
||||
o._basePath = bp
|
||||
}
|
||||
|
||||
// Build a url path and query string
|
||||
func (o *PingURL) Build() (*url.URL, error) {
|
||||
var result url.URL
|
||||
|
||||
var _path = "/ping"
|
||||
|
||||
_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 *PingURL) 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 *PingURL) String() string {
|
||||
return o.Must(o.Build()).String()
|
||||
}
|
||||
|
||||
// BuildFull builds a full url with scheme, host, path and query string
|
||||
func (o *PingURL) BuildFull(scheme, host string) (*url.URL, error) {
|
||||
if scheme == "" {
|
||||
return nil, errors.New("scheme is required for a full url on PingURL")
|
||||
}
|
||||
if host == "" {
|
||||
return nil, errors.New("host is required for a full url on PingURL")
|
||||
}
|
||||
|
||||
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 *PingURL) StringFull(scheme, host string) string {
|
||||
return o.Must(o.BuildFull(scheme, host)).String()
|
||||
}
|
||||
522
pkg/restapi/server.go
Normal file
522
pkg/restapi/server.go
Normal file
@@ -0,0 +1,522 @@
|
||||
// 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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/runtime/flagext"
|
||||
"github.com/go-openapi/swag"
|
||||
flags "github.com/jessevdk/go-flags"
|
||||
"golang.org/x/net/netutil"
|
||||
|
||||
"github.com/bloomberg/goldpinger/pkg/restapi/operations"
|
||||
)
|
||||
|
||||
const (
|
||||
schemeHTTP = "http"
|
||||
schemeHTTPS = "https"
|
||||
schemeUnix = "unix"
|
||||
)
|
||||
|
||||
var defaultSchemes []string
|
||||
|
||||
func init() {
|
||||
defaultSchemes = []string{
|
||||
schemeHTTP,
|
||||
}
|
||||
}
|
||||
|
||||
// NewServer creates a new api goldpinger server but does not configure it
|
||||
func NewServer(api *operations.GoldpingerAPI) *Server {
|
||||
s := new(Server)
|
||||
|
||||
s.shutdown = make(chan struct{})
|
||||
s.api = api
|
||||
s.interrupt = make(chan os.Signal, 1)
|
||||
return s
|
||||
}
|
||||
|
||||
// ConfigureAPI configures the API and handlers.
|
||||
func (s *Server) ConfigureAPI() {
|
||||
if s.api != nil {
|
||||
s.handler = configureAPI(s.api)
|
||||
}
|
||||
}
|
||||
|
||||
// ConfigureFlags configures the additional flags defined by the handlers. Needs to be called before the parser.Parse
|
||||
func (s *Server) ConfigureFlags() {
|
||||
if s.api != nil {
|
||||
configureFlags(s.api)
|
||||
}
|
||||
}
|
||||
|
||||
// Server for the goldpinger API
|
||||
type Server struct {
|
||||
EnabledListeners []string `long:"scheme" description:"the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec"`
|
||||
CleanupTimeout time.Duration `long:"cleanup-timeout" description:"grace period for which to wait before killing idle connections" default:"10s"`
|
||||
GracefulTimeout time.Duration `long:"graceful-timeout" description:"grace period for which to wait before shutting down the server" default:"15s"`
|
||||
MaxHeaderSize flagext.ByteSize `long:"max-header-size" description:"controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body." default:"1MiB"`
|
||||
|
||||
SocketPath flags.Filename `long:"socket-path" description:"the unix socket to listen on" default:"/var/run/goldpinger.sock"`
|
||||
domainSocketL net.Listener
|
||||
|
||||
Host string `long:"host" description:"the IP to listen on" default:"localhost" env:"HOST"`
|
||||
Port int `long:"port" description:"the port to listen on for insecure connections, defaults to a random value" env:"PORT"`
|
||||
ListenLimit int `long:"listen-limit" description:"limit the number of outstanding requests"`
|
||||
KeepAlive time.Duration `long:"keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)" default:"3m"`
|
||||
ReadTimeout time.Duration `long:"read-timeout" description:"maximum duration before timing out read of the request" default:"30s"`
|
||||
WriteTimeout time.Duration `long:"write-timeout" description:"maximum duration before timing out write of the response" default:"60s"`
|
||||
httpServerL net.Listener
|
||||
|
||||
TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"`
|
||||
TLSPort int `long:"tls-port" description:"the port to listen on for secure connections, defaults to a random value" env:"TLS_PORT"`
|
||||
TLSCertificate flags.Filename `long:"tls-certificate" description:"the certificate to use for secure connections" env:"TLS_CERTIFICATE"`
|
||||
TLSCertificateKey flags.Filename `long:"tls-key" description:"the private key to use for secure conections" env:"TLS_PRIVATE_KEY"`
|
||||
TLSCACertificate flags.Filename `long:"tls-ca" description:"the certificate authority file to be used with mutual tls auth" env:"TLS_CA_CERTIFICATE"`
|
||||
TLSListenLimit int `long:"tls-listen-limit" description:"limit the number of outstanding requests"`
|
||||
TLSKeepAlive time.Duration `long:"tls-keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)"`
|
||||
TLSReadTimeout time.Duration `long:"tls-read-timeout" description:"maximum duration before timing out read of the request"`
|
||||
TLSWriteTimeout time.Duration `long:"tls-write-timeout" description:"maximum duration before timing out write of the response"`
|
||||
httpsServerL net.Listener
|
||||
|
||||
api *operations.GoldpingerAPI
|
||||
handler http.Handler
|
||||
hasListeners bool
|
||||
shutdown chan struct{}
|
||||
shuttingDown int32
|
||||
interrupted bool
|
||||
interrupt chan os.Signal
|
||||
}
|
||||
|
||||
// Logf logs message either via defined user logger or via system one if no user logger is defined.
|
||||
func (s *Server) Logf(f string, args ...interface{}) {
|
||||
if s.api != nil && s.api.Logger != nil {
|
||||
s.api.Logger(f, args...)
|
||||
} else {
|
||||
log.Printf(f, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// Fatalf logs message either via defined user logger or via system one if no user logger is defined.
|
||||
// Exits with non-zero status after printing
|
||||
func (s *Server) Fatalf(f string, args ...interface{}) {
|
||||
if s.api != nil && s.api.Logger != nil {
|
||||
s.api.Logger(f, args...)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
log.Fatalf(f, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// SetAPI configures the server with the specified API. Needs to be called before Serve
|
||||
func (s *Server) SetAPI(api *operations.GoldpingerAPI) {
|
||||
if api == nil {
|
||||
s.api = nil
|
||||
s.handler = nil
|
||||
return
|
||||
}
|
||||
|
||||
s.api = api
|
||||
s.api.Logger = log.Printf
|
||||
s.handler = configureAPI(api)
|
||||
}
|
||||
|
||||
func (s *Server) hasScheme(scheme string) bool {
|
||||
schemes := s.EnabledListeners
|
||||
if len(schemes) == 0 {
|
||||
schemes = defaultSchemes
|
||||
}
|
||||
|
||||
for _, v := range schemes {
|
||||
if v == scheme {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Serve the api
|
||||
func (s *Server) Serve() (err error) {
|
||||
if !s.hasListeners {
|
||||
if err = s.Listen(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// set default handler, if none is set
|
||||
if s.handler == nil {
|
||||
if s.api == nil {
|
||||
return errors.New("can't create the default handler, as no api is set")
|
||||
}
|
||||
|
||||
s.SetHandler(s.api.Serve(nil))
|
||||
}
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
once := new(sync.Once)
|
||||
signalNotify(s.interrupt)
|
||||
go handleInterrupt(once, s)
|
||||
|
||||
servers := []*http.Server{}
|
||||
wg.Add(1)
|
||||
go s.handleShutdown(wg, &servers)
|
||||
|
||||
if s.hasScheme(schemeUnix) {
|
||||
domainSocket := new(http.Server)
|
||||
domainSocket.MaxHeaderBytes = int(s.MaxHeaderSize)
|
||||
domainSocket.Handler = s.handler
|
||||
if int64(s.CleanupTimeout) > 0 {
|
||||
domainSocket.IdleTimeout = s.CleanupTimeout
|
||||
}
|
||||
|
||||
configureServer(domainSocket, "unix", string(s.SocketPath))
|
||||
|
||||
wg.Add(1)
|
||||
s.Logf("Serving goldpinger at unix://%s", s.SocketPath)
|
||||
go func(l net.Listener) {
|
||||
defer wg.Done()
|
||||
if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed {
|
||||
s.Fatalf("%v", err)
|
||||
}
|
||||
s.Logf("Stopped serving goldpinger at unix://%s", s.SocketPath)
|
||||
}(s.domainSocketL)
|
||||
servers = append(servers, domainSocket)
|
||||
}
|
||||
|
||||
if s.hasScheme(schemeHTTP) {
|
||||
httpServer := new(http.Server)
|
||||
httpServer.MaxHeaderBytes = int(s.MaxHeaderSize)
|
||||
httpServer.ReadTimeout = s.ReadTimeout
|
||||
httpServer.WriteTimeout = s.WriteTimeout
|
||||
httpServer.SetKeepAlivesEnabled(int64(s.KeepAlive) > 0)
|
||||
if s.ListenLimit > 0 {
|
||||
s.httpServerL = netutil.LimitListener(s.httpServerL, s.ListenLimit)
|
||||
}
|
||||
|
||||
if int64(s.CleanupTimeout) > 0 {
|
||||
httpServer.IdleTimeout = s.CleanupTimeout
|
||||
}
|
||||
|
||||
httpServer.Handler = s.handler
|
||||
|
||||
configureServer(httpServer, "http", s.httpServerL.Addr().String())
|
||||
|
||||
wg.Add(1)
|
||||
s.Logf("Serving goldpinger at http://%s", s.httpServerL.Addr())
|
||||
go func(l net.Listener) {
|
||||
defer wg.Done()
|
||||
if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed {
|
||||
s.Fatalf("%v", err)
|
||||
}
|
||||
s.Logf("Stopped serving goldpinger at http://%s", l.Addr())
|
||||
}(s.httpServerL)
|
||||
servers = append(servers, httpServer)
|
||||
}
|
||||
|
||||
if s.hasScheme(schemeHTTPS) {
|
||||
httpsServer := new(http.Server)
|
||||
httpsServer.MaxHeaderBytes = int(s.MaxHeaderSize)
|
||||
httpsServer.ReadTimeout = s.TLSReadTimeout
|
||||
httpsServer.WriteTimeout = s.TLSWriteTimeout
|
||||
httpsServer.SetKeepAlivesEnabled(int64(s.TLSKeepAlive) > 0)
|
||||
if s.TLSListenLimit > 0 {
|
||||
s.httpsServerL = netutil.LimitListener(s.httpsServerL, s.TLSListenLimit)
|
||||
}
|
||||
if int64(s.CleanupTimeout) > 0 {
|
||||
httpsServer.IdleTimeout = s.CleanupTimeout
|
||||
}
|
||||
httpsServer.Handler = s.handler
|
||||
|
||||
// Inspired by https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go
|
||||
httpsServer.TLSConfig = &tls.Config{
|
||||
// Causes servers to use Go's default ciphersuite preferences,
|
||||
// which are tuned to avoid attacks. Does nothing on clients.
|
||||
PreferServerCipherSuites: true,
|
||||
// Only use curves which have assembly implementations
|
||||
// https://github.com/golang/go/tree/master/src/crypto/elliptic
|
||||
CurvePreferences: []tls.CurveID{tls.CurveP256},
|
||||
// Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
|
||||
NextProtos: []string{"http/1.1", "h2"},
|
||||
// https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols
|
||||
MinVersion: tls.VersionTLS12,
|
||||
// These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy
|
||||
CipherSuites: []uint16{
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
|
||||
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
|
||||
},
|
||||
}
|
||||
|
||||
// build standard config from server options
|
||||
if s.TLSCertificate != "" && s.TLSCertificateKey != "" {
|
||||
httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1)
|
||||
httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(string(s.TLSCertificate), string(s.TLSCertificateKey))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if s.TLSCACertificate != "" {
|
||||
// include specified CA certificate
|
||||
caCert, caCertErr := ioutil.ReadFile(string(s.TLSCACertificate))
|
||||
if caCertErr != nil {
|
||||
return caCertErr
|
||||
}
|
||||
caCertPool := x509.NewCertPool()
|
||||
ok := caCertPool.AppendCertsFromPEM(caCert)
|
||||
if !ok {
|
||||
return fmt.Errorf("cannot parse CA certificate")
|
||||
}
|
||||
httpsServer.TLSConfig.ClientCAs = caCertPool
|
||||
httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
}
|
||||
|
||||
// call custom TLS configurator
|
||||
configureTLS(httpsServer.TLSConfig)
|
||||
|
||||
if len(httpsServer.TLSConfig.Certificates) == 0 {
|
||||
// after standard and custom config are passed, this ends up with no certificate
|
||||
if s.TLSCertificate == "" {
|
||||
if s.TLSCertificateKey == "" {
|
||||
s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified")
|
||||
}
|
||||
s.Fatalf("the required flag `--tls-certificate` was not specified")
|
||||
}
|
||||
if s.TLSCertificateKey == "" {
|
||||
s.Fatalf("the required flag `--tls-key` was not specified")
|
||||
}
|
||||
// this happens with a wrong custom TLS configurator
|
||||
s.Fatalf("no certificate was configured for TLS")
|
||||
}
|
||||
|
||||
// must have at least one certificate or panics
|
||||
httpsServer.TLSConfig.BuildNameToCertificate()
|
||||
|
||||
configureServer(httpsServer, "https", s.httpsServerL.Addr().String())
|
||||
|
||||
wg.Add(1)
|
||||
s.Logf("Serving goldpinger at https://%s", s.httpsServerL.Addr())
|
||||
go func(l net.Listener) {
|
||||
defer wg.Done()
|
||||
if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed {
|
||||
s.Fatalf("%v", err)
|
||||
}
|
||||
s.Logf("Stopped serving goldpinger at https://%s", l.Addr())
|
||||
}(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig))
|
||||
servers = append(servers, httpsServer)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Listen creates the listeners for the server
|
||||
func (s *Server) Listen() error {
|
||||
if s.hasListeners { // already done this
|
||||
return nil
|
||||
}
|
||||
|
||||
if s.hasScheme(schemeHTTPS) {
|
||||
// Use http host if https host wasn't defined
|
||||
if s.TLSHost == "" {
|
||||
s.TLSHost = s.Host
|
||||
}
|
||||
// Use http listen limit if https listen limit wasn't defined
|
||||
if s.TLSListenLimit == 0 {
|
||||
s.TLSListenLimit = s.ListenLimit
|
||||
}
|
||||
// Use http tcp keep alive if https tcp keep alive wasn't defined
|
||||
if int64(s.TLSKeepAlive) == 0 {
|
||||
s.TLSKeepAlive = s.KeepAlive
|
||||
}
|
||||
// Use http read timeout if https read timeout wasn't defined
|
||||
if int64(s.TLSReadTimeout) == 0 {
|
||||
s.TLSReadTimeout = s.ReadTimeout
|
||||
}
|
||||
// Use http write timeout if https write timeout wasn't defined
|
||||
if int64(s.TLSWriteTimeout) == 0 {
|
||||
s.TLSWriteTimeout = s.WriteTimeout
|
||||
}
|
||||
}
|
||||
|
||||
if s.hasScheme(schemeUnix) {
|
||||
domSockListener, err := net.Listen("unix", string(s.SocketPath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.domainSocketL = domSockListener
|
||||
}
|
||||
|
||||
if s.hasScheme(schemeHTTP) {
|
||||
listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h, p, err := swag.SplitHostPort(listener.Addr().String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Host = h
|
||||
s.Port = p
|
||||
s.httpServerL = listener
|
||||
}
|
||||
|
||||
if s.hasScheme(schemeHTTPS) {
|
||||
tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.TLSHost = sh
|
||||
s.TLSPort = sp
|
||||
s.httpsServerL = tlsListener
|
||||
}
|
||||
|
||||
s.hasListeners = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shutdown server and clean up resources
|
||||
func (s *Server) Shutdown() error {
|
||||
if atomic.CompareAndSwapInt32(&s.shuttingDown, 0, 1) {
|
||||
close(s.shutdown)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) {
|
||||
// wg.Done must occur last, after s.api.ServerShutdown()
|
||||
// (to preserve old behaviour)
|
||||
defer wg.Done()
|
||||
|
||||
<-s.shutdown
|
||||
|
||||
servers := *serversPtr
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout)
|
||||
defer cancel()
|
||||
|
||||
shutdownChan := make(chan bool)
|
||||
for i := range servers {
|
||||
server := servers[i]
|
||||
go func() {
|
||||
var success bool
|
||||
defer func() {
|
||||
shutdownChan <- success
|
||||
}()
|
||||
if err := server.Shutdown(ctx); err != nil {
|
||||
// Error from closing listeners, or context timeout:
|
||||
s.Logf("HTTP server Shutdown: %v", err)
|
||||
} else {
|
||||
success = true
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Wait until all listeners have successfully shut down before calling ServerShutdown
|
||||
success := true
|
||||
for range servers {
|
||||
success = success && <-shutdownChan
|
||||
}
|
||||
if success {
|
||||
s.api.ServerShutdown()
|
||||
}
|
||||
}
|
||||
|
||||
// GetHandler returns a handler useful for testing
|
||||
func (s *Server) GetHandler() http.Handler {
|
||||
return s.handler
|
||||
}
|
||||
|
||||
// SetHandler allows for setting a http handler on this server
|
||||
func (s *Server) SetHandler(handler http.Handler) {
|
||||
s.handler = handler
|
||||
}
|
||||
|
||||
// UnixListener returns the domain socket listener
|
||||
func (s *Server) UnixListener() (net.Listener, error) {
|
||||
if !s.hasListeners {
|
||||
if err := s.Listen(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return s.domainSocketL, nil
|
||||
}
|
||||
|
||||
// HTTPListener returns the http listener
|
||||
func (s *Server) HTTPListener() (net.Listener, error) {
|
||||
if !s.hasListeners {
|
||||
if err := s.Listen(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return s.httpServerL, nil
|
||||
}
|
||||
|
||||
// TLSListener returns the https listener
|
||||
func (s *Server) TLSListener() (net.Listener, error) {
|
||||
if !s.hasListeners {
|
||||
if err := s.Listen(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return s.httpsServerL, nil
|
||||
}
|
||||
|
||||
func handleInterrupt(once *sync.Once, s *Server) {
|
||||
once.Do(func() {
|
||||
for _ = range s.interrupt {
|
||||
if s.interrupted {
|
||||
s.Logf("Server already shutting down")
|
||||
continue
|
||||
}
|
||||
s.interrupted = true
|
||||
s.Logf("Shutting down... ")
|
||||
if err := s.Shutdown(); err != nil {
|
||||
s.Logf("HTTP server Shutdown: %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func signalNotify(interrupt chan<- os.Signal) {
|
||||
signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
}
|
||||
357
static/index.html
Normal file
357
static/index.html
Normal file
@@ -0,0 +1,357 @@
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<title>Goldpinger</title>
|
||||
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/lodash/4.14.0/lodash.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/sigma.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.exporters.svg.min.js"></script>:
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.layout.forceAtlas2.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.neo4j.cypher.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.parsers.cypher.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.parsers.gexf.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.parsers.json.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.pathfinding.astar.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.plugins.animate.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.plugins.dragNodes.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.plugins.filter.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.plugins.neighborhoods.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.plugins.relativeSize.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.renderers.customEdgeShapes.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.renderers.customShapes.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.renderers.edgeLabels.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.renderers.parallelEdges.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.renderers.snapshot.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/sigma.js/1.1.0/plugins/sigma.statistics.HITS.min.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
|
||||
<!-- Optional theme -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
|
||||
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
#container {
|
||||
}
|
||||
#graph-container {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
/*background-color: white;*/
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Goldpinger</a>
|
||||
</div>
|
||||
<div id="navbar" class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Graph</a></li>
|
||||
<li><a href="#" id="show-data">Data</a></li>
|
||||
<li><a href="/check_all" >Raw</a></li>
|
||||
<li><a href="/metrics" >Metrics</a></li>
|
||||
</ul>
|
||||
<div class="navbar-form navbar-left" role="search">
|
||||
<div class="form-group">
|
||||
<!-- <input id="timeout" type="number" step="any" class="form-control" placeholder="5.0" value="5.0"> -->
|
||||
</div>
|
||||
<button id="reload-graph" class="btn btn-default">reload</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div id="graph-container"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="modal-window-code" class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="modal-title">title</h4>
|
||||
</div>
|
||||
<div class="modal-body" id="modal-body">
|
||||
body
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var fetchJSON = function(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
console.log("calling " + url);
|
||||
var req = new XMLHttpRequest();
|
||||
req.open('get', url, true);
|
||||
req.responseType = 'json';
|
||||
req.onload = function() {
|
||||
if (req.status == 200) {
|
||||
resolve(req.response);
|
||||
} else {
|
||||
reject({
|
||||
status: req.status,
|
||||
response: req.response,
|
||||
statusText: req.statusText
|
||||
});
|
||||
}
|
||||
};
|
||||
req.send();
|
||||
});
|
||||
};
|
||||
|
||||
var prepareJSON = function(subject){
|
||||
return "<code style='white-space: pre;'>"
|
||||
+ JSON.stringify(subject, undefined, 4)
|
||||
+ "</code>"
|
||||
}
|
||||
|
||||
var loadingDialog = function(enable){
|
||||
$('#modal-title').html("Loading");
|
||||
$('#modal-body').html(prepareJSON({stuff:{will_be_there:true, soon: "Math.random() > 0.5"}}));
|
||||
|
||||
// show the things
|
||||
if (enable){
|
||||
$('#modal-window-code').modal('show');
|
||||
} else {
|
||||
$('#modal-window-code').modal('hide');
|
||||
}
|
||||
};
|
||||
|
||||
var global_data = undefined;
|
||||
var s; // the sigma graph
|
||||
|
||||
var main = function(timeout){
|
||||
|
||||
timeout = timeout || Number($("#timeout").val()) || 5.0;
|
||||
|
||||
loadingDialog(true);
|
||||
|
||||
fetchJSON("/check_all?timeout="+timeout)
|
||||
.then(function(data){
|
||||
|
||||
loadingDialog(false);
|
||||
|
||||
//console.log(data);
|
||||
global_data = data;
|
||||
|
||||
// prepare nodes
|
||||
var nodes = [];
|
||||
var resp = data.responses;
|
||||
_.forOwn(resp, function(value, podIP) {
|
||||
nodes.push({
|
||||
"label": podIP+ " (" + value.HostIP + ")",
|
||||
"id": podIP,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
_data: value
|
||||
});
|
||||
});
|
||||
//console.log(nodes);
|
||||
|
||||
// prepare the edges
|
||||
var edges = [];
|
||||
var resp = data.responses;
|
||||
_.forOwn(resp, function(value, source) {
|
||||
var call = value.response;
|
||||
if (!_.isString(call)){
|
||||
_.forOwn(call, function(value, target){
|
||||
edges.push({
|
||||
source: source,
|
||||
target: target,
|
||||
_data: value
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
//console.log(edges);
|
||||
|
||||
|
||||
// build the actual graph
|
||||
s = new sigma({
|
||||
graph: {
|
||||
nodes: [],
|
||||
edges: []
|
||||
},
|
||||
renderer: {
|
||||
container: document.getElementById('graph-container'),
|
||||
type: 'canvas'
|
||||
},
|
||||
settings: {
|
||||
edgeLabelSize: 'proportional',
|
||||
minArrowSize: 7,
|
||||
minNodeSize: 10,
|
||||
sideMargin: 0.45
|
||||
}
|
||||
});
|
||||
|
||||
// generate the nodes on the graph
|
||||
nodes.forEach(function(node, i, a){
|
||||
node.x = Math.cos(Math.PI * 2 * i / a.length);
|
||||
node.y = Math.sin(Math.PI * 2 * i / a.length);
|
||||
node.size = 10;
|
||||
node.color = "#4CC40B";
|
||||
if (!node._data.OK) {
|
||||
node.color = "red";
|
||||
}
|
||||
//console.log(node);
|
||||
s.graph.addNode(node);
|
||||
});
|
||||
|
||||
// generate the edges
|
||||
edges.forEach(function(edge, i){
|
||||
var color = "#ccc";
|
||||
var type = "curvedArrow";
|
||||
if (edge.source == edge.target){
|
||||
color = "gray";
|
||||
type = "curve";
|
||||
}
|
||||
if (!edge._data.OK) {
|
||||
color = "red";
|
||||
}
|
||||
var edge = {
|
||||
id: "e" + i,
|
||||
source: edge.source,
|
||||
target: edge.target,
|
||||
type: type,
|
||||
color: color,
|
||||
label: edge._data.elapsed,
|
||||
size: 7
|
||||
}
|
||||
//console.log(edge);
|
||||
s.graph.addEdge(edge)
|
||||
});
|
||||
|
||||
console.log(s.graph.nodes());
|
||||
console.log(s.graph.edges());
|
||||
|
||||
s.refresh();
|
||||
|
||||
var hideNotTouching = function(dst){
|
||||
s.graph.edges().forEach(function(edge){
|
||||
if (dst == undefined) {
|
||||
// revert everything to the original state
|
||||
if (edge._color){
|
||||
edge.color = edge._color;
|
||||
delete edge._color;
|
||||
}
|
||||
} else if (edge.source != dst){
|
||||
// hide
|
||||
if (!edge._color){
|
||||
edge._color = edge.color;
|
||||
}
|
||||
edge.color = "#faf8f6";
|
||||
} else {
|
||||
// show
|
||||
if (edge._color) {
|
||||
edge.color = edge._color;
|
||||
}
|
||||
}
|
||||
});
|
||||
s.refresh();
|
||||
}
|
||||
|
||||
s.bind("clickNode", function (e) {
|
||||
var node = e.data.node;
|
||||
hideNotTouching(node.id);
|
||||
|
||||
// fill the voids
|
||||
$('#modal-title').html(node.id);
|
||||
$('#modal-body').html(prepareJSON(node._data));
|
||||
|
||||
// show the things
|
||||
$('#modal-window-code').modal('show');
|
||||
});
|
||||
s.bind("clickStage", function (e) {
|
||||
hideNotTouching();
|
||||
});
|
||||
|
||||
s.bind("clickEdge", function (e) {
|
||||
var edge = e.data.edge;
|
||||
|
||||
console.log(edge);
|
||||
|
||||
// fill the voids
|
||||
$('#modal-title').html(edge.id);
|
||||
$('#modal-body').html(prepareJSON(edge._data));
|
||||
|
||||
// show the things
|
||||
$('#modal-window-code').modal('show');
|
||||
});
|
||||
})
|
||||
.catch(function(err){
|
||||
console.error(err);
|
||||
$('#modal-title').html("Error");
|
||||
$('#modal-body').html(prepareJSON(err));
|
||||
$('#modal-window-code').modal('show');
|
||||
});
|
||||
};
|
||||
|
||||
main();
|
||||
|
||||
$("#show-data").click(function (e) {
|
||||
// fill the voids
|
||||
$('#modal-title').html("/check_all");
|
||||
$('#modal-body').html(prepareJSON(global_data));
|
||||
|
||||
// show the things
|
||||
$('#modal-window-code').modal('show');
|
||||
});
|
||||
$("#reload-graph").click(function (e) {
|
||||
s.kill();
|
||||
main();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
122
swagger.yml
Normal file
122
swagger.yml
Normal file
@@ -0,0 +1,122 @@
|
||||
---
|
||||
swagger: '2.0'
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: Goldpinger
|
||||
definitions:
|
||||
CallStats:
|
||||
properties:
|
||||
check:
|
||||
type: integer
|
||||
check_all:
|
||||
type: integer
|
||||
ping:
|
||||
type: integer
|
||||
PingResults:
|
||||
type: object
|
||||
properties:
|
||||
boot_time:
|
||||
format: date-time
|
||||
type: string
|
||||
received:
|
||||
$ref: '#/definitions/CallStats'
|
||||
PodResult:
|
||||
type: object
|
||||
properties:
|
||||
OK:
|
||||
type: boolean
|
||||
default: false
|
||||
HostIP:
|
||||
type: string
|
||||
format: ipv4
|
||||
response:
|
||||
$ref: '#/definitions/PingResults'
|
||||
error:
|
||||
type: string
|
||||
status-code:
|
||||
type: integer
|
||||
format: int32
|
||||
CheckResults:
|
||||
type: object
|
||||
additionalProperties:
|
||||
$ref: '#/definitions/PodResult'
|
||||
CheckAllPodResult:
|
||||
type: object
|
||||
properties:
|
||||
OK:
|
||||
type: boolean
|
||||
default: false
|
||||
HostIP:
|
||||
type: string
|
||||
format: ipv4
|
||||
response:
|
||||
$ref: '#/definitions/CheckResults'
|
||||
error:
|
||||
type: string
|
||||
status-code:
|
||||
type: integer
|
||||
format: int32
|
||||
CheckAllResults:
|
||||
type: object
|
||||
properties:
|
||||
OK:
|
||||
type: boolean
|
||||
default: false
|
||||
hosts-healthy:
|
||||
type: integer
|
||||
format: int32
|
||||
hosts-number:
|
||||
type: integer
|
||||
format: int32
|
||||
hosts:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
hostIP:
|
||||
type: string
|
||||
format: ipv4
|
||||
podIP:
|
||||
type: string
|
||||
format: ipv4
|
||||
responses:
|
||||
type: object
|
||||
additionalProperties:
|
||||
$ref: '#/definitions/CheckAllPodResult'
|
||||
paths:
|
||||
/ping:
|
||||
get:
|
||||
description: return query stats
|
||||
produces:
|
||||
- application/json
|
||||
operationId: ping
|
||||
responses:
|
||||
200:
|
||||
description: return success
|
||||
schema:
|
||||
$ref: '#/definitions/PingResults'
|
||||
/check:
|
||||
get:
|
||||
description: Queries the API server for all other pods in this service,
|
||||
and pings them via their pods IPs. Calls their /ping endpoint
|
||||
produces:
|
||||
- application/json
|
||||
operationId: checkServicePods
|
||||
responses:
|
||||
200:
|
||||
description: Success, return response
|
||||
schema:
|
||||
$ref: '#/definitions/CheckResults'
|
||||
/check_all:
|
||||
get:
|
||||
description: 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.
|
||||
produces:
|
||||
- application/json
|
||||
operationId: checkAllPods
|
||||
responses:
|
||||
200:
|
||||
description: Success, return response
|
||||
schema:
|
||||
$ref: '#/definitions/CheckAllResults'
|
||||
Reference in New Issue
Block a user