Compare commits
2 Commits
v2024.3.26
...
k8s
Author | SHA1 | Date | |
---|---|---|---|
1b7344bcb5 | |||
bcc73a97cc |
@ -33,15 +33,15 @@ archives:
|
|||||||
- README.md
|
- README.md
|
||||||
- misc/packaging/common/config.yml
|
- misc/packaging/common/config.yml
|
||||||
checksum:
|
checksum:
|
||||||
name_template: "checksums.txt"
|
name_template: 'checksums.txt'
|
||||||
snapshot:
|
snapshot:
|
||||||
name_template: "{{ .Version }}"
|
name_template: "{{ .Version }}"
|
||||||
changelog:
|
changelog:
|
||||||
sort: asc
|
sort: asc
|
||||||
filters:
|
filters:
|
||||||
exclude:
|
exclude:
|
||||||
- "^docs:"
|
- '^docs:'
|
||||||
- "^test:"
|
- '^test:'
|
||||||
nfpms:
|
nfpms:
|
||||||
- id: bouncer-bin
|
- id: bouncer-bin
|
||||||
builds:
|
builds:
|
||||||
@ -63,10 +63,6 @@ nfpms:
|
|||||||
- src: layers
|
- src: layers
|
||||||
dst: /etc/bouncer/layers
|
dst: /etc/bouncer/layers
|
||||||
type: config
|
type: config
|
||||||
- dst: /etc/bouncer/bootstrap.d
|
|
||||||
type: dir
|
|
||||||
file_info:
|
|
||||||
mode: 0700
|
|
||||||
- id: bouncer-admin
|
- id: bouncer-admin
|
||||||
meta: true
|
meta: true
|
||||||
package_name: bouncer-admin
|
package_name: bouncer-admin
|
||||||
|
23
Dockerfile
23
Dockerfile
@ -1,4 +1,4 @@
|
|||||||
FROM reg.cadoles.com/proxy_cache/library/golang:1.21.6 AS BUILD
|
FROM golang:1.20 AS BUILD
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y make
|
&& apt-get install -y make
|
||||||
@ -9,15 +9,10 @@ RUN mkdir -p /usr/local/bin \
|
|||||||
&& wget -O /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_amd64 \
|
&& wget -O /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_amd64 \
|
||||||
&& chmod +x /usr/local/bin/yq
|
&& chmod +x /usr/local/bin/yq
|
||||||
|
|
||||||
WORKDIR /src
|
|
||||||
|
|
||||||
COPY go.mod .
|
|
||||||
COPY go.sum .
|
|
||||||
|
|
||||||
RUN go mod download
|
|
||||||
|
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
RUN make GORELEASER_ARGS='build --rm-dist --single-target --snapshot' goreleaser
|
RUN make GORELEASER_ARGS='build --rm-dist --single-target --snapshot' goreleaser
|
||||||
|
|
||||||
# Patch config
|
# Patch config
|
||||||
@ -26,11 +21,17 @@ RUN /src/dist/bouncer_linux_amd64_v1/bouncer -c '' config dump > /src/dist/bounc
|
|||||||
&& yq -i '.admin.auth.privateKey = "/etc/bouncer/admin-key.json"' /src/dist/bouncer_linux_amd64_v1/config.yml \
|
&& yq -i '.admin.auth.privateKey = "/etc/bouncer/admin-key.json"' /src/dist/bouncer_linux_amd64_v1/config.yml \
|
||||||
&& yq -i '.redis.adresses = ["redis:6379"]' /src/dist/bouncer_linux_amd64_v1/config.yml
|
&& yq -i '.redis.adresses = ["redis:6379"]' /src/dist/bouncer_linux_amd64_v1/config.yml
|
||||||
|
|
||||||
FROM reg.cadoles.com/proxy_cache/library/alpine:3.19.1 AS RUNTIME
|
FROM alpine:3.18 AS RUNTIME
|
||||||
|
|
||||||
RUN apk add --no-cache ca-certificates dumb-init
|
ARG DUMB_INIT_VERSION=1.2.5
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
|
RUN apk add --no-cache ca-certificates
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/local/bin \
|
||||||
|
&& wget -O /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_x86_64 \
|
||||||
|
&& chmod +x /usr/local/bin/dumb-init
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
|
||||||
|
|
||||||
RUN mkdir -p /usr/local/bin /usr/share/bouncer/bin /etc/bouncer
|
RUN mkdir -p /usr/local/bin /usr/share/bouncer/bin /etc/bouncer
|
||||||
|
|
||||||
|
8
Makefile
8
Makefile
@ -16,9 +16,6 @@ GOTEST_ARGS ?= -short
|
|||||||
|
|
||||||
OPENWRT_DEVICE ?= 192.168.1.1
|
OPENWRT_DEVICE ?= 192.168.1.1
|
||||||
|
|
||||||
SIEGE_URLS_FILE ?= misc/siege/urls.txt
|
|
||||||
SIEGE_CONCURRENCY ?= 100
|
|
||||||
|
|
||||||
watch: tools/modd/bin/modd deps ## Watching updated files - live reload
|
watch: tools/modd/bin/modd deps ## Watching updated files - live reload
|
||||||
( set -o allexport && source .env && set +o allexport && tools/modd/bin/modd )
|
( set -o allexport && source .env && set +o allexport && tools/modd/bin/modd )
|
||||||
|
|
||||||
@ -108,10 +105,7 @@ grafterm: tools/grafterm/bin/grafterm
|
|||||||
tools/grafterm/bin/grafterm -c ./misc/grafterm/dashboard.json -v job=bouncer-proxy -r 5s
|
tools/grafterm/bin/grafterm -c ./misc/grafterm/dashboard.json -v job=bouncer-proxy -r 5s
|
||||||
|
|
||||||
siege:
|
siege:
|
||||||
$(eval TMP := $(shell mktemp))
|
siege -i -c 100 -f ./misc/siege/urls.txt
|
||||||
cat $(SIEGE_URLS_FILE) | envsubst > $(TMP)
|
|
||||||
siege -i -b -c $(SIEGE_CONCURRENCY) -f $(TMP)
|
|
||||||
rm -rf $(TMP)
|
|
||||||
|
|
||||||
tools/gitea-release/bin/gitea-release.sh:
|
tools/gitea-release/bin/gitea-release.sh:
|
||||||
mkdir -p tools/gitea-release/bin
|
mkdir -p tools/gitea-release/bin
|
||||||
|
@ -6,11 +6,9 @@
|
|||||||
## Exemples
|
## Exemples
|
||||||
|
|
||||||
- [(FR) - Exemple de déploiement multi-noeuds](../misc/docker-compose/README.md)
|
- [(FR) - Exemple de déploiement multi-noeuds](../misc/docker-compose/README.md)
|
||||||
|
|
||||||
## Référence
|
## Référence
|
||||||
|
|
||||||
- [(FR) - Layers](./fr/references/layers/README.md)
|
- [(FR) - Layers](./fr/references/layers/README.md)
|
||||||
- [(FR) - Métriques](./fr/references/metrics.md)
|
|
||||||
- [(FR) - Fichier de configuration](../misc/packaging/common/config.yml)
|
- [(FR) - Fichier de configuration](../misc/packaging/common/config.yml)
|
||||||
- [(FR) - API d'administration](./fr/references/admin_api.md)
|
- [(FR) - API d'administration](./fr/references/admin_api.md)
|
||||||
|
|
||||||
@ -19,7 +17,6 @@
|
|||||||
### Utilisation
|
### Utilisation
|
||||||
|
|
||||||
- [(FR) - Ajouter un layer de type "file d'attente"](./fr/tutorials/add-queue-layer.md)
|
- [(FR) - Ajouter un layer de type "file d'attente"](./fr/tutorials/add-queue-layer.md)
|
||||||
- [(FR) - Amorçage d'un serveur Bouncer via la configuration](./fr/tutorials/bootstrapping.md)
|
|
||||||
|
|
||||||
### Développement
|
### Développement
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
5. Tester que le CLI est en capacité d'interroger l'API d'administration
|
5. Tester que le CLI est en capacité d'interroger l'API d'administration
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bouncer admin proxy query
|
bouncer admin query proxy
|
||||||
```
|
```
|
||||||
|
|
||||||
Un message équivalent à celui ci devrait s'afficher:
|
Un message équivalent à celui ci devrait s'afficher:
|
||||||
|
@ -32,10 +32,6 @@ Ce layer permet de bloquer l'accès à un site (ou une section de celui ci) cibl
|
|||||||
|
|
||||||
Voir le [fichier de configuration de référence](../../../../misc/packaging/common/config.yml), section `layers.circuitbreaker` pour voir les options permettant de personnaliser le chemin du répertoire contenant les templates.
|
Voir le [fichier de configuration de référence](../../../../misc/packaging/common/config.yml), section `layers.circuitbreaker` pour voir les options permettant de personnaliser le chemin du répertoire contenant les templates.
|
||||||
|
|
||||||
## Schéma
|
### Schéma
|
||||||
|
|
||||||
Voir le [schéma JSON](../../../../internal/proxy/director/layer/circuitbreaker/layer-options.json).
|
Voir le [schéma JSON](../../../../internal/proxy/director/layer/circuitbreaker/layer-options.json).
|
||||||
|
|
||||||
## Métriques
|
|
||||||
|
|
||||||
_Aucune [métrique Prometheus](../metrics.md) n'est exportée par ce layer._
|
|
@ -30,34 +30,6 @@ Ce layer permet d'ajouter un mécanisme de file d'attente dynamique au proxy ass
|
|||||||
|
|
||||||
Par exemple, si vous souhaitez limiter votre file à l'ensemble d'une section "`/blog`" d'un site, vous pouvez déclarer la valeur `["*/blog*"]`. Les autres URLs du site ne seront pas affectées par cette file d'attente.
|
Par exemple, si vous souhaitez limiter votre file à l'ensemble d'une section "`/blog`" d'un site, vous pouvez déclarer la valeur `["*/blog*"]`. Les autres URLs du site ne seront pas affectées par cette file d'attente.
|
||||||
|
|
||||||
## Schéma
|
### Schéma
|
||||||
|
|
||||||
Voir le [schéma JSON](../../../../internal/proxy/director/layer/queue/schema/layer-options.json).
|
Voir le [schéma JSON](../../../../internal/proxy/director/layer/queue/schema/layer-options.json).
|
||||||
|
|
||||||
## Métriques
|
|
||||||
|
|
||||||
Les [métriques Prometheus](../metrics.md) suivantes sont exposées par ce layer.
|
|
||||||
|
|
||||||
### `bouncer_layer_queue_capacity{layer=<layerName>,proxy=<proxyName>}`
|
|
||||||
|
|
||||||
- **Type:** `gauge`
|
|
||||||
- **Description**: Capacité maximale de la queue
|
|
||||||
- **Exemple**
|
|
||||||
|
|
||||||
```
|
|
||||||
# HELP bouncer_layer_queue_capacity Bouncer's queue layer capacity
|
|
||||||
# TYPE bouncer_layer_queue_capacity gauge
|
|
||||||
bouncer_layer_queue_capacity{layer="queue",proxy="cadoles"} 2
|
|
||||||
```
|
|
||||||
|
|
||||||
### `bouncer_layer_queue_sessions{layer=<layerName>,proxy=<proxyName>}`
|
|
||||||
|
|
||||||
- **Type:** `gauge`
|
|
||||||
- **Description**: Nombre courant de sessions ouvertes
|
|
||||||
- **Exemple**
|
|
||||||
|
|
||||||
```
|
|
||||||
# HELP bouncer_layer_queue_sessions Bouncer's queue layer current sessions
|
|
||||||
# TYPE bouncer_layer_queue_sessions gauge
|
|
||||||
bouncer_layer_queue_sessions{layer="queue",proxy="cadoles"} 3
|
|
||||||
```
|
|
@ -1,29 +0,0 @@
|
|||||||
# Métriques
|
|
||||||
|
|
||||||
Bouncer expose un certain nombre de métriques Prometheus sur le serveur proxy ainsi que sur le serveur d'administration. Ces métriques sont par défaut accessibles sur `/.bouncer/metrics`.
|
|
||||||
|
|
||||||
Il est possible de configurer le point d'entrée de ces métriques ainsi que d'ajouter une authentification de type `Basic Auth` [via la configuration](../../../misc/packaging/common/config.yml) (voir les clés `admin.metrics` et `proxy.metrics`).
|
|
||||||
|
|
||||||
Outre les métriques par défaut fournies par la librairie [Prometheus](https://prometheus.io/docs/guides/go-application/#instrumenting-a-go-application-for-prometheus), les serveurs Bouncer exposent également des métriques propres.
|
|
||||||
|
|
||||||
Chaque layer associé à un proxy peut également ses propres métriques spécifiques. [Voir la page de documentation](./layers/README.md) de chaque layer pour plus d'informations.
|
|
||||||
|
|
||||||
## Métriques spécifiques
|
|
||||||
|
|
||||||
### Serveur proxy
|
|
||||||
|
|
||||||
#### `bouncer_proxy_director_proxy_requests_total{proxy=<proxyName>}`
|
|
||||||
|
|
||||||
- **Type:** `counter`
|
|
||||||
- **Description**: Nombre total de requêtes ayant transité par le proxy
|
|
||||||
- **Exemple**
|
|
||||||
|
|
||||||
```
|
|
||||||
# HELP bouncer_proxy_director_proxy_requests_total Bouncer proxy total requests
|
|
||||||
# TYPE bouncer_proxy_director_proxy_requests_total counter
|
|
||||||
bouncer_proxy_director_proxy_requests_total{proxy="cadoles"} 64
|
|
||||||
```
|
|
||||||
|
|
||||||
### Serveur d'administration
|
|
||||||
|
|
||||||
_Pas de métrique supplémentaire._
|
|
@ -1,47 +0,0 @@
|
|||||||
# Amorçage d'un serveur Bouncer via la configuration
|
|
||||||
|
|
||||||
Il est possible d'amorcer des données par défaut (i.e. des "proxies" et "layers" associés) via la configuration du serveur d'administration.
|
|
||||||
|
|
||||||
> **Attention** Ce mécanisme de modifiera pas des proxies déjà existants dans la base de données du serveur Bouncer. Autrement dit, si un proxy est déjà pré-existant lors du démarrage du serveur Bouncer, il ne sera pas modifié.
|
|
||||||
|
|
||||||
La définition des proxies et layers par défaut s'effectue dans la section `bootstrap` du fichier de configuration. Deux possibilités pour définir les proxys à charger par défaut:
|
|
||||||
|
|
||||||
- Utiliser un répertoire contenant des fichiers YAML (un par proxy) en définissant le chemin du répertoire via l'attribut `bootstrap.dir`;
|
|
||||||
- Définir directement la liste des proxies via l'attribut `bootstrap.proxies`.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# Configuration d'une série de proxy/layers
|
|
||||||
# à créer par défaut par le serveur d'administration
|
|
||||||
bootstrap:
|
|
||||||
# Répertoire contenant les définitions de proxy à créer
|
|
||||||
# par défaut. Les fichiers seront récupérés si ils
|
|
||||||
# correspondent au patron de nommage suivant:
|
|
||||||
#
|
|
||||||
# <bootstrap_dir>/<proxy_name>.yml
|
|
||||||
#
|
|
||||||
# Voir ci-dessous pour les attributs possibles dans les fichiers.
|
|
||||||
#
|
|
||||||
# Si l'attribut est vide ou absent le chargement des fichiers
|
|
||||||
# est désactivé.
|
|
||||||
dir: /etc/bouncer/bootstrap.d
|
|
||||||
|
|
||||||
# Tableau associatif de définition de proxies à créer par
|
|
||||||
# défaut par le serveur d'administration.
|
|
||||||
# Si `proxies` et `dir` sont tous les deux définis, les fichiers
|
|
||||||
# présents dans le répertoire `dir` surchargeront les valeurs définies
|
|
||||||
# dans `proxies`.
|
|
||||||
#
|
|
||||||
# Par défaut vide.
|
|
||||||
proxies:
|
|
||||||
# my-proxy:
|
|
||||||
# enabled: true # Activer/désactiver le proxy
|
|
||||||
# from: ["*"] # Filtre d'origine d'activation du proxy
|
|
||||||
# to: "https://example.net" # Destination du proxy
|
|
||||||
# weight: 0 # Priorité du proxy
|
|
||||||
# layers: # Layers associés au proxy
|
|
||||||
# my-layer:
|
|
||||||
# type: queue # Type du proxy
|
|
||||||
# enabled: false # Activer/désactiver le layer
|
|
||||||
# weight: 0 # Priorité du layer
|
|
||||||
# options: {"capacity": 100} # Options associées au layer
|
|
||||||
```
|
|
13
go.mod
13
go.mod
@ -5,7 +5,6 @@ go 1.20
|
|||||||
require (
|
require (
|
||||||
forge.cadoles.com/Cadoles/go-proxy v0.0.0-20230701194111-c6b3d482cca6
|
forge.cadoles.com/Cadoles/go-proxy v0.0.0-20230701194111-c6b3d482cca6
|
||||||
github.com/Masterminds/sprig/v3 v3.2.3
|
github.com/Masterminds/sprig/v3 v3.2.3
|
||||||
github.com/bsm/redislock v0.9.4
|
|
||||||
github.com/btcsuite/btcd/btcutil v1.1.3
|
github.com/btcsuite/btcd/btcutil v1.1.3
|
||||||
github.com/drone/envsubst v1.0.3
|
github.com/drone/envsubst v1.0.3
|
||||||
github.com/getsentry/sentry-go v0.22.0
|
github.com/getsentry/sentry-go v0.22.0
|
||||||
@ -61,7 +60,7 @@ require (
|
|||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||||
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
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.9.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
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
@ -81,11 +80,11 @@ require (
|
|||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
|
||||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||||
github.com/lestrrat-go/httprc v1.0.4 // indirect
|
github.com/lestrrat-go/httprc v1.0.4 // indirect
|
||||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||||
github.com/lestrrat-go/jwx/v2 v2.0.19
|
github.com/lestrrat-go/jwx/v2 v2.0.11
|
||||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||||
github.com/lib/pq v1.10.0 // indirect
|
github.com/lib/pq v1.10.0 // indirect
|
||||||
github.com/lithammer/shortuuid/v4 v4.0.0
|
github.com/lithammer/shortuuid/v4 v4.0.0
|
||||||
@ -97,10 +96,10 @@ require (
|
|||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b
|
gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
golang.org/x/crypto v0.17.0 // indirect
|
golang.org/x/crypto v0.9.0 // indirect
|
||||||
golang.org/x/mod v0.9.0 // indirect
|
golang.org/x/mod v0.9.0 // indirect
|
||||||
golang.org/x/sys v0.15.0 // indirect
|
golang.org/x/sys v0.10.0 // indirect
|
||||||
golang.org/x/term v0.15.0 // indirect
|
golang.org/x/term v0.8.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
|
||||||
gopkg.in/go-playground/validator.v9 v9.29.1 // indirect
|
gopkg.in/go-playground/validator.v9 v9.29.1 // indirect
|
||||||
|
39
go.sum
39
go.sum
@ -84,8 +84,6 @@ 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/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/bsm/redislock v0.9.4 h1:X/Wse1DPpiQgHbVYRE9zv6m070UcKoOGekgvpNhiSvw=
|
|
||||||
github.com/bsm/redislock v0.9.4/go.mod h1:Epf7AJLiSFwLCiZcfi6pWFO/8eAYrYpQXFxEDPoDeAk=
|
|
||||||
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=
|
||||||
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M=
|
||||||
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY=
|
||||||
@ -145,6 +143,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||||
|
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||||
@ -326,16 +325,17 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|||||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
|
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
|
||||||
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
||||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
||||||
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
||||||
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
|
github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8=
|
||||||
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
||||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
||||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
||||||
github.com/lestrrat-go/jwx/v2 v2.0.19 h1:ekv1qEZE6BVct89QA+pRF6+4pCpfVrOnEJnTnT4RXoY=
|
github.com/lestrrat-go/jwx/v2 v2.0.11 h1:ViHMnaMeaO0qV16RZWBHM7GTrAnX2aFLVKofc7FuKLQ=
|
||||||
github.com/lestrrat-go/jwx/v2 v2.0.19/go.mod h1:l3im3coce1lL2cDeAjqmaR+Awx+X8Ih+2k8BuHNJ4CU=
|
github.com/lestrrat-go/jwx/v2 v2.0.11/go.mod h1:ZtPtMFlrfDrH2Y0iwfa3dRFn8VzwBrB+cyrm3IBWdDg=
|
||||||
|
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||||
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
|
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
|
||||||
@ -452,6 +452,7 @@ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
|||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
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/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
@ -497,8 +498,8 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
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/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -535,6 +536,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -579,7 +581,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
|||||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||||
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
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/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -608,6 +612,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||||
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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -673,20 +678,24 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
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.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||||
|
golang.org/x/sys v0.10.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=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
|
||||||
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -697,8 +706,9 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
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/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -757,6 +767,7 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|||||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
@ -2,22 +2,12 @@ package admin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/config"
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/schema"
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/setup"
|
"forge.cadoles.com/cadoles/bouncer/internal/setup"
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/store"
|
|
||||||
"github.com/bsm/redislock"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) initRepositories(ctx context.Context) error {
|
func (s *Server) initRepositories(ctx context.Context) error {
|
||||||
if err := s.initRedisClient(ctx); err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := s.initLayerRepository(ctx); err != nil {
|
if err := s.initLayerRepository(ctx); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -29,16 +19,8 @@ func (s *Server) initRepositories(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initRedisClient(ctx context.Context) error {
|
|
||||||
client := setup.NewRedisClient(ctx, s.redisConfig)
|
|
||||||
|
|
||||||
s.redisClient = client
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) initLayerRepository(ctx context.Context) error {
|
func (s *Server) initLayerRepository(ctx context.Context) error {
|
||||||
layerRepository, err := setup.NewLayerRepository(ctx, s.redisClient)
|
layerRepository, err := setup.NewLayerRepository(ctx, s.redisConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -49,7 +31,7 @@ func (s *Server) initLayerRepository(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initProxyRepository(ctx context.Context) error {
|
func (s *Server) initProxyRepository(ctx context.Context) error {
|
||||||
proxyRepository, err := setup.NewProxyRepository(ctx, s.redisClient)
|
proxyRepository, err := setup.NewProxyRepository(ctx, s.redisConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -58,112 +40,3 @@ func (s *Server) initProxyRepository(ctx context.Context) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const bootstrapLockKey = "bouncer-bootstrap"
|
|
||||||
|
|
||||||
func (s *Server) bootstrapProxies(ctx context.Context) error {
|
|
||||||
if err := s.validateBootstrap(ctx); err != nil {
|
|
||||||
return errors.Wrap(err, "could not validate bootstrapped proxies")
|
|
||||||
}
|
|
||||||
|
|
||||||
proxyRepo := s.proxyRepository
|
|
||||||
layerRepo := s.layerRepository
|
|
||||||
|
|
||||||
locker := redislock.New(s.redisClient)
|
|
||||||
|
|
||||||
backoff := redislock.ExponentialBackoff(time.Second, time.Duration(s.bootstrapConfig.LockTimeout)*2)
|
|
||||||
|
|
||||||
logger.Debug(ctx, "acquiring proxies bootstrap lock", logger.F("lockTimeout", s.bootstrapConfig.LockTimeout))
|
|
||||||
|
|
||||||
lock, err := locker.Obtain(ctx, bootstrapLockKey, time.Duration(s.bootstrapConfig.LockTimeout), &redislock.Options{
|
|
||||||
RetryStrategy: backoff,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := lock.Release(ctx); err != nil {
|
|
||||||
logger.Error(ctx, "could not release lock", logger.E(errors.WithStack(err)))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
logger.Info(ctx, "bootstrapping proxies")
|
|
||||||
|
|
||||||
for proxyName, proxyConfig := range s.bootstrapConfig.Proxies {
|
|
||||||
_, err := s.proxyRepository.GetProxy(ctx, proxyName)
|
|
||||||
if !errors.Is(err, store.ErrNotFound) {
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Info(ctx, "ignoring existing proxy", logger.F("proxyName", proxyName))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Info(ctx, "creating proxy", logger.F("proxyName", proxyName))
|
|
||||||
|
|
||||||
if _, err := proxyRepo.CreateProxy(ctx, proxyName, string(proxyConfig.To), proxyConfig.From...); err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = proxyRepo.UpdateProxy(
|
|
||||||
ctx, proxyName,
|
|
||||||
store.WithProxyUpdateEnabled(bool(proxyConfig.Enabled)),
|
|
||||||
store.WithProxyUpdateWeight(int(proxyConfig.Weight)),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for layerName, layerConfig := range proxyConfig.Layers {
|
|
||||||
layerType := store.LayerType(layerConfig.Type)
|
|
||||||
layerOptions := store.LayerOptions(layerConfig.Options)
|
|
||||||
|
|
||||||
if _, err := layerRepo.CreateLayer(ctx, proxyName, layerName, layerType, layerOptions); err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := layerRepo.UpdateLayer(
|
|
||||||
ctx,
|
|
||||||
proxyName, layerName,
|
|
||||||
store.WithLayerUpdateEnabled(bool(layerConfig.Enabled)),
|
|
||||||
store.WithLayerUpdateOptions(layerOptions),
|
|
||||||
store.WithLayerUpdateWeight(int(layerConfig.Weight)),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const validateErrMessage = "could not validate proxy '%s': could not validate layer '%s'"
|
|
||||||
|
|
||||||
func (s *Server) validateBootstrap(ctx context.Context) error {
|
|
||||||
for proxyName, proxyConf := range s.bootstrapConfig.Proxies {
|
|
||||||
for layerName, layerConf := range proxyConf.Layers {
|
|
||||||
layerType := store.LayerType(layerConf.Type)
|
|
||||||
if !setup.LayerTypeExists(layerType) {
|
|
||||||
return errors.Errorf(validateErrMessage+": could not find layer type '%s'", proxyName, layerName, layerType)
|
|
||||||
}
|
|
||||||
|
|
||||||
layerOptionsSchema, err := setup.GetLayerOptionsSchema(layerType)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, validateErrMessage, proxyName, layerName)
|
|
||||||
}
|
|
||||||
|
|
||||||
rawOptions := func(opts config.InterpolatedMap) map[string]any {
|
|
||||||
return opts
|
|
||||||
}(layerConf.Options)
|
|
||||||
|
|
||||||
if err := schema.Validate(ctx, layerOptionsSchema, rawOptions); err != nil {
|
|
||||||
return errors.Wrapf(err, validateErrMessage, proxyName, layerName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -51,6 +51,15 @@ func (s *Server) queryLayer(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateLayerName(v string) (store.LayerName, error) {
|
||||||
|
name, err := store.ValidateName(v)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return store.LayerName(name), nil
|
||||||
|
}
|
||||||
|
|
||||||
type GetLayerResponse struct {
|
type GetLayerResponse struct {
|
||||||
Layer *store.Layer `json:"layer"`
|
Layer *store.Layer `json:"layer"`
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Option struct {
|
type Option struct {
|
||||||
BootstrapConfig config.BootstrapConfig
|
|
||||||
ServerConfig config.AdminServerConfig
|
ServerConfig config.AdminServerConfig
|
||||||
RedisConfig config.RedisConfig
|
RedisConfig config.RedisConfig
|
||||||
}
|
}
|
||||||
@ -30,9 +29,3 @@ func WithRedisConfig(conf config.RedisConfig) OptionFunc {
|
|||||||
opt.RedisConfig = conf
|
opt.RedisConfig = conf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithBootstrapConfig(conf config.BootstrapConfig) OptionFunc {
|
|
||||||
return func(opt *Option) {
|
|
||||||
opt.BootstrapConfig = conf
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -114,23 +114,6 @@ func (s *Server) deleteProxy(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
layers, err := s.layerRepository.QueryLayers(ctx, proxyName)
|
|
||||||
if err != nil {
|
|
||||||
logAndCaptureError(ctx, "could not query proxy's layers", errors.WithStack(err))
|
|
||||||
api.ErrorResponse(w, http.StatusInternalServerError, api.ErrCodeUnknownError, nil)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, layer := range layers {
|
|
||||||
if err := s.layerRepository.DeleteLayer(ctx, proxyName, layer.Name); err != nil {
|
|
||||||
logAndCaptureError(ctx, "could not delete layer", errors.WithStack(err))
|
|
||||||
api.ErrorResponse(w, http.StatusInternalServerError, api.ErrCodeUnknownError, nil)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
api.DataResponse(w, http.StatusOK, DeleteProxyResponse{
|
api.DataResponse(w, http.StatusOK, DeleteProxyResponse{
|
||||||
ProxyName: proxyName,
|
ProxyName: proxyName,
|
||||||
})
|
})
|
||||||
|
@ -19,15 +19,12 @@ import (
|
|||||||
"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"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
"gitlab.com/wpetit/goweb/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
serverConfig config.AdminServerConfig
|
serverConfig config.AdminServerConfig
|
||||||
redisConfig config.RedisConfig
|
redisConfig config.RedisConfig
|
||||||
redisClient redis.UniversalClient
|
|
||||||
bootstrapConfig config.BootstrapConfig
|
|
||||||
proxyRepository store.ProxyRepository
|
proxyRepository store.ProxyRepository
|
||||||
layerRepository store.LayerRepository
|
layerRepository store.LayerRepository
|
||||||
}
|
}
|
||||||
@ -56,12 +53,6 @@ func (s *Server) run(parentCtx context.Context, addrs chan net.Addr, errs chan e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.bootstrapProxies(ctx); err != nil {
|
|
||||||
errs <- errors.WithStack(err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.serverConfig.HTTP.Host, s.serverConfig.HTTP.Port))
|
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.serverConfig.HTTP.Host, s.serverConfig.HTTP.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs <- errors.WithStack(err)
|
errs <- errors.WithStack(err)
|
||||||
@ -186,6 +177,5 @@ func NewServer(funcs ...OptionFunc) *Server {
|
|||||||
return &Server{
|
return &Server{
|
||||||
serverConfig: opt.ServerConfig,
|
serverConfig: opt.ServerConfig,
|
||||||
redisConfig: opt.RedisConfig,
|
redisConfig: opt.RedisConfig,
|
||||||
bootstrapConfig: opt.BootstrapConfig,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,28 +5,15 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/admin"
|
"forge.cadoles.com/cadoles/bouncer/internal/admin"
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/auth/jwt"
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/command/common"
|
"forge.cadoles.com/cadoles/bouncer/internal/command/common"
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/jwk"
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/setup"
|
"forge.cadoles.com/cadoles/bouncer/internal/setup"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"gitlab.com/wpetit/goweb/logger"
|
"gitlab.com/wpetit/goweb/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
flagPrintDefaultToken = "print-default-token"
|
|
||||||
)
|
|
||||||
|
|
||||||
func RunCommand() *cli.Command {
|
func RunCommand() *cli.Command {
|
||||||
flags := append(
|
flags := common.Flags()
|
||||||
common.Flags(),
|
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: flagPrintDefaultToken,
|
|
||||||
Usage: "Generate and print a default writer token in console at startup",
|
|
||||||
Value: true,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return &cli.Command{
|
return &cli.Command{
|
||||||
Name: "run",
|
Name: "run",
|
||||||
@ -49,26 +36,9 @@ func RunCommand() *cli.Command {
|
|||||||
|
|
||||||
defer flushSentry()
|
defer flushSentry()
|
||||||
|
|
||||||
if printDefaultToken := ctx.Bool(flagPrintDefaultToken); printDefaultToken {
|
|
||||||
key, err := jwk.Generate(jwk.DefaultKeySize)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "could not generate default key")
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := jwt.GenerateToken(ctx.Context, key, string(conf.Admin.Auth.Issuer), "default-admin", jwt.Role(jwt.RoleWriter))
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.SetLevel(logger.LevelInfo)
|
|
||||||
logger.Info(ctx.Context, "default writer token", logger.F("token", token))
|
|
||||||
logger.SetLevel(logger.Level(conf.Logger.Level))
|
|
||||||
}
|
|
||||||
|
|
||||||
srv := admin.NewServer(
|
srv := admin.NewServer(
|
||||||
admin.WithServerConfig(conf.Admin),
|
admin.WithServerConfig(conf.Admin),
|
||||||
admin.WithRedisConfig(conf.Redis),
|
admin.WithRedisConfig(conf.Redis),
|
||||||
admin.WithBootstrapConfig(conf.Bootstrap),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
addrs, srvErrs := srv.Start(ctx.Context)
|
addrs, srvErrs := srv.Start(ctx.Context)
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/store"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BootstrapConfig struct {
|
|
||||||
Proxies map[store.ProxyName]BootstrapProxyConfig `yaml:"proxies"`
|
|
||||||
Dir InterpolatedString `yaml:"dir"`
|
|
||||||
LockTimeout InterpolatedDuration `yaml:"lockTimeout"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *BootstrapConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
||||||
src := struct {
|
|
||||||
Proxies map[store.ProxyName]BootstrapProxyConfig `yaml:"proxies"`
|
|
||||||
Dir InterpolatedString `yaml:"dir"`
|
|
||||||
}{
|
|
||||||
Proxies: make(map[store.ProxyName]BootstrapProxyConfig),
|
|
||||||
Dir: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := unmarshal(&src); err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Proxies = src.Proxies
|
|
||||||
c.Dir = src.Dir
|
|
||||||
|
|
||||||
if src.Dir != "" {
|
|
||||||
proxies, err := loadBootstrapDir(string(src.Dir))
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "could not load bootstrap dir '%s'", src.Dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Proxies = overrideProxies(c.Proxies, proxies)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type BootstrapProxyConfig struct {
|
|
||||||
Enabled InterpolatedBool `yaml:"enabled"`
|
|
||||||
Weight InterpolatedInt `yaml:"weight"`
|
|
||||||
To InterpolatedString `yaml:"to"`
|
|
||||||
From InterpolatedStringSlice `yaml:"from"`
|
|
||||||
Layers map[store.LayerName]BootstrapLayerConfig `yaml:"layers"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BootstrapLayerConfig struct {
|
|
||||||
Enabled InterpolatedBool `yaml:"enabled"`
|
|
||||||
Type InterpolatedString `yaml:"type"`
|
|
||||||
Weight InterpolatedInt `yaml:"weight"`
|
|
||||||
Options InterpolatedMap `yaml:"options"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDefaultBootstrapConfig() BootstrapConfig {
|
|
||||||
return BootstrapConfig{
|
|
||||||
Dir: "",
|
|
||||||
LockTimeout: *NewInterpolatedDuration(30 * time.Second),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadBootstrapDir(dir string) (map[store.ProxyName]BootstrapProxyConfig, error) {
|
|
||||||
pattern := filepath.Join(dir, "*.yml")
|
|
||||||
|
|
||||||
files, err := filepath.Glob(pattern)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
proxies := make(map[store.ProxyName]BootstrapProxyConfig)
|
|
||||||
for _, f := range files {
|
|
||||||
data, err := os.ReadFile(f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "could not read file '%s'", f)
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy := BootstrapProxyConfig{}
|
|
||||||
|
|
||||||
if err := yaml.Unmarshal(data, &proxy); err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "could not unmarshal proxy")
|
|
||||||
}
|
|
||||||
|
|
||||||
name := store.ProxyName(strings.TrimSuffix(filepath.Base(f), filepath.Ext(f)))
|
|
||||||
proxies[name] = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
return proxies, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func overrideProxies(base map[store.ProxyName]BootstrapProxyConfig, proxies map[store.ProxyName]BootstrapProxyConfig) map[store.ProxyName]BootstrapProxyConfig {
|
|
||||||
for name, proxy := range proxies {
|
|
||||||
base[name] = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
return base
|
|
||||||
}
|
|
@ -2,7 +2,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@ -15,14 +15,13 @@ type Config struct {
|
|||||||
Redis RedisConfig `yaml:"redis"`
|
Redis RedisConfig `yaml:"redis"`
|
||||||
Logger LoggerConfig `yaml:"logger"`
|
Logger LoggerConfig `yaml:"logger"`
|
||||||
Layers LayersConfig `yaml:"layers"`
|
Layers LayersConfig `yaml:"layers"`
|
||||||
Bootstrap BootstrapConfig `yaml:"bootstrap"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFromFile retrieves the configuration from the given file
|
// NewFromFile retrieves the configuration from the given file
|
||||||
func NewFromFile(path string) (*Config, error) {
|
func NewFromFile(path string) (*Config, error) {
|
||||||
config := NewDefault()
|
config := NewDefault()
|
||||||
|
|
||||||
data, err := os.ReadFile(path)
|
data, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "could not read file '%s'", path)
|
return nil, errors.Wrapf(err, "could not read file '%s'", path)
|
||||||
}
|
}
|
||||||
@ -49,7 +48,6 @@ func NewDefault() *Config {
|
|||||||
Logger: NewDefaultLoggerConfig(),
|
Logger: NewDefaultLoggerConfig(),
|
||||||
Redis: NewDefaultRedisConfig(),
|
Redis: NewDefaultRedisConfig(),
|
||||||
Layers: NewDefaultLayersConfig(),
|
Layers: NewDefaultLayersConfig(),
|
||||||
Bootstrap: NewDefaultBootstrapConfig(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RedisModeSimple = "simple"
|
RedisModeSimple = "simple"
|
||||||
RedisModeSentinel = "sentinel"
|
RedisModeSentinel = "sentinel"
|
||||||
@ -11,17 +9,11 @@ const (
|
|||||||
type RedisConfig struct {
|
type RedisConfig struct {
|
||||||
Adresses InterpolatedStringSlice `yaml:"addresses"`
|
Adresses InterpolatedStringSlice `yaml:"addresses"`
|
||||||
Master InterpolatedString `yaml:"master"`
|
Master InterpolatedString `yaml:"master"`
|
||||||
ReadTimeout InterpolatedDuration `yaml:"readTimeout"`
|
|
||||||
WriteTimeout InterpolatedDuration `yaml:"writeTimeout"`
|
|
||||||
DialTimeout InterpolatedDuration `yaml:"dialTimeout"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultRedisConfig() RedisConfig {
|
func NewDefaultRedisConfig() RedisConfig {
|
||||||
return RedisConfig{
|
return RedisConfig{
|
||||||
Adresses: InterpolatedStringSlice{"localhost:6379"},
|
Adresses: InterpolatedStringSlice{"localhost:6379"},
|
||||||
Master: "",
|
Master: "",
|
||||||
ReadTimeout: InterpolatedDuration(30 * time.Second),
|
|
||||||
WriteTimeout: InterpolatedDuration(30 * time.Second),
|
|
||||||
DialTimeout: InterpolatedDuration(30 * time.Second),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil/base58"
|
"github.com/btcsuite/btcd/btcutil/base58"
|
||||||
@ -55,7 +56,7 @@ func PublicKeySet(keys ...jwk.Key) (jwk.Set, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func LoadOrGenerate(path string, size int) (jwk.Key, error) {
|
func LoadOrGenerate(path string, size int) (jwk.Key, error) {
|
||||||
data, err := os.ReadFile(path)
|
data, err := ioutil.ReadFile(path)
|
||||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -71,7 +72,7 @@ func LoadOrGenerate(path string, size int) (jwk.Key, error) {
|
|||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile(path, data, 0o640); err != nil {
|
if err := ioutil.WriteFile(path, data, 0o640); err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,25 +5,22 @@ import (
|
|||||||
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/setup"
|
"forge.cadoles.com/cadoles/bouncer/internal/setup"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) initRepositories(ctx context.Context) error {
|
func (s *Server) initRepositories(ctx context.Context) error {
|
||||||
client := setup.NewRedisClient(ctx, s.redisConfig)
|
if err := s.initProxyRepository(ctx); err != nil {
|
||||||
|
|
||||||
if err := s.initProxyRepository(ctx, client); err != nil {
|
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.initLayerRepository(ctx, client); err != nil {
|
if err := s.initLayerRepository(ctx); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initProxyRepository(ctx context.Context, client redis.UniversalClient) error {
|
func (s *Server) initProxyRepository(ctx context.Context) error {
|
||||||
proxyRepository, err := setup.NewProxyRepository(ctx, client)
|
proxyRepository, err := setup.NewProxyRepository(ctx, s.redisConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -33,8 +30,8 @@ func (s *Server) initProxyRepository(ctx context.Context, client redis.Universal
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initLayerRepository(ctx context.Context, client redis.UniversalClient) error {
|
func (s *Server) initLayerRepository(ctx context.Context) error {
|
||||||
layerRepository, err := setup.NewLayerRepository(ctx, client)
|
layerRepository, err := setup.NewLayerRepository(ctx, s.redisConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
@ -9,17 +9,20 @@ import (
|
|||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewRedisClient(ctx context.Context, conf config.RedisConfig) redis.UniversalClient {
|
func NewProxyRepository(ctx context.Context, conf config.RedisConfig) (store.ProxyRepository, error) {
|
||||||
return redis.NewUniversalClient(&redis.UniversalOptions{
|
rdb := redis.NewUniversalClient(&redis.UniversalOptions{
|
||||||
Addrs: conf.Adresses,
|
Addrs: conf.Adresses,
|
||||||
MasterName: string(conf.Master),
|
MasterName: string(conf.Master),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return redisStore.NewProxyRepository(rdb), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProxyRepository(ctx context.Context, client redis.UniversalClient) (store.ProxyRepository, error) {
|
func NewLayerRepository(ctx context.Context, conf config.RedisConfig) (store.LayerRepository, error) {
|
||||||
return redisStore.NewProxyRepository(client), nil
|
rdb := redis.NewUniversalClient(&redis.UniversalOptions{
|
||||||
}
|
Addrs: conf.Adresses,
|
||||||
|
MasterName: string(conf.Master),
|
||||||
|
})
|
||||||
|
|
||||||
func NewLayerRepository(ctx context.Context, client redis.UniversalClient) (store.LayerRepository, error) {
|
return redisStore.NewLayerRepository(rdb), nil
|
||||||
return redisStore.NewLayerRepository(client), nil
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"forge.cadoles.com/cadoles/bouncer/internal/proxy/director/layer/queue"
|
"forge.cadoles.com/cadoles/bouncer/internal/proxy/director/layer/queue"
|
||||||
queueRedis "forge.cadoles.com/cadoles/bouncer/internal/proxy/director/layer/queue/redis"
|
queueRedis "forge.cadoles.com/cadoles/bouncer/internal/proxy/director/layer/queue/redis"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -35,6 +36,10 @@ func setupQueueLayer(conf *config.Config) (director.Layer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newQueueAdapter(redisConf config.RedisConfig) (queue.Adapter, error) {
|
func newQueueAdapter(redisConf config.RedisConfig) (queue.Adapter, error) {
|
||||||
rdb := newRedisClient(redisConf)
|
rdb := redis.NewUniversalClient(&redis.UniversalOptions{
|
||||||
|
Addrs: redisConf.Adresses,
|
||||||
|
MasterName: string(redisConf.Master),
|
||||||
|
})
|
||||||
|
|
||||||
return queueRedis.NewAdapter(rdb, 2), nil
|
return queueRedis.NewAdapter(rdb, 2), nil
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package setup
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"forge.cadoles.com/cadoles/bouncer/internal/config"
|
|
||||||
"github.com/redis/go-redis/v9"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newRedisClient(conf config.RedisConfig) redis.UniversalClient {
|
|
||||||
return redis.NewUniversalClient(&redis.UniversalOptions{
|
|
||||||
Addrs: conf.Adresses,
|
|
||||||
MasterName: string(conf.Master),
|
|
||||||
ReadTimeout: time.Duration(conf.ReadTimeout),
|
|
||||||
WriteTimeout: time.Duration(conf.WriteTimeout),
|
|
||||||
DialTimeout: time.Duration(conf.DialTimeout),
|
|
||||||
RouteByLatency: true,
|
|
||||||
ContextTimeoutEnabled: true,
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
# K6 - Load Test
|
|
||||||
|
|
||||||
Very basic load testing script for [k6](https://k6.io/).
|
|
||||||
|
|
||||||
## How to run
|
|
||||||
|
|
||||||
```shell
|
|
||||||
k6 run cadoles-loadtest.js
|
|
||||||
```
|
|
@ -1,29 +0,0 @@
|
|||||||
import { check } from 'k6';
|
|
||||||
import { browser } from 'k6/experimental/browser';
|
|
||||||
|
|
||||||
export const options = {
|
|
||||||
scenarios: {
|
|
||||||
browser: {
|
|
||||||
vus: 10,
|
|
||||||
iterations: 100,
|
|
||||||
executor: 'shared-iterations',
|
|
||||||
options: {
|
|
||||||
browser: {
|
|
||||||
type: 'chromium',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function () {
|
|
||||||
const page = browser.newPage();
|
|
||||||
try {
|
|
||||||
await page.goto('https://www.cadoles.com');
|
|
||||||
check(page, {
|
|
||||||
'Homepage loaded': p => p.locator('h1').textContent().trim() == 'La liberté est un choix',
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
page.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
# Kubernetes
|
|
||||||
|
|
||||||
## Initialize your project
|
|
||||||
|
|
||||||
1. Generate the Docker configuration to enable image builds with Kaniko and communicate with reg.cadoles.com
|
|
||||||
|
|
||||||
```shell
|
|
||||||
docker login reg.cadoles.com
|
|
||||||
mkdir -p misc/k8s/kustomization/base/secrets/dockerconfig
|
|
||||||
docker --config misc/k8s/kustomization/base/secrets/dockerconfig login reg.cadoles.com
|
|
||||||
mv misc/k8s/kustomization/base/secrets/dockerconfig/config.json misc/k8s/kustomization/base/secrets/dockerconfig/.dockerconfigjson
|
|
||||||
mkdir -p misc/k8s/kustomization/overlays/dev/secrets/dockerconfig
|
|
||||||
cp misc/k8s/kustomization/base/secrets/dockerconfig/.dockerconfigjson misc/k8s/kustomization/overlays/dev/secrets/dockerconfig/.dockerconfigjson
|
|
||||||
```
|
|
||||||
|
|
||||||
## Getting started with Kind
|
|
||||||
|
|
||||||
1. Create your [Kind](https://kind.sigs.k8s.io/) cluster
|
|
||||||
|
|
||||||
```shell
|
|
||||||
kind create cluster --config misc/k8s/kind/bouncer-cluster.yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Deploy required operators
|
|
||||||
|
|
||||||
```shell
|
|
||||||
kubectl apply -k misc/k8s/kind/cluster --server-side
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Deploy your Bouncer development environment
|
|
||||||
|
|
||||||
```shell
|
|
||||||
skaffold dev -p dev --cleanup=false --default-repo reg.cadoles.com/<YOUR_PERSONNAL_USER_NAME>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
Bouncer will automatically create proxies based on the files present in the `misc/k8s/kustomization/overlays/dev/files/bouncer/bootstrap.d` folder.
|
|
||||||
|
|
||||||
By default, with you host web browser, open http://localhost:9000, you should see the Cadoles website.
|
|
||||||
|
|
||||||
### Using the admin API
|
|
||||||
|
|
||||||
1. Open shell in bouncer-admin pod
|
|
||||||
|
|
||||||
```shell
|
|
||||||
kubectl exec -it -n bouncer-dev bouncer-admin-<suffix> -- /bin/sh
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Create an authentication token
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bouncer --config /etc/bouncer/config.yml auth create-token --role writer --subject $(whoami) > .bouncer-token
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Create a proxy and enable it
|
|
||||||
|
|
||||||
```shell
|
|
||||||
bouncer admin proxy query
|
|
||||||
```
|
|
||||||
|
|
||||||
## Benchmarking
|
|
||||||
|
|
||||||
You can use [`siege`](https://github.com/JoeDog/siege) to benchmark your instance with the Cadoles proxy.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
BASE_URL=http://localhost:9000 make siege
|
|
||||||
```
|
|
@ -1,3 +0,0 @@
|
|||||||
kind: Cluster
|
|
||||||
apiVersion: kind.x-k8s.io/v1alpha4
|
|
||||||
name: bouncer-dev
|
|
@ -1,5 +0,0 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
||||||
kind: Kustomization
|
|
||||||
|
|
||||||
resources:
|
|
||||||
- https://forge.cadoles.com/CadolesKube/c-kustom//base/redis?ref=develop
|
|
@ -28,13 +28,9 @@ admin:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
addresses:
|
addresses:
|
||||||
- rfs-bouncer-redis:${RFS_BOUNCER_REDIS_SERVICE_PORT}
|
- ${REDIS_SENTINEL_HOST}:${REDIS_SENTINEL_PORT}
|
||||||
master: mymaster
|
master: "${REDIS_MASTER_NAME}"
|
||||||
|
|
||||||
logger:
|
logger:
|
||||||
level: ${BOUNCER_LOG_LEVEL}
|
level: 3
|
||||||
format: human
|
format: human
|
||||||
|
|
||||||
bootstrap:
|
|
||||||
dir: /etc/bouncer/bootstrap.d
|
|
||||||
lockTimeout: 30s
|
|
||||||
|
@ -10,7 +10,8 @@ configMapGenerator:
|
|||||||
files:
|
files:
|
||||||
- ./files/config.yml
|
- ./files/config.yml
|
||||||
- ./files/admin-key.json
|
- ./files/admin-key.json
|
||||||
- name: bouncer-admin-bootstrap
|
|
||||||
- name: bouncer-admin-env
|
- name: bouncer-admin-env
|
||||||
literals:
|
literals:
|
||||||
- BOUNCER_LOG_LEVEL=2
|
- REDIS_SENTINEL_HOST="rfs-$(REDIS_SERVICE_NAME)"
|
||||||
|
- REDIS_SENTINEL_PORT="26379"
|
||||||
|
- REDIS_MASTER_NAME="mymaster"
|
||||||
|
@ -4,7 +4,6 @@ metadata:
|
|||||||
name: bouncer-admin
|
name: bouncer-admin
|
||||||
labels:
|
labels:
|
||||||
app: bouncer-admin
|
app: bouncer-admin
|
||||||
io.kompose.service: bouncer-admin
|
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
selector:
|
selector:
|
||||||
@ -14,38 +13,26 @@ spec:
|
|||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: bouncer-admin
|
app: bouncer-admin
|
||||||
io.kompose.service: bouncer-admin
|
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: bouncer-admin
|
- name: bouncer-admin
|
||||||
image: bouncer
|
image: reg.cadoles.com/cadoles/bouncer:v2023.7.8-b44ff2a
|
||||||
command:
|
command: ["bouncer"]
|
||||||
[
|
args: ["--debug", "-c", "/etc/bouncer/config.yml", "server", "admin", "run"]
|
||||||
"bouncer",
|
|
||||||
"--debug",
|
|
||||||
"-c",
|
|
||||||
"/etc/bouncer/config.yml",
|
|
||||||
"server",
|
|
||||||
"admin",
|
|
||||||
"run",
|
|
||||||
]
|
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
resources: {}
|
|
||||||
ports:
|
|
||||||
- name: bouncer-admin
|
|
||||||
containerPort: 8081
|
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: bouncer-admin-env
|
name: bouncer-admin-env
|
||||||
|
env:
|
||||||
|
- name: REDIS_SENTINEL_HOST
|
||||||
|
value: "rfs-$(REDIS_SERVICE_NAME)"
|
||||||
|
ports:
|
||||||
|
- name: bouncer-admin
|
||||||
|
containerPort: 8081
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /etc/bouncer/
|
- mountPath: /etc/bouncer/
|
||||||
name: bouncer-admin-config
|
name: bouncer-admin-config
|
||||||
- mountPath: /etc/bouncer/bootstrap.d
|
|
||||||
name: bouncer-admin-bootstrap
|
|
||||||
volumes:
|
volumes:
|
||||||
- name: bouncer-admin-config
|
- name: bouncer-admin-config
|
||||||
configMap:
|
configMap:
|
||||||
name: bouncer-admin-config
|
name: bouncer-admin-config
|
||||||
- name: bouncer-admin-bootstrap
|
|
||||||
configMap:
|
|
||||||
name: bouncer-admin-bootstrap
|
|
||||||
|
@ -9,6 +9,6 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: bouncer-admin
|
- name: bouncer-admin
|
||||||
port: 8081
|
port: 8081
|
||||||
targetPort: bouncer-admin
|
targetPort: 8080
|
||||||
selector:
|
selector:
|
||||||
io.kompose.service: bouncer-admin
|
io.kompose.service: bouncer-admin
|
||||||
|
@ -14,9 +14,9 @@ layers:
|
|||||||
|
|
||||||
redis:
|
redis:
|
||||||
addresses:
|
addresses:
|
||||||
- rfs-bouncer-redis:${RFS_BOUNCER_REDIS_SERVICE_PORT}
|
- ${RFS_BOUNCER_REDIS_SERVICE_HOST}:${RFS_BOUNCER_REDIS_SERVICE_PORT}
|
||||||
master: mymaster
|
master: ""
|
||||||
|
|
||||||
logger:
|
logger:
|
||||||
level: ${BOUNCER_LOG_LEVEL}
|
level: 3
|
||||||
format: human
|
format: human
|
||||||
|
@ -9,6 +9,3 @@ configMapGenerator:
|
|||||||
- name: bouncer-server-config
|
- name: bouncer-server-config
|
||||||
files:
|
files:
|
||||||
- ./files/config.yml
|
- ./files/config.yml
|
||||||
- name: bouncer-server-env
|
|
||||||
literals:
|
|
||||||
- BOUNCER_LOG_LEVEL=2
|
|
||||||
|
@ -4,7 +4,6 @@ metadata:
|
|||||||
name: bouncer-server
|
name: bouncer-server
|
||||||
labels:
|
labels:
|
||||||
app: bouncer-server
|
app: bouncer-server
|
||||||
io.kompose.service: bouncer-server
|
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
selector:
|
selector:
|
||||||
@ -14,25 +13,12 @@ spec:
|
|||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: bouncer-server
|
app: bouncer-server
|
||||||
io.kompose.service: bouncer-server
|
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: bouncer-server
|
- name: bouncer-server
|
||||||
image: bouncer
|
image: reg.cadoles.com/cadoles/bouncer:v2023.7.8-b44ff2a
|
||||||
command:
|
command: ["bouncer", "-c", "/etc/bouncer/config.yml", "server", "proxy", "run"]
|
||||||
[
|
|
||||||
"bouncer",
|
|
||||||
"-c",
|
|
||||||
"/etc/bouncer/config.yml",
|
|
||||||
"server",
|
|
||||||
"proxy",
|
|
||||||
"run",
|
|
||||||
]
|
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
envFrom:
|
|
||||||
- configMapRef:
|
|
||||||
name: bouncer-server-env
|
|
||||||
resources: {}
|
|
||||||
ports:
|
ports:
|
||||||
- name: bouncer-server
|
- name: bouncer-server
|
||||||
containerPort: 8080
|
containerPort: 8080
|
||||||
|
@ -9,6 +9,6 @@ spec:
|
|||||||
ports:
|
ports:
|
||||||
- name: bouncer-server
|
- name: bouncer-server
|
||||||
port: 8080
|
port: 8080
|
||||||
targetPort: bouncer-server
|
targetPort: 8080
|
||||||
selector:
|
selector:
|
||||||
io.kompose.service: bouncer-server
|
io.kompose.service: bouncer-server
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
from: ["*"]
|
|
||||||
to: https://www.cadoles.com
|
|
||||||
enabled: true
|
|
||||||
weight: 0
|
|
||||||
layers:
|
|
||||||
my-queue:
|
|
||||||
type: queue
|
|
||||||
enabled: true
|
|
||||||
weight: 0
|
|
||||||
options:
|
|
||||||
capacity: 10
|
|
@ -16,17 +16,3 @@ patches:
|
|||||||
target:
|
target:
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
version: v1
|
version: v1
|
||||||
|
|
||||||
configMapGenerator:
|
|
||||||
- name: bouncer-admin-bootstrap
|
|
||||||
behavior: merge
|
|
||||||
files:
|
|
||||||
- ./files/bouncer/bootstrap.d/cadoles.yml
|
|
||||||
- name: bouncer-admin-env
|
|
||||||
behavior: merge
|
|
||||||
literals:
|
|
||||||
- BOUNCER_LOG_LEVEL=0
|
|
||||||
- name: bouncer-server-env
|
|
||||||
behavior: merge
|
|
||||||
literals:
|
|
||||||
- BOUNCER_LOG_LEVEL=0
|
|
||||||
|
@ -141,15 +141,12 @@ proxy:
|
|||||||
#
|
#
|
||||||
# Les modes "standalone", "sentinel" et "cluster" de Redis sont supportés:
|
# Les modes "standalone", "sentinel" et "cluster" de Redis sont supportés:
|
||||||
# - Mode "standalone": renseigner une seule entrée dans redis.addresses;
|
# - Mode "standalone": renseigner une seule entrée dans redis.addresses;
|
||||||
# - Mode "sentinel": renseigner le nom du master sentinel dans redis.master et une ou plusieurs adresses dans redis.addresses;
|
# - Mode "sentinel": renseigner une adresse dans redis.master et une ou plusieurs adresses dans redis.addresses;
|
||||||
# - Mode "cluster": renseigner plusieurs adresses dans redis.addresses et laisser redis.master vide.
|
# - Mode "cluster": renseigner plusieurs adresses dans redis.addresses et laisser redis.master vide.
|
||||||
redis:
|
redis:
|
||||||
addresses:
|
addresses:
|
||||||
- localhost:6379
|
- localhost:6379
|
||||||
master: ""
|
master: ""
|
||||||
writeTimeout: 30s
|
|
||||||
readTimeout: 30s
|
|
||||||
dialTimeout: 30s
|
|
||||||
|
|
||||||
# Configuration des logs
|
# Configuration des logs
|
||||||
logger:
|
logger:
|
||||||
@ -159,7 +156,7 @@ logger:
|
|||||||
# 2 - WARNING
|
# 2 - WARNING
|
||||||
# 3 - ERROR
|
# 3 - ERROR
|
||||||
# 4 - FATAL
|
# 4 - FATAL
|
||||||
level: 2
|
level: 1
|
||||||
# Format des logs, "human" ou "json"
|
# Format des logs, "human" ou "json"
|
||||||
format: human
|
format: human
|
||||||
|
|
||||||
@ -177,36 +174,3 @@ layers:
|
|||||||
# Répertoire contenant les templates
|
# Répertoire contenant les templates
|
||||||
templateDir: "/etc/bouncer/layers/circuitbreaker/templates"
|
templateDir: "/etc/bouncer/layers/circuitbreaker/templates"
|
||||||
|
|
||||||
# Configuration d'une série de proxy/layers
|
|
||||||
# à créer par défaut par le serveur d'administration
|
|
||||||
bootstrap:
|
|
||||||
# Répertoire contenant les définitions de proxy à créer
|
|
||||||
# par défaut. Les fichiers seront récupérés si ils
|
|
||||||
# correspondent au patron de nommage suivant:
|
|
||||||
#
|
|
||||||
# <bootstrap_dir>/<proxy_name>.yml
|
|
||||||
#
|
|
||||||
# Si l'attribut est vide ou absent le chargement des fichiers
|
|
||||||
# est désactivé.
|
|
||||||
dir: /etc/bouncer/bootstrap.d
|
|
||||||
# Délai d'expiration du verrou distribué utilisé lors du chargement
|
|
||||||
# des définitions de proxy par défaut.
|
|
||||||
lockTimeout: 30s
|
|
||||||
# Tableau associatif de définition de proxies à créer par
|
|
||||||
# défaut par le serveur d'administration.
|
|
||||||
# Si `proxies` et `dir` sont tous les deux définis, les fichiers
|
|
||||||
# présents dans le répertoire `dir` surchargeront les valeurs définies
|
|
||||||
# dans `proxies`.
|
|
||||||
# Par défault non défini
|
|
||||||
proxies:
|
|
||||||
# my-proxy:
|
|
||||||
# enabled: true
|
|
||||||
# from: ["*"]
|
|
||||||
# to: "https://example.net"
|
|
||||||
# weight: 0
|
|
||||||
# layers:
|
|
||||||
# my-layer:
|
|
||||||
# type: queue
|
|
||||||
# enabled: false
|
|
||||||
# weight: 0
|
|
||||||
# options: {"capacity": 100}
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
${BASE_URL}/blog/
|
http://localhost:8080/blog/
|
||||||
${BASE_URL}/services/
|
http://localhost:8080/services/
|
||||||
${BASE_URL}
|
http://localhost:8080/
|
||||||
${BASE_URL}/recrutement/
|
http://localhost:8080/recrutement/
|
||||||
${BASE_URL}/faq/
|
http://localhost:8080/faq/
|
||||||
${BASE_URL}/societe/histoire/
|
http://localhost:8080/societe/histoire/
|
@ -26,28 +26,17 @@ build:
|
|||||||
sha256: {}
|
sha256: {}
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- image: bouncer
|
- image: reg.cadoles.com/cadoles/bouncer
|
||||||
context: .
|
context: .
|
||||||
sync:
|
sync:
|
||||||
infer:
|
infer:
|
||||||
- cmd/**
|
- cmd/**
|
||||||
- internal/**
|
- internal/**
|
||||||
- layers/**
|
- layers/**
|
||||||
- misc/**
|
- tools/**
|
||||||
|
- data/**
|
||||||
docker:
|
docker:
|
||||||
dockerfile: Dockerfile
|
dockerfile: misc/images/bouncer/Dockerfile
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
statusCheckDeadlineSeconds: 600
|
statusCheckDeadlineSeconds: 600
|
||||||
|
|
||||||
portForward:
|
|
||||||
- resourceType: service
|
|
||||||
resourceName: bouncer-admin
|
|
||||||
namespace: bouncer-dev
|
|
||||||
port: 8081
|
|
||||||
localPort: 9999
|
|
||||||
- resourceType: service
|
|
||||||
resourceName: bouncer-server
|
|
||||||
namespace: bouncer-dev
|
|
||||||
port: 8080
|
|
||||||
localPort: 9000 # *Optional*
|
|
||||||
|
Reference in New Issue
Block a user