Compare commits

..

1 Commits

Author SHA1 Message Date
c55c723868 chore: Create branch for project modifications testing
All checks were successful
arcad/emissary/pipeline/head This commit looks good
2023-08-28 11:26:44 +02:00
49 changed files with 218 additions and 2913 deletions

View File

@ -1,14 +0,0 @@
/apps
/bin
/dist
/out
/tmp
/tools
/.emissary-token
/.env
/agent-key.json
/server-key.json
/CHANGELOG.md
/state.json
/*.sqlite*
/.mktools

View File

@ -105,9 +105,6 @@ nfpms:
file_info: file_info:
mode: 0755 mode: 0755
packager: apk packager: apk
- src: misc/packaging/openrc/emissary-server.logrotate.conf
dst: /etc/logrotate.d/emissary-server
packager: apk
- dst: /var/lib/emissary - dst: /var/lib/emissary
type: dir type: dir
file_info: file_info:
@ -150,8 +147,5 @@ nfpms:
file_info: file_info:
mode: 0755 mode: 0755
packager: apk packager: apk
- src: misc/packaging/openrc/emissary-agent.logrotate.conf
dst: /etc/logrotate.d/emissary-agent
packager: apk
scripts: scripts:
postinstall: "misc/packaging/common/postinstall-agent.sh" postinstall: "misc/packaging/common/postinstall-agent.sh"

View File

@ -1,12 +1,4 @@
FROM alpine as certs FROM golang:1.19 AS BUILD
RUN apk update && apk add ca-certificates curl openssl bash
RUN curl -k https://forge.cadoles.com/Cadoles/Jenkins/raw/branch/master/resources/com/cadoles/common/add-letsencrypt-ca.sh | bash
#####################################
# Emissary Server #
#####################################
FROM golang:1.21 AS build-emissary-server
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y make && apt-get install -y make
@ -15,9 +7,9 @@ COPY . /src
WORKDIR /src WORKDIR /src
RUN make mktools && make GORELEASER_ARGS="build --snapshot --clean --single-target --id emissary-server" goreleaser RUN make GORELEASER_ARGS='build --rm-dist --single-target --snapshot' release
FROM busybox:latest AS emissary-server FROM busybox:latest AS RUNTIME
ARG DUMB_INIT_VERSION=1.2.5 ARG DUMB_INIT_VERSION=1.2.5
@ -27,47 +19,11 @@ RUN mkdir -p /usr/local/bin \
ENTRYPOINT ["/usr/local/bin/dumb-init", "--"] ENTRYPOINT ["/usr/local/bin/dumb-init", "--"]
COPY --from=build-emissary-server /src/dist/emissary-server_linux_amd64_v1 /app COPY --from=BUILD /src/dist/emissary_linux_amd64_v1 /app
COPY misc/docker/server.yml /etc/emissary/server.yml COPY --from=BUILD /src/tmp/config.yml /etc/emissary/config.yml
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
EXPOSE 3000 EXPOSE 3000
RUN mkdir -p /data ENTRYPOINT ["/app/emissary"]
CMD [ "/app/emissary", "-c", "/etc/emissary/config.yml", "server", "run"] CMD ["server", "run", "-c", "/etc/emissary/config.yml"]
#####################################
# Emissary Agent #
#####################################
FROM golang:1.21 AS build-emissary-agent
RUN apt-get update \
&& apt-get install -y make
COPY . /src
WORKDIR /src
RUN make mktools && make GORELEASER_ARGS="build --snapshot --clean --single-target --id emissary-agent" goreleaser
FROM busybox:latest AS emissary-agent
ARG DUMB_INIT_VERSION=1.2.5
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", "--"]
COPY --from=build-emissary-agent /src/dist/emissary-agent_linux_amd64_v1 /app
COPY --chmod=777 misc/docker/docker-agent-wrapper.sh /usr/local/bin/docker-agent-wrapper
COPY misc/docker/agent.yml /etc/emissary/agent.yml
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
RUN mkdir -p /data
CMD [ "/usr/local/bin/docker-agent-wrapper", "/app/emissary", "-c", "/etc/emissary/agent.yml", "agent", "run" ]

View File

@ -1,11 +1,12 @@
LINT_ARGS ?= --timeout 5m LINT_ARGS ?= --timeout 5m
GORELEASER_ARGS ?= release --snapshot --clean GORELEASER_VERSION ?= v1.13.1
GORELEASER_ARGS ?= release --snapshot --rm-dist
GITCHLOG_ARGS ?= GITCHLOG_ARGS ?=
SHELL := /bin/bash SHELL := /bin/bash
EMISSARY_VERSION ?= EMISSARY_VERSION ?=
DOCKER_IMAGE_NAME ?= reg.cadoles.com/cadoles/emissary DOCKER_IMAGE_NAME ?= bornholm/emissary
DOCKER_IMAGE_TAG ?= $(MKT_PROJECT_VERSION) DOCKER_IMAGE_TAG ?= $(MKT_PROJECT_VERSION)
GOTEST_ARGS ?= -short GOTEST_ARGS ?= -short
@ -70,23 +71,17 @@ dump-config: build-emissary
./bin/emissary config dump > tmp/config.yml ./bin/emissary config dump > tmp/config.yml
.PHONY: goreleaser .PHONY: goreleaser
goreleaser: .env .mktools goreleaser: .mktools
( set -o allexport && source .env && set +o allexport && curl -sfL https://goreleaser.com/static/run | GORELEASER_CURRENT_TAG="$(MKT_PROJECT_VERSION)" bash /dev/stdin $(GORELEASER_ARGS) ) ( set -o allexport && source .env && set +o allexport && VERSION=$(GORELEASER_VERSION) curl -sfL https://goreleaser.com/static/run | GORELEASER_CURRENT_TAG="$(MKT_PROJECT_VERSION)" bash /dev/stdin $(GORELEASER_ARGS) )
install-git-hooks: install-git-hooks:
git config core.hooksPath .githooks git config core.hooksPath .githooks
docker-build: docker-build-agent docker-build-server docker-build:
docker build -t $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) .
docker-build-%: docker-release:
docker build --target emissary-$* -t $(DOCKER_IMAGE_NAME)-$*:latest . docker push $(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)
docker-release: docker-release-agent docker-release-server
docker-release-%:
docker tag $(DOCKER_IMAGE_NAME)-$*:latest $(DOCKER_IMAGE_NAME)-$*:$(DOCKER_IMAGE_TAG)
docker push $(DOCKER_IMAGE_NAME)-$*:latest
docker push $(DOCKER_IMAGE_NAME)-$*:$(DOCKER_IMAGE_TAG)
deploy-openwrt-agent: deploy-openwrt-agent:
$(MAKE) GOARCH="arm" GORELEASER_ARGS='build --single-target --snapshot --clean' goreleaser $(MAKE) GOARCH="arm" GORELEASER_ARGS='build --single-target --snapshot --clean' goreleaser
@ -131,15 +126,13 @@ load-sample-specs:
cat misc/spec-samples/app.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name app.emissary.cadoles.com cat misc/spec-samples/app.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name app.emissary.cadoles.com
cat misc/spec-samples/proxy.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name proxy.emissary.cadoles.com cat misc/spec-samples/proxy.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name proxy.emissary.cadoles.com
cat misc/spec-samples/mdns.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name mdns.emissary.cadoles.com cat misc/spec-samples/mdns.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name mdns.emissary.cadoles.com
cat misc/spec-samples/uci.emissary.cadoles.com.json | ./bin/server api agent spec update -a $(AGENT_ID) --no-patch --spec-data - --spec-name uci.emissary.cadoles.com
version: .mktools version: .mktools
@echo $(MKT_PROJECT_VERSION) @echo $(MKT_PROJECT_VERSION)
update-edge-lib: update-edge-lib:
git pull --rebase git pull --rebase
go clean -modcache GOPROXY=direct GOPRIVATE=forge.cadoles.com/arcad/edge go get -u forge.cadoles.com/arcad/edge
GONOPROXY=forge.cadoles.com/arcad/edge GOPRIVATE=forge.cadoles.com/arcad/edge go get -v -u forge.cadoles.com/arcad/edge
go mod tidy go mod tidy
$(MAKE) test $(MAKE) test
git add go.mod go.sum git add go.mod go.sum

View File

@ -7,7 +7,6 @@
- (FR) - [Premiers pas](./tutorials/fr/first-steps.md) - (FR) - [Premiers pas](./tutorials/fr/first-steps.md)
- (FR) - [Déployer un serveur mandataire inverse sur un agent](./tutorials/fr/deploy-reverse-proxy.md) - (FR) - [Déployer un serveur mandataire inverse sur un agent](./tutorials/fr/deploy-reverse-proxy.md)
- (FR) - [Déployer une configuration UCI personnalisée sur un agent](./tutorials/fr/deploy-uci-configuration.md) - (FR) - [Déployer une configuration UCI personnalisée sur un agent](./tutorials/fr/deploy-uci-configuration.md)
- (FR) - [Démarrer un agent avec Docker](./tutorials/fr/docker-agent.md)
## References ## References

View File

@ -1,10 +0,0 @@
# Lancer un agent avec Docker
```shell
docker run \
--rm -it \
--network bridge \
-v emissary-agent-data:/data \
-e EMISSARY_AGENT_SERVER_URL=<server_url> \
reg.cadoles.com/cadoles/emissary-agent:latest
```

28
go.mod
View File

@ -1,11 +1,9 @@
module forge.cadoles.com/Cadoles/emissary module forge.cadoles.com/Cadoles/emissary
go 1.21 go 1.19
toolchain go1.21.2
require ( require (
forge.cadoles.com/arcad/edge v0.0.0-20231130180951-32f04af138d7 forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978
github.com/Masterminds/sprig/v3 v3.2.3 github.com/Masterminds/sprig/v3 v3.2.3
github.com/alecthomas/participle/v2 v2.0.0-beta.5 github.com/alecthomas/participle/v2 v2.0.0-beta.5
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
@ -16,7 +14,7 @@ require (
github.com/denisbrodbeck/machineid v1.0.1 github.com/denisbrodbeck/machineid v1.0.1
github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c github.com/dop251/goja v0.0.0-20230304130813-e2f543bf4b4c
github.com/evanphx/json-patch/v5 v5.6.0 github.com/evanphx/json-patch/v5 v5.6.0
github.com/getsentry/sentry-go v0.25.0 github.com/go-chi/chi v4.1.2+incompatible
github.com/go-chi/cors v1.2.1 github.com/go-chi/cors v1.2.1
github.com/golang-migrate/migrate/v4 v4.15.2 github.com/golang-migrate/migrate/v4 v4.15.2
github.com/jackc/pgx/v5 v5.3.1 github.com/jackc/pgx/v5 v5.3.1
@ -28,7 +26,7 @@ require (
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/qri-io/jsonschema v0.2.1 github.com/qri-io/jsonschema v0.2.1
github.com/urfave/cli/v2 v2.24.4 github.com/urfave/cli/v2 v2.24.4
gitlab.com/wpetit/goweb v0.0.0-20231019192040-4c72331a7648 gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
modernc.org/sqlite v1.21.0 modernc.org/sqlite v1.21.0
) )
@ -36,7 +34,6 @@ require (
require ( require (
github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/allegro/bigcache/v3 v3.1.0 // indirect
github.com/barnybug/go-cast v0.0.0-20201201064555-a87ccbc26692 // indirect github.com/barnybug/go-cast v0.0.0-20201201064555-a87ccbc26692 // indirect
github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd // indirect github.com/dop251/goja_nodejs v0.0.0-20230320130059-dcf93ba651dd // indirect
github.com/gabriel-vasile/mimetype v1.4.1 // indirect github.com/gabriel-vasile/mimetype v1.4.1 // indirect
@ -44,13 +41,10 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/mdns v1.0.5 // indirect github.com/hashicorp/mdns v1.0.5 // indirect
github.com/huandu/xstrings v1.3.3 // indirect github.com/huandu/xstrings v1.3.3 // indirect
github.com/igm/sockjs-go/v3 v3.0.2 // indirect github.com/igm/sockjs-go/v3 v3.0.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect github.com/imdario/mergo v0.3.12 // indirect
github.com/keegancsmith/rpc v1.3.0 // indirect
github.com/klauspost/compress v1.16.6 // indirect
github.com/miekg/dns v1.1.53 // indirect github.com/miekg/dns v1.1.53 // 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
@ -58,8 +52,7 @@ require (
github.com/orcaman/concurrent-map v1.0.0 // indirect github.com/orcaman/concurrent-map v1.0.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cast v1.3.1 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect golang.org/x/net v0.9.0 // indirect
golang.org/x/net v0.11.0 // indirect
google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9 // indirect google.golang.org/genproto v0.0.0-20220728213248-dd149ef739b9 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )
@ -82,7 +75,7 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jackc/puddle/v2 v2.2.0 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/leodido/go-urn v1.2.2 // indirect github.com/leodido/go-urn v1.2.2 // indirect
github.com/lestrrat-go/blackmagic v1.0.1 // indirect github.com/lestrrat-go/blackmagic v1.0.1 // indirect
@ -103,14 +96,15 @@ require (
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.opencensus.io v0.24.0 // indirect go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect
golang.org/x/crypto v0.10.0 // indirect golang.org/x/crypto v0.7.0 // indirect
golang.org/x/mod v0.10.0 // indirect golang.org/x/mod v0.10.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.9.0 // indirect golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.9.0 // indirect golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.10.0 // indirect golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.8.0 // indirect golang.org/x/tools v0.8.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
lukechampine.com/uint128 v1.2.0 // indirect lukechampine.com/uint128 v1.2.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect modernc.org/cc/v3 v3.40.0 // indirect

75
go.sum
View File

@ -54,8 +54,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
forge.cadoles.com/arcad/edge v0.0.0-20231130180951-32f04af138d7 h1:aDiZNT87sSC014GIapyEZ9O98EHOWHBNLtJR6p1ngG0= forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978 h1:fekSRSb8gYcVx8C0B9K6B7+KiFHVixIwvPUkxcnRFp4=
forge.cadoles.com/arcad/edge v0.0.0-20231130180951-32f04af138d7/go.mod h1:DXxP+2fbR3hD3Q4ePoJn6jJItpOyBWx9wNsxCZEh4M4= forge.cadoles.com/arcad/edge v0.0.0-20230426135323-17808d14c978/go.mod h1:uv3wBa+UbcEUb7IiJCj1T96Xo3cmx1BwNxbBYRZhln8=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg=
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
@ -128,7 +128,6 @@ github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkK
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI= github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
github.com/alecthomas/assert/v2 v2.0.3 h1:WKqJODfOiQG0nEJKFKzDIG3E29CN2/4zR9XGJzKIkbg= github.com/alecthomas/assert/v2 v2.0.3 h1:WKqJODfOiQG0nEJKFKzDIG3E29CN2/4zR9XGJzKIkbg=
github.com/alecthomas/assert/v2 v2.0.3/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA=
github.com/alecthomas/chroma v0.7.0/go.mod h1:1U/PfCsTALWWYHDnsIQkxEBM0+6LLe0v8+RSVMOwxeY= github.com/alecthomas/chroma v0.7.0/go.mod h1:1U/PfCsTALWWYHDnsIQkxEBM0+6LLe0v8+RSVMOwxeY=
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
@ -140,7 +139,6 @@ github.com/alecthomas/participle/v2 v2.0.0-beta.5 h1:y6dsSYVb1G5eK6mgmy+BgI3Mw35
github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM= github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM=
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/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -148,8 +146,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk=
github.com/allegro/bigcache/v3 v3.1.0 h1:H2Vp8VOvxcrB91o86fUSVJFqeuz8kpyyB02eH3bSzwk=
github.com/allegro/bigcache/v3 v3.1.0/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
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=
@ -508,17 +504,15 @@ github.com/gabriel-vasile/mimetype v1.4.1 h1:TRWk7se+TOjCYgRth7+1/OYLNiRNIotknkF
github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M= github.com/gabriel-vasile/mimetype v1.4.1/go.mod h1:05Vi0w3Y9c/lNvJOdmIwvrrAhX3rYhfQQCaf9VJcv7M=
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY=
@ -556,10 +550,10 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
@ -679,7 +673,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@ -768,8 +761,6 @@ github.com/hashicorp/go.net v0.0.0-20151006203346-104dcad90073/go.mod h1:hjKkEWc
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v0.0.0-20151206042412-9d85cf22f9f8/go.mod h1:aa76Av3qgPeIQp9Y3qIkTBPieQYNkQ13Kxe7pze9Wb0= github.com/hashicorp/mdns v0.0.0-20151206042412-9d85cf22f9f8/go.mod h1:aa76Av3qgPeIQp9Y3qIkTBPieQYNkQ13Kxe7pze9Wb0=
@ -779,7 +770,6 @@ github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
@ -847,8 +837,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= github.com/jackc/puddle/v2 v2.2.0 h1:RdcDk92EJBuBS55nQMMYFXTxwstHug4jkhT5pq8VxPk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jedib0t/go-pretty/v6 v6.4.4 h1:N+gz6UngBPF4M288kiMURPHELDMIhF/Em35aYuKrsSc= github.com/jedib0t/go-pretty/v6 v6.4.4 h1:N+gz6UngBPF4M288kiMURPHELDMIhF/Em35aYuKrsSc=
github.com/jedib0t/go-pretty/v6 v6.4.4/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI= github.com/jedib0t/go-pretty/v6 v6.4.4/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@ -888,8 +878,6 @@ github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaR
github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/keegancsmith/rpc v1.3.0 h1:wGWOpjcNrZaY8GDYZJfvyxmlLljm3YQWF+p918DXtDk=
github.com/keegancsmith/rpc v1.3.0/go.mod h1:6O2xnOGjPyvIPbvp0MdrOe5r6cu1GZ4JoTzpzDhWeo0=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
@ -901,8 +889,6 @@ github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk=
github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -920,7 +906,7 @@ 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=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4= github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4= github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ= github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
@ -990,7 +976,6 @@ github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOq
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY=
@ -1126,11 +1111,8 @@ github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
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-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/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=
@ -1192,7 +1174,6 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
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.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
@ -1228,9 +1209,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@ -1291,8 +1271,6 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
@ -1334,8 +1312,8 @@ github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPS
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
gitlab.com/wpetit/goweb v0.0.0-20231019192040-4c72331a7648 h1:t2UQmCmUoElIBBuVTqxqo8DcTJA/exQ/Q7XycfLqCZo= gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b h1:nkvOl8TCj/mErADnwFFynjxBtC+hHsrESw6rw56JGmg=
gitlab.com/wpetit/goweb v0.0.0-20231019192040-4c72331a7648/go.mod h1:WdxGjM3HJWgBkUa4TwaTXUqY2BnRKlNSyUIv1aF4jxk= gitlab.com/wpetit/goweb v0.0.0-20230419082146-a94d9ed7202b/go.mod h1:3sus4zjoUv1GB7eDLL60QaPkUnXJCWBpjvbe0jWifeY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
@ -1389,8 +1367,6 @@ go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
@ -1425,9 +1401,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/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.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.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/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-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1556,8 +1531,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/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-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1722,8 +1697,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.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.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
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-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -1733,8 +1708,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
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=
@ -1749,8 +1724,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/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-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=
@ -2005,7 +1980,6 @@ google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -2020,8 +1994,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
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.29.1 h1:7QBf+IK2gx70Ap/hDsOmam3GE0v9HicjfEdAxE62UoM= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/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=
@ -2132,7 +2106,6 @@ modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=
modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw= modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
@ -2166,14 +2139,12 @@ modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo=
modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws= modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws=
modernc.org/tcl v1.15.1/go.mod h1:aEjeGJX2gz1oWKOLDVZ2tnEWLUrIn8H+GFu+akoDhqs=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
modernc.org/z v1.7.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ=
modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -43,15 +43,13 @@ func (a *Agent) Run(ctx context.Context) error {
logger.Debug(ctx, "registering agent") logger.Debug(ctx, "registering agent")
if err := a.registerAgent(ctx, client, state); err != nil { if err := a.registerAgent(ctx, client, state); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not register agent", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not register agent", logger.CapturedE(err))
} }
logger.Debug(ctx, "state before reconciliation", logger.F("state", state)) logger.Debug(ctx, "state before reconciliation", logger.F("state", state))
if err := a.Reconcile(ctx, state); err != nil { if err := a.Reconcile(ctx, state); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not reconcile node with state", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not reconcile node with state", logger.CapturedE(err))
return return
} }
@ -81,8 +79,7 @@ func (a *Agent) Reconcile(ctx context.Context, state *State) error {
) )
if err := ctrl.Reconcile(ctrlCtx, state); err != nil { if err := ctrl.Reconcile(ctrlCtx, state); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not reconcile", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not reconcile", logger.CapturedE(err))
} }
} }
@ -113,10 +110,9 @@ func (a *Agent) collectMetadata(ctx context.Context) (map[string]any, error) {
for _, collector := range a.collectors { for _, collector := range a.collectors {
name, value, err := collector.Collect(ctx) name, value, err := collector.Collect(ctx)
if err != nil { if err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "could not collect metadata", ctx, "could not collect metadata",
logger.CapturedE(err), logger.F("name", name), logger.E(errors.WithStack(err)), logger.F("name", name),
) )
continue continue

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"net" "net"
"path/filepath"
"text/template" "text/template"
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec" "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
@ -16,60 +17,47 @@ import (
appModule "forge.cadoles.com/arcad/edge/pkg/module/app" appModule "forge.cadoles.com/arcad/edge/pkg/module/app"
"forge.cadoles.com/arcad/edge/pkg/module/blob" "forge.cadoles.com/arcad/edge/pkg/module/blob"
"forge.cadoles.com/arcad/edge/pkg/module/cast" "forge.cadoles.com/arcad/edge/pkg/module/cast"
"forge.cadoles.com/arcad/edge/pkg/module/fetch"
fetchModule "forge.cadoles.com/arcad/edge/pkg/module/fetch" fetchModule "forge.cadoles.com/arcad/edge/pkg/module/fetch"
netModule "forge.cadoles.com/arcad/edge/pkg/module/net" netModule "forge.cadoles.com/arcad/edge/pkg/module/net"
"forge.cadoles.com/arcad/edge/pkg/module/rpc"
shareModule "forge.cadoles.com/arcad/edge/pkg/module/share" shareModule "forge.cadoles.com/arcad/edge/pkg/module/share"
shareSqlite "forge.cadoles.com/arcad/edge/pkg/module/share/sqlite"
"forge.cadoles.com/arcad/edge/pkg/storage" "forge.cadoles.com/arcad/edge/pkg/storage"
"forge.cadoles.com/arcad/edge/pkg/storage/driver" "forge.cadoles.com/arcad/edge/pkg/storage/sqlite"
"forge.cadoles.com/arcad/edge/pkg/storage/share"
"github.com/Masterminds/sprig/v3" "github.com/Masterminds/sprig/v3"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwa"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger" "gitlab.com/wpetit/goweb/logger"
// Register storage drivers
_ "forge.cadoles.com/arcad/edge/pkg/storage/driver/cache"
_ "forge.cadoles.com/arcad/edge/pkg/storage/driver/rpc"
_ "forge.cadoles.com/arcad/edge/pkg/storage/driver/sqlite"
) )
type Dependencies struct { type Dependencies struct {
Bus bus.Bus Bus bus.Bus
DocumentStore storage.DocumentStore DocumentStore storage.DocumentStore
BlobStore storage.BlobStore BlobStore storage.BlobStore
ShareStore share.Store
KeySet jwk.Set KeySet jwk.Set
AppRepository appModule.Repository AppRepository appModule.Repository
AppID app.ID AppID app.ID
ShareRepository shareModule.Repository
} }
const defaultSQLiteParams = "?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs *spec.Spec) ([]edgeHTTP.HandlerOptionFunc, error) { func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs *spec.Spec) ([]edgeHTTP.HandlerOptionFunc, error) {
appEntry, exists := specs.Apps[appKey] dataDir, err := c.ensureAppDataDir(ctx, appKey)
if !exists {
return nil, errors.Errorf("could not find app entry '%s'", appKey)
}
storage := appEntry.Storage
if storage == nil {
return nil, errors.Errorf("could not find app entry '%s' storage configuration", appKey)
}
documentStore, err := driver.NewDocumentStore(appEntry.Storage.DocumentStoreDSN)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.Wrap(err, "could not retrieve app data dir")
} }
blobStore, err := driver.NewBlobStore(appEntry.Storage.BlobStoreDSN) dbFile := filepath.Join(dataDir, appKey+".sqlite")
db, err := sqlite.Open(dbFile + defaultSQLiteParams)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.Wrapf(err, "could not open database file '%s'", dbFile)
} }
shareStore, err := driver.NewShareStore(appEntry.Storage.ShareStoreDSN) shareDBFile := filepath.Join(dataDir, "shared.sqlite")
shareDB, err := sqlite.Open(shareDBFile + defaultSQLiteParams)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.Wrapf(err, "could not open database file '%s'", shareDBFile)
} }
keySet, err := getAuthKeySet(specs.Config) keySet, err := getAuthKeySet(specs.Config)
@ -88,37 +76,24 @@ func (c *Controller) getHandlerOptions(ctx context.Context, appKey string, specs
mounts = append(mounts, authMount) mounts = append(mounts, authMount)
} }
mounts = append( mounts = append(mounts, appModule.Mount(c.appRepository))
mounts,
appModule.Mount(c.appRepository),
blob.Mount(10<<(10*2)), // 10Mb
fetch.Mount(),
)
deps := Dependencies{ deps := Dependencies{
Bus: memory.NewBus(), Bus: memory.NewBus(),
DocumentStore: documentStore, DocumentStore: sqlite.NewDocumentStoreWithDB(db),
BlobStore: blobStore, BlobStore: sqlite.NewBlobStoreWithDB(db),
ShareStore: shareStore,
KeySet: keySet, KeySet: keySet,
AppRepository: c.appRepository, AppRepository: c.appRepository,
AppID: app.ID(appKey), AppID: app.ID(appKey),
ShareRepository: shareSqlite.NewRepositoryWithDB(shareDB),
} }
modules := c.getAppModules(deps) modules := c.getAppModules(deps)
anonymousUserMiddleware, err := getAnonymousUserMiddleware(specs.Config.Auth)
if err != nil {
return nil, errors.Wrap(err, "could not get anonymous user middleware")
}
options := []edgeHTTP.HandlerOptionFunc{ options := []edgeHTTP.HandlerOptionFunc{
edgeHTTP.WithBus(deps.Bus), edgeHTTP.WithBus(deps.Bus),
edgeHTTP.WithServerModules(modules...), edgeHTTP.WithServerModules(modules...),
edgeHTTP.WithHTTPMounts(mounts...), edgeHTTP.WithHTTPMounts(mounts...),
edgeHTTP.WithHTTPMiddlewares(
anonymousUserMiddleware,
),
} }
return options, nil return options, nil
@ -205,10 +180,9 @@ func createResolveAppURL(specs *spec.Spec) (ResolveAppURLFunc, error) {
for ifaceName, ifaceTmpl := range ifaceMappings { for ifaceName, ifaceTmpl := range ifaceMappings {
iface, err := net.InterfaceByName(ifaceName) iface, err := net.InterfaceByName(ifaceName)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(
logger.Warn(
ctx, "could not find interface", ctx, "could not find interface",
logger.CapturedE(err), logger.F("iface", ifaceName), logger.E(errors.WithStack(err)), logger.F("iface", ifaceName),
) )
continue continue
@ -216,10 +190,9 @@ func createResolveAppURL(specs *spec.Spec) (ResolveAppURLFunc, error) {
addresses, err := iface.Addrs() addresses, err := iface.Addrs()
if err != nil { if err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "could not list interface addresses", ctx, "could not list interface addresses",
logger.CapturedE(err), logger.E(errors.WithStack(err)),
logger.F("iface", iface.Name), logger.F("iface", iface.Name),
) )
@ -229,10 +202,9 @@ func createResolveAppURL(specs *spec.Spec) (ResolveAppURLFunc, error) {
for _, addr := range addresses { for _, addr := range addresses {
ifaIP, network, err := net.ParseCIDR(addr.String()) ifaIP, network, err := net.ParseCIDR(addr.String())
if err != nil { if err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "could not parse interface ip", ctx, "could not parse interface ip",
logger.CapturedE(err), logger.E(errors.WithStack(err)),
logger.F("iface", iface.Name), logger.F("iface", iface.Name),
) )
@ -307,12 +279,12 @@ func (c *Controller) getAppModules(deps Dependencies) []app.ServerModuleFactory
cast.CastModuleFactory(), cast.CastModuleFactory(),
module.LifecycleModuleFactory(), module.LifecycleModuleFactory(),
netModule.ModuleFactory(deps.Bus), netModule.ModuleFactory(deps.Bus),
rpc.ModuleFactory(deps.Bus), module.RPCModuleFactory(deps.Bus),
module.StoreModuleFactory(deps.DocumentStore), module.StoreModuleFactory(deps.DocumentStore),
blob.ModuleFactory(deps.Bus, deps.BlobStore), blob.ModuleFactory(deps.Bus, deps.BlobStore),
authModuleFactory(deps.KeySet), authModuleFactory(deps.KeySet),
appModule.ModuleFactory(deps.AppRepository), appModule.ModuleFactory(deps.AppRepository),
fetchModule.ModuleFactory(deps.Bus), fetchModule.ModuleFactory(deps.Bus),
shareModule.ModuleFactory(deps.AppID, deps.ShareStore), shareModule.ModuleFactory(deps.AppID, deps.ShareRepository),
} }
} }

View File

@ -63,16 +63,14 @@ func (r *AppRepository) List(ctx context.Context) ([]*app.Manifest, error) {
bundle, err := bundle.FromPath(path) bundle, err := bundle.FromPath(path)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(bundleCtx, "could not load bundle", logger.E(errors.WithStack(err)))
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
continue continue
} }
manifest, err := app.LoadManifest(bundle) manifest, err := app.LoadManifest(bundle)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(bundleCtx, "could not load manifest", logger.E(errors.WithStack(err)))
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
continue continue
} }
@ -99,16 +97,14 @@ func (r *AppRepository) findManifest(ctx context.Context, id app.ID) (*app.Manif
bundle, err := bundle.FromPath(path) bundle, err := bundle.FromPath(path)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(bundleCtx, "could not load bundle", logger.E(errors.WithStack(err)))
logger.Error(bundleCtx, "could not load bundle", logger.CapturedE(err))
continue continue
} }
manifest, err := app.LoadManifest(bundle) manifest, err := app.LoadManifest(bundle)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(bundleCtx, "could not load manifest", logger.E(errors.WithStack(err)))
logger.Error(bundleCtx, "could not load manifest", logger.CapturedE(err))
continue continue
} }

View File

@ -1,18 +1,15 @@
package app package app
import ( import (
"net/http"
"time" "time"
appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec" "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
"forge.cadoles.com/Cadoles/emissary/internal/jwk" "forge.cadoles.com/Cadoles/emissary/internal/jwk"
"forge.cadoles.com/arcad/edge/pkg/app" "forge.cadoles.com/arcad/edge/pkg/app"
"forge.cadoles.com/arcad/edge/pkg/module" "forge.cadoles.com/arcad/edge/pkg/module"
"forge.cadoles.com/arcad/edge/pkg/module/auth" "forge.cadoles.com/arcad/edge/pkg/module/auth"
authModule "forge.cadoles.com/arcad/edge/pkg/module/auth" authModule "forge.cadoles.com/arcad/edge/pkg/module/auth"
authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http" authHTTP "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
authModuleMiddleware "forge.cadoles.com/arcad/edge/pkg/module/auth/middleware"
"github.com/dop251/goja" "github.com/dop251/goja"
"github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwa"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -57,7 +54,7 @@ func authModuleFactory(keySet jwk.Set) app.ServerModuleFactory {
) )
} }
func getAuthMount(auth *appSpec.Auth, keySet jwk.Set) (auth.MountFunc, error) { func getAuthMount(auth *spec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
switch { switch {
case auth.Local != nil: case auth.Local != nil:
var rawKey any = auth.Local.Key var rawKey any = auth.Local.Key
@ -80,8 +77,7 @@ func getAuthMount(auth *appSpec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
return authModule.Mount( return authModule.Mount(
authHTTP.NewLocalHandler( authHTTP.NewLocalHandler(
key, jwa.HS256, key,
jwa.HS256,
authHTTP.WithRoutePrefix("/auth"), authHTTP.WithRoutePrefix("/auth"),
authHTTP.WithAccounts(auth.Local.Accounts...), authHTTP.WithAccounts(auth.Local.Accounts...),
authHTTP.WithCookieOptions(getCookieDomain, cookieDuration), authHTTP.WithCookieOptions(getCookieDomain, cookieDuration),
@ -95,72 +91,3 @@ func getAuthMount(auth *appSpec.Auth, keySet jwk.Set) (auth.MountFunc, error) {
return nil, nil return nil, nil
} }
} }
func getAnonymousUserMiddleware(auth *appSpec.Auth) (func(http.Handler) http.Handler, error) {
anonymousUserSigningKey, err := getAnonymousUserSigningKey(auth)
if err != nil {
return nil, errors.Wrap(err, "could not get anonymous user signing key")
}
cookieDuration := defaultCookieDuration
if auth.Local.CookieDuration != "" {
cookieDuration, err = time.ParseDuration(auth.Local.CookieDuration)
if err != nil {
return nil, errors.WithStack(err)
}
}
middleware := authModuleMiddleware.AnonymousUser(
anonymousUserSigningKey,
auth.Local.SigningAlgorithm,
authModuleMiddleware.WithCookieOptions(getCookieDomain, cookieDuration),
)
return middleware, nil
}
func getAnonymousUserSigningKey(auth *appSpec.Auth) (jwk.Key, error) {
var (
key jwk.Key
err error
)
generateNewKey := func() (jwk.Key, error) {
key, err := jwk.Generate(2048)
if err != nil {
return nil, errors.WithStack(err)
}
return key, nil
}
switch {
default:
fallthrough
case auth == nil:
key, err = generateNewKey()
if err != nil {
return nil, errors.Wrap(err, "could not generate anonymous user signing key")
}
return key, nil
case auth.Local != nil:
switch typedKey := auth.Local.Key.(type) {
case string:
key, err = jwk.FromRaw([]byte(typedKey))
if err != nil {
return nil, errors.Wrap(err, "could not parse local auth key")
}
if err := key.Set(jwk.AlgorithmKey, jwa.HS256); err != nil {
return nil, errors.WithStack(err)
}
default:
return nil, errors.Errorf("unexpected key type '%T'", auth.Local.Key)
}
}
return key, nil
}

View File

@ -66,11 +66,10 @@ func (c *Controller) stopAllApps(ctx context.Context, spec *spec.Spec) {
logger.Info(ctx, "stopping app", logger.F("appID", appID)) logger.Info(ctx, "stopping app", logger.F("appID", appID))
if err := entry.Server.Stop(); err != nil { if err := entry.Server.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "error while stopping app", ctx, "error while stopping app",
logger.F("appID", appID), logger.F("appID", appID),
logger.CapturedE(err), logger.E(errors.WithStack(err)),
) )
delete(c.servers, appID) delete(c.servers, appID)
@ -88,11 +87,10 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
logger.Info(ctx, "stopping app", logger.F("appKey", appKey)) logger.Info(ctx, "stopping app", logger.F("appKey", appKey))
if err := server.Server.Stop(); err != nil { if err := server.Server.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "error while stopping app", ctx, "error while stopping app",
logger.F("appKey", appKey), logger.F("appKey", appKey),
logger.CapturedE(err), logger.E(errors.WithStack(err)),
) )
delete(c.servers, appKey) delete(c.servers, appKey)
@ -100,10 +98,9 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
} }
if err := c.updateAppRepository(ctx, specs); err != nil { if err := c.updateAppRepository(ctx, specs); err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "could not update app repository", ctx, "could not update app repository",
logger.CapturedE(err), logger.E(errors.WithStack(err)),
) )
return return
@ -114,8 +111,7 @@ func (c *Controller) updateApps(ctx context.Context, specs *spec.Spec) {
appCtx := logger.With(ctx, logger.F("appKey", appKey)) appCtx := logger.With(ctx, logger.F("appKey", appKey))
if err := c.updateApp(ctx, specs, appKey); err != nil { if err := c.updateApp(ctx, specs, appKey); err != nil {
err = errors.WithStack(err) logger.Error(appCtx, "could not update app", logger.E(errors.WithStack(err)))
logger.Error(appCtx, "could not update app", logger.CapturedE(err))
continue continue
} }
} }
@ -204,14 +200,12 @@ func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey str
return nil return nil
} }
ctx = logger.With(ctx, if defChanged && server.AppDefHash != 0 {
logger.F("appKey", appKey), logger.Info(
ctx, "restarting app",
logger.F("address", appEntry.Address), logger.F("address", appEntry.Address),
) )
if defChanged && server.AppDefHash != 0 {
logger.Info(ctx, "restarting app")
if err := server.Server.Stop(); err != nil { if err := server.Server.Stop(); err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -223,7 +217,10 @@ func (c *Controller) updateApp(ctx context.Context, specs *spec.Spec, appKey str
c.servers[appKey] = serverEntry c.servers[appKey] = serverEntry
} else { } else {
logger.Info(ctx, "starting app") logger.Info(
ctx, "starting app",
logger.F("address", appEntry.Address),
)
} }
if err := server.Server.Start(ctx, appEntry.Address); err != nil { if err := server.Server.Start(ctx, appEntry.Address); err != nil {

View File

@ -8,14 +8,15 @@ import (
"sync" "sync"
"time" "time"
"forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec" appSpec "forge.cadoles.com/Cadoles/emissary/internal/agent/controller/app/spec"
"forge.cadoles.com/Cadoles/emissary/internal/proxy/wildcard" "forge.cadoles.com/Cadoles/emissary/internal/proxy/wildcard"
edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http" edgeHTTP "forge.cadoles.com/arcad/edge/pkg/http"
"gitlab.com/wpetit/goweb/logger" "gitlab.com/wpetit/goweb/logger"
"forge.cadoles.com/arcad/edge/pkg/bundle" "forge.cadoles.com/arcad/edge/pkg/bundle"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/pkg/errors" "github.com/pkg/errors"
_ "forge.cadoles.com/Cadoles/emissary/internal/imports/passwd" _ "forge.cadoles.com/Cadoles/emissary/internal/imports/passwd"
@ -48,7 +49,7 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
router.Use(middleware.Compress(5)) router.Use(middleware.Compress(5))
handler := edgeHTTP.NewHandler(s.handlerOptions...) handler := edgeHTTP.NewHandler(s.handlerOptions...)
if err := handler.Load(ctx, s.bundle); err != nil { if err := handler.Load(s.bundle); err != nil {
return errors.Wrap(err, "could not load app bundle") return errors.Wrap(err, "could not load app bundle")
} }
@ -72,8 +73,7 @@ func (s *Server) Start(ctx context.Context, addr string) (err error) {
defer func() { defer func() {
if recovered := recover(); recovered != nil { if recovered := recover(); recovered != nil {
if err, ok := recovered.(error); ok { if err, ok := recovered.(error); ok {
err = errors.WithStack(err) logger.Error(ctx, err.Error(), logger.E(errors.WithStack(err)))
logger.Error(ctx, err.Error(), logger.CapturedE(err))
return return
} }
@ -128,7 +128,7 @@ func (s *Server) Stop() error {
return nil return nil
} }
func NewServer(bundle bundle.Bundle, config *appSpec.Config, handlerOptions ...edgeHTTP.HandlerOptionFunc) *Server { func NewServer(bundle bundle.Bundle, config *spec.Config, handlerOptions ...edgeHTTP.HandlerOptionFunc) *Server {
return &Server{ return &Server{
bundle: bundle, bundle: bundle,
config: config, config: config,

View File

@ -24,37 +24,15 @@
"type": "string", "type": "string",
"enum": [ "enum": [
"zip", "zip",
"tar.gz", "tar.gz"
"zim"
] ]
},
"storage": {
"type": "object",
"properties": {
"blobStoreDsn": {
"type": "string"
},
"documentStoreDsn": {
"type": "string"
},
"shareStoreDsn": {
"type": "string"
}
},
"required": [
"blobStoreDsn",
"documentStoreDsn",
"shareStoreDsn"
],
"additionalProperties": false
} }
}, },
"required": [ "required": [
"url", "url",
"sha256sum", "sha256sum",
"address", "address",
"format", "format"
"storage"
], ],
"additionalProperties": false "additionalProperties": false
} }
@ -106,9 +84,6 @@
"key": { "key": {
"type": ["object", "string"] "type": ["object", "string"]
}, },
"signingAlgorithm": {
"type": "string"
},
"accounts": { "accounts": {
"type": "array", "type": "array",
"items": { "items": {
@ -142,8 +117,7 @@
} }
}, },
"required": [ "required": [
"key", "key"
"signingAlgorithm"
], ],
"additionalProperties": false "additionalProperties": false
} }

View File

@ -3,7 +3,6 @@ package spec
import ( import (
"forge.cadoles.com/Cadoles/emissary/internal/spec" "forge.cadoles.com/Cadoles/emissary/internal/spec"
edgeAuth "forge.cadoles.com/arcad/edge/pkg/module/auth/http" edgeAuth "forge.cadoles.com/arcad/edge/pkg/module/auth/http"
"github.com/lestrrat-go/jwx/v2/jwa"
) )
const Name spec.Name = "app.emissary.cadoles.com" const Name spec.Name = "app.emissary.cadoles.com"
@ -19,13 +18,6 @@ type AppEntry struct {
SHA256Sum string `json:"sha256sum"` SHA256Sum string `json:"sha256sum"`
Address string `json:"address"` Address string `json:"address"`
Format string `json:"format"` Format string `json:"format"`
Storage *AppStorage `json:"storage"`
}
type AppStorage struct {
ShareStoreDSN string `json:"shareStoreDsn"`
DocumentStoreDSN string `json:"documentStoreDsn"`
BlobStoreDSN string `json:"blobStoreDsn"`
} }
type Auth struct { type Auth struct {
@ -34,7 +26,6 @@ type Auth struct {
type LocalAuth struct { type LocalAuth struct {
Key any `json:"key"` Key any `json:"key"`
SigningAlgorithm jwa.SignatureAlgorithm `json:"signingAlgorithm"`
Accounts []edgeAuth.LocalAccount `json:"accounts"` Accounts []edgeAuth.LocalAccount `json:"accounts"`
CookieDomain string `json:"cookieDomain"` CookieDomain string `json:"cookieDomain"`
CookieDuration string `json:"cookieDuration"` CookieDuration string `json:"cookieDuration"`

View File

@ -6,12 +6,7 @@
"url": "http://example.com/edge.sdk.client.test_0.0.0.zip", "url": "http://example.com/edge.sdk.client.test_0.0.0.zip",
"sha256sum": "58019192dacdae17755707719707db007e26dac856102280583fbd18427dd352", "sha256sum": "58019192dacdae17755707719707db007e26dac856102280583fbd18427dd352",
"address": ":8081", "address": ":8081",
"format": "zip", "format": "zip"
"storage": {
"blobStoreDsn": "sqlite://apps/data/edge.sdk.client.test/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/edge.sdk.client.test/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
} }
}, },
"config": { "config": {
@ -28,7 +23,6 @@
"q": "yJJLNc9w6O4y2icME8k99FugV9E7ObwUxF3v5JN3y1cmAT0h2njyE3iAGqaDZwcY1_jGCisjwoqX6i5E8xqhxX3Gcy3J7SmUAf8fhY8wU3zv9DK7skg2IdvanDb8Y1OM6GchbYZAOVPEg2IvVio8zI-Ih3DDwDk8Df0ufzoHRb8", "q": "yJJLNc9w6O4y2icME8k99FugV9E7ObwUxF3v5JN3y1cmAT0h2njyE3iAGqaDZwcY1_jGCisjwoqX6i5E8xqhxX3Gcy3J7SmUAf8fhY8wU3zv9DK7skg2IdvanDb8Y1OM6GchbYZAOVPEg2IvVio8zI-Ih3DDwDk8Df0ufzoHRb8",
"qi": "zOE-4R3cjPesm3MX-4PdwmsaF9QZLUVRUvvHJ08pKs6kAXP18hzjctAoOjhQDxlTYqNYNePfKzKwost3OJoPgRIc9w9qwUCK1gNOS4Z_xozCIaXgMddNFhkoAfZ4JaKjNCiinzjGfqG99Lf-yzmmREuuhRv7SdS3ST4VQjiJQew" "qi": "zOE-4R3cjPesm3MX-4PdwmsaF9QZLUVRUvvHJ08pKs6kAXP18hzjctAoOjhQDxlTYqNYNePfKzKwost3OJoPgRIc9w9qwUCK1gNOS4Z_xozCIaXgMddNFhkoAfZ4JaKjNCiinzjGfqG99Lf-yzmmREuuhRv7SdS3ST4VQjiJQew"
}, },
"signingAlgorithm": "RS256",
"accounts": [ "accounts": [
{ {
"username": "foo", "username": "foo",

View File

@ -117,8 +117,7 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
service, err := dnssd.NewService(config) service, err := dnssd.NewService(config)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not create mdns service", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not create mdns service", logger.CapturedE(err))
continue continue
} }
@ -133,8 +132,7 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
for _, service := range services { for _, service := range services {
if _, err := responder.Add(service); err != nil { if _, err := responder.Add(service); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not add mdns service", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not add mdns service", logger.CapturedE(err))
continue continue
} }
@ -150,8 +148,7 @@ func (c *Controller) updateResponder(ctx context.Context, spec *mdns.Spec) error
defer c.stopResponder(ctx) defer c.stopResponder(ctx)
if err := responder.Respond(ctx); err != nil && !errors.Is(err, context.Canceled) { if err := responder.Respond(ctx); err != nil && !errors.Is(err, context.Canceled) {
err = errors.WithStack(err) logger.Error(ctx, "could not respond to mdns queries", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not respond to mdns queries", logger.CapturedE(err))
} }
}() }()

View File

@ -64,10 +64,9 @@ func (c *SysUpgradeController) Reconcile(ctx context.Context, state *agent.State
defer func() { defer func() {
if err := os.RemoveAll(downloadDir); err != nil { if err := os.RemoveAll(downloadDir); err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "could not remove download direction", ctx, "could not remove download direction",
logger.CapturedE(err), logger.E(errors.WithStack(err)),
logger.F("downloadDir", downloadDir), logger.F("downloadDir", downloadDir),
) )
} }

View File

@ -46,8 +46,7 @@ func (c *UCIController) Reconcile(ctx context.Context, state *agent.State) error
} }
if err := c.updateConfiguration(ctx, uciSpec); err != nil { if err := c.updateConfiguration(ctx, uciSpec); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not update configuration", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not update configuration", logger.CapturedE(err))
return nil return nil
} }

View File

@ -145,8 +145,7 @@ func (c *Controller) writeState(ctx context.Context, state *agent.State) error {
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not remove temporary file", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not remove temporary file", logger.CapturedE(err))
} }
}() }()
@ -156,8 +155,7 @@ func (c *Controller) writeState(ctx context.Context, state *agent.State) error {
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not close temporary file", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not close temporary file", logger.CapturedE(err))
} }
}() }()

View File

@ -58,11 +58,10 @@ func (c *Controller) stopAllProxies(ctx context.Context) {
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID)) logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
if err := entry.Proxy.Stop(); err != nil { if err := entry.Proxy.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "error while stopping proxy", ctx, "error while stopping proxy",
logger.F("proxyID", proxyID), logger.F("proxyID", proxyID),
logger.CapturedE(err), logger.E(errors.WithStack(err)),
) )
delete(c.proxies, proxyID) delete(c.proxies, proxyID)
@ -80,11 +79,10 @@ func (c *Controller) updateProxies(ctx context.Context, spec *spec.Spec) {
logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID)) logger.Info(ctx, "stopping proxy", logger.F("proxyID", proxyID))
if err := entry.Proxy.Stop(); err != nil { if err := entry.Proxy.Stop(); err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "error while stopping proxy", ctx, "error while stopping proxy",
logger.F("proxyID", proxyID), logger.F("proxyID", proxyID),
logger.CapturedE(err), logger.E(errors.WithStack(err)),
) )
delete(c.proxies, proxyID) delete(c.proxies, proxyID)
@ -96,8 +94,7 @@ func (c *Controller) updateProxies(ctx context.Context, spec *spec.Spec) {
proxyCtx := logger.With(ctx, logger.F("proxyID", proxyID)) proxyCtx := logger.With(ctx, logger.F("proxyID", proxyID))
if err := c.updateProxy(ctx, proxyID, proxySpec); err != nil { if err := c.updateProxy(ctx, proxyID, proxySpec); err != nil {
err = errors.WithStack(err) logger.Error(proxyCtx, "could not update proxy", logger.E(errors.WithStack(err)))
logger.Error(proxyCtx, "could not update proxy", logger.CapturedE(err))
continue continue
} }
} }

View File

@ -38,14 +38,12 @@ func (p *ReverseProxy) Start(ctx context.Context, addr string, funcs ...proxy.Op
go func() { go func() {
defer func() { defer func() {
if err := p.Stop(); err != nil { if err := p.Stop(); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "error while stopping gateway", logger.E(errors.WithStack(err)))
logger.Error(ctx, "error while stopping gateway", logger.CapturedE(err))
} }
}() }()
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
err = errors.WithStack(err) logger.Error(ctx, "error while listening", logger.E(errors.WithStack(err)))
logger.Error(ctx, "error while listening", logger.CapturedE(err))
} }
}() }()

View File

@ -40,15 +40,14 @@ func (c *Controller) reconcileAgent(ctx context.Context, client *client.Client,
ctx = logger.With(ctx, logger.F("agentID", agent.ID)) ctx = logger.With(ctx, logger.F("agentID", agent.ID))
if agent.Status != datastore.AgentStatusAccepted { if agent.Status != datastore.AgentStatusAccepted {
logger.Warn(ctx, "unexpected agent status", logger.F("status", agent.Status)) logger.Error(ctx, "unexpected agent status", logger.F("status", agent.Status))
return nil return nil
} }
specs, err := client.GetAgentSpecs(ctx, agent.ID) specs, err := client.GetAgentSpecs(ctx, agent.ID)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not retrieve agent specs", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not retrieve agent specs", logger.CapturedE(err))
return nil return nil
} }

View File

@ -7,11 +7,8 @@ import (
"sort" "sort"
"time" "time"
"forge.cadoles.com/Cadoles/emissary/internal/command/common"
"github.com/getsentry/sentry-go"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"gitlab.com/wpetit/goweb/logger"
) )
func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands ...*cli.Command) { func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands ...*cli.Command) {
@ -49,27 +46,6 @@ func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands
return errors.WithStack(err) return errors.WithStack(err)
} }
conf, err := common.LoadConfig(ctx)
if err != nil {
return errors.Wrap(err, "Could not load configuration")
}
if conf.Sentry.DSN != "" {
err = sentry.Init(sentry.ClientOptions{
Dsn: string(conf.Sentry.DSN),
Debug: ctx.Bool("debug"),
AttachStacktrace: true,
Environment: string(conf.Sentry.Environment),
})
if err != nil {
logger.Error(ctx.Context, "could not initialize sentry", logger.E(errors.WithStack(err)))
}
logger.SetCaptureFunc(func(err error) {
sentry.CaptureException(err)
})
}
return nil return nil
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
@ -108,15 +84,11 @@ func Main(buildDate, projectVersion, gitRef, defaultConfigPath string, commands
}, },
} }
defer sentry.Flush(2 * time.Second)
app.ExitErrHandler = func(ctx *cli.Context, err error) { app.ExitErrHandler = func(ctx *cli.Context, err error) {
if err == nil { if err == nil {
return return
} }
sentry.CaptureException(err)
debug := ctx.Bool("debug") debug := ctx.Bool("debug")
if !debug { if !debug {

View File

@ -32,8 +32,7 @@ func PingCommand() *cli.Command {
defer func() { defer func() {
if err := db.Close(); err != nil { if err := db.Close(); err != nil {
err = errors.WithStack(err) logger.Error(ctx.Context, "error while closing database connection", logger.E(errors.WithStack(err)))
logger.Error(ctx.Context, "error while closing database connection", logger.CapturedE(err))
} }
}() }()

View File

@ -11,7 +11,6 @@ import (
// Config definition // Config definition
type Config struct { type Config struct {
Logger LoggerConfig `yaml:"logger"` Logger LoggerConfig `yaml:"logger"`
Sentry SentryConfig `yaml:"sentry"`
Server ServerConfig `yaml:"server"` Server ServerConfig `yaml:"server"`
Agent AgentConfig `yaml:"agent"` Agent AgentConfig `yaml:"agent"`
} }
@ -45,7 +44,6 @@ func NewDefault() *Config {
Logger: NewDefaultLoggerConfig(), Logger: NewDefaultLoggerConfig(),
Agent: NewDefaultAgentConfig(), Agent: NewDefaultAgentConfig(),
Server: NewDefaultServerConfig(), Server: NewDefaultServerConfig(),
Sentry: NewDefaultSentryConfig(),
} }
} }

View File

@ -15,6 +15,6 @@ type DatabaseConfig struct {
func NewDefaultDatabaseConfig() DatabaseConfig { func NewDefaultDatabaseConfig() DatabaseConfig {
return DatabaseConfig{ return DatabaseConfig{
Driver: "sqlite", Driver: "sqlite",
DSN: "sqlite://emissary.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=150000&_pragma=journal_mode=WAL", DSN: "sqlite://emissary.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
} }
} }

View File

@ -10,41 +10,7 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
var ( var reVar = regexp.MustCompile(`^\${(\w+)}$`)
interpolationRegExp = regexp.MustCompile(`^\${((?P<varName>\w+)|((?P<varNameWithDefault>\w+):-(?P<defaultValue>[^}]+)))}$`)
varNameGroupIndex = interpolationRegExp.SubexpIndex("varName")
varNameWithDefaultGroupIndex = interpolationRegExp.SubexpIndex("varNameWithDefault")
defaultValueGroupIndex = interpolationRegExp.SubexpIndex("defaultValue")
)
func interpolate(str string, getValueFunc func(name string) string) string {
for _, match := range interpolationRegExp.FindAllStringSubmatch(str, -1) {
varName := match[varNameWithDefaultGroupIndex]
if varName == "" {
varName = match[varNameGroupIndex]
}
if varName == "" {
continue
}
defaultValue := ""
if defaultValueGroupIndex < len(match) {
defaultValue = match[defaultValueGroupIndex]
}
str = getValueFunc(varName)
if str == "" {
str = defaultValue
}
}
return str
}
func interpolateEnv(str string) string {
return interpolate(str, os.Getenv)
}
type InterpolatedString string type InterpolatedString string
@ -55,7 +21,11 @@ func (is *InterpolatedString) UnmarshalYAML(value *yaml.Node) error {
return errors.WithStack(err) return errors.WithStack(err)
} }
*is = InterpolatedString(interpolateEnv(str)) if match := reVar.FindStringSubmatch(str); len(match) > 0 {
*is = InterpolatedString(os.Getenv(match[1]))
} else {
*is = InterpolatedString(str)
}
return nil return nil
} }
@ -69,7 +39,9 @@ func (ii *InterpolatedInt) UnmarshalYAML(value *yaml.Node) error {
return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line) return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line)
} }
str = interpolateEnv(str) if match := reVar.FindStringSubmatch(str); len(match) > 0 {
str = os.Getenv(match[1])
}
intVal, err := strconv.ParseInt(str, 10, 32) intVal, err := strconv.ParseInt(str, 10, 32)
if err != nil { if err != nil {
@ -90,7 +62,9 @@ func (ib *InterpolatedBool) UnmarshalYAML(value *yaml.Node) error {
return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line) return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line)
} }
str = interpolateEnv(str) if match := reVar.FindStringSubmatch(str); len(match) > 0 {
str = os.Getenv(match[1])
}
boolVal, err := strconv.ParseBool(str) boolVal, err := strconv.ParseBool(str)
if err != nil { if err != nil {
@ -117,7 +91,9 @@ func (im *InterpolatedMap) UnmarshalYAML(value *yaml.Node) error {
continue continue
} }
strVal = interpolateEnv(strVal) if match := reVar.FindStringSubmatch(strVal); len(match) > 0 {
strVal = os.Getenv(match[1])
}
data[key] = strVal data[key] = strVal
} }
@ -137,7 +113,9 @@ func (iss *InterpolatedStringSlice) UnmarshalYAML(value *yaml.Node) error {
} }
for index, value := range data { for index, value := range data {
value = interpolateEnv(value) if match := reVar.FindStringSubmatch(value); len(match) > 0 {
value = os.Getenv(match[1])
}
data[index] = value data[index] = value
} }
@ -156,7 +134,9 @@ func (id *InterpolatedDuration) UnmarshalYAML(value *yaml.Node) error {
return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line) return errors.Wrapf(err, "could not decode value '%v' (line '%d') into string", value.Value, value.Line)
} }
str = interpolateEnv(str) if match := reVar.FindStringSubmatch(str); len(match) > 0 {
str = os.Getenv(match[1])
}
duration, err := time.ParseDuration(str) duration, err := time.ParseDuration(str)
if err != nil { if err != nil {

View File

@ -1,63 +0,0 @@
package config
import (
"fmt"
"testing"
)
type interpolateTestCase struct {
String string
Data map[string]string
Expected string
}
var interpolateTestCases = []interpolateTestCase{
{
String: "${foo}",
Data: map[string]string{
"foo": "bar",
},
Expected: "bar",
},
{
String: "${hello:-world}",
Data: map[string]string{},
Expected: "world",
},
{
String: "${hello:-}",
Data: map[string]string{},
Expected: "${hello:-}",
},
{
String: "foo",
Data: map[string]string{},
Expected: "foo",
},
{
String: "",
Data: map[string]string{},
Expected: "",
},
}
func TestInterpolate(t *testing.T) {
for idx, tc := range interpolateTestCases {
func(idx int, tc interpolateTestCase) {
t.Run(fmt.Sprintf("Case_%d", idx), func(t *testing.T) {
result := interpolate(tc.String, func(name string) string {
value, exists := tc.Data[name]
if !exists {
return ""
}
return value
})
if e, g := tc.Expected, result; e != g {
t.Errorf("result: expected '%v', got '%v'", tc.Expected, result)
}
})
}(idx, tc)
}
}

View File

@ -1,18 +0,0 @@
package config
import (
"os"
)
type SentryConfig struct {
DSN InterpolatedString `yaml:"dsn"`
Environment InterpolatedString `yaml:"environment"`
}
func NewDefaultSentryConfig() SentryConfig {
hostname, _ := os.Hostname()
return SentryConfig{
DSN: "",
Environment: InterpolatedString(hostname),
}
}

View File

@ -5,7 +5,6 @@ import (
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"time" "time"
"forge.cadoles.com/Cadoles/emissary/internal/datastore" "forge.cadoles.com/Cadoles/emissary/internal/datastore"
@ -17,12 +16,11 @@ import (
type AgentRepository struct { type AgentRepository struct {
db *sql.DB db *sql.DB
sqliteBusyRetryMaxAttempts int
} }
// DeleteSpec implements datastore.AgentRepository. // DeleteSpec implements datastore.AgentRepository.
func (r *AgentRepository) DeleteSpec(ctx context.Context, agentID datastore.AgentID, name string) error { func (r *AgentRepository) DeleteSpec(ctx context.Context, agentID datastore.AgentID, name string) error {
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
exists, err := r.agentExists(ctx, tx, agentID) exists, err := r.agentExists(ctx, tx, agentID)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
@ -51,7 +49,7 @@ func (r *AgentRepository) DeleteSpec(ctx context.Context, agentID datastore.Agen
func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentID) ([]*datastore.Spec, error) { func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentID) ([]*datastore.Spec, error) {
specs := make([]*datastore.Spec, 0) specs := make([]*datastore.Spec, 0)
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
exists, err := r.agentExists(ctx, tx, agentID) exists, err := r.agentExists(ctx, tx, agentID)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
@ -74,8 +72,7 @@ func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentI
defer func() { defer func() {
if err := rows.Close(); err != nil { if err := rows.Close(); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not close rows", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not close rows", logger.CapturedE(err))
} }
}() }()
@ -110,7 +107,7 @@ func (r *AgentRepository) GetSpecs(ctx context.Context, agentID datastore.AgentI
func (r *AgentRepository) UpdateSpec(ctx context.Context, agentID datastore.AgentID, name string, revision int, data map[string]any) (*datastore.Spec, error) { func (r *AgentRepository) UpdateSpec(ctx context.Context, agentID datastore.AgentID, name string, revision int, data map[string]any) (*datastore.Spec, error) {
spec := &datastore.Spec{} spec := &datastore.Spec{}
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
exists, err := r.agentExists(ctx, tx, agentID) exists, err := r.agentExists(ctx, tx, agentID)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
@ -169,7 +166,7 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
agents := make([]*datastore.Agent, 0) agents := make([]*datastore.Agent, 0)
count := 0 count := 0
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `SELECT id, label, thumbprint, status, contacted_at, created_at, updated_at FROM agents` query := `SELECT id, label, thumbprint, status, contacted_at, created_at, updated_at FROM agents`
limit := 10 limit := 10
@ -222,15 +219,14 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
logger.Debug(ctx, "executing query", logger.F("query", query), logger.F("args", args)) logger.Debug(ctx, "executing query", logger.F("query", query), logger.F("args", args))
rows, err := tx.QueryContext(ctx, query, args...) rows, err := r.db.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
defer func() { defer func() {
if err := rows.Close(); err != nil { if err := rows.Close(); err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not close rows", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not close rows", logger.CapturedE(err))
} }
}() }()
@ -274,7 +270,7 @@ func (r *AgentRepository) Query(ctx context.Context, opts ...datastore.AgentQuer
func (r *AgentRepository) Create(ctx context.Context, thumbprint string, keySet jwk.Set, metadata map[string]any) (*datastore.Agent, error) { func (r *AgentRepository) Create(ctx context.Context, thumbprint string, keySet jwk.Set, metadata map[string]any) (*datastore.Agent, error) {
agent := &datastore.Agent{} agent := &datastore.Agent{}
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `SELECT count(id) FROM agents WHERE thumbprint = $1` query := `SELECT count(id) FROM agents WHERE thumbprint = $1`
row := tx.QueryRowContext(ctx, query, thumbprint) row := tx.QueryRowContext(ctx, query, thumbprint)
@ -333,15 +329,15 @@ func (r *AgentRepository) Create(ctx context.Context, thumbprint string, keySet
// Delete implements datastore.AgentRepository // Delete implements datastore.AgentRepository
func (r *AgentRepository) Delete(ctx context.Context, id datastore.AgentID) error { func (r *AgentRepository) Delete(ctx context.Context, id datastore.AgentID) error {
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
query := `DELETE FROM agents WHERE id = $1` query := `DELETE FROM agents WHERE id = $1`
_, err := tx.ExecContext(ctx, query, id) _, err := r.db.ExecContext(ctx, query, id)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
query = `DELETE FROM specs WHERE agent_id = $1` query = `DELETE FROM specs WHERE agent_id = $1`
_, err = tx.ExecContext(ctx, query, id) _, err = r.db.ExecContext(ctx, query, id)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -361,14 +357,14 @@ func (r *AgentRepository) Get(ctx context.Context, id datastore.AgentID) (*datas
ID: id, ID: id,
} }
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
query := ` query := `
SELECT "id", "label", "thumbprint", "keyset", "metadata", "status", "contacted_at", "created_at", "updated_at" SELECT "id", "label", "thumbprint", "keyset", "metadata", "status", "contacted_at", "created_at", "updated_at"
FROM agents FROM agents
WHERE id = $1 WHERE id = $1
` `
row := tx.QueryRowContext(ctx, query, id) row := r.db.QueryRowContext(ctx, query, id)
metadata := JSONMap{} metadata := JSONMap{}
contactedAt := sql.NullTime{} contactedAt := sql.NullTime{}
@ -412,7 +408,7 @@ func (r *AgentRepository) Update(ctx context.Context, id datastore.AgentID, opts
agent := &datastore.Agent{} agent := &datastore.Agent{}
err := r.withTxRetry(ctx, func(tx *sql.Tx) error { err := r.withTx(ctx, func(tx *sql.Tx) error {
query := ` query := `
UPDATE agents SET id = $1 UPDATE agents SET id = $1
` `
@ -536,59 +532,6 @@ func (r *AgentRepository) agentExists(ctx context.Context, tx *sql.Tx, agentID d
return true, nil return true, nil
} }
func (r *AgentRepository) withTxRetry(ctx context.Context, fn func(*sql.Tx) error) error {
attempts := 0
max := r.sqliteBusyRetryMaxAttempts
ctx = logger.With(ctx, logger.F("max", max))
var err error
for {
ctx = logger.With(ctx)
if attempts >= max {
logger.Debug(ctx, "transaction retrying failed", logger.F("attempts", attempts))
return errors.Wrapf(err, "transaction failed after %d attempts", max)
}
err = r.withTx(ctx, fn)
if err != nil {
if !strings.Contains(err.Error(), "(5) (SQLITE_BUSY)") {
return errors.WithStack(err)
}
err = errors.WithStack(err)
logger.Warn(ctx, "database is busy", logger.E(err))
wait := time.Duration(8<<(attempts+1)) * time.Millisecond
logger.Debug(
ctx, "database is busy, waiting before retrying transaction",
logger.F("wait", wait.String()),
logger.F("attempts", attempts),
)
timer := time.NewTimer(wait)
select {
case <-timer.C:
attempts++
continue
case <-ctx.Done():
if err := ctx.Err(); err != nil {
return errors.WithStack(err)
}
return nil
}
}
return nil
}
}
func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) error { func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) error {
tx, err := r.db.BeginTx(ctx, nil) tx, err := r.db.BeginTx(ctx, nil)
if err != nil { if err != nil {
@ -601,8 +544,7 @@ func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) er
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not rollback transaction", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not rollback transaction", logger.CapturedE(err))
} }
}() }()
@ -617,8 +559,8 @@ func (r *AgentRepository) withTx(ctx context.Context, fn func(*sql.Tx) error) er
return nil return nil
} }
func NewAgentRepository(db *sql.DB, sqliteBusyRetryMaxAttempts int) *AgentRepository { func NewAgentRepository(db *sql.DB) *AgentRepository {
return &AgentRepository{db, sqliteBusyRetryMaxAttempts} return &AgentRepository{db}
} }
var _ datastore.AgentRepository = &AgentRepository{} var _ datastore.AgentRepository = &AgentRepository{}

View File

@ -40,7 +40,7 @@ func TestSQLiteAgentRepository(t *testing.T) {
t.Fatalf("%+v", errors.WithStack(err)) t.Fatalf("%+v", errors.WithStack(err))
} }
repo := NewAgentRepository(db, 5) repo := NewAgentRepository(db)
testsuite.TestAgentRepository(t, repo) testsuite.TestAgentRepository(t, repo)
} }

View File

@ -9,7 +9,7 @@ import (
"forge.cadoles.com/Cadoles/emissary/internal/agent/metadata" "forge.cadoles.com/Cadoles/emissary/internal/agent/metadata"
"forge.cadoles.com/Cadoles/emissary/internal/datastore" "forge.cadoles.com/Cadoles/emissary/internal/datastore"
"forge.cadoles.com/Cadoles/emissary/internal/jwk" "forge.cadoles.com/Cadoles/emissary/internal/jwk"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/wpetit/goweb/api" "gitlab.com/wpetit/goweb/api"
"gitlab.com/wpetit/goweb/logger" "gitlab.com/wpetit/goweb/logger"
@ -39,8 +39,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
keySet, err := jwk.Parse(registerAgentReq.KeySet) keySet, err := jwk.Parse(registerAgentReq.KeySet)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not parse key set", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not parse key set", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -52,15 +51,14 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
validSignature, err := jwk.Verify(keySet, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata) validSignature, err := jwk.Verify(keySet, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not validate signature", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not validate signature", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
} }
if !validSignature { if !validSignature {
logger.Warn(ctx, "conflicting signature", logger.F("signature", registerAgentReq.Signature)) logger.Error(ctx, "conflicting signature", logger.F("signature", registerAgentReq.Signature))
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil) api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
return return
@ -76,8 +74,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
) )
if err != nil { if err != nil {
if !errors.Is(err, datastore.ErrAlreadyExist) { if !errors.Is(err, datastore.ErrAlreadyExist) {
err = errors.WithStack(err) logger.Error(ctx, "could not create agent", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not create agent", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -89,16 +86,15 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
datastore.WithAgentQueryLimit(1), datastore.WithAgentQueryLimit(1),
) )
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not retrieve agents", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not retrieve agents", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
} }
if len(agents) == 0 { if len(agents) == 0 {
err = errors.WithStack(err) logger.Error(ctx, "could not retrieve matching agent", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not retrieve matching agent", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeNotFound, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeNotFound, nil)
return return
@ -108,12 +104,10 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
agent, err = s.agentRepo.Get(ctx, agentID) agent, err = s.agentRepo.Get(ctx, agentID)
if err != nil { if err != nil {
err = errors.WithStack(err)
logger.Error( logger.Error(
ctx, "could not retrieve agent", ctx, "could not retrieve agent",
logger.CapturedE(err), logger.F("agentID", agentID), logger.E(errors.WithStack(err)), logger.F("agentID", agentID),
) )
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -121,8 +115,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
validSignature, err = jwk.Verify(agent.KeySet.Set, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata) validSignature, err = jwk.Verify(agent.KeySet.Set, registerAgentReq.Signature, registerAgentReq.Thumbprint, registerAgentReq.Metadata)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not validate signature using previous keyset", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not validate signature using previous keyset", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil) api.ErrorResponse(w, http.StatusConflict, ErrCodeConflict, nil)
@ -136,9 +129,7 @@ func (s *Server) registerAgent(w http.ResponseWriter, r *http.Request) {
datastore.WithAgentUpdateThumbprint(registerAgentReq.Thumbprint), datastore.WithAgentUpdateThumbprint(registerAgentReq.Thumbprint),
) )
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not update agent", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not update agent", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -186,8 +177,7 @@ func (s *Server) updateAgent(w http.ResponseWriter, r *http.Request) {
options..., options...,
) )
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not update agent", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not update agent", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -268,8 +258,7 @@ func (s *Server) queryAgents(w http.ResponseWriter, r *http.Request) {
options..., options...,
) )
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not list agents", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not list agents", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -303,8 +292,7 @@ func (s *Server) deleteAgent(w http.ResponseWriter, r *http.Request) {
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not delete agent", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not delete agent", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -336,8 +324,7 @@ func (s *Server) getAgent(w http.ResponseWriter, r *http.Request) {
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not get agent", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not get agent", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -355,7 +342,7 @@ func getAgentID(w http.ResponseWriter, r *http.Request) (datastore.AgentID, bool
agentID, err := strconv.ParseInt(rawAgentID, 10, 64) agentID, err := strconv.ParseInt(rawAgentID, 10, 64)
if err != nil { if err != nil {
logger.Error(r.Context(), "could not parse agent id", logger.CapturedE(errors.WithStack(err))) logger.Error(r.Context(), "could not parse agent id", logger.E(errors.WithStack(err)))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil) api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return 0, false return 0, false
@ -369,8 +356,7 @@ func getIntQueryParam(w http.ResponseWriter, r *http.Request, param string, defa
if rawValue != "" { if rawValue != "" {
value, err := strconv.ParseInt(rawValue, 10, 64) value, err := strconv.ParseInt(rawValue, 10, 64)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(r.Context(), "could not parse int param", logger.F("param", param), logger.E(errors.WithStack(err)))
logger.Error(r.Context(), "could not parse int param", logger.F("param", param), logger.CapturedE(err))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil) api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return 0, false return 0, false
@ -403,8 +389,7 @@ func getIntSliceValues(w http.ResponseWriter, r *http.Request, param string, def
for _, rv := range rawValues { for _, rv := range rawValues {
value, err := strconv.ParseInt(rv, 10, 64) value, err := strconv.ParseInt(rv, 10, 64)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(r.Context(), "could not parse int slice param", logger.F("param", param), logger.E(errors.WithStack(err)))
logger.Error(r.Context(), "could not parse int slice param", logger.F("param", param), logger.CapturedE(err))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil) api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return nil, false return nil, false

View File

@ -124,8 +124,7 @@ func assertRequestUser(w http.ResponseWriter, r *http.Request) (auth.User, bool)
ctx := r.Context() ctx := r.Context()
user, err := auth.CtxUser(ctx) user, err := auth.CtxUser(ctx)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(ctx, "could not retrieve user", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not retrieve user", logger.CapturedE(err))
forbidden(w, r) forbidden(w, r)
@ -148,7 +147,7 @@ func forbidden(w http.ResponseWriter, r *http.Request) {
} }
func logUnexpectedUserType(ctx context.Context, user auth.User) { func logUnexpectedUserType(ctx context.Context, user auth.User) {
logger.Warn( logger.Error(
ctx, "unexpected user type", ctx, "unexpected user type",
logger.F("subject", user.Subject()), logger.F("subject", user.Subject()),
logger.F("type", fmt.Sprintf("%T", user)), logger.F("type", fmt.Sprintf("%T", user)),

View File

@ -18,8 +18,8 @@ import (
"forge.cadoles.com/Cadoles/emissary/internal/jwk" "forge.cadoles.com/Cadoles/emissary/internal/jwk"
"github.com/antonmedv/expr" "github.com/antonmedv/expr"
"github.com/antonmedv/expr/vm" "github.com/antonmedv/expr/vm"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/middleware"
"github.com/go-chi/cors" "github.com/go-chi/cors"
"github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwa"
"github.com/lestrrat-go/jwx/v2/jwt" "github.com/lestrrat-go/jwx/v2/jwt"

View File

@ -6,7 +6,7 @@ import (
"forge.cadoles.com/Cadoles/emissary/internal/datastore" "forge.cadoles.com/Cadoles/emissary/internal/datastore"
"forge.cadoles.com/Cadoles/emissary/internal/spec" "forge.cadoles.com/Cadoles/emissary/internal/spec"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi"
"github.com/pkg/errors" "github.com/pkg/errors"
"gitlab.com/wpetit/goweb/api" "gitlab.com/wpetit/goweb/api"
"gitlab.com/wpetit/goweb/logger" "gitlab.com/wpetit/goweb/logger"
@ -44,9 +44,7 @@ func (s *Server) updateSpec(w http.ResponseWriter, r *http.Request) {
data.Message = validationErr.Error() data.Message = validationErr.Error()
} }
err = errors.WithStack(err) logger.Error(ctx, "could not validate spec", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not validate spec", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeInvalidRequest, data) api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeInvalidRequest, data)
return return
@ -72,9 +70,7 @@ func (s *Server) updateSpec(w http.ResponseWriter, r *http.Request) {
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not update spec", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not update spec", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -103,9 +99,7 @@ func (s *Server) getAgentSpecs(w http.ResponseWriter, r *http.Request) {
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not list specs", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not list specs", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -147,9 +141,7 @@ func (s *Server) deleteSpec(w http.ResponseWriter, r *http.Request) {
return return
} }
err = errors.WithStack(err) logger.Error(ctx, "could not delete spec", logger.E(errors.WithStack(err)))
logger.Error(ctx, "could not delete spec", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil) api.ErrorResponse(w, http.StatusInternalServerError, ErrCodeUnknownError, nil)
return return
@ -167,9 +159,7 @@ func getSpecID(w http.ResponseWriter, r *http.Request) (datastore.SpecID, bool)
specID, err := strconv.ParseInt(rawSpecID, 10, 64) specID, err := strconv.ParseInt(rawSpecID, 10, 64)
if err != nil { if err != nil {
err = errors.WithStack(err) logger.Error(r.Context(), "could not parse spec id", logger.E(errors.WithStack(err)))
logger.Error(r.Context(), "could not parse spec id", logger.CapturedE(err))
api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil) api.ErrorResponse(w, http.StatusBadRequest, api.ErrCodeMalformedRequest, nil)
return 0, false return 0, false

View File

@ -59,7 +59,7 @@ func NewAgentRepository(ctx context.Context, conf config.DatabaseConfig) (datast
return nil, errors.WithStack(err) return nil, errors.WithStack(err)
} }
agentRepository = sqlite.NewAgentRepository(db, 5) agentRepository = sqlite.NewAgentRepository(db)
default: default:
return nil, errors.Errorf("unsupported database driver '%s'", driver) return nil, errors.Errorf("unsupported database driver '%s'", driver)

View File

@ -1,32 +0,0 @@
logger:
level: ${EMISSARY_AGENT_LOGGER_LEVEL:-1}
format: ${EMISSARY_AGENT_LOGGER_FORMAT:-human}
sentry:
dsn: ${EMISSARY_AGENT_SENTRY_DSN}
agent:
serverUrl: ${EMISSARY_AGENT_SERVER_URL:-http://127.0.0.1:3000}
privateKeyPath: ${EMISSARY_AGENT_PRIVATE_KEY_PATH:-/data/agent-key.json}
reconciliationInterval: ${EMISSARY_AGENT_RECONCILIATION_INTERVAL:-30}
controllers:
persistence:
enabled: true
stateFile: ${EMISSARY_AGENT_CONTROLLERS_PERSISTENCE_STATE_FILE:-/data/state.json}
spec:
enabled: true
proxy:
enabled: true
uci:
enabled: false
app:
enabled: true
dataDir: ${EMISSARY_AGENT_CONTROLLERS_APP_DATA_DIR:-/data/apps/data}
downloadDir: ${EMISSARY_AGENT_CONTROLLERS_APP_DOWNLOAD_DIR:-/data/apps/bundles}
sysupgrade:
enabled: false
mdns:
enabled: true
collectors:
- name: uname
command: uname
args:
- -a

View File

@ -1,10 +0,0 @@
#!/bin/sh
set -e
# Generate machine id if not exists
if [ ! -f /etc/machine-id ]; then
cat /proc/sys/kernel/random/uuid > /etc/machine-id
fi
exec $@

View File

@ -1,35 +0,0 @@
logger:
level: ${EMISSARY_SERVER_LOGGER_LEVEL:-1}
format: ${EMISSARY_SERVER_LOGGER_FORMAT:-human}
sentry:
dsn: ${EMISSARY_SERVER_SENTRY_DSN}
server:
http:
host: ${EMISSARY_SERVER_HTTP_HOST:-0.0.0.0}
port: ${EMISSARY_SERVER_HTTP_HOST:-3000}
database:
driver: ${EMISSARY_SERVER_DATABASE_DRIVER:-sqlite}
dsn: ${EMISSARY_SERVER_DATABASE_DSN:-sqlite:///data/emissary.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=150000&_pragma=journal_mode=WAL}
cors:
allowedOrigins:
- ${EMISSARY_SERVER_CORS_ALLOWED_ORIGINS:-http://localhost:3001}
allowCredentials: ${EMISSARY_SERVER_CORS_ALLOW_CREDENTIALS:-true}
allowMethods:
- POST
- GET
- PUT
- DELETE
allowedHeaders:
- Origin
- Accept
- Content-Type
- Authorization
- Sentry-Trace
debug: ${EMISSARY_SERVER_CORS_DEBUG:-false}
auth:
local:
privateKeyPath: ${EMISSARY_SERVER_AUTH_LOCAL_PRIVATE_KEY_PATH:-/data/server-key.json}
remote:
jwksUrl: "${EMISSARY_SERVER_AUTH_REMOTE_JWKS_URL}"
roleExtractionRules:
- "${EMISSARY_SERVER_AUTH_ROLE_EXTRACTION_RULES_0:-jwt.role != nil ? str(jwt.role) : ''}"

View File

@ -4,7 +4,7 @@ ARG HTTP_PROXY=
ARG HTTPS_PROXY= ARG HTTPS_PROXY=
ARG http_proxy= ARG http_proxy=
ARG https_proxy= ARG https_proxy=
ARG GO_VERSION=1.21.1 ARG GO_VERSION=1.20.2
# Install dev environment dependencies # Install dev environment dependencies
RUN export DEBIAN_FRONTEND=noninteractive &&\ RUN export DEBIAN_FRONTEND=noninteractive &&\

View File

@ -1,9 +0,0 @@
/var/log/emissary/agent.log {
missingok
sharedscripts
compress
rotate 7
postrotate
/etc/init.d/emissary-agent restart
endscript
}

View File

@ -1,9 +0,0 @@
/var/log/emissary/server.log {
missingok
sharedscripts
compress
rotate 7
postrotate
/etc/init.d/emissary-server restart
endscript
}

View File

@ -4,40 +4,20 @@
"url": "https://emissary.cadol.es/files/apps/app.arcad.edge.hextris_v2023.4.20-2bbbe94.zip", "url": "https://emissary.cadol.es/files/apps/app.arcad.edge.hextris_v2023.4.20-2bbbe94.zip",
"sha256sum": "67942ef4b623c46308c3f640b534bd4cb6b1d6021a422e40b62ab97658ba4586", "sha256sum": "67942ef4b623c46308c3f640b534bd4cb6b1d6021a422e40b62ab97658ba4586",
"address": ":8083", "address": ":8083",
"format": "zip", "format": "zip"
"storage": {
"blobStoreDsn": "sqlite://apps/data/app.arcad.edge.hextris/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/app.arcad.edge.hextris/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
}, },
"edge.sdk.client.test": { "edge.sdk.client.test": {
"url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_2023.10.22-stable.847.22a3326.zip", "url": "https://emissary.cadol.es/files/apps/edge.sdk.client.test_v2023.4.20-20c4189.zip",
"sha256sum": "37aa6c4af57b647dc5cae4ec7d36f4289d99c1f090e533997e0d59188a0a04f4", "sha256sum": "1edeb4aa75c1675db49cf27367b1537234a04526848ea6657931ca63f26e5dae",
"address": ":8084", "address": ":8084",
"format": "zip", "format": "zip"
"storage": {
"blobStoreDsn": "sqlite://apps/data/edge.sdk.client.test/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/edge.sdk.client.test/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
},
"arcad.diffusion": {
"url": "https://emissary.cadol.es/files/apps/arcad.diffusion_v2023.10.12-cab0070.zip",
"sha256sum": "db58ec1ed463092fea2ee27cfd33dea5259739f1c6a4c9bf909ffd22392ee449",
"address": ":8085",
"format": "zip",
"storage": {
"blobStoreDsn": "sqlite://apps/data/arcad.diffusion/blobstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"shareStoreDsn": "sqlite://apps/data/sharestore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000",
"documentStoreDsn": "sqlite://apps/data/arcad.diffusion/documentstore.sqlite?_pragma=foreign_keys(1)&_pragma=busy_timeout=60000"
}
} }
}, },
"config": { "config": {
"appUrlResolving": { "appUrlResolving": {
"ifaceMappings": { "ifaceMappings": {
"lo": "http://{{ .DeviceIP }}:{{ .AppPort }}" "eth0": "http://{{ .DeviceIP }}:{{ .AppPort }}",
"eth1": "http://{{ .DeviceIP }}:{{ .AppPort }}"
}, },
"defaultUrlTemplate": "http://{{ last ( splitList \".\" ( toString .Manifest.ID ) ) }}.localhost.arcad.lan:8080" "defaultUrlTemplate": "http://{{ last ( splitList \".\" ( toString .Manifest.ID ) ) }}.localhost.arcad.lan:8080"
}, },
@ -48,7 +28,6 @@
"auth": { "auth": {
"local": { "local": {
"key": "absolutlynotsecret", "key": "absolutlynotsecret",
"signingAlgorithm": "HS256",
"cookieDuration": "1h", "cookieDuration": "1h",
"accounts": [ "accounts": [
{ {

View File

@ -14,11 +14,6 @@
"type": "_http._tcp", "type": "_http._tcp",
"port": 8080, "port": 8080,
"host": "arcad-test" "host": "arcad-test"
},
"diffusion": {
"type": "_http._tcp",
"port": 8080,
"host": "arcad-diffusion"
} }
} }
} }

View File

@ -11,10 +11,6 @@
"hostPattern": "test.localhost.arcad.lan:*", "hostPattern": "test.localhost.arcad.lan:*",
"target": "http://localhost:8084" "target": "http://localhost:8084"
}, },
{
"hostPattern": "diffusion.localhost.arcad.lan:*",
"target": "http://localhost:8085"
},
{ {
"hostPattern": "arcad-hextris.local:*", "hostPattern": "arcad-hextris.local:*",
"target": "http://localhost:8083" "target": "http://localhost:8083"
@ -23,10 +19,6 @@
"hostPattern": "arcad-test.local:*", "hostPattern": "arcad-test.local:*",
"target": "http://localhost:8084" "target": "http://localhost:8084"
}, },
{
"hostPattern": "arcad-diffusion.local:*",
"target": "http://localhost:8085"
},
{ {
"hostPattern": "*", "hostPattern": "*",
"target": "http://localhost:8084" "target": "http://localhost:8084"

View File

@ -1,2067 +0,0 @@
{
"config": {
"packages": [
{
"configs": [
{
"name": "dnsmasq",
"options": [
{
"name": "domainneeded",
"type": "option",
"value": "1"
},
{
"name": "boguspriv",
"type": "option",
"value": "1"
},
{
"name": "filterwin2k",
"type": "option",
"value": "0"
},
{
"name": "localise_queries",
"type": "option",
"value": "1"
},
{
"name": "rebind_localhost",
"type": "option",
"value": "1"
},
{
"name": "local",
"type": "option",
"value": "/lan/"
},
{
"name": "domain",
"type": "option",
"value": "lan"
},
{
"name": "expandhosts",
"type": "option",
"value": "1"
},
{
"name": "nonegcache",
"type": "option",
"value": "0"
},
{
"name": "authoritative",
"type": "option",
"value": "1"
},
{
"name": "readethers",
"type": "option",
"value": "1"
},
{
"name": "leasefile",
"type": "option",
"value": "/tmp/dhcp.leases"
},
{
"name": "resolvfile",
"type": "option",
"value": "/tmp/resolv.conf.d/resolv.conf.auto"
},
{
"name": "nonwildcard",
"type": "option",
"value": "1"
},
{
"name": "localservice",
"type": "option",
"value": "1"
},
{
"name": "ednspacket_max",
"type": "option",
"value": "1232"
},
{
"name": "rebind_protection",
"type": "option",
"value": "0"
},
{
"name": "interface",
"type": "list",
"value": "lan"
},
{
"name": "interface",
"type": "list",
"value": "guest"
},
{
"name": "logqueries",
"type": "option",
"value": "1"
},
{
"name": "address",
"type": "list",
"value": "/arcad.lan/10.10.10.1"
},
{
"name": "address",
"type": "list",
"value": "/#/10.10.10.1"
}
]
},
{
"name": "dhcp",
"options": [
{
"name": "interface",
"type": "option",
"value": "lan"
},
{
"name": "start",
"type": "option",
"value": "100"
},
{
"name": "limit",
"type": "option",
"value": "150"
},
{
"name": "leasetime",
"type": "option",
"value": "12h"
},
{
"name": "dhcpv4",
"type": "option",
"value": "server"
},
{
"name": "dhcpv6",
"type": "option",
"value": "server"
},
{
"name": "ra",
"type": "option",
"value": "server"
},
{
"name": "ra_slaac",
"type": "option",
"value": "1"
},
{
"name": "ra_flags",
"type": "list",
"value": "managed-config"
},
{
"name": "ra_flags",
"type": "list",
"value": "other-config"
}
],
"section": "lan"
},
{
"name": "dhcp",
"options": [
{
"name": "interface",
"type": "option",
"value": "wan"
},
{
"name": "ignore",
"type": "option",
"value": "1"
}
],
"section": "wan"
},
{
"name": "odhcpd",
"options": [
{
"name": "maindhcp",
"type": "option",
"value": "0"
},
{
"name": "leasefile",
"type": "option",
"value": "/tmp/hosts/odhcpd"
},
{
"name": "leasetrigger",
"type": "option",
"value": "/usr/sbin/odhcpd-update"
},
{
"name": "loglevel",
"type": "option",
"value": "4"
}
],
"section": "odhcpd"
},
{
"name": "dhcp",
"options": [
{
"name": "interface",
"type": "option",
"value": "guest"
},
{
"name": "start",
"type": "option",
"value": "100"
},
{
"name": "limit",
"type": "option",
"value": "150"
},
{
"name": "leasetime",
"type": "option",
"value": "12h"
},
{
"name": "dhcp_option",
"type": "list",
"value": "160,http://arcad.lan"
}
],
"section": "guest"
}
],
"name": "dhcp"
},
{
"configs": [
{
"name": "dropbear",
"options": [
{
"name": "PasswordAuth",
"type": "option",
"value": "on"
},
{
"name": "RootPasswordAuth",
"type": "option",
"value": "on"
},
{
"name": "Port",
"type": "option",
"value": "22"
}
]
}
],
"name": "dropbear"
},
{
"configs": [
{
"name": "main",
"options": [
{
"name": "reconciliation_interval",
"type": "option",
"value": "60"
},
{
"name": "server_url",
"type": "option",
"value": "https://emissary.cadol.es"
}
],
"section": "agent"
}
],
"name": "emissary"
},
{
"configs": [
{
"name": "defaults",
"options": [
{
"name": "syn_flood",
"type": "option",
"value": "1"
},
{
"name": "input",
"type": "option",
"value": "ACCEPT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "REJECT"
}
]
},
{
"name": "zone",
"options": [
{
"name": "name",
"type": "option",
"value": "lan"
},
{
"name": "network",
"type": "list",
"value": "lan"
},
{
"name": "input",
"type": "option",
"value": "ACCEPT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "zone",
"options": [
{
"name": "name",
"type": "option",
"value": "wan"
},
{
"name": "network",
"type": "list",
"value": "wan"
},
{
"name": "network",
"type": "list",
"value": "wan6"
},
{
"name": "input",
"type": "option",
"value": "REJECT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "REJECT"
},
{
"name": "masq",
"type": "option",
"value": "1"
},
{
"name": "mtu_fix",
"type": "option",
"value": "1"
}
]
},
{
"name": "forwarding",
"options": [
{
"name": "src",
"type": "option",
"value": "lan"
},
{
"name": "dest",
"type": "option",
"value": "wan"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-DHCP-Renew"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "udp"
},
{
"name": "dest_port",
"type": "option",
"value": "68"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
},
{
"name": "family",
"type": "option",
"value": "ipv4"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-Ping"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "icmp_type",
"type": "option",
"value": "echo-request"
},
{
"name": "family",
"type": "option",
"value": "ipv4"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-IGMP"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "igmp"
},
{
"name": "family",
"type": "option",
"value": "ipv4"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-DHCPv6"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "udp"
},
{
"name": "dest_port",
"type": "option",
"value": "546"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-MLD"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "src_ip",
"type": "option",
"value": "fe80::/10"
},
{
"name": "icmp_type",
"type": "list",
"value": "130/0"
},
{
"name": "icmp_type",
"type": "list",
"value": "131/0"
},
{
"name": "icmp_type",
"type": "list",
"value": "132/0"
},
{
"name": "icmp_type",
"type": "list",
"value": "143/0"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-ICMPv6-Input"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-request"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-reply"
},
{
"name": "icmp_type",
"type": "list",
"value": "destination-unreachable"
},
{
"name": "icmp_type",
"type": "list",
"value": "packet-too-big"
},
{
"name": "icmp_type",
"type": "list",
"value": "time-exceeded"
},
{
"name": "icmp_type",
"type": "list",
"value": "bad-header"
},
{
"name": "icmp_type",
"type": "list",
"value": "unknown-header-type"
},
{
"name": "icmp_type",
"type": "list",
"value": "router-solicitation"
},
{
"name": "icmp_type",
"type": "list",
"value": "neighbour-solicitation"
},
{
"name": "icmp_type",
"type": "list",
"value": "router-advertisement"
},
{
"name": "icmp_type",
"type": "list",
"value": "neighbour-advertisement"
},
{
"name": "limit",
"type": "option",
"value": "1000/sec"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-ICMPv6-Forward"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest",
"type": "option",
"value": "*"
},
{
"name": "proto",
"type": "option",
"value": "icmp"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-request"
},
{
"name": "icmp_type",
"type": "list",
"value": "echo-reply"
},
{
"name": "icmp_type",
"type": "list",
"value": "destination-unreachable"
},
{
"name": "icmp_type",
"type": "list",
"value": "packet-too-big"
},
{
"name": "icmp_type",
"type": "list",
"value": "time-exceeded"
},
{
"name": "icmp_type",
"type": "list",
"value": "bad-header"
},
{
"name": "icmp_type",
"type": "list",
"value": "unknown-header-type"
},
{
"name": "limit",
"type": "option",
"value": "1000/sec"
},
{
"name": "family",
"type": "option",
"value": "ipv6"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-IPSec-ESP"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest",
"type": "option",
"value": "lan"
},
{
"name": "proto",
"type": "option",
"value": "esp"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow-ISAKMP"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest",
"type": "option",
"value": "lan"
},
{
"name": "dest_port",
"type": "option",
"value": "500"
},
{
"name": "proto",
"type": "option",
"value": "udp"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow SSH on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "22"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow HTTP on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "80"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow HTTPS on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "443"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "zone",
"options": [
{
"name": "name",
"type": "option",
"value": "guest"
},
{
"name": "input",
"type": "option",
"value": "ACCEPT"
},
{
"name": "output",
"type": "option",
"value": "ACCEPT"
},
{
"name": "forward",
"type": "option",
"value": "REJECT"
},
{
"name": "network",
"type": "list",
"value": "guest"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8080 on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "8080"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8443 on WAN"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "proto",
"type": "option",
"value": "tcp"
},
{
"name": "dest_port",
"type": "option",
"value": "8443"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "proto",
"type": "list",
"value": "udp"
},
{
"name": "dest_port",
"type": "option",
"value": "5353"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
},
{
"name": "name",
"type": "option",
"value": "Allow mDNS from device"
},
{
"name": "src",
"type": "option",
"value": "*"
}
]
},
{
"name": "rule",
"options": [
{
"name": "proto",
"type": "list",
"value": "udp"
},
{
"name": "src_port",
"type": "option",
"value": "5353"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
},
{
"name": "name",
"type": "option",
"value": "Allow mDNS to device"
},
{
"name": "src",
"type": "option",
"value": "*"
}
]
},
{
"name": "redirect",
"options": [
{
"name": "target",
"type": "option",
"value": "DNAT"
},
{
"name": "proto",
"type": "list",
"value": "udp"
},
{
"name": "src",
"type": "option",
"value": "guest"
},
{
"name": "src_dport",
"type": "option",
"value": "53"
},
{
"name": "dest_ip",
"type": "option",
"value": "10.10.10.1"
},
{
"name": "dest_port",
"type": "option",
"value": "53"
},
{
"name": "name",
"type": "option",
"value": "Redirect DNS"
}
]
},
{
"name": "redirect",
"options": [
{
"name": "target",
"type": "option",
"value": "DNAT"
},
{
"name": "name",
"type": "option",
"value": "Redirect HTTP"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "guest"
},
{
"name": "src_dport",
"type": "option",
"value": "80"
},
{
"name": "dest_ip",
"type": "option",
"value": "10.10.10.1"
},
{
"name": "dest_port",
"type": "option",
"value": "80"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8081 for edge.sdk.client.test on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8081"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8082 for app.arcad.edge.hextris on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8082"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8083 for arcad.diffusion on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8083"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
},
{
"name": "rule",
"options": [
{
"name": "name",
"type": "option",
"value": "Allow 8084 for app.arcad.edge.menu on WAN"
},
{
"name": "proto",
"type": "list",
"value": "tcp"
},
{
"name": "src",
"type": "option",
"value": "wan"
},
{
"name": "dest_port",
"type": "option",
"value": "8084"
},
{
"name": "target",
"type": "option",
"value": "ACCEPT"
}
]
}
],
"name": "firewall"
},
{
"configs": [
{
"name": "core",
"options": [
{
"name": "lang",
"type": "option",
"value": "auto"
},
{
"name": "mediaurlbase",
"type": "option",
"value": "/luci-static/bootstrap"
},
{
"name": "resourcebase",
"type": "option",
"value": "/luci-static/resources"
},
{
"name": "ubuspath",
"type": "option",
"value": "/ubus/"
}
],
"section": "main"
},
{
"name": "extern",
"options": [
{
"name": "uci",
"type": "option",
"value": "/etc/config/"
},
{
"name": "dropbear",
"type": "option",
"value": "/etc/dropbear/"
},
{
"name": "openvpn",
"type": "option",
"value": "/etc/openvpn/"
},
{
"name": "passwd",
"type": "option",
"value": "/etc/passwd"
},
{
"name": "opkg",
"type": "option",
"value": "/etc/opkg.conf"
},
{
"name": "firewall",
"type": "option",
"value": "/etc/firewall.user"
},
{
"name": "uploads",
"type": "option",
"value": "/lib/uci/upload/"
}
],
"section": "flash_keep"
},
{
"name": "internal",
"options": null,
"section": "languages"
},
{
"name": "internal",
"options": [
{
"name": "sessionpath",
"type": "option",
"value": "/tmp/luci-sessions"
},
{
"name": "sessiontime",
"type": "option",
"value": "3600"
}
],
"section": "sauth"
},
{
"name": "internal",
"options": [
{
"name": "enable",
"type": "option",
"value": "1"
}
],
"section": "ccache"
},
{
"name": "internal",
"options": [
{
"name": "Bootstrap",
"type": "option",
"value": "/luci-static/bootstrap"
},
{
"name": "BootstrapDark",
"type": "option",
"value": "/luci-static/bootstrap-dark"
},
{
"name": "BootstrapLight",
"type": "option",
"value": "/luci-static/bootstrap-light"
}
],
"section": "themes"
},
{
"name": "internal",
"options": [
{
"name": "rollback",
"type": "option",
"value": "90"
},
{
"name": "holdoff",
"type": "option",
"value": "4"
},
{
"name": "timeout",
"type": "option",
"value": "5"
},
{
"name": "display",
"type": "option",
"value": "1.5"
}
],
"section": "apply"
},
{
"name": "internal",
"options": [
{
"name": "dns",
"type": "option",
"value": "openwrt.org"
},
{
"name": "ping",
"type": "option",
"value": "openwrt.org"
},
{
"name": "route",
"type": "option",
"value": "openwrt.org"
}
],
"section": "diag"
}
],
"name": "luci"
},
{
"configs": [
{
"name": "interface",
"options": [
{
"name": "proto",
"type": "option",
"value": "static"
},
{
"name": "ipaddr",
"type": "option",
"value": "127.0.0.1"
},
{
"name": "netmask",
"type": "option",
"value": "255.0.0.0"
},
{
"name": "device",
"type": "option",
"value": "lo"
}
],
"section": "loopback"
},
{
"name": "interface",
"options": [
{
"name": "proto",
"type": "option",
"value": "dhcp"
},
{
"name": "device",
"type": "option",
"value": "eth0"
}
],
"section": "wan"
},
{
"name": "interface",
"options": [
{
"name": "proto",
"type": "option",
"value": "static"
},
{
"name": "device",
"type": "option",
"value": "wlan0"
},
{
"name": "ipaddr",
"type": "option",
"value": "10.10.10.1"
},
{
"name": "netmask",
"type": "option",
"value": "255.255.255.0"
}
],
"section": "guest"
}
],
"name": "network"
},
{
"configs": [
{
"name": "rpcd",
"options": [
{
"name": "socket",
"type": "option",
"value": "/var/run/ubus/ubus.sock"
},
{
"name": "timeout",
"type": "option",
"value": "30"
}
]
},
{
"name": "login",
"options": [
{
"name": "username",
"type": "option",
"value": "root"
},
{
"name": "password",
"type": "option",
"value": "$p$root"
},
{
"name": "read",
"type": "list",
"value": "*"
},
{
"name": "write",
"type": "list",
"value": "*"
}
]
}
],
"name": "rpcd"
},
{
"configs": [
{
"name": "system",
"options": [
{
"name": "hostname",
"type": "option",
"value": "arcad-will"
},
{
"name": "timezone",
"type": "option",
"value": "UTC"
},
{
"name": "ttylogin",
"type": "option",
"value": "0"
},
{
"name": "log_size",
"type": "option",
"value": "64"
},
{
"name": "urandom_seed",
"type": "option",
"value": "0"
}
]
},
{
"name": "timeserver",
"options": [
{
"name": "enabled",
"type": "option",
"value": "1"
},
{
"name": "enable_server",
"type": "option",
"value": "0"
},
{
"name": "server",
"type": "list",
"value": "0.openwrt.pool.ntp.org"
},
{
"name": "server",
"type": "list",
"value": "1.openwrt.pool.ntp.org"
},
{
"name": "server",
"type": "list",
"value": "2.openwrt.pool.ntp.org"
},
{
"name": "server",
"type": "list",
"value": "3.openwrt.pool.ntp.org"
}
],
"section": "ntp"
}
],
"name": "system"
},
{
"configs": [
{
"name": "network",
"options": [
{
"name": "init",
"type": "option",
"value": "network"
},
{
"name": "affects",
"type": "list",
"value": "dhcp"
}
]
},
{
"name": "wireless",
"options": [
{
"name": "affects",
"type": "list",
"value": "network"
}
]
},
{
"name": "firewall",
"options": [
{
"name": "init",
"type": "option",
"value": "firewall"
},
{
"name": "affects",
"type": "list",
"value": "luci-splash"
},
{
"name": "affects",
"type": "list",
"value": "qos"
},
{
"name": "affects",
"type": "list",
"value": "miniupnpd"
}
]
},
{
"name": "olsr",
"options": [
{
"name": "init",
"type": "option",
"value": "olsrd"
}
]
},
{
"name": "dhcp",
"options": [
{
"name": "init",
"type": "option",
"value": "dnsmasq"
},
{
"name": "affects",
"type": "list",
"value": "odhcpd"
}
]
},
{
"name": "odhcpd",
"options": [
{
"name": "init",
"type": "option",
"value": "odhcpd"
}
]
},
{
"name": "dropbear",
"options": [
{
"name": "init",
"type": "option",
"value": "dropbear"
}
]
},
{
"name": "httpd",
"options": [
{
"name": "init",
"type": "option",
"value": "httpd"
}
]
},
{
"name": "fstab",
"options": [
{
"name": "exec",
"type": "option",
"value": "/sbin/block mount"
}
]
},
{
"name": "qos",
"options": [
{
"name": "init",
"type": "option",
"value": "qos"
}
]
},
{
"name": "system",
"options": [
{
"name": "init",
"type": "option",
"value": "led"
},
{
"name": "exec",
"type": "option",
"value": "/etc/init.d/log reload"
},
{
"name": "affects",
"type": "list",
"value": "luci_statistics"
},
{
"name": "affects",
"type": "list",
"value": "dhcp"
}
]
},
{
"name": "luci_splash",
"options": [
{
"name": "init",
"type": "option",
"value": "luci_splash"
}
]
},
{
"name": "upnpd",
"options": [
{
"name": "init",
"type": "option",
"value": "miniupnpd"
}
]
},
{
"name": "ntpclient",
"options": [
{
"name": "init",
"type": "option",
"value": "ntpclient"
}
]
},
{
"name": "samba",
"options": [
{
"name": "init",
"type": "option",
"value": "samba"
}
]
},
{
"name": "tinyproxy",
"options": [
{
"name": "init",
"type": "option",
"value": "tinyproxy"
}
]
}
],
"name": "ucitrack"
},
{
"configs": [
{
"name": "uhttpd",
"options": [
{
"name": "listen_http",
"type": "list",
"value": "0.0.0.0:8080"
},
{
"name": "listen_http",
"type": "list",
"value": "[::]:8080"
},
{
"name": "listen_https",
"type": "list",
"value": "0.0.0.0:8443"
},
{
"name": "listen_https",
"type": "list",
"value": "[::]:8443"
},
{
"name": "redirect_https",
"type": "option",
"value": "0"
},
{
"name": "home",
"type": "option",
"value": "/www"
},
{
"name": "rfc1918_filter",
"type": "option",
"value": "1"
},
{
"name": "max_requests",
"type": "option",
"value": "3"
},
{
"name": "max_connections",
"type": "option",
"value": "100"
},
{
"name": "cert",
"type": "option",
"value": "/etc/uhttpd.crt"
},
{
"name": "key",
"type": "option",
"value": "/etc/uhttpd.key"
},
{
"name": "cgi_prefix",
"type": "option",
"value": "/cgi-bin"
},
{
"name": "lua_prefix",
"type": "list",
"value": "/cgi-bin/luci=/usr/lib/lua/luci/sgi/uhttpd.lua"
},
{
"name": "script_timeout",
"type": "option",
"value": "60"
},
{
"name": "network_timeout",
"type": "option",
"value": "30"
},
{
"name": "http_keepalive",
"type": "option",
"value": "20"
},
{
"name": "tcp_keepalive",
"type": "option",
"value": "1"
},
{
"name": "ubus_prefix",
"type": "option",
"value": "/ubus"
}
],
"section": "main"
},
{
"name": "cert",
"options": [
{
"name": "days",
"type": "option",
"value": "730"
},
{
"name": "key_type",
"type": "option",
"value": "ec"
},
{
"name": "bits",
"type": "option",
"value": "2048"
},
{
"name": "ec_curve",
"type": "option",
"value": "P-256"
},
{
"name": "country",
"type": "option",
"value": "ZZ"
},
{
"name": "state",
"type": "option",
"value": "Somewhere"
},
{
"name": "location",
"type": "option",
"value": "Unknown"
},
{
"name": "commonname",
"type": "option",
"value": "OpenWrt"
}
],
"section": "defaults"
}
],
"name": "uhttpd"
},
{
"configs": [
{
"name": "wifi-device",
"options": [
{
"name": "type",
"type": "option",
"value": "mac80211"
},
{
"name": "path",
"type": "option",
"value": "platform/soc/3f300000.mmcnr/mmc_host/mmc1/mmc1:0001/mmc1:0001:1"
},
{
"name": "channel",
"type": "option",
"value": "1"
},
{
"name": "band",
"type": "option",
"value": "2g"
},
{
"name": "htmode",
"type": "option",
"value": "HT20"
},
{
"name": "cell_density",
"type": "option",
"value": "0"
}
],
"section": "radio0"
},
{
"name": "wifi-iface",
"options": [
{
"name": "device",
"type": "option",
"value": "radio0"
},
{
"name": "mode",
"type": "option",
"value": "ap"
},
{
"name": "ssid",
"type": "option",
"value": "Arcad - Connect and Play"
},
{
"name": "encryption",
"type": "option",
"value": "none"
},
{
"name": "network",
"type": "option",
"value": "guest"
}
],
"section": "default_radio0"
}
],
"name": "wireless"
}
]
},
"postImportCommands": []
}