Showing preview only (385K chars total). Download the full file or copy to clipboard to get everything.
Repository: jittering/traefik-kop
Branch: main
Commit: 4cb22a54e4f5
Files: 59
Total size: 366.7 KB
Directory structure:
gitextract_f_8i9uu6/
├── .dockerignore
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── on_push.yaml
│ └── on_tag.yaml
├── .gitignore
├── .goreleaser.yml
├── CHANGELOG.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── bin/
│ └── traefik-kop/
│ └── main.go
├── config.go
├── docker-compose.yml
├── docker.go
├── docker_helpers_test.go
├── docker_proxy.go
├── docker_proxy_test.go
├── docker_test.go
├── fixtures/
│ ├── docker-prefix.yml
│ ├── gitea.yml
│ ├── hello-automapped.yml
│ ├── hello-ignore.yml
│ ├── hello-multi-ns.yml
│ ├── hello-no-cert.yml
│ ├── hellodetect.yml
│ ├── helloip.yml
│ ├── helloworld.yml
│ ├── loadbalance1.yml
│ ├── loadbalance2.yml
│ ├── mqtt.yml
│ ├── musicassistant-tls.yml
│ ├── network.yml
│ ├── prefix-bindip.yml
│ ├── prefix.yml
│ └── sample.toml
├── go.mod
├── go.sum
├── kv.go
├── kv_test.go
├── kv_walk_test.go
├── multi_provider.go
├── multi_provider_test.go
├── polling_provider.go
├── polling_provider_test.go
├── store.go
├── store_test.go
├── testing/
│ ├── docker-compose.yml
│ ├── helloworld/
│ │ ├── Dockerfile
│ │ ├── README.md
│ │ ├── go.mod
│ │ └── main.go
│ ├── internal/
│ │ ├── Makefile
│ │ └── docker-compose.yml
│ ├── kop/
│ │ └── docker-compose.yml
│ └── publish-random.sh
├── traefik_kop.go
├── traefik_kop_test.go
└── util.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .dockerignore
================================================
.git
.gitignore
.env
.dockerignore
Dockerfile
Makefile
LICENSE
README.md
docs
dist/
================================================
FILE: .github/FUNDING.yml
================================================
github: chetan
================================================
FILE: .github/workflows/on_push.yaml
================================================
name: on-push
on:
push:
branches:
- main
pull_request:
branches:
- main
permissions:
packages: write
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build_docker:
name: Build Docker
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
# so we get proper snapshot version info
fetch-depth: 0
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ~1.25
cache: false
- name: Remote cache
uses: actions/cache@v4
if: ${{ runner.environment == 'github-hosted' }}
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
# repo disappeared
# - name: Local cache
# uses: actions-self-hosted/cache@v4
# if: ${{ runner.environment == 'self-hosted' }}
# with:
# cache-dir: /local-cache
# path: |
# ~/.cache/go-build
# ~/go/pkg/mod
# key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
- name: Set up GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
version: latest
install-only: true
- name: Test
run: |
set -eo pipefail
go mod tidy
go mod download
go test ./...
- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -eo pipefail
goreleaser release --clean --snapshot --parallelism 2
- name: Push docker images
if: ${{ github.ref == 'refs/heads/main' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Manually push docker images
docker images --format '{{ .Repository }}:{{ .Tag }}' \
| grep traefik-kop \
| grep -v none \
| xargs -n 1 docker push
- name: Cleanup local docker images
if: ${{ runner.environment == 'self-hosted' }}
run: |
# traefik-kop images
docker images \
| grep ghcr.io/jittering/traefik-kop \
| awk '{print $3}' \
| sort | uniq \
| xargs -r docker rmi -f
# runner images
docker images \
| grep myoung34/github-runner \
| grep none \
| awk '{print $3}' \
| sort | uniq \
| xargs -r docker rmi -f
- name: Cleanup old images from registry
uses: dataaxiom/ghcr-cleanup-action@v1
with:
tags: "*-next-*"
older-than: "30 days"
delete-untagged: true
================================================
FILE: .github/workflows/on_tag.yaml
================================================
name: tagged-release
on:
push:
tags:
- "v*"
permissions:
packages: write
contents: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
tagged-release:
name: Tagged Release
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ~1.25
cache: false
- name: Remote cache
uses: actions/cache@v4
if: ${{ runner.environment == 'github-hosted' }}
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
# repo disappeared
# - name: Local cache
# uses: actions-self-hosted/cache@v4
# if: ${{ runner.environment == 'self-hosted' }}
# with:
# cache-dir: /local-cache
# path: |
# ~/.cache/go-build
# ~/go/pkg/mod
# key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
- name: Test
run: |
set -eo pipefail
go mod tidy
go mod download
go test ./...
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
version: latest
args: release --clean
- name: Cleanup local docker images
if: ${{ runner.environment == 'self-hosted' }}
run: |
# traefik-kop images
docker images \
| grep ghcr.io/jittering/traefik-kop \
| awk '{print $3}' \
| sort | uniq \
| xargs -r docker rmi -f
# runner images
docker images \
| grep myoung34/github-runner \
| grep none \
| awk '{print $3}' \
| sort | uniq \
| xargs -r docker rmi -f
- name: Cleanup old images from registry
uses: dataaxiom/ghcr-cleanup-action@v1
with:
tags: "*-next-*"
older-than: "30 days"
delete-untagged: true
================================================
FILE: .gitignore
================================================
.DS_Store
.vscode/
/traefik-kop*
/dist
*.out
.history/
*.tmp
# temp files created by sugardb (used in tests)
aof/
================================================
FILE: .goreleaser.yml
================================================
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
version: 2
project_name: traefik-kop
before:
hooks:
- go mod tidy
- go mod download
builds:
- main: ./bin/traefik-kop/
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm
- arm64
goarm:
- "6"
- "7"
archives:
- name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
checksum:
name_template: "checksums.txt"
snapshot:
version_template: "{{ incpatch .Version }}-next-{{ .ShortCommit }}"
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
dockers_v2:
- images:
- "ghcr.io/jittering/{{ .ProjectName }}"
tags:
- "{{ .Version }}"
- "{{ if not .IsSnapshot }}{{ .Major }}.{{ .Minor }}{{ end }}"
- "{{ if not .IsSnapshot }}latest{{ end }}"
dockerfile: Dockerfile
platforms:
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64
labels:
"org.opencontainers.image.title": "{{ .ProjectName }}"
"org.opencontainers.image.description": "{{ .ProjectName }}"
"org.opencontainers.image.url": "https://github.com/jittering/{{ .ProjectName }}"
"org.opencontainers.image.source": "https://github.com/jittering/{{ .ProjectName }}"
"org.opencontainers.image.version": "{{ .Version }}"
"org.opencontainers.image.created": "{{ .Date }}"
"org.opencontainers.image.revision": "{{ .FullCommit }}"
"org.opencontainers.image.licenses": "MIT"
================================================
FILE: CHANGELOG.md
================================================
# Changelog
## v0.19.4
- disallow using DOCKER_HOST var together with prefixes (resolves #83)
## v0.19.3
### Fixes
- kop.bind.ip ignored when using label prefix (resolves #82)
## v0.19.2
### Fixes
- Proper fix for docker API version (upgraded traefik dep to 3.6.1)
## v0.19.1
### Fixes
- Auto-negotiation docker API version [#78](https://github.com/jittering/traefik-kop/issues/78)
## v0.19
### New Features
- Add `--skip-replace` (env: `SKIP_REPLACE=1`) to entirely [skip IP replacement](README.md#disable-ip-replacement-auto-detection)
### Fixes
- NPE when using label prefix [#76](https://github.com/jittering/traefik-kop/issues/76)
### Other
- Upgraded `traefik` lib used by `traefik-kop` to v3.5
**Note:** 3.x had some minor route config changes including a new field in 3.5. It is recommended to use the latest 3.5.x version of traefik with this release. If you are on 3.4 or lower, you should continue using 0.18.1 [`ghcr.io/jittering/traefik-kop:0.18.1`] (See #77 for details).
## v0.18.1
- Fixed docker build
## v0.18
### New Features
- Add `--bind-interface` (env: `BIND_INTERFACE`) to select the network interface from which to derive the bind IP when `--bind-ip` is not set. This requires the container to be run with `network_mode: host`. [#64, thanks @libnewton](https://github.com/jittering/traefik-kop/pull/58)
- Allow passing redis username via `--redis-user` (env: `REDIS_USER`) [#69](https://github.com/jittering/traefik-kop/pull/69)
- Allow filtering traefik labels using prefix [#70](https://github.com/jittering/traefik-kop/pull/70)
## v0.17
### New Features
- Support for setting a TTL on Redis keys [#58](https://github.com/jittering/traefik-kop/pull/58)
- Support for merging load balancers across multiple nodes managed by `traefik-kop` [#59](https://github.com/jittering/traefik-kop/pull/59)
### Fixes
- Allow outbound IP detection to fail [#56](https://github.com/jittering/traefik-kop/pull/56)
- Normalize container labels [#56](https://github.com/jittering/traefik-kop/pull/57)
## v0.16
### Fixes
- Fix port detection when publishing to ephemeral ports [#48, thanks @Flamefork](https://github.com/jittering/traefik-kop/pull/48)
## v0.15
### Fixes
- Push last config to redis in the case of a restart or failure in the cache [#46](https://github.com/jittering/traefik-kop/pull/46)
## v0.14
### New Features
- Allow filtering containers processed by `traefik-kop` using [namespaces](https://github.com/jittering/traefik-kop#namespaces)
### Fixes
- Use exact service name match when searching container labels (#39, thanks @damfleu)
**Full Changelog**: https://github.com/jittering/traefik-kop/compare/v0.13.3...v0.14
## v0.13.3
- 16beda8 build: bump go version to 1.22
## v0.13.2
- 10ab916 fix: properly stringify floats when writing to redis (resolves #25)
## v0.13.1
* [build: upgraded docker client dep](https://github.com/jittering/traefik-kop/commit/e7f30f3108f46cf0d174369b45f59d57398d002b)
* [fix: NPE when creating error message from port map](https://github.com/jittering/traefik-kop/commit/80d40e2aa904a78d4ec7b311c9f99bc449f556f3) ([fixes #24](https://github.com/jittering/traefik-kop/issues/24))
* [fix: avoid possible NPE when resolving CNI container IP](https://github.com/jittering/traefik-kop/commit/37686b0089ccaf91d4fa13df62447e15671944dd)
## [v0.13](https://github.com/jittering/traefik-kop/tree/v0.13) (2022-10-17)
[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.12.1...v0.13)
### New Features
- Set bind IP per-container or service
- Set traefik docker provider config (e.g., `defaultRule`)
### Fixes
- Correctly set port for TCP and UDP services
### Closed issues
- Go runtime error [\#20](https://github.com/jittering/traefik-kop/issues/20)
- Default Rule [\#18](https://github.com/jittering/traefik-kop/issues/18)
- Provide IP for each docker via label [\#17](https://github.com/jittering/traefik-kop/issues/17)
- setting port for tcp service does not work [\#16](https://github.com/jittering/traefik-kop/issues/16)
- Doesn't work with multiple services on one container [\#14](https://github.com/jittering/traefik-kop/issues/14)
## v0.12.1
This release updates the upstream version of the traefik library to v2.8.4 and
adds additional logging around port detection (both debug and info levels) to
make it easier to see what's going on and troubleshoot various scenarios.
[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.12...v0.12.1)
- [8c5a3f0](https://github.com/jittering/traefik-kop/commit/8c5a3f0) build: bump actions/cache to v3
- [dad6e90](https://github.com/jittering/traefik-kop/commit/dad6e90) build: bump go version in github actions
- [f009b84](https://github.com/jittering/traefik-kop/commit/f009b84) docs: added more detail and logging around port selection
- [2f18114](https://github.com/jittering/traefik-kop/commit/2f18114) test: added helloworld service for testing multiple bindings
- [be636f7](https://github.com/jittering/traefik-kop/commit/be636f7) build: upgraded traefik to 2.8.4 (now supports go 1.18+)
## v0.12
### Notes
By default, `traefik-kop` will listen for push events via the Docker API in
order to detect configuration changes. In some circumstances, a change may not
be pushed correctly. For example, when using healthchecks in certain
configurations, the `start -> healthy` change may not be detected via push
event. As a failsafe, there is an additional polling mechanism to detect those
missed changes.
The default interval of 60 seconds should be light so as not to cause any
issues, however it can be adjusted as needed via the `KOP_POLL_INTERVAL` env var
or set to 0 to disable it completely.
[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.11...v0.12)
- [347352b](https://github.com/jittering/traefik-kop/commit/347352b) build: fix goreleaser tidy
- [b6447c3](https://github.com/jittering/traefik-kop/commit/b6447c3) build: go mod tidy
- [12ad255](https://github.com/jittering/traefik-kop/commit/12ad255) docs: added poll interval to readme
- [10f7aab](https://github.com/jittering/traefik-kop/commit/10f7aab) feat: expose providers in case anyone wants to reuse
- [5b58547](https://github.com/jittering/traefik-kop/commit/5b58547) feat: add log message when explicitly disabling polling
- [02802d5](https://github.com/jittering/traefik-kop/commit/02802d5) feat: configurable poll interval (default 60)
- [b2ef52b](https://github.com/jittering/traefik-kop/commit/b2ef52b) feat: combine providers into single config watcher
- [07fe8aa](https://github.com/jittering/traefik-kop/commit/07fe8aa) feat: added polling provider as a workaround for healthcheck issue
- [cc3854b](https://github.com/jittering/traefik-kop/commit/cc3854b) feat: added config for changing docker endpoint
- [c309d40](https://github.com/jittering/traefik-kop/commit/c309d40) build: upgraded traefik lib to v2.7
- [32c2df6](https://github.com/jittering/traefik-kop/commit/32c2df6) test: added pihole container (with builtin healthcheck)
- [e770242](https://github.com/jittering/traefik-kop/commit/e770242) docs: updated changelog
## v0.11
[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.10.1...v0.11)
#### Notes
* If your container is configured to use a network-routable IP address via an
overlay network or CNI plugin, that address will override the `bind-ip`
configuration when the `traefik.docker.network` label is present.
**Merged pull requests:**
- Add support for `traefik.docker.network` [\#8](https://github.com/jittering/traefik-kop/pull/8) ([hcooper](https://github.com/hcooper))
## v0.10.1
* e0af6eb Merge pull request #7 from jittering/fix/port-detect
## v0.10.1
* e0af6eb Merge pull request #7 from jittering/fix/port-detect
## v0.10.0
* 5d029d2 feat: add support for ports published via --publish-all (closes #6)
## v0.9.2
* 5871d16 feat: log the container name/id if found
## v0.9.1
* fbd2d1d fix: Automatic port assignment not working for containers without a service
## v0.9
* 4bd7cd1 Merge pull request #2 from jittering/feature/detect-host-port
## v0.8.1
* e69bd05 fix: strip @docker when removing keys
### Docker images
- `docker pull ghcr.io/jittering/traefik-kop:0.8.1`
## v0.8
* dccbf22 build: fix release step
### Docker images
- `docker pull ghcr.io/jittering/traefik-kop:0.8`
================================================
FILE: Dockerfile
================================================
FROM scratch
ENTRYPOINT ["/traefik-kop"]
ARG TARGETPLATFORM
COPY $TARGETPLATFORM/traefik-kop /traefik-kop
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Chetan Sarva
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
PROJECT=ghcr.io/jittering/traefik-kop
.DEFAULT_GOAL := run
SHELL := bash
build-docker: build-linux
docker build --platform linux/amd64 -t ${PROJECT}:latest .
build-linux:
GOOS=linux go build ./bin/traefik-kop
build:
go build ./bin/traefik-kop
run:
go run ./bin/traefik-kop
serve: run
test:
go test ./...
cover:
go test -coverprofile=c.out ./...
watch:
watchexec -e go,yml "make test"
watch-cover:
watchexec -e go,yml "make cover"
clean:
rm -rf dist/
rm -f traefik-kop
rm -rf aof/
release: clean
goreleaser release --rm-dist --skip-validate
update-changelog:
echo -e "# Changelog\n" >> temp.md
rel=$$(gh release list | head -n 1 | awk '{print $$1}'); \
echo "## $$rel" >> temp.md; \
echo "" >> temp.md; \
gh release view --json body $$rel | \
jq --raw-output '.body' | \
grep -v '^## Changelog' | \
sed -e 's/^#/##/g' >> temp.md
cat CHANGELOG.md | grep -v '^# Changelog' >> temp.md
mv temp.md CHANGELOG.md
================================================
FILE: README.md
================================================
# traefik-kop
A dynamic docker->redis->traefik discovery agent.
Solves the problem of running a non-Swarm/Kubernetes multi-host cluster with a
single public-facing traefik instance.
```text
+---------------------+ +---------------------+
| | | |
+---------+ :443 | +---------+ | :8088 | +------------+ |
| WAN |--------------->| traefik |<-------------------->| svc-nginx | |
+---------+ | +---------+ | | +------------+ |
| | | | |
| +---------+ | | +-------------+ |
| | redis |<-------------------->| traefik-kop | |
| +---------+ | | +-------------+ |
| docker1 | | docker2 |
+---------------------+ +---------------------+
```
`traefik-kop` solves this problem by using the same `traefik` docker-provider
logic. It reads the container labels from the local docker node and publishes
them to a given `redis` instance. Simply configure your `traefik` node with a
`redis` provider and point it to the same instance, as in the diagram above.
## Contents
- [traefik-kop](#traefik-kop)
- [Contents](#contents)
- [Usage](#usage)
- [Configuration](#configuration)
- [IP Binding](#ip-binding)
- [bind-ip](#bind-ip)
- [bind-interface](#bind-interface)
- [traefik-kop service labels](#traefik-kop-service-labels)
- [Container Networking](#container-networking)
- [Disable IP Replacement (auto-detection)](#disable-ip-replacement-auto-detection)
- [Load Balancer Merging](#load-balancer-merging)
- [Service port binding](#service-port-binding)
- [Namespaces](#namespaces)
- [Namespace via label prefix](#namespace-via-label-prefix)
- [Docker API](#docker-api)
- [Traefik Docker Provider Config](#traefik-docker-provider-config)
- [Releasing](#releasing)
- [License](#license)
## Usage
Configure `traefik` to use the redis provider, for example via `traefik.yml`:
```yaml
providers:
providersThrottleDuration: 2s
docker:
watch: true
endpoint: unix:///var/run/docker.sock
swarmModeRefreshSeconds: 15s
exposedByDefault: false
redis:
endpoints:
# assumes a redis link with this service name running on the same
# docker host as traefik
- "redis:6379"
```
Run `traefik-kop` on your other nodes via docker-compose:
```yaml
services:
traefik-kop:
image: "ghcr.io/jittering/traefik-kop:latest"
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "REDIS_ADDR=192.168.1.50:6379"
- "BIND_IP=192.168.1.75"
# Alternatively, derive from an interface (requires network_mode: host)
# - "BIND_INTERFACE=eth0"
```
Then add the usual labels to your target service:
```yml
services:
nginx:
image: "nginx:alpine"
restart: unless-stopped
ports:
# The host port binding will automatically be picked up for use as the
# service endpoint. See 'service port binding' in the configuration
# section for more.
- 8088:80
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.rule=Host(`nginx-on-docker2.example.com`)"
- "traefik.http.routers.nginx.tls=true"
- "traefik.http.routers.nginx.tls.certresolver=default"
# [opptional] explicitly set the port binding for this service.
# See 'service port binding' in the configuration section for more.
- "traefik.http.services.nginx.loadbalancer.server.scheme=http"
- "traefik.http.services.nginx.loadbalancer.server.port=8088"
```
See also the [IP Binding](#ip-binding) section below.
## Configuration
traefik-kop can be configured via either CLI flags or environment variables.
```text
USAGE:
traefik-kop [global options] command [command options] [arguments...]
GLOBAL OPTIONS:
--hostname value Hostname to identify this node in redis (default: "server.local") [$KOP_HOSTNAME]
--bind-ip value IP address to bind services to [$BIND_IP]
--bind-interface value Network interface to derive bind IP (overrides auto-detect) [$BIND_INTERFACE]
--skip-replace Disable custom IP replacement (default: false) [$SKIP_REPLACE]
--redis-addr value Redis address (default: "127.0.0.1:6379") [$REDIS_ADDR]
--redis-user value Redis username (default: "default") [$REDIS_USER]
--redis-pass value Redis password (if needed) [$REDIS_PASS]
--redis-db value Redis DB number (default: 0) [$REDIS_DB]
--redis-ttl value Redis TTL (in seconds) (default: 0) [$REDIS_TTL]
--docker-host value Docker endpoint (default: "unix:///var/run/docker.sock") [$DOCKER_ADDR]
--docker-config value Docker provider config (file must end in .yaml) [$DOCKER_CONFIG]
--docker-prefix value Docker label prefix [$DOCKER_PREFIX]
--poll-interval value Poll interval for refreshing container list (default: 60) [$KOP_POLL_INTERVAL]
--namespace value Namespace to process containers for [$NAMESPACE]
--verbose Enable debug logging (default: false) [$VERBOSE, $DEBUG]
--help, -h show help
--version, -V Print the version (default: false)
```
Most important are the `bind-ip`/`bind-interface` and `redis-addr` flags.
## IP Binding
There are a number of ways to set the IP published to traefik. Below is the
order of precedence (highest first) and detailed descriptions of each setting.
1. `kop.<service name>.bind.ip` label
2. `kop.bind.ip` label
3. Container networking IP
4. `--bind-ip` CLI flag (or `BIND_IP` env var)
5. `--bind-interface` CLI flag (or `BIND_INTERFACE` env var), requires network_mode: host
6. Auto-detected host IP
### bind-ip
Since your upstream docker nodes are external to your primary traefik server,
traefik needs to connect to these services via the server's public IP rather
than the usual method of using the internal docker-network IPs (by default
172.20.0.x or similar).
When using host networking this can be auto-detected, however it is advisable in
the majority of cases to manually set this to the desired IP address. This can
be done using the docker image by exporting the `BIND_IP` environment variable.
### bind-interface
If you prefer to bind using the primary IPv4 address of a specific network
interface, you can specify it via `--bind-interface` or the `BIND_INTERFACE`
environment variable, for example `--bind-interface eth0`. This is used when
`--bind-ip` is not provided. If the interface has multiple addresses, the first
non-loopback IPv4 address is selected.
This option requires that the container be run with `network_mode: host` so that the interface is visible to the container.
### traefik-kop service labels
The bind IP can be set via label for each service/container.
Labels can be one of two keys:
- `kop.<service name>.bind.ip=2.2.2.2`
- `kop.bind.ip=2.2.2.2`
For a container with a single exposed service, or where all services use
the same IP, the latter is sufficient.
### Container Networking
If your container is configured to use a network-routable IP address via an
overlay network or CNI plugin, that address will override the `bind-ip`
configuration above when the `traefik.docker.network` label is present on the
service.
If using a global overlay `network` in your [Traefik Docker Provider
Config](#traefik-docker-provider-config), it is recommended that you [disable IP
replacement](#disable-ip-replacement-auto-detection) entirely (see below).
### Disable IP Replacement (auto-detection)
traefik-kop's custom IP and port auto-detection can be disabled by passing the `--skip-replace` flag
or setting the `SKIP_REPLACE=1` environment variable. When set, `traefik-kop` will rely solely on
traefik's native IP and port detection. Other relevant flags such as `--bind-ip` or `--bind-interface`
will have no effect.
This works best when your services are using an overlay network, as described in
[Container Networking](#container-networking) above.
## Load Balancer Merging
If your service is running on multiple nodes and load balanced by traefik, you can enable
merging of load balancers by adding the following label to your container:
- `kop.merge-lbs=true`
When set, kop will check in redis for an existing definition and, if found, append it's service
address to the ones already present.
This setting is off by default as there are some cases where it could cause an issue, such as if
your node's IP changes. In this case, the dead IP would be left in place and the new IP would get
added to the list, causing some of your traffic to fail.
## Service port binding
By default, the service port will be picked up from the container port bindings
if only a single port is bound. For example:
```yml
services:
nginx:
image: "nginx:alpine"
restart: unless-stopped
ports:
- 8088:80
```
`8088` would automatically be used as the service endpoint's port in traefik. If
you have more than one port or are using *host networking*, you will need to
explicitly set the port binding via service label, like so:
```yaml
services:
nginx:
image: "nginx:alpine"
network_mode: host
ports:
- 8088:80
- 8888:81
labels:
# (note: other labels snipped for brevity)
- "traefik.http.services.nginx.loadbalancer.server.port=8088"
```
__NOTE:__ unlike the standard traefik-docker usage, we need to expose the
service port on the host and tell traefik to bind to *that* port (8088 in the
example above) in the load balancer config, not the internal port (80). This is
so that traefik can reach it over the network.
## Namespaces
traefik-kop has the ability to target containers via namespaces(s). Simply
configure `kop` with a namespace:
```yaml
services:
traefik-kop:
image: "ghcr.io/jittering/traefik-kop:latest"
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "REDIS_ADDR=192.168.1.50:6379"
- "BIND_IP=192.168.1.75"
- "NAMESPACE=staging"
```
Then add the `kop.namespace` label to your target services, along with the usual traefik labels:
```yaml
services:
nginx:
image: "nginx:alpine"
restart: unless-stopped
ports:
- 8088:80
labels:
- "kop.namespace=staging"
- "traefik.enable=true"
- "traefik..."
```
Multiple namespaces can be used by comma-delimiting your values. Traefik-kop will include a container as long as one of its namespaces is found.
```yaml
services:
traefik-kop:
# ...
environment:
# will expose any service with either 'dev' or 'staging'
- "NAMESPACE=dev,staging"
```
```yaml
services:
nginx:
# ...
labels:
# will be exposed because it has namespace 'staging'
- "kop.namespace=staging,experimental"
```
### Namespace via label prefix
An alternative method of namespacing is to add a custom prefix for your traefik-related labels. This
works as an *inclusion* filter for `traefik-kop` and an *exclusion* filter for `traefik`. This can
be useful in a scenario here you are running both `traefik` and `traefik-kop` side-by-side on the
same host.
```yaml
services:
nginx:
labels:
- "traefik.enable=true"
- "traefik.http.routers..."
- "traefik..."
```
becomes
```yaml
services:
traefik-kop:
image: "ghcr.io/jittering/traefik-kop:latest"
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "REDIS_ADDR=192.168.1.50:6379"
- "BIND_IP=192.168.1.75"
- "DOCKER_PREFIX=kop.public"
nginx:
labels:
- "kop.public.traefik.enable=true"
- "kop.public.traefik.http.routers..."
- "kop.public.traefik..."
```
## Docker API
traefik-kop expects to connect to the Docker host API via a unix socket, by
default at `/var/run/docker.sock`. The location can be overridden via the
`DOCKER_ADDR` env var or `--docker-host` flag.
Other connection methods (like ssh, http/s) are not supported.
By default, `traefik-kop` will listen for push events via the Docker API in
order to detect configuration changes. In some circumstances, a change may not
be pushed correctly. For example, when using healthchecks in certain
configurations, the `start -> healthy` change may not be detected via push
event. As a failsafe, there is an additional polling mechanism to detect those
missed changes.
The default interval of 60 seconds should be light so as not to cause any
issues, however it can be adjusted as needed via the `KOP_POLL_INTERVAL` env var
or set to 0 to disable it completely.
### Traefik Docker Provider Config
In addition to the simple `--docker-host` setting above, all [Docker Provider
configuration
options](https://doc.traefik.io/traefik/providers/docker/#provider-configuration)
are available via the `--docker-config <filename.yaml>` flag which expects
either a filename to read configuration from or an inline YAML document.
For example:
```yaml
services:
traefik-kop:
image: "ghcr.io/jittering/traefik-kop:latest"
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
REDIS_ADDR: "172.28.183.97:6380"
BIND_IP: "172.28.183.97"
DOCKER_CONFIG: |
---
docker:
defaultRule: Host(`{{.Name}}.foo.example.com`)
```
## Releasing
To release a new version, simply push a new tag to github.
```sh
git push
git tag -a v0.11.0
git push --tags
```
To update the changelog:
```sh
make update-changelog
# or (replace tag below)
docker run -it --rm -v "$(pwd)":/usr/local/src/your-app \
githubchangeloggenerator/github-changelog-generator \
-u jittering -p traefik-kop --output "" \
--since-tag v0.10.1
```
## License
traefik-kop: MIT, (c) 2015, Pixelcop Research, Inc.
traefik: MIT, (c) 2016-2025 Containous SAS; 2020-2022 Traefik Labs
================================================
FILE: bin/traefik-kop/main.go
================================================
package main
import (
"fmt"
"net"
"os"
"strings"
traefikkop "github.com/jittering/traefik-kop"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
const defaultDockerHost = "unix:///var/run/docker.sock"
var (
version string
commit string
date string
builtBy string
)
func printVersion(c *cli.Context) error {
fmt.Printf("%s version %s (commit: %s, built %s)\n", c.App.Name, c.App.Version, commit, date)
return nil
}
func flags() {
if version == "" {
version = "n/a"
}
if commit == "" {
commit = "head"
}
if date == "" {
date = "n/a"
}
cli.VersionFlag = &cli.BoolFlag{
Name: "version",
Aliases: []string{"V"},
Usage: "Print the version",
}
cli.VersionPrinter = func(c *cli.Context) {
printVersion(c)
}
app := &cli.App{
Name: "traefik-kop",
Usage: "A dynamic docker->redis->traefik discovery agent",
Version: version,
Action: doStart,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "hostname",
Usage: "Hostname to identify this node in redis",
Value: getHostname(),
EnvVars: []string{"KOP_HOSTNAME"},
},
&cli.StringFlag{
Name: "bind-ip",
Usage: "IP address to bind services to",
EnvVars: []string{"BIND_IP"},
},
&cli.StringFlag{
Name: "bind-interface",
Usage: "Network interface to derive bind IP (overrides auto-detect)",
EnvVars: []string{"BIND_INTERFACE"},
},
&cli.BoolFlag{
Name: "skip-replace",
Usage: "Disable custom IP replacement",
EnvVars: []string{"SKIP_REPLACE"},
},
&cli.StringFlag{
Name: "redis-addr",
Usage: "Redis address",
Value: "127.0.0.1:6379",
EnvVars: []string{"REDIS_ADDR"},
},
&cli.StringFlag{
Name: "redis-user",
Usage: "Redis username",
Value: "default",
EnvVars: []string{"REDIS_USER"},
},
&cli.StringFlag{
Name: "redis-pass",
Usage: "Redis password (if needed)",
EnvVars: []string{"REDIS_PASS"},
},
&cli.IntFlag{
Name: "redis-db",
Usage: "Redis DB number",
Value: 0,
EnvVars: []string{"REDIS_DB"},
},
&cli.IntFlag{
Name: "redis-ttl",
Usage: "Redis TTL (in seconds)",
Value: 0,
EnvVars: []string{"REDIS_TTL"},
},
&cli.StringFlag{
Name: "docker-host",
Usage: "Docker endpoint",
Value: defaultDockerHost,
EnvVars: []string{"DOCKER_ADDR", "DOCKER_HOST"},
},
&cli.StringFlag{
Name: "docker-config",
Usage: "Docker provider config (file must end in .yaml)",
EnvVars: []string{"DOCKER_CONFIG"},
},
&cli.StringFlag{
Name: "docker-prefix",
Usage: "Docker label prefix",
EnvVars: []string{"DOCKER_PREFIX"},
},
&cli.Int64Flag{
Name: "poll-interval",
Usage: "Poll interval for refreshing container list",
Value: 60,
EnvVars: []string{"KOP_POLL_INTERVAL"},
},
&cli.StringFlag{
Name: "namespace",
Usage: "Namespace to process containers for",
EnvVars: []string{"NAMESPACE"},
},
&cli.BoolFlag{
Name: "verbose",
Usage: "Enable debug logging",
Value: false,
EnvVars: []string{"VERBOSE", "DEBUG"},
},
},
}
err := app.Run(os.Args)
if err != nil {
log.Fatal().Err(err).Msg("Application error")
}
}
func setupLogging(debug bool) {
if debug {
logrus.SetLevel(logrus.DebugLevel)
zerolog.SetGlobalLevel(zerolog.DebugLevel)
log.Logger = log.Logger.Level(zerolog.DebugLevel)
} else {
logrus.SetLevel(logrus.InfoLevel)
zerolog.SetGlobalLevel(zerolog.InfoLevel)
log.Logger = log.Logger.Level(zerolog.InfoLevel)
}
zerolog.DefaultContextLogger = &log.Logger
formatter := &logrus.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true}
logrus.SetFormatter(formatter)
}
func main() {
flags()
}
func splitStringArr(str string) []string {
trimmed := strings.TrimSpace(str)
if trimmed != "" {
trimmedVals := strings.Split(trimmed, ",")
splitArr := make([]string, len(trimmedVals))
for i, v := range trimmedVals {
splitArr[i] = strings.TrimSpace(v)
}
return splitArr
}
return []string{}
}
func doStart(c *cli.Context) error {
traefikkop.Version = version
namespaces := splitStringArr(c.String("namespace"))
// Determine bind IP: precedence -> explicit --bind-ip -> --bind-interface -> auto-detect
bindIP := strings.TrimSpace(c.String("bind-ip"))
if bindIP == "" {
iface := strings.TrimSpace(c.String("bind-interface"))
bindIP = getDefaultIP(iface)
}
config := traefikkop.Config{
Hostname: c.String("hostname"),
BindIP: bindIP,
SkipReplace: c.Bool("skip-replace"),
RedisAddr: c.String("redis-addr"),
RedisUser: c.String("redis-user"),
RedisPass: c.String("redis-pass"),
RedisDB: c.Int("redis-db"),
RedisTTL: c.Int("redis-ttl"),
DockerHost: c.String("docker-host"),
DockerConfig: c.String("docker-config"),
DockerPrefix: c.String("docker-prefix"),
PollInterval: c.Int64("poll-interval"),
Namespace: namespaces,
}
if config.BindIP == "" {
log.Fatal().Msg("Bind IP cannot be empty")
}
if os.Getenv("DOCKER_HOST") != "" {
if config.DockerPrefix != "" {
log.Fatal().Msgf("Using the DOCKER_HOST env var with the DOCKER PREFIX feature is not allowed; use DOCKER_ADDR to set the Docker endpoint instead")
} else if config.DockerHost != os.Getenv("DOCKER_HOST") {
log.Warn().Msgf("Setting the DOCKER_HOST env var in addition to the --docker-host flag or DOCKER_ADDR env var is not recommended and may cause unexpected behavior.")
}
}
setupLogging(c.Bool("verbose"))
log.Debug().Msgf("using traefik-kop config: %s", fmt.Sprintf("%+v", config))
traefikkop.Start(config)
return nil
}
func getHostname() string {
hostname, err := os.Hostname()
if err != nil {
return "traefik-kop"
}
return hostname
}
func getDefaultIP(iface string) string {
// If a network interface is specified, attempt to get its primary IPv4 address
if strings.TrimSpace(iface) != "" {
if ip := GetInterfaceIP(iface); ip != nil {
return ip.String()
}
log.Warn().Msgf("failed to get IP for interface '%s'; falling back to auto-detect", iface)
}
ip := GetOutboundIP()
if ip == nil {
return ""
}
return ip.String()
}
// Get preferred outbound ip of this machine
// via https://stackoverflow.com/a/37382208/102920
func GetOutboundIP() net.IP {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Warn().Msgf("failed to detect outbound IP: %s", err)
return nil
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP
}
// GetInterfaceIP returns the first non-loopback IPv4 address for the named interface
func GetInterfaceIP(name string) net.IP {
iface, err := net.InterfaceByName(name)
if err != nil {
log.Warn().Msgf("unable to find interface '%s': %v", name, err)
return nil
}
addrs, err := iface.Addrs()
if err != nil {
log.Warn().Msgf("unable to list addresses for interface '%s': %v", name, err)
return nil
}
for _, a := range addrs {
var ip net.IP
switch v := a.(type) {
case *net.IPNet:
ip = v.IP
case *net.IPAddr:
ip = v.IP
}
if ip == nil || ip.IsLoopback() {
continue
}
ip = ip.To4()
if ip == nil {
continue // skip IPv6 for bind default
}
return ip
}
return nil
}
================================================
FILE: config.go
================================================
package traefikkop
import (
"io"
"os"
"regexp"
"strings"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v3/pkg/provider/docker"
"gopkg.in/yaml.v3"
)
type Config struct {
DockerConfig string
DockerHost string
// prefix for traefik labels to accept
DockerPrefix string
Hostname string
BindIP string
SkipReplace bool
RedisAddr string
RedisTTL int
RedisUser string
RedisPass string
RedisDB int
PollInterval int64
Namespace []string
}
type ConfigFile struct {
Docker docker.Provider `yaml:"docker"`
}
func loadDockerConfig(input string) (*docker.Provider, error) {
if input == "" {
return nil, nil
}
var r io.Reader
if looksLikeFile(input) {
// see if given filename
_, err := os.Stat(input)
if err == nil {
log.Debug().Msgf("loading docker config from file %s", input)
r, err = os.Open(input)
if err != nil {
return nil, errors.Wrapf(err, "failed to open docker config %s", input)
}
defer r.(io.Closer).Close()
} else {
return nil, errors.Wrapf(err, "failed to stat docker config %s", input)
}
} else {
log.Debug().Msgf("loading docker config from yaml input")
r = strings.NewReader(input) // treat as direct yaml input
}
// parse
conf := ConfigFile{Docker: docker.Provider{}}
err := yaml.NewDecoder(r).Decode(&conf)
if err != nil {
return nil, errors.Wrap(err, "failed to load config")
}
conf.Docker.Network = strings.TrimSpace(conf.Docker.Network)
return &conf.Docker, nil
}
func looksLikeFile(input string) bool {
if strings.Contains(input, "\n") {
return false
}
ok, _ := regexp.MatchString(`\.ya?ml`, input)
return ok
}
================================================
FILE: docker-compose.yml
================================================
version: "3"
services:
traefik-kop:
image: "ghcr.io/jittering/traefik-kop:latest"
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- "REDIS_ADDR=192.168.1.50:6379"
- "BIND_IP=192.168.1.75"
================================================
FILE: docker.go
================================================
package traefikkop
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
// Copied from traefik. See docker provider package for original impl
type dockerCache struct {
client client.APIClient
list []container.Summary
details map[string]container.InspectResponse
expires time.Time
}
// Must be 0 for unix socket?
// Non-zero throws an error
const defaultTimeout = time.Duration(0)
func createDockerClient(endpoint string) (client.APIClient, error) {
opts, err := getClientOpts(endpoint)
if err != nil {
return nil, err
}
httpHeaders := map[string]string{
"User-Agent": "traefik-kop " + Version,
}
opts = append(opts, client.WithHTTPHeaders(httpHeaders))
// Use API version negotiation for compatibility with both old and new Docker daemons
// This fixes the issue with Docker CE 29.0.0 which requires minimum API version 1.44
opts = append(opts, client.WithAPIVersionNegotiation())
return client.NewClientWithOpts(opts...)
}
func getClientOpts(endpoint string) ([]client.Opt, error) {
// we currently do not support ssh, so skip helper setup
opts := []client.Opt{
client.WithHost(endpoint),
client.WithTimeout(time.Duration(defaultTimeout)),
}
return opts, nil
}
// populate the cache with the current list of running containers and their details.
//
// Cache expires after 30 seconds.
func (dc *dockerCache) populate() error {
if time.Now().After(dc.expires) {
dc.list = nil
dc.details = make(map[string]container.InspectResponse)
}
if dc.list == nil {
var err error
dc.list, err = dc.client.ContainerList(context.Background(), container.ListOptions{})
if err != nil {
return errors.Wrap(err, "failed to list containers")
}
}
for _, c := range dc.list {
var container container.InspectResponse
var ok bool
if container, ok = dc.details[c.ID]; !ok {
var err error
container, err = dc.client.ContainerInspect(context.Background(), c.ID)
if err != nil {
return errors.Wrapf(err, "failed to inspect container %s", c.ID)
}
dc.details[c.ID] = container
}
// normalize labels
labels := make(map[string]string, len(container.Config.Labels))
for k, v := range container.Config.Labels {
labels[strings.ToLower(k)] = v
}
container.Config.Labels = labels
}
dc.expires = time.Now().Add(5 * time.Second) // cache expires in 30 seconds
return nil
}
// looks up the docker container by finding the matching service or router traefik label
func (dc *dockerCache) findContainerByServiceName(svcType string, svcName string, routerName string) (container.InspectResponse, error) {
err := dc.populate()
if err != nil {
return container.InspectResponse{}, err
}
svcName = stripDocker(svcName)
routerName = stripDocker(routerName)
for _, container := range dc.details {
// check labels
svcNeedle := fmt.Sprintf("traefik.%s.services.%s.", svcType, svcName)
routerNeedle := fmt.Sprintf("traefik.%s.routers.%s.", svcType, routerName)
for k := range container.Config.Labels {
if strings.HasPrefix(k, svcNeedle) || (routerName != "" && strings.HasPrefix(k, routerNeedle)) {
log.Debug().Msgf("found container '%s' (%s) for service '%s'", container.Name, container.ID, svcName)
return container, nil
}
}
}
return container.InspectResponse{}, errors.Errorf("service label not found for %s/%s", svcType, svcName)
}
// Check if the port is explicitly set via label
func isPortSet(container container.InspectResponse, svcType string, svcName string) string {
svcName = stripDocker(svcName)
needle := fmt.Sprintf("traefik.%s.services.%s.loadbalancer.server.port", svcType, svcName)
return container.Config.Labels[needle]
}
// getPortBinding checks the docker container config for a port binding for the
// service. Currently this will only work if a single port is mapped/exposed.
//
// i.e., it looks for the following from a docker-compose service:
//
// ports:
// - 5555:5555
//
// If more than one port is bound (e.g., for a service like minio), then this
// detection will fail. Instead, the user should explicitly set the port in the
// label.
func getPortBinding(container container.InspectResponse) (string, error) {
log.Debug().Msg("looking for port in host config bindings")
numBindings := len(container.HostConfig.PortBindings)
log.Debug().Msgf("found %d host-port bindings", numBindings)
if numBindings > 1 {
return "", errors.Errorf("found more than one host-port binding for container '%s' (%s)", container.Name, portBindingString(container.HostConfig.PortBindings))
}
for _, v := range container.HostConfig.PortBindings {
if len(v) > 1 {
return "", errors.Errorf("found more than one host-port binding for container '%s' (%s)", container.Name, portBindingString(container.HostConfig.PortBindings))
}
if v[0].HostPort != "" {
log.Debug().Msgf("found host-port binding %s", v[0].HostPort)
return v[0].HostPort, nil
}
}
// check for a randomly set port via --publish-all
if container.NetworkSettings != nil && len(container.NetworkSettings.Ports) == 1 {
log.Debug().Msg("looking for [randomly set] port in network settings")
for _, v := range container.NetworkSettings.Ports {
if len(v) > 0 {
port := v[0].HostPort
if port != "" {
if len(v) > 1 {
log.Warn().Msgf("found %d port(s); trying the first one", len(v))
}
return port, nil
}
}
}
} else {
log.Debug().Msg("skipping network settings check, no ports found")
}
return "", errors.Errorf("no host-port binding found for container '%s'", container.Name)
}
func logJSON(name string, v interface{}) {
log.Debug().Func(func(e *zerolog.Event) {
data, err := json.MarshalIndent(v, "", " ")
if err != nil {
e.Msgf("failed to marshal: %s", err)
} else {
e.Msgf("json dump of %s", name)
fmt.Println(string(data))
}
})
}
// Convert host:container port binding map to a compact printable string
func portBindingString(bindings nat.PortMap) string {
s := []string{}
for k, v := range bindings {
if len(v) > 0 {
containerPort := strings.TrimSuffix(string(k), "/tcp")
containerPort = strings.TrimSuffix(string(containerPort), "/udp")
s = append(s, fmt.Sprintf("%s:%s", v[0].HostPort, containerPort))
}
}
return strings.Join(s, ", ")
}
// stripDocker removes the @docker suffix from a service name.
// This is used to normalize service names when storing or retrieving them from the store.
func stripDocker(svcName string) string {
return strings.TrimSuffix(svcName, "@docker")
}
================================================
FILE: docker_helpers_test.go
================================================
package traefikkop
import (
"context"
"fmt"
"io"
"log"
"net"
"os"
"path"
"sort"
"sync"
"testing"
"github.com/docker/cli/cli/compose/loader"
compose "github.com/docker/cli/cli/compose/types"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/go-connections/nat"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/ryanuber/go-glob"
"github.com/stretchr/testify/assert"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/safe"
"github.com/traefik/traefik/v3/pkg/server"
)
type testStore struct {
kv map[string]interface{}
}
func (s testStore) Ping() error {
return nil
}
// Add a method to push the last configuration if needed
func (s *testStore) KeepConfAlive() error {
return nil
}
func (s *testStore) Get(key string) (string, error) {
if s.kv == nil {
return "", nil
}
val, ok := s.kv[key]
if !ok {
return "", nil
}
if val == nil {
return "", nil
}
strVal, ok := val.(string)
if !ok {
return fmt.Sprintf("%s", val), nil
}
return strVal, nil
}
func (s *testStore) Gets(key string) (map[string]string, error) {
if s.kv == nil {
return nil, nil
}
vals := make(map[string]string)
for k, _ := range s.kv {
if glob.Glob(key, k) {
vals[k], _ = s.Get(k)
}
}
return vals, nil
}
func (s *testStore) Store(conf dynamic.Configuration) error {
kv, err := ConfigToKV(conf)
if err != nil {
return err
}
if s.kv == nil {
s.kv = kv
} else {
// merge kv into s.kv
for k, v := range kv {
s.kv[k] = v
}
}
return nil
}
type DockerAPIStub struct {
containers []container.Summary
containersJSON map[string]container.InspectResponse
}
func (d DockerAPIStub) ServerVersion(ctx context.Context) (types.Version, error) {
// Return a version that's compatible with both old and new Docker clients
return types.Version{
Version: "29.0.0",
APIVersion: "1.45", // Compatible with Docker CE 29.0.0 and API negotiation
}, nil
}
func (d DockerAPIStub) Events(ctx context.Context, options events.ListOptions) (<-chan events.Message, <-chan error) {
// Implement your logic here
fmt.Println("Events")
return nil, nil
}
func (d DockerAPIStub) ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) {
// Implement your logic here
fmt.Println("ContainerList")
return d.containers, nil
}
func (d DockerAPIStub) ContainerInspect(ctx context.Context, containerID string) (container.InspectResponse, error) {
// Implement your logic here
fmt.Println("ContainerInspect", containerID)
return d.containersJSON[containerID], nil
}
func (d DockerAPIStub) ServiceList(ctx context.Context, options swarm.ServiceListOptions) ([]swarm.Service, error) {
// Implement your logic here
fmt.Println("ServiceList")
return nil, nil
}
func (d DockerAPIStub) NetworkList(ctx context.Context, options network.ListOptions) ([]network.Summary, error) {
// Implement your logic here
fmt.Println("NetworkList")
return nil, nil
}
func createHTTPServer() (*fiber.App, string) {
app := fiber.New()
app.Use(logger.New())
app.Get("/v*/version", func(c *fiber.Ctx) error {
version, err := dockerAPI.ServerVersion(c.Context())
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(version)
})
app.Get("/v*/containers/json", func(c *fiber.Ctx) error {
containers, err := dockerAPI.ContainerList(c.Context(), container.ListOptions{})
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(containers)
})
app.Get("/v*/containers/:id/json", func(c *fiber.Ctx) error {
container, err := dockerAPI.ContainerInspect(c.Context(), c.Params("id"))
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
// fmt.Printf("returning container: %+v\n", container)
// print container as json
// json.NewEncoder((os.Stdout)).Encode(container)
return c.JSON(container)
})
app.Get("/v*/events", func(c *fiber.Ctx) error {
return nil
})
listener, err := getAvailablePort()
if err != nil {
log.Fatal(err)
}
go app.Listener(listener)
dockerEndpoint := fmt.Sprintf("http://localhost:%d", listener.Addr().(*net.TCPAddr).Port)
return app, dockerEndpoint
}
func buildConfigDetails(source map[string]any, env map[string]string) compose.ConfigDetails {
workingDir, err := os.Getwd()
if err != nil {
panic(err)
}
return compose.ConfigDetails{
WorkingDir: workingDir,
ConfigFiles: []compose.ConfigFile{
{Filename: "filename.yml", Config: source},
},
Environment: env,
}
}
func loadYAML(yaml []byte) (*compose.Config, error) {
return loadYAMLWithEnv(yaml, nil)
}
func loadYAMLWithEnv(yaml []byte, env map[string]string) (*compose.Config, error) {
dict, err := loader.ParseYAML(yaml)
if err != nil {
return nil, err
}
return loader.Load(buildConfigDetails(dict, env))
}
// convert compose services to containers
func createContainers(composeConfig *compose.Config) []container.Summary {
containers := make([]container.Summary, 0)
for _, service := range composeConfig.Services {
container := container.Summary{
ID: service.Name,
Labels: service.Labels,
State: "running",
Status: "running",
}
// convert ports
ports := make([]types.Port, 0)
for _, port := range service.Ports {
ports = append(ports, types.Port{
IP: "172.18.0.2",
PrivatePort: uint16(port.Target),
PublicPort: uint16(port.Published),
Type: port.Protocol,
})
}
container.Ports = ports
containers = append(containers, container)
}
return containers
}
// convert compose services to containersJSON
func createContainersJSON(composeConfig *compose.Config) map[string]container.InspectResponse {
containersJSON := make(map[string]container.InspectResponse)
for _, service := range composeConfig.Services {
containerJSON := container.InspectResponse{
ContainerJSONBase: &types.ContainerJSONBase{
ID: service.Name,
Name: service.Name,
State: &types.ContainerState{
Status: "running",
Running: true,
},
HostConfig: &container.HostConfig{
NetworkMode: "testing_default", // network name
PortBindings: nat.PortMap{},
},
},
Config: &container.Config{
Labels: service.Labels,
},
NetworkSettings: &types.NetworkSettings{
Networks: map[string]*network.EndpointSettings{
"testing_default": {
NetworkID: "testing_default", // should normally look like a random id but we can reuse the name here
IPAddress: "172.18.0.2",
},
"foobar": {
NetworkID: "foobar",
IPAddress: "10.10.10.5",
},
},
},
}
// add port bindings
for _, port := range service.Ports {
portID := nat.Port(fmt.Sprintf("%d/%s", port.Published, port.Protocol))
containerJSON.HostConfig.PortBindings[portID] = []nat.PortBinding{
{
HostIP: "",
HostPort: fmt.Sprintf("%d", port.Published),
},
}
}
containerJSON.NetworkSettings.Ports = containerJSON.HostConfig.PortBindings
for portID, mappings := range containerJSON.NetworkSettings.Ports {
for i, mapping := range mappings {
if mapping.HostPort == "0" {
// Emulating random port assignment for testing
containerJSON.NetworkSettings.Ports[portID][i].HostPort = "12345"
}
}
}
containersJSON[service.Name] = containerJSON
}
return containersJSON
}
func processFile(t *testing.T, file ...string) TraefikStore {
store := &testStore{}
for _, f := range file {
processFileWithConfig(t, store, nil, f)
}
return store
}
func processFileWithConfig(t *testing.T, store TraefikStore, config *Config, file string) TraefikStore {
p := path.Join("fixtures", file)
f, err := os.Open(p)
assert.NoError(t, err)
if err != nil {
t.FailNow()
}
b, err := io.ReadAll(f)
assert.NoError(t, err)
composeConfig, err := loadYAML(b)
assert.NoError(t, err)
if store == nil {
store = &testStore{}
}
// fmt.Printf("%+v\n", composeConfig)
dockerAPI.containers = createContainers(composeConfig)
dockerAPI.containersJSON = createContainersJSON(composeConfig)
if config == nil {
config = &Config{
BindIP: "192.168.100.100",
}
} else {
config.BindIP = "192.168.100.100"
}
if config.DockerHost == "" {
config.DockerHost = dockerEndpoint
}
dp := newDockerProvider(*config)
handleConfigChange := createConfigHandler(*config, store, dp, dc)
routinesPool := safe.NewPool(context.Background())
watcher := server.NewConfigurationWatcher(
routinesPool,
dp,
[]string{},
"docker",
)
watcher.AddListener(handleConfigChange)
// ensure we get exactly one change
wgChanges := sync.WaitGroup{}
wgChanges.Add(1)
watcher.AddListener(func(c dynamic.Configuration) {
wgChanges.Done()
})
watcher.Start()
defer watcher.Stop()
wgChanges.Wait()
if ts, ok := store.(*testStore); ok {
// print the kv store with sorted keys
fmt.Println("printing kv store after processing file:", file)
keys := make([]string, 0, len(ts.kv))
for k := range ts.kv {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Printf("%s: %+v\n", k, ts.kv[k])
}
}
return store
}
func assertServiceIP(t *testing.T, store *testStore, serviceName string, ip string) {
assert.Equal(t, ip, store.kv[fmt.Sprintf("traefik/http/services/%s/loadBalancer/servers/0/url", serviceName)])
}
type svc struct {
name string
proto string
ip string
}
func assertServiceIPs(t *testing.T, store TraefikStore, svcs []svc) {
for _, svc := range svcs {
path := "url"
if svc.proto != "http" {
path = "address"
}
key := fmt.Sprintf("traefik/%s/services/%s/loadBalancer/servers/0/%s", svc.proto, svc.name, path)
val, err := store.Get(key)
assert.NoError(t, err)
assert.Equal(t,
svc.ip,
val,
"service %s has wrong IP at key: %s",
svc,
key,
)
}
}
================================================
FILE: docker_proxy.go
================================================
package traefikkop
import (
"bufio"
"context"
"encoding/json"
"fmt"
"net"
"os"
"strings"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/client"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/rs/zerolog/log"
"github.com/valyala/fasthttp"
)
func getAvailablePort() (net.Listener, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return nil, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return nil, err
}
return l, nil
}
// DockerProxyServer is a proxy server that filters docker labels based on a prefix
type DockerProxyServer struct {
upstream client.APIClient
labelPrefix string
}
func createProxy(upstream client.APIClient, labelPrefix string) *DockerProxyServer {
if labelPrefix != "" && !strings.HasSuffix(labelPrefix, ".") {
labelPrefix += "."
}
return &DockerProxyServer{
upstream: upstream,
labelPrefix: labelPrefix,
}
}
func (s *DockerProxyServer) filterLabels(labels map[string]string) map[string]string {
if s.labelPrefix == "" || labels == nil {
return labels
}
newLabels := make(map[string]string)
for k, v := range labels {
if strings.HasPrefix(k, s.labelPrefix) {
// strip prefix from our labels
newKey := strings.TrimPrefix(k, s.labelPrefix)
newLabels[newKey] = v
} else if !strings.HasPrefix(k, "traefik.") {
// keep every other than traefik.* labels as is
newLabels[k] = v
}
}
return newLabels
}
func (s *DockerProxyServer) handleVersion(c *fiber.Ctx) error {
v, err := s.upstream.ServerVersion(context.Background())
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(v)
}
func (s *DockerProxyServer) handleContainersList(c *fiber.Ctx) error {
containers, err := s.upstream.ContainerList(context.Background(), container.ListOptions{})
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
// modify labels
for _, container := range containers {
container.Labels = s.filterLabels(container.Labels)
}
return c.JSON(containers)
}
func (s *DockerProxyServer) handleContainerInspect(c *fiber.Ctx) error {
container, err := s.upstream.ContainerInspect(context.Background(), c.Params("id"))
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
if container.Config != nil {
container.Config.Labels = s.filterLabels(container.Config.Labels)
}
return c.JSON(container)
}
func (s *DockerProxyServer) handleEvents(c *fiber.Ctx) error {
var fa filters.Args
f := c.Query("filters")
if f != "" {
var err error
fa, err = filters.FromJSON(f)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
}
}
eventsCh, errCh := s.upstream.Events(context.Background(), events.ListOptions{Filters: fa})
c.Status(fiber.StatusOK).Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
encoder := json.NewEncoder(w)
for {
select {
case event := <-eventsCh:
if event.Type == "container" && event.Actor.Attributes != nil {
event.Actor.Attributes = s.filterLabels(event.Actor.Attributes)
}
err := encoder.Encode(event)
if err != nil {
log.Error().Msgf("Error encoding event: %v", err)
}
case err := <-errCh:
if err != nil {
e := encoder.Encode(err)
if e != nil {
log.Error().Msgf("Error encoding error: %v", e)
}
return
}
}
err := w.Flush()
if err != nil {
break
}
}
}))
return nil
}
func (s *DockerProxyServer) handleNotFound(c *fiber.Ctx) error {
log.Warn().Msgf("Unhandled request: %s %s", c.Method(), c.OriginalURL())
return c.Status(fiber.StatusNotFound).SendString("Not Found")
}
func (s *DockerProxyServer) start() (*fiber.App, string) {
app := fiber.New(fiber.Config{DisableStartupMessage: true})
if os.Getenv("DEBUG") != "" {
app.Use(logger.New())
}
app.All("/_ping", func(ctx *fiber.Ctx) error { return ctx.SendStatus(fiber.StatusNoContent) })
app.Get("/v*/version", s.handleVersion)
app.Get("/v*/containers/json", s.handleContainersList)
app.Get("/v*/containers/:id/json", s.handleContainerInspect)
app.Get("/v*/events", s.handleEvents)
app.All("/*", s.handleNotFound)
listener, err := getAvailablePort()
if err != nil {
log.Fatal().Err(err)
}
go app.Listener(listener)
dockerEndpoint := fmt.Sprintf("http://localhost:%d", listener.Addr().(*net.TCPAddr).Port)
log.Debug().Msgf("Started docker proxy at %s with label prefix '%s'", dockerEndpoint, s.labelPrefix)
return app, dockerEndpoint
}
================================================
FILE: docker_proxy_test.go
================================================
package traefikkop
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_dockerProxyServerNoPrefix(t *testing.T) {
mockDockerEndpoint := dockerEndpoint
mockDockerClient := dc
// now create our proxy pointing to the mock
proxyServer := createProxy(mockDockerClient, "")
_, proxyDockerEndpoint := proxyServer.start()
var err error
dockerEndpoint = proxyDockerEndpoint
dc, err = createDockerClient(proxyDockerEndpoint)
assert.NoError(t, err, "should create docker client")
defer func() {
dockerEndpoint = mockDockerEndpoint
dc = mockDockerClient
}()
// both services get mapped to the same port (error case)
store := processFile(t, "hellodetect.yml")
processFileWithConfig(t, store, nil, "docker-prefix.yml")
assertServiceIPs(t, store, []svc{
{"hello-detect", "http", "http://192.168.100.100:5577"},
{"hello-detect2", "http", "http://192.168.100.100:5577"},
})
assert.NotEmpty(t, g(store, fmt.Sprintf("traefik/http/routers/%s/service", "hello-detect2")))
assert.Empty(t, g(store, fmt.Sprintf("traefik/http/routers/%s/service", "prefixed")))
}
func Test_dockerProxyServerPrefix(t *testing.T) {
mockDockerEndpoint := dockerEndpoint
mockDockerClient := dc
// now create our proxy pointing to the mock
proxyServer := createProxy(mockDockerClient, "foo")
_, proxyDockerEndpoint := proxyServer.start()
var err error
dockerEndpoint = proxyDockerEndpoint
dc, err = createDockerClient(proxyDockerEndpoint)
assert.NoError(t, err, "should create docker client")
defer func() {
dockerEndpoint = mockDockerEndpoint
dc = mockDockerClient
}()
// both services get mapped to the same port (error case)
store := processFile(t, "hellodetect.yml")
processFileWithConfig(t, store, nil, "docker-prefix.yml")
assertServiceIPs(t, store, []svc{
{"prefixed", "http", "http://192.168.100.100:5588"},
})
assert.Empty(t, g(store, fmt.Sprintf("traefik/http/routers/%s/service", "hello-detect2")))
assert.NotEmpty(t, g(store, fmt.Sprintf("traefik/http/routers/%s/service", "prefixed")))
}
// test that services with kop.bind.ip or foo.kop.bind.ip labels are handled correctly
func Test_dockerProxyServerPrefixWithKopBindIP(t *testing.T) {
mockDockerEndpoint := dockerEndpoint
mockDockerClient := dc
// now create our proxy pointing to the mock
proxyServer := createProxy(mockDockerClient, "foo")
_, proxyDockerEndpoint := proxyServer.start()
var err error
dockerEndpoint = proxyDockerEndpoint
dc, err = createDockerClient(proxyDockerEndpoint)
assert.NoError(t, err, "should create docker client")
defer func() {
dockerEndpoint = mockDockerEndpoint
dc = mockDockerClient
}()
// both services get mapped to the same port (error case)
store := processFile(t, "hellodetect.yml")
processFileWithConfig(t, store, nil, "prefix-bindip.yml")
assertServiceIPs(t, store, []svc{
{"prefixed", "http", "http://foo.bar.baz:5588"},
{"unprefixed", "http", "http://example.local:5599"},
})
assert.Empty(t, g(store, fmt.Sprintf("traefik/http/routers/%s/service", "hello-detect2")))
assert.NotEmpty(t, g(store, fmt.Sprintf("traefik/http/routers/%s/service", "prefixed")))
}
================================================
FILE: docker_test.go
================================================
package traefikkop
import (
"context"
"log"
"os"
"testing"
"github.com/docker/docker/client"
"github.com/gofiber/fiber/v2"
"github.com/stretchr/testify/assert"
)
var app *fiber.App
var dockerEndpoint string
var dc client.APIClient
var dockerAPI = &DockerAPIStub{}
func setup() {
os.Unsetenv("DOCKER_HOST") // make sure this doesn't interfere with our client setup
app, dockerEndpoint = createHTTPServer()
var err error
dc, err = createDockerClient(dockerEndpoint)
if err != nil {
log.Fatal(err)
}
}
func teardown() {
err := app.Shutdown()
if err != nil {
log.Fatal(err)
}
}
func TestMain(m *testing.M) {
setup()
code := m.Run()
teardown()
os.Exit(code)
}
func Test_httpServerVersion(t *testing.T) {
v, err := dc.ServerVersion(context.Background())
assert.NoError(t, err)
assert.Equal(t, "29.0.0", v.Version)
assert.Equal(t, "1.45", v.APIVersion)
}
func Test_helloWorld(t *testing.T) {
store := processFile(t, "helloworld.yml")
assert.NotNil(t, store)
assert.Equal(t, "hello1", g(store, "traefik/http/routers/hello1/service"))
assert.Equal(t, "hello2", g(store, "traefik/http/routers/hello2/service"))
assert.NotEmpty(t, g(store, "traefik/http/routers/hello1/tls/certResolver"))
assert.NotEmpty(t, g(store, "traefik/http/routers/hello2/tls/certResolver"))
assertServiceIPs(t, store, []svc{
{"hello1", "http", "http://192.168.100.100:5555"},
{"hello2", "http", "http://192.168.100.100:5566"},
})
// assertServiceIP(t, store, "hello1", "http://192.168.100.100:5555")
// assert.Equal(t, "http://192.168.100.100:5555", g(store, "traefik/http/services/hello1/loadBalancer/servers/0/url"))
// assert.Equal(t, "http://192.168.100.100:5566", g(store, "traefik/http/services/hello2/loadBalancer/servers/0/url"))
}
func Test_helloDetect(t *testing.T) {
// both services get mapped to the same port (error case)
store := processFile(t, "hellodetect.yml")
assertServiceIPs(t, store, []svc{
{"hello-detect", "http", "http://192.168.100.100:5577"},
{"hello-detect2", "http", "http://192.168.100.100:5577"},
})
}
func Test_helloIP(t *testing.T) {
// override ip via labels
store := processFile(t, "helloip.yml")
assertServiceIPs(t, store, []svc{
{"helloip", "http", "http://4.4.4.4:5599"},
{"helloip2", "http", "http://3.3.3.3:5599"},
})
}
func Test_helloNetwork(t *testing.T) {
// use ip from specific docker network
store := processFile(t, "network.yml")
assertServiceIPs(t, store, []svc{
{"hello1", "http", "http://10.10.10.5:5555"},
})
}
func Test_TCP(t *testing.T) {
// tcp service
store := processFile(t, "gitea.yml")
assertServiceIPs(t, store, []svc{
{"gitea-ssh", "tcp", "192.168.100.100:20022"},
})
}
func Test_TCPMQTT(t *testing.T) {
// from https://github.com/jittering/traefik-kop/issues/35
store := processFile(t, "mqtt.yml")
assertServiceIPs(t, store, []svc{
{"mqtt", "http", "http://192.168.100.100:9001"},
{"mqtt", "tcp", "192.168.100.100:1883"},
})
}
func Test_helloWorldNoCert(t *testing.T) {
store := processFile(t, "hello-no-cert.yml")
assert.Equal(t, "hello1", g(store, "traefik/http/routers/hello1/service"))
assert.Empty(t, g(store, "traefik/http/routers/hello1/tls/certResolver"))
assertServiceIPs(t, store, []svc{
{"hello1", "http", "http://192.168.100.100:5555"},
})
}
func Test_routerTLSWithoutCertResolver(t *testing.T) {
store := processFile(t, "musicassistant-tls.yml")
assert.Equal(t, "true", g(store, "traefik/http/routers/musicassistant/tls"))
}
func g(s TraefikStore, k string) string {
v, err := s.Get(k)
if err != nil {
return ""
}
return v
}
func Test_helloWorldIgnore(t *testing.T) {
store := processFile(t, "hello-ignore.yml")
assert.Empty(t, g(store, "traefik/http/routers/hello1/service"))
store = processFileWithConfig(t, nil, &Config{Namespace: []string{"foobar"}}, "hello-ignore.yml")
assert.Equal(t, "hello1", g(store, "traefik/http/routers/hello1/service"))
assertServiceIPs(t, store, []svc{
{"hello1", "http", "http://192.168.100.100:5555"},
})
}
func Test_helloWorldMultiNS(t *testing.T) {
store := processFile(t, "hello-multi-ns.yml")
assert.Empty(t, g(store, "traefik/http/routers/hello1/service"))
store = processFileWithConfig(t, nil, &Config{Namespace: []string{"foobar"}}, "hello-multi-ns.yml")
assert.Equal(t, "hello1", g(store, "traefik/http/routers/hello1/service"))
assertServiceIPs(t, store, []svc{
{"hello1", "http", "http://192.168.100.100:5555"},
})
store = processFileWithConfig(t, nil, &Config{Namespace: []string{"xyz"}}, "hello-multi-ns.yml")
assert.Equal(t, "hello1", g(store, "traefik/http/routers/hello1/service"))
assertServiceIPs(t, store, []svc{
{"hello1", "http", "http://192.168.100.100:5555"},
})
store = processFileWithConfig(t, nil, &Config{Namespace: []string{"foobar", "xyz"}}, "hello-multi-ns.yml")
assert.Equal(t, "hello1", g(store, "traefik/http/routers/hello1/service"))
assertServiceIPs(t, store, []svc{
{"hello1", "http", "http://192.168.100.100:5555"},
})
store = processFileWithConfig(t, nil, &Config{Namespace: []string{"abc"}}, "hello-multi-ns.yml")
assert.Empty(t, g(store, "traefik/http/routers/hello1/service"))
}
func Test_helloWorldAutoMapped(t *testing.T) {
store := processFile(t, "hello-automapped.yml")
assert.Equal(t, "hello", g(store, "traefik/http/routers/hello/service"))
assertServiceIPs(t, store, []svc{
{"hello", "http", "http://192.168.100.100:12345"},
})
}
func Test_samePrefix(t *testing.T) {
store := processFile(t, "prefix.yml")
// Two services `hello` and `hello-test`.
// The former's name is a prefix of the latter. Ensure the matching does not mix them up.
assertServiceIPs(t, store, []svc{
{"hello", "http", "http://192.168.100.100:5555"},
{"hello-test", "http", "http://192.168.100.100:5566"},
})
}
// Should be able to merge loadbalanced services
func Test_loadbalance(t *testing.T) {
store := processFile(t, "loadbalance1.yml", "loadbalance2.yml")
url1 := g(store, "traefik/http/services/lbtest/loadBalancer/servers/0/url")
url2 := g(store, "traefik/http/services/lbtest/loadBalancer/servers/1/url")
assert.NotEmpty(t, url1)
assert.NotEmpty(t, url2)
urls := []string{url1, url2}
assert.Contains(t, urls, "http://192.168.100.100:5555")
assert.Contains(t, urls, "http://192.168.100.100:5556")
}
================================================
FILE: fixtures/docker-prefix.yml
================================================
services:
# test labels with a prefix, i.e., DOCKER_PREFIX=foo.
dockerprefix:
restart: unless-stopped
ports:
- 5588:5588
labels:
- "foo.traefik.enable=true"
- "foo.traefik.http.routers.prefixed.rule=Host(`hello-prefix.local`)"
- "foo.traefik.http.routers.prefixed.service=prefixed"
- "foo.traefik.http.routers.prefixed.tls=true"
- "foo.traefik.http.routers.prefixed.tls.certresolver=default"
- "foo.traefik.http.services.prefixed.loadbalancer.server.scheme=http"
================================================
FILE: fixtures/gitea.yml
================================================
services:
gitea:
image: gitea/gitea
labels:
traefik.enable: "true"
traefik.http.routers.gitea.rule: "Host(`git.domain`)"
traefik.http.routers.gitea.entrypoints: webs
traefik.http.routers.gitea.service: gitea@redis
traefik.http.services.gitea.loadbalancer.server.port: 20080
traefik.tcp.routers.gitea-ssh.rule: "HostSNI(`*`)"
traefik.tcp.routers.gitea-ssh.entrypoints: ssh
traefik.tcp.routers.gitea-ssh.service: gitea-ssh@redis
traefik.tcp.services.gitea-ssh.loadbalancer.server.port: 20022
================================================
FILE: fixtures/hello-automapped.yml
================================================
services:
hello:
image: helloworld
restart: unless-stopped
ports:
- 5555
labels:
- "traefik.enable=true"
- "traefik.http.routers.hello.rule=Host(`hello.local`)"
- "traefik.http.routers.hello.service=hello"
- "traefik.http.routers.hello.tls=true"
- "traefik.http.routers.hello.tls.certresolver=default"
================================================
FILE: fixtures/hello-ignore.yml
================================================
services:
helloworld:
image: helloworld
restart: unless-stopped
ports:
- 5555:5555
- 5566:5566
labels:
- "kop.namespace=foobar"
- "traefik.enable=true"
- "traefik.http.routers.hello1.rule=Host(`hello1.local`)"
- "traefik.http.routers.hello1.service=hello1"
- "traefik.http.routers.hello1.tls=true"
- "traefik.http.routers.hello1.tls.certresolver=default"
- "traefik.http.services.hello1.loadbalancer.server.scheme=http"
- "traefik.http.services.hello1.loadbalancer.server.port=5555"
================================================
FILE: fixtures/hello-multi-ns.yml
================================================
services:
helloworld:
image: helloworld
restart: unless-stopped
ports:
- 5555:5555
- 5566:5566
labels:
- "kop.namespace=foobar,xyz"
- "traefik.enable=true"
- "traefik.http.routers.hello1.rule=Host(`hello1.local`)"
- "traefik.http.routers.hello1.service=hello1"
- "traefik.http.routers.hello1.tls=true"
- "traefik.http.routers.hello1.tls.certresolver=default"
- "traefik.http.services.hello1.loadbalancer.server.scheme=http"
- "traefik.http.services.hello1.loadbalancer.server.port=5555"
================================================
FILE: fixtures/hello-no-cert.yml
================================================
services:
helloworld:
image: helloworld
restart: unless-stopped
ports:
- 5555:5555
- 5566:5566
labels:
- "traefik.enable=true"
- "traefik.http.routers.hello1.rule=Host(`hello1.local`)"
- "traefik.http.routers.hello1.service=hello1"
- "traefik.http.routers.hello1.tls=true"
# - "traefik.http.routers.hello1.tls.certresolver=default"
- "traefik.http.services.hello1.loadbalancer.server.scheme=http"
- "traefik.http.services.hello1.loadbalancer.server.port=5555"
================================================
FILE: fixtures/hellodetect.yml
================================================
services:
# This service is the same as above except that it does not have a label
# which explicitly maps the port and so it fails to correctly determine which
# port to tell traefik to connect to. i.e., both services connect to 5555.
#
# This scenario will *not* be handled correctly by traefik-kop as we have no
# fallback way to determine the port.
hellodetect:
build:
dockerfile: ./helloworld/Dockerfile
context: ./
restart: unless-stopped
ports:
- 5577:5555
- 5588:5566
labels:
- "traefik.enable=true"
- "traefik.http.routers.hello-detect.rule=Host(`hello-detect.local`)"
- "traefik.http.routers.hello-detect.service=hello-detect"
- "traefik.http.routers.hello-detect.tls=true"
- "traefik.http.routers.hello-detect.tls.certresolver=default"
- "traefik.http.services.hello-detect.loadbalancer.server.scheme=http"
- "traefik.http.routers.hello-detect2.rule=Host(`hello-detect2.local`)"
- "traefik.http.routers.hello-detect2.service=hello-detect2"
- "traefik.http.routers.hello-detect2.tls=true"
- "traefik.http.routers.hello-detect2.tls.certresolver=default"
- "traefik.http.services.hello-detect2.loadbalancer.server.scheme=http"
================================================
FILE: fixtures/helloip.yml
================================================
services:
helloip:
build:
dockerfile: ./helloworld/Dockerfile
context: ./
restart: unless-stopped
ports:
- 5599:5555
labels:
# override ip for a specific service (helloip)
- "kop.helloip.bind.ip=4.4.4.4"
- "traefik.enable=true"
- "traefik.http.routers.helloip.rule=Host(`helloip.local`)"
- "traefik.http.routers.helloip.service=helloip"
- "traefik.http.routers.helloip.tls=true"
- "traefik.http.routers.helloip.tls.certresolver=default"
- "traefik.http.services.helloip.loadbalancer.server.scheme=http"
- "traefik.http.services.helloip.loadbalancer.server.port=5599"
helloip2:
build:
dockerfile: ./helloworld/Dockerfile
context: ./
restart: unless-stopped
ports:
- 5599:5555
labels:
# override without service name (assumes single service or same ip for all services)
- "kop.bind.ip=3.3.3.3"
- "traefik.enable=true"
- "traefik.http.routers.helloip2.rule=Host(`helloip2.local`)"
- "traefik.http.routers.helloip2.service=helloip2"
- "traefik.http.routers.helloip2.tls=true"
- "traefik.http.routers.helloip2.tls.certresolver=default"
- "traefik.http.services.helloip2.loadbalancer.server.scheme=http"
- "traefik.http.services.helloip2.loadbalancer.server.port=5599"
================================================
FILE: fixtures/helloworld.yml
================================================
services:
helloworld:
image: helloworld
restart: unless-stopped
ports:
- 5555:5555
- 5566:5566
labels:
- "traefik.enable=true"
- "traefik.http.routers.hello1.rule=Host(`hello1.local`)"
- "traefik.http.routers.hello1.service=hello1"
- "traefik.http.routers.hello1.tls=true"
- "traefik.http.routers.hello1.tls.certresolver=default"
- "traefik.http.services.hello1.loadbalancer.server.scheme=http"
- "traefik.http.services.hello1.loadbalancer.server.port=5555"
- "traefik.http.routers.hello2.rule=Host(`hello2.local`)"
- "traefik.http.routers.hello2.service=hello2"
- "traefik.http.routers.hello2.tls=true"
- "traefik.http.routers.hello2.tls.certresolver=default"
- "traefik.http.services.hello2.loadbalancer.server.scheme=http"
- "traefik.http.services.hello2.loadbalancer.server.port=5566"
================================================
FILE: fixtures/loadbalance1.yml
================================================
services:
lb1:
image: helloworld
build: "../helloworld"
restart: "no"
labels:
- "traefik.enable=true"
- "traefik.http.routers.lb1.rule=Host(`lb.local`)"
- "traefik.http.routers.lb1.service=lbtest"
- "traefik.http.routers.lb1.tls=true"
- "traefik.http.routers.lb1.tls.certresolver=default"
- "traefik.http.services.lbtest.loadbalancer.server.scheme=http"
- "traefik.http.services.lbtest.loadbalancer.server.port=5555"
- "traefik.merge-lbs=true"
================================================
FILE: fixtures/loadbalance2.yml
================================================
services:
lb2:
image: helloworld
build: "../helloworld"
restart: "no"
labels:
- "traefik.enable=true"
- "traefik.http.routers.lb1.rule=Host(`lb.local`)"
- "traefik.http.routers.lb1.service=lbtest"
- "traefik.http.routers.lb1.tls=true"
- "traefik.http.routers.lb1.tls.certresolver=default"
- "traefik.http.services.lbtest.loadbalancer.server.scheme=http"
- "traefik.http.services.lbtest.loadbalancer.server.port=5556"
- "traefik.merge-lbs=true"
================================================
FILE: fixtures/mqtt.yml
================================================
services:
gitea:
image: gitea/gitea
labels:
- "traefik.enable=true"
- "traefik.http.routers.mqtt.rule=Host(`mqtt.local`)"
- "traefik.http.services.mqtt.loadbalancer.server.port=9001"
# MQTT routing
- "traefik.tcp.routers.mqtt.rule=HostSNI(`*`)"
- "traefik.tcp.routers.mqtt.entrypoints=mqtt"
- "traefik.tcp.routers.mqtt.service=service-broker-mqtt"
- "traefik.tcp.services.mqtt.loadbalancer.server.port=1883"
================================================
FILE: fixtures/musicassistant-tls.yml
================================================
services:
musicassistant:
image: helloworld
restart: unless-stopped
ports:
- 5555:5555
labels:
- "traefik.enable=true"
- "traefik.http.routers.musicassistant.rule=Host(`musicassistant.example.com`)"
- "traefik.http.routers.musicassistant.entrypoints=websecure"
- "traefik.http.routers.musicassistant.tls=true"
================================================
FILE: fixtures/network.yml
================================================
services:
helloworld:
image: helloworld
restart: unless-stopped
ports:
- 5555:5555
- 5566:5566
labels:
- "traefik.enable=true"
- "traefik.docker.network=foobar"
- "traefik.http.routers.hello1.rule=Host(`hello1.local`)"
- "traefik.http.routers.hello1.service=hello1"
- "traefik.http.routers.hello1.tls=true"
- "traefik.http.routers.hello1.tls.certresolver=default"
- "traefik.http.services.hello1.loadbalancer.server.scheme=http"
- "traefik.http.services.hello1.loadbalancer.server.port=5555"
================================================
FILE: fixtures/prefix-bindip.yml
================================================
services:
# test labels with a prefix, i.e., DOCKER_PREFIX=foo.
dockerprefix:
image: nginx
restart: "no"
ports:
- 5588:80
labels:
- "foo.traefik.enable=true"
- "foo.traefik.http.routers.prefixed.rule=Host(`hello-prefix.local`)"
- "foo.traefik.http.routers.prefixed.service=prefixed"
- "foo.traefik.http.routers.prefixed.tls=true"
- "foo.traefik.http.routers.prefixed.tls.certresolver=default"
- "foo.traefik.http.services.prefixed.loadbalancer.server.scheme=http"
- "foo.kop.bind.ip=foo.bar.baz"
dockerprefix2:
image: nginx
restart: "no"
ports:
- 5599:80
labels:
- "foo.traefik.enable=true"
- "foo.traefik.http.routers.unprefixed.rule=Host(`hello-prefix2.local`)"
- "foo.traefik.http.routers.unprefixed.service=unprefixed"
- "foo.traefik.http.routers.unprefixed.tls=true"
- "foo.traefik.http.routers.unprefixed.tls.certresolver=default"
- "foo.traefik.http.services.unprefixed.loadbalancer.server.scheme=http"
- "kop.bind.ip=example.local"
================================================
FILE: fixtures/prefix.yml
================================================
services:
hello:
image: helloworld
restart: unless-stopped
ports:
- 5555:5555
labels:
- "traefik.enable=true"
- "traefik.http.routers.hello.rule=Host(`hello.local`)"
- "traefik.http.routers.hello.service=hello"
- "traefik.http.routers.hello.tls=true"
- "traefik.http.routers.hello.tls.certresolver=default"
- "traefik.http.services.hello.loadbalancer.server.scheme=http"
- "traefik.http.services.hello.loadbalancer.server.port=5555"
hello-test:
image: helloworld
restart: unless-stopped
ports:
- 5566:5566
labels:
- "traefik.enable=true"
- "traefik.http.routers.hello-test.rule=Host(`hello-test.local`)"
- "traefik.http.routers.hello-test.service=hello-test"
- "traefik.http.routers.hello-test.tls=true"
- "traefik.http.routers.hello-test.tls.certresolver=default"
- "traefik.http.services.hello-test.loadbalancer.server.scheme=http"
- "traefik.http.services.hello-test.loadbalancer.server.port=5566"
================================================
FILE: fixtures/sample.toml
================================================
[global]
checkNewVersion = true
sendAnonymousUsage = true
[serversTransport]
insecureSkipVerify = true
rootCAs = ["foobar", "foobar"]
maxIdleConnsPerHost = 42
[serversTransport.forwardingTimeouts]
dialTimeout = 42
responseHeaderTimeout = 42
idleConnTimeout = 42
[entryPoints]
[entryPoints.EntryPoint0]
address = "foobar"
[entryPoints.EntryPoint0.transport]
[entryPoints.EntryPoint0.transport.lifeCycle]
requestAcceptGraceTimeout = 42
graceTimeOut = 42
[entryPoints.EntryPoint0.transport.respondingTimeouts]
readTimeout = 42
writeTimeout = 42
idleTimeout = 42
[entryPoints.EntryPoint0.proxyProtocol]
insecure = true
trustedIPs = ["foobar", "foobar"]
[entryPoints.EntryPoint0.forwardedHeaders]
insecure = true
trustedIPs = ["foobar", "foobar"]
[providers]
providersThrottleDuration = 42
[providers.docker]
constraints = "foobar"
watch = true
endpoint = "foobar"
defaultRule = "foobar"
exposedByDefault = true
useBindPortIP = true
swarmMode = true
network = "foobar"
swarmModeRefreshSeconds = 42
httpClientTimeout = 42
[providers.docker.tls]
ca = "foobar"
caOptional = true
cert = "foobar"
key = "foobar"
insecureSkipVerify = true
[providers.file]
directory = "foobar"
watch = true
filename = "foobar"
debugLogGeneratedTemplate = true
[providers.marathon]
constraints = "foobar"
trace = true
watch = true
endpoint = "foobar"
defaultRule = "foobar"
exposedByDefault = true
dcosToken = "foobar"
dialerTimeout = 42
responseHeaderTimeout = 42
tlsHandshakeTimeout = 42
keepAlive = 42
forceTaskHostname = true
respectReadinessChecks = true
[providers.marathon.tls]
ca = "foobar"
caOptional = true
cert = "foobar"
key = "foobar"
insecureSkipVerify = true
[providers.marathon.basic]
httpBasicAuthUser = "foobar"
httpBasicPassword = "foobar"
[providers.kubernetesIngress]
endpoint = "foobar"
token = "foobar"
certAuthFilePath = "foobar"
namespaces = ["foobar", "foobar"]
labelSelector = "foobar"
ingressClass = "foobar"
[providers.kubernetesIngress.ingressEndpoint]
ip = "foobar"
hostname = "foobar"
publishedService = "foobar"
[providers.kubernetesCRD]
endpoint = "foobar"
token = "foobar"
certAuthFilePath = "foobar"
namespaces = ["foobar", "foobar"]
labelSelector = "foobar"
ingressClass = "foobar"
[providers.rest]
entryPoint = "foobar"
[providers.rancher]
constraints = "foobar"
watch = true
defaultRule = "foobar"
exposedByDefault = true
enableServiceHealthFilter = true
refreshSeconds = 42
intervalPoll = true
prefix = "foobar"
[api]
entryPoint = "foobar"
dashboard = true
middlewares = ["foobar", "foobar"]
[api.statistics]
recentErrors = 42
[metrics]
[metrics.prometheus]
buckets = [42.0, 42.0]
entryPoint = "foobar"
middlewares = ["foobar", "foobar"]
[metrics.datadog]
address = "foobar"
pushInterval = "10s"
[metrics.statsD]
address = "foobar"
pushInterval = "10s"
[metrics.influxDB]
address = "foobar"
protocol = "foobar"
pushInterval = "10s"
database = "foobar"
retentionPolicy = "foobar"
username = "foobar"
password = "foobar"
[ping]
entryPoint = "foobar"
middlewares = ["foobar", "foobar"]
[log]
level = "foobar"
filePath = "foobar"
format = "foobar"
[accessLog]
filePath = "foobar"
format = "foobar"
bufferingSize = 42
[accessLog.filters]
statusCodes = ["foobar", "foobar"]
retryAttempts = true
minDuration = 42
[accessLog.fields]
defaultMode = "foobar"
[accessLog.fields.names]
name0 = "foobar"
name1 = "foobar"
[accessLog.fields.headers]
defaultMode = "foobar"
[accessLog.fields.headers.names]
name0 = "foobar"
name1 = "foobar"
[tracing]
serviceName = "foobar"
spanNameLimit = 42
[tracing.jaeger]
samplingServerURL = "foobar"
samplingType = "foobar"
samplingParam = 42.0
localAgentHostPort = "foobar"
gen128Bit = true
propagation = "foobar"
traceContextHeaderName = "foobar"
[tracing.zipkin]
httpEndpoint = "foobar"
sameSpan = true
id128Bit = true
debug = true
sampleRate = 42.0
[tracing.datadog]
localAgentHostPort = "foobar"
globalTag = "foobar"
debug = true
prioritySampling = true
traceIDHeaderName = "foobar"
parentIDHeaderName = "foobar"
samplingPriorityHeaderName = "foobar"
bagagePrefixHeaderName = "foobar"
[tracing.instana]
localAgentHost = "foobar"
localAgentPort = 42
logLevel = "foobar"
[tracing.haystack]
localAgentHost = "foobar"
localAgentPort = 42
globalTag = "foobar"
traceIDHeaderName = "foobar"
parentIDHeaderName = "foobar"
spanIDHeaderName = "foobar"
[hostResolver]
cnameFlattening = true
resolvConfig = "foobar"
resolvDepth = 42
[acme]
email = "foobar"
acmeLogging = true
caServer = "foobar"
storage = "foobar"
entryPoint = "foobar"
keyType = "foobar"
[acme.dnsChallenge]
provider = "foobar"
delayBeforeCheck = 42
resolvers = ["foobar", "foobar"]
disablePropagationCheck = true
[acme.httpChallenge]
entryPoint = "foobar"
[acme.tlsChallenge]
[[acme.domains]]
main = "foobar"
sans = ["foobar", "foobar"]
[[acme.domains]]
main = "foobar"
sans = ["foobar", "foobar"]
## Dynamic configuration
[http]
[http.routers]
[http.routers.Router0]
entryPoints = ["foobar", "foobar"]
middlewares = ["foobar", "foobar"]
service = "foobar"
rule = "foobar"
priority = 42
[http.routers.Router0.tls]
[http.middlewares]
[http.middlewares.Middleware0]
[http.middlewares.Middleware0.addPrefix]
prefix = "foobar"
[http.middlewares.Middleware1]
[http.middlewares.Middleware1.stripPrefix]
prefixes = ["foobar", "foobar"]
[http.middlewares.Middleware10]
[http.middlewares.Middleware10.rateLimit]
average = 42
period = "1s"
burst = 42
[http.middlewares.Middleware10.rateLimit.sourceCriterion]
requestHeaderName = "foobar"
requestHost = true
[http.middlewares.Middleware10.rateLimit.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware11]
[http.middlewares.Middleware11.redirectRegex]
regex = "foobar"
replacement = "foobar"
permanent = true
[http.middlewares.Middleware12]
[http.middlewares.Middleware12.redirectScheme]
scheme = "foobar"
port = "foobar"
permanent = true
[http.middlewares.Middleware13]
[http.middlewares.Middleware13.basicAuth]
users = ["foobar", "foobar"]
usersFile = "foobar"
realm = "foobar"
removeHeader = true
headerField = "foobar"
[http.middlewares.Middleware14]
[http.middlewares.Middleware14.digestAuth]
users = ["foobar", "foobar"]
usersFile = "foobar"
removeHeader = true
realm = "foobar"
headerField = "foobar"
[http.middlewares.Middleware15]
[http.middlewares.Middleware15.forwardAuth]
address = "foobar"
trustForwardHeader = true
authResponseHeaders = ["foobar", "foobar"]
authResponseHeadersRegex = "foobar"
authRequestHeaders = ["foobar", "foobar"]
[http.middlewares.Middleware15.forwardAuth.tls]
ca = "foobar"
caOptional = true
cert = "foobar"
key = "foobar"
insecureSkipVerify = true
[http.middlewares.Middleware16]
[http.middlewares.Middleware16.inFlightReq]
amount = 42
[http.middlewares.Middleware16.inFlightReq.sourceCriterion]
requestHeaderName = "foobar"
requestHost = true
[http.middlewares.Middleware16.inFlightReq.sourceCriterion.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware17]
[http.middlewares.Middleware17.buffering]
maxRequestBodyBytes = 42
memRequestBodyBytes = 42
maxResponseBodyBytes = 42
memResponseBodyBytes = 42
retryExpression = "foobar"
[http.middlewares.Middleware18]
[http.middlewares.Middleware18.circuitBreaker]
expression = "foobar"
[http.middlewares.Middleware19]
[http.middlewares.Middleware19.compress]
[http.middlewares.Middleware2]
[http.middlewares.Middleware2.stripPrefixRegex]
regex = ["foobar", "foobar"]
[http.middlewares.Middleware20]
[http.middlewares.Middleware20.passTLSClientCert]
pem = true
[http.middlewares.Middleware20.passTLSClientCert.info]
notAfter = true
notBefore = true
sans = true
[http.middlewares.Middleware20.passTLSClientCert.info.subject]
country = true
province = true
locality = true
organization = true
organizationalUnit = true
commonName = true
serialNumber = true
domainComponent = true
[http.middlewares.Middleware20.passTLSClientCert.info.issuer]
country = true
province = true
locality = true
organization = true
commonName = true
serialNumber = true
domainComponent = true
[http.middlewares.Middleware21]
[http.middlewares.Middleware21.retry]
regex = 0
[http.middlewares.Middleware3]
[http.middlewares.Middleware3.replacePath]
path = "foobar"
[http.middlewares.Middleware4]
[http.middlewares.Middleware4.replacePathRegex]
regex = "foobar"
replacement = "foobar"
[http.middlewares.Middleware5]
[http.middlewares.Middleware5.chain]
middlewares = ["foobar", "foobar"]
[http.middlewares.Middleware6]
[http.middlewares.Middleware6.ipWhiteList]
sourceRange = ["foobar", "foobar"]
[http.middlewares.Middleware7]
[http.middlewares.Middleware7.ipWhiteList]
[http.middlewares.Middleware7.ipWhiteList.ipStrategy]
depth = 42
excludedIPs = ["foobar", "foobar"]
[http.middlewares.Middleware8]
[http.middlewares.Middleware8.headers]
accessControlAllowCredentials = true
accessControlAllowHeaders = ["foobar", "foobar"]
accessControlAllowMethods = ["foobar", "foobar"]
accessControlAllowOriginList = ["foobar", "foobar"]
accessControlExposeHeaders = ["foobar", "foobar"]
accessControlMaxAge = 42
addVaryHeader = true
allowedHosts = ["foobar", "foobar"]
hostsProxyHeaders = ["foobar", "foobar"]
sslRedirect = true
sslTemporaryRedirect = true
sslHost = "foobar"
sslForceHost = true
stsSeconds = 42
stsIncludeSubdomains = true
stsPreload = true
forceSTSHeader = true
frameDeny = true
customFrameOptionsValue = "foobar"
contentTypeNosniff = true
browserXssFilter = true
customBrowserXSSValue = "foobar"
contentSecurityPolicy = "foobar"
publicKey = "foobar"
referrerPolicy = "foobar"
featurePolicy = "foobar"
isDevelopment = true
[http.middlewares.Middleware8.headers.customRequestHeaders]
name0 = "foobar"
name1 = "foobar"
[http.middlewares.Middleware8.headers.customResponseHeaders]
name0 = "foobar"
name1 = "foobar"
[http.middlewares.Middleware8.headers.sslProxyHeaders]
name0 = "foobar"
name1 = "foobar"
[http.middlewares.Middleware9]
[http.middlewares.Middleware9.errors]
status = ["foobar", "foobar"]
service = "foobar"
query = "foobar"
[http.services]
[http.services.Service0]
[http.services.Service0.loadBalancer]
passHostHeader = true
[http.services.Service0.loadBalancer.sticky.cookie]
name = "foobar"
[[http.services.Service0.loadBalancer.servers]]
url = "foobar"
[[http.services.Service0.loadBalancer.servers]]
url = "foobar"
[http.services.Service0.loadBalancer.healthCheck]
scheme = "foobar"
path = "foobar"
port = 42
interval = "5s"
timeout = "10s"
hostname = "foobar"
[http.services.Service0.loadBalancer.healthCheck.headers]
name0 = "foobar"
name1 = "foobar"
[http.services.Service0.loadBalancer.responseForwarding]
flushInterval = "5s"
[tcp]
[tcp.routers]
[tcp.routers.TCPRouter0]
entryPoints = ["foobar", "foobar"]
service = "foobar"
rule = "foobar"
[tcp.routers.TCPRouter0.tls]
passthrough = true
[tcp.services]
[tcp.services.TCPService0]
[tcp.services.TCPService0.loadBalancer]
[[tcp.services.TCPService0.loadBalancer.servers]]
address = "foobar"
[[tcp.services.TCPService0.loadBalancer.servers]]
address = "foobar"
[tls]
[[tls.Certificates]]
certFile = "foobar"
keyFile = "foobar"
stores = ["foobar", "foobar"]
[[tls.Certificates]]
certFile = "foobar"
keyFile = "foobar"
stores = ["foobar", "foobar"]
[tls.options]
[tls.options.TLS0]
minVersion = "foobar"
cipherSuites = ["foobar", "foobar"]
sniStrict = true
[tls.options.TLS0.clientCA]
files = ["foobar", "foobar"]
optional = true
[tls.options.TLS1]
minVersion = "foobar"
cipherSuites = ["foobar", "foobar"]
sniStrict = true
[tls.options.TLS1.clientCA]
files = ["foobar", "foobar"]
optional = true
[tls.stores]
[tls.stores.Store0]
[tls.stores.Store0.defaultCertificate]
certFile = "foobar"
keyFile = "foobar"
[tls.stores.Store1]
[tls.stores.Store1.defaultCertificate]
certFile = "foobar"
keyFile = "foobar"
================================================
FILE: go.mod
================================================
module github.com/jittering/traefik-kop
go 1.24.0
toolchain go1.24.4
replace (
github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20250523120546-41b6ec3aed59
github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
)
require (
github.com/BurntSushi/toml v1.5.0
github.com/docker/cli v29.0.0+incompatible
github.com/docker/docker v28.5.2+incompatible
github.com/docker/go-connections v0.6.0
github.com/echovault/sugardb v0.17.0
github.com/gofiber/fiber/v2 v2.52.9
github.com/pkg/errors v0.9.1
github.com/redis/go-redis/v9 v9.16.0
github.com/rs/zerolog v1.34.0
github.com/ryanuber/go-glob v1.0.0
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.11.1
github.com/traefik/paerser v0.2.2
github.com/traefik/traefik/v3 v3.6.1
github.com/urfave/cli/v2 v2.27.7
github.com/valyala/fasthttp v1.68.0
golang.org/x/exp v0.0.0-20251017212417-90e834f514db
gopkg.in/yaml.v3 v3.0.1
)
require (
cloud.google.com/go/auth v0.17.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.30 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 // indirect
github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/VividCortex/gohistogram v1.0.0 // indirect
github.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang/v11 v11.1.0 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 // indirect
github.com/alibabacloud-go/debug v1.0.1 // indirect
github.com/alibabacloud-go/tea v1.3.13 // indirect
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect
github.com/aliyun/credentials-go v1.4.7 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/aws/aws-sdk-go-v2 v1.39.4 // indirect
github.com/aws/aws-sdk-go-v2/config v1.31.15 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.18.19 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ec2 v1.203.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ecs v1.53.15 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 // indirect
github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.2 // indirect
github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssm v1.56.13 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.29.8 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 // indirect
github.com/aws/smithy-go v1.23.1 // indirect
github.com/aziontech/azionapi-go-sdk v0.143.0 // indirect
github.com/baidubce/bce-sdk-go v0.9.250 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/boltdb/bolt v1.3.1 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/bytedance/sonic v1.12.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/deepmap/oapi-codegen v1.9.1 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dnsimple/dnsimple-go/v4 v4.0.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/exoscale/egoscale/v3 v3.1.27 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-acme/alidns-20150109/v4 v4.6.1 // indirect
github.com/go-acme/lego/v4 v4.28.0 // indirect
github.com/go-acme/tencentclouddnspod v1.1.10 // indirect
github.com/go-acme/tencentedgdeone v1.1.48 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-kit/kit v0.13.0 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.2 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.23.0 // indirect
github.com/go-resty/resty/v2 v2.16.5 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/go-zookeeper/zk v1.0.3 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/gofrs/flock v0.13.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-github/v28 v28.1.1 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.15.0 // indirect
github.com/gophercloud/gophercloud v1.14.1 // indirect
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
github.com/hashicorp/consul/api v1.26.1 // indirect
github.com/hashicorp/cronexpr v1.1.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-msgpack v0.5.5 // indirect
github.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/hashicorp/memberlist v0.5.1 // indirect
github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b // indirect
github.com/hashicorp/raft v1.7.1 // indirect
github.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702 // indirect
github.com/hashicorp/serf v0.10.1 // indirect
github.com/http-wasm/http-wasm-host-go v0.7.0 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.173 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.7.0 // indirect
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // indirect
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
github.com/infobloxopen/infoblox-go-client/v2 v2.10.0 // indirect
github.com/jonboulle/clockwork v0.5.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/klauspost/compress v1.18.1 // indirect
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
github.com/kvtools/consul v1.0.2 // indirect
github.com/kvtools/etcdv3 v1.0.3 // indirect
github.com/kvtools/redis v1.2.0 // indirect
github.com/kvtools/valkeyrie v1.0.0 // indirect
github.com/kvtools/zookeeper v1.0.2 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
github.com/labbsr0x/goh v1.0.1 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/linode/linodego v1.60.0 // indirect
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect
github.com/mailgun/multibuf v0.1.2 // indirect
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 // indirect
github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/miekg/dns v1.1.68 // indirect
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/hashstructure v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/moby/api v1.52.0 // indirect
github.com/moby/moby/client v0.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/namedotcom/go/v4 v4.0.2 // indirect
github.com/nrdcg/auroradns v1.1.0 // indirect
github.com/nrdcg/bunny-go v0.1.0 // indirect
github.com/nrdcg/desec v0.11.1 // indirect
github.com/nrdcg/dnspod-go v0.4.0 // indirect
github.com/nrdcg/freemyip v0.3.0 // indirect
github.com/nrdcg/goacmedns v0.2.0 // indirect
github.com/nrdcg/goinwx v0.11.0 // indirect
github.com/nrdcg/mailinabox v0.3.0 // indirect
github.com/nrdcg/namesilo v0.5.0 // indirect
github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/oci-go-sdk/common/v1065 v1065.103.0 // indirect
github.com/nrdcg/oci-go-sdk/dns/v1065 v1065.103.0 // indirect
github.com/nrdcg/porkbun v0.4.0 // indirect
github.com/nrdcg/vegadns v0.3.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/ovh/go-ovh v1.9.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/peterhellberg/link v1.2.0 // indirect
github.com/pires/go-proxyproto v0.8.1 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pquerna/otp v1.5.0 // indirect
github.com/prometheus/client_golang v1.23.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.55.0 // indirect
github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/robertkrimen/otto v0.5.1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sacloud/api-client-go v0.3.3 // indirect
github.com/sacloud/go-http v0.1.9 // indirect
github.com/sacloud/iaas-api-go v1.20.0 // indirect
github.com/sacloud/packages-go v0.0.11 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.35 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/selectel/domains-go v1.1.0 // indirect
github.com/selectel/go-selvpcclient/v4 v4.1.0 // indirect
github.com/sethvargo/go-retry v0.3.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.2.1 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/sony/gobreaker v1.0.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/pflag v1.0.7 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
github.com/stealthrocket/wasi-go v0.8.0 // indirect
github.com/stealthrocket/wazergo v0.19.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.48 // indirect
github.com/tetratelabs/wazero v1.8.0 // indirect
github.com/tidwall/resp v0.1.1 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/traefik/grpc-web v0.16.0 // indirect
github.com/traefik/yaegi v0.16.1 // indirect
github.com/transip/gotransip/v6 v6.26.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/ultradns/ultradns-go-sdk v1.8.1-20250722213956-faef419 // indirect
github.com/unrolled/render v1.0.2 // indirect
github.com/unrolled/secure v1.0.9 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
github.com/volcengine/volc-sdk-golang v1.0.224 // indirect
github.com/vulcand/oxy/v2 v2.0.3 // indirect
github.com/vulcand/predicate v1.2.0 // indirect
github.com/vultr/govultr/v3 v3.24.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/yandex-cloud/go-genproto v0.34.0 // indirect
github.com/yandex-cloud/go-sdk/services/dns v0.0.16 // indirect
github.com/yandex-cloud/go-sdk/v2 v2.24.0 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
github.com/yuin/gopher-lua v1.1.1 // indirect
github.com/zeebo/errs v1.4.0 // indirect
go.etcd.io/etcd/api/v3 v3.6.4 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect
go.etcd.io/etcd/client/v3 v3.6.4 // indirect
go.mongodb.org/mongo-driver v1.13.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/bridges/otellogrus v0.13.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/contrib/propagators/autoprop v0.63.0 // indirect
go.opentelemetry.io/contrib/propagators/aws v1.38.0 // indirect
go.opentelemetry.io/contrib/propagators/b3 v1.38.0 // indirect
go.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect
go.opentelemetry.io/contrib/propagators/ot v1.38.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
go.opentelemetry.io/otel/log v0.14.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
go.opentelemetry.io/otel/sdk/log v0.14.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.3.1 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.46.0 // indirect
golang.org/x/oauth2 v0.32.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/sys v0.37.0 // indirect
golang.org/x/term v0.36.0 // indirect
golang.org/x/text v0.30.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.38.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/api v0.254.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/grpc v1.76.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.15.1 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/api v0.34.1 // indirect
k8s.io/apiextensions-apiserver v0.34.1 // indirect
k8s.io/apimachinery v0.34.1 // indirect
k8s.io/client-go v0.34.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 // indirect
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d // indirect
knative.dev/networking v0.0.0-20241022012959-60e29ff520dc // indirect
knative.dev/pkg v0.0.0-20241021183759-9b9d535af5ad // indirect
mvdan.cc/xurls/v2 v2.5.0 // indirect
nhooyr.io/websocket v1.8.7 // indirect
sigs.k8s.io/gateway-api v1.4.0 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
================================================
FILE: go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=
cloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
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=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 h1:Dy3M9aegiI7d7PF1LUdjbVigJReo+QOceYsMyFh9qoE=
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesnDfrtF6RFUGzQfLo=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 h1:5YTBM8QDVIBN3sxBil89WfdAAqDZbyJTgh688DSxX5w=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 h1:KpMC6LFL7mqpExyMC9jVOYRiVhLmamjeZfRsUpB7l4s=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0/go.mod h1:J7MUC/wtRpfGVbQ5sIItY5/FuVWmvzlY21WAOfQnq/I=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0/go.mod h1:AW8VEadnhw9xox+VaVd9sP7NjzOAnaZBLRH6Tq3cJ38=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 h1:yzrctSl9GMIQ5lHu7jc8olOsGjWDCsBpJhWqfGa/YIM=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0/go.mod h1:GE4m0rnnfwLGX0Y9A9A25Zx5N/90jneT5ABevqzhuFQ=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 h1:zLzoX5+W2l95UJoVwiyNS4dX8vHyQ6x2xRLoBBL9wMk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0/go.mod h1:wVEOJfGTj0oPAUGA1JuRAvz/lxXQsWW16axmHPP47Bk=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA=
github.com/Azure/go-autorest/autorest v0.11.30 h1:iaZ1RGz/ALZtN5eq4Nr1SOFSlf2E4pDI3Tcsl+dZPVE=
github.com/Azure/go-autorest/autorest v0.11.30/go.mod h1:t1kpPIOpIVX7annvothKvb0stsrXa37i7b+xpmBW8Fs=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk=
github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8=
github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 h1:Ov8avRZi2vmrE2JcXw+tu5K/yB41r7xK9GZDiBF7NdM=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13/go.mod h1:5BAVfWLWXihP47vYrPuBKKf4cS0bXI+KM9Qx6ETDJYo=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
github.com/Azure/go-autorest/autorest/to v0.4.1 h1:CxNHBqdzTr7rLtdrtb5CMjJcDut+WNGCVv7OmS5+lTc=
github.com/Azure/go-autorest/autorest/to v0.4.1/go.mod h1:EtaofgU4zmtvn1zT2ARsjRFdq9vXx0YWtmElwL+GZ9M=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI=
github.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/sarama v1.30.1/go.mod h1:hGgx05L/DiW8XYBXeJdKIN6V2QUy2H6JqME5VT1NLRw=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0=
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/akamai/AkamaiOPEN-edgegrid-golang/v11 v11.1.0 h1:h/33OxYLqBk0BYmEbSUy7MlvgQR/m1w1/7OJFKoPL1I=
github.com/akamai/AkamaiOPEN-edgegrid-golang/v11 v11.1.0/go.mod h1:rvh3imDA6EaQi+oM/GQHkQAOHbXPKJ7EWJvfjuw141Q=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=
github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=
github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=
github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.12/go.mod h1:f2wDpbM7hK9SvLIH09zSKVU1TsyemUNOqErMscMMl7c=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 h1:Q00FU3H94Ts0ZIHDmY+fYGgB7dV9D/YX6FGsgorQPgw=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13/go.mod h1:lxFGfobinVsQ49ntjpgWghXmIF0/Sm4+wvBJ1h5RtaE=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=
github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=
github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=
github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
github.com/alibabacloud-go/openapi-util v0.1.1 h1:ujGErJjG8ncRW6XtBBMphzHTvCxn4DjrVw4m04HsS28=
github.com/alibabacloud-go/openapi-util v0.1.1/go.mod h1:/UehBSE2cf1gYT43GV4E+RxTdLRzURImCYY0aRmlXpw=
github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
github.com/alibabacloud-go/tea v1.3.12/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
github.com/alibabacloud-go/tea v1.3.13 h1:WhGy6LIXaMbBM6VBYcsDCz6K/TPsT1Ri2hPmmZffZ94=
github.com/alibabacloud-go/tea v1.3.13/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
github.com/aliyun/credentials-go v1.4.7 h1:T17dLqEtPUFvjDRRb5giVvLh6dFT8IcNFJJb7MeyCxw=
github.com/aliyun/credentials-go v1.4.7/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2 v1.39.4 h1:qTsQKcdQPHnfGYBBs+Btl8QwxJeoWcOcPcixK90mRhg=
github.com/aws/aws-sdk-go-v2 v1.39.4/go.mod h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM=
github.com/aws/aws-sdk-go-v2/config v1.31.15 h1:gE3M4xuNXfC/9bG4hyowGm/35uQTi7bUKeYs5e/6uvU=
github.com/aws/aws-sdk-go-v2/config v1.31.15/go.mod h1:HvnvGJoE2I95KAIW8kkWVPJ4XhdrlvwJpV6pEzFQa8o=
github.com/aws/aws-sdk-go-v2/credentials v1.18.19 h1:Jc1zzwkSY1QbkEcLujwqRTXOdvW8ppND3jRBb/VhBQc=
github.com/aws/aws-sdk-go-v2/credentials v1.18.19/go.mod h1:DIfQ9fAk5H0pGtnqfqkbSIzky82qYnGvh06ASQXXg6A=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11 h1:X7X4YKb+c0rkI6d4uJ5tEMxXgCZ+jZ/D6mvkno8c8Uw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11/go.mod h1:EqM6vPZQsZHYvC4Cai35UDg/f5NCEU+vp0WfbVqVcZc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 h1:7AANQZkF3ihM8fbdftpjhken0TP9sBzFbV/Ze/Y4HXA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11/go.mod h1:NTF4QCGkm6fzVwncpkFQqoquQyOolcyXfbpC98urj+c=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 h1:ShdtWUZT37LCAA4Mw2kJAJtzaszfSHFb5n25sdcv4YE=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11/go.mod h1:7bUb2sSr2MZ3M/N+VyETLTQtInemHXb/Fl3s8CLzm0Y=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.203.1 h1:ZgY9zeVAe+54Qa7o1GXKRNTez79lffCeJSSinhl+qec=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.203.1/go.mod h1:0naMk66LtdeTmE+1CWQTKwtzOQ2t8mavOhMhR0Pv1m0=
github.com/aws/aws-sdk-go-v2/service/ecs v1.53.15 h1:uH0DMwDjLGgjjYMk3M1MXHggk37trTiJIvwyJNP17Ig=
github.com/aws/aws-sdk-go-v2/service/ecs v1.53.15/go.mod h1:49tE5yYdlAHqZIO8u5+u9Xy9k8IaV0v5cstZrjnX5+c=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 h1:xtuxji5CS0JknaXoACOunXOYOQzgfTvGAc9s2QdCJA4=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2/go.mod h1:zxwi0DIR0rcRcgdbl7E2MSOvxDyyXGBlScvBkARFaLQ=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 h1:GpMf3z2KJa4RnJ0ew3Hac+hRFYLZ9DDjfgXjuW+pB54=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11/go.mod h1:6MZP3ZI4QQsgUCFTwMZA2V0sEriNQ8k2hmoHF3qjimQ=
github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.2 h1:pr1dQ9vamhAf2mYOgiRRC/w9Ht4POFhy6+xXw7hOqwY=
github.com/aws/aws-sdk-go-v2/service/lightsail v1.50.2/go.mod h1:A4Ch93K7Wam4Qe0Wl0XbPgcgoL5KIJtFIe7wHw6OPWE=
github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1 h1:KuoA/cmy/yK8n9v/d6WH36cZwGxFOrn0TmZ4lNN3MKQ=
github.com/aws/aws-sdk-go-v2/service/route53 v1.59.1/go.mod h1:BymbICXBfXQHO6i+yTBhocA9a6DM0uMDQqYelqa9wzs=
github.com/aws/aws-sdk-go-v2/service/ssm v1.56.13 h1:JfPeW7F6Y+VqBg6p+8zQv4wlgceguYu5ZT0USEGZ89g=
github.com/aws/aws-sdk-go-v2/service/ssm v1.56.13/go.mod h1:EonGQFn66wZkJJrrKXrryrxoS3V30rcHvaWvc6oGHCI=
github.com/aws/aws-sdk-go-v2/service/sso v1.29.8 h1:M5nimZmugcZUO9wG7iVtROxPhiqyZX6ejS1lxlDPbTU=
github.com/aws/aws-sdk-go-v2/service/sso v1.29.8/go.mod h1:mbef/pgKhtKRwrigPPs7SSSKZgytzP8PQ6P6JAAdqyM=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3 h1:S5GuJZpYxE0lKeMHKn+BRTz6PTFpgThyJ+5mYfux7BM=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3/go.mod h1:X4OF+BTd7HIb3L+tc4UlWHVrpgwZZIVENU15pRDVTI0=
github.com/aws/aws-sdk-go-v2/service/sts v1.38.9 h1:Ekml5vGg6sHSZLZJQJagefnVe6PmqC2oiRkBq4F7fU0=
github.com/aws/aws-sdk-go-v2/service/sts v1.38.9/go.mod h1:/e15V+o1zFHWdH3u7lpI3rVBcxszktIKuHKCY2/py+k=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M=
github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/aziontech/azionapi-go-sdk v0.143.0 h1:4eEBlYT10prgeCVTNR9FIc7f59Crbl2zrH1a4D1BUqU=
github.com/aziontech/azionapi-go-sdk v0.143.0/go.mod h1:cA5DY/VP4X5Eu11LpQNzNn83ziKjja7QVMIl4J45feA=
github.com/baidubce/bce-sdk-go v0.9.250 h1:fnvV5clsNCAP6pCauj0eNaUnoLVmjQGnco7rcMqp984=
github.com/baidubce/bce-sdk-go v0.9.250/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bytedance/sonic v1.12.0 h1:YGPgxF9xzaCNvd/ZKdQ28yRovhfMFZQjuk6fKBzZ3ls=
github.com/bytedance/sonic v1.12.0/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd h1:0n+lFLh5zU0l6KSk3KpnDwfbPGAR44aRLgTbCnhRBHU=
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd/go.mod h1:BbQgeDS5i0tNvypwEoF1oNjOJw8knRAE1DnVvjDstcQ=
github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e h1:D+uTEzDZc1Fhmd0Pq06c+O9+KkAyExw0eVmu/NOqaHU=
github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e/go.mod h1:s8kLgBQolDbsJOPVIGCEEv9zGAKUUf/685Gi0Qqg8z8=
github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595 h1:aPspFRO6b94To3gl4yTDOEtpjFwXI7V2W+z0JcNljQ4=
github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595/go.mod h1:+lHFbEasIiQVGzhVDVw/cn0ZaOzde2OwNncp1NhXV4c=
github.com/containous/mux v0.0.0-20250523120546-41b6ec3aed59 h1:lJUOWjGohYjLKEfAz2nyI/dpzfKNPQLi5GLH7aaOZkw=
github.com/containous/mux v0.0.0-20250523120546-41b6ec3aed59/go.mod h1:z8WW7n06n8/1xF9Jl9WmuDeZuHAhfL+bwarNjsciwwg=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
github.com/deepmap/oapi-codegen v1.9.1 h1:yHmEnA7jSTUMQgV+uN02WpZtwHnz2CBW3mZRIxr1vtI=
github.com/deepmap/oapi-codegen v1.9.1/go.mod h1:PLqNAhdedP8ttRpBBkzLKU3bp+Fpy+tTgeAMlztR2cw=
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dnsimple/dnsimple-go/v4 v4.0.0 h1:nUCICZSyZDiiqimAAL+E8XL+0sKGks5VRki5S8XotRo=
github.com/dnsimple/dnsimple-go/v4 v4.0.0/go.mod h1:AXT2yfAFOntJx6iMeo1J/zKBw0ggXFYBt4e97dqqPnc=
github.com/docker/cli v29.0.0+incompatible h1:KgsN2RUFMNM8wChxryicn4p46BdQWpXOA1XLGBGPGAw=
github.com/docker/cli v29.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/echovault/sugardb v0.17.0 h1:do6fmfoDIKjqBAGG4ohQ7C9NcynEHd9cUuqOCZrI4MI=
github.com/echovault/sugardb v0.17.0/go.mod h1:HLaXt8GrOQYsSAdWSiawtf6As3lNDdWKzoBsROIDpyk=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=
github.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=
github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=
github.com/exoscale/egoscale/v3 v3.1.27 h1:vKdWZG8QFDc7rY7lCfcuudO+ovyp5psYjFwKVqmkhCE=
github.com/exoscale/egoscale/v3 v3.1.27/go.mod h1:0iY8OxgHJCS5TKqDNhwOW95JBKCnBZl3YGU4Yt+NqkU=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-acme/alidns-20150109/v4 v4.6.1 h1:Dch3aWRcw4U62+jKPjPQN3iW3TPvgIywATbvHzojXeo=
github.com/go-acme/alidns-20150109/v4 v4.6.1/go.mod h1:RBcqBA5IvUWtlpjx6dC6EkPVyBNLQ+mR18XoaP38BFY=
github.com/go-acme/lego/v4 v4.28.0 h1:URKsCcybo7SjqqZckeBcDN9Vl29/bKS///75tcNkMHQ=
github.com/go-acme/lego/v4 v4.28.0/go.mod h1:bzjilr03IgbaOwlH396hq5W56Bi0/uoRwW/JM8hP7m4=
github.com/go-acme/tencentclouddnspod v1.1.10 h1:ERVJ4mc3cT4Nb3+n6H/c1AwZnChGBqLoymE0NVYscKI=
github.com/go-acme/tencentclouddnspod v1.1.10/go.mod h1:Bo/0YQJ/99FM+44HmCQkByuptX1tJsJ9V14MGV/2Qco=
github.com/go-acme/tencentedgdeone v1.1.48 h1:WLyLBsRVhSLFmtbEFXk0naLODSQn7X6J0Fc/qR8xVUk=
github.com/go-acme/tencentedgdeone v1.1.48/go.mod h1:mu6tA+bPhlSd+CKUfzRikE0mfxmTlBI6dVTn9LY9dRI=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=
github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU=
github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA=
github.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
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/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
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/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA=
github.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-yaml v1.9.8/go.mod h1:JubOolP3gh0HpiBc4BLRD4YmjEjHAmIIB2aaXKkTfoE=
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/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.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=
github.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=
github.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/gophercloud v1.14.1 h1:DTCNaTVGl8/cFu58O1JwWgis9gtISAFONqpMKNg/Vpw=
github.com/gophercloud/gophercloud v1.14.1/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf h1:C1GPyPJrOlJlIrcaBBiBpDsqZena2Ks8spa5xZqr1XQ=
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf/go.mod h1:zXqxTI6jXDdKnlf8s+nT+3c8LrwUEy3yNpO4XJL90lA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
github.com/hashicorp/consul/api v1.26.1 h1:5oSXOO5fboPZeW5SN+TdGFP/BILDgBm19OrPZ/pICIM=
github.com/hashicorp/consul/api v1.26.1/go.mod h1:B4sQTeaSO16NtynqrAdwOlahJ7IUDZM9cj2420xYL8A=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU=
github.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo=
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0=
github.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=
github.com/hashicorp/memberlist v0.5.1 h1:mk5dRuzeDNis2bi6LLoQIXfMH7JQvAzt3mQD0vNZZUo=
github.com/hashicorp/memberlist v0.5.1/go.mod h1:zGDXV6AqbDTKTM6yxW0I4+JtFzZAJVoIPvss4hV8F24=
github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b h1:R1UDhkwGltpSPY9bCBBxIMQd+NY9BkN0vFHnJo/8o8w=
github.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b/go.mod h1:ijDwa6o1uG1jFSq6kERiX2PamKGpZzTmo0XOFNeFZgw=
github.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM=
github.com/hashicorp/raft v1.7.1 h1:ytxsNx4baHsRZrhUcbt3+79zc4ly8qm7pi0393pSchY=
github.com/hashicorp/raft v1.7.1/go.mod h1:hUeiEwQQR/Nk2iKDD0dkEhklSsu3jcAcqvPzPoZSAEM=
github.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702 h1:RLKEcCuKcZ+qp2VlaaZsYZfLOmIiuJNpEi48Rl8u9cQ=
github.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/http-wasm/http-wasm-host-go v0.7.0 h1:+1KrRyOO6tWiDB24QrtSYyDmzFLBBs3jioKaUT0mq1c=
github.com/http-wasm/http-wasm-host-go v0.7.0/go.mod h1:adXKcLmL7yuavH/e0kBAp7b3TgAHTo/enCduyN5bXGM=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.173 h1:Y4ixGadyrK9xHw6Z+cyiiME3SBXepEcUoiT+B8C5FoQ=
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.173/go.mod h1:M+yna96Fx9o5GbIUnF3OvVvQGjgfVSyeJbV9Yb1z/wI=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb-client-go/v2 v2.7.0 h1:QgP5mlBE9sGnzplpnf96pr+p7uqlIlL4W2GAP3n+XZg=
github.com/influxdata/influxdb-client-go/v2 v2.7.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/infobloxopen/infoblox-go-client/v2 v2.10.0 h1:AKsihjFT/t6Y0keEv3p59DACcOuh0inWXdUB0ZOzYH0=
github.com/infobloxopen/infoblox-go-client/v2 v2.10.0/go.mod h1:NeNJpz09efw/edzqkVivGv1bWqBXTomqYBRFbP+XBqg=
github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
github.com/jarcoal/httpmock v1.4.1 h1:0Ju+VCFuARfFlhVXFc2HxlcQkfB+Xq12/EotHko+x2A=
github.com/jarcoal/httpmock v1.4.1/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 h1:9Nu54bhS/H/Kgo2/7xNSUuC5G28VR8ljfrLKU2G4IjU=
github.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12/go.mod h1:TBzl5BIHNXfS9+C35ZyJaklL7mLDbgUkcgXzSLa8Tk0=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress
gitextract_f_8i9uu6/ ├── .dockerignore ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ ├── on_push.yaml │ └── on_tag.yaml ├── .gitignore ├── .goreleaser.yml ├── CHANGELOG.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── bin/ │ └── traefik-kop/ │ └── main.go ├── config.go ├── docker-compose.yml ├── docker.go ├── docker_helpers_test.go ├── docker_proxy.go ├── docker_proxy_test.go ├── docker_test.go ├── fixtures/ │ ├── docker-prefix.yml │ ├── gitea.yml │ ├── hello-automapped.yml │ ├── hello-ignore.yml │ ├── hello-multi-ns.yml │ ├── hello-no-cert.yml │ ├── hellodetect.yml │ ├── helloip.yml │ ├── helloworld.yml │ ├── loadbalance1.yml │ ├── loadbalance2.yml │ ├── mqtt.yml │ ├── musicassistant-tls.yml │ ├── network.yml │ ├── prefix-bindip.yml │ ├── prefix.yml │ └── sample.toml ├── go.mod ├── go.sum ├── kv.go ├── kv_test.go ├── kv_walk_test.go ├── multi_provider.go ├── multi_provider_test.go ├── polling_provider.go ├── polling_provider_test.go ├── store.go ├── store_test.go ├── testing/ │ ├── docker-compose.yml │ ├── helloworld/ │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── go.mod │ │ └── main.go │ ├── internal/ │ │ ├── Makefile │ │ └── docker-compose.yml │ ├── kop/ │ │ └── docker-compose.yml │ └── publish-random.sh ├── traefik_kop.go ├── traefik_kop_test.go └── util.go
SYMBOL INDEX (157 symbols across 20 files)
FILE: bin/traefik-kop/main.go
constant defaultDockerHost (line 16) | defaultDockerHost = "unix:///var/run/docker.sock"
function printVersion (line 25) | func printVersion(c *cli.Context) error {
function flags (line 30) | func flags() {
function setupLogging (line 150) | func setupLogging(debug bool) {
function main (line 166) | func main() {
function splitStringArr (line 170) | func splitStringArr(str string) []string {
function doStart (line 183) | func doStart(c *cli.Context) error {
function getHostname (line 230) | func getHostname() string {
function getDefaultIP (line 238) | func getDefaultIP(iface string) string {
function GetOutboundIP (line 255) | func GetOutboundIP() net.IP {
function GetInterfaceIP (line 269) | func GetInterfaceIP(name string) net.IP {
FILE: config.go
type Config (line 15) | type Config struct
type ConfigFile (line 33) | type ConfigFile struct
function loadDockerConfig (line 37) | func loadDockerConfig(input string) (*docker.Provider, error) {
function looksLikeFile (line 74) | func looksLikeFile(input string) bool {
FILE: docker.go
type dockerCache (line 20) | type dockerCache struct
method populate (line 61) | func (dc *dockerCache) populate() error {
method findContainerByServiceName (line 101) | func (dc *dockerCache) findContainerByServiceName(svcType string, svcN...
constant defaultTimeout (line 29) | defaultTimeout = time.Duration(0)
function createDockerClient (line 31) | func createDockerClient(endpoint string) (client.APIClient, error) {
function getClientOpts (line 49) | func getClientOpts(endpoint string) ([]client.Opt, error) {
function isPortSet (line 126) | func isPortSet(container container.InspectResponse, svcType string, svcN...
function getPortBinding (line 143) | func getPortBinding(container container.InspectResponse) (string, error) {
function logJSON (line 181) | func logJSON(name string, v interface{}) {
function portBindingString (line 194) | func portBindingString(bindings nat.PortMap) string {
function stripDocker (line 208) | func stripDocker(svcName string) string {
FILE: docker_helpers_test.go
type testStore (line 32) | type testStore struct
method Ping (line 36) | func (s testStore) Ping() error {
method KeepConfAlive (line 41) | func (s *testStore) KeepConfAlive() error {
method Get (line 45) | func (s *testStore) Get(key string) (string, error) {
method Gets (line 63) | func (s *testStore) Gets(key string) (map[string]string, error) {
method Store (line 76) | func (s *testStore) Store(conf dynamic.Configuration) error {
type DockerAPIStub (line 94) | type DockerAPIStub struct
method ServerVersion (line 99) | func (d DockerAPIStub) ServerVersion(ctx context.Context) (types.Versi...
method Events (line 107) | func (d DockerAPIStub) Events(ctx context.Context, options events.List...
method ContainerList (line 113) | func (d DockerAPIStub) ContainerList(ctx context.Context, options cont...
method ContainerInspect (line 119) | func (d DockerAPIStub) ContainerInspect(ctx context.Context, container...
method ServiceList (line 125) | func (d DockerAPIStub) ServiceList(ctx context.Context, options swarm....
method NetworkList (line 131) | func (d DockerAPIStub) NetworkList(ctx context.Context, options networ...
function createHTTPServer (line 137) | func createHTTPServer() (*fiber.App, string) {
function buildConfigDetails (line 184) | func buildConfigDetails(source map[string]any, env map[string]string) co...
function loadYAML (line 199) | func loadYAML(yaml []byte) (*compose.Config, error) {
function loadYAMLWithEnv (line 203) | func loadYAMLWithEnv(yaml []byte, env map[string]string) (*compose.Confi...
function createContainers (line 213) | func createContainers(composeConfig *compose.Config) []container.Summary {
function createContainersJSON (line 239) | func createContainersJSON(composeConfig *compose.Config) map[string]cont...
function processFile (line 296) | func processFile(t *testing.T, file ...string) TraefikStore {
function processFileWithConfig (line 304) | func processFileWithConfig(t *testing.T, store TraefikStore, config *Con...
function assertServiceIP (line 378) | func assertServiceIP(t *testing.T, store *testStore, serviceName string,...
type svc (line 382) | type svc struct
function assertServiceIPs (line 388) | func assertServiceIPs(t *testing.T, store TraefikStore, svcs []svc) {
FILE: docker_proxy.go
function getAvailablePort (line 22) | func getAvailablePort() (net.Listener, error) {
type DockerProxyServer (line 36) | type DockerProxyServer struct
method filterLabels (line 51) | func (s *DockerProxyServer) filterLabels(labels map[string]string) map...
method handleVersion (line 72) | func (s *DockerProxyServer) handleVersion(c *fiber.Ctx) error {
method handleContainersList (line 80) | func (s *DockerProxyServer) handleContainersList(c *fiber.Ctx) error {
method handleContainerInspect (line 94) | func (s *DockerProxyServer) handleContainerInspect(c *fiber.Ctx) error {
method handleEvents (line 107) | func (s *DockerProxyServer) handleEvents(c *fiber.Ctx) error {
method handleNotFound (line 152) | func (s *DockerProxyServer) handleNotFound(c *fiber.Ctx) error {
method start (line 157) | func (s *DockerProxyServer) start() (*fiber.App, string) {
function createProxy (line 41) | func createProxy(upstream client.APIClient, labelPrefix string) *DockerP...
FILE: docker_proxy_test.go
function Test_dockerProxyServerNoPrefix (line 10) | func Test_dockerProxyServerNoPrefix(t *testing.T) {
function Test_dockerProxyServerPrefix (line 38) | func Test_dockerProxyServerPrefix(t *testing.T) {
function Test_dockerProxyServerPrefixWithKopBindIP (line 68) | func Test_dockerProxyServerPrefixWithKopBindIP(t *testing.T) {
FILE: docker_test.go
function setup (line 19) | func setup() {
function teardown (line 29) | func teardown() {
function TestMain (line 36) | func TestMain(m *testing.M) {
function Test_httpServerVersion (line 46) | func Test_httpServerVersion(t *testing.T) {
function Test_helloWorld (line 53) | func Test_helloWorld(t *testing.T) {
function Test_helloDetect (line 73) | func Test_helloDetect(t *testing.T) {
function Test_helloIP (line 82) | func Test_helloIP(t *testing.T) {
function Test_helloNetwork (line 91) | func Test_helloNetwork(t *testing.T) {
function Test_TCP (line 99) | func Test_TCP(t *testing.T) {
function Test_TCPMQTT (line 107) | func Test_TCPMQTT(t *testing.T) {
function Test_helloWorldNoCert (line 116) | func Test_helloWorldNoCert(t *testing.T) {
function Test_routerTLSWithoutCertResolver (line 127) | func Test_routerTLSWithoutCertResolver(t *testing.T) {
function g (line 133) | func g(s TraefikStore, k string) string {
function Test_helloWorldIgnore (line 141) | func Test_helloWorldIgnore(t *testing.T) {
function Test_helloWorldMultiNS (line 152) | func Test_helloWorldMultiNS(t *testing.T) {
function Test_helloWorldAutoMapped (line 178) | func Test_helloWorldAutoMapped(t *testing.T) {
function Test_samePrefix (line 186) | func Test_samePrefix(t *testing.T) {
function Test_loadbalance (line 198) | func Test_loadbalance(t *testing.T) {
FILE: kv.go
type KV (line 15) | type KV struct
method SetBase (line 24) | func (kv *KV) SetBase(b string) {
method add (line 28) | func (kv *KV) add(val interface{}, format string, a ...interface{}) {
function NewKV (line 20) | func NewKV() *KV {
function ConfigToKV (line 51) | func ConfigToKV(conf dynamic.Configuration) (map[string]interface{}, err...
type walkOptions (line 67) | type walkOptions struct
function walkTypedValue (line 71) | func walkTypedValue(kv *KV, path string, typ reflect.Type, val reflect.V...
function walkStructValue (line 126) | func walkStructValue(kv *KV, path string, typ reflect.Type, val reflect....
function walkMapValue (line 165) | func walkMapValue(kv *KV, path string, typ reflect.Type, val reflect.Val...
function walkSliceValue (line 192) | func walkSliceValue(kv *KV, path string, typ reflect.Type, val reflect.V...
function isLeafType (line 213) | func isLeafType(typ reflect.Type) bool {
function leafString (line 230) | func leafString(typ reflect.Type, val reflect.Value) (string, bool, erro...
function marshalerValue (line 273) | func marshalerValue(val reflect.Value, iface reflect.Type) (interface{},...
function joinPath (line 292) | func joinPath(base, child string) string {
function jsonFieldName (line 296) | func jsonFieldName(field reflect.StructField) (string, bool, bool) {
function isEmptyJSONValue (line 319) | func isEmptyJSONValue(val reflect.Value) bool {
FILE: kv_test.go
function Test_configToKV (line 13) | func Test_configToKV(t *testing.T) {
function dumpKV (line 40) | func dumpKV(kv map[string]interface{}) {
FILE: kv_walk_test.go
function TestConfigToKVAllowEmptyLabel (line 12) | func TestConfigToKVAllowEmptyLabel(t *testing.T) {
function TestConfigToKVUsesJSONLeafEncoding (line 34) | func TestConfigToKVUsesJSONLeafEncoding(t *testing.T) {
FILE: multi_provider.go
type MultiProvider (line 11) | type MultiProvider struct
method Init (line 19) | func (p MultiProvider) Init() error {
method Provide (line 29) | func (p MultiProvider) Provide(configurationChan chan<- dynamic.Messag...
function NewMultiProvider (line 15) | func NewMultiProvider(upstream []provider.Provider) *MultiProvider {
FILE: multi_provider_test.go
function TestMultiProvider_ProvideCounts (line 13) | func TestMultiProvider_ProvideCounts(t *testing.T) {
FILE: polling_provider.go
type PollingProvider (line 15) | type PollingProvider struct
method Init (line 25) | func (p PollingProvider) Init() error {
method Provide (line 29) | func (p PollingProvider) Provide(configurationChan chan<- dynamic.Mess...
function NewPollingProvider (line 21) | func NewPollingProvider(refreshInterval time.Duration, upstream provider...
FILE: polling_provider_test.go
type noopProvider (line 14) | type noopProvider struct
method Init (line 18) | func (n *noopProvider) Init() error {
method Provide (line 22) | func (n *noopProvider) Provide(configurationChan chan<- dynamic.Messag...
function TestPollingProvider_CountsPolls (line 27) | func TestPollingProvider_CountsPolls(t *testing.T) {
FILE: store.go
type TraefikStore (line 19) | type TraefikStore interface
function collectKeys (line 27) | func collectKeys(m interface{}) []string {
type RedisStore (line 38) | type RedisStore struct
method Ping (line 65) | func (s *RedisStore) Ping() error {
method sk (line 71) | func (s RedisStore) sk(b string) string {
method Get (line 75) | func (s *RedisStore) Get(key string) (string, error) {
method Gets (line 86) | func (s *RedisStore) Gets(key string) (map[string]string, error) {
method Store (line 110) | func (s *RedisStore) Store(conf dynamic.Configuration) error {
method NeedsUpdate (line 159) | func (s *RedisStore) NeedsUpdate() bool {
method KeepConfAlive (line 169) | func (s *RedisStore) KeepConfAlive() error {
method swapKeys (line 182) | func (s *RedisStore) swapKeys(setkey string) error {
method k (line 197) | func (s RedisStore) k(sk, b string) string {
method removeKeys (line 203) | func (s *RedisStore) removeKeys(setkey string, keys []string) error {
method removeOldKeys (line 224) | func (s *RedisStore) removeOldKeys(m interface{}, setname string) error {
function NewRedisStore (line 46) | func NewRedisStore(hostname string, addr string, ttl int, user string, p...
function mkslice (line 252) | func mkslice(old []string) []interface{} {
FILE: store_test.go
constant NGINX_CONF_JSON (line 16) | NGINX_CONF_JSON = `{"http":{"routers":{"nginx@docker":{"service":"nginx"...
constant NGINX_CONF_JSON_DIFFRENT_SERVICE_NAME (line 17) | NGINX_CONF_JSON_DIFFRENT_SERVICE_NAME = `{"http":{"routers":{"nginx@dock...
function Test_collectKeys (line 19) | func Test_collectKeys(t *testing.T) {
function Test_redisStore (line 43) | func Test_redisStore(t *testing.T) {
FILE: testing/helloworld/main.go
function main (line 10) | func main() {
FILE: traefik_kop.go
function newDockerProvider (line 32) | func newDockerProvider(config Config) *docker.Provider {
function createConfigHandler (line 57) | func createConfigHandler(config Config, store TraefikStore, dp *docker.P...
function Start (line 88) | func Start(config Config) {
function keepContainer (line 170) | func keepContainer(ns []string, container container.InspectResponse) bool {
function filterServices (line 186) | func filterServices(dc *dockerCache, conf *dynamic.Configuration, ns []s...
function replaceIPs (line 285) | func replaceIPs(dc *dockerCache, conf *dynamic.Configuration, ip string) {
function getRouterOfService (line 385) | func getRouterOfService(conf *dynamic.Configuration, svcName string, svc...
function getContainerPort (line 422) | func getContainerPort(dc *dockerCache, conf *dynamic.Configuration, svcT...
function getContainerNetworkIP (line 455) | func getContainerNetworkIP(dc *dockerCache, conf *dynamic.Configuration,...
function getKopOverrideBinding (line 489) | func getKopOverrideBinding(dc *dockerCache, conf *dynamic.Configuration,...
function mergeLoadBalancers (line 514) | func mergeLoadBalancers(dc *dockerCache, conf *dynamic.Configuration, st...
function mergeGenericLoadBalancers (line 544) | func mergeGenericLoadBalancers(
FILE: traefik_kop_test.go
function init (line 21) | func init() {
type fakeDockerClient (line 26) | type fakeDockerClient struct
method ContainerList (line 33) | func (c *fakeDockerClient) ContainerList(ctx context.Context, options ...
method ContainerInspect (line 37) | func (c *fakeDockerClient) ContainerInspect(ctx context.Context, conta...
function Test_replaceIPs (line 41) | func Test_replaceIPs(t *testing.T) {
function createTestClient (line 65) | func createTestClient(labels map[string]string) *fakeDockerClient {
function Test_replacePorts (line 85) | func Test_replacePorts(t *testing.T) {
function Test_replacePortsNoService (line 130) | func Test_replacePortsNoService(t *testing.T) {
FILE: util.go
function dumpJson (line 8) | func dumpJson(o interface{}) []byte {
function splitStringArr (line 16) | func splitStringArr(str string) []string {
Condensed preview — 59 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (394K chars).
[
{
"path": ".dockerignore",
"chars": 86,
"preview": ".git\n.gitignore\n.env\n\n.dockerignore\nDockerfile\n\nMakefile\nLICENSE\nREADME.md\ndocs\ndist/\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 15,
"preview": "github: chetan\n"
},
{
"path": ".github/workflows/on_push.yaml",
"chars": 3242,
"preview": "name: on-push\n\non:\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n\npermissions:\n package"
},
{
"path": ".github/workflows/on_tag.yaml",
"chars": 2529,
"preview": "name: tagged-release\n\non:\n push:\n tags:\n - \"v*\"\n\npermissions:\n packages: write\n contents: write\n\nenv:\n REGIS"
},
{
"path": ".gitignore",
"chars": 115,
"preview": ".DS_Store\n.vscode/\n/traefik-kop*\n/dist\n*.out\n.history/\n*.tmp\n\n# temp files created by sugardb (used in tests)\naof/\n"
},
{
"path": ".goreleaser.yml",
"chars": 1568,
"preview": "# yaml-language-server: $schema=https://goreleaser.com/static/schema.json\n\nversion: 2\nproject_name: traefik-kop\nbefore:\n"
},
{
"path": "CHANGELOG.md",
"chars": 8366,
"preview": "# Changelog\n\n## v0.19.4\n\n- disallow using DOCKER_HOST var together with prefixes (resolves #83)\n\n## v0.19.3\n\n### Fixes\n\n"
},
{
"path": "Dockerfile",
"chars": 106,
"preview": "FROM scratch\nENTRYPOINT [\"/traefik-kop\"]\nARG TARGETPLATFORM\nCOPY $TARGETPLATFORM/traefik-kop /traefik-kop\n"
},
{
"path": "LICENSE",
"chars": 1069,
"preview": "MIT License\n\nCopyright (c) 2021 Chetan Sarva\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
},
{
"path": "Makefile",
"chars": 951,
"preview": "\nPROJECT=ghcr.io/jittering/traefik-kop\n\n.DEFAULT_GOAL := run\n\nSHELL := bash\n\nbuild-docker: build-linux\n\tdocker build --p"
},
{
"path": "README.md",
"chars": 14156,
"preview": "# traefik-kop\n\nA dynamic docker->redis->traefik discovery agent.\n\nSolves the problem of running a non-Swarm/Kubernetes m"
},
{
"path": "bin/traefik-kop/main.go",
"chars": 7342,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"strings\"\n\n\ttraefikkop \"github.com/jittering/traefik-kop\"\n\t\"github.com/rs/ze"
},
{
"path": "config.go",
"chars": 1682,
"preview": "package traefikkop\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/pkg/errors\"\n\t\"github.com/rs/zerolog/log\"\n\t\"g"
},
{
"path": "docker-compose.yml",
"chars": 267,
"preview": "version: \"3\"\n\nservices:\n traefik-kop:\n image: \"ghcr.io/jittering/traefik-kop:latest\"\n restart: unless-stopped\n "
},
{
"path": "docker.go",
"chars": 6684,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/docker/docker/api/types"
},
{
"path": "docker_helpers_test.go",
"chars": 10135,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net\"\n\t\"os\"\n\t\"path\"\n\t\"sort\"\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.co"
},
{
"path": "docker_proxy.go",
"chars": 4782,
"preview": "package traefikkop\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/docker/do"
},
{
"path": "docker_proxy_test.go",
"chars": 3138,
"preview": "package traefikkop\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc Test_dockerProxyServerNoPr"
},
{
"path": "docker_test.go",
"chars": 6283,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/docker/docker/client\"\n\t\"github.com/gofiber"
},
{
"path": "fixtures/docker-prefix.yml",
"chars": 521,
"preview": "services:\n # test labels with a prefix, i.e., DOCKER_PREFIX=foo.\n dockerprefix:\n restart: unless-stopped\n ports:"
},
{
"path": "fixtures/gitea.yml",
"chars": 555,
"preview": "services:\n gitea:\n image: gitea/gitea\n labels:\n traefik.enable: \"true\"\n traefik.http.routers.gitea.rule"
},
{
"path": "fixtures/hello-automapped.yml",
"chars": 357,
"preview": "\nservices:\n hello:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555\n labels:\n - \"traef"
},
{
"path": "fixtures/hello-ignore.yml",
"chars": 562,
"preview": "\nservices:\n helloworld:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555:5555\n - 5566:556"
},
{
"path": "fixtures/hello-multi-ns.yml",
"chars": 566,
"preview": "\nservices:\n helloworld:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555:5555\n - 5566:556"
},
{
"path": "fixtures/hello-no-cert.yml",
"chars": 533,
"preview": "\nservices:\n helloworld:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555:5555\n - 5566:556"
},
{
"path": "fixtures/hellodetect.yml",
"chars": 1255,
"preview": "services:\n # This service is the same as above except that it does not have a label\n # which explicitly maps the port "
},
{
"path": "fixtures/helloip.yml",
"chars": 1344,
"preview": "services:\n helloip:\n build:\n dockerfile: ./helloworld/Dockerfile\n context: ./\n restart: unless-stopped\n"
},
{
"path": "fixtures/helloworld.yml",
"chars": 898,
"preview": "\nservices:\n helloworld:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555:5555\n - 5566:556"
},
{
"path": "fixtures/loadbalance1.yml",
"chars": 510,
"preview": "services:\n lb1:\n image: helloworld\n build: \"../helloworld\"\n restart: \"no\"\n labels:\n - \"traefik.enable="
},
{
"path": "fixtures/loadbalance2.yml",
"chars": 510,
"preview": "services:\n lb2:\n image: helloworld\n build: \"../helloworld\"\n restart: \"no\"\n labels:\n - \"traefik.enable="
},
{
"path": "fixtures/mqtt.yml",
"chars": 466,
"preview": "services:\n gitea:\n image: gitea/gitea\n labels:\n - \"traefik.enable=true\"\n - \"traefik.http.routers.mqtt.r"
},
{
"path": "fixtures/musicassistant-tls.yml",
"chars": 358,
"preview": "services:\n musicassistant:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555:5555\n labels:\n "
},
{
"path": "fixtures/network.yml",
"chars": 571,
"preview": "\nservices:\n helloworld:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555:5555\n - 5566:556"
},
{
"path": "fixtures/prefix-bindip.yml",
"chars": 1074,
"preview": "services:\n # test labels with a prefix, i.e., DOCKER_PREFIX=foo.\n dockerprefix:\n image: nginx\n restart: \"no\"\n "
},
{
"path": "fixtures/prefix.yml",
"chars": 1035,
"preview": "\nservices:\n hello:\n image: helloworld\n restart: unless-stopped\n ports:\n - 5555:5555\n labels:\n - \""
},
{
"path": "fixtures/sample.toml",
"chars": 14273,
"preview": "[global]\n checkNewVersion = true\n sendAnonymousUsage = true\n\n[serversTransport]\n insecureSkipVerify = true\n rootCAs "
},
{
"path": "go.mod",
"chars": 21474,
"preview": "module github.com/jittering/traefik-kop\n\ngo 1.24.0\n\ntoolchain go1.24.4\n\nreplace (\n\tgithub.com/abbot/go-http-auth => gith"
},
{
"path": "go.sum",
"chars": 193855,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "kv.go",
"chars": 8195,
"preview": "package traefikkop\n\nimport (\n\t\"encoding\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.co"
},
{
"path": "kv_test.go",
"chars": 1190,
"preview": "package traefikkop\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/BurntSushi/toml\"\n\t\"github.com/stretchr/tes"
},
{
"path": "kv_walk_test.go",
"chars": 1489,
"preview": "package traefikkop\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n\tptypes \"github.com/traefik/paer"
},
{
"path": "multi_provider.go",
"chars": 813,
"preview": "package traefikkop\n\nimport (\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n\t\"github.com/traefik/traefik/v3/pkg/pro"
},
{
"path": "multi_provider_test.go",
"chars": 751,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"sync/atomic\"\n\t\"testing\"\n\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n\t"
},
{
"path": "polling_provider.go",
"chars": 1583,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"github.com/rs/zerolog/log\"\n\t\"github.com/traefik/traefik/v3/pkg/config"
},
{
"path": "polling_provider_test.go",
"chars": 1150,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/traefik/traefik/v3/pkg/config/dy"
},
{
"path": "store.go",
"chars": 7191,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\""
},
{
"path": "store_test.go",
"chars": 2315,
"preview": "package traefikkop\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net\"\n\t\"testing\"\n\n\t\"github.com/BurntSushi/toml\"\n\t\"github.com/echov"
},
{
"path": "testing/docker-compose.yml",
"chars": 7001,
"preview": "services:\n # Redis for use in testing, if we don't have one available locally\n redis:\n image: \"redis:alpine\"\n re"
},
{
"path": "testing/helloworld/Dockerfile",
"chars": 169,
"preview": "FROM golang:alpine AS builder\n\nCOPY * /go/\nRUN go build -o helloworld ./\n\nFROM alpine:latest\n\nCOPY --from=builder /go/he"
},
{
"path": "testing/helloworld/README.md",
"chars": 110,
"preview": "# helloworld\n\nSimple helloworld service for testing a container which listens on multiple\nports (5555, 5566).\n"
},
{
"path": "testing/helloworld/go.mod",
"chars": 70,
"preview": "module github.com/jittering/traefik-kop/testing/helloworld\n\ngo 1.22.3\n"
},
{
"path": "testing/helloworld/main.go",
"chars": 1698,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"net/http\"\n)\n\nfunc main() {\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/\", "
},
{
"path": "testing/internal/Makefile",
"chars": 110,
"preview": "\nup:\n\tcd ../.. && make build-linux\n\tdocker compose up --build -d\n\ndown:\n\tdocker compose down --remove-orphans\n"
},
{
"path": "testing/internal/docker-compose.yml",
"chars": 687,
"preview": "# Test case for issue #51\n# https://github.com/jittering/traefik-kop/issues/51\n#\n# kop fails to start if outbound IP can"
},
{
"path": "testing/kop/docker-compose.yml",
"chars": 484,
"preview": "# Compose file for testing traefik-kop itself from within a container env\nversion: \"3\"\n\nservices:\n traefik-kop:\n ima"
},
{
"path": "testing/publish-random.sh",
"chars": 315,
"preview": "#!/bin/bash\n\n# Test a docker run command\n\ndocker run --rm -it \\\n --label \"traefik.enable=true\" \\\n --label \"traefik.htt"
},
{
"path": "traefik_kop.go",
"chars": 20687,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/url\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/docker/"
},
{
"path": "traefik_kop_test.go",
"chars": 5732,
"preview": "package traefikkop\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/BurntSushi/toml\"\n\t\"github.c"
},
{
"path": "util.go",
"chars": 483,
"preview": "package traefikkop\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n)\n\nfunc dumpJson(o interface{}) []byte {\n\tout, err := json.Mars"
}
]
About this extraction
This page contains the full source code of the jittering/traefik-kop GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 59 files (366.7 KB), approximately 159.2k tokens, and a symbol index with 157 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.