Full Code of jittering/traefik-kop for AI

main 4cb22a54e4f5 cached
59 files
366.7 KB
159.2k tokens
157 symbols
1 requests
Download .txt
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
Download .txt
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
Download .txt
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.

Copied to clipboard!