Compare commits

..

No commits in common. "master" and "v0.1.1" have entirely different histories.

20 changed files with 277 additions and 2118 deletions

View file

@ -1,6 +1,6 @@
# Contributing # Contributing
Pi-hole exporter is an open source project, completely opened to be a community-driven project. PI-Hole exporter is an open source project, completely opened to be a community-driven project.
If you'd like to contribute, you are free to do so. If you'd like to contribute, you are free to do so.

View file

@ -12,3 +12,7 @@ updates:
interval: daily interval: daily
time: "04:00" time: "04:00"
open-pull-requests-limit: 10 open-pull-requests-limit: 10
ignore:
- dependency-name: golang
versions:
- 1.16.1.pre.alpine3.12

31
.github/main.workflow vendored Normal file
View file

@ -0,0 +1,31 @@
workflow "Build and Publish" {
on = "push"
resolves = ["Master", "Docker Push"]
}
# Filter for master branch
action "Master" {
uses = "actions/bin/filter@master"
args = "branch master"
}
action "Docker Build" {
uses = "actions/docker/cli@fe7ed3ce992160973df86480b83a2f8ed581cd50"
needs = ["Master"]
args = "build -t pihole-exporter ."
}
action "Docker Registry" {
uses = "actions/docker/login@fe7ed3ce992160973df86480b83a2f8ed581cd50"
env = {
DOCKER_REGISTRY_URL = "docker.pkg.github.com"
}
secrets = ["DOCKER_PASSWORD", "DOCKER_USERNAME"]
needs = ["Docker Build"]
}
action "Docker Push" {
uses = "actions/docker/cli@fe7ed3ce992160973df86480b83a2f8ed581cd50"
args = "push pihole-exporter"
needs = ["Docker Registry"]
}

View file

