Compare commits

..

85 commits
0.7.1 ... main

Author SHA1 Message Date
Hector
74265fda0e merge: update-example-systemd-file
* Merge branch 'update-example-systemd-file' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!115
* Merged by: Hector <hector@hjs.dev>
2023-10-27 06:23:20 +00:00
Hector
deabab8363 chore: update example systemd file (!115)
- Update the example systemd file to be more complete
- Added description, documentation link, and some improved service settings

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/115
2023-10-27 06:23:20 +00:00
Hector
581220c654 merge: add-manual-docker-multistep-build
* Merge branch 'add-manual-docker-multistep-build' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!114
* Merged by: Hector <hector@hjs.dev>
2023-10-27 06:01:44 +00:00
Hector
f4d6598308 build: add manual docker multistep build (!114)
- Include two Dockerfiles in the repo: one for Goreleaser and one for manual builds
- Update the Goreleaser config to use it's own Dockerfile
- The Dockerfile for manual builds uses a two step process to build the exporter - this way the base system does not need Go installed

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/114
2023-10-27 06:01:41 +00:00
Hector
31b29021c5 merge: update-dependencies
* Merge branch 'update-dependencies' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!113
* Merged by: Hector <hector@hjs.dev>
2023-10-27 05:34:22 +00:00
Hector
900e05fea8 chore: update dependencies (!113)
- Update project dependencies

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/113
2023-10-27 05:34:21 +00:00
Hector
2b91e58d14
merge: add-healthcheck-file-to-gorelaser-config
* Merge branch 'add-healthcheck-file-to-gorelaser-config' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!112
* Merged by: Hector <hector@hjs.dev>
2023-09-09 09:09:44 +00:00
Hector
b1fa45f76b
chore: add healthcheck file to gorelaser config (!112)
* Add missing goreleaser config to include the healthcheck script in the docker image

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/112
2023-09-09 09:09:44 +00:00
Hector
a2139d9774
merge: add-troubleshooting-section-to-readme
* Merge branch 'add-troubleshooting-section-to-readme' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!111
* Merged by: Hector <hector@hjs.dev>
2023-09-09 06:39:58 +00:00
Hector
283ce50c59
docs: add troubleshooting section to readme (!111)
* Update README with a troubleshooting section
* Describe how to solve the "no such file or directory" error

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/111
2023-09-09 06:39:58 +00:00
Hector
1333fde5ca
merge: add-health-endpoint-to-exporter
* Merge branch 'add-health-endpoint-to-exporter' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!110
* Merged by: Hector <hector@hjs.dev>
2023-09-09 06:15:23 +00:00
Hector
8c67b44052
feat: add health endpoint to exporter (!110)
* Add new `/health` endpoint to check if exporter is running correctly
* Update docker healthcheck to use the new endpoint

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/110
2023-09-09 06:15:23 +00:00
Hector
f92318e864
merge: add-healthcheck-to-docker-image
* Merge branch 'add-healthcheck-to-docker-image' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!109
* Merged by: Hector <hector@hjs.dev>
2023-09-07 21:16:20 +00:00
Hector
9738a20a82
build: add healthcheck to docker image (!109)
* Update docker image to include a healthcheck instruction using a custom script
* Replace docker base image with alpine

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/109
2023-09-07 21:16:20 +00:00
Hector
a4c48ba46f
merge: publish-arm64-based-docker-images
* Merge branch 'publish-arm64-based-docker-images' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!108
* Merged by: Hector <hector@hjs.dev>
2023-09-07 20:29:30 +00:00
Hector
970bbb51d4
ci: publish arm64 based docker images (!108)
* Update `goreleaser` config to publish `arm64` based docker images
* Remove manual image tagging script and replace with `goreleaser` config

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/108
2023-09-07 20:29:30 +00:00
Hector
e80e361068
merge: update-dependencies
* Merge branch 'update-dependencies' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!107
* Merged by: Hector <hector@hjs.dev>
2023-09-07 18:33:25 +00:00
Hector
4a344cf8d0
chore: update dependencies (!107)
* Update project dependencies

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/107
2023-09-07 18:33:24 +00:00
Hector
b1504423f4 merge: update-dependencies
* Merge branch 'update-dependencies' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!106
* Merged by: Hector <hector@hjs.dev>
2023-08-01 13:30:21 +00:00
Hector
ba36fdb24e chore: update dependencies (!106)
* Update dependencies to the latest versions

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/106
2023-08-01 13:30:20 +00:00
Hector
235d34114b merge: chore/exclude-new-merge-messages-from-changelog
* Merge branch 'chore/exclude-new-merge-messages-from-changelog' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!104
* Merged by: Hector <hector@hjs.dev>
2023-07-03 07:18:37 +00:00
Hector
29d03c5a88 chore: exclude new merge messages from changelog (!104)
* Update the goreleaser config to exclude the new merge commit messages

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/104
2023-07-03 07:18:37 +00:00
Hector
a388773836 merge: chore/dependency-updates
* Merge branch 'chore/dependency-updates' into 'main'
* See merge request hectorjsmith/fail2ban-prometheus-exporter!103
* Merged by: Hector <hector@hjs.dev>
2023-07-03 07:03:14 +00:00
Hector
fdd223c96b chore: dependency updates (!103)
* Update dependencies to their latest versions

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/103
2023-07-03 07:03:14 +00:00
Hector
fe039c0787 Merge branch 'docs/add-go-report-card-to-readme' into 'main'
docs: add go report card to readme

See merge request hectorjsmith/fail2ban-prometheus-exporter!102
2023-06-23 20:42:46 +00:00
Hector
426011fe14 docs: add go report card to readme (!102)
* Add a badge with the project's go report card to the project `README` file

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/102
2023-06-23 20:42:46 +00:00
Hector
f877fcb79d Merge branch 'ci/fix-release-step-script' into 'main'
ci: fix release step script

See merge request hectorjsmith/fail2ban-prometheus-exporter!101
2023-06-22 21:52:31 +00:00
Hector
8c67048868 ci: fix release step script (!101)
* Fix the yaml config for the release step to handle a multi-line command

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/101
2023-06-22 21:52:31 +00:00
Hector
0a132c83df Merge branch 'docs/add-dry-run-command-to-readme' into 'main'
docs: add dry run flag to readme

See merge request hectorjsmith/fail2ban-prometheus-exporter!100
2023-06-22 18:37:01 +00:00
Hector
e46da3e7dd docs: add dry run flag to readme (!100)
* Update `README` to include the new `--dry-run` flag

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/100
2023-06-22 18:37:01 +00:00
Hector
18000cf9ef Merge branch 'ci/add-go-vet-to-test-stage' into 'main'
ci: add go vet to test stage

See merge request hectorjsmith/fail2ban-prometheus-exporter!99
2023-06-22 18:24:15 +00:00
Hector
b6cec83503 ci: add go vet to test stage (!99)
* Add `go vet` to the test stage of the Gitlab CI/CD pipeline
* Fix issues raised by `go vet`

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/99
2023-06-22 18:24:15 +00:00
Hector
8d457da2b9 Merge branch 'feat/add-new-dry-run-mode' into 'main'
feat: add new dry run mode

See merge request hectorjsmith/fail2ban-prometheus-exporter!98
2023-06-22 16:09:36 +00:00
Hector
9c1a10e309 feat: add new dry run mode (!98)
* Add a new *dry-run* mode to exit just before running the server
* This allows testing that the socket is working before starting the server

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/98
2023-06-22 16:09:36 +00:00
Hector
5275d280be Merge branch 'build/disable-cgo-for-makefile-build' into 'main'
build: disable cgo for makefile build

See merge request hectorjsmith/fail2ban-prometheus-exporter!97
2023-06-22 15:22:42 +00:00
Hector
b9ab77d62d build: disable cgo for makefile build (!97)
* Disable `CGO` in the makefile build to avoid dependencies on external C libraries
* This also aligns with the build done for releases and docker images

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/97
2023-06-22 15:22:42 +00:00
Hector
5f879e1921 Merge branch 'feat/print-fail2ban-version-on-startup' into 'main'
feat: print fail2ban version on startup

See merge request hectorjsmith/fail2ban-prometheus-exporter!96
2023-06-22 15:16:12 +00:00
Hector
8e0284d9f0 feat: print fail2ban version on startup (!96)
* Print the version reported by `fail2ban-server` when the exporter starts up
* Logs an error if the connection to the server fails

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/96
2023-06-22 15:16:12 +00:00
Hector
d1b65a2134 Merge branch 'chore/replace-ioutils-with-os-calls' into 'main'
chore: replace ioutil with os calls

See merge request hectorjsmith/fail2ban-prometheus-exporter!95
2023-06-22 14:33:57 +00:00
Hector
dc342e3051 chore: replace ioutil with os calls (!95)
* Replace calls to deprecated `ioutil` functions with the `os` package

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/95
2023-06-22 14:33:56 +00:00
Hector
1508693dd6 Merge branch 'chore/rename-examples-folder' into 'main'
chore: rename examples folder

See merge request hectorjsmith/fail2ban-prometheus-exporter!94
2023-06-22 14:22:31 +00:00
Hector
594d9f26a1 chore: rename examples folder (!94)
* Rename the `examples` folder to `_examples` to distinguish it from source code folders

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/94
2023-06-22 14:22:31 +00:00
Hector
938860d5dc Merge branch 'set-dependency-scanning-config-1' into 'main'
ci: configure dependency scanning

See merge request hectorjsmith/fail2ban-prometheus-exporter!93
2023-06-21 17:50:43 +00:00
Hector
cfa20f6c1d ci: configure dependency scanning (!93)
* Enable dependency scanning CI pipeline

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/93
2023-06-21 17:50:43 +00:00
Hector
211a5015d0 Merge branch 'chore/update-makefile-commands' into 'main'
chore: update makefile commands

