Compare commits
1 Commits
v2023.7.1-
...
feat/docke
Author | SHA1 | Date | |
---|---|---|---|
62c48d2388 |
@ -1,9 +0,0 @@
|
|||||||
/admin-key.json
|
|
||||||
/config.yml
|
|
||||||
/tools
|
|
||||||
/out
|
|
||||||
/dist
|
|
||||||
/data
|
|
||||||
/bin
|
|
||||||
/.bouncer-token
|
|
||||||
/.env
|
|
18
Dockerfile
18
Dockerfile
@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.20 AS BUILD
|
FROM reg.cadoles.com/proxy_cache/library/golang:1.21.6 AS BUILD
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y make
|
&& apt-get install -y make
|
||||||
@ -9,7 +9,7 @@ WORKDIR /src
|
|||||||
|
|
||||||
RUN make GORELEASER_ARGS='build --rm-dist --single-target --snapshot' goreleaser
|
RUN make GORELEASER_ARGS='build --rm-dist --single-target --snapshot' goreleaser
|
||||||
|
|
||||||
FROM busybox:latest AS RUNTIME
|
FROM reg.cadoles.com/proxy_cache/library/busybox:latest AS RUNTIME
|
||||||
|
|
||||||
ARG DUMB_INIT_VERSION=1.2.5
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
|
|
||||||
@ -19,18 +19,12 @@ RUN mkdir -p /usr/local/bin \
|
|||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
|
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
|
||||||
|
|
||||||
RUN mkdir -p /usr/local/bin /usr/share/bouncer/bin /etc/bouncer
|
COPY --from=BUILD /src/dist/bouncer_linux_amd64_v1 /app
|
||||||
|
COPY --from=BUILD /src/config.yml /etc/bouncer/config.yml
|
||||||
COPY --from=BUILD /src/dist/bouncer_linux_amd64_v1/bouncer /usr/share/bouncer/bin/bouncer
|
|
||||||
COPY --from=BUILD /src/layers /usr/share/bouncer/
|
|
||||||
|
|
||||||
RUN ln -s /usr/share/bouncer/bin/bouncer /usr/local/bin/bouncer \
|
|
||||||
&& /usr/share/bouncer/bin/bouncer -c '' config dump > /etc/bouncer/config.yml
|
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
EXPOSE 8081
|
EXPOSE 8081
|
||||||
|
|
||||||
ENV BOUNCER_WORKDIR=/usr/share/bouncer
|
ENTRYPOINT ["/app/bouncer"]
|
||||||
ENV BOUNCER_CONFIG=/etc/bouncer/config.yml
|
|
||||||
|
|
||||||
CMD ["bouncer"]
|
CMD ["bouncer", "run", "-c", "/etc/bouncer/config.yml"]
|
||||||
|
21
Makefile
21
Makefile
@ -5,11 +5,11 @@ GITCHLOG_ARGS ?=
|
|||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
|
|
||||||
BOUNCER_VERSION ?=
|
BOUNCER_VERSION ?=
|
||||||
GIT_COMMIT := $(shell git rev-parse --short HEAD)
|
GIT_VERSION := $(shell git describe --always)
|
||||||
DATE_VERSION := $(shell date +%Y.%-m.%-d)
|
DATE_VERSION := $(shell date +%Y.%-m.%-d)
|
||||||
FULL_VERSION := v$(DATE_VERSION)-$(GIT_COMMIT)$(if $(shell git diff --stat),-dirty,)
|
FULL_VERSION := v$(DATE_VERSION)-$(GIT_VERSION)$(if $(shell git diff --stat),-dirty,)
|
||||||
|
|
||||||
DOCKER_IMAGE_NAME ?= reg.cadoles.com/cadoles/bouncer
|
DOCKER_IMAGE_NAME ?= cadoles/bouncer
|
||||||
DOCKER_IMAGE_TAG ?= $(FULL_VERSION)
|
DOCKER_IMAGE_TAG ?= $(FULL_VERSION)
|
||||||
|
|
||||||
GOTEST_ARGS ?= -short
|
GOTEST_ARGS ?= -short
|
||||||
@ -25,6 +25,16 @@ test: test-go ## Executing tests
|
|||||||
test-go: deps
|
test-go: deps
|
||||||
( set -o allexport && source .env && set +o allexport && go test -v -count=1 $(GOTEST_ARGS) ./... )
|
( set -o allexport && source .env && set +o allexport && go test -v -count=1 $(GOTEST_ARGS) ./... )
|
||||||
|
|
||||||
|
test-install-script: tools/bin/bash_unit
|
||||||
|
tools/bin/bash_unit ./misc/script/test_install.sh
|
||||||
|
|
||||||
|
tools/bin/bash_unit:
|
||||||
|
mkdir -p tools/bin
|
||||||
|
cd tools/bin && bash <(curl -s https://raw.githubusercontent.com/pgrange/bash_unit/master/install.sh)
|
||||||
|
|
||||||
|
lint: ## Lint sources code
|
||||||
|
golangci-lint run --enable-all $(LINT_ARGS)
|
||||||
|
|
||||||
build: build-bouncer ## Build artefacts
|
build: build-bouncer ## Build artefacts
|
||||||
|
|
||||||
build-bouncer: deps ## Build executable
|
build-bouncer: deps ## Build executable
|
||||||
@ -73,6 +83,9 @@ finish-release:
|
|||||||
git push --all
|
git push --all
|
||||||
git push --tags
|
git push --tags
|
||||||
|
|
||||||
|
install-git-hooks:
|
||||||
|
git config core.hooksPath .githooks
|
||||||
|
|
||||||
docker-build:
|
docker-build:
|
||||||
docker build -t $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) .
|
docker build -t $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) .
|
||||||
|
|
||||||
@ -93,7 +106,7 @@ gitea-release: tools/gitea-release/bin/gitea-release.sh goreleaser
|
|||||||
GITEA_RELEASE_BASE_URL="https://forge.cadoles.com" \
|
GITEA_RELEASE_BASE_URL="https://forge.cadoles.com" \
|
||||||
GITEA_RELEASE_VERSION="$(FULL_VERSION)" \
|
GITEA_RELEASE_VERSION="$(FULL_VERSION)" \
|
||||||
GITEA_RELEASE_NAME="$(FULL_VERSION)" \
|
GITEA_RELEASE_NAME="$(FULL_VERSION)" \
|
||||||
GITEA_RELEASE_COMMITISH_TARGET="$(GIT_COMMIT)" \
|
GITEA_RELEASE_COMMITISH_TARGET="$(GIT_VERSION)" \
|
||||||
GITEA_RELEASE_IS_DRAFT="false" \
|
GITEA_RELEASE_IS_DRAFT="false" \
|
||||||
GITEA_RELEASE_BODY="" \
|
GITEA_RELEASE_BODY="" \
|
||||||
GITEA_RELEASE_ATTACHMENTS="$$(find .gitea-release/* -type f)" \
|
GITEA_RELEASE_ATTACHMENTS="$$(find .gitea-release/* -type f)" \
|
||||||
|
@ -16,5 +16,4 @@
|
|||||||
|
|
||||||
### Développement
|
### Développement
|
||||||
|
|
||||||
- [(FR) - Démarrer avec les sources](./fr/tutorials/getting-start-with-sources.md)
|
|
||||||
- [(FR) - Créer son propre layer](./fr/tutorials/create-custom-layer.md)
|
- [(FR) - Créer son propre layer](./fr/tutorials/create-custom-layer.md)
|
@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
Vous trouverez ci-dessous la liste des entités "Layer" activables sur vos entité "Proxy":
|
Vous trouverez ci-dessous la liste des entités "Layer" activables sur vos entité "Proxy":
|
||||||
|
|
||||||
- [Queue](./queue.md) - File d'attente dynamique
|
- [Queue](./queue) - File d'attente dynamique
|
@ -24,4 +24,4 @@ Ce layer permet d'ajouter un mécanisme de file d'attente dynamique au proxy ass
|
|||||||
|
|
||||||
### Schéma
|
### Schéma
|
||||||
|
|
||||||
Voir le [schéma JSON](../../../../internal/proxy/director/layer/queue/schema/layer-options.json).
|
Voir le [schéma JSON](../../../../internal/queue/schema/layer-options.json).
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Étapes
|
## Étapes
|
||||||
|
|
||||||
1. Sur le serveur hébergeant les services Bouncer, utiliser le CLI pour créer un nouveau layer pour votre proxy. Dans l'exemple, nous utiliserons le proxy `cadoles` créé dans le cadre du tutoriels ["Premiers pas"](../getting-started.md).
|
1. Sur le serveur hébergeant les services Bouncer, utiliser le CLI pour créer un nouveau calque ("layer") pour votre proxy. Dans l'exemple, nous utiliserons le proxy `cadoles` créé dans le cadre du tutoriels ["Premiers pas"](../getting-started.md).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Création d'un calque nommé 'my-queue' pour le proxy 'cadoles' de type 'queue'
|
# Création d'un calque nommé 'my-queue' pour le proxy 'cadoles' de type 'queue'
|
||||||
@ -19,7 +19,7 @@
|
|||||||
+----------+-------+---------+--------+---------+-------------------------+-------------------------+
|
+----------+-------+---------+--------+---------+-------------------------+-------------------------+
|
||||||
```
|
```
|
||||||
|
|
||||||
2. À ce stade, le layer est encore inactif. Définir la capacité de la file d'attente à 1 et activer le layer en utilisant le CLI:
|
2. À ce stade, le calque est encore inactif. Définir la capacité de la file d'attente à 1 et activer le calque en utilisant le CLI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bouncer admin layer update --proxy-name cadoles --layer-name my-queue --layer-enabled=true --layer-options '{"capacity": 1}'
|
bouncer admin layer update --proxy-name cadoles --layer-name my-queue --layer-enabled=true --layer-options '{"capacity": 1}'
|
||||||
|
@ -1,11 +1,64 @@
|
|||||||
# Créer son propre layer
|
# Créer son propre layer
|
||||||
|
|
||||||
Dans ce tutoriel, nous verrons comment implémenter un layer personnalisé qui permettra d'ajouter une authentification de type [`Basic Auth](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) à un proxy.
|
Dans ce tutoriel, nous allons voir comme implémenter un layer personnalisé qui permettra d'ajouter une authentification de type [`Basic Auth](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication) à un proxy.
|
||||||
|
|
||||||
## Prérequis
|
## Prérequis
|
||||||
|
|
||||||
Avoir un environnement de développement local fonctionnel. Voir tutoriel ["Démarrer avec les sources"](./getting-started-with-sources.md).
|
Les éléments suivants doivent être installés sur votre machine:
|
||||||
|
|
||||||
|
- [Golang > 1.20](https://go.dev/)
|
||||||
|
- [Docker](https://www.docker.com/)
|
||||||
|
- [Git](https://git-scm.com/)
|
||||||
|
- [GNU Make](https://www.gnu.org/software/make/)
|
||||||
|
|
||||||
## Étapes
|
## Étapes
|
||||||
|
|
||||||
|
### Préparer son environnement de développement
|
||||||
|
|
||||||
|
1. Cloner le dépôt des sources du projet Bouncer
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://forge.cadoles.com/Cadoles/bouncer
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Se positionner dans le répertoire du projet
|
||||||
|
|
||||||
|
```
|
||||||
|
cd bouncer
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Lancer le projet en mode "développement"
|
||||||
|
|
||||||
|
```
|
||||||
|
make watch
|
||||||
|
```
|
||||||
|
|
||||||
|
Si toutes les dépendances sont correctement installées et configurées sur votre machine, la console devrait afficher une série de messages pour ensuite s'arrêter sur quelque chose ressemblant à:
|
||||||
|
|
||||||
|
```
|
||||||
|
14:47:06: daemon: make run BOUNCER_CMD="--config config.yml server admin run"
|
||||||
|
2023-06-23 20:47:06.095 [INFO] <./internal/command/server/admin/run.go:42> RunCommand.func1 listening {"url": "http://127.0.0.1:8081"}
|
||||||
|
2023-06-23 20:47:06.095 [INFO] <./internal/admin/server.go:126> (*Server).run http server listening
|
||||||
|
14:47:06: daemon: make run-redis
|
||||||
|
bouncer-redis
|
||||||
|
docker run --rm -t \
|
||||||
|
--name bouncer-redis \
|
||||||
|
-v /home/wpetit/workspace/bouncer/data/redis:/data \
|
||||||
|
-p 6379:6379 \
|
||||||
|
redis:alpine3.17 \
|
||||||
|
redis-server --save 60 1 --loglevel warning
|
||||||
|
1:C 23 Jun 2023 20:47:06.754 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
|
||||||
|
1:C 23 Jun 2023 20:47:06.754 # Redis version=7.0.11, bits=64, commit=00000000, modified=0, pid=1, just started
|
||||||
|
1:C 23 Jun 2023 20:47:06.754 # Configuration loaded
|
||||||
|
1:M 23 Jun 2023 20:47:06.759 # Warning: Could not create server TCP listening socket ::*:6379: unable to bind socket, errno: 97
|
||||||
|
1:M 23 Jun 2023 20:47:06.760 # Server initialized
|
||||||
|
1:M 23 Jun 2023 20:47:06.760 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect
|
||||||
|
```
|
||||||
|
|
||||||
|
À ce stade, le serveur `bouncer-admin` écoute sur http://127.0.0.1:8081 et le serveur `bouncer-proxy` sur http://127.0.0.1:8080.
|
||||||
|
|
||||||
|
L'outil [`modd`](https://github.com/cortesi/modd) est utilisé pour surveiller les modifications sur les sources et relancer automatiquement la compilation et les services en cas de changement.
|
||||||
|
|
||||||
### Préparer la structure de base du nouveau layer
|
### Préparer la structure de base du nouveau layer
|
||||||
|
|
||||||
Une implémetation d'un layer se compose majoritairement de 3 éléments:
|
Une implémetation d'un layer se compose majoritairement de 3 éléments:
|
||||||
|
@ -1,125 +0,0 @@
|
|||||||
# Démarrer avec les sources
|
|
||||||
|
|
||||||
Dans ce tutoriel, nous verrons comment lancer un environnement de développement en local sur notre machine afin de travailler sur les sources de Bouncer.
|
|
||||||
|
|
||||||
## Prérequis
|
|
||||||
|
|
||||||
Les éléments suivants doivent être installés sur votre machine:
|
|
||||||
|
|
||||||
- [Golang > 1.20](https://go.dev/)
|
|
||||||
- [Docker](https://www.docker.com/)
|
|
||||||
- [Git](https://git-scm.com/)
|
|
||||||
- [GNU Make](https://www.gnu.org/software/make/)
|
|
||||||
|
|
||||||
Les ports suivants doivent être disponibles sur votre machine:
|
|
||||||
|
|
||||||
- `8080`
|
|
||||||
- `8081`
|
|
||||||
|
|
||||||
## Étapes
|
|
||||||
|
|
||||||
1. Cloner le dépôt des sources du projet Bouncer
|
|
||||||
|
|
||||||
```
|
|
||||||
git clone https://forge.cadoles.com/Cadoles/bouncer
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Se positionner dans le répertoire du projet
|
|
||||||
|
|
||||||
```
|
|
||||||
cd bouncer
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Lancer le projet en mode "développement"
|
|
||||||
|
|
||||||
```
|
|
||||||
make watch
|
|
||||||
```
|
|
||||||
|
|
||||||
Si toutes les dépendances sont correctement installées et configurées sur votre machine, la console devrait afficher une série de messages pour ensuite s'arrêter sur quelque chose ressemblant à:
|
|
||||||
|
|
||||||
```
|
|
||||||
14:47:06: daemon: make run BOUNCER_CMD="--config config.yml server admin run"
|
|
||||||
2023-06-23 20:47:06.095 [INFO] <./internal/command/server/admin/run.go:42> RunCommand.func1 listening {"url": "http://127.0.0.1:8081"}
|
|
||||||
2023-06-23 20:47:06.095 [INFO] <./internal/admin/server.go:126> (*Server).run http server listening
|
|
||||||
14:47:06: daemon: make run-redis
|
|
||||||
bouncer-redis
|
|
||||||
docker run --rm -t \
|
|
||||||
--name bouncer-redis \
|
|
||||||
-v /home/wpetit/workspace/bouncer/data/redis:/data \
|
|
||||||
-p 6379:6379 \
|
|
||||||
redis:alpine3.17 \
|
|
||||||
redis-server --save 60 1 --loglevel warning
|
|
||||||
1:C 23 Jun 2023 20:47:06.754 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
|
|
||||||
1:C 23 Jun 2023 20:47:06.754 # Redis version=7.0.11, bits=64, commit=00000000, modified=0, pid=1, just started
|
|
||||||
1:C 23 Jun 2023 20:47:06.754 # Configuration loaded
|
|
||||||
1:M 23 Jun 2023 20:47:06.759 # Warning: Could not create server TCP listening socket ::*:6379: unable to bind socket, errno: 97
|
|
||||||
1:M 23 Jun 2023 20:47:06.760 # Server initialized
|
|
||||||
1:M 23 Jun 2023 20:47:06.760 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect
|
|
||||||
```
|
|
||||||
|
|
||||||
À ce stade, le serveur `bouncer-admin` écoute sur http://127.0.0.1:8081 et le serveur `bouncer-proxy` sur http://127.0.0.1:8080.
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> L'outil [`modd`](https://github.com/cortesi/modd) est utilisé pour surveiller les modifications sur les sources et relancer automatiquement la compilation et les services en cas de changement.
|
|
||||||
|
|
||||||
## Commandes `make` utiles
|
|
||||||
|
|
||||||
### `make watch`
|
|
||||||
|
|
||||||
Surveiller les sources, compiler celles ci en cas de modifications et lancer les services `bouncer-proxy` et `bouncer-admin`.
|
|
||||||
|
|
||||||
#### `make test`
|
|
||||||
|
|
||||||
Exécuter les tests unitaires/d'intégration du projet.
|
|
||||||
|
|
||||||
#### `make build`
|
|
||||||
|
|
||||||
Compiler une version de développement du binaire `bouncer`.
|
|
||||||
|
|
||||||
#### `make docker-build`
|
|
||||||
|
|
||||||
Construire une image Docker pour Bouncer.
|
|
||||||
|
|
||||||
Vous pouvez ensuite lancer l'image localement avec la commande:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run \
|
|
||||||
-it --rm \
|
|
||||||
reg.cadoles.com/cadoles/bouncer:<tag> \
|
|
||||||
-p 8080:8080 \
|
|
||||||
bouncer server proxy run
|
|
||||||
```
|
|
||||||
|
|
||||||
## Arborescence du projet
|
|
||||||
|
|
||||||
```bash
|
|
||||||
.
|
|
||||||
├── bin # Répertoire de destination des binaires Go de développement
|
|
||||||
├── cmd # Package principal (main) du binaire Bouncer
|
|
||||||
├── data # Répertoire des données de développement (Redis)
|
|
||||||
├── dist # Répertoire de destination des archives/paquets pour la publication
|
|
||||||
├── doc # Répertoire de documentation du projet
|
|
||||||
├── internal # Source Go du projet
|
|
||||||
│ ├── admin
|
|
||||||
│ ├── auth
|
|
||||||
│ ├── chi
|
|
||||||
│ ├── client
|
|
||||||
│ ├── command
|
|
||||||
│ ├── config
|
|
||||||
│ ├── format
|
|
||||||
│ ├── imports
|
|
||||||
│ ├── jwk
|
|
||||||
│ ├── proxy
|
|
||||||
│ ├── schema
|
|
||||||
│ ├── setup
|
|
||||||
│ └── store
|
|
||||||
├── layers # Fichiers annexes liés aux layers (templates HTML)
|
|
||||||
│ └── queue
|
|
||||||
├── misc # Fichiers annexes
|
|
||||||
│ ├── jenkins # Fichiers liés au pipeline d'intégration continue Jenkins
|
|
||||||
│ ├── logo # Logo du projet
|
|
||||||
│ └── packaging # Fichiers liés à l'empaquetage des binaires
|
|
||||||
└── tools # Outils utilisés en développement
|
|
||||||
```
|
|
12
go.mod
12
go.mod
@ -21,7 +21,6 @@ require (
|
|||||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
|
||||||
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/containerd/continuity v0.3.0 // indirect
|
github.com/containerd/continuity v0.3.0 // indirect
|
||||||
@ -31,24 +30,18 @@ require (
|
|||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
|
||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/huandu/xstrings v1.3.3 // indirect
|
github.com/huandu/xstrings v1.3.3 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.0 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
|
||||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||||
github.com/opencontainers/runc v1.1.5 // indirect
|
github.com/opencontainers/runc v1.1.5 // indirect
|
||||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
|
||||||
github.com/prometheus/client_model v0.3.0 // indirect
|
|
||||||
github.com/prometheus/common v0.42.0 // indirect
|
|
||||||
github.com/prometheus/procfs v0.10.1 // indirect
|
|
||||||
github.com/qri-io/jsonpointer v0.1.1 // indirect
|
github.com/qri-io/jsonpointer v0.1.1 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||||
@ -59,7 +52,6 @@ require (
|
|||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106 // indirect
|
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
@ -96,7 +88,7 @@ require (
|
|||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
golang.org/x/crypto v0.8.0 // indirect
|
golang.org/x/crypto v0.8.0 // indirect
|
||||||
golang.org/x/mod v0.9.0 // indirect
|
golang.org/x/mod v0.9.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
golang.org/x/sys v0.7.0 // indirect
|
||||||
golang.org/x/term v0.7.0 // indirect
|
golang.org/x/term v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.7.0 // indirect
|
golang.org/x/tools v0.7.0 // indirect
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||||
|
21
go.sum
21
go.sum
@ -80,8 +80,6 @@ github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUS
|
|||||||
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
|
github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
|
||||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
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/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
|
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
|
||||||
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
||||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||||
@ -232,8 +230,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
|||||||
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
|
||||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/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=
|
||||||
@ -313,7 +309,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
|||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
|
||||||
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/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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@ -352,8 +347,6 @@ github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp9
|
|||||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
||||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
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/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
@ -386,7 +379,6 @@ github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuh
|
|||||||
github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4=
|
github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4=
|
||||||
github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg=
|
github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg=
|
||||||
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
@ -394,15 +386,7 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||||||
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
|
||||||
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
|
|
||||||
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
|
|
||||||
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
|
|
||||||
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
|
|
||||||
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
|
|
||||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
|
||||||
github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA=
|
github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA=
|
||||||
github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
|
github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
|
||||||
github.com/qri-io/jsonschema v0.2.1 h1:NNFoKms+kut6ABPf6xiKNM5214jzxAhDBrPHCJ97Wg0=
|
github.com/qri-io/jsonschema v0.2.1 h1:NNFoKms+kut6ABPf6xiKNM5214jzxAhDBrPHCJ97Wg0=
|
||||||
@ -414,7 +398,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
|||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
|
||||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@ -682,8 +665,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
@ -910,8 +891,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
|||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
|
||||||
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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
"github.com/go-chi/cors"
|
"github.com/go-chi/cors"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
"gitlab.com/wpetit/goweb/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -102,25 +101,6 @@ func (s *Server) run(parentCtx context.Context, addrs chan net.Addr, errs chan e
|
|||||||
|
|
||||||
router.Use(corsMiddleware.Handler)
|
router.Use(corsMiddleware.Handler)
|
||||||
|
|
||||||
if s.serverConfig.Metrics.Enabled {
|
|
||||||
metrics := s.serverConfig.Metrics
|
|
||||||
|
|
||||||
logger.Info(ctx, "enabling metrics", logger.F("endpoint", metrics.Endpoint))
|
|
||||||
|
|
||||||
router.Group(func(r chi.Router) {
|
|
||||||
if metrics.BasicAuth != nil {
|
|
||||||
logger.Info(ctx, "enabling authentication on metrics endpoint")
|
|
||||||
|
|
||||||
r.Use(middleware.BasicAuth(
|
|
||||||
"metrics",
|
|
||||||
metrics.BasicAuth.CredentialsMap(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Handle(string(metrics.Endpoint), promhttp.Handler())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
router.Route("/api/v1", func(r chi.Router) {
|
router.Route("/api/v1", func(r chi.Router) {
|
||||||
r.Group(func(r chi.Router) {
|
r.Group(func(r chi.Router) {
|
||||||
r.Use(auth.Middleware(
|
r.Use(auth.Middleware(
|
||||||
|
@ -18,8 +18,6 @@ func Dump() *cli.Command {
|
|||||||
Usage: "Dump the current configuration",
|
Usage: "Dump the current configuration",
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
Action: func(ctx *cli.Context) error {
|
Action: func(ctx *cli.Context) error {
|
||||||
logger.SetLevel(logger.LevelError)
|
|
||||||
|
|
||||||
conf, err := common.LoadConfig(ctx)
|
conf, err := common.LoadConfig(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "Could not load configuration")
|
return errors.Wrap(err, "Could not load configuration")
|
||||||
|
@ -50,10 +50,9 @@ func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands
|
|||||||
},
|
},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "workdir",
|
Name: "workdir",
|
||||||
Value: "",
|
Value: "",
|
||||||
EnvVars: []string{"BOUNCER_WORKDIR"},
|
Usage: "The working directory",
|
||||||
Usage: "The working directory",
|
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "projectVersion",
|
Name: "projectVersion",
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
type AdminServerConfig struct {
|
type AdminServerConfig struct {
|
||||||
HTTP HTTPConfig `yaml:"http"`
|
HTTP HTTPConfig `yaml:"http"`
|
||||||
CORS CORSConfig `yaml:"cors"`
|
CORS CORSConfig `yaml:"cors"`
|
||||||
Auth AuthConfig `yaml:"auth"`
|
Auth AuthConfig `yaml:"auth"`
|
||||||
Metrics MetricsConfig `yaml:"metrics"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultAdminServerConfig() AdminServerConfig {
|
func NewDefaultAdminServerConfig() AdminServerConfig {
|
||||||
return AdminServerConfig{
|
return AdminServerConfig{
|
||||||
HTTP: NewHTTPConfig("127.0.0.1", 8081),
|
HTTP: NewHTTPConfig("127.0.0.1", 8081),
|
||||||
CORS: NewDefaultCORSConfig(),
|
CORS: NewDefaultCORSConfig(),
|
||||||
Auth: NewDefaultAuthConfig(),
|
Auth: NewDefaultAuthConfig(),
|
||||||
Metrics: NewDefaultMetricsConfig(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ type LoggerConfig struct {
|
|||||||
|
|
||||||
func NewDefaultLoggerConfig() LoggerConfig {
|
func NewDefaultLoggerConfig() LoggerConfig {
|
||||||
return LoggerConfig{
|
return LoggerConfig{
|
||||||
Level: InterpolatedInt(logger.LevelError),
|
Level: InterpolatedInt(logger.LevelInfo),
|
||||||
Format: InterpolatedString(logger.FormatHuman),
|
Format: InterpolatedString(logger.FormatHuman),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type MetricsConfig struct {
|
|
||||||
Enabled InterpolatedBool `yaml:"enabled"`
|
|
||||||
Endpoint InterpolatedString `yaml:"endpoint"`
|
|
||||||
BasicAuth *BasicAuthConfig `yaml:"basicAuth"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BasicAuthConfig struct {
|
|
||||||
Credentials *InterpolatedMap `yaml:"credentials"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *BasicAuthConfig) CredentialsMap() map[string]string {
|
|
||||||
if c.Credentials == nil {
|
|
||||||
return map[string]string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
credentials := make(map[string]string, len(*c.Credentials))
|
|
||||||
|
|
||||||
for k, v := range *c.Credentials {
|
|
||||||
credentials[k] = fmt.Sprintf("%v", v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return credentials
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultMetricsConfig() MetricsConfig {
|
|
||||||
return MetricsConfig{
|
|
||||||
Enabled: true,
|
|
||||||
Endpoint: "/.bouncer/metrics",
|
|
||||||
BasicAuth: nil,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +1,11 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
type ProxyServerConfig struct {
|
type ProxyServerConfig struct {
|
||||||
HTTP HTTPConfig `yaml:"http"`
|
HTTP HTTPConfig `yaml:"http"`
|
||||||
Metrics MetricsConfig `yaml:"metrics"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultProxyServerConfig() ProxyServerConfig {
|
func NewDefaultProxyServerConfig() ProxyServerConfig {
|
||||||
return ProxyServerConfig{
|
return ProxyServerConfig{
|
||||||
HTTP: NewHTTPConfig("0.0.0.0", 8080),
|
HTTP: NewHTTPConfig("0.0.0.0", 8080),
|
||||||
Metrics: NewDefaultMetricsConfig(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"forge.cadoles.com/Cadoles/go-proxy/wildcard"
|
"forge.cadoles.com/Cadoles/go-proxy/wildcard"
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/store"
|
"forge.cadoles.com/cadoles/bouncer/internal/store"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
"gitlab.com/wpetit/goweb/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -60,8 +59,6 @@ MAIN:
|
|||||||
logger.F("remoteAddr", r.RemoteAddr),
|
logger.F("remoteAddr", r.RemoteAddr),
|
||||||
)
|
)
|
||||||
|
|
||||||
metricProxyRequestsTotal.With(prometheus.Labels{metricLabelProxy: string(match.Name)}).Add(1)
|
|
||||||
|
|
||||||
ctx = withProxy(ctx, match)
|
ctx = withProxy(ctx, match)
|
||||||
|
|
||||||
layers, err := d.getLayers(ctx, match.Name)
|
layers, err := d.getLayers(ctx, match.Name)
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
package queue
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DebouncerMap struct {
|
|
||||||
debouncers sync.Map
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDebouncerMap() *DebouncerMap {
|
|
||||||
return &DebouncerMap{
|
|
||||||
debouncers: sync.Map{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *DebouncerMap) Do(key string, after time.Duration, fn func()) {
|
|
||||||
newDebouncer := NewDebouncer(after)
|
|
||||||
rawDebouncer, loaded := m.debouncers.LoadOrStore(key, newDebouncer)
|
|
||||||
|
|
||||||
debouncer, ok := rawDebouncer.(*Debouncer)
|
|
||||||
if !ok {
|
|
||||||
panic(errors.Errorf("unexpected debouncer value, expected '%T', got '%T'", newDebouncer, rawDebouncer))
|
|
||||||
}
|
|
||||||
|
|
||||||
if loaded {
|
|
||||||
debouncer.Update(after)
|
|
||||||
}
|
|
||||||
|
|
||||||
debouncer.Do(fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDebouncer(after time.Duration) *Debouncer {
|
|
||||||
return &Debouncer{after: after}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Debouncer struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
after time.Duration
|
|
||||||
timer *time.Timer
|
|
||||||
fn func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Debouncer) Do(fn func()) {
|
|
||||||
d.mu.Lock()
|
|
||||||
defer d.mu.Unlock()
|
|
||||||
|
|
||||||
if d.timer != nil {
|
|
||||||
d.timer.Stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
d.fn = fn
|
|
||||||
d.timer = time.AfterFunc(d.after, d.fn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Debouncer) Update(after time.Duration) {
|
|
||||||
d.mu.Lock()
|
|
||||||
defer d.mu.Unlock()
|
|
||||||
|
|
||||||
if after == d.after {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if d.timer != nil {
|
|
||||||
d.timer.Stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
d.after = after
|
|
||||||
d.timer = time.AfterFunc(d.after, d.fn)
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package queue
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
metricNamespace = "bouncer_layer_queue"
|
|
||||||
metricLabelProxy = "proxy"
|
|
||||||
metricLabelLayer = "layer"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
metricQueueSessions = promauto.NewGaugeVec(
|
|
||||||
prometheus.GaugeOpts{
|
|
||||||
Name: "sessions",
|
|
||||||
Help: "Bouncer's queue layer current sessions",
|
|
||||||
Namespace: metricNamespace,
|
|
||||||
},
|
|
||||||
[]string{metricLabelProxy, metricLabelLayer},
|
|
||||||
)
|
|
||||||
metricQueueCapacity = promauto.NewGaugeVec(
|
|
||||||
prometheus.GaugeOpts{
|
|
||||||
Name: "capacity",
|
|
||||||
Help: "Bouncer's queue layer capacity",
|
|
||||||
Namespace: metricNamespace,
|
|
||||||
},
|
|
||||||
[]string{metricLabelProxy, metricLabelLayer},
|
|
||||||
)
|
|
||||||
)
|
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"math/rand"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
@ -17,7 +16,6 @@ import (
|
|||||||
"github.com/Masterminds/sprig/v3"
|
"github.com/Masterminds/sprig/v3"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
"gitlab.com/wpetit/goweb/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,9 +30,7 @@ type Queue struct {
|
|||||||
loadOnce sync.Once
|
loadOnce sync.Once
|
||||||
tmpl *template.Template
|
tmpl *template.Template
|
||||||
|
|
||||||
refreshJobRunning uint32
|
refreshJobRunning uint32
|
||||||
updateMetricsJobRunning uint32
|
|
||||||
postKeepAliveDebouncer *DebouncerMap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LayerType implements director.MiddlewareLayer
|
// LayerType implements director.MiddlewareLayer
|
||||||
@ -56,8 +52,6 @@ func (q *Queue) Middleware(layer *store.Layer) proxy.Middleware {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer q.updateMetrics(ctx, layer.Proxy, layer.Name, options)
|
|
||||||
|
|
||||||
cookieName := q.getCookieName(layer.Name)
|
cookieName := q.getCookieName(layer.Name)
|
||||||
|
|
||||||
cookie, err := r.Cookie(cookieName)
|
cookie, err := r.Cookie(cookieName)
|
||||||
@ -78,6 +72,8 @@ func (q *Queue) Middleware(layer *store.Layer) proxy.Middleware {
|
|||||||
sessionID := cookie.Value
|
sessionID := cookie.Value
|
||||||
queueName := string(layer.Name)
|
queueName := string(layer.Name)
|
||||||
|
|
||||||
|
q.refreshQueue(queueName, options.KeepAlive)
|
||||||
|
|
||||||
rank, err := q.adapter.Touch(ctx, queueName, sessionID)
|
rank, err := q.adapter.Touch(ctx, queueName, sessionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(ctx, "could not retrieve session rank", logger.E(errors.WithStack(err)))
|
logger.Error(ctx, "could not retrieve session rank", logger.E(errors.WithStack(err)))
|
||||||
@ -106,30 +102,6 @@ func (q *Queue) Middleware(layer *store.Layer) proxy.Middleware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queue) updateSessionsMetric(ctx context.Context, proxyName store.ProxyName, layerName store.LayerName) {
|
|
||||||
if !atomic.CompareAndSwapUint32(&q.updateMetricsJobRunning, 0, 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
defer atomic.StoreUint32(&q.updateMetricsJobRunning, 0)
|
|
||||||
|
|
||||||
queueName := string(layerName)
|
|
||||||
|
|
||||||
status, err := q.adapter.Status(ctx, queueName)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error(ctx, "could not retrieve queue status", logger.E(errors.WithStack(err)))
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
metricQueueSessions.With(
|
|
||||||
prometheus.Labels{
|
|
||||||
metricLabelLayer: string(layerName),
|
|
||||||
metricLabelProxy: string(proxyName),
|
|
||||||
},
|
|
||||||
).Set(float64(status.Sessions))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueName string, options *LayerOptions, rank int64) {
|
func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueName string, options *LayerOptions, rank int64) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
@ -163,22 +135,20 @@ func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueNam
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshRate := time.Duration(int64(options.KeepAlive.Seconds()/2)) * time.Second
|
|
||||||
|
|
||||||
templateData := struct {
|
templateData := struct {
|
||||||
QueueName string
|
QueueName string
|
||||||
LayerOptions *LayerOptions
|
LayerOptions *LayerOptions
|
||||||
Rank int64
|
Rank int64
|
||||||
CurrentSessions int64
|
CurrentSessions int64
|
||||||
MaxSessions int64
|
MaxSessions int64
|
||||||
RefreshRate time.Duration
|
RefreshRate int64
|
||||||
}{
|
}{
|
||||||
QueueName: queueName,
|
QueueName: queueName,
|
||||||
LayerOptions: options,
|
LayerOptions: options,
|
||||||
Rank: rank + 1,
|
Rank: rank + 1,
|
||||||
CurrentSessions: status.Sessions,
|
CurrentSessions: status.Sessions,
|
||||||
MaxSessions: options.Capacity,
|
MaxSessions: options.Capacity,
|
||||||
RefreshRate: refreshRate,
|
RefreshRate: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusServiceUnavailable)
|
w.WriteHeader(http.StatusServiceUnavailable)
|
||||||
@ -191,55 +161,24 @@ func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueNam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queue) refreshQueue(ctx context.Context, layerName store.LayerName, keepAlive time.Duration) {
|
func (q *Queue) refreshQueue(queueName string, keepAlive time.Duration) {
|
||||||
if !atomic.CompareAndSwapUint32(&q.refreshJobRunning, 0, 1) {
|
if !atomic.CompareAndSwapUint32(&q.refreshJobRunning, 0, 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer atomic.StoreUint32(&q.refreshJobRunning, 0)
|
go func() {
|
||||||
|
defer atomic.StoreUint32(&q.refreshJobRunning, 0)
|
||||||
|
|
||||||
if err := q.adapter.Refresh(ctx, string(layerName), keepAlive); err != nil {
|
ctx, cancel := context.WithTimeout(context.Background(), keepAlive*2)
|
||||||
logger.Error(ctx, "could not refresh queue",
|
defer cancel()
|
||||||
logger.E(errors.WithStack(err)),
|
|
||||||
logger.F("queue", layerName),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queue) updateMetrics(ctx context.Context, proxyName store.ProxyName, layerName store.LayerName, options *LayerOptions) {
|
if err := q.adapter.Refresh(ctx, queueName, keepAlive); err != nil {
|
||||||
// Update queue capacity metric
|
logger.Error(ctx, "could not refresh queue",
|
||||||
metricQueueCapacity.With(
|
logger.E(errors.WithStack(err)),
|
||||||
prometheus.Labels{
|
logger.F("queue", queueName),
|
||||||
metricLabelLayer: string(layerName),
|
)
|
||||||
metricLabelProxy: string(proxyName),
|
}
|
||||||
},
|
}()
|
||||||
).Set(float64(options.Capacity))
|
|
||||||
|
|
||||||
// Refresh queue data and metrics
|
|
||||||
q.refreshQueue(ctx, layerName, options.KeepAlive)
|
|
||||||
q.updateSessionsMetric(ctx, proxyName, layerName)
|
|
||||||
|
|
||||||
// (Re)schedule an update job after session ttl + semi-random time padding
|
|
||||||
// to update metrics after last session expiration
|
|
||||||
randDuration := rand.Int63n(int64(options.KeepAlive))
|
|
||||||
timePadding := options.KeepAlive/2 + time.Duration(randDuration)
|
|
||||||
after := options.KeepAlive + timePadding
|
|
||||||
|
|
||||||
debouncingKey := fmt.Sprintf("%s/%s", proxyName, layerName)
|
|
||||||
|
|
||||||
q.postKeepAliveDebouncer.Do(debouncingKey, after, func() {
|
|
||||||
ctx := logger.With(
|
|
||||||
context.Background(),
|
|
||||||
logger.F("proxy", proxyName),
|
|
||||||
logger.F("layer", layerName),
|
|
||||||
logger.F("after", after),
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.Info(ctx, "running post keep alive refresh job")
|
|
||||||
|
|
||||||
q.refreshQueue(ctx, layerName, options.KeepAlive)
|
|
||||||
q.updateSessionsMetric(ctx, proxyName, layerName)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queue) getCookieName(layerName store.LayerName) string {
|
func (q *Queue) getCookieName(layerName store.LayerName) string {
|
||||||
@ -253,10 +192,9 @@ func New(adapter Adapter, funcs ...OptionFunc) *Queue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Queue{
|
return &Queue{
|
||||||
adapter: adapter,
|
adapter: adapter,
|
||||||
templateDir: opts.TemplateDir,
|
templateDir: opts.TemplateDir,
|
||||||
defaultKeepAlive: opts.DefaultKeepAlive,
|
defaultKeepAlive: opts.DefaultKeepAlive,
|
||||||
postKeepAliveDebouncer: NewDebouncerMap(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package director
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
metricNamespace = "bouncer_proxy_director"
|
|
||||||
metricLabelProxy = "proxy"
|
|
||||||
)
|
|
||||||
|
|
||||||
var metricProxyRequestsTotal = promauto.NewCounterVec(
|
|
||||||
prometheus.CounterOpts{
|
|
||||||
Name: "proxy_requests_total",
|
|
||||||
Help: "Bouncer proxy total requests",
|
|
||||||
Namespace: metricNamespace,
|
|
||||||
},
|
|
||||||
[]string{metricLabelProxy},
|
|
||||||
)
|
|
@ -15,7 +15,6 @@ import (
|
|||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
"gitlab.com/wpetit/goweb/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -85,40 +84,18 @@ func (s *Server) run(parentCtx context.Context, addrs chan net.Addr, errs chan e
|
|||||||
)
|
)
|
||||||
|
|
||||||
router.Use(middleware.RequestLogger(bouncerChi.NewLogFormatter()))
|
router.Use(middleware.RequestLogger(bouncerChi.NewLogFormatter()))
|
||||||
|
router.Use(director.Middleware())
|
||||||
|
|
||||||
if s.serverConfig.Metrics.Enabled {
|
handler := proxy.New(
|
||||||
metrics := s.serverConfig.Metrics
|
proxy.WithRequestTransformers(
|
||||||
|
director.RequestTransformer(),
|
||||||
|
),
|
||||||
|
proxy.WithResponseTransformers(
|
||||||
|
director.ResponseTransformer(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
logger.Info(ctx, "enabling metrics", logger.F("endpoint", metrics.Endpoint))
|
router.Handle("/*", handler)
|
||||||
|
|
||||||
router.Group(func(r chi.Router) {
|
|
||||||
if metrics.BasicAuth != nil {
|
|
||||||
logger.Info(ctx, "enabling authentication on metrics endpoint")
|
|
||||||
|
|
||||||
r.Use(middleware.BasicAuth(
|
|
||||||
"metrics",
|
|
||||||
metrics.BasicAuth.CredentialsMap(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Handle(string(metrics.Endpoint), promhttp.Handler())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
router.Group(func(r chi.Router) {
|
|
||||||
r.Use(director.Middleware())
|
|
||||||
|
|
||||||
handler := proxy.New(
|
|
||||||
proxy.WithRequestTransformers(
|
|
||||||
director.RequestTransformer(),
|
|
||||||
),
|
|
||||||
proxy.WithResponseTransformers(
|
|
||||||
director.ResponseTransformer(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
r.Handle("/*", handler)
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := http.Serve(listener, router); err != nil && !errors.Is(err, net.ErrClosed) {
|
if err := http.Serve(listener, router); err != nil && !errors.Is(err, net.ErrClosed) {
|
||||||
errs <- errors.WithStack(err)
|
errs <- errors.WithStack(err)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Veuillez patienter - {{ .QueueName }}</title>
|
<title>Veuillez patienter - {{ .QueueName }}</title>
|
||||||
<meta http-equiv="refresh" content="{{ .RefreshRate.Seconds }}">
|
<meta http-equiv="refresh" content="{{ .RefreshRate }}">
|
||||||
<style>
|
<style>
|
||||||
html {
|
html {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 32 KiB |
@ -26,26 +26,10 @@ admin:
|
|||||||
- Authorization
|
- Authorization
|
||||||
- Sentry-Trace
|
- Sentry-Trace
|
||||||
debug: false
|
debug: false
|
||||||
|
|
||||||
# Authentification JWT
|
|
||||||
auth:
|
auth:
|
||||||
# Origine du jeton JWT
|
|
||||||
issuer: http://127.0.0.1:8081
|
issuer: http://127.0.0.1:8081
|
||||||
# Clé privée permettant de signer les jetons
|
|
||||||
# JWT générés pour l'usage de l'API d'administration.
|
|
||||||
privateKey: /etc/bouncer/admin-key.json
|
privateKey: /etc/bouncer/admin-key.json
|
||||||
|
|
||||||
# Métriques Prometheus
|
|
||||||
metrics:
|
|
||||||
# Activer ou désactiver la publication des métriques
|
|
||||||
enabled: true
|
|
||||||
# Route de publication des métriques
|
|
||||||
endpoint: /.bouncer/metrics
|
|
||||||
# Authentification "basic auth" sur la page
|
|
||||||
# de publication
|
|
||||||
# Mettre à null pour désactiver l'authentification
|
|
||||||
basicAuth: null
|
|
||||||
|
|
||||||
# Configuration du service "proxy"
|
# Configuration du service "proxy"
|
||||||
proxy:
|
proxy:
|
||||||
http:
|
http:
|
||||||
@ -54,18 +38,6 @@ proxy:
|
|||||||
host: 0.0.0.0
|
host: 0.0.0.0
|
||||||
# Port d'écoute du service
|
# Port d'écoute du service
|
||||||
port: 8080
|
port: 8080
|
||||||
|
|
||||||
# Métriques Prometheus
|
|
||||||
metrics:
|
|
||||||
# Activer ou désactiver la publication des métriques
|
|
||||||
enabled: true
|
|
||||||
# Route de publication des métriques
|
|
||||||
endpoint: /.bouncer/metrics
|
|
||||||
# Authentification "basic auth" sur la page
|
|
||||||
# de publication
|
|
||||||
# Mettre à null pour désactiver l'authentification
|
|
||||||
basicAuth:
|
|
||||||
prom: etheus
|
|
||||||
|
|
||||||
# Configuration du client Redis
|
# Configuration du client Redis
|
||||||
#
|
#
|
||||||
|
@ -8,8 +8,8 @@ layers/**
|
|||||||
prep: make build-bouncer
|
prep: make build-bouncer
|
||||||
prep: make config.yml
|
prep: make config.yml
|
||||||
prep: make .bouncer-token
|
prep: make .bouncer-token
|
||||||
daemon: make run BOUNCER_CMD="--debug --config config.yml server admin run"
|
daemon: make run BOUNCER_CMD="--config config.yml server admin run"
|
||||||
daemon: make run BOUNCER_CMD="--debug --config config.yml server proxy run"
|
daemon: make run BOUNCER_CMD="--config config.yml server proxy run"
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user