@ -3,17 +3,20 @@ name: Test (master)
on: on:
push: push:
branches: branches:
- master - '*'
pull_request:
branches:
- '*'
jobs: jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
go_version: [ '1.20' ] go_version: [ '1.14', '1.15', '1.16', '1.17' ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: actions/setup-go@v3 - uses: actions/setup-go@v1
with: with:
go-version: ${{ matrix.go_version }} go-version: ${{ matrix.go_version }}
@ -23,30 +26,3 @@ jobs:
- name: Run go tests - name: Run go tests
run: go test -v -cover -race ./... run: go test -v -cover -race ./...
docker-build:
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v3
- uses: azure/docker-login@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up docker buildx
id: buildx
uses: crazy-max/ghaction-docker-buildx@v1
with:
buildx-version: latest
qemu-version: latest
- name: Docker buildx available platforms
run: echo ${{ steps.buildx.outputs.platforms }}
- name: Run docker buildx build
run: |
docker buildx build \
--platform linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 \
--output=type=registry,push=true \
--tag ekofr/pihole-exporter:latest \
.

View file

@ -10,10 +10,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
go_version: [ '1.20' ] go_version: [ '1.14', '1.15', '1.16', '1.17' ]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: actions/setup-go@v3 - uses: actions/setup-go@v2
with: with:
go-version: ${{ matrix.go_version }} go-version: ${{ matrix.go_version }}
- run: go get -t -v ./... - run: go get -t -v ./...
@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: test needs: test
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: azure/docker-login@v1 - uses: azure/docker-login@v1
with: with:
@ -48,7 +48,7 @@ jobs:
run: | run: |
docker buildx build \ docker buildx build \
--platform linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 \ --platform linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64 \
--output=type=registry,push=true \ --output=type=registry \
--tag ekofr/pihole-exporter:${{ steps.get_version.outputs.TAG_NAME }} \ --tag ekofr/pihole-exporter:${{ steps.get_version.outputs.TAG_NAME }} \
. .
@ -99,10 +99,10 @@ jobs:
extension: '.exe' extension: '.exe'
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: actions/setup-go@v3 - uses: actions/setup-go@v2
with: with:
go-version: '1.20' go-version: 1.15
- name: Download go dependencies - name: Download go dependencies
run: go get -t -v ./... run: go get -t -v ./...

1
.gitignore vendored
View file

@ -1,7 +1,6 @@
vendor vendor
bin bin
tmp tmp
.vscode .vscode
report.xml report.xml
debug debug

View file

@ -1,18 +0,0 @@
repos:
- repo: https://github.com/dnephin/pre-commit-golang
rev: v0.5.1
hooks:
- id: go-fmt
- id: go-vet
- id: validate-toml
- id: no-go-testing
- id: go-unit-tests
- id: go-build
- id: go-mod-tidy
- repo: https://github.com/pre-commit/pre-commit-hooks.git
rev: v4.3.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: mixed-line-ending
- id: check-merge-conflict

View file

@ -2,7 +2,7 @@ ARG IMAGE=scratch
ARG OS=linux ARG OS=linux
ARG ARCH=amd64 ARG ARCH=amd64
FROM golang:1.21.2-alpine3.17 as builder FROM golang:1.17.3-alpine3.13 as builder
WORKDIR /go/src/github.com/eko/pihole-exporter WORKDIR /go/src/github.com/eko/pihole-exporter
COPY . . COPY . .

View file

@ -1,17 +1,14 @@
# Pi-hole Prometheus Exporter # PI-Hole Prometheus Exporter
![Build/Push (master)](https://github.com/eko/pihole-exporter/workflows/Build/Push%20(master)/badge.svg) ![Build/Push (master)](https://github.com/eko/pihole-exporter/workflows/Build/Push%20(master)/badge.svg)
[![GoDoc](https://godoc.org/github.com/eko/pihole-exporter?status.png)](https://godoc.org/github.com/eko/pihole-exporter) [![GoDoc](https://godoc.org/github.com/eko/pihole-exporter?status.png)](https://godoc.org/github.com/eko/pihole-exporter)
[![GoReportCard](https://goreportcard.com/badge/github.com/eko/pihole-exporter)](https://goreportcard.com/report/github.com/eko/pihole-exporter) [![GoReportCard](https://goreportcard.com/badge/github.com/eko/pihole-exporter)](https://goreportcard.com/report/github.com/eko/pihole-exporter)
This is a Prometheus exporter for [Pi-hole](https://pi-hole.net/)'s Raspberry PI ad blocker. This is a Prometheus exporter for [PI-Hole](https://pi-hole.net/)'s Raspberry PI ad blocker.
![Grafana dashboard](https://raw.githubusercontent.com/eko/pihole-exporter/master/dashboard.jpg) ![Grafana dashboard](https://raw.githubusercontent.com/eko/pihole-exporter/master/dashboard.jpg)
Available Grafana Dasboards: Grafana dashboard is [available here](https://grafana.com/dashboards/10176) on the Grafana dashboard website and also [here](https://raw.githubusercontent.com/eko/pihole-exporter/master/grafana/dashboard.json) on the GitHub repository.
* Prometheus: [Grafana Labs](https://grafana.com/grafana/dashboards/10176-pi-hole-exporter/) / [JSON/Github](https://raw.githubusercontent.com/eko/pihole-exporter/master/grafana/dashboard.json) --> [Preview](https://raw.githubusercontent.com/eko/pihole-exporter/master/dashboard.jpg)
* InfluxDB 2 (Flux): [Grafana Labs](https://grafana.com/grafana/dashboards/17094-pi-hole-exporter-influxdb-2/) / [JSON/Github](https://raw.githubusercontent.com/eko/pihole-exporter/master/grafana/dashboard-influxdb2.json) --> [Preview](https://raw.githubusercontent.com/eko/pihole-exporter/master/dashboard-influxdb2.png)
## Prerequisites ## Prerequisites
@ -46,6 +43,7 @@ You can run it using the following example and pass configuration environment va
$ docker run \ $ docker run \
-e 'PIHOLE_HOSTNAME=192.168.1.2' \ -e 'PIHOLE_HOSTNAME=192.168.1.2' \
-e 'PIHOLE_PASSWORD=mypassword' \ -e 'PIHOLE_PASSWORD=mypassword' \
-e 'INTERVAL=30s' \
-e 'PORT=9617' \ -e 'PORT=9617' \
-p 9617:9617 \ -p 9617:9617 \
ekofr/pihole-exporter:latest ekofr/pihole-exporter:latest
@ -58,8 +56,8 @@ $ API_TOKEN=$(awk -F= -v key="WEBPASSWORD" '$1==key {print $2}' /etc/pihole/setu
$ docker run \ $ docker run \
-e 'PIHOLE_HOSTNAME=192.168.1.2' \ -e 'PIHOLE_HOSTNAME=192.168.1.2' \
-e "PIHOLE_API_TOKEN=$API_TOKEN" \ -e "PIHOLE_API_TOKEN=$API_TOKEN" \
-e 'INTERVAL=30s' \
-e 'PORT=9617' \ -e 'PORT=9617' \
-p 9617:9617 \
ekofr/pihole-exporter:latest ekofr/pihole-exporter:latest
``` ```
@ -71,6 +69,7 @@ $ docker run \
-e 'PIHOLE_PROTOCOL=https' \ -e 'PIHOLE_PROTOCOL=https' \
-e 'PIHOLE_HOSTNAME=192.168.1.2' \ -e 'PIHOLE_HOSTNAME=192.168.1.2' \
-e 'PIHOLE_PASSWORD=mypassword' \ -e 'PIHOLE_PASSWORD=mypassword' \
-e 'INTERVAL=30s' \
-e 'PORT=9617' \ -e 'PORT=9617' \
-v '/etc/ssl/certs:/etc/ssl/certs:ro' \ -v '/etc/ssl/certs:/etc/ssl/certs:ro' \
-p 9617:9617 \ -p 9617:9617 \
@ -82,12 +81,12 @@ To do so, you can specify a list of hostnames, protocols, passwords/API tokens a
``` ```
$ docker run \ $ docker run \
-e 'PIHOLE_PROTOCOL=http,http,http" \ -e 'PIHOLE_PROTOCOL="http,http,http" \
-e 'PIHOLE_HOSTNAME=192.168.1.2,192.168.1.3,192.168.1.4"' \ -e 'PIHOLE_HOSTNAME="192.168.1.2,192.168.1.3,192.168.1.4"' \
-e "PIHOLE_API_TOKEN=$API_TOKEN1,$API_TOKEN2,$API_TOKEN3" \ -e "PIHOLE_API_TOKEN="$API_TOKEN1,$API_TOKEN2,$API_TOKEN3" \
-e "PIHOLE_PORT=8080,8081,8080" \ -e "PIHOLE_PORT="8080,8081,8080" \
-e 'INTERVAL=30s' \
-e 'PORT=9617' \ -e 'PORT=9617' \
-p 9617:9617 \
ekofr/pihole-exporter:latest ekofr/pihole-exporter:latest
``` ```
@ -95,12 +94,12 @@ If port, protocol and API token/password is the same for all instances, you can
``` ```
$ docker run \ $ docker run \
-e 'PIHOLE_PROTOCOL=http" \ -e 'PIHOLE_PROTOCOL=",http" \
-e 'PIHOLE_HOSTNAME=192.168.1.2,192.168.1.3,192.168.1.4"' \ -e 'PIHOLE_HOSTNAME="192.168.1.2,192.168.1.3,192.168.1.4"' \
-e "PIHOLE_API_TOKEN=$API_TOKEN" \ -e "PIHOLE_API_TOKEN="$API_TOKEN" \
-e "PIHOLE_PORT=8080" \ -e "PIHOLE_PORT="8080" \
-e 'INTERVAL=30s' \
-e 'PORT=9617' \ -e 'PORT=9617' \
-p 9617:9617 \
ekofr/pihole-exporter:latest ekofr/pihole-exporter:latest
``` ```
@ -108,7 +107,7 @@ $ docker run \
Optionally, you can download and build it from the sources. You have to retrieve the project sources by using one of the following way: Optionally, you can download and build it from the sources. You have to retrieve the project sources by using one of the following way:
```bash ```bash
$ go install github.com/eko/pihole-exporter@latest $ go get -u github.com/eko/pihole-exporter
# or # or
$ git clone https://github.com/eko/pihole-exporter.git $ git clone https://github.com/eko/pihole-exporter.git
``` ```
@ -143,12 +142,12 @@ $ ./pihole_exporter -pihole_hostname 192.168.1.10 -pihole_api_token $API_TOKEN
```bash ```bash
2019/05/09 20:19:52 ------------------------------------ 2019/05/09 20:19:52 ------------------------------------
2019/05/09 20:19:52 - Pi-hole exporter configuration - 2019/05/09 20:19:52 - PI-Hole exporter configuration -
2019/05/09 20:19:52 ------------------------------------ 2019/05/09 20:19:52 ------------------------------------
2019/05/09 20:19:52 PIHoleHostname : 192.168.1.10 2019/05/09 20:19:52 PIHoleHostname : 192.168.1.10
2019/05/09 20:19:52 PIHolePassword : azerty 2019/05/09 20:19:52 PIHolePassword : azerty
2019/05/09 20:19:52 Port : 9617 2019/05/09 20:19:52 Port : 9617
2019/05/09 20:19:52 Timeout : 5s 2019/05/09 20:19:52 Interval : 10s
2019/05/09 20:19:52 ------------------------------------ 2019/05/09 20:19:52 ------------------------------------
2019/05/09 20:19:52 New Prometheus metric registered: domains_blocked 2019/05/09 20:19:52 New Prometheus metric registered: domains_blocked
2019/05/09 20:19:52 New Prometheus metric registered: dns_queries_today 2019/05/09 20:19:52 New Prometheus metric registered: dns_queries_today
@ -183,21 +182,19 @@ scrape_configs:
## Available CLI options ## Available CLI options
```bash ```bash
# Hostname of the host(s) where Pi-hole is installed # Interval of time the exporter will fetch data from PI-Hole
-interval duration (optional) (default 10s)
# Hostname of the Raspberry PI where PI-Hole is installed
-pihole_hostname string (optional) (default "127.0.0.1") -pihole_hostname string (optional) (default "127.0.0.1")
# Password defined on the Pi-hole interface # Password defined on the PI-Hole interface
-pihole_password string (optional) -pihole_password string (optional)
# Timeout to connect and retrieve data from a Pi-hole instance
-timeout duration (optional) (default 5s)
# WEBPASSWORD / api token defined on the Pi-hole interface at `/etc/pihole/setupVars.conf` # WEBPASSWORD / api token defined on the PI-Hole interface at `/etc/pihole/setupVars.conf`
-pihole_api_token string (optional) -pihole_api_token string (optional)
# Address to be used for the exporter
-bind_addr string (optional) (default "0.0.0.0")
# Port to be used for the exporter # Port to be used for the exporter
-port string (optional) (default "9617") -port string (optional) (default "9617")
``` ```
@ -217,12 +214,12 @@ scrape_configs:
| pihole_unique_clients | This represent the number of unique clients seen | | pihole_unique_clients | This represent the number of unique clients seen |
| pihole_dns_queries_all_types | This represent the number of DNS queries made for all types | | pihole_dns_queries_all_types | This represent the number of DNS queries made for all types |
| pihole_reply | This represent the number of replies made for all types | | pihole_reply | This represent the number of replies made for all types |
| pihole_top_queries | This represent the number of top queries made by Pi-hole by domain | | pihole_top_queries | This represent the number of top queries made by PI-Hole by domain |
| pihole_top_ads | This represent the number of top ads made by Pi-hole by domain | | pihole_top_ads | This represent the number of top ads made by PI-Hole by domain |
| pihole_top_sources | This represent the number of top sources requests made by Pi-hole by source host | | pihole_top_sources | This represent the number of top sources requests made by PI-Hole by source host |
| pihole_forward_destinations | This represent the number of forward destinations requests made by Pi-hole by destination | | pihole_forward_destinations | This represent the number of forward destinations requests made by PI-Hole by destination |
| pihole_querytypes | This represent the number of queries made by Pi-hole by type | | pihole_querytypes | This represent the number of queries made by PI-Hole by type |
| pihole_status | This represent if Pi-hole is enabled | | pihole_status | This represent if PI-Hole is enabled |
## Pihole-Exporter Helm Chart ## Pihole-Exporter Helm Chart

View file

@ -4,13 +4,11 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"log"
"reflect" "reflect"
"runtime"
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/heetch/confita" "github.com/heetch/confita"
"github.com/heetch/confita/backend" "github.com/heetch/confita/backend"
"github.com/heetch/confita/backend/env" "github.com/heetch/confita/backend/env"
@ -24,8 +22,6 @@ type Config struct {
PIHolePort uint16 `config:"pihole_port"` PIHolePort uint16 `config:"pihole_port"`
PIHolePassword string `config:"pihole_password"` PIHolePassword string `config:"pihole_password"`
PIHoleApiToken string `config:"pihole_api_token"` PIHoleApiToken string `config:"pihole_api_token"`
BindAddr string `config:"bind_addr"`
Port uint16 `config:"port"`
} }
type EnvConfig struct { type EnvConfig struct {
@ -34,9 +30,8 @@ type EnvConfig struct {
PIHolePort []uint16 `config:"pihole_port"` PIHolePort []uint16 `config:"pihole_port"`
PIHolePassword []string `config:"pihole_password"` PIHolePassword []string `config:"pihole_password"`
PIHoleApiToken []string `config:"pihole_api_token"` PIHoleApiToken []string `config:"pihole_api_token"`
BindAddr string `config:"bind_addr"`
Port uint16 `config:"port"` Port uint16 `config:"port"`
Timeout time.Duration `config:"timeout"` Interval time.Duration `config:"interval"`
} }
func getDefaultEnvConfig() *EnvConfig { func getDefaultEnvConfig() *EnvConfig {
@ -46,9 +41,8 @@ func getDefaultEnvConfig() *EnvConfig {
PIHolePort: []uint16{80}, PIHolePort: []uint16{80},
PIHolePassword: []string{}, PIHolePassword: []string{},
PIHoleApiToken: []string{}, PIHoleApiToken: []string{},
BindAddr: "0.0.0.0",
Port: 9617, Port: 9617,
Timeout: 5 * time.Second, Interval: 10 * time.Second,
} }
} }
@ -84,14 +78,9 @@ func (c *Config) String() string {
for i := 0; i < fields.NumField(); i++ { for i := 0; i < fields.NumField(); i++ {
valueField := fields.Field(i) valueField := fields.Field(i)
typeField := fields.Type().Field(i) typeField := fields.Type().Field(i)
if typeField.Name != "PIHolePassword" && typeField.Name != "PIHoleApiToken" {
buffer[i] = fmt.Sprintf("%s=%v", typeField.Name, valueField.Interface()) buffer[i] = fmt.Sprintf("%s=%v", typeField.Name, valueField.Interface())
} else if valueField.Len() > 0 {
buffer[i] = fmt.Sprintf("%s=%s", typeField.Name, "*****")
}
} }
buffer = removeEmptyString(buffer)
return fmt.Sprintf("<Config@%X %s>", &c, strings.Join(buffer, ", ")) return fmt.Sprintf("<Config@%X %s>", &c, strings.Join(buffer, ", "))
} }
@ -163,16 +152,6 @@ func extractStringConfig(data []string, idx int, hostsCount int) (bool, string,
return false, "", true return false, "", true
} }
func removeEmptyString(source []string) []string {
var result []string
for _, s := range source {
if s != "" {
result = append(result, s)
}
}
return result
}
func (c Config) hostnameURL() string { func (c Config) hostnameURL() string {
s := fmt.Sprintf("%s://%s", c.PIHoleProtocol, c.PIHoleHostname) s := fmt.Sprintf("%s://%s", c.PIHoleProtocol, c.PIHoleHostname)
if c.PIHolePort != 0 { if c.PIHolePort != 0 {
@ -193,26 +172,25 @@ func (c Config) PIHoleLoginURL() string {
func (c EnvConfig) show() { func (c EnvConfig) show() {
val := reflect.ValueOf(&c).Elem() val := reflect.ValueOf(&c).Elem()
log.Info("------------------------------------") log.Println("------------------------------------")
log.Info("- Pi-hole exporter configuration -") log.Println("- PI-Hole exporter configuration -")
log.Info("------------------------------------") log.Println("------------------------------------")
log.Info("Go version: ", runtime.Version())
for i := 0; i < val.NumField(); i++ { for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i) valueField := val.Field(i)
typeField := val.Type().Field(i) typeField := val.Type().Field(i)
// Do not print password or api token but do print the authentication method // Do not print password or api token but do print the authentication method
if typeField.Name != "PIHolePassword" && typeField.Name != "PIHoleApiToken" { if typeField.Name != "PIHolePassword" && typeField.Name != "PIHoleApiToken" {
log.Info(fmt.Sprintf("%s : %v", typeField.Name, valueField.Interface())) log.Println(fmt.Sprintf("%s : %v", typeField.Name, valueField.Interface()))
} else { } else {
showAuthenticationMethod(typeField.Name, valueField.Len()) showAuthenticationMethod(typeField.Name, valueField.Len())
} }
} }
log.Info("------------------------------------") log.Println("------------------------------------")
} }
func showAuthenticationMethod(name string, length int) { func showAuthenticationMethod(name string, length int) {
if length > 0 { if length > 0 {
log.Info(fmt.Sprintf("Pi-hole Authentication Method : %s", name)) log.Println(fmt.Sprintf("Pi-Hole Authentication Method : %s", name))
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 KiB

25
go.mod
View file

@ -1,28 +1,11 @@
module github.com/eko/pihole-exporter module github.com/eko/pihole-exporter
go 1.20 go 1.15
require ( require (
github.com/heetch/confita v0.10.0 github.com/heetch/confita v0.10.0
github.com/prometheus/client_golang v1.17.0 github.com/prometheus/client_golang v1.11.0
github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.8.4
github.com/xonvanetta/shutdown v0.0.3 github.com/xonvanetta/shutdown v0.0.3
golang.org/x/net v0.16.0 golang.org/x/net v0.0.0-20200625001655-4c5254603344
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
golang.org/x/sys v0.13.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
) )

124
go.sum
View file

@ -1,19 +1,24 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
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-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/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 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-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 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 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@ -31,8 +36,12 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 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.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 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-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -42,15 +51,26 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 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.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.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 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/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.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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.8.6/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.8.6/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
@ -92,19 +112,26 @@ github.com/heetch/confita v0.10.0 h1:00V4eQPDU71v9nZD7N/DsSb9cnPJh59CjrpQPfln47A
github.com/heetch/confita v0.10.0/go.mod h1:W6GDCVPvi2LpvdEriwZTu2fyxuK+Grx1vY302gtWfvM= github.com/heetch/confita v0.10.0/go.mod h1:W6GDCVPvi2LpvdEriwZTu2fyxuK+Grx1vY302gtWfvM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 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/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.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 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/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.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/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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 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.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 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/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
@ -118,7 +145,12 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 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/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
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-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/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
@ -133,41 +165,47 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 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-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-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/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.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/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.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.0 h1:jlIyCplCJFULU/01vCkhKuTyc3OorI3bJFuw6obfgho=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@ -179,6 +217,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190506204251-e1dfcc566284/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/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-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-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -189,19 +228,24 @@ golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/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-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-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-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-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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 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-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-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-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-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-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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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-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-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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -212,18 +256,25 @@ golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190508220229-2d0786266e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-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-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-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
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= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -232,22 +283,31 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRn
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
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/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1 h1:7QnIQpGRHE5RnLKnESfDoxm2dTapTZua5a0kS0A+VXQ=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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-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/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 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.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.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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/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.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

File diff suppressed because it is too large Load diff

View file

@ -67,7 +67,7 @@
} }
] ]
}, },
"description": "This is a Pi-hole dashboard when using the https://github.com/eko/pihole-exporter Prometheus exporter", "description": "This is a PI-Hole dashboard when using the https://github.com/eko/pihole-exporter Prometheus exporter",
"editable": true, "editable": true,
"gnetId": 10176, "gnetId": 10176,
"graphTooltip": 0, "graphTooltip": 0,
@ -86,7 +86,7 @@
}, },
"id": 60, "id": 60,
"panels": [], "panels": [],
"title": "🥧🕳️ Pi-hole", "title": "🍓PI-Hole",
"type": "row" "type": "row"
}, },
{ {
@ -1522,7 +1522,7 @@
] ]
}, },
"timezone": "", "timezone": "",
"title": "Pi-hole Exporter", "title": "PI-Hole Exporter",
"uid": "Pi-hole-Exporter", "uid": "PI-Hole-Exporter",
"version": 31 "version": 31
} }

View file

@ -1,12 +1,13 @@
package metrics package metrics
import ( import (
"log"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
) )
var ( var (
// DomainsBlocked - The number of domains being blocked by Pi-hole. // DomainsBlocked - The number of domains being blocked by PI-Hole.
DomainsBlocked = prometheus.NewGaugeVec( DomainsBlocked = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "domains_being_blocked", Name: "domains_being_blocked",
@ -16,7 +17,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// DNSQueriesToday - The number of DNS requests made over Pi-hole over the current day. // DNSQueriesToday - The number of DNS requests made over PI-Hole over the current day.
DNSQueriesToday = prometheus.NewGaugeVec( DNSQueriesToday = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "dns_queries_today", Name: "dns_queries_today",
@ -26,7 +27,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// AdsBlockedToday - The number of ads blocked by Pi-hole over the current day. // AdsBlockedToday - The number of ads blocked by PI-Hole over the current day.
AdsBlockedToday = prometheus.NewGaugeVec( AdsBlockedToday = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "ads_blocked_today", Name: "ads_blocked_today",
@ -36,7 +37,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// AdsPercentageToday - The percentage of ads blocked by Pi-hole over the current day. // AdsPercentageToday - The percentage of ads blocked by PI-Hole over the current day.
AdsPercentageToday = prometheus.NewGaugeVec( AdsPercentageToday = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "ads_percentage_today", Name: "ads_percentage_today",
@ -46,7 +47,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// UniqueDomains - The number of unique domains seen by Pi-hole. // UniqueDomains - The number of unique domains seen by PI-Hole.
UniqueDomains = prometheus.NewGaugeVec( UniqueDomains = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "unique_domains", Name: "unique_domains",
@ -56,7 +57,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// QueriesForwarded - The number of queries forwarded by Pi-hole. // QueriesForwarded - The number of queries forwarded by PI-Hole.
QueriesForwarded = prometheus.NewGaugeVec( QueriesForwarded = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "queries_forwarded", Name: "queries_forwarded",
@ -66,7 +67,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// QueriesCached - The number of queries cached by Pi-hole. // QueriesCached - The number of queries cached by PI-Hole.
QueriesCached = prometheus.NewGaugeVec( QueriesCached = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "queries_cached", Name: "queries_cached",
@ -76,7 +77,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// ClientsEverSeen - The number of clients ever seen by Pi-hole. // ClientsEverSeen - The number of clients ever seen by PI-Hole.
ClientsEverSeen = prometheus.NewGaugeVec( ClientsEverSeen = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "clients_ever_seen", Name: "clients_ever_seen",
@ -86,7 +87,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// UniqueClients - The number of unique clients seen by Pi-hole. // UniqueClients - The number of unique clients seen by PI-Hole.
UniqueClients = prometheus.NewGaugeVec( UniqueClients = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "unique_clients", Name: "unique_clients",
@ -96,7 +97,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// DNSQueriesAllTypes - The number of DNS queries made for all types by Pi-hole. // DNSQueriesAllTypes - The number of DNS queries made for all types by PI-Hole.
DNSQueriesAllTypes = prometheus.NewGaugeVec( DNSQueriesAllTypes = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "dns_queries_all_types", Name: "dns_queries_all_types",
@ -106,7 +107,7 @@ var (
[]string{"hostname"}, []string{"hostname"},
) )
// Reply - The number of replies made for every types by Pi-hole. // Reply - The number of replies made for every types by PI-Hole.
Reply = prometheus.NewGaugeVec( Reply = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "reply", Name: "reply",
@ -116,68 +117,68 @@ var (
[]string{"hostname", "type"}, []string{"hostname", "type"},
) )
// TopQueries - The number of top queries made by Pi-hole by domain. // TopQueries - The number of top queries made by PI-Hole by domain.
TopQueries = prometheus.NewGaugeVec( TopQueries = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "top_queries", Name: "top_queries",
Namespace: "pihole", Namespace: "pihole",
Help: "This represent the number of top queries made by Pi-hole by domain", Help: "This represent the number of top queries made by PI-Hole by domain",
}, },
[]string{"hostname", "domain"}, []string{"hostname", "domain"},
) )
// TopAds - The number of top ads made by Pi-hole by domain. // TopAds - The number of top ads made by PI-Hole by domain.
TopAds = prometheus.NewGaugeVec( TopAds = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "top_ads", Name: "top_ads",
Namespace: "pihole", Namespace: "pihole",
Help: "This represent the number of top ads made by Pi-hole by domain", Help: "This represent the number of top ads made by PI-Hole by domain",
}, },
[]string{"hostname", "domain"}, []string{"hostname", "domain"},
) )
// TopSources - The number of top sources requests made by Pi-hole by source host. // TopSources - The number of top sources requests made by PI-Hole by source host.
TopSources = prometheus.NewGaugeVec( TopSources = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "top_sources", Name: "top_sources",
Namespace: "pihole", Namespace: "pihole",
Help: "This represent the number of top sources requests made by Pi-hole by source host", Help: "This represent the number of top sources requests made by PI-Hole by source host",
}, },
[]string{"hostname", "source"}, []string{"hostname", "source"},
) )
// ForwardDestinations - The number of forward destinations requests made by Pi-hole by destination. // ForwardDestinations - The number of forward destinations requests made by PI-Hole by destination.
ForwardDestinations = prometheus.NewGaugeVec( ForwardDestinations = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "forward_destinations", Name: "forward_destinations",
Namespace: "pihole", Namespace: "pihole",
Help: "This represent the number of forward destinations requests made by Pi-hole by destination", Help: "This represent the number of forward destinations requests made by PI-Hole by destination",
}, },
[]string{"hostname", "destination"}, []string{"hostname", "destination"},
) )
// QueryTypes - The number of queries made by Pi-hole by type. // QueryTypes - The number of queries made by PI-Hole by type.
QueryTypes = prometheus.NewGaugeVec( QueryTypes = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "querytypes", Name: "querytypes",
Namespace: "pihole", Namespace: "pihole",
Help: "This represent the number of queries made by Pi-hole by type", Help: "This represent the number of queries made by PI-Hole by type",
}, },
[]string{"hostname", "type"}, []string{"hostname", "type"},
) )
// Status - Is Pi-hole enabled? // Status - Is PI-Hole enabled?
Status = prometheus.NewGaugeVec( Status = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "status", Name: "status",
Namespace: "pihole", Namespace: "pihole",
Help: "This if Pi-hole is enabled", Help: "This if PI-Hole is enabled",
}, },
[]string{"hostname"}, []string{"hostname"},
) )
) )
// Init initializes all Prometheus metrics made available by Pi-hole exporter. // Init initializes all Prometheus metrics made available by PI-Hole exporter.
func Init() { func Init() {
initMetric("domains_blocked", DomainsBlocked) initMetric("domains_blocked", DomainsBlocked)
initMetric("dns_queries_today", DNSQueriesToday) initMetric("dns_queries_today", DNSQueriesToday)
@ -200,5 +201,5 @@ func Init() {
func initMetric(name string, metric *prometheus.GaugeVec) { func initMetric(name string, metric *prometheus.GaugeVec) {
prometheus.MustRegister(metric) prometheus.MustRegister(metric)
log.Info("New Prometheus metric registered: ", name) log.Printf("New Prometheus metric registered: %s", name)
} }

View file

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
@ -11,55 +12,26 @@ import (
"strings" "strings"
"time" "time"
log "github.com/sirupsen/logrus"
"github.com/eko/pihole-exporter/config" "github.com/eko/pihole-exporter/config"
"github.com/eko/pihole-exporter/internal/metrics" "github.com/eko/pihole-exporter/internal/metrics"
) )
type ClientStatus byte // Client struct is a PI-Hole client to request an instance of a PI-Hole ad blocker.
const (
MetricsCollectionInProgress ClientStatus = iota
MetricsCollectionSuccess
MetricsCollectionError
MetricsCollectionTimeout
)
func (status ClientStatus) String() string {
return []string{"MetricsCollectionInProgress", "MetricsCollectionSuccess", "MetricsCollectionError", "MetricsCollectionTimeout"}[status]
}
type ClientChannel struct {
Status ClientStatus
Err error
}
func (c *ClientChannel) String() string {
if c.Err != nil {
return fmt.Sprintf("ClientChannel<Status: %s, Err: '%s'>", c.Status, c.Err.Error())
} else {
return fmt.Sprintf("ClientChannel<Status: %s, Err: <nil>>", c.Status)
}
}
// Client struct is a Pi-hole client to request an instance of a Pi-hole ad blocker.
type Client struct { type Client struct {
httpClient http.Client httpClient http.Client
interval time.Duration interval time.Duration
config *config.Config config *config.Config
Status chan *ClientChannel
} }
// NewClient method initializes a new Pi-hole client. // NewClient method initializes a new PI-Hole client.
func NewClient(config *config.Config, envConfig *config.EnvConfig) *Client { func NewClient(config *config.Config) *Client {
err := config.Validate() err := config.Validate()
if err != nil { if err != nil {
log.Error(err) log.Print(err)
os.Exit(1) os.Exit(1)
} }
log.Printf("Creating client with config %s\n", config) fmt.Printf("Creating client with config %s\n", config)
return &Client{ return &Client{
config: config, config: config,
@ -67,9 +39,7 @@ func NewClient(config *config.Config, envConfig *config.EnvConfig) *Client {
CheckRedirect: func(req *http.Request, via []*http.Request) error { CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse return http.ErrUseLastResponse
}, },
Timeout: envConfig.Timeout,
}, },
Status: make(chan *ClientChannel, 1),
} }
} }
@ -77,24 +47,32 @@ func (c *Client) String() string {
return c.config.PIHoleHostname return c.config.PIHoleHostname
} }
func (c *Client) CollectMetricsAsync(writer http.ResponseWriter, request *http.Request) { /*
log.Printf("Collecting from %s", c.config.PIHoleHostname) // Metrics scrapes pihole and sets them
if stats, err := c.getStatistics(); err == nil { func (c *Client) Metrics() http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
stats, err := c.getStatistics()
if err != nil {
writer.WriteHeader(http.StatusBadRequest)
_, _ = writer.Write([]byte(err.Error()))
return
}
c.setMetrics(stats) c.setMetrics(stats)
c.Status <- &ClientChannel{Status: MetricsCollectionSuccess, Err: nil}
log.Printf("New tick of statistics from %s: %s", c.config.PIHoleHostname, stats) log.Printf("New tick of statistics: %s", stats.ToString())
} else { promhttp.Handler().ServeHTTP(writer, request)
c.Status <- &ClientChannel{Status: MetricsCollectionError, Err: err}
}
} }
}*/
func (c *Client) CollectMetrics(writer http.ResponseWriter, request *http.Request) error { func (c *Client) CollectMetrics(writer http.ResponseWriter, request *http.Request) error {
stats, err := c.getStatistics() stats, err := c.getStatistics()
if err != nil { if err != nil {
return err return err
} }
c.setMetrics(stats) c.setMetrics(stats)
log.Printf("New tick of statistics from %s: %s", c.config.PIHoleHostname, stats)
log.Printf("New tick of statistics from %s: %s", c, stats)
return nil return nil
} }
@ -114,20 +92,10 @@ func (c *Client) setMetrics(stats *Stats) {
metrics.UniqueClients.WithLabelValues(c.config.PIHoleHostname).Set(float64(stats.UniqueClients)) metrics.UniqueClients.WithLabelValues(c.config.PIHoleHostname).Set(float64(stats.UniqueClients))
metrics.DNSQueriesAllTypes.WithLabelValues(c.config.PIHoleHostname).Set(float64(stats.DNSQueriesAllTypes)) metrics.DNSQueriesAllTypes.WithLabelValues(c.config.PIHoleHostname).Set(float64(stats.DNSQueriesAllTypes))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "unknown").Set(float64(stats.ReplyUnknown))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "no_data").Set(float64(stats.ReplyNoData)) metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "no_data").Set(float64(stats.ReplyNoData))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "nx_domain").Set(float64(stats.ReplyNxDomain)) metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "nx_domain").Set(float64(stats.ReplyNxDomain))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "cname").Set(float64(stats.ReplyCname)) metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "cname").Set(float64(stats.ReplyCname))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "ip").Set(float64(stats.ReplyIP)) metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "ip").Set(float64(stats.ReplyIP))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "domain").Set(float64(stats.ReplyDomain))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "rr_name").Set(float64(stats.ReplyRRName))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "serv_fail").Set(float64(stats.ReplyServFail))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "refused").Set(float64(stats.ReplyRefused))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "not_imp").Set(float64(stats.ReplyNotImp))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "other").Set(float64(stats.ReplyOther))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "dnssec").Set(float64(stats.ReplyDNSSEC))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "none").Set(float64(stats.ReplyNone))
metrics.Reply.WithLabelValues(c.config.PIHoleHostname, "blob").Set(float64(stats.ReplyBlob))
var isEnabled int = 0 var isEnabled int = 0
if stats.Status == enabledStatus { if stats.Status == enabledStatus {
@ -135,12 +103,6 @@ func (c *Client) setMetrics(stats *Stats) {
} }
metrics.Status.WithLabelValues(c.config.PIHoleHostname).Set(float64(isEnabled)) metrics.Status.WithLabelValues(c.config.PIHoleHostname).Set(float64(isEnabled))
// Pi-hole returns a subset of stats when Auth is missing or incorrect.
// This provides a warning to users that metrics are not complete.
if len(stats.TopQueries) == 0 {
log.Warnf("Invalid Authentication - Some metrics may be missing. Please confirm your Pi-hole API token / Password for %s", c.config.PIHoleHostname)
}
for domain, value := range stats.TopQueries { for domain, value := range stats.TopQueries {
metrics.TopQueries.WithLabelValues(c.config.PIHoleHostname, domain).Set(float64(value)) metrics.TopQueries.WithLabelValues(c.config.PIHoleHostname, domain).Set(float64(value))
} }
@ -175,7 +137,7 @@ func (c *Client) getPHPSessionID() (sessionID string) {
resp, err := c.httpClient.Do(req) resp, err := c.httpClient.Do(req)
if err != nil { if err != nil {
log.Errorf("An error has occured during login to Pi-hole: %v", err) log.Printf("An error has occured during login to PI-Hole: %v", err)
} }
for _, cookie := range resp.Cookies() { for _, cookie := range resp.Cookies() {
@ -208,18 +170,17 @@ func (c *Client) getStatistics() (*Stats, error) {
resp, err := c.httpClient.Do(req) resp, err := c.httpClient.Do(req)
if err != nil { if err != nil {
return nil, fmt.Errorf("an error has occured during retrieving Pi-hole statistics: %w", err) return nil, fmt.Errorf("an error has occured during retrieving PI-Hole statistics: %w", err)
} }
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to read Pi-hole statistics HTTP response: %w", err) return nil, fmt.Errorf("unable to read PI-Hole statistics HTTP response: %w", err)
} }
err = json.Unmarshal(body, stats) err = json.Unmarshal(body, stats)
if err != nil { if err != nil {
return nil, fmt.Errorf("unable to unmarshal Pi-hole statistics to statistics struct model: %w", err) return nil, fmt.Errorf("unable to unmarshal PI-Hole statistics to statistics struct model: %w", err)
} }
return stats, nil return stats, nil

View file

@ -6,7 +6,7 @@ const (
enabledStatus = "enabled" enabledStatus = "enabled"
) )
// Stats struct is the Pi-hole statistics JSON API corresponding model. // Stats struct is the PI-Hole statistics JSON API corresponding model.
type Stats struct { type Stats struct {
DomainsBeingBlocked int `json:"domains_being_blocked"` DomainsBeingBlocked int `json:"domains_being_blocked"`
DNSQueriesToday int `json:"dns_queries_today"` DNSQueriesToday int `json:"dns_queries_today"`
@ -18,20 +18,10 @@ type Stats struct {
ClientsEverSeen int `json:"clients_ever_seen"` ClientsEverSeen int `json:"clients_ever_seen"`
UniqueClients int `json:"unique_clients"` UniqueClients int `json:"unique_clients"`
DNSQueriesAllTypes int `json:"dns_queries_all_types"` DNSQueriesAllTypes int `json:"dns_queries_all_types"`
ReplyUnknown int `json:"reply_UNKNOWN"`
ReplyNoData int `json:"reply_NODATA"` ReplyNoData int `json:"reply_NODATA"`
ReplyNxDomain int `json:"reply_NXDOMAIN"` ReplyNxDomain int `json:"reply_NXDOMAIN"`
ReplyCname int `json:"reply_CNAME"` ReplyCname int `json:"reply_CNAME"`
ReplyIP int `json:"reply_IP"` ReplyIP int `json:"reply_IP"`
ReplyDomain int `json:"reply_DOMAIN"`
ReplyRRName int `json:"reply_RRNAME"`
ReplyServFail int `json:"reply_SERVFAIL"`
ReplyRefused int `json:"reply_REFUSED"`
ReplyNotImp int `json:"reply_NOTIMP"`
ReplyOther int `json:"reply_OTHER"`
ReplyDNSSEC int `json:"reply_DNSSEC"`
ReplyNone int `json:"reply_NONE"`
ReplyBlob int `json:"reply_BLOB"`
TopQueries map[string]int `json:"top_queries"` TopQueries map[string]int `json:"top_queries"`
TopAds map[string]int `json:"top_ads"` TopAds map[string]int `json:"top_ads"`
TopSources map[string]int `json:"top_sources"` TopSources map[string]int `json:"top_sources"`

View file

@ -2,6 +2,7 @@ package server
import ( import (
"fmt" "fmt"
"log"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
@ -9,7 +10,6 @@ import (
"github.com/eko/pihole-exporter/internal/pihole" "github.com/eko/pihole-exporter/internal/pihole"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
@ -20,33 +20,34 @@ type Server struct {
// NewServer method initializes a new HTTP server instance and associates // NewServer method initializes a new HTTP server instance and associates
// the different routes that will be used by Prometheus (metrics) or for monitoring (readiness, liveness). // the different routes that will be used by Prometheus (metrics) or for monitoring (readiness, liveness).
func NewServer(addr string, port uint16, clients []*pihole.Client) *Server { func NewServer(port uint16, clients []*pihole.Client) *Server {
mux := http.NewServeMux() mux := http.NewServeMux()
httpServer := &http.Server{ httpServer := &http.Server{Addr: ":" + strconv.Itoa(int(port)), Handler: mux}
Addr: addr + ":" + strconv.Itoa(int(port)),
Handler: mux,
}
s := &Server{ s := &Server{
httpServer: httpServer, httpServer: httpServer,
} }
mux.HandleFunc("/metrics", func(writer http.ResponseWriter, request *http.Request) { mux.HandleFunc("/metrics",
log.Printf("request.Header: %v\n", request.Header) func(writer http.ResponseWriter, request *http.Request) {
errors := make([]string, 0)
for _, client := range clients { for _, client := range clients {
go client.CollectMetricsAsync(writer, request) if err := client.CollectMetrics(writer, request); err != nil {
errors = append(errors, err.Error())
fmt.Printf("Error %s\n", err)
}
} }
for _, client := range clients { if len(errors) == len(clients) {
status := <-client.Status writer.WriteHeader(http.StatusBadRequest)
if status.Status == pihole.MetricsCollectionError { body := strings.Join(errors, "\n")
log.Printf("An error occured while contacting %s: %s", client.GetHostname(), status.Err.Error()) _, _ = writer.Write([]byte(body))
}
} }
promhttp.Handler().ServeHTTP(writer, request) promhttp.Handler().ServeHTTP(writer, request)
}) },
)
mux.Handle("/readiness", s.readinessHandler()) mux.Handle("/readiness", s.readinessHandler())
mux.Handle("/liveness", s.livenessHandler()) mux.Handle("/liveness", s.livenessHandler())
@ -72,27 +73,6 @@ func (s *Server) Stop() {
s.httpServer.Shutdown(ctx) s.httpServer.Shutdown(ctx)
} }
func (s *Server) handleMetrics(clients []*pihole.Client) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
errors := make([]string, 0)
for _, client := range clients {
if err := client.CollectMetrics(writer, request); err != nil {
errors = append(errors, err.Error())
fmt.Printf("Error %s\n", err)
}
}
if len(errors) == len(clients) {
writer.WriteHeader(http.StatusBadRequest)
body := strings.Join(errors, "\n")
_, _ = writer.Write([]byte(body))
}
promhttp.Handler().ServeHTTP(writer, request)
}
}
func (s *Server) readinessHandler() http.HandlerFunc { func (s *Server) readinessHandler() http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) { return func(w http.ResponseWriter, req *http.Request) {
if s.isReady() { if s.isReady() {

11
main.go
View file

@ -1,6 +1,7 @@
package main package main
import ( import (
"fmt"
"log" "log"
"github.com/eko/pihole-exporter/config" "github.com/eko/pihole-exporter/config"
@ -20,9 +21,9 @@ func main() {
serverDead := make(chan struct{}) serverDead := make(chan struct{})
clients := buildClients(clientConfigs, envConf) clients := buildClients(clientConfigs)
s := server.NewServer(envConf.BindAddr, envConf.Port, clients) s := server.NewServer(envConf.Port, clients)
go func() { go func() {
s.ListenAndServe() s.ListenAndServe()
close(serverDead) close(serverDead)
@ -40,15 +41,15 @@ func main() {
case <-serverDead: case <-serverDead:
} }
log.Println("pihole-exporter HTTP server stopped") fmt.Println("pihole-exporter HTTP server stopped")
} }
func buildClients(clientConfigs []config.Config, envConfig *config.EnvConfig) []*pihole.Client { func buildClients(clientConfigs []config.Config) []*pihole.Client {
clients := make([]*pihole.Client, 0, len(clientConfigs)) clients := make([]*pihole.Client, 0, len(clientConfigs))
for i := range clientConfigs { for i := range clientConfigs {
clientConfig := &clientConfigs[i] clientConfig := &clientConfigs[i]
client := pihole.NewClient(clientConfig, envConfig) client := pihole.NewClient(clientConfig)
clients = append(clients, client) clients = append(clients, client)
} }
return clients return clients