See merge request hectorjsmith/fail2ban-prometheus-exporter!92
2023-06-21 15:02:11 +00:00
Hector
56ecc03341 chore: update makefile commands (!92)
* Tweak makefile commands and file formatting
* Remove command and build step for go mod formatting
* Add command to update project dependencies
* Add make command to list all make commands

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/92
2023-06-21 15:02:11 +00:00
Hector
b32bbeb1cd Merge branch 'fix/set-http-server-timeouts' into 'main'
fix: set http server timeouts

See merge request hectorjsmith/fail2ban-prometheus-exporter!91
2023-06-21 11:09:39 +00:00
Hector
37b67643e8 fix: set http server timeouts (!91)
* Set timeout values when configuring the HTTP server to mitigate "Slowloris" vulnerability

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/91
2023-06-21 11:09:39 +00:00
Hector
1eec68b49b Merge branch 'refactor/move-server-setup-code-to-new-package' into 'main'
refactor: move server setup code to new package

See merge request hectorjsmith/fail2ban-prometheus-exporter!90
2023-06-21 10:58:43 +00:00
Hector
11c4b26c0b refactor: move server setup code to new package (!90)
* Move code setting up the HTTP server to it's own package
* This helps clean up the `main` function and make it easier to read
* Rename the `BasicAuthMiddleware` to remove reference to Basic since it can now handle any type of auth type

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/90
2023-06-21 10:58:43 +00:00
Hector
41b05f7e16 Merge branch 'refactor/rewrite-auth-handler-code' into 'main'
refactor: rewrite auth handler code

See merge request hectorjsmith/fail2ban-prometheus-exporter!89
2023-06-21 10:31:33 +00:00
Hector
3cff8ccd64 refactor: rewrite auth handler code (!89)
* Rewrite the code handling basic auth to make it easier to extend for other types of auth.
* The behaviour of the existing code is maintained.
* No changes to how basic auth is configured from a user's perspective.

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/89
2023-06-21 10:31:33 +00:00
Hector
3215fe5f4c Merge branch 'refactor/replace-cli-parser-with-kong' into 'main'
refactor: replace cli parser with kong

See merge request hectorjsmith/fail2ban-prometheus-exporter!88
2023-06-20 20:16:23 +00:00
Hector
43cab7adc2 refactor: replace cli parser with kong (!88)
https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/88
2023-06-20 20:16:23 +00:00
Hector
d584345fc6 Merge branch 'ci/add-sast-step-to-pipeline' into 'main'
ci: add sast step to pipeline

See merge request hectorjsmith/fail2ban-prometheus-exporter!87
2023-06-20 17:24:16 +00:00
Hector
8974395bba ci: add sast step to pipeline (!87)
https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/87
2023-06-20 17:24:16 +00:00
Hector
ad593dbd9b Merge branch 'docs/update-readme-with-latest-changes' into 'main'
docs: update readme with latest changes

See merge request hectorjsmith/fail2ban-prometheus-exporter!86
2023-06-20 16:34:25 +00:00
Hector
f1e69fc4da docs: update readme with latest changes (!86)
Update `README` to reflect recent changes in the project build process.

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/86
2023-06-20 16:34:25 +00:00
Hector
30b92d61da Merge branch 'feat/tag-docker-images-with-extra-labels' into 'main'
feat: tag docker images with extra labels

See merge request hectorjsmith/fail2ban-prometheus-exporter!85
2023-06-20 07:20:11 +00:00
Hector
812f506432 feat: tag docker images with extra labels (!85)
Add a new build step to tag docker images with extra labels:
- `:latest`
- `:<major>`
- `:<major>.<minor>`

This job is only triggered on main release tags.

https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/merge_requests/85
2023-06-20 07:20:11 +00:00
Hector
f29e127f5f Merge branch 'chore/update-go-and-dependencies' into 'main'
chore: update go and dependencies

See merge request hectorjsmith/fail2ban-prometheus-exporter!84
2023-06-19 21:59:42 +00:00
Hector
d7f9b5c4ab chore: update go and dependencies
Update Go version to 1.20
Update dependencies to latest versions
2023-06-19 21:59:42 +00:00
Hector
56cc0b7901 Merge branch 'fix/disable-cgo-in-build' into 'main'
fix: disable cgo in goreleaser build

See merge request hectorjsmith/fail2ban-prometheus-exporter!83
2023-06-19 21:27:09 +00:00
Hector
53a1f12f39 fix: disable cgo in goreleaser build 2023-06-19 21:27:09 +00:00
Hector
c19b986795 Merge branch 'chore/add-build-output-to-gitignore' into 'main'
chore: add build output to gitignore

See merge request hectorjsmith/fail2ban-prometheus-exporter!82
2023-06-19 20:52:48 +00:00
Hector
d7cf78bd59 chore: add build output to gitignore 2023-06-19 20:52:47 +00:00
Hector
17e5a3835b Merge branch 'feat/automate-releases-using-goreleaser' into 'main'
feat: automate releases using goreleaser

See merge request hectorjsmith/fail2ban-prometheus-exporter!81
2023-06-19 20:37:30 +00:00
Hector
e599570220 feat: automate releases using goreleaser 2023-06-19 20:37:30 +00:00
Hector
baa157fc06 Merge branch 'chore/rewrite-dockerfile' into 'main'
chore: rewrite dockerfile

See merge request hectorjsmith/fail2ban-prometheus-exporter!80
2023-06-19 19:06:18 +00:00
Hector
772cdb52c5 chore: rewrite dockerfile
Rewrite the Dockerfile to be ready for fully automating releases using GoReleaser.
2023-06-19 19:06:18 +00:00
Hector
1d4ec79bac Merge branch 'docs/remove-changelog-file' into 'main'
docs: remove changelog file

See merge request hectorjsmith/fail2ban-prometheus-exporter!79
2023-06-19 18:44:58 +00:00
Hector
c966da3a5f docs: remove changelog file
Removing the changelog file from the repo because we are moving to auto generating a changelog for each release.
This file has also always been out of date between releases, making it pointless to have in the repo itself.
2023-06-19 18:44:57 +00:00
Hector
0d5b771205 Merge branch 'chore/rewrite-make-commands' into 'main'
chore: rewrite make commands

See merge request hectorjsmith/fail2ban-prometheus-exporter!78
2023-06-19 18:37:27 +00:00
Hector
8ff64467db chore: rewrite make commands 2023-06-19 18:37:27 +00:00
Hector
95f9c821ff Merge branch 'chore/move-source-code-to-root-folder' into 'main'
chore: move source code to root folder

See merge request hectorjsmith/fail2ban-prometheus-exporter!77
2023-06-19 17:58:16 +00:00
Hector
ae1285dc66 chore: move source code to root folder 2023-06-19 17:58:16 +00:00
Hector
c3b6fb3b07 Merge branch 'chore/remove-hardcoded-tools' into 'main'
chore: remove hardcoded tools

See merge request hectorjsmith/fail2ban-prometheus-exporter!76
2023-06-19 17:50:28 +00:00
Hector
83be83d83d chore: remove hardcoded tools 2023-06-19 17:50:28 +00:00
Hector
da991a22ee Merge branch 'release/0.7.2' into 'main'
Release/0.7.2

See merge request hectorjsmith/fail2ban-prometheus-exporter!75
2023-03-16 20:52:34 +00:00
Hector
be58ab36ff docs: update changelog for release 2023-03-16 20:35:56 +00:00
Hector
9d1bdadab1 Merge branch 'chore/update-dependencies' into 'main'
chore: update dependencies

See merge request hectorjsmith/fail2ban-prometheus-exporter!74
2023-03-16 18:05:22 +00:00
Hector
3a77a0ad3a chore: update dependencies
Update all project dependencies to their latest versions.
2023-03-16 18:05:22 +00:00
Hector
e005abfc1c Merge branch 'docs/update-example-grafana-dashboard' into 'main'
docs: update grafana dashboard

See merge request hectorjsmith/fail2ban-prometheus-exporter!73
2022-10-13 08:36:43 +00:00
Hector
f6663d1ffd docs: update grafana dashboard
Update the example grafana dashboard to add support for multiple
exporter instances. This includes updating panel queries and display
names.
The grafana version has been bumped to 9.1.8.
2022-10-13 08:36:43 +00:00
Hector
482773713a Merge branch 'release/0.7.1' into 'main'
Release/0.7.1

See merge request hectorjsmith/fail2ban-prometheus-exporter!72
2022-09-18 20:38:46 +00:00
49 changed files with 962 additions and 1200 deletions

2
.gitignore vendored
View file

@ -4,3 +4,5 @@ vendor/
build/
dist/
fail2ban_exporter

View file

@ -1,69 +1,64 @@
stages:
- test
- build
- release
.go_template:
image: golang:latest
before_script:
- make go/dependencies
.docker_template:
image: docker:stable
services:
- docker:dind
before_script:
- apk add git
- apk add make
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
dependencies:
extends: .go_template
sast:
stage: test
script:
- make go/checkDependencies
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
format:
extends: .go_template
stage: test
script:
- make go/checkFmt
- make check/fmt
vet:
extends: .go_template
stage: test
allow_failure: true
script:
- make vet
test:
extends: .go_template
stage: test
script:
- make go/test
- make test
build:
extends: .go_template
stage: build
only:
- main
- tags
script:
- git fetch --tags
- make build/snapshot
- make build
artifacts:
paths:
- dist/*.tar.gz
- dist/checksums.txt
- fail2ban_exporter
expire_in: 1 day
docker/gitlab:
extends: .docker_template
stage: build
only:
- tags
script:
- make docker/build/latest
- make docker/build/tag
- docker push registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
docker/gitlab/nightly:
extends: .docker_template
stage: build
only:
- main
script:
- make docker/build/nightly
- docker push registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
release:
stage: release
image: docker:stable
services:
- docker:dind
variables:
DOCKER_REGISTRY: $CI_REGISTRY
DOCKER_USERNAME: $CI_REGISTRY_USER
DOCKER_PASSWORD: $CI_REGISTRY_PASSWORD
GIT_DEPTH: 0
rules:
- if: $CI_COMMIT_TAG =~ /^v.*$/
script: |
docker run --rm --privileged \
-v $PWD:/go/src/gitlab.com/hectorjsmith/fail2ban-prometheus-exporter \
-w /go/src/gitlab.com/hectorjsmith/fail2ban-prometheus-exporter \
-v /var/run/docker.sock:/var/run/docker.sock \
-e DOCKER_USERNAME -e DOCKER_PASSWORD -e DOCKER_REGISTRY \
-e GITLAB_TOKEN \
goreleaser/goreleaser release --clean

View file

@ -1,13 +1,7 @@
# This is an example goreleaser.yaml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com
project_name: fail2ban_exporter
before:
hooks:
- make go/dependencies
builds:
-
- env: [CGO_ENABLED=0]
binary: fail2ban_exporter
dir: src
goos:
- linux
- darwin
@ -20,14 +14,84 @@ builds:
- "6"
- "7"
archives:
-
wrap_in_directory: true
files:
- LICENSE
- README.md
- CHANGELOG.md
checksum:
name_template: 'checksums.txt'
dockers:
- image_templates:
- "registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}-amd64"
- "registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}.{{ .Minor }}-amd64"
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Version }}-amd64'
- "registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest-amd64"
extra_files:
- health
use: buildx
dockerfile: Dockerfile.goreleaser
build_flag_templates:
- "--pull"
- "--platform=linux/amd64"
- --label=org.opencontainers.image.title={{ .ProjectName }}
- --label=org.opencontainers.image.description={{ .ProjectName }}
- --label=org.opencontainers.image.url=https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
- --label=org.opencontainers.image.source=https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
- --label=org.opencontainers.image.version={{ .Version }}
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- --label=org.opencontainers.image.licenses=MIT
- image_templates:
- "registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}-arm64"
- "registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}.{{ .Minor }}-arm64"
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Version }}-arm64'
- "registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest-arm64"
extra_files:
- health
use: buildx
dockerfile: Dockerfile.goreleaser
build_flag_templates:
- "--pull"
- "--platform=linux/arm64"
- --label=org.opencontainers.image.title={{ .ProjectName }}
- --label=org.opencontainers.image.description={{ .ProjectName }}
- --label=org.opencontainers.image.url=https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
- --label=org.opencontainers.image.source=https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
- --label=org.opencontainers.image.version={{ .Version }}
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- --label=org.opencontainers.image.licenses=MIT
goarch: arm64
docker_manifests:
- name_template: 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}'
image_templates:
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}-amd64'
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}-arm64'
- name_template: 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}.{{ .Minor }}'
image_templates:
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}.{{ .Minor }}-amd64'
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Major }}.{{ .Minor }}-arm64'
- name_template: 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Version }}'
image_templates:
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Version }}-amd64'
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:{{ .Version }}-arm64'
- name_template: 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest'
image_templates:
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest-amd64'
- 'registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest-arm64'
changelog:
skip: true
groups:
- title: "⛔ Breaking Changes"
regexp: '^.*?!:.+$'
order: 0
- title: "🎉 Features"
regexp: '^.*?feat(\(\w+\))??:.+$'
order: 1
- title: "🐛 Fixes"
regexp: '^.*?fix(\(\w+\))??:.+$'
order: 2
- title: "📑 Other"
order: 999
filters:
exclude:
- "^Merge"
- "^merge"

View file

@ -1,126 +0,0 @@
# CHANGELOG
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog], and this project adheres to [Semantic Versioning].
## [Unreleased]
*Nothing yet*
## [0.7.1] - 2022-09-18
### Fixed
- (04b84cc) fix: report failure when server fails to start ([#23](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/23))
## [0.7.0] - 2022-06-19
### Added
- (fd58b20) feat: option to exit on socket conn error ([#21](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/21))
## [0.6.0] - 2022-02-20
*Rewrite CLI flags and environment variables*
### Added
- (23e073f) feat: add example systemd service file
- (3911eca) feat: rename output binary and archives
- (f6e328a) feat: correctly handle shutdown signals
- (6e575aa) feat: rewrite cli flags and environment variables
- (0f0efe5) feat: remove startup script from docker image
- (e2902b8) feat: improve logging on startup
- (1f27dac) feat: add default value for fail2ban socket path
- (b7e317e) feat: configure tool using environment variables ([#17](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/17))
- (6f76a03) feat: add support for basic auth ([#16](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/16))
### Fixed
- (93da909) fix: use correct flag in dockerfile ([#18](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/18))
### BREAKING CHANGE
- Release binary name has been changed to `fail2ban_exporter`.
- Replace `--socket` flag with `--collector.f2b.socket`.
- Merge `--port` flag and `--web.listen-address` into a single flag.
- Remove `--collector.textfile` flag, its value is now derived from `--collector.textfile.directory`.
- Remove `F2B_COLLECTOR_TEXT` and `F2B_WEB_PORT` environment variables.
- Using the textfile collector in docker now requires setting environment variables.
- CLI params now require two dashes instead of one (e.g. `--socket`).
## [0.5.0] - 2021-12-21
*Remove deprecated code & support python2*
### Added
- (b397a51) feat: sample grafana dashboard ([#15](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/15))
- (c208c8e) feat: add listen address parameter - thanks [@private-creator](https://gitlab.com/private-creator)!
### Fixed
- (7932ccb) fix: support python2 fail2ban ([#14](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/14)) - thanks [@private-creator](https://gitlab.com/private-creator)!
### BREAKING CHANGE
- Remove `-db` CLI flag
- Remove `f2b_errors{type="db"}` metric
## [0.4.0] - 2021-10-18
*Add new fail2ban config metrics*
### Added
- (56730c8) feat: add new jail config metrics
- (5a107cc) feat: support for textfile metrics ([#13](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/13))
### Removed
- (b268f86) remove: database-based metrics
- (0b6a941) remove: windows builds
## [0.3.0] - 2021-09-27
*Export new version metrics ([#12](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/12))*
### Added
- (3c9a005) feat: render basic html page at root url
- (22a165d) feat: improve startup logging
- (fba9ee2) feat: export new version metric ([#12](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/12))
## [0.2.0] - 2021-08-31
*Collect metrics through fail2ban socket - based on [#11](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/11)*
### Added
- (39133d0) feat: collect new up metric from fail2ban socket
- (4da46f3) feat: export metrics with socket errors
- (bd841c3) feat: set up metric to 0 if errors found
- (1964dde) feat: export metrics for failed/banned counts
- (2ab1f7d) feat: support reading fail2ban socket in docker
- (1282d63) feat: new metric for enabled jails ([#1](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/1))
### Fixed
- (526b1c7) fix: update banned metrics to exclude expired bans ([#11](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/11))
### Deprecated
- Use of the fail2ban database has been deprecated. The exporter now collects metrics through the fail2ban socket file. See [#11](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/issues/11) for more details.
## [0.1.0] - 2021-03-28
*Initial release*
### Added
- (6355c9e) feat: fail on startup if database file does not exist ([#8](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/8))
- (4f18bf3) feat: add cli parameters for db path and metrics port ([#4](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/issues/4))
- (91cba80) feat: export number of banned ips
- (4b96501) feat: export bad ip count per jail
- (0b40e5d) feat: connect to fail2ban db and extract total bad ips
- (7ced846) feat: initial setup of metric exporter
### Fixed
- (0842419) fix: compile tool without cgo_enabled flag
## 0.0.0 - 2021-02-05
*Repository creation*
---
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
[Unreleased]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.7.1...main
[0.1.0]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.0.0...0.1.0
[0.2.0]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.1.0...0.2.0
[0.3.0]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.2.0...0.3.0
[0.4.0]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.3.0...0.4.0
[0.5.0]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.4.0...0.5.0
[0.6.0]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.5.0...0.6.0
[0.7.0]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.6.0...0.7.0
[0.7.1]: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/compare/0.7.0...0.7.1

View file

@ -1,23 +1,30 @@
# Using golang:latest instead of alpine because of issues with sqlite3
FROM golang:latest AS build
FROM golang:1.20-buster AS build
# Create build folder to compile tool
WORKDIR /build
# Create build workspace folder
WORKDIR /workspace
ADD . /workspace
# Copy source files to build folder and link to the /go folder
COPY . /build
RUN ln -s /go/src/ /build/src
# Install updates and build tools
RUN apt update --yes && \
apt install --yes build-essential
# Compile the tool using a Make command
RUN make build/docker
# Build the actual binary
RUN make build
# -- -- -- -- -- --
FROM debian:buster-slim
# Set up image to run the tool
FROM alpine
# Create main app folder to run from
WORKDIR /app
# Copy compiled binary to release image
COPY --from=build /build/src/fail2ban_exporter /app/fail2ban_exporter
# Copy built binary from build image
COPY --from=build /workspace/fail2ban_exporter /app
# Setup a healthcheck
COPY health /app/health
RUN apk add curl
HEALTHCHECK --interval=10s --timeout=4s --retries=3 CMD /app/health
ENTRYPOINT ["/app/fail2ban_exporter"]

15
Dockerfile.goreleaser Normal file
View file

@ -0,0 +1,15 @@
FROM alpine
# Create main app folder to run from
WORKDIR /app
# Copy compiled binary to release image
# (must build the binary before running docker build)
COPY fail2ban_exporter /app/fail2ban_exporter
# Setup a healthcheck
COPY health /app/health
RUN apk add curl
HEALTHCHECK --interval=10s --timeout=4s --retries=3 CMD /app/health
ENTRYPOINT ["/app/fail2ban_exporter"]

View file

@ -1,39 +1,55 @@
go/dependencies:
cd src/ && go mod download
# List make commands
.PHONY: ls
ls:
cat Makefile | grep "^[a-zA-Z#].*" | cut -d ":" -f 1 | sed s';#;\n#;'g
# Make sure no unnecessary dependencies are present
go/checkDependencies:
cd src/ && go mod tidy -v
git diff-index --quiet HEAD
# Download dependencies
.PHONY: download
download:
go mod download
# Standard go test
go/test:
cd src/ && go test ./... -v -race
# Update project dependencies
.PHONY: update
update:
go get -u
go mod download
go mod tidy
go/fmt:
cd src/ && go fmt ./...
# Run project tests
.PHONY: test
test: download
go test ./... -v -race
go/checkFmt:
# Look for "suspicious constructs" in source code
.PHONY: vet
vet: download
go vet ./...
# Format code
.PHONY: fmt
fmt: download
go mod tidy
go fmt ./...
# Check for unformatted go code
.PHONY: check/fmt
check/fmt: download
test -z $(shell gofmt -l .)
docs/genChangelog:
./tools/git-chglog_linux_amd64 --config tools/chglog/config.yml 0.0.0.. > CHANGELOG_gen.md
build/snapshot:
./tools/goreleaser_linux_amd64 --snapshot --rm-dist --skip-publish
build/release:
./tools/goreleaser_linux_amd64 --rm-dist --skip-publish
# Build project
.PHONY: build
build:
CGO_ENABLED=0 go build \
-ldflags "\
-X main.version=${shell git describe --tags} \
-X main.commit=${shell git rev-parse HEAD} \
-X main.date=${shell date --iso-8601=seconds} \
-X main.builtBy=manual \
" \
-o fail2ban_exporter \
exporter.go
# Build project docker container
.PHONY: build/docker
build/docker:
cd src/ && go build -o fail2ban_exporter \
-ldflags '-X main.version=$(shell git describe --tags) -X main.commit=${shell git rev-parse HEAD} -X "main.date=${shell date --rfc-3339=seconds}" -X main.builtBy=docker' exporter.go
docker/build/latest:
docker build -t registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest .
docker/build/nightly:
docker build -t registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:nightly .
docker/build/tag:
docker build -t registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:$(shell git describe --tags) .
docker build -t fail2ban-prometheus-exporter .

View file

@ -1,6 +1,7 @@
# Fail2Ban Prometheus Exporter
[![Pipeline](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/badges/main/pipeline.svg)](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter)
[![Go Report Card](https://goreportcard.com/badge/gitlab.com/hectorjsmith/fail2ban-prometheus-exporter)](https://goreportcard.com/report/gitlab.com/hectorjsmith/fail2ban-prometheus-exporter)
Collect metrics from a running fail2ban instance.
@ -10,6 +11,7 @@ Collect metrics from a running fail2ban instance.
3. Configuration
4. Building from source
5. Textfile metrics
6. Troubleshooting
## 1. Quick Start
@ -22,7 +24,7 @@ The following command will start collecting metrics from the `/var/run/fail2ban/
```
$ fail2ban_exporter --collector.f2b.socket=/var/run/fail2ban/fail2ban.sock --web.listen-address=":9191"
2022/02/20 09:54:06 fail2ban exporter version 0.5.0
2022/02/20 09:54:06 fail2ban exporter version 0.8.1
2022/02/20 09:54:06 starting server at :9191
2022/02/20 09:54:06 reading metrics from fail2ban socket: /var/run/fail2ban/fail2ban.sock
2022/02/20 09:54:06 metrics available at '/metrics'
@ -31,6 +33,9 @@ $ fail2ban_exporter --collector.f2b.socket=/var/run/fail2ban/fail2ban.sock --web
Binary files for each release can be found on the [releases](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/releases) page.
There is also an [example systemd service file](/_examples/systemd/fail2ban_exporter.service) included in the repository.
This is a starting point to run the exporter as a service.
### 1.2. Docker
**Docker run**
@ -55,7 +60,7 @@ services:
- "9191:9191"
```
Use the `:latest` tag to get the latest stable release. Or use the `:nightly` tag for the latest (unstable) version.
Use the `:latest` tag to get the latest stable release.
See the [registry page](https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/container_registry) for all available tags.
**NOTE:** While it is possible to mount the `fail2ban.sock` file directly, it is recommended to mount the parent folder instead.
@ -100,10 +105,12 @@ Status for the jail: sshd
### 2.1. Grafana
The metrics exported by this tool are compatible with Prometheus and Grafana.
A sample grafana dashboard can be found in the [grafana.json](/examples/grafana/dashboard.json) file.
A sample grafana dashboard can be found in the [grafana.json](/_examples/grafana/dashboard.json) file.
Just import the contents of this file into a new Grafana dashboard to get started.
*(Sample dashboard is compatible with Grafana `8.3.3` and above)*
The dashboard supports displaying data from multiple exporters. Use the `instance` dashboard variable to select which ones to display.
*(Sample dashboard is compatible with Grafana `9.1.8` and above)*
## 3. Configuration
@ -112,23 +119,31 @@ There are no configuration files.
**CLI flags**
```
usage: exporter [<flags>]
🚀 Collect prometheus metrics from a running Fail2Ban instance
Flags:
-h, --help Show context-sensitive help (also try --help-long and --help-man).
-v, --version show version info and exit
--collector.f2b.socket="/var/run/fail2ban/fail2ban.sock"
path to the fail2ban server socket
--collector.textfile.directory=""
directory to read text files with metrics from
--web.listen-address=":9191"
address to use for the metrics server
--web.basic-auth.username=""
username to use to protect endpoints with basic auth
--web.basic-auth.password=""
password to use to protect endpoints with basic auth
--collector.f2b.exit-on-socket-connection-error
when set to true the exporter will immediately exit on a fail2ban socket connection error
-h, --help Show context-sensitive help.
-v, --version Show version info and exit
--dry-run Attempt to connect to the fail2ban socket then exit
before starting the server
--web.listen-address=":9191" Address to use for the metrics server
($F2B_WEB_LISTEN_ADDRESS)
--collector.f2b.socket="/var/run/fail2ban/fail2ban.sock"
Path to the fail2ban server socket
($F2B_COLLECTOR_SOCKET)
--collector.f2b.exit-on-socket-connection-error
When set to true the exporter will immediately
exit on a fail2ban socket connection error
($F2B_EXIT_ON_SOCKET_CONN_ERROR)
--collector.textfile.directory=STRING
Directory to read text files with metrics from
($F2B_COLLECTOR_TEXT_PATH)
--web.basic-auth.username=STRING
Username to use to protect endpoints with basic auth
($F2B_WEB_BASICAUTH_USER)
--web.basic-auth.password=STRING
Password to use to protect endpoints with basic auth
($F2B_WEB_BASICAUTH_PASS)
```
**Environment variables**
@ -147,12 +162,13 @@ If both are specified, the CLI flag takes precedence.
## 4. Building from source
The simplest way to build the project is to run the `build/snapshot` make command.
This will use `goreleaser` to build out binaries and archives for the project.
Binaries are stored in the `dist/` folder.
Building from source has the following dependencies:
- Go v1.20
- Make
Alternatively, `go mod download` and `go build` can be used from the `src/` folder to build out the project.
This will download dependencies and build the project.
From there, simply run `make build`
This will download the necessary dependencies and build a `fail2ban_exporter` binary in the root of the project.
## 5. Textfile metrics
@ -189,3 +205,35 @@ docker run -d \
-p "9191:9191" \
registry.gitlab.com/hectorjsmith/fail2ban-prometheus-exporter:latest
```
## 6. Troubleshooting
### 6.1. "no such file or directory"
```
error opening socket: dial unix /var/run/fail2ban/fail2ban.sock: connect: no such file or directory
```
There are a couple of potential causes for the error above.
**File not found**
The first is that the file does not exist, so first check that the file path shown in the error actually exists on the system running the exporter.
The fail2ban server may be storing the socket file in another location on your machine.
If you are using docker, make sure the correct host folder was mounted to the correct location.
If the file is not in the expected location, you can run the exporter with the corresponding CLI flag or environment variable to use a different file path.
**Permissions**
If the file does exist, the likely cause are file permissions.
By default, the fail2ban server runs as the `root` user and the socket file can only be accessed by the same user.
If you are running the exporter as a non-root user, it will not be able to open the socket file to read/write commands to the server, leading to the error above.
In this case there are a few solutions:
1. Run the exporter as the same user as fail2ban (usually `root`)
2. Update the fail2ban server config to run as a non-root user, then run the exporter as the same user
3. Update the socket file permissions to be less restrictive
I would recommend option `1.` since it is the simplest. Option `2.` is a bit more complex, check the [fail2ban server documentation](https://coderwall.com/p/haj28a/running-rootless-fail2ban-on-debian) for more details. And option `3.` is just a temporary fix. The socket file gets re-created each time the fail2ban server is restarted and the original permissions will be restored, so you will need to update the permissions every time the server restarts.

View file

@ -9,13 +9,13 @@
"pluginName": "Prometheus"
}
],
"__elements": [],
"__elements": {},
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "8.3.3"
"version": "9.1.8"
},
{
"type": "datasource",
@ -40,7 +40,10 @@
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"datasource": {
"type": "datasource",
"uid": "grafana"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
@ -59,7 +62,6 @@
"fiscalYearStartMonth": 0,
"graphTooltip": 2,
"id": null,
"iteration": 1640159475017,
"links": [],
"liveNow": false,
"panels": [
@ -76,7 +78,8 @@
},
"custom": {
"align": "auto",
"displayMode": "auto"
"displayMode": "auto",
"inspect": false
},
"mappings": [],
"thresholds": {
@ -121,15 +124,16 @@
},
"showHeader": true
},
"pluginVersion": "8.3.3",
"pluginVersion": "9.1.8",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": false,
"expr": "f2b_config_jail_max_retries",
"expr": "f2b_config_jail_max_retries{instance=~\"$instance\"}",
"format": "table",
"instant": true,
"interval": "",
@ -141,8 +145,9 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": false,
"expr": "f2b_config_jail_ban_time",
"expr": "f2b_config_jail_ban_time{instance=~\"$instance\"}",
"format": "table",
"hide": false,
"instant": true,
@ -155,8 +160,9 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": false,
"expr": "f2b_config_jail_find_time",
"expr": "f2b_config_jail_find_time{instance=~\"$instance\"}",
"format": "table",
"hide": false,
"instant": true,
@ -193,6 +199,10 @@
],
"operation": "aggregate"
},
"instance": {
"aggregations": [],
"operation": "groupby"
},
"jail": {
"aggregations": [],
"operation": "groupby"
@ -229,6 +239,8 @@
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@ -284,10 +296,12 @@
"lastNotNull"
],
"displayMode": "table",
"placement": "right"
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "single"
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.2.1",
@ -297,11 +311,13 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": true,
"expr": "f2b_jail_failed_total",
"expr": "f2b_jail_failed_total{instance=~\"$instance\"}",
"hide": false,
"interval": "",
"legendFormat": "{{jail}}",
"legendFormat": "{{jail}} ({{instance}})",
"range": true,
"refId": "A"
}
],
@ -321,6 +337,8 @@
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@ -376,10 +394,12 @@
"lastNotNull"
],
"displayMode": "table",
"placement": "right"
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "single"
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.2.1",
@ -389,10 +409,12 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": true,
"expr": "f2b_jail_banned_total",
"expr": "f2b_jail_banned_total{instance=~\"$instance\"}",
"interval": "",
"legendFormat": "{{jail}}",
"legendFormat": "{{jail}} ({{instance}})",
"range": true,
"refId": "A"
}
],
@ -412,6 +434,8 @@
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@ -467,10 +491,12 @@
"lastNotNull"
],
"displayMode": "table",
"placement": "right"
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "single"
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.2.1",
@ -480,10 +506,12 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": true,
"expr": "f2b_jail_failed_current",
"expr": "f2b_jail_failed_current{instance=~\"$instance\"}",
"interval": "",
"legendFormat": "{{jail}}",
"legendFormat": "{{jail}} ({{instance}})",
"range": true,
"refId": "A"
}
],
@ -503,6 +531,8 @@
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@ -558,10 +588,12 @@
"lastNotNull"
],
"displayMode": "table",
"placement": "right"
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "single"
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.2.1",
@ -571,10 +603,12 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": true,
"expr": "f2b_jail_banned_current",
"expr": "f2b_jail_banned_current{instance=~\"$instance\"}",
"interval": "",
"legendFormat": "{{jail}}",
"legendFormat": "{{jail}} ({{instance}})",
"range": true,
"refId": "A"
}
],
@ -594,6 +628,8 @@
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@ -650,10 +686,12 @@
"lastNotNull"
],
"displayMode": "table",
"placement": "right"
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "single"
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.2.1",
@ -663,10 +701,12 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": true,
"expr": "f2b_up",
"expr": "f2b_up{instance=~\"$instance\"}",
"interval": "",
"legendFormat": "Up",
"legendFormat": "Up ({{instance}})",
"range": true,
"refId": "A"
}
],
@ -686,6 +726,8 @@
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
@ -742,10 +784,12 @@
"lastNotNull"
],
"displayMode": "table",
"placement": "right"
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "single"
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.2.1",
@ -755,10 +799,12 @@
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"editorMode": "code",
"exemplar": true,
"expr": "f2b_errors",
"expr": "f2b_errors{instance=~\"$instance\"}",
"interval": "",
"legendFormat": "{{type}}",
"legendFormat": "{{type}} ({{instance}})",
"range": true,
"refId": "A"
}
],
@ -768,14 +814,14 @@
}
],
"refresh": "30s",
"schemaVersion": 34,
"schemaVersion": 37,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"current": {
"selected": true,
"selected": false,
"text": "Prometheus",
"value": "Prometheus"
},
@ -791,6 +837,30 @@
"regex": "",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {},
"datasource": {
"type": "prometheus",
"uid": "${DS_PROMETHEUS}"
},
"definition": "f2b_up",
"description": "Select which instance(s) to show",
"hide": 0,
"includeAll": false,
"label": "Instance",
"multi": true,
"name": "instance",
"options": [],
"query": {
"query": "f2b_up",
"refId": "StandardVariableQuery"
},
"refresh": 1,
"regex": "/.*instance=\"([^\"]+)\"/",
"skipUrlSync": false,
"sort": 0,
"type": "query"
}
]
},
@ -802,6 +872,6 @@
"timezone": "",
"title": "F2B",
"uid": "cTkH9AT7z",
"version": 17,
"version": 3,
"weekStart": ""
}
}

View file

@ -0,0 +1,19 @@
[Unit]
Description=Fail2ban metric exporter for Prometheus
Documentation=https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/-/blob/main/README.md
Requires=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/sbin/fail2ban_exporter
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
# Currently need to run the exporter as root to ensure it has read/write access to the
# fail2ban socket file.
User=root
Group=root
[Install]
WantedBy=multi-user.target

29
auth/basic.go Normal file
View file

@ -0,0 +1,29 @@
package auth
import (
"fmt"
"net/http"
)
func NewBasicAuthProvider(username, password string) AuthProvider {
return &basicAuthProvider{
hashedAuth: encodeBasicAuth(username, password),
}
}
type basicAuthProvider struct {
hashedAuth string
}
func (p *basicAuthProvider) IsAllowed(request *http.Request) bool {
username, password, ok := request.BasicAuth()
if !ok {
return false
}
requestAuth := encodeBasicAuth(username, password)
return p.hashedAuth == requestAuth
}
func encodeBasicAuth(username, password string) string {
return HashString(fmt.Sprintf("%s:%s", username, password))
}

53
auth/basic_test.go Normal file
View file

@ -0,0 +1,53 @@
package auth
import (
"net/http"
"net/http/httptest"
"testing"
)
func Test_GIVEN_BasicAuthSet_WHEN_CallingIsAllowedWithCorrectCreds_THEN_TrueReturned(t *testing.T) {
// assemble
username := "u1"
password := HashString("abc")
request := httptest.NewRequest(http.MethodGet, "http://example.com", nil)
request.SetBasicAuth(username, password)
provider := NewBasicAuthProvider(username, password)
// act
result := provider.IsAllowed(request)
// assert
if !result {
t.Errorf("expected request to be allowed, but failed")
}
}
func Test_GIVEN_BasicAuthSet_WHEN_CallingIsAllowedWithoutCreds_THEN_FalseReturned(t *testing.T) {
// assemble
request := httptest.NewRequest(http.MethodGet, "http://example.com", nil)
provider := NewBasicAuthProvider("u1", "p1")
// act
result := provider.IsAllowed(request)
// assert
if result {
t.Errorf("expected request to be denied, but was allowed")
}
}
func Test_GIVEN_BasicAuthSet_WHEN_CallingIsAllowedWithWrongCreds_THEN_FalseReturned(t *testing.T) {
// assemble
request := httptest.NewRequest(http.MethodGet, "http://example.com", nil)
request.SetBasicAuth("wrong", "pw")
provider := NewBasicAuthProvider("u1", "p1")
// act
result := provider.IsAllowed(request)
// assert
if result {
t.Errorf("expected request to be denied, but was allowed")
}
}

14
auth/empty.go Normal file
View file

@ -0,0 +1,14 @@
package auth
import "net/http"
func NewEmptyAuthProvider() AuthProvider {
return &emptyAuthProvider{}
}
type emptyAuthProvider struct {
}
func (p *emptyAuthProvider) IsAllowed(request *http.Request) bool {
return true
}

36
auth/empty_test.go Normal file
View file

@ -0,0 +1,36 @@
package auth
import (
"net/http"
"net/http/httptest"
"testing"
)
func Test_GIVEN_EmptyAuth_WHEN_CallingIsAllowedWithoutAuth_THEN_TrueReturned(t *testing.T) {
// assemble
request := httptest.NewRequest(http.MethodGet, "http://example.com", nil)
provider := NewEmptyAuthProvider()
// act
response := provider.IsAllowed(request)
// assert
if !response {
t.Errorf("expected request to be allowed, but failed")
}
}
func Test_GIVEN_EmptyAuth_WHEN_CallingIsAllowedWithAuth_THEN_TrueReturned(t *testing.T) {
// assemble
request := httptest.NewRequest(http.MethodGet, "http://example.com", nil)
request.SetBasicAuth("user", "pass")
provider := NewEmptyAuthProvider()
// act
response := provider.IsAllowed(request)
// assert
if !response {
t.Errorf("expected request to be allowed, but failed")
}
}

View file

@ -5,7 +5,7 @@ import (
"encoding/hex"
)
func Hash(data []byte) []byte {
func hash(data []byte) []byte {
if len(data) == 0 {
return []byte{}
}
@ -14,5 +14,5 @@ func Hash(data []byte) []byte {
}
func HashString(data string) string {
return hex.EncodeToString(Hash([]byte(data)))
return hex.EncodeToString(hash([]byte(data)))
}

9
auth/provider.go Normal file
View file

@ -0,0 +1,9 @@
package auth
import (
"net/http"
)
type AuthProvider interface {
IsAllowed(*http.Request) bool
}

84
cfg/cfg.go Normal file
View file

@ -0,0 +1,84 @@
package cfg
import (
"fmt"
"log"
"os"
"github.com/alecthomas/kong"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/auth"
)
var cliStruct struct {
VersionMode bool `name:"version" short:"v" help:"Show version info and exit"`
DryRunMode bool `name:"dry-run" help:"Attempt to connect to the fail2ban socket then exit before starting the server"`
ServerAddress string `name:"web.listen-address" env:"F2B_WEB_LISTEN_ADDRESS" help:"Address to use for the metrics server" default:"${default_address}"`
F2bSocketPath string `name:"collector.f2b.socket" env:"F2B_COLLECTOR_SOCKET" help:"Path to the fail2ban server socket" default:"${default_socket}"`
ExitOnSocketError bool `name:"collector.f2b.exit-on-socket-connection-error" env:"F2B_EXIT_ON_SOCKET_CONN_ERROR" help:"When set to true the exporter will immediately exit on a fail2ban socket connection error"`
TextFileExporterPath string `name:"collector.textfile.directory" env:"F2B_COLLECTOR_TEXT_PATH" help:"Directory to read text files with metrics from"`
BasicAuthUser string `name:"web.basic-auth.username" env:"F2B_WEB_BASICAUTH_USER" help:"Username to use to protect endpoints with basic auth"`
BasicAuthPass string `name:"web.basic-auth.password" env:"F2B_WEB_BASICAUTH_PASS" help:"Password to use to protect endpoints with basic auth"`
}
func Parse() *AppSettings {
ctx := kong.Parse(
&cliStruct,
kong.Vars{
"default_socket": "/var/run/fail2ban/fail2ban.sock",
"default_address": ":9191",
},
kong.Name("fail2ban_exporter"),
kong.Description("🚀 Export prometheus metrics from a running Fail2Ban instance"),
kong.UsageOnError(),
)
validateFlags(ctx)
settings := &AppSettings{
VersionMode: cliStruct.VersionMode,
DryRunMode: cliStruct.DryRunMode,
MetricsAddress: cliStruct.ServerAddress,
Fail2BanSocketPath: cliStruct.F2bSocketPath,
FileCollectorPath: cliStruct.TextFileExporterPath,
ExitOnSocketConnError: cliStruct.ExitOnSocketError,
AuthProvider: createAuthProvider(),
}
return settings
}
func createAuthProvider() auth.AuthProvider {
username := cliStruct.BasicAuthUser
password := cliStruct.BasicAuthPass
if len(username) == 0 && len(password) == 0 {
return auth.NewEmptyAuthProvider()
}
log.Print("basic auth enabled")
return auth.NewBasicAuthProvider(username, password)
}
func validateFlags(cliCtx *kong.Context) {
var flagsValid = true
var messages = []string{}
if !cliStruct.VersionMode {
if cliStruct.F2bSocketPath == "" {
messages = append(messages, "error: fail2ban socket path must not be blank")
flagsValid = false
}
if cliStruct.ServerAddress == "" {
messages = append(messages, "error: invalid server address, must not be blank")
flagsValid = false
}
if (len(cliStruct.BasicAuthUser) > 0) != (len(cliStruct.BasicAuthPass) > 0) {
messages = append(messages, "error: to enable basic auth both the username and the password must be provided")
flagsValid = false
}
}
if !flagsValid {
cliCtx.PrintUsage(false)
fmt.Println()
for i := 0; i < len(messages); i++ {
fmt.Println(messages[i])
}
os.Exit(1)
}
}

13
cfg/settings.go Normal file
View file

@ -0,0 +1,13 @@
package cfg
import "gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/auth"
type AppSettings struct {
VersionMode bool
DryRunMode bool
MetricsAddress string
Fail2BanSocketPath string
FileCollectorPath string
AuthProvider auth.AuthProvider
ExitOnSocketConnError bool
}

View file

@ -1,11 +1,12 @@
package f2b
import (
"log"
"os"
"github.com/prometheus/client_golang/prometheus"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/cfg"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/socket"
"log"
"os"
)
type Collector struct {
@ -18,7 +19,8 @@ type Collector struct {
}
func NewExporter(appSettings *cfg.AppSettings, exporterVersion string) *Collector {
log.Printf("reading metrics from fail2ban socket: %s", appSettings.Fail2BanSocketPath)
log.Printf("reading fail2ban metrics from socket file: %s", appSettings.Fail2BanSocketPath)
printFail2BanServerVersion(appSettings.Fail2BanSocketPath)
return &Collector{
socketPath: appSettings.Fail2BanSocketPath,
exporterVersion: exporterVersion,
@ -58,3 +60,33 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) {
}
c.collectErrorCountMetric(ch)
}
func (c *Collector) IsHealthy() bool {
s, err := socket.ConnectToSocket(c.socketPath)
if err != nil {
log.Printf("error opening socket: %v", err)
c.socketConnectionErrorCount++
return false
}
pingSuccess, err := s.Ping()
if err != nil {
log.Printf("error pinging fail2ban server: %v", err)
c.socketRequestErrorCount++
return false
}
return pingSuccess
}
func printFail2BanServerVersion(socketPath string) {
s, err := socket.ConnectToSocket(socketPath)
if err != nil {
log.Printf("error connecting to socket: %v", err)
} else {
version, err := s.GetServerVersion()
if err != nil {
log.Printf("error interacting with socket: %v", err)
} else {
log.Printf("successfully connected to fail2ban socket! fail2ban version: %s", version)
}
}
}

View file

@ -1,11 +1,12 @@
package textfile
import (
"github.com/prometheus/client_golang/prometheus"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"github.com/prometheus/client_golang/prometheus"
)
const namespace = "textfile"
@ -19,7 +20,7 @@ var (
)
func (c *Collector) collectFileContents() {
files, err := ioutil.ReadDir(c.folderPath)
files, err := os.ReadDir(c.folderPath)
if err != nil {
log.Printf("error reading directory '%s': %v", c.folderPath, err)
return
@ -36,7 +37,7 @@ func (c *Collector) collectFileContents() {
}
fullPath := filepath.Join(c.folderPath, fileName)
content, err := ioutil.ReadFile(fullPath)
content, err := os.ReadFile(fullPath)
if err != nil {
c.appendErrorForPath(fileName)
log.Printf("error reading contents of file '%s': %v", fileName, err)

View file

@ -1,9 +0,0 @@
[Unit]
Description=Fail2Ban Exporter
[Service]
User=fail2ban_exporter
ExecStart=/usr/sbin/fail2ban_exporter
[Install]
WantedBy=multi-user.target

66
exporter.go Normal file
View file

@ -0,0 +1,66 @@
package main
import (
"fmt"
"log"
"os"
"os/signal"
"syscall"
"github.com/prometheus/client_golang/prometheus"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/cfg"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/f2b"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/textfile"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/server"
)
var (
version = "dev"
commit = "none"
date = "unknown"
builtBy = "unknown"
)
func printAppVersion() {
fmt.Println(version)
fmt.Printf(" build date: %s\r\n commit hash: %s\r\n built by: %s\r\n", date, commit, builtBy)
}
func main() {
appSettings := cfg.Parse()
if appSettings.VersionMode {
printAppVersion()
return
}
handleGracefulShutdown()
log.Printf("fail2ban exporter version %s", version)
log.Printf("starting server at %s", appSettings.MetricsAddress)
f2bCollector := f2b.NewExporter(appSettings, version)
prometheus.MustRegister(f2bCollector)
textFileCollector := textfile.NewCollector(appSettings)
prometheus.MustRegister(textFileCollector)
if !appSettings.DryRunMode {
svrErr := server.StartServer(appSettings, f2bCollector, textFileCollector)
err := <-svrErr
log.Fatal(err)
} else {
log.Print("running in dry-run mode - exiting")
}
}
func handleGracefulShutdown() {
var signals = make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGTERM)
signal.Notify(signals, syscall.SIGINT)
go func() {
sig := <-signals
log.Printf("caught signal: %+v", sig)
os.Exit(0)
}()
}

21
go.mod Normal file
View file

@ -0,0 +1,21 @@
module gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
go 1.20
require (
github.com/alecthomas/kong v0.8.1
github.com/kisielk/og-rek v1.2.0
github.com/nlpodyssey/gopickle v0.2.0
github.com/prometheus/client_golang v1.17.0
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
golang.org/x/sys v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)

33
go.sum Normal file
View file

@ -0,0 +1,33 @@
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY=
github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/kisielk/og-rek v1.2.0 h1:CTvDIin+YnetsSQAYbe+QNAxXU3B50C5hseEz8xEoJw=
github.com/kisielk/og-rek v1.2.0/go.mod h1:6ihsOSzSAxR/65S3Bn9zNihoEqRquhDQZ2c6I2+MG3c=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
github.com/nlpodyssey/gopickle v0.2.0 h1:4naD2DVylYJupQLbCQFdwo6yiXEmPyp+0xf5MVlrBDY=
github.com/nlpodyssey/gopickle v0.2.0/go.mod h1:YIUwjJ2O7+vnBsxUN+MHAAI3N+adqEGiw+nDpwW95bY=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=

8
health Executable file
View file

@ -0,0 +1,8 @@
#!/bin/sh
port=9191
if [ ! -z $F2B_WEB_LISTEN_ADDRESS ]; then
port=`echo $F2B_WEB_LISTEN_ADDRESS | cut -d ":" -f 2 -`
fi
curl --fail localhost:$port/health || exit 1

17
server/auth.go Normal file
View file

@ -0,0 +1,17 @@
package server
import (
"net/http"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/auth"
)
func AuthMiddleware(handlerFunc http.HandlerFunc, authProvider auth.AuthProvider) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if authProvider.IsAllowed(r) {
handlerFunc.ServeHTTP(w, r)
} else {
w.WriteHeader(http.StatusUnauthorized)
}
}
}

46
server/auth_test.go Normal file
View file

@ -0,0 +1,46 @@
package server
import (
"net/http"
"net/http/httptest"
"testing"
)
type testAuthProvider struct {
match bool
}
func (p testAuthProvider) IsAllowed(request *http.Request) bool {
return p.match
}
func newTestRequest() *http.Request {
return httptest.NewRequest(http.MethodGet, "http://example.com", nil)
}
func executeAuthMiddlewareTest(t *testing.T, authMatches bool, expectedCode int, expectedCallCount int) {
callCount := 0
testHandler := func(w http.ResponseWriter, r *http.Request) {
callCount++
}
handler := AuthMiddleware(testHandler, testAuthProvider{match: authMatches})
recorder := httptest.NewRecorder()
request := newTestRequest()
handler.ServeHTTP(recorder, request)
if recorder.Code != expectedCode {
t.Errorf("statusCode = %v, want %v", recorder.Code, expectedCode)
}
if callCount != expectedCallCount {
t.Errorf("callCount = %v, want %v", callCount, expectedCallCount)
}
}
func Test_GIVEN_MatchingBasicAuth_WHEN_MethodCalled_THEN_RequestProcessed(t *testing.T) {
executeAuthMiddlewareTest(t, true, http.StatusOK, 1)
}
func Test_GIVEN_NonMatchingBasicAuth_WHEN_MethodCalled_THEN_RequestRejected(t *testing.T) {
executeAuthMiddlewareTest(t, false, http.StatusUnauthorized, 0)
}

44
server/handler.go Normal file
View file

@ -0,0 +1,44 @@
package server
import (
"log"
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/f2b"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/textfile"
)
const (
metricsPath = "/metrics"
)
func rootHtmlHandler(w http.ResponseWriter, r *http.Request) {
_, err := w.Write([]byte(
`<html>
<head><title>Fail2Ban Exporter</title></head>
<body>
<h1>Fail2Ban Exporter</h1>
<p><a href="` + metricsPath + `">Metrics</a></p>
</body>
</html>`))
if err != nil {
log.Printf("error handling root url: %v", err)
w.WriteHeader(http.StatusInternalServerError)
}
}
func metricHandler(w http.ResponseWriter, r *http.Request, collector *textfile.Collector) {
promhttp.Handler().ServeHTTP(w, r)
collector.WriteTextFileMetrics(w, r)
}
func healthHandler(w http.ResponseWriter, r *http.Request, collector *f2b.Collector) {
if collector.IsHealthy() {
w.WriteHeader(http.StatusOK)
w.Write([]byte("{\"healthy\":true}"))
} else {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("{\"healthy\":false}"))
}
}

48
server/server.go Normal file
View file

@ -0,0 +1,48 @@
package server
import (
"log"
"net/http"
"time"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/cfg"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/f2b"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/textfile"
)
func StartServer(
appSettings *cfg.AppSettings,
f2bCollector *f2b.Collector,
textFileCollector *textfile.Collector,
) chan error {
http.HandleFunc("/", AuthMiddleware(
rootHtmlHandler,
appSettings.AuthProvider,
))
http.HandleFunc(metricsPath, AuthMiddleware(
func(w http.ResponseWriter, r *http.Request) {
metricHandler(w, r, textFileCollector)
},
appSettings.AuthProvider,
))
http.HandleFunc("/health",
func(w http.ResponseWriter, r *http.Request) {
healthHandler(w, r, f2bCollector)
},
)
log.Printf("metrics available at '%s'", metricsPath)
svrErr := make(chan error)
go func() {
httpServer := &http.Server{
Addr: appSettings.MetricsAddress,
ReadHeaderTimeout: 10 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 30 * time.Second,
}
svrErr <- httpServer.ListenAndServe()
}()
log.Print("ready")
return svrErr
}

View file

@ -1,31 +0,0 @@
package auth
import (
"net/http"
)
type BasicAuthProvider interface {
Enabled() bool
DoesBasicAuthMatch(username, password string) bool
}
func BasicAuthMiddleware(handlerFunc http.HandlerFunc, basicAuthProvider BasicAuthProvider) http.HandlerFunc {
if basicAuthProvider.Enabled() {
return func(w http.ResponseWriter, r *http.Request) {
if doesBasicAuthMatch(r, basicAuthProvider) {
handlerFunc.ServeHTTP(w, r)
} else {
w.WriteHeader(http.StatusUnauthorized)
}
}
}
return handlerFunc
}
func doesBasicAuthMatch(r *http.Request, basicAuthProvider BasicAuthProvider) bool {
rawUsername, rawPassword, ok := r.BasicAuth()
if ok {
return basicAuthProvider.DoesBasicAuthMatch(rawUsername, rawPassword)
}
return false
}

View file

@ -1,58 +0,0 @@
package auth
import (
"net/http"
"net/http/httptest"
"testing"
)
type testAuthProvider struct {
enabled bool
match bool
}
func (p testAuthProvider) Enabled() bool {
return p.enabled
}
func (p testAuthProvider) DoesBasicAuthMatch(username, password string) bool {
return p.match
}
func newTestRequest() *http.Request {
return httptest.NewRequest(http.MethodGet, "http://example.com", nil)
}
func executeBasicAuthMiddlewareTest(t *testing.T, authEnabled bool, authMatches bool, expectedCode int, expectedCallCount int) {
callCount := 0
testHandler := func(w http.ResponseWriter, r *http.Request) {
callCount++
}
handler := BasicAuthMiddleware(testHandler, testAuthProvider{enabled: authEnabled, match: authMatches})
recorder := httptest.NewRecorder()
request := newTestRequest()
if authEnabled {
request.SetBasicAuth("test", "test")
}
handler.ServeHTTP(recorder, request)
if recorder.Code != expectedCode {
t.Errorf("statusCode = %v, want %v", recorder.Code, expectedCode)
}
if callCount != expectedCallCount {
t.Errorf("callCount = %v, want %v", callCount, expectedCallCount)
}
}
func Test_GIVEN_DisabledBasicAuth_WHEN_MethodCalled_THEN_RequestProcessed(t *testing.T) {
executeBasicAuthMiddlewareTest(t, false, false, http.StatusOK, 1)
}
func Test_GIVEN_EnabledBasicAuth_WHEN_MethodCalledWithCorrectCredentials_THEN_RequestProcessed(t *testing.T) {
executeBasicAuthMiddlewareTest(t, true, true, http.StatusOK, 1)
}
func Test_GIVEN_EnabledBasicAuth_WHEN_MethodCalledWithIncorrectCredentials_THEN_RequestRejected(t *testing.T) {
executeBasicAuthMiddlewareTest(t, true, false, http.StatusUnauthorized, 0)
}

View file

@ -1,25 +0,0 @@
package cfg
import "gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/auth"
type hashedBasicAuth struct {
username string
password string
}
func newHashedBasicAuth(rawUsername, rawPassword string) *hashedBasicAuth {
return &hashedBasicAuth{
username: auth.HashString(rawUsername),
password: auth.HashString(rawPassword),
}
}
func (p *hashedBasicAuth) Enabled() bool {
return len(p.username) > 0 && len(p.password) > 0
}
func (p *hashedBasicAuth) DoesBasicAuthMatch(rawUsername, rawPassword string) bool {
username := auth.HashString(rawUsername)
password := auth.HashString(rawPassword)
return username == p.username && password == p.password
}

View file

@ -1,60 +0,0 @@
package cfg
import "testing"
func Test_hashedBasicAuth_DoesBasicAuthMatch(t *testing.T) {
type args struct {
username string
password string
}
type fields struct {
username string
password string
}
tests := []struct {
name string
fields fields
args args
want bool
}{
{"Happy test #1", fields{username: "1234", password: "1234"}, args{username: "1234", password: "1234"}, true},
{"Happy test #2", fields{username: "test", password: "1234"}, args{username: "test", password: "1234"}, true},
{"Happy test #3", fields{username: "TEST", password: "1234"}, args{username: "TEST", password: "1234"}, true},
{"Non match #1", fields{username: "test", password: "1234"}, args{username: "1234", password: "1234"}, false},
{"Non match #2", fields{username: "1234", password: "test"}, args{username: "1234", password: "1234"}, false},
{"Non match #3", fields{username: "1234", password: "test"}, args{username: "1234", password: "TEST"}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
basicAuth := newHashedBasicAuth(tt.fields.username, tt.fields.password)
if got := basicAuth.DoesBasicAuthMatch(tt.args.username, tt.args.password); got != tt.want {
t.Errorf("DoesBasicAuthMatch() = %v, want %v", got, tt.want)
}
})
}
}
func Test_hashedBasicAuth_Enabled(t *testing.T) {
type fields struct {
username string
password string
}
tests := []struct {
name string
fields fields
want bool
}{
{"Both blank", fields{username: "", password: ""}, false},
{"Single blank #1", fields{username: "test", password: ""}, false},
{"Single blank #1", fields{username: "", password: "test"}, false},
{"Both populated", fields{username: "test", password: "test"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
basicAuth := newHashedBasicAuth(tt.fields.username, tt.fields.password)
if got := basicAuth.Enabled(); got != tt.want {
t.Errorf("Enabled() = %v, want %v", got, tt.want)
}
})
}
}

View file

@ -1,109 +0,0 @@
package cfg
import (
"fmt"
"gopkg.in/alecthomas/kingpin.v2"
"os"
)
const (
socketEnvName = "F2B_COLLECTOR_SOCKET"
fileCollectorPathEnvName = "F2B_COLLECTOR_TEXT_PATH"
addressEnvName = "F2B_WEB_LISTEN_ADDRESS"
basicAuthUserEnvName = "F2B_WEB_BASICAUTH_USER"
basicAuthPassEnvName = "F2B_WEB_BASICAUTH_PASS"
exitOnSocketConnErrorEnvName = "F2B_EXIT_ON_SOCKET_CONN_ERROR"
)
type AppSettings struct {
VersionMode bool
MetricsAddress string
Fail2BanSocketPath string
FileCollectorPath string
BasicAuthProvider *hashedBasicAuth
ExitOnSocketConnError bool
}
func init() {
kingpin.HelpFlag.Short('h')
}
func Parse() *AppSettings {
settings := &AppSettings{}
readParamsFromCli(settings)
settings.validateFlags()
return settings
}
func readParamsFromCli(settings *AppSettings) {
versionMode := kingpin.
Flag("version", "show version info and exit").
Short('v').
Default("false").
Bool()
socketPath := kingpin.
Flag("collector.f2b.socket", "path to the fail2ban server socket").
Default("/var/run/fail2ban/fail2ban.sock").
Envar(socketEnvName).
String()
fileCollectorPath := kingpin.
Flag("collector.textfile.directory", "directory to read text files with metrics from").
Default("").
Envar(fileCollectorPathEnvName).
String()
address := kingpin.
Flag("web.listen-address", "address to use for the metrics server").
Default(":9191").
Envar(addressEnvName).
String()
rawBasicAuthUsername := kingpin.
Flag("web.basic-auth.username", "username to use to protect endpoints with basic auth").
Default("").
Envar(basicAuthUserEnvName).
String()
rawBasicAuthPassword := kingpin.
Flag("web.basic-auth.password", "password to use to protect endpoints with basic auth").
Default("").
Envar(basicAuthPassEnvName).
String()
rawExitOnSocketConnError := kingpin.
Flag("collector.f2b.exit-on-socket-connection-error", "when set to true the exporter will immediately exit on a fail2ban socket connection error").
Default("false").
Envar(exitOnSocketConnErrorEnvName).
Bool()
kingpin.Parse()
settings.VersionMode = *versionMode
settings.MetricsAddress = *address
settings.Fail2BanSocketPath = *socketPath
settings.FileCollectorPath = *fileCollectorPath
settings.setBasicAuthValues(*rawBasicAuthUsername, *rawBasicAuthPassword)
settings.ExitOnSocketConnError = *rawExitOnSocketConnError
}
func (settings *AppSettings) setBasicAuthValues(rawUsername, rawPassword string) {
settings.BasicAuthProvider = newHashedBasicAuth(rawUsername, rawPassword)
}
func (settings *AppSettings) validateFlags() {
var flagsValid = true
if !settings.VersionMode {
if settings.Fail2BanSocketPath == "" {
fmt.Println("error: fail2ban socket path must not be blank")
flagsValid = false
}
if settings.MetricsAddress == "" {
fmt.Println("error: invalid server address, must not be blank")
flagsValid = false
}
if (len(settings.BasicAuthProvider.username) > 0) != (len(settings.BasicAuthProvider.password) > 0) {
fmt.Println("error: to enable basic auth both the username and the password must be provided")
flagsValid = false
}
}
if !flagsValid {
kingpin.Usage()
os.Exit(1)
}
}

View file

@ -1,103 +0,0 @@
package main
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/auth"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/cfg"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/f2b"
"gitlab.com/hectorjsmith/fail2ban-prometheus-exporter/collector/textfile"
"log"
"net/http"
"os"
"os/signal"
"syscall"
)
const (
metricsPath = "/metrics"
)
var (
version = "dev"
commit = "none"
date = "unknown"
builtBy = "unknown"
)
func printAppVersion() {
fmt.Println(version)
fmt.Printf(" build date: %s\r\n commit hash: %s\r\n built by: %s\r\n", date, commit, builtBy)
}
func rootHtmlHandler(w http.ResponseWriter, r *http.Request) {
_, err := w.Write([]byte(
`<html>
<head><title>Fail2Ban Exporter</title></head>
<body>
<h1>Fail2Ban Exporter</h1>
<p><a href="` + metricsPath + `">Metrics</a></p>
</body>
</html>`))
if err != nil {
log.Printf("error handling root url: %v", err)
w.WriteHeader(http.StatusInternalServerError)
}
}
func metricHandler(w http.ResponseWriter, r *http.Request, collector *textfile.Collector) {
promhttp.Handler().ServeHTTP(w, r)
collector.WriteTextFileMetrics(w, r)
}
func main() {
appSettings := cfg.Parse()
if appSettings.VersionMode {
printAppVersion()
} else {
handleGracefulShutdown()
log.Printf("fail2ban exporter version %s", version)
log.Printf("starting server at %s", appSettings.MetricsAddress)
f2bCollector := f2b.NewExporter(appSettings, version)
prometheus.MustRegister(f2bCollector)
textFileCollector := textfile.NewCollector(appSettings)
prometheus.MustRegister(textFileCollector)
http.HandleFunc("/", auth.BasicAuthMiddleware(rootHtmlHandler, appSettings.BasicAuthProvider))
http.HandleFunc(metricsPath, auth.BasicAuthMiddleware(
func(w http.ResponseWriter, r *http.Request) {
metricHandler(w, r, textFileCollector)
},
appSettings.BasicAuthProvider,
))
log.Printf("metrics available at '%s'", metricsPath)
if appSettings.BasicAuthProvider.Enabled() {
log.Printf("basic auth enabled")
}
svrErr := make(chan error)
go func() {
svrErr <- http.ListenAndServe(appSettings.MetricsAddress, nil)
}()
log.Print("ready")
err := <-svrErr
log.Fatal(err)
}
}
func handleGracefulShutdown() {
var signals = make(chan os.Signal)
signal.Notify(signals, syscall.SIGTERM)
signal.Notify(signals, syscall.SIGINT)
go func() {
sig := <-signals
log.Printf("caught signal: %+v", sig)
os.Exit(0)
}()
}

View file

@ -1,10 +0,0 @@
module gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
go 1.15
require (
github.com/kisielk/og-rek v1.1.0
github.com/nlpodyssey/gopickle v0.1.0
github.com/prometheus/client_golang v1.9.0
gopkg.in/alecthomas/kingpin.v2 v2.2.6
)

View file

@ -1,414 +0,0 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kisielk/og-rek v1.1.0 h1:u10TvQbPtrlY/6H4+BiFsBywwSVTGFsx0YOVtpx3IbI=
github.com/kisielk/og-rek v1.1.0/go.mod h1:6ihsOSzSAxR/65S3Bn9zNihoEqRquhDQZ2c6I2+MG3c=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nlpodyssey/gopickle v0.1.0 h1:9wjwRqXsOSYWZl4c4ko472b6RW+VB1I441ZcfFg1r5g=
github.com/nlpodyssey/gopickle v0.1.0/go.mod h1:YIUwjJ2O7+vnBsxUN+MHAAI3N+adqEGiw+nDpwW95bY=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=

View file

@ -1,60 +0,0 @@
# CHANGELOG
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog], and this project adheres to [Semantic Versioning].
{{ if .Versions -}}
## [Unreleased]
{{- if .Unreleased.CommitGroups }}
{{ template "commits" .Unreleased.CommitGroups }}
{{- end -}}
{{- if .Unreleased.NoteGroups -}}
{{ template "notes" .Unreleased.NoteGroups }}
{{- end -}}
{{- end -}}
{{ range .Versions -}}
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
{{ template "commits" .CommitGroups }}
{{- if .NoteGroups -}}
{{ template "notes" .NoteGroups }}
{{- end -}}
{{ end }}
---
*This changelog is automatically generated by [git-chglog]*
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
[git-chglog]: https://github.com/git-chglog/git-chglog
{{- if .Versions }}
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...main
{{ range .Versions -}}
{{ if .Tag.Previous -}}
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
{{ end -}}
{{ end -}}
{{ end -}}
{{- define "notes" }}
{{- range . -}}
### {{ .Title }}
{{ range .Notes -}}
- {{ .Body }}
{{ end }}
{{ end }}
{{ end -}}
{{- define "commits" }}
{{- range . -}}
{{ if or (eq .RawTitle "feat") (eq .RawTitle "fix") }}
### {{ .Title }}
{{ range .Commits -}}
- ({{ .Hash.Short }}) {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Header }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}

View file

@ -1,23 +0,0 @@
style: gitlab
template: CHANGELOG.tpl.md
info:
title: CHANGELOG
repository_url: https://gitlab.com/hectorjsmith/fail2ban-prometheus-exporter
options:
commit_groups:
title_maps:
feat: Added
fix: Fixed
revert: Reverted
header:
pattern: "^(\\w*)\\:\\s(.*)$"
pattern_maps:
- Type
- Subject
notes:
keywords:
- BREAKING CHANGE
- Changed
- Deprecated
- Removed
- Security

Binary file not shown.

Binary file not shown.