[
  {
    "path": ".dockerignore",
    "content": ".git\n.gitignore\n.env\n\n.dockerignore\nDockerfile\n\nMakefile\nLICENSE\nREADME.md\ndocs\ndist/\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: chetan\n"
  },
  {
    "path": ".github/workflows/on_push.yaml",
    "content": "name: on-push\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\npermissions:\n  packages: write\n  contents: read\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n\nenv:\n  REGISTRY: ghcr.io\n  IMAGE_NAME: ${{ github.repository }}\n\njobs:\n  build_docker:\n    name: Build Docker\n    runs-on: self-hosted\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n        with:\n          # so we get proper snapshot version info\n          fetch-depth: 0\n\n      - name: Log in to the Container registry\n        uses: docker/login-action@v3\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Set up Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: ~1.25\n          cache: false\n\n      - name: Remote cache\n        uses: actions/cache@v4\n        if: ${{ runner.environment == 'github-hosted' }}\n        with:\n          path: |\n            ~/.cache/go-build\n            ~/go/pkg/mod\n          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n\n      # repo disappeared\n      # - name: Local cache\n      #   uses: actions-self-hosted/cache@v4\n      #   if: ${{ runner.environment == 'self-hosted' }}\n      #   with:\n      #     cache-dir: /local-cache\n      #     path: |\n      #       ~/.cache/go-build\n      #       ~/go/pkg/mod\n      #     key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n\n      - name: Set up GoReleaser\n        uses: goreleaser/goreleaser-action@v6\n        with:\n          version: latest\n          install-only: true\n\n      - name: Test\n        run: |\n          set -eo pipefail\n          go mod tidy\n          go mod download\n          go test ./...\n\n      - name: Build\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          set -eo pipefail\n          goreleaser release --clean --snapshot --parallelism 2\n\n      - name: Push docker images\n        if: ${{ github.ref == 'refs/heads/main' }}\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          # Manually push docker images\n          docker images --format '{{ .Repository }}:{{ .Tag }}' \\\n            | grep traefik-kop \\\n            | grep -v none \\\n            | xargs -n 1 docker push\n\n      - name: Cleanup local docker images\n        if: ${{ runner.environment == 'self-hosted' }}\n        run: |\n          # traefik-kop images\n          docker images \\\n            | grep ghcr.io/jittering/traefik-kop \\\n            | awk '{print $3}' \\\n            | sort | uniq \\\n            | xargs -r docker rmi -f\n\n          # runner images\n          docker images \\\n            | grep myoung34/github-runner \\\n            | grep none \\\n            | awk '{print $3}' \\\n            | sort | uniq \\\n            | xargs -r docker rmi -f\n\n      - name: Cleanup old images from registry\n        uses: dataaxiom/ghcr-cleanup-action@v1\n        with:\n          tags: \"*-next-*\"\n          older-than: \"30 days\"\n          delete-untagged: true\n"
  },
  {
    "path": ".github/workflows/on_tag.yaml",
    "content": "name: tagged-release\n\non:\n  push:\n    tags:\n      - \"v*\"\n\npermissions:\n  packages: write\n  contents: write\n\nenv:\n  REGISTRY: ghcr.io\n  IMAGE_NAME: ${{ github.repository }}\n\njobs:\n  tagged-release:\n    name: Tagged Release\n    runs-on: self-hosted\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Log in to the Container registry\n        uses: docker/login-action@v3\n        with:\n          registry: ${{ env.REGISTRY }}\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Set up QEMU\n        uses: docker/setup-qemu-action@v3\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Set up Go\n        uses: actions/setup-go@v6\n        with:\n          go-version: ~1.25\n          cache: false\n\n      - name: Remote cache\n        uses: actions/cache@v4\n        if: ${{ runner.environment == 'github-hosted' }}\n        with:\n          path: |\n            ~/.cache/go-build\n            ~/go/pkg/mod\n          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n\n      # repo disappeared\n      # - name: Local cache\n      #   uses: actions-self-hosted/cache@v4\n      #   if: ${{ runner.environment == 'self-hosted' }}\n      #   with:\n      #     cache-dir: /local-cache\n      #     path: |\n      #       ~/.cache/go-build\n      #       ~/go/pkg/mod\n      #     key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}\n\n      - name: Test\n        run: |\n          set -eo pipefail\n          go mod tidy\n          go mod download\n          go test ./...\n\n      - name: Run GoReleaser\n        uses: goreleaser/goreleaser-action@v6\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        with:\n          version: latest\n          args: release --clean\n\n      - name: Cleanup local docker images\n        if: ${{ runner.environment == 'self-hosted' }}\n        run: |\n          # traefik-kop images\n          docker images \\\n            | grep ghcr.io/jittering/traefik-kop \\\n            | awk '{print $3}' \\\n            | sort | uniq \\\n            | xargs -r docker rmi -f\n\n          # runner images\n          docker images \\\n            | grep myoung34/github-runner \\\n            | grep none \\\n            | awk '{print $3}' \\\n            | sort | uniq \\\n            | xargs -r docker rmi -f\n\n      - name: Cleanup old images from registry\n        uses: dataaxiom/ghcr-cleanup-action@v1\n        with:\n          tags: \"*-next-*\"\n          older-than: \"30 days\"\n          delete-untagged: true\n"
  },
  {
    "path": ".gitignore",
    "content": ".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",
    "content": "# yaml-language-server: $schema=https://goreleaser.com/static/schema.json\n\nversion: 2\nproject_name: traefik-kop\nbefore:\n  hooks:\n    - go mod tidy\n    - go mod download\nbuilds:\n  - main: ./bin/traefik-kop/\n    env:\n      - CGO_ENABLED=0\n    goos:\n      - linux\n      - darwin\n    goarch:\n      - amd64\n      - arm\n      - arm64\n    goarm:\n      - \"6\"\n      - \"7\"\narchives:\n  - name_template: \"{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}\"\nchecksum:\n  name_template: \"checksums.txt\"\nsnapshot:\n  version_template: \"{{ incpatch .Version }}-next-{{ .ShortCommit }}\"\nchangelog:\n  sort: asc\n  filters:\n    exclude:\n      - \"^docs:\"\n      - \"^test:\"\n\ndockers_v2:\n  - images:\n      - \"ghcr.io/jittering/{{ .ProjectName }}\"\n    tags:\n      - \"{{ .Version }}\"\n      - \"{{ if not .IsSnapshot }}{{ .Major }}.{{ .Minor }}{{ end }}\"\n      - \"{{ if not .IsSnapshot }}latest{{ end }}\"\n    dockerfile: Dockerfile\n    platforms:\n      - linux/amd64\n      - linux/arm/v6\n      - linux/arm/v7\n      - linux/arm64\n    labels:\n      \"org.opencontainers.image.title\": \"{{ .ProjectName }}\"\n      \"org.opencontainers.image.description\": \"{{ .ProjectName }}\"\n      \"org.opencontainers.image.url\": \"https://github.com/jittering/{{ .ProjectName }}\"\n      \"org.opencontainers.image.source\": \"https://github.com/jittering/{{ .ProjectName }}\"\n      \"org.opencontainers.image.version\": \"{{ .Version }}\"\n      \"org.opencontainers.image.created\": \"{{ .Date }}\"\n      \"org.opencontainers.image.revision\": \"{{ .FullCommit }}\"\n      \"org.opencontainers.image.licenses\": \"MIT\"\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# 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- kop.bind.ip ignored when using label prefix (resolves #82)\n\n## v0.19.2\n\n### Fixes\n\n- Proper fix for docker API version (upgraded traefik dep to 3.6.1)\n\n## v0.19.1\n\n### Fixes\n\n- Auto-negotiation docker API version [#78](https://github.com/jittering/traefik-kop/issues/78)\n\n## v0.19\n\n### New Features\n\n- Add `--skip-replace` (env: `SKIP_REPLACE=1`) to entirely [skip IP replacement](README.md#disable-ip-replacement-auto-detection)\n\n### Fixes\n\n- NPE when using label prefix [#76](https://github.com/jittering/traefik-kop/issues/76)\n\n### Other\n\n- Upgraded `traefik` lib used by `traefik-kop` to v3.5\n\n**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).\n\n## v0.18.1\n\n- Fixed docker build\n\n## v0.18\n\n### New Features\n\n- 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)\n- Allow passing redis username via `--redis-user` (env: `REDIS_USER`) [#69](https://github.com/jittering/traefik-kop/pull/69)\n- Allow filtering traefik labels using prefix [#70](https://github.com/jittering/traefik-kop/pull/70)\n\n## v0.17\n\n### New Features\n\n- Support for setting a TTL on Redis keys [#58](https://github.com/jittering/traefik-kop/pull/58)\n- Support for merging load balancers across multiple nodes managed by `traefik-kop` [#59](https://github.com/jittering/traefik-kop/pull/59)\n\n### Fixes\n\n- Allow outbound IP detection to fail [#56](https://github.com/jittering/traefik-kop/pull/56)\n- Normalize container labels [#56](https://github.com/jittering/traefik-kop/pull/57)\n\n## v0.16\n\n### Fixes\n\n- Fix port detection when publishing to ephemeral ports [#48, thanks @Flamefork](https://github.com/jittering/traefik-kop/pull/48)\n\n## v0.15\n\n### Fixes\n\n- 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)\n\n## v0.14\n\n### New Features\n\n- Allow filtering containers processed by `traefik-kop` using [namespaces](https://github.com/jittering/traefik-kop#namespaces)\n\n### Fixes\n\n- Use exact service name match when searching container labels (#39, thanks @damfleu)\n\n**Full Changelog**: https://github.com/jittering/traefik-kop/compare/v0.13.3...v0.14\n\n## v0.13.3\n\n- 16beda8 build: bump go version to 1.22\n\n## v0.13.2\n\n- 10ab916 fix: properly stringify floats when writing to redis (resolves #25)\n\n## v0.13.1\n\n* [build: upgraded docker client dep](https://github.com/jittering/traefik-kop/commit/e7f30f3108f46cf0d174369b45f59d57398d002b)\n* [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))\n* [fix: avoid possible NPE when resolving CNI container IP](https://github.com/jittering/traefik-kop/commit/37686b0089ccaf91d4fa13df62447e15671944dd)\n\n\n\n## [v0.13](https://github.com/jittering/traefik-kop/tree/v0.13) (2022-10-17)\n\n[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.12.1...v0.13)\n\n### New Features\n\n- Set bind IP per-container or service\n- Set traefik docker provider config (e.g., `defaultRule`)\n\n### Fixes\n\n- Correctly set port for TCP and UDP services\n\n### Closed issues\n\n- Go runtime error [\\#20](https://github.com/jittering/traefik-kop/issues/20)\n- Default Rule [\\#18](https://github.com/jittering/traefik-kop/issues/18)\n- Provide IP for each docker via label [\\#17](https://github.com/jittering/traefik-kop/issues/17)\n- setting port for tcp service does not work [\\#16](https://github.com/jittering/traefik-kop/issues/16)\n- Doesn't work with multiple services on one container [\\#14](https://github.com/jittering/traefik-kop/issues/14)\n\n## v0.12.1\n\nThis release updates the upstream version of the traefik library to v2.8.4 and\nadds additional logging around port detection (both debug and info levels) to\nmake it easier to see what's going on and troubleshoot various scenarios.\n\n[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.12...v0.12.1)\n\n- [8c5a3f0](https://github.com/jittering/traefik-kop/commit/8c5a3f0) build: bump actions/cache to v3\n- [dad6e90](https://github.com/jittering/traefik-kop/commit/dad6e90) build: bump go version in github actions\n- [f009b84](https://github.com/jittering/traefik-kop/commit/f009b84) docs: added more detail and logging around port selection\n- [2f18114](https://github.com/jittering/traefik-kop/commit/2f18114) test: added helloworld service for testing multiple bindings\n- [be636f7](https://github.com/jittering/traefik-kop/commit/be636f7) build: upgraded traefik to 2.8.4 (now supports go 1.18+)\n\n## v0.12\n\n### Notes\n\nBy default, `traefik-kop` will listen for push events via the Docker API in\norder to detect configuration changes. In some circumstances, a change may not\nbe pushed correctly. For example, when using healthchecks in certain\nconfigurations, the `start -> healthy` change may not be detected via push\nevent. As a failsafe, there is an additional polling mechanism to detect those\nmissed changes.\n\nThe default interval of 60 seconds should be light so as not to cause any\nissues, however it can be adjusted as needed via the `KOP_POLL_INTERVAL` env var\nor set to 0 to disable it completely.\n\n[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.11...v0.12)\n\n- [347352b](https://github.com/jittering/traefik-kop/commit/347352b) build: fix goreleaser tidy\n- [b6447c3](https://github.com/jittering/traefik-kop/commit/b6447c3) build: go mod tidy\n- [12ad255](https://github.com/jittering/traefik-kop/commit/12ad255) docs: added poll interval to readme\n- [10f7aab](https://github.com/jittering/traefik-kop/commit/10f7aab) feat: expose providers in case anyone wants to reuse\n- [5b58547](https://github.com/jittering/traefik-kop/commit/5b58547) feat: add log message when explicitly disabling polling\n- [02802d5](https://github.com/jittering/traefik-kop/commit/02802d5) feat: configurable poll interval (default 60)\n- [b2ef52b](https://github.com/jittering/traefik-kop/commit/b2ef52b) feat: combine providers into single config watcher\n- [07fe8aa](https://github.com/jittering/traefik-kop/commit/07fe8aa) feat: added polling provider as a workaround for healthcheck issue\n- [cc3854b](https://github.com/jittering/traefik-kop/commit/cc3854b) feat: added config for changing docker endpoint\n- [c309d40](https://github.com/jittering/traefik-kop/commit/c309d40) build: upgraded traefik lib to v2.7\n- [32c2df6](https://github.com/jittering/traefik-kop/commit/32c2df6) test: added pihole container (with builtin healthcheck)\n- [e770242](https://github.com/jittering/traefik-kop/commit/e770242) docs: updated changelog\n\n\n\n## v0.11\n\n\n[Full Changelog](https://github.com/jittering/traefik-kop/compare/v0.10.1...v0.11)\n\n#### Notes\n\n* If your container is configured to use a network-routable IP address via an\noverlay network or CNI plugin, that address will override the `bind-ip`\nconfiguration when the `traefik.docker.network` label is present.\n\n**Merged pull requests:**\n\n- Add support for `traefik.docker.network` [\\#8](https://github.com/jittering/traefik-kop/pull/8) ([hcooper](https://github.com/hcooper))\n\n\n## v0.10.1\n\n* e0af6eb Merge pull request #7 from jittering/fix/port-detect\n\n\n\n## v0.10.1\n\n* e0af6eb Merge pull request #7 from jittering/fix/port-detect\n\n\n\n## v0.10.0\n\n* 5d029d2 feat: add support for ports published via --publish-all (closes #6)\n\n\n\n## v0.9.2\n\n* 5871d16 feat: log the container name/id if found\n\n\n\n## v0.9.1\n\n\n* fbd2d1d fix: Automatic port assignment not working for containers without a service\n\n\n## v0.9\n\n\n* 4bd7cd1 Merge pull request #2 from jittering/feature/detect-host-port\n\n\n\n## v0.8.1\n\n\n* e69bd05 fix: strip @docker when removing keys\n\n\n### Docker images\n\n- `docker pull ghcr.io/jittering/traefik-kop:0.8.1`\n\n\n## v0.8\n\n\n* dccbf22 build: fix release step\n\n\n### Docker images\n\n- `docker pull ghcr.io/jittering/traefik-kop:0.8`\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM scratch\nENTRYPOINT [\"/traefik-kop\"]\nARG TARGETPLATFORM\nCOPY $TARGETPLATFORM/traefik-kop /traefik-kop\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Chetan Sarva\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "\nPROJECT=ghcr.io/jittering/traefik-kop\n\n.DEFAULT_GOAL := run\n\nSHELL := bash\n\nbuild-docker: build-linux\n\tdocker build --platform linux/amd64 -t ${PROJECT}:latest .\n\nbuild-linux:\n\tGOOS=linux go build ./bin/traefik-kop\n\nbuild:\n\tgo build ./bin/traefik-kop\n\nrun:\n\tgo run ./bin/traefik-kop\n\nserve: run\n\ntest:\n\tgo test ./...\n\ncover:\n\tgo test -coverprofile=c.out ./...\n\nwatch:\n\twatchexec -e go,yml \"make test\"\n\nwatch-cover:\n\twatchexec -e go,yml \"make cover\"\n\nclean:\n\trm -rf dist/\n\trm -f traefik-kop\n\trm -rf aof/\n\nrelease: clean\n\tgoreleaser release --rm-dist --skip-validate\n\nupdate-changelog:\n\techo -e \"# Changelog\\n\" >> temp.md\n\trel=$$(gh release list | head -n 1 | awk '{print $$1}'); \\\n\t\techo \"## $$rel\" >> temp.md; \\\n\t\techo \"\" >> temp.md; \\\n\t\tgh release view --json body $$rel | \\\n\t\t\tjq --raw-output '.body' | \\\n\t\t\tgrep -v '^## Changelog' | \\\n\t\t\tsed -e 's/^#/##/g' >> temp.md\n\tcat CHANGELOG.md | grep -v '^# Changelog' >> temp.md\n\tmv temp.md CHANGELOG.md\n"
  },
  {
    "path": "README.md",
    "content": "# traefik-kop\n\nA dynamic docker->redis->traefik discovery agent.\n\nSolves the problem of running a non-Swarm/Kubernetes multi-host cluster with a\nsingle public-facing traefik instance.\n\n```text\n                        +---------------------+          +---------------------+\n                        |                     |          |                     |\n+---------+     :443    |  +---------+        |   :8088  |  +------------+     |\n|   WAN   |--------------->| traefik |<-------------------->| svc-nginx  |     |\n+---------+             |  +---------+        |          |  +------------+     |\n                        |       |             |          |                     |\n                        |  +---------+        |          |  +-------------+    |\n                        |  |  redis  |<-------------------->| traefik-kop |    |\n                        |  +---------+        |          |  +-------------+    |\n                        |             docker1 |          |             docker2 |\n                        +---------------------+          +---------------------+\n```\n\n`traefik-kop` solves this problem by using the same `traefik` docker-provider\nlogic. It reads the container labels from the local docker node and publishes\nthem to a given `redis` instance. Simply configure your `traefik` node with a\n`redis` provider and point it to the same instance, as in the diagram above.\n\n## Contents\n\n- [traefik-kop](#traefik-kop)\n  - [Contents](#contents)\n  - [Usage](#usage)\n  - [Configuration](#configuration)\n  - [IP Binding](#ip-binding)\n    - [bind-ip](#bind-ip)\n    - [bind-interface](#bind-interface)\n    - [traefik-kop service labels](#traefik-kop-service-labels)\n    - [Container Networking](#container-networking)\n    - [Disable IP Replacement (auto-detection)](#disable-ip-replacement-auto-detection)\n  - [Load Balancer Merging](#load-balancer-merging)\n  - [Service port binding](#service-port-binding)\n  - [Namespaces](#namespaces)\n    - [Namespace via label prefix](#namespace-via-label-prefix)\n  - [Docker API](#docker-api)\n    - [Traefik Docker Provider Config](#traefik-docker-provider-config)\n  - [Releasing](#releasing)\n  - [License](#license)\n\n## Usage\n\nConfigure `traefik` to use the redis provider, for example via `traefik.yml`:\n\n```yaml\nproviders:\n  providersThrottleDuration: 2s\n  docker:\n    watch: true\n    endpoint: unix:///var/run/docker.sock\n    swarmModeRefreshSeconds: 15s\n    exposedByDefault: false\n  redis:\n    endpoints:\n      # assumes a redis link with this service name running on the same\n      # docker host as traefik\n      - \"redis:6379\"\n```\n\nRun `traefik-kop` on your other nodes via docker-compose:\n\n```yaml\nservices:\n  traefik-kop:\n    image: \"ghcr.io/jittering/traefik-kop:latest\"\n    restart: unless-stopped\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n    environment:\n      - \"REDIS_ADDR=192.168.1.50:6379\"\n      - \"BIND_IP=192.168.1.75\"\n      # Alternatively, derive from an interface (requires network_mode: host)\n      # - \"BIND_INTERFACE=eth0\"\n```\n\nThen add the usual labels to your target service:\n\n```yml\nservices:\n  nginx:\n    image: \"nginx:alpine\"\n    restart: unless-stopped\n    ports:\n      # The host port binding will automatically be picked up for use as the\n      # service endpoint. See 'service port binding' in the configuration\n      # section for more.\n      - 8088:80\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.nginx.rule=Host(`nginx-on-docker2.example.com`)\"\n      - \"traefik.http.routers.nginx.tls=true\"\n      - \"traefik.http.routers.nginx.tls.certresolver=default\"\n      # [opptional] explicitly set the port binding for this service.\n      # See 'service port binding' in the configuration section for more.\n      - \"traefik.http.services.nginx.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.nginx.loadbalancer.server.port=8088\"\n```\n\nSee also the [IP Binding](#ip-binding) section below.\n\n## Configuration\n\ntraefik-kop can be configured via either CLI flags or environment variables.\n\n```text\nUSAGE:\n   traefik-kop [global options] command [command options] [arguments...]\n\nGLOBAL OPTIONS:\n   --hostname value       Hostname to identify this node in redis (default: \"server.local\") [$KOP_HOSTNAME]\n   --bind-ip value        IP address to bind services to [$BIND_IP]\n   --bind-interface value Network interface to derive bind IP (overrides auto-detect) [$BIND_INTERFACE]\n   --skip-replace         Disable custom IP replacement (default: false) [$SKIP_REPLACE]\n   --redis-addr value     Redis address (default: \"127.0.0.1:6379\") [$REDIS_ADDR]\n   --redis-user value     Redis username (default: \"default\") [$REDIS_USER]\n   --redis-pass value     Redis password (if needed) [$REDIS_PASS]\n   --redis-db value       Redis DB number (default: 0) [$REDIS_DB]\n   --redis-ttl value      Redis TTL (in seconds) (default: 0) [$REDIS_TTL]\n   --docker-host value    Docker endpoint (default: \"unix:///var/run/docker.sock\") [$DOCKER_ADDR]\n   --docker-config value  Docker provider config (file must end in .yaml) [$DOCKER_CONFIG]\n   --docker-prefix value  Docker label prefix [$DOCKER_PREFIX]\n   --poll-interval value  Poll interval for refreshing container list (default: 60) [$KOP_POLL_INTERVAL]\n   --namespace value      Namespace to process containers for [$NAMESPACE]\n   --verbose              Enable debug logging (default: false) [$VERBOSE, $DEBUG]\n   --help, -h             show help\n   --version, -V          Print the version (default: false)\n```\n\nMost important are the `bind-ip`/`bind-interface` and `redis-addr` flags.\n\n## IP Binding\n\nThere are a number of ways to set the IP published to traefik. Below is the\norder of precedence (highest first) and detailed descriptions of each setting.\n\n1. `kop.<service name>.bind.ip` label\n2. `kop.bind.ip` label\n3. Container networking IP\n4. `--bind-ip` CLI flag (or `BIND_IP` env var)\n5. `--bind-interface` CLI flag (or `BIND_INTERFACE` env var), requires network_mode: host\n6. Auto-detected host IP\n\n### bind-ip\n\nSince your upstream docker nodes are external to your primary traefik server,\ntraefik needs to connect to these services via the server's public IP rather\nthan the usual method of using the internal docker-network IPs (by default\n172.20.0.x or similar).\n\nWhen using host networking this can be auto-detected, however it is advisable in\nthe majority of cases to manually set this to the desired IP address. This can\nbe done using the docker image by exporting the `BIND_IP` environment variable.\n\n### bind-interface\n\nIf you prefer to bind using the primary IPv4 address of a specific network\ninterface, you can specify it via `--bind-interface` or the `BIND_INTERFACE`\nenvironment variable, for example `--bind-interface eth0`. This is used when\n`--bind-ip` is not provided. If the interface has multiple addresses, the first\nnon-loopback IPv4 address is selected.\n\nThis option requires that the container be run with  `network_mode: host` so that the interface is visible to the container.\n\n### traefik-kop service labels\n\nThe bind IP can be set via label for each service/container.\n\nLabels can be one of two keys:\n\n- `kop.<service name>.bind.ip=2.2.2.2`\n- `kop.bind.ip=2.2.2.2`\n\nFor a container with a single exposed service, or where all services use\nthe same IP, the latter is sufficient.\n\n### Container Networking\n\nIf your container is configured to use a network-routable IP address via an\noverlay network or CNI plugin, that address will override the `bind-ip`\nconfiguration above when the `traefik.docker.network` label is present on the\nservice.\n\nIf using a global overlay `network` in your [Traefik Docker Provider\nConfig](#traefik-docker-provider-config), it is recommended that you [disable IP\nreplacement](#disable-ip-replacement-auto-detection) entirely (see below).\n\n### Disable IP Replacement (auto-detection)\n\ntraefik-kop's custom IP and port auto-detection can be disabled by passing the `--skip-replace` flag\nor setting the `SKIP_REPLACE=1` environment variable. When set, `traefik-kop` will rely solely on\ntraefik's native IP and port detection. Other relevant flags such as `--bind-ip` or `--bind-interface`\nwill have no effect.\n\nThis works best when your services are using an overlay network, as described in\n[Container Networking](#container-networking) above.\n\n## Load Balancer Merging\n\nIf your service is running on multiple nodes and load balanced by traefik, you can enable\nmerging of load balancers by adding the following label to your container:\n\n- `kop.merge-lbs=true`\n\nWhen set, kop will check in redis for an existing definition and, if found, append it's service\naddress to the ones already present.\n\nThis setting is off by default as there are some cases where it could cause an issue, such as if\nyour node's IP changes. In this case, the dead IP would be left in place and the new IP would get\nadded to the list, causing some of your traffic to fail.\n\n## Service port binding\n\nBy default, the service port will be picked up from the container port bindings\nif only a single port is bound. For example:\n\n```yml\nservices:\n  nginx:\n    image: \"nginx:alpine\"\n    restart: unless-stopped\n    ports:\n      - 8088:80\n```\n\n`8088` would automatically be used as the service endpoint's port in traefik. If\nyou have more than one port or are using *host networking*, you will need to\nexplicitly set the port binding via service label, like so:\n\n```yaml\nservices:\n  nginx:\n    image: \"nginx:alpine\"\n    network_mode: host\n    ports:\n      - 8088:80\n      - 8888:81\n    labels:\n      # (note: other labels snipped for brevity)\n      - \"traefik.http.services.nginx.loadbalancer.server.port=8088\"\n```\n\n__NOTE:__ unlike the standard traefik-docker usage, we need to expose the\nservice port on the host and tell traefik to bind to *that* port (8088 in the\nexample above) in the load balancer config, not the internal port (80). This is\nso that traefik can reach it over the network.\n\n## Namespaces\n\ntraefik-kop has the ability to target containers via namespaces(s). Simply\nconfigure `kop` with a namespace:\n\n```yaml\nservices:\n  traefik-kop:\n    image: \"ghcr.io/jittering/traefik-kop:latest\"\n    restart: unless-stopped\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n    environment:\n      - \"REDIS_ADDR=192.168.1.50:6379\"\n      - \"BIND_IP=192.168.1.75\"\n      - \"NAMESPACE=staging\"\n```\n\nThen add the `kop.namespace` label to your target services, along with the usual traefik labels:\n\n```yaml\nservices:\n  nginx:\n    image: \"nginx:alpine\"\n    restart: unless-stopped\n    ports:\n      - 8088:80\n    labels:\n      - \"kop.namespace=staging\"\n      - \"traefik.enable=true\"\n      - \"traefik...\"\n```\n\nMultiple namespaces can be used by comma-delimiting your values. Traefik-kop will include a container as long as one of its namespaces is found.\n\n```yaml\nservices:\n  traefik-kop:\n    # ...\n    environment:\n      # will expose any service with either 'dev' or 'staging'\n      - \"NAMESPACE=dev,staging\"\n```\n\n```yaml\nservices:\n  nginx:\n    # ...\n    labels:\n      # will be exposed because it has namespace 'staging'\n      - \"kop.namespace=staging,experimental\"\n```\n\n### Namespace via label prefix\n\nAn alternative method of namespacing is to add a custom prefix for your traefik-related labels. This\nworks as an *inclusion* filter for `traefik-kop` and an *exclusion* filter for `traefik`. This can\nbe useful in a scenario here you are running both `traefik` and `traefik-kop` side-by-side on the\nsame host.\n\n```yaml\nservices:\n  nginx:\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers...\"\n      - \"traefik...\"\n```\n\nbecomes\n\n```yaml\nservices:\n  traefik-kop:\n    image: \"ghcr.io/jittering/traefik-kop:latest\"\n    restart: unless-stopped\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n    environment:\n      - \"REDIS_ADDR=192.168.1.50:6379\"\n      - \"BIND_IP=192.168.1.75\"\n      - \"DOCKER_PREFIX=kop.public\"\n\n  nginx:\n    labels:\n      - \"kop.public.traefik.enable=true\"\n      - \"kop.public.traefik.http.routers...\"\n      - \"kop.public.traefik...\"\n```\n\n## Docker API\n\ntraefik-kop expects to connect to the Docker host API via a unix socket, by\ndefault at `/var/run/docker.sock`. The location can be overridden via the\n`DOCKER_ADDR` env var or `--docker-host` flag.\n\nOther connection methods (like ssh, http/s) are not supported.\n\nBy default, `traefik-kop` will listen for push events via the Docker API in\norder to detect configuration changes. In some circumstances, a change may not\nbe pushed correctly. For example, when using healthchecks in certain\nconfigurations, the `start -> healthy` change may not be detected via push\nevent. As a failsafe, there is an additional polling mechanism to detect those\nmissed changes.\n\nThe default interval of 60 seconds should be light so as not to cause any\nissues, however it can be adjusted as needed via the `KOP_POLL_INTERVAL` env var\nor set to 0 to disable it completely.\n\n### Traefik Docker Provider Config\n\nIn addition to the simple `--docker-host` setting above, all [Docker Provider\nconfiguration\noptions](https://doc.traefik.io/traefik/providers/docker/#provider-configuration)\nare available via the `--docker-config <filename.yaml>` flag which expects\neither a filename to read configuration from or an inline YAML document.\n\nFor example:\n\n```yaml\nservices:\n  traefik-kop:\n    image: \"ghcr.io/jittering/traefik-kop:latest\"\n    restart: unless-stopped\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n    environment:\n      REDIS_ADDR: \"172.28.183.97:6380\"\n      BIND_IP: \"172.28.183.97\"\n      DOCKER_CONFIG: |\n        ---\n        docker:\n          defaultRule: Host(`{{.Name}}.foo.example.com`)\n```\n\n## Releasing\n\nTo release a new version, simply push a new tag to github.\n\n```sh\ngit push\ngit tag -a v0.11.0\ngit push --tags\n```\n\nTo update the changelog:\n\n```sh\nmake update-changelog\n# or (replace tag below)\ndocker run -it --rm -v \"$(pwd)\":/usr/local/src/your-app \\\n  githubchangeloggenerator/github-changelog-generator \\\n  -u jittering -p traefik-kop --output \"\" \\\n  --since-tag v0.10.1\n```\n\n## License\n\ntraefik-kop: MIT, (c) 2015, Pixelcop Research, Inc.\n\ntraefik: MIT, (c) 2016-2025 Containous SAS; 2020-2022 Traefik Labs\n"
  },
  {
    "path": "bin/traefik-kop/main.go",
    "content": "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/zerolog\"\n\t\"github.com/rs/zerolog/log\"\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/urfave/cli/v2\"\n)\n\nconst defaultDockerHost = \"unix:///var/run/docker.sock\"\n\nvar (\n\tversion string\n\tcommit  string\n\tdate    string\n\tbuiltBy string\n)\n\nfunc printVersion(c *cli.Context) error {\n\tfmt.Printf(\"%s version %s (commit: %s, built %s)\\n\", c.App.Name, c.App.Version, commit, date)\n\treturn nil\n}\n\nfunc flags() {\n\tif version == \"\" {\n\t\tversion = \"n/a\"\n\t}\n\tif commit == \"\" {\n\t\tcommit = \"head\"\n\t}\n\tif date == \"\" {\n\t\tdate = \"n/a\"\n\t}\n\n\tcli.VersionFlag = &cli.BoolFlag{\n\t\tName:    \"version\",\n\t\tAliases: []string{\"V\"},\n\t\tUsage:   \"Print the version\",\n\t}\n\tcli.VersionPrinter = func(c *cli.Context) {\n\t\tprintVersion(c)\n\t}\n\n\tapp := &cli.App{\n\t\tName:    \"traefik-kop\",\n\t\tUsage:   \"A dynamic docker->redis->traefik discovery agent\",\n\t\tVersion: version,\n\n\t\tAction: doStart,\n\n\t\tFlags: []cli.Flag{\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"hostname\",\n\t\t\t\tUsage:   \"Hostname to identify this node in redis\",\n\t\t\t\tValue:   getHostname(),\n\t\t\t\tEnvVars: []string{\"KOP_HOSTNAME\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"bind-ip\",\n\t\t\t\tUsage:   \"IP address to bind services to\",\n\t\t\t\tEnvVars: []string{\"BIND_IP\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"bind-interface\",\n\t\t\t\tUsage:   \"Network interface to derive bind IP (overrides auto-detect)\",\n\t\t\t\tEnvVars: []string{\"BIND_INTERFACE\"},\n\t\t\t},\n\t\t\t&cli.BoolFlag{\n\t\t\t\tName:    \"skip-replace\",\n\t\t\t\tUsage:   \"Disable custom IP replacement\",\n\t\t\t\tEnvVars: []string{\"SKIP_REPLACE\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"redis-addr\",\n\t\t\t\tUsage:   \"Redis address\",\n\t\t\t\tValue:   \"127.0.0.1:6379\",\n\t\t\t\tEnvVars: []string{\"REDIS_ADDR\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"redis-user\",\n\t\t\t\tUsage:   \"Redis username\",\n\t\t\t\tValue:   \"default\",\n\t\t\t\tEnvVars: []string{\"REDIS_USER\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"redis-pass\",\n\t\t\t\tUsage:   \"Redis password (if needed)\",\n\t\t\t\tEnvVars: []string{\"REDIS_PASS\"},\n\t\t\t},\n\t\t\t&cli.IntFlag{\n\t\t\t\tName:    \"redis-db\",\n\t\t\t\tUsage:   \"Redis DB number\",\n\t\t\t\tValue:   0,\n\t\t\t\tEnvVars: []string{\"REDIS_DB\"},\n\t\t\t},\n\t\t\t&cli.IntFlag{\n\t\t\t\tName:    \"redis-ttl\",\n\t\t\t\tUsage:   \"Redis TTL (in seconds)\",\n\t\t\t\tValue:   0,\n\t\t\t\tEnvVars: []string{\"REDIS_TTL\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"docker-host\",\n\t\t\t\tUsage:   \"Docker endpoint\",\n\t\t\t\tValue:   defaultDockerHost,\n\t\t\t\tEnvVars: []string{\"DOCKER_ADDR\", \"DOCKER_HOST\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"docker-config\",\n\t\t\t\tUsage:   \"Docker provider config (file must end in .yaml)\",\n\t\t\t\tEnvVars: []string{\"DOCKER_CONFIG\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"docker-prefix\",\n\t\t\t\tUsage:   \"Docker label prefix\",\n\t\t\t\tEnvVars: []string{\"DOCKER_PREFIX\"},\n\t\t\t},\n\t\t\t&cli.Int64Flag{\n\t\t\t\tName:    \"poll-interval\",\n\t\t\t\tUsage:   \"Poll interval for refreshing container list\",\n\t\t\t\tValue:   60,\n\t\t\t\tEnvVars: []string{\"KOP_POLL_INTERVAL\"},\n\t\t\t},\n\t\t\t&cli.StringFlag{\n\t\t\t\tName:    \"namespace\",\n\t\t\t\tUsage:   \"Namespace to process containers for\",\n\t\t\t\tEnvVars: []string{\"NAMESPACE\"},\n\t\t\t},\n\t\t\t&cli.BoolFlag{\n\t\t\t\tName:    \"verbose\",\n\t\t\t\tUsage:   \"Enable debug logging\",\n\t\t\t\tValue:   false,\n\t\t\t\tEnvVars: []string{\"VERBOSE\", \"DEBUG\"},\n\t\t\t},\n\t\t},\n\t}\n\n\terr := app.Run(os.Args)\n\tif err != nil {\n\t\tlog.Fatal().Err(err).Msg(\"Application error\")\n\t}\n}\n\nfunc setupLogging(debug bool) {\n\tif debug {\n\t\tlogrus.SetLevel(logrus.DebugLevel)\n\t\tzerolog.SetGlobalLevel(zerolog.DebugLevel)\n\t\tlog.Logger = log.Logger.Level(zerolog.DebugLevel)\n\t} else {\n\t\tlogrus.SetLevel(logrus.InfoLevel)\n\t\tzerolog.SetGlobalLevel(zerolog.InfoLevel)\n\t\tlog.Logger = log.Logger.Level(zerolog.InfoLevel)\n\t}\n\tzerolog.DefaultContextLogger = &log.Logger\n\n\tformatter := &logrus.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true}\n\tlogrus.SetFormatter(formatter)\n}\n\nfunc main() {\n\tflags()\n}\n\nfunc splitStringArr(str string) []string {\n\ttrimmed := strings.TrimSpace(str)\n\tif trimmed != \"\" {\n\t\ttrimmedVals := strings.Split(trimmed, \",\")\n\t\tsplitArr := make([]string, len(trimmedVals))\n\t\tfor i, v := range trimmedVals {\n\t\t\tsplitArr[i] = strings.TrimSpace(v)\n\t\t}\n\t\treturn splitArr\n\t}\n\treturn []string{}\n}\n\nfunc doStart(c *cli.Context) error {\n\ttraefikkop.Version = version\n\n\tnamespaces := splitStringArr(c.String(\"namespace\"))\n\n\t// Determine bind IP: precedence -> explicit --bind-ip -> --bind-interface -> auto-detect\n\tbindIP := strings.TrimSpace(c.String(\"bind-ip\"))\n\tif bindIP == \"\" {\n\t\tiface := strings.TrimSpace(c.String(\"bind-interface\"))\n\t\tbindIP = getDefaultIP(iface)\n\t}\n\n\tconfig := traefikkop.Config{\n\t\tHostname:     c.String(\"hostname\"),\n\t\tBindIP:       bindIP,\n\t\tSkipReplace:  c.Bool(\"skip-replace\"),\n\t\tRedisAddr:    c.String(\"redis-addr\"),\n\t\tRedisUser:    c.String(\"redis-user\"),\n\t\tRedisPass:    c.String(\"redis-pass\"),\n\t\tRedisDB:      c.Int(\"redis-db\"),\n\t\tRedisTTL:     c.Int(\"redis-ttl\"),\n\t\tDockerHost:   c.String(\"docker-host\"),\n\t\tDockerConfig: c.String(\"docker-config\"),\n\t\tDockerPrefix: c.String(\"docker-prefix\"),\n\t\tPollInterval: c.Int64(\"poll-interval\"),\n\t\tNamespace:    namespaces,\n\t}\n\n\tif config.BindIP == \"\" {\n\t\tlog.Fatal().Msg(\"Bind IP cannot be empty\")\n\t}\n\n\tif os.Getenv(\"DOCKER_HOST\") != \"\" {\n\t\tif config.DockerPrefix != \"\" {\n\t\t\tlog.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\")\n\t\t} else if config.DockerHost != os.Getenv(\"DOCKER_HOST\") {\n\t\t\tlog.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.\")\n\t\t}\n\t}\n\n\tsetupLogging(c.Bool(\"verbose\"))\n\tlog.Debug().Msgf(\"using traefik-kop config: %s\", fmt.Sprintf(\"%+v\", config))\n\n\ttraefikkop.Start(config)\n\treturn nil\n}\n\nfunc getHostname() string {\n\thostname, err := os.Hostname()\n\tif err != nil {\n\t\treturn \"traefik-kop\"\n\t}\n\treturn hostname\n}\n\nfunc getDefaultIP(iface string) string {\n\t// If a network interface is specified, attempt to get its primary IPv4 address\n\tif strings.TrimSpace(iface) != \"\" {\n\t\tif ip := GetInterfaceIP(iface); ip != nil {\n\t\t\treturn ip.String()\n\t\t}\n\t\tlog.Warn().Msgf(\"failed to get IP for interface '%s'; falling back to auto-detect\", iface)\n\t}\n\tip := GetOutboundIP()\n\tif ip == nil {\n\t\treturn \"\"\n\t}\n\treturn ip.String()\n}\n\n// Get preferred outbound ip of this machine\n// via https://stackoverflow.com/a/37382208/102920\nfunc GetOutboundIP() net.IP {\n\tconn, err := net.Dial(\"udp\", \"8.8.8.8:80\")\n\tif err != nil {\n\t\tlog.Warn().Msgf(\"failed to detect outbound IP: %s\", err)\n\t\treturn nil\n\t}\n\tdefer conn.Close()\n\n\tlocalAddr := conn.LocalAddr().(*net.UDPAddr)\n\n\treturn localAddr.IP\n}\n\n// GetInterfaceIP returns the first non-loopback IPv4 address for the named interface\nfunc GetInterfaceIP(name string) net.IP {\n\tiface, err := net.InterfaceByName(name)\n\tif err != nil {\n\t\tlog.Warn().Msgf(\"unable to find interface '%s': %v\", name, err)\n\t\treturn nil\n\t}\n\taddrs, err := iface.Addrs()\n\tif err != nil {\n\t\tlog.Warn().Msgf(\"unable to list addresses for interface '%s': %v\", name, err)\n\t\treturn nil\n\t}\n\tfor _, a := range addrs {\n\t\tvar ip net.IP\n\t\tswitch v := a.(type) {\n\t\tcase *net.IPNet:\n\t\t\tip = v.IP\n\t\tcase *net.IPAddr:\n\t\t\tip = v.IP\n\t\t}\n\t\tif ip == nil || ip.IsLoopback() {\n\t\t\tcontinue\n\t\t}\n\t\tip = ip.To4()\n\t\tif ip == nil {\n\t\t\tcontinue // skip IPv6 for bind default\n\t\t}\n\t\treturn ip\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "config.go",
    "content": "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\"github.com/traefik/traefik/v3/pkg/provider/docker\"\n\t\"gopkg.in/yaml.v3\"\n)\n\ntype Config struct {\n\tDockerConfig string\n\tDockerHost   string\n\n\t// prefix for traefik labels to accept\n\tDockerPrefix string\n\tHostname     string\n\tBindIP       string\n\tSkipReplace  bool\n\tRedisAddr    string\n\tRedisTTL     int\n\tRedisUser    string\n\tRedisPass    string\n\tRedisDB      int\n\tPollInterval int64\n\tNamespace    []string\n}\n\ntype ConfigFile struct {\n\tDocker docker.Provider `yaml:\"docker\"`\n}\n\nfunc loadDockerConfig(input string) (*docker.Provider, error) {\n\tif input == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tvar r io.Reader\n\n\tif looksLikeFile(input) {\n\t\t// see if given filename\n\t\t_, err := os.Stat(input)\n\t\tif err == nil {\n\t\t\tlog.Debug().Msgf(\"loading docker config from file %s\", input)\n\t\t\tr, err = os.Open(input)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, errors.Wrapf(err, \"failed to open docker config %s\", input)\n\t\t\t}\n\t\t\tdefer r.(io.Closer).Close()\n\t\t} else {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to stat docker config %s\", input)\n\t\t}\n\t} else {\n\t\tlog.Debug().Msgf(\"loading docker config from yaml input\")\n\t\tr = strings.NewReader(input) // treat as direct yaml input\n\t}\n\n\t// parse\n\tconf := ConfigFile{Docker: docker.Provider{}}\n\terr := yaml.NewDecoder(r).Decode(&conf)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to load config\")\n\t}\n\n\tconf.Docker.Network = strings.TrimSpace(conf.Docker.Network)\n\n\treturn &conf.Docker, nil\n}\n\nfunc looksLikeFile(input string) bool {\n\tif strings.Contains(input, \"\\n\") {\n\t\treturn false\n\t}\n\tok, _ := regexp.MatchString(`\\.ya?ml`, input)\n\treturn ok\n}\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: \"3\"\n\nservices:\n  traefik-kop:\n    image: \"ghcr.io/jittering/traefik-kop:latest\"\n    restart: unless-stopped\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n    environment:\n      - \"REDIS_ADDR=192.168.1.50:6379\"\n      - \"BIND_IP=192.168.1.75\"\n"
  },
  {
    "path": "docker.go",
    "content": "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/container\"\n\t\"github.com/docker/docker/client\"\n\t\"github.com/docker/go-connections/nat\"\n\t\"github.com/pkg/errors\"\n\t\"github.com/rs/zerolog\"\n\t\"github.com/rs/zerolog/log\"\n)\n\n// Copied from traefik. See docker provider package for original impl\n\ntype dockerCache struct {\n\tclient  client.APIClient\n\tlist    []container.Summary\n\tdetails map[string]container.InspectResponse\n\texpires time.Time\n}\n\n// Must be 0 for unix socket?\n// Non-zero throws an error\nconst defaultTimeout = time.Duration(0)\n\nfunc createDockerClient(endpoint string) (client.APIClient, error) {\n\topts, err := getClientOpts(endpoint)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\thttpHeaders := map[string]string{\n\t\t\"User-Agent\": \"traefik-kop \" + Version,\n\t}\n\topts = append(opts, client.WithHTTPHeaders(httpHeaders))\n\n\t// Use API version negotiation for compatibility with both old and new Docker daemons\n\t// This fixes the issue with Docker CE 29.0.0 which requires minimum API version 1.44\n\topts = append(opts, client.WithAPIVersionNegotiation())\n\n\treturn client.NewClientWithOpts(opts...)\n}\n\nfunc getClientOpts(endpoint string) ([]client.Opt, error) {\n\t// we currently do not support ssh, so skip helper setup\n\topts := []client.Opt{\n\t\tclient.WithHost(endpoint),\n\t\tclient.WithTimeout(time.Duration(defaultTimeout)),\n\t}\n\treturn opts, nil\n}\n\n// populate the cache with the current list of running containers and their details.\n//\n// Cache expires after 30 seconds.\nfunc (dc *dockerCache) populate() error {\n\tif time.Now().After(dc.expires) {\n\t\tdc.list = nil\n\t\tdc.details = make(map[string]container.InspectResponse)\n\t}\n\n\tif dc.list == nil {\n\t\tvar err error\n\t\tdc.list, err = dc.client.ContainerList(context.Background(), container.ListOptions{})\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"failed to list containers\")\n\t\t}\n\t}\n\n\tfor _, c := range dc.list {\n\t\tvar container container.InspectResponse\n\t\tvar ok bool\n\t\tif container, ok = dc.details[c.ID]; !ok {\n\t\t\tvar err error\n\t\t\tcontainer, err = dc.client.ContainerInspect(context.Background(), c.ID)\n\t\t\tif err != nil {\n\t\t\t\treturn errors.Wrapf(err, \"failed to inspect container %s\", c.ID)\n\t\t\t}\n\t\t\tdc.details[c.ID] = container\n\t\t}\n\n\t\t// normalize labels\n\t\tlabels := make(map[string]string, len(container.Config.Labels))\n\t\tfor k, v := range container.Config.Labels {\n\t\t\tlabels[strings.ToLower(k)] = v\n\t\t}\n\t\tcontainer.Config.Labels = labels\n\t}\n\n\tdc.expires = time.Now().Add(5 * time.Second) // cache expires in 30 seconds\n\n\treturn nil\n}\n\n// looks up the docker container by finding the matching service or router traefik label\nfunc (dc *dockerCache) findContainerByServiceName(svcType string, svcName string, routerName string) (container.InspectResponse, error) {\n\terr := dc.populate()\n\tif err != nil {\n\t\treturn container.InspectResponse{}, err\n\t}\n\n\tsvcName = stripDocker(svcName)\n\trouterName = stripDocker(routerName)\n\n\tfor _, container := range dc.details {\n\t\t// check labels\n\t\tsvcNeedle := fmt.Sprintf(\"traefik.%s.services.%s.\", svcType, svcName)\n\t\trouterNeedle := fmt.Sprintf(\"traefik.%s.routers.%s.\", svcType, routerName)\n\t\tfor k := range container.Config.Labels {\n\t\t\tif strings.HasPrefix(k, svcNeedle) || (routerName != \"\" && strings.HasPrefix(k, routerNeedle)) {\n\t\t\t\tlog.Debug().Msgf(\"found container '%s' (%s) for service '%s'\", container.Name, container.ID, svcName)\n\t\t\t\treturn container, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn container.InspectResponse{}, errors.Errorf(\"service label not found for %s/%s\", svcType, svcName)\n}\n\n// Check if the port is explicitly set via label\nfunc isPortSet(container container.InspectResponse, svcType string, svcName string) string {\n\tsvcName = stripDocker(svcName)\n\tneedle := fmt.Sprintf(\"traefik.%s.services.%s.loadbalancer.server.port\", svcType, svcName)\n\treturn container.Config.Labels[needle]\n}\n\n// getPortBinding checks the docker container config for a port binding for the\n// service. Currently this will only work if a single port is mapped/exposed.\n//\n// i.e., it looks for the following from a docker-compose service:\n//\n// ports:\n//   - 5555:5555\n//\n// If more than one port is bound (e.g., for a service like minio), then this\n// detection will fail. Instead, the user should explicitly set the port in the\n// label.\nfunc getPortBinding(container container.InspectResponse) (string, error) {\n\tlog.Debug().Msg(\"looking for port in host config bindings\")\n\tnumBindings := len(container.HostConfig.PortBindings)\n\tlog.Debug().Msgf(\"found %d host-port bindings\", numBindings)\n\tif numBindings > 1 {\n\t\treturn \"\", errors.Errorf(\"found more than one host-port binding for container '%s' (%s)\", container.Name, portBindingString(container.HostConfig.PortBindings))\n\t}\n\tfor _, v := range container.HostConfig.PortBindings {\n\t\tif len(v) > 1 {\n\t\t\treturn \"\", errors.Errorf(\"found more than one host-port binding for container '%s' (%s)\", container.Name, portBindingString(container.HostConfig.PortBindings))\n\t\t}\n\t\tif v[0].HostPort != \"\" {\n\t\t\tlog.Debug().Msgf(\"found host-port binding %s\", v[0].HostPort)\n\t\t\treturn v[0].HostPort, nil\n\t\t}\n\t}\n\n\t// check for a randomly set port via --publish-all\n\tif container.NetworkSettings != nil && len(container.NetworkSettings.Ports) == 1 {\n\t\tlog.Debug().Msg(\"looking for [randomly set] port in network settings\")\n\t\tfor _, v := range container.NetworkSettings.Ports {\n\t\t\tif len(v) > 0 {\n\t\t\t\tport := v[0].HostPort\n\t\t\t\tif port != \"\" {\n\t\t\t\t\tif len(v) > 1 {\n\t\t\t\t\t\tlog.Warn().Msgf(\"found %d port(s); trying the first one\", len(v))\n\t\t\t\t\t}\n\t\t\t\t\treturn port, nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tlog.Debug().Msg(\"skipping network settings check, no ports found\")\n\t}\n\n\treturn \"\", errors.Errorf(\"no host-port binding found for container '%s'\", container.Name)\n}\n\nfunc logJSON(name string, v interface{}) {\n\tlog.Debug().Func(func(e *zerolog.Event) {\n\t\tdata, err := json.MarshalIndent(v, \"\", \"  \")\n\t\tif err != nil {\n\t\t\te.Msgf(\"failed to marshal: %s\", err)\n\t\t} else {\n\t\t\te.Msgf(\"json dump of %s\", name)\n\t\t\tfmt.Println(string(data))\n\t\t}\n\t})\n}\n\n// Convert host:container port binding map to a compact printable string\nfunc portBindingString(bindings nat.PortMap) string {\n\ts := []string{}\n\tfor k, v := range bindings {\n\t\tif len(v) > 0 {\n\t\t\tcontainerPort := strings.TrimSuffix(string(k), \"/tcp\")\n\t\t\tcontainerPort = strings.TrimSuffix(string(containerPort), \"/udp\")\n\t\t\ts = append(s, fmt.Sprintf(\"%s:%s\", v[0].HostPort, containerPort))\n\t\t}\n\t}\n\treturn strings.Join(s, \", \")\n}\n\n// stripDocker removes the @docker suffix from a service name.\n// This is used to normalize service names when storing or retrieving them from the store.\nfunc stripDocker(svcName string) string {\n\treturn strings.TrimSuffix(svcName, \"@docker\")\n}\n"
  },
  {
    "path": "docker_helpers_test.go",
    "content": "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.com/docker/cli/cli/compose/loader\"\n\tcompose \"github.com/docker/cli/cli/compose/types\"\n\t\"github.com/docker/docker/api/types\"\n\t\"github.com/docker/docker/api/types/container\"\n\t\"github.com/docker/docker/api/types/events\"\n\t\"github.com/docker/docker/api/types/network\"\n\t\"github.com/docker/docker/api/types/swarm\"\n\t\"github.com/docker/go-connections/nat\"\n\t\"github.com/gofiber/fiber/v2\"\n\t\"github.com/gofiber/fiber/v2/middleware/logger\"\n\t\"github.com/ryanuber/go-glob\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n\t\"github.com/traefik/traefik/v3/pkg/safe\"\n\t\"github.com/traefik/traefik/v3/pkg/server\"\n)\n\ntype testStore struct {\n\tkv map[string]interface{}\n}\n\nfunc (s testStore) Ping() error {\n\treturn nil\n}\n\n// Add a method to push the last configuration if needed\nfunc (s *testStore) KeepConfAlive() error {\n\treturn nil\n}\n\nfunc (s *testStore) Get(key string) (string, error) {\n\tif s.kv == nil {\n\t\treturn \"\", nil\n\t}\n\tval, ok := s.kv[key]\n\tif !ok {\n\t\treturn \"\", nil\n\t}\n\tif val == nil {\n\t\treturn \"\", nil\n\t}\n\tstrVal, ok := val.(string)\n\tif !ok {\n\t\treturn fmt.Sprintf(\"%s\", val), nil\n\t}\n\treturn strVal, nil\n}\n\nfunc (s *testStore) Gets(key string) (map[string]string, error) {\n\tif s.kv == nil {\n\t\treturn nil, nil\n\t}\n\tvals := make(map[string]string)\n\tfor k, _ := range s.kv {\n\t\tif glob.Glob(key, k) {\n\t\t\tvals[k], _ = s.Get(k)\n\t\t}\n\t}\n\treturn vals, nil\n}\n\nfunc (s *testStore) Store(conf dynamic.Configuration) error {\n\tkv, err := ConfigToKV(conf)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif s.kv == nil {\n\t\ts.kv = kv\n\t} else {\n\t\t// merge kv into s.kv\n\t\tfor k, v := range kv {\n\t\t\ts.kv[k] = v\n\t\t}\n\t}\n\n\treturn nil\n}\n\ntype DockerAPIStub struct {\n\tcontainers     []container.Summary\n\tcontainersJSON map[string]container.InspectResponse\n}\n\nfunc (d DockerAPIStub) ServerVersion(ctx context.Context) (types.Version, error) {\n\t// Return a version that's compatible with both old and new Docker clients\n\treturn types.Version{\n\t\tVersion:    \"29.0.0\",\n\t\tAPIVersion: \"1.45\", // Compatible with Docker CE 29.0.0 and API negotiation\n\t}, nil\n}\n\nfunc (d DockerAPIStub) Events(ctx context.Context, options events.ListOptions) (<-chan events.Message, <-chan error) {\n\t// Implement your logic here\n\tfmt.Println(\"Events\")\n\treturn nil, nil\n}\n\nfunc (d DockerAPIStub) ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) {\n\t// Implement your logic here\n\tfmt.Println(\"ContainerList\")\n\treturn d.containers, nil\n}\n\nfunc (d DockerAPIStub) ContainerInspect(ctx context.Context, containerID string) (container.InspectResponse, error) {\n\t// Implement your logic here\n\tfmt.Println(\"ContainerInspect\", containerID)\n\treturn d.containersJSON[containerID], nil\n}\n\nfunc (d DockerAPIStub) ServiceList(ctx context.Context, options swarm.ServiceListOptions) ([]swarm.Service, error) {\n\t// Implement your logic here\n\tfmt.Println(\"ServiceList\")\n\treturn nil, nil\n}\n\nfunc (d DockerAPIStub) NetworkList(ctx context.Context, options network.ListOptions) ([]network.Summary, error) {\n\t// Implement your logic here\n\tfmt.Println(\"NetworkList\")\n\treturn nil, nil\n}\n\nfunc createHTTPServer() (*fiber.App, string) {\n\tapp := fiber.New()\n\tapp.Use(logger.New())\n\n\tapp.Get(\"/v*/version\", func(c *fiber.Ctx) error {\n\t\tversion, err := dockerAPI.ServerVersion(c.Context())\n\t\tif err != nil {\n\t\t\treturn c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{\"error\": err.Error()})\n\t\t}\n\t\treturn c.JSON(version)\n\t})\n\n\tapp.Get(\"/v*/containers/json\", func(c *fiber.Ctx) error {\n\t\tcontainers, err := dockerAPI.ContainerList(c.Context(), container.ListOptions{})\n\t\tif err != nil {\n\t\t\treturn c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{\"error\": err.Error()})\n\t\t}\n\t\treturn c.JSON(containers)\n\t})\n\n\tapp.Get(\"/v*/containers/:id/json\", func(c *fiber.Ctx) error {\n\t\tcontainer, err := dockerAPI.ContainerInspect(c.Context(), c.Params(\"id\"))\n\t\tif err != nil {\n\t\t\treturn c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{\"error\": err.Error()})\n\t\t}\n\t\t// fmt.Printf(\"returning container: %+v\\n\", container)\n\t\t// print container as json\n\t\t// json.NewEncoder((os.Stdout)).Encode(container)\n\t\treturn c.JSON(container)\n\t})\n\n\tapp.Get(\"/v*/events\", func(c *fiber.Ctx) error {\n\t\treturn nil\n\t})\n\n\tlistener, err := getAvailablePort()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tgo app.Listener(listener)\n\n\tdockerEndpoint := fmt.Sprintf(\"http://localhost:%d\", listener.Addr().(*net.TCPAddr).Port)\n\n\treturn app, dockerEndpoint\n}\n\nfunc buildConfigDetails(source map[string]any, env map[string]string) compose.ConfigDetails {\n\tworkingDir, err := os.Getwd()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\treturn compose.ConfigDetails{\n\t\tWorkingDir: workingDir,\n\t\tConfigFiles: []compose.ConfigFile{\n\t\t\t{Filename: \"filename.yml\", Config: source},\n\t\t},\n\t\tEnvironment: env,\n\t}\n}\n\nfunc loadYAML(yaml []byte) (*compose.Config, error) {\n\treturn loadYAMLWithEnv(yaml, nil)\n}\n\nfunc loadYAMLWithEnv(yaml []byte, env map[string]string) (*compose.Config, error) {\n\tdict, err := loader.ParseYAML(yaml)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn loader.Load(buildConfigDetails(dict, env))\n}\n\n// convert compose services to containers\nfunc createContainers(composeConfig *compose.Config) []container.Summary {\n\tcontainers := make([]container.Summary, 0)\n\tfor _, service := range composeConfig.Services {\n\t\tcontainer := container.Summary{\n\t\t\tID:     service.Name,\n\t\t\tLabels: service.Labels,\n\t\t\tState:  \"running\",\n\t\t\tStatus: \"running\",\n\t\t}\n\t\t// convert ports\n\t\tports := make([]types.Port, 0)\n\t\tfor _, port := range service.Ports {\n\t\t\tports = append(ports, types.Port{\n\t\t\t\tIP:          \"172.18.0.2\",\n\t\t\t\tPrivatePort: uint16(port.Target),\n\t\t\t\tPublicPort:  uint16(port.Published),\n\t\t\t\tType:        port.Protocol,\n\t\t\t})\n\t\t}\n\t\tcontainer.Ports = ports\n\t\tcontainers = append(containers, container)\n\t}\n\treturn containers\n}\n\n// convert compose services to containersJSON\nfunc createContainersJSON(composeConfig *compose.Config) map[string]container.InspectResponse {\n\tcontainersJSON := make(map[string]container.InspectResponse)\n\tfor _, service := range composeConfig.Services {\n\t\tcontainerJSON := container.InspectResponse{\n\t\t\tContainerJSONBase: &types.ContainerJSONBase{\n\t\t\t\tID:   service.Name,\n\t\t\t\tName: service.Name,\n\t\t\t\tState: &types.ContainerState{\n\t\t\t\t\tStatus:  \"running\",\n\t\t\t\t\tRunning: true,\n\t\t\t\t},\n\t\t\t\tHostConfig: &container.HostConfig{\n\t\t\t\t\tNetworkMode:  \"testing_default\", // network name\n\t\t\t\t\tPortBindings: nat.PortMap{},\n\t\t\t\t},\n\t\t\t},\n\t\t\tConfig: &container.Config{\n\t\t\t\tLabels: service.Labels,\n\t\t\t},\n\t\t\tNetworkSettings: &types.NetworkSettings{\n\t\t\t\tNetworks: map[string]*network.EndpointSettings{\n\t\t\t\t\t\"testing_default\": {\n\t\t\t\t\t\tNetworkID: \"testing_default\", // should normally look like a random id but we can reuse the name here\n\t\t\t\t\t\tIPAddress: \"172.18.0.2\",\n\t\t\t\t\t},\n\t\t\t\t\t\"foobar\": {\n\t\t\t\t\t\tNetworkID: \"foobar\",\n\t\t\t\t\t\tIPAddress: \"10.10.10.5\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\t// add port bindings\n\t\tfor _, port := range service.Ports {\n\t\t\tportID := nat.Port(fmt.Sprintf(\"%d/%s\", port.Published, port.Protocol))\n\t\t\tcontainerJSON.HostConfig.PortBindings[portID] = []nat.PortBinding{\n\t\t\t\t{\n\t\t\t\t\tHostIP:   \"\",\n\t\t\t\t\tHostPort: fmt.Sprintf(\"%d\", port.Published),\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\tcontainerJSON.NetworkSettings.Ports = containerJSON.HostConfig.PortBindings\n\t\tfor portID, mappings := range containerJSON.NetworkSettings.Ports {\n\t\t\tfor i, mapping := range mappings {\n\t\t\t\tif mapping.HostPort == \"0\" {\n\t\t\t\t\t// Emulating random port assignment for testing\n\t\t\t\t\tcontainerJSON.NetworkSettings.Ports[portID][i].HostPort = \"12345\"\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcontainersJSON[service.Name] = containerJSON\n\t}\n\treturn containersJSON\n}\n\nfunc processFile(t *testing.T, file ...string) TraefikStore {\n\tstore := &testStore{}\n\tfor _, f := range file {\n\t\tprocessFileWithConfig(t, store, nil, f)\n\t}\n\treturn store\n}\n\nfunc processFileWithConfig(t *testing.T, store TraefikStore, config *Config, file string) TraefikStore {\n\tp := path.Join(\"fixtures\", file)\n\tf, err := os.Open(p)\n\tassert.NoError(t, err)\n\tif err != nil {\n\t\tt.FailNow()\n\t}\n\n\tb, err := io.ReadAll(f)\n\tassert.NoError(t, err)\n\n\tcomposeConfig, err := loadYAML(b)\n\tassert.NoError(t, err)\n\n\tif store == nil {\n\t\tstore = &testStore{}\n\t}\n\n\t// fmt.Printf(\"%+v\\n\", composeConfig)\n\n\tdockerAPI.containers = createContainers(composeConfig)\n\tdockerAPI.containersJSON = createContainersJSON(composeConfig)\n\n\tif config == nil {\n\t\tconfig = &Config{\n\t\t\tBindIP: \"192.168.100.100\",\n\t\t}\n\t} else {\n\t\tconfig.BindIP = \"192.168.100.100\"\n\t}\n\tif config.DockerHost == \"\" {\n\t\tconfig.DockerHost = dockerEndpoint\n\t}\n\n\tdp := newDockerProvider(*config)\n\thandleConfigChange := createConfigHandler(*config, store, dp, dc)\n\n\troutinesPool := safe.NewPool(context.Background())\n\twatcher := server.NewConfigurationWatcher(\n\t\troutinesPool,\n\t\tdp,\n\t\t[]string{},\n\t\t\"docker\",\n\t)\n\twatcher.AddListener(handleConfigChange)\n\n\t// ensure we get exactly one change\n\twgChanges := sync.WaitGroup{}\n\twgChanges.Add(1)\n\twatcher.AddListener(func(c dynamic.Configuration) {\n\t\twgChanges.Done()\n\t})\n\n\twatcher.Start()\n\tdefer watcher.Stop()\n\n\twgChanges.Wait()\n\n\tif ts, ok := store.(*testStore); ok {\n\t\t// print the kv store with sorted keys\n\t\tfmt.Println(\"printing kv store after processing file:\", file)\n\t\tkeys := make([]string, 0, len(ts.kv))\n\t\tfor k := range ts.kv {\n\t\t\tkeys = append(keys, k)\n\t\t}\n\t\tsort.Strings(keys)\n\t\tfor _, k := range keys {\n\t\t\tfmt.Printf(\"%s: %+v\\n\", k, ts.kv[k])\n\t\t}\n\t}\n\n\treturn store\n}\n\nfunc assertServiceIP(t *testing.T, store *testStore, serviceName string, ip string) {\n\tassert.Equal(t, ip, store.kv[fmt.Sprintf(\"traefik/http/services/%s/loadBalancer/servers/0/url\", serviceName)])\n}\n\ntype svc struct {\n\tname  string\n\tproto string\n\tip    string\n}\n\nfunc assertServiceIPs(t *testing.T, store TraefikStore, svcs []svc) {\n\tfor _, svc := range svcs {\n\t\tpath := \"url\"\n\t\tif svc.proto != \"http\" {\n\t\t\tpath = \"address\"\n\t\t}\n\t\tkey := fmt.Sprintf(\"traefik/%s/services/%s/loadBalancer/servers/0/%s\", svc.proto, svc.name, path)\n\t\tval, err := store.Get(key)\n\t\tassert.NoError(t, err)\n\t\tassert.Equal(t,\n\t\t\tsvc.ip,\n\t\t\tval,\n\t\t\t\"service %s has wrong IP at key: %s\",\n\t\t\tsvc,\n\t\t\tkey,\n\t\t)\n\t}\n}\n"
  },
  {
    "path": "docker_proxy.go",
    "content": "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/docker/api/types/container\"\n\t\"github.com/docker/docker/api/types/events\"\n\t\"github.com/docker/docker/api/types/filters\"\n\t\"github.com/docker/docker/client\"\n\t\"github.com/gofiber/fiber/v2\"\n\t\"github.com/gofiber/fiber/v2/middleware/logger\"\n\t\"github.com/rs/zerolog/log\"\n\t\"github.com/valyala/fasthttp\"\n)\n\nfunc getAvailablePort() (net.Listener, error) {\n\taddr, err := net.ResolveTCPAddr(\"tcp\", \"localhost:0\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tl, err := net.ListenTCP(\"tcp\", addr)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn l, nil\n}\n\n// DockerProxyServer is a proxy server that filters docker labels based on a prefix\ntype DockerProxyServer struct {\n\tupstream    client.APIClient\n\tlabelPrefix string\n}\n\nfunc createProxy(upstream client.APIClient, labelPrefix string) *DockerProxyServer {\n\tif labelPrefix != \"\" && !strings.HasSuffix(labelPrefix, \".\") {\n\t\tlabelPrefix += \".\"\n\t}\n\treturn &DockerProxyServer{\n\t\tupstream:    upstream,\n\t\tlabelPrefix: labelPrefix,\n\t}\n}\n\nfunc (s *DockerProxyServer) filterLabels(labels map[string]string) map[string]string {\n\tif s.labelPrefix == \"\" || labels == nil {\n\t\treturn labels\n\t}\n\n\tnewLabels := make(map[string]string)\n\n\tfor k, v := range labels {\n\t\tif strings.HasPrefix(k, s.labelPrefix) {\n\t\t\t// strip prefix from our labels\n\t\t\tnewKey := strings.TrimPrefix(k, s.labelPrefix)\n\t\t\tnewLabels[newKey] = v\n\t\t} else if !strings.HasPrefix(k, \"traefik.\") {\n\t\t\t// keep every other than traefik.* labels as is\n\t\t\tnewLabels[k] = v\n\t\t}\n\t}\n\n\treturn newLabels\n}\n\nfunc (s *DockerProxyServer) handleVersion(c *fiber.Ctx) error {\n\tv, err := s.upstream.ServerVersion(context.Background())\n\tif err != nil {\n\t\treturn c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{\"error\": err.Error()})\n\t}\n\treturn c.JSON(v)\n}\n\nfunc (s *DockerProxyServer) handleContainersList(c *fiber.Ctx) error {\n\tcontainers, err := s.upstream.ContainerList(context.Background(), container.ListOptions{})\n\tif err != nil {\n\t\treturn c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{\"error\": err.Error()})\n\t}\n\n\t// modify labels\n\tfor _, container := range containers {\n\t\tcontainer.Labels = s.filterLabels(container.Labels)\n\t}\n\n\treturn c.JSON(containers)\n}\n\nfunc (s *DockerProxyServer) handleContainerInspect(c *fiber.Ctx) error {\n\tcontainer, err := s.upstream.ContainerInspect(context.Background(), c.Params(\"id\"))\n\tif err != nil {\n\t\treturn c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{\"error\": err.Error()})\n\t}\n\n\tif container.Config != nil {\n\t\tcontainer.Config.Labels = s.filterLabels(container.Config.Labels)\n\t}\n\n\treturn c.JSON(container)\n}\n\nfunc (s *DockerProxyServer) handleEvents(c *fiber.Ctx) error {\n\tvar fa filters.Args\n\tf := c.Query(\"filters\")\n\tif f != \"\" {\n\t\tvar err error\n\t\tfa, err = filters.FromJSON(f)\n\t\tif err != nil {\n\t\t\treturn c.Status(fiber.StatusBadRequest).JSON(fiber.Map{\"error\": err.Error()})\n\t\t}\n\t}\n\n\teventsCh, errCh := s.upstream.Events(context.Background(), events.ListOptions{Filters: fa})\n\n\tc.Status(fiber.StatusOK).Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {\n\t\tencoder := json.NewEncoder(w)\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase event := <-eventsCh:\n\t\t\t\tif event.Type == \"container\" && event.Actor.Attributes != nil {\n\t\t\t\t\tevent.Actor.Attributes = s.filterLabels(event.Actor.Attributes)\n\t\t\t\t}\n\n\t\t\t\terr := encoder.Encode(event)\n\t\t\t\tif err != nil {\n\t\t\t\t\tlog.Error().Msgf(\"Error encoding event: %v\", err)\n\t\t\t\t}\n\t\t\tcase err := <-errCh:\n\t\t\t\tif err != nil {\n\t\t\t\t\te := encoder.Encode(err)\n\t\t\t\t\tif e != nil {\n\t\t\t\t\t\tlog.Error().Msgf(\"Error encoding error: %v\", e)\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\terr := w.Flush()\n\t\t\tif err != nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}))\n\n\treturn nil\n}\n\nfunc (s *DockerProxyServer) handleNotFound(c *fiber.Ctx) error {\n\tlog.Warn().Msgf(\"Unhandled request: %s %s\", c.Method(), c.OriginalURL())\n\treturn c.Status(fiber.StatusNotFound).SendString(\"Not Found\")\n}\n\nfunc (s *DockerProxyServer) start() (*fiber.App, string) {\n\tapp := fiber.New(fiber.Config{DisableStartupMessage: true})\n\tif os.Getenv(\"DEBUG\") != \"\" {\n\t\tapp.Use(logger.New())\n\t}\n\n\tapp.All(\"/_ping\", func(ctx *fiber.Ctx) error { return ctx.SendStatus(fiber.StatusNoContent) })\n\tapp.Get(\"/v*/version\", s.handleVersion)\n\tapp.Get(\"/v*/containers/json\", s.handleContainersList)\n\tapp.Get(\"/v*/containers/:id/json\", s.handleContainerInspect)\n\tapp.Get(\"/v*/events\", s.handleEvents)\n\tapp.All(\"/*\", s.handleNotFound)\n\n\tlistener, err := getAvailablePort()\n\tif err != nil {\n\t\tlog.Fatal().Err(err)\n\t}\n\n\tgo app.Listener(listener)\n\n\tdockerEndpoint := fmt.Sprintf(\"http://localhost:%d\", listener.Addr().(*net.TCPAddr).Port)\n\tlog.Debug().Msgf(\"Started docker proxy at %s with label prefix '%s'\", dockerEndpoint, s.labelPrefix)\n\n\treturn app, dockerEndpoint\n}\n"
  },
  {
    "path": "docker_proxy_test.go",
    "content": "package traefikkop\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/assert\"\n)\n\nfunc Test_dockerProxyServerNoPrefix(t *testing.T) {\n\tmockDockerEndpoint := dockerEndpoint\n\tmockDockerClient := dc\n\n\t// now create our proxy pointing to the mock\n\tproxyServer := createProxy(mockDockerClient, \"\")\n\t_, proxyDockerEndpoint := proxyServer.start()\n\n\tvar err error\n\tdockerEndpoint = proxyDockerEndpoint\n\tdc, err = createDockerClient(proxyDockerEndpoint)\n\tassert.NoError(t, err, \"should create docker client\")\n\tdefer func() {\n\t\tdockerEndpoint = mockDockerEndpoint\n\t\tdc = mockDockerClient\n\t}()\n\n\t// both services get mapped to the same port (error case)\n\tstore := processFile(t, \"hellodetect.yml\")\n\tprocessFileWithConfig(t, store, nil, \"docker-prefix.yml\")\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello-detect\", \"http\", \"http://192.168.100.100:5577\"},\n\t\t{\"hello-detect2\", \"http\", \"http://192.168.100.100:5577\"},\n\t})\n\tassert.NotEmpty(t, g(store, fmt.Sprintf(\"traefik/http/routers/%s/service\", \"hello-detect2\")))\n\tassert.Empty(t, g(store, fmt.Sprintf(\"traefik/http/routers/%s/service\", \"prefixed\")))\n}\n\nfunc Test_dockerProxyServerPrefix(t *testing.T) {\n\tmockDockerEndpoint := dockerEndpoint\n\tmockDockerClient := dc\n\n\t// now create our proxy pointing to the mock\n\tproxyServer := createProxy(mockDockerClient, \"foo\")\n\t_, proxyDockerEndpoint := proxyServer.start()\n\n\tvar err error\n\tdockerEndpoint = proxyDockerEndpoint\n\tdc, err = createDockerClient(proxyDockerEndpoint)\n\tassert.NoError(t, err, \"should create docker client\")\n\tdefer func() {\n\t\tdockerEndpoint = mockDockerEndpoint\n\t\tdc = mockDockerClient\n\t}()\n\n\t// both services get mapped to the same port (error case)\n\tstore := processFile(t, \"hellodetect.yml\")\n\tprocessFileWithConfig(t, store, nil, \"docker-prefix.yml\")\n\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"prefixed\", \"http\", \"http://192.168.100.100:5588\"},\n\t})\n\n\tassert.Empty(t, g(store, fmt.Sprintf(\"traefik/http/routers/%s/service\", \"hello-detect2\")))\n\tassert.NotEmpty(t, g(store, fmt.Sprintf(\"traefik/http/routers/%s/service\", \"prefixed\")))\n}\n\n// test that services with kop.bind.ip or foo.kop.bind.ip labels are handled correctly\nfunc Test_dockerProxyServerPrefixWithKopBindIP(t *testing.T) {\n\tmockDockerEndpoint := dockerEndpoint\n\tmockDockerClient := dc\n\n\t// now create our proxy pointing to the mock\n\tproxyServer := createProxy(mockDockerClient, \"foo\")\n\t_, proxyDockerEndpoint := proxyServer.start()\n\n\tvar err error\n\tdockerEndpoint = proxyDockerEndpoint\n\tdc, err = createDockerClient(proxyDockerEndpoint)\n\tassert.NoError(t, err, \"should create docker client\")\n\tdefer func() {\n\t\tdockerEndpoint = mockDockerEndpoint\n\t\tdc = mockDockerClient\n\t}()\n\n\t// both services get mapped to the same port (error case)\n\tstore := processFile(t, \"hellodetect.yml\")\n\tprocessFileWithConfig(t, store, nil, \"prefix-bindip.yml\")\n\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"prefixed\", \"http\", \"http://foo.bar.baz:5588\"},\n\t\t{\"unprefixed\", \"http\", \"http://example.local:5599\"},\n\t})\n\n\tassert.Empty(t, g(store, fmt.Sprintf(\"traefik/http/routers/%s/service\", \"hello-detect2\")))\n\tassert.NotEmpty(t, g(store, fmt.Sprintf(\"traefik/http/routers/%s/service\", \"prefixed\")))\n}\n"
  },
  {
    "path": "docker_test.go",
    "content": "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/fiber/v2\"\n\t\"github.com/stretchr/testify/assert\"\n)\n\nvar app *fiber.App\nvar dockerEndpoint string\nvar dc client.APIClient\nvar dockerAPI = &DockerAPIStub{}\n\nfunc setup() {\n\tos.Unsetenv(\"DOCKER_HOST\") // make sure this doesn't interfere with our client setup\n\tapp, dockerEndpoint = createHTTPServer()\n\tvar err error\n\tdc, err = createDockerClient(dockerEndpoint)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc teardown() {\n\terr := app.Shutdown()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n\nfunc TestMain(m *testing.M) {\n\tsetup()\n\n\tcode := m.Run()\n\n\tteardown()\n\n\tos.Exit(code)\n}\n\nfunc Test_httpServerVersion(t *testing.T) {\n\tv, err := dc.ServerVersion(context.Background())\n\tassert.NoError(t, err)\n\tassert.Equal(t, \"29.0.0\", v.Version)\n\tassert.Equal(t, \"1.45\", v.APIVersion)\n}\n\nfunc Test_helloWorld(t *testing.T) {\n\tstore := processFile(t, \"helloworld.yml\")\n\n\tassert.NotNil(t, store)\n\n\tassert.Equal(t, \"hello1\", g(store, \"traefik/http/routers/hello1/service\"))\n\tassert.Equal(t, \"hello2\", g(store, \"traefik/http/routers/hello2/service\"))\n\tassert.NotEmpty(t, g(store, \"traefik/http/routers/hello1/tls/certResolver\"))\n\tassert.NotEmpty(t, g(store, \"traefik/http/routers/hello2/tls/certResolver\"))\n\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello1\", \"http\", \"http://192.168.100.100:5555\"},\n\t\t{\"hello2\", \"http\", \"http://192.168.100.100:5566\"},\n\t})\n\n\t// assertServiceIP(t, store, \"hello1\", \"http://192.168.100.100:5555\")\n\t// assert.Equal(t, \"http://192.168.100.100:5555\", g(store, \"traefik/http/services/hello1/loadBalancer/servers/0/url\"))\n\t// assert.Equal(t, \"http://192.168.100.100:5566\", g(store, \"traefik/http/services/hello2/loadBalancer/servers/0/url\"))\n}\n\nfunc Test_helloDetect(t *testing.T) {\n\t// both services get mapped to the same port (error case)\n\tstore := processFile(t, \"hellodetect.yml\")\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello-detect\", \"http\", \"http://192.168.100.100:5577\"},\n\t\t{\"hello-detect2\", \"http\", \"http://192.168.100.100:5577\"},\n\t})\n}\n\nfunc Test_helloIP(t *testing.T) {\n\t// override ip via labels\n\tstore := processFile(t, \"helloip.yml\")\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"helloip\", \"http\", \"http://4.4.4.4:5599\"},\n\t\t{\"helloip2\", \"http\", \"http://3.3.3.3:5599\"},\n\t})\n}\n\nfunc Test_helloNetwork(t *testing.T) {\n\t// use ip from specific docker network\n\tstore := processFile(t, \"network.yml\")\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello1\", \"http\", \"http://10.10.10.5:5555\"},\n\t})\n}\n\nfunc Test_TCP(t *testing.T) {\n\t// tcp service\n\tstore := processFile(t, \"gitea.yml\")\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"gitea-ssh\", \"tcp\", \"192.168.100.100:20022\"},\n\t})\n}\n\nfunc Test_TCPMQTT(t *testing.T) {\n\t// from https://github.com/jittering/traefik-kop/issues/35\n\tstore := processFile(t, \"mqtt.yml\")\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"mqtt\", \"http\", \"http://192.168.100.100:9001\"},\n\t\t{\"mqtt\", \"tcp\", \"192.168.100.100:1883\"},\n\t})\n}\n\nfunc Test_helloWorldNoCert(t *testing.T) {\n\tstore := processFile(t, \"hello-no-cert.yml\")\n\n\tassert.Equal(t, \"hello1\", g(store, \"traefik/http/routers/hello1/service\"))\n\tassert.Empty(t, g(store, \"traefik/http/routers/hello1/tls/certResolver\"))\n\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello1\", \"http\", \"http://192.168.100.100:5555\"},\n\t})\n}\n\nfunc Test_routerTLSWithoutCertResolver(t *testing.T) {\n\tstore := processFile(t, \"musicassistant-tls.yml\")\n\n\tassert.Equal(t, \"true\", g(store, \"traefik/http/routers/musicassistant/tls\"))\n}\n\nfunc g(s TraefikStore, k string) string {\n\tv, err := s.Get(k)\n\tif err != nil {\n\t\treturn \"\"\n\t}\n\treturn v\n}\n\nfunc Test_helloWorldIgnore(t *testing.T) {\n\tstore := processFile(t, \"hello-ignore.yml\")\n\tassert.Empty(t, g(store, \"traefik/http/routers/hello1/service\"))\n\n\tstore = processFileWithConfig(t, nil, &Config{Namespace: []string{\"foobar\"}}, \"hello-ignore.yml\")\n\tassert.Equal(t, \"hello1\", g(store, \"traefik/http/routers/hello1/service\"))\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello1\", \"http\", \"http://192.168.100.100:5555\"},\n\t})\n}\n\nfunc Test_helloWorldMultiNS(t *testing.T) {\n\tstore := processFile(t, \"hello-multi-ns.yml\")\n\tassert.Empty(t, g(store, \"traefik/http/routers/hello1/service\"))\n\n\tstore = processFileWithConfig(t, nil, &Config{Namespace: []string{\"foobar\"}}, \"hello-multi-ns.yml\")\n\tassert.Equal(t, \"hello1\", g(store, \"traefik/http/routers/hello1/service\"))\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello1\", \"http\", \"http://192.168.100.100:5555\"},\n\t})\n\n\tstore = processFileWithConfig(t, nil, &Config{Namespace: []string{\"xyz\"}}, \"hello-multi-ns.yml\")\n\tassert.Equal(t, \"hello1\", g(store, \"traefik/http/routers/hello1/service\"))\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello1\", \"http\", \"http://192.168.100.100:5555\"},\n\t})\n\n\tstore = processFileWithConfig(t, nil, &Config{Namespace: []string{\"foobar\", \"xyz\"}}, \"hello-multi-ns.yml\")\n\tassert.Equal(t, \"hello1\", g(store, \"traefik/http/routers/hello1/service\"))\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello1\", \"http\", \"http://192.168.100.100:5555\"},\n\t})\n\n\tstore = processFileWithConfig(t, nil, &Config{Namespace: []string{\"abc\"}}, \"hello-multi-ns.yml\")\n\tassert.Empty(t, g(store, \"traefik/http/routers/hello1/service\"))\n}\n\nfunc Test_helloWorldAutoMapped(t *testing.T) {\n\tstore := processFile(t, \"hello-automapped.yml\")\n\tassert.Equal(t, \"hello\", g(store, \"traefik/http/routers/hello/service\"))\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello\", \"http\", \"http://192.168.100.100:12345\"},\n\t})\n}\n\nfunc Test_samePrefix(t *testing.T) {\n\tstore := processFile(t, \"prefix.yml\")\n\n\t// Two services `hello` and `hello-test`.\n\t// The former's name is a prefix of the latter. Ensure the matching does not mix them up.\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello\", \"http\", \"http://192.168.100.100:5555\"},\n\t\t{\"hello-test\", \"http\", \"http://192.168.100.100:5566\"},\n\t})\n}\n\n// Should be able to merge loadbalanced services\nfunc Test_loadbalance(t *testing.T) {\n\tstore := processFile(t, \"loadbalance1.yml\", \"loadbalance2.yml\")\n\n\turl1 := g(store, \"traefik/http/services/lbtest/loadBalancer/servers/0/url\")\n\turl2 := g(store, \"traefik/http/services/lbtest/loadBalancer/servers/1/url\")\n\n\tassert.NotEmpty(t, url1)\n\tassert.NotEmpty(t, url2)\n\n\turls := []string{url1, url2}\n\n\tassert.Contains(t, urls, \"http://192.168.100.100:5555\")\n\tassert.Contains(t, urls, \"http://192.168.100.100:5556\")\n}\n"
  },
  {
    "path": "fixtures/docker-prefix.yml",
    "content": "services:\n  # test labels with a prefix, i.e., DOCKER_PREFIX=foo.\n  dockerprefix:\n    restart: unless-stopped\n    ports:\n      - 5588:5588\n    labels:\n      - \"foo.traefik.enable=true\"\n      - \"foo.traefik.http.routers.prefixed.rule=Host(`hello-prefix.local`)\"\n      - \"foo.traefik.http.routers.prefixed.service=prefixed\"\n      - \"foo.traefik.http.routers.prefixed.tls=true\"\n      - \"foo.traefik.http.routers.prefixed.tls.certresolver=default\"\n      - \"foo.traefik.http.services.prefixed.loadbalancer.server.scheme=http\"\n"
  },
  {
    "path": "fixtures/gitea.yml",
    "content": "services:\n  gitea:\n    image: gitea/gitea\n    labels:\n      traefik.enable: \"true\"\n      traefik.http.routers.gitea.rule: \"Host(`git.domain`)\"\n      traefik.http.routers.gitea.entrypoints: webs\n      traefik.http.routers.gitea.service: gitea@redis\n      traefik.http.services.gitea.loadbalancer.server.port: 20080\n\n      traefik.tcp.routers.gitea-ssh.rule: \"HostSNI(`*`)\"\n      traefik.tcp.routers.gitea-ssh.entrypoints: ssh\n      traefik.tcp.routers.gitea-ssh.service: gitea-ssh@redis\n      traefik.tcp.services.gitea-ssh.loadbalancer.server.port: 20022\n"
  },
  {
    "path": "fixtures/hello-automapped.yml",
    "content": "\nservices:\n  hello:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello.rule=Host(`hello.local`)\"\n      - \"traefik.http.routers.hello.service=hello\"\n      - \"traefik.http.routers.hello.tls=true\"\n      - \"traefik.http.routers.hello.tls.certresolver=default\"\n"
  },
  {
    "path": "fixtures/hello-ignore.yml",
    "content": "\nservices:\n  helloworld:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n      - 5566:5566\n    labels:\n      - \"kop.namespace=foobar\"\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello1.rule=Host(`hello1.local`)\"\n      - \"traefik.http.routers.hello1.service=hello1\"\n      - \"traefik.http.routers.hello1.tls=true\"\n      - \"traefik.http.routers.hello1.tls.certresolver=default\"\n      - \"traefik.http.services.hello1.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello1.loadbalancer.server.port=5555\"\n"
  },
  {
    "path": "fixtures/hello-multi-ns.yml",
    "content": "\nservices:\n  helloworld:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n      - 5566:5566\n    labels:\n      - \"kop.namespace=foobar,xyz\"\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello1.rule=Host(`hello1.local`)\"\n      - \"traefik.http.routers.hello1.service=hello1\"\n      - \"traefik.http.routers.hello1.tls=true\"\n      - \"traefik.http.routers.hello1.tls.certresolver=default\"\n      - \"traefik.http.services.hello1.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello1.loadbalancer.server.port=5555\"\n"
  },
  {
    "path": "fixtures/hello-no-cert.yml",
    "content": "\nservices:\n  helloworld:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n      - 5566:5566\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello1.rule=Host(`hello1.local`)\"\n      - \"traefik.http.routers.hello1.service=hello1\"\n      - \"traefik.http.routers.hello1.tls=true\"\n      # - \"traefik.http.routers.hello1.tls.certresolver=default\"\n      - \"traefik.http.services.hello1.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello1.loadbalancer.server.port=5555\"\n"
  },
  {
    "path": "fixtures/hellodetect.yml",
    "content": "services:\n  # This service is the same as above except that it does not have a label\n  # which explicitly maps the port and so it fails to correctly determine which\n  # port to tell traefik to connect to. i.e., both services connect to 5555.\n  #\n  # This scenario will *not* be handled correctly by traefik-kop as we have no\n  # fallback way to determine the port.\n  hellodetect:\n    build:\n      dockerfile: ./helloworld/Dockerfile\n      context: ./\n    restart: unless-stopped\n    ports:\n      - 5577:5555\n      - 5588:5566\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello-detect.rule=Host(`hello-detect.local`)\"\n      - \"traefik.http.routers.hello-detect.service=hello-detect\"\n      - \"traefik.http.routers.hello-detect.tls=true\"\n      - \"traefik.http.routers.hello-detect.tls.certresolver=default\"\n      - \"traefik.http.services.hello-detect.loadbalancer.server.scheme=http\"\n      - \"traefik.http.routers.hello-detect2.rule=Host(`hello-detect2.local`)\"\n      - \"traefik.http.routers.hello-detect2.service=hello-detect2\"\n      - \"traefik.http.routers.hello-detect2.tls=true\"\n      - \"traefik.http.routers.hello-detect2.tls.certresolver=default\"\n      - \"traefik.http.services.hello-detect2.loadbalancer.server.scheme=http\"\n"
  },
  {
    "path": "fixtures/helloip.yml",
    "content": "services:\n  helloip:\n    build:\n      dockerfile: ./helloworld/Dockerfile\n      context: ./\n    restart: unless-stopped\n    ports:\n      - 5599:5555\n    labels:\n      # override ip for a specific service (helloip)\n      - \"kop.helloip.bind.ip=4.4.4.4\"\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.helloip.rule=Host(`helloip.local`)\"\n      - \"traefik.http.routers.helloip.service=helloip\"\n      - \"traefik.http.routers.helloip.tls=true\"\n      - \"traefik.http.routers.helloip.tls.certresolver=default\"\n      - \"traefik.http.services.helloip.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.helloip.loadbalancer.server.port=5599\"\n\n  helloip2:\n    build:\n      dockerfile: ./helloworld/Dockerfile\n      context: ./\n    restart: unless-stopped\n    ports:\n      - 5599:5555\n    labels:\n      # override without service name (assumes single service or same ip for all services)\n      - \"kop.bind.ip=3.3.3.3\"\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.helloip2.rule=Host(`helloip2.local`)\"\n      - \"traefik.http.routers.helloip2.service=helloip2\"\n      - \"traefik.http.routers.helloip2.tls=true\"\n      - \"traefik.http.routers.helloip2.tls.certresolver=default\"\n      - \"traefik.http.services.helloip2.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.helloip2.loadbalancer.server.port=5599\"\n"
  },
  {
    "path": "fixtures/helloworld.yml",
    "content": "\nservices:\n  helloworld:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n      - 5566:5566\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello1.rule=Host(`hello1.local`)\"\n      - \"traefik.http.routers.hello1.service=hello1\"\n      - \"traefik.http.routers.hello1.tls=true\"\n      - \"traefik.http.routers.hello1.tls.certresolver=default\"\n      - \"traefik.http.services.hello1.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello1.loadbalancer.server.port=5555\"\n      - \"traefik.http.routers.hello2.rule=Host(`hello2.local`)\"\n      - \"traefik.http.routers.hello2.service=hello2\"\n      - \"traefik.http.routers.hello2.tls=true\"\n      - \"traefik.http.routers.hello2.tls.certresolver=default\"\n      - \"traefik.http.services.hello2.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello2.loadbalancer.server.port=5566\"\n"
  },
  {
    "path": "fixtures/loadbalance1.yml",
    "content": "services:\n  lb1:\n    image: helloworld\n    build: \"../helloworld\"\n    restart: \"no\"\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.lb1.rule=Host(`lb.local`)\"\n      - \"traefik.http.routers.lb1.service=lbtest\"\n      - \"traefik.http.routers.lb1.tls=true\"\n      - \"traefik.http.routers.lb1.tls.certresolver=default\"\n      - \"traefik.http.services.lbtest.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.lbtest.loadbalancer.server.port=5555\"\n      - \"traefik.merge-lbs=true\"\n"
  },
  {
    "path": "fixtures/loadbalance2.yml",
    "content": "services:\n  lb2:\n    image: helloworld\n    build: \"../helloworld\"\n    restart: \"no\"\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.lb1.rule=Host(`lb.local`)\"\n      - \"traefik.http.routers.lb1.service=lbtest\"\n      - \"traefik.http.routers.lb1.tls=true\"\n      - \"traefik.http.routers.lb1.tls.certresolver=default\"\n      - \"traefik.http.services.lbtest.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.lbtest.loadbalancer.server.port=5556\"\n      - \"traefik.merge-lbs=true\"\n"
  },
  {
    "path": "fixtures/mqtt.yml",
    "content": "services:\n  gitea:\n    image: gitea/gitea\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.mqtt.rule=Host(`mqtt.local`)\"\n      - \"traefik.http.services.mqtt.loadbalancer.server.port=9001\"\n      # MQTT routing\n      - \"traefik.tcp.routers.mqtt.rule=HostSNI(`*`)\"\n      - \"traefik.tcp.routers.mqtt.entrypoints=mqtt\"\n      - \"traefik.tcp.routers.mqtt.service=service-broker-mqtt\"\n      - \"traefik.tcp.services.mqtt.loadbalancer.server.port=1883\"\n"
  },
  {
    "path": "fixtures/musicassistant-tls.yml",
    "content": "services:\n  musicassistant:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.musicassistant.rule=Host(`musicassistant.example.com`)\"\n      - \"traefik.http.routers.musicassistant.entrypoints=websecure\"\n      - \"traefik.http.routers.musicassistant.tls=true\"\n"
  },
  {
    "path": "fixtures/network.yml",
    "content": "\nservices:\n  helloworld:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n      - 5566:5566\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.docker.network=foobar\"\n      - \"traefik.http.routers.hello1.rule=Host(`hello1.local`)\"\n      - \"traefik.http.routers.hello1.service=hello1\"\n      - \"traefik.http.routers.hello1.tls=true\"\n      - \"traefik.http.routers.hello1.tls.certresolver=default\"\n      - \"traefik.http.services.hello1.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello1.loadbalancer.server.port=5555\"\n"
  },
  {
    "path": "fixtures/prefix-bindip.yml",
    "content": "services:\n  # test labels with a prefix, i.e., DOCKER_PREFIX=foo.\n  dockerprefix:\n    image: nginx\n    restart: \"no\"\n    ports:\n      - 5588:80\n    labels:\n      - \"foo.traefik.enable=true\"\n      - \"foo.traefik.http.routers.prefixed.rule=Host(`hello-prefix.local`)\"\n      - \"foo.traefik.http.routers.prefixed.service=prefixed\"\n      - \"foo.traefik.http.routers.prefixed.tls=true\"\n      - \"foo.traefik.http.routers.prefixed.tls.certresolver=default\"\n      - \"foo.traefik.http.services.prefixed.loadbalancer.server.scheme=http\"\n      - \"foo.kop.bind.ip=foo.bar.baz\"\n  dockerprefix2:\n    image: nginx\n    restart: \"no\"\n    ports:\n      - 5599:80\n    labels:\n      - \"foo.traefik.enable=true\"\n      - \"foo.traefik.http.routers.unprefixed.rule=Host(`hello-prefix2.local`)\"\n      - \"foo.traefik.http.routers.unprefixed.service=unprefixed\"\n      - \"foo.traefik.http.routers.unprefixed.tls=true\"\n      - \"foo.traefik.http.routers.unprefixed.tls.certresolver=default\"\n      - \"foo.traefik.http.services.unprefixed.loadbalancer.server.scheme=http\"\n      - \"kop.bind.ip=example.local\"\n"
  },
  {
    "path": "fixtures/prefix.yml",
    "content": "\nservices:\n  hello:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello.rule=Host(`hello.local`)\"\n      - \"traefik.http.routers.hello.service=hello\"\n      - \"traefik.http.routers.hello.tls=true\"\n      - \"traefik.http.routers.hello.tls.certresolver=default\"\n      - \"traefik.http.services.hello.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello.loadbalancer.server.port=5555\"\n\n  hello-test:\n    image: helloworld\n    restart: unless-stopped\n    ports:\n      - 5566:5566\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello-test.rule=Host(`hello-test.local`)\"\n      - \"traefik.http.routers.hello-test.service=hello-test\"\n      - \"traefik.http.routers.hello-test.tls=true\"\n      - \"traefik.http.routers.hello-test.tls.certresolver=default\"\n      - \"traefik.http.services.hello-test.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello-test.loadbalancer.server.port=5566\"\n"
  },
  {
    "path": "fixtures/sample.toml",
    "content": "[global]\n  checkNewVersion = true\n  sendAnonymousUsage = true\n\n[serversTransport]\n  insecureSkipVerify = true\n  rootCAs = [\"foobar\", \"foobar\"]\n  maxIdleConnsPerHost = 42\n  [serversTransport.forwardingTimeouts]\n    dialTimeout = 42\n    responseHeaderTimeout = 42\n    idleConnTimeout = 42\n\n[entryPoints]\n  [entryPoints.EntryPoint0]\n    address = \"foobar\"\n    [entryPoints.EntryPoint0.transport]\n      [entryPoints.EntryPoint0.transport.lifeCycle]\n        requestAcceptGraceTimeout = 42\n        graceTimeOut = 42\n      [entryPoints.EntryPoint0.transport.respondingTimeouts]\n        readTimeout = 42\n        writeTimeout = 42\n        idleTimeout = 42\n    [entryPoints.EntryPoint0.proxyProtocol]\n      insecure = true\n      trustedIPs = [\"foobar\", \"foobar\"]\n    [entryPoints.EntryPoint0.forwardedHeaders]\n      insecure = true\n      trustedIPs = [\"foobar\", \"foobar\"]\n\n[providers]\n  providersThrottleDuration = 42\n  [providers.docker]\n    constraints = \"foobar\"\n    watch = true\n    endpoint = \"foobar\"\n    defaultRule = \"foobar\"\n    exposedByDefault = true\n    useBindPortIP = true\n    swarmMode = true\n    network = \"foobar\"\n    swarmModeRefreshSeconds = 42\n    httpClientTimeout = 42\n    [providers.docker.tls]\n      ca = \"foobar\"\n      caOptional = true\n      cert = \"foobar\"\n      key = \"foobar\"\n      insecureSkipVerify = true\n  [providers.file]\n    directory = \"foobar\"\n    watch = true\n    filename = \"foobar\"\n    debugLogGeneratedTemplate = true\n  [providers.marathon]\n    constraints = \"foobar\"\n    trace = true\n    watch = true\n    endpoint = \"foobar\"\n    defaultRule = \"foobar\"\n    exposedByDefault = true\n    dcosToken = \"foobar\"\n    dialerTimeout = 42\n    responseHeaderTimeout = 42\n    tlsHandshakeTimeout = 42\n    keepAlive = 42\n    forceTaskHostname = true\n    respectReadinessChecks = true\n    [providers.marathon.tls]\n      ca = \"foobar\"\n      caOptional = true\n      cert = \"foobar\"\n      key = \"foobar\"\n      insecureSkipVerify = true\n    [providers.marathon.basic]\n      httpBasicAuthUser = \"foobar\"\n      httpBasicPassword = \"foobar\"\n  [providers.kubernetesIngress]\n    endpoint = \"foobar\"\n    token = \"foobar\"\n    certAuthFilePath = \"foobar\"\n    namespaces = [\"foobar\", \"foobar\"]\n    labelSelector = \"foobar\"\n    ingressClass = \"foobar\"\n    [providers.kubernetesIngress.ingressEndpoint]\n      ip = \"foobar\"\n      hostname = \"foobar\"\n      publishedService = \"foobar\"\n  [providers.kubernetesCRD]\n    endpoint = \"foobar\"\n    token = \"foobar\"\n    certAuthFilePath = \"foobar\"\n    namespaces = [\"foobar\", \"foobar\"]\n    labelSelector = \"foobar\"\n    ingressClass = \"foobar\"\n  [providers.rest]\n    entryPoint = \"foobar\"\n  [providers.rancher]\n    constraints = \"foobar\"\n    watch = true\n    defaultRule = \"foobar\"\n    exposedByDefault = true\n    enableServiceHealthFilter = true\n    refreshSeconds = 42\n    intervalPoll = true\n    prefix = \"foobar\"\n\n[api]\n  entryPoint = \"foobar\"\n  dashboard = true\n  middlewares = [\"foobar\", \"foobar\"]\n  [api.statistics]\n    recentErrors = 42\n\n[metrics]\n  [metrics.prometheus]\n    buckets = [42.0, 42.0]\n    entryPoint = \"foobar\"\n    middlewares = [\"foobar\", \"foobar\"]\n  [metrics.datadog]\n    address = \"foobar\"\n    pushInterval = \"10s\"\n  [metrics.statsD]\n    address = \"foobar\"\n    pushInterval = \"10s\"\n  [metrics.influxDB]\n    address = \"foobar\"\n    protocol = \"foobar\"\n    pushInterval = \"10s\"\n    database = \"foobar\"\n    retentionPolicy = \"foobar\"\n    username = \"foobar\"\n    password = \"foobar\"\n\n[ping]\n  entryPoint = \"foobar\"\n  middlewares = [\"foobar\", \"foobar\"]\n\n[log]\n  level = \"foobar\"\n  filePath = \"foobar\"\n  format = \"foobar\"\n\n[accessLog]\n  filePath = \"foobar\"\n  format = \"foobar\"\n  bufferingSize = 42\n  [accessLog.filters]\n    statusCodes = [\"foobar\", \"foobar\"]\n    retryAttempts = true\n    minDuration = 42\n  [accessLog.fields]\n    defaultMode = \"foobar\"\n    [accessLog.fields.names]\n      name0 = \"foobar\"\n      name1 = \"foobar\"\n    [accessLog.fields.headers]\n      defaultMode = \"foobar\"\n      [accessLog.fields.headers.names]\n        name0 = \"foobar\"\n        name1 = \"foobar\"\n\n[tracing]\n  serviceName = \"foobar\"\n  spanNameLimit = 42\n  [tracing.jaeger]\n    samplingServerURL = \"foobar\"\n    samplingType = \"foobar\"\n    samplingParam = 42.0\n    localAgentHostPort = \"foobar\"\n    gen128Bit = true\n    propagation = \"foobar\"\n    traceContextHeaderName = \"foobar\"\n  [tracing.zipkin]\n    httpEndpoint = \"foobar\"\n    sameSpan = true\n    id128Bit = true\n    debug = true\n    sampleRate = 42.0\n  [tracing.datadog]\n    localAgentHostPort = \"foobar\"\n    globalTag = \"foobar\"\n    debug = true\n    prioritySampling = true\n    traceIDHeaderName = \"foobar\"\n    parentIDHeaderName = \"foobar\"\n    samplingPriorityHeaderName = \"foobar\"\n    bagagePrefixHeaderName = \"foobar\"\n  [tracing.instana]\n    localAgentHost = \"foobar\"\n    localAgentPort = 42\n    logLevel = \"foobar\"\n  [tracing.haystack]\n    localAgentHost = \"foobar\"\n    localAgentPort = 42\n    globalTag = \"foobar\"\n    traceIDHeaderName = \"foobar\"\n    parentIDHeaderName = \"foobar\"\n    spanIDHeaderName = \"foobar\"\n\n[hostResolver]\n  cnameFlattening = true\n  resolvConfig = \"foobar\"\n  resolvDepth = 42\n\n[acme]\n  email = \"foobar\"\n  acmeLogging = true\n  caServer = \"foobar\"\n  storage = \"foobar\"\n  entryPoint = \"foobar\"\n  keyType = \"foobar\"\n  [acme.dnsChallenge]\n    provider = \"foobar\"\n    delayBeforeCheck = 42\n    resolvers = [\"foobar\", \"foobar\"]\n    disablePropagationCheck = true\n  [acme.httpChallenge]\n    entryPoint = \"foobar\"\n  [acme.tlsChallenge]\n\n  [[acme.domains]]\n    main = \"foobar\"\n    sans = [\"foobar\", \"foobar\"]\n\n  [[acme.domains]]\n    main = \"foobar\"\n    sans = [\"foobar\", \"foobar\"]\n\n## Dynamic configuration\n\n[http]\n  [http.routers]\n    [http.routers.Router0]\n      entryPoints = [\"foobar\", \"foobar\"]\n      middlewares = [\"foobar\", \"foobar\"]\n      service = \"foobar\"\n      rule = \"foobar\"\n      priority = 42\n      [http.routers.Router0.tls]\n  [http.middlewares]\n    [http.middlewares.Middleware0]\n      [http.middlewares.Middleware0.addPrefix]\n        prefix = \"foobar\"\n    [http.middlewares.Middleware1]\n      [http.middlewares.Middleware1.stripPrefix]\n        prefixes = [\"foobar\", \"foobar\"]\n    [http.middlewares.Middleware10]\n      [http.middlewares.Middleware10.rateLimit]\n        average = 42\n        period = \"1s\"\n        burst = 42\n        [http.middlewares.Middleware10.rateLimit.sourceCriterion]\n          requestHeaderName = \"foobar\"\n          requestHost = true\n        [http.middlewares.Middleware10.rateLimit.sourceCriterion.ipStrategy]\n          depth = 42\n          excludedIPs = [\"foobar\", \"foobar\"]\n    [http.middlewares.Middleware11]\n      [http.middlewares.Middleware11.redirectRegex]\n        regex = \"foobar\"\n        replacement = \"foobar\"\n        permanent = true\n    [http.middlewares.Middleware12]\n      [http.middlewares.Middleware12.redirectScheme]\n        scheme = \"foobar\"\n        port = \"foobar\"\n        permanent = true\n    [http.middlewares.Middleware13]\n      [http.middlewares.Middleware13.basicAuth]\n        users = [\"foobar\", \"foobar\"]\n        usersFile = \"foobar\"\n        realm = \"foobar\"\n        removeHeader = true\n        headerField = \"foobar\"\n    [http.middlewares.Middleware14]\n      [http.middlewares.Middleware14.digestAuth]\n        users = [\"foobar\", \"foobar\"]\n        usersFile = \"foobar\"\n        removeHeader = true\n        realm = \"foobar\"\n        headerField = \"foobar\"\n    [http.middlewares.Middleware15]\n      [http.middlewares.Middleware15.forwardAuth]\n        address = \"foobar\"\n        trustForwardHeader = true\n        authResponseHeaders = [\"foobar\", \"foobar\"]\n        authResponseHeadersRegex = \"foobar\"\n        authRequestHeaders = [\"foobar\", \"foobar\"]\n        [http.middlewares.Middleware15.forwardAuth.tls]\n          ca = \"foobar\"\n          caOptional = true\n          cert = \"foobar\"\n          key = \"foobar\"\n          insecureSkipVerify = true\n    [http.middlewares.Middleware16]\n      [http.middlewares.Middleware16.inFlightReq]\n        amount = 42\n        [http.middlewares.Middleware16.inFlightReq.sourceCriterion]\n          requestHeaderName = \"foobar\"\n          requestHost = true\n          [http.middlewares.Middleware16.inFlightReq.sourceCriterion.ipStrategy]\n            depth = 42\n            excludedIPs = [\"foobar\", \"foobar\"]\n    [http.middlewares.Middleware17]\n      [http.middlewares.Middleware17.buffering]\n        maxRequestBodyBytes = 42\n        memRequestBodyBytes = 42\n        maxResponseBodyBytes = 42\n        memResponseBodyBytes = 42\n        retryExpression = \"foobar\"\n    [http.middlewares.Middleware18]\n      [http.middlewares.Middleware18.circuitBreaker]\n        expression = \"foobar\"\n    [http.middlewares.Middleware19]\n      [http.middlewares.Middleware19.compress]\n    [http.middlewares.Middleware2]\n      [http.middlewares.Middleware2.stripPrefixRegex]\n        regex = [\"foobar\", \"foobar\"]\n    [http.middlewares.Middleware20]\n      [http.middlewares.Middleware20.passTLSClientCert]\n        pem = true\n        [http.middlewares.Middleware20.passTLSClientCert.info]\n          notAfter = true\n          notBefore = true\n          sans = true\n          [http.middlewares.Middleware20.passTLSClientCert.info.subject]\n            country = true\n            province = true\n            locality = true\n            organization = true\n            organizationalUnit = true\n            commonName = true\n            serialNumber = true\n            domainComponent = true\n          [http.middlewares.Middleware20.passTLSClientCert.info.issuer]\n            country = true\n            province = true\n            locality = true\n            organization = true\n            commonName = true\n            serialNumber = true\n            domainComponent = true\n    [http.middlewares.Middleware21]\n      [http.middlewares.Middleware21.retry]\n        regex = 0\n    [http.middlewares.Middleware3]\n      [http.middlewares.Middleware3.replacePath]\n        path = \"foobar\"\n    [http.middlewares.Middleware4]\n      [http.middlewares.Middleware4.replacePathRegex]\n        regex = \"foobar\"\n        replacement = \"foobar\"\n    [http.middlewares.Middleware5]\n      [http.middlewares.Middleware5.chain]\n        middlewares = [\"foobar\", \"foobar\"]\n    [http.middlewares.Middleware6]\n      [http.middlewares.Middleware6.ipWhiteList]\n        sourceRange = [\"foobar\", \"foobar\"]\n    [http.middlewares.Middleware7]\n      [http.middlewares.Middleware7.ipWhiteList]\n        [http.middlewares.Middleware7.ipWhiteList.ipStrategy]\n          depth = 42\n          excludedIPs = [\"foobar\", \"foobar\"]\n    [http.middlewares.Middleware8]\n      [http.middlewares.Middleware8.headers]\n        accessControlAllowCredentials = true\n        accessControlAllowHeaders = [\"foobar\", \"foobar\"]\n        accessControlAllowMethods = [\"foobar\", \"foobar\"]\n        accessControlAllowOriginList = [\"foobar\", \"foobar\"]\n        accessControlExposeHeaders = [\"foobar\", \"foobar\"]\n        accessControlMaxAge = 42\n        addVaryHeader = true\n        allowedHosts = [\"foobar\", \"foobar\"]\n        hostsProxyHeaders = [\"foobar\", \"foobar\"]\n        sslRedirect = true\n        sslTemporaryRedirect = true\n        sslHost = \"foobar\"\n        sslForceHost = true\n        stsSeconds = 42\n        stsIncludeSubdomains = true\n        stsPreload = true\n        forceSTSHeader = true\n        frameDeny = true\n        customFrameOptionsValue = \"foobar\"\n        contentTypeNosniff = true\n        browserXssFilter = true\n        customBrowserXSSValue = \"foobar\"\n        contentSecurityPolicy = \"foobar\"\n        publicKey = \"foobar\"\n        referrerPolicy = \"foobar\"\n        featurePolicy = \"foobar\"\n        isDevelopment = true\n        [http.middlewares.Middleware8.headers.customRequestHeaders]\n          name0 = \"foobar\"\n          name1 = \"foobar\"\n        [http.middlewares.Middleware8.headers.customResponseHeaders]\n          name0 = \"foobar\"\n          name1 = \"foobar\"\n        [http.middlewares.Middleware8.headers.sslProxyHeaders]\n          name0 = \"foobar\"\n          name1 = \"foobar\"\n    [http.middlewares.Middleware9]\n      [http.middlewares.Middleware9.errors]\n        status = [\"foobar\", \"foobar\"]\n        service = \"foobar\"\n        query = \"foobar\"\n  [http.services]\n    [http.services.Service0]\n      [http.services.Service0.loadBalancer]\n        passHostHeader = true\n        [http.services.Service0.loadBalancer.sticky.cookie]\n          name = \"foobar\"\n\n        [[http.services.Service0.loadBalancer.servers]]\n          url = \"foobar\"\n\n        [[http.services.Service0.loadBalancer.servers]]\n          url = \"foobar\"\n        [http.services.Service0.loadBalancer.healthCheck]\n          scheme = \"foobar\"\n          path = \"foobar\"\n          port = 42\n          interval = \"5s\"\n          timeout = \"10s\"\n          hostname = \"foobar\"\n          [http.services.Service0.loadBalancer.healthCheck.headers]\n            name0 = \"foobar\"\n            name1 = \"foobar\"\n        [http.services.Service0.loadBalancer.responseForwarding]\n          flushInterval = \"5s\"\n\n[tcp]\n  [tcp.routers]\n    [tcp.routers.TCPRouter0]\n      entryPoints = [\"foobar\", \"foobar\"]\n      service = \"foobar\"\n      rule = \"foobar\"\n      [tcp.routers.TCPRouter0.tls]\n        passthrough = true\n  [tcp.services]\n    [tcp.services.TCPService0]\n      [tcp.services.TCPService0.loadBalancer]\n\n        [[tcp.services.TCPService0.loadBalancer.servers]]\n          address = \"foobar\"\n\n        [[tcp.services.TCPService0.loadBalancer.servers]]\n          address = \"foobar\"\n\n[tls]\n\n  [[tls.Certificates]]\n    certFile = \"foobar\"\n    keyFile = \"foobar\"\n    stores = [\"foobar\", \"foobar\"]\n\n  [[tls.Certificates]]\n    certFile = \"foobar\"\n    keyFile = \"foobar\"\n    stores = [\"foobar\", \"foobar\"]\n  [tls.options]\n    [tls.options.TLS0]\n      minVersion = \"foobar\"\n      cipherSuites = [\"foobar\", \"foobar\"]\n      sniStrict = true\n      [tls.options.TLS0.clientCA]\n        files = [\"foobar\", \"foobar\"]\n        optional = true\n    [tls.options.TLS1]\n      minVersion = \"foobar\"\n      cipherSuites = [\"foobar\", \"foobar\"]\n      sniStrict = true\n      [tls.options.TLS1.clientCA]\n        files = [\"foobar\", \"foobar\"]\n        optional = true\n  [tls.stores]\n    [tls.stores.Store0]\n      [tls.stores.Store0.defaultCertificate]\n        certFile = \"foobar\"\n        keyFile = \"foobar\"\n    [tls.stores.Store1]\n      [tls.stores.Store1.defaultCertificate]\n        certFile = \"foobar\"\n        keyFile = \"foobar\"\n"
  },
  {
    "path": "go.mod",
    "content": "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 => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e\n\tgithub.com/gorilla/mux => github.com/containous/mux v0.0.0-20250523120546-41b6ec3aed59\n\tgithub.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595\n)\n\nrequire (\n\tgithub.com/BurntSushi/toml v1.5.0\n\tgithub.com/docker/cli v29.0.0+incompatible\n\tgithub.com/docker/docker v28.5.2+incompatible\n\tgithub.com/docker/go-connections v0.6.0\n\tgithub.com/echovault/sugardb v0.17.0\n\tgithub.com/gofiber/fiber/v2 v2.52.9\n\tgithub.com/pkg/errors v0.9.1\n\tgithub.com/redis/go-redis/v9 v9.16.0\n\tgithub.com/rs/zerolog v1.34.0\n\tgithub.com/ryanuber/go-glob v1.0.0\n\tgithub.com/sirupsen/logrus v1.9.3\n\tgithub.com/stretchr/testify v1.11.1\n\tgithub.com/traefik/paerser v0.2.2\n\tgithub.com/traefik/traefik/v3 v3.6.1\n\tgithub.com/urfave/cli/v2 v2.27.7\n\tgithub.com/valyala/fasthttp v1.68.0\n\tgolang.org/x/exp v0.0.0-20251017212417-90e834f514db\n\tgopkg.in/yaml.v3 v3.0.1\n)\n\nrequire (\n\tcloud.google.com/go/auth v0.17.0 // indirect\n\tcloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect\n\tcloud.google.com/go/compute/metadata v0.9.0 // indirect\n\tdario.cat/mergo v1.0.1 // indirect\n\tgithub.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect\n\tgithub.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect\n\tgithub.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 // indirect\n\tgithub.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 // indirect\n\tgithub.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect\n\tgithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect\n\tgithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect\n\tgithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect\n\tgithub.com/Azure/go-autorest v14.2.0+incompatible // indirect\n\tgithub.com/Azure/go-autorest/autorest v0.11.30 // indirect\n\tgithub.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect\n\tgithub.com/Azure/go-autorest/autorest/azure/auth v0.5.13 // indirect\n\tgithub.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect\n\tgithub.com/Azure/go-autorest/autorest/date v0.3.0 // indirect\n\tgithub.com/Azure/go-autorest/autorest/to v0.4.1 // indirect\n\tgithub.com/Azure/go-autorest/logger v0.2.1 // indirect\n\tgithub.com/Azure/go-autorest/tracing v0.6.0 // indirect\n\tgithub.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 // indirect\n\tgithub.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect\n\tgithub.com/Masterminds/goutils v1.1.1 // indirect\n\tgithub.com/Masterminds/semver/v3 v3.3.1 // indirect\n\tgithub.com/Masterminds/sprig/v3 v3.2.3 // indirect\n\tgithub.com/Microsoft/go-winio v0.6.2 // indirect\n\tgithub.com/VividCortex/gohistogram v1.0.0 // indirect\n\tgithub.com/abbot/go-http-auth v0.0.0-00010101000000-000000000000 // indirect\n\tgithub.com/akamai/AkamaiOPEN-edgegrid-golang/v11 v11.1.0 // indirect\n\tgithub.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect\n\tgithub.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 // indirect\n\tgithub.com/alibabacloud-go/debug v1.0.1 // indirect\n\tgithub.com/alibabacloud-go/tea v1.3.13 // indirect\n\tgithub.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect\n\tgithub.com/aliyun/credentials-go v1.4.7 // indirect\n\tgithub.com/andybalholm/brotli v1.2.0 // indirect\n\tgithub.com/armon/go-metrics v0.4.1 // indirect\n\tgithub.com/aws/aws-sdk-go-v2 v1.39.4 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/config v1.31.15 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/credentials v1.18.19 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/ec2 v1.203.1 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/ecs v1.53.15 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/lightsail v1.50.2 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/route53 v1.59.1 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/ssm v1.56.13 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/sso v1.29.8 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3 // indirect\n\tgithub.com/aws/aws-sdk-go-v2/service/sts v1.38.9 // indirect\n\tgithub.com/aws/smithy-go v1.23.1 // indirect\n\tgithub.com/aziontech/azionapi-go-sdk v0.143.0 // indirect\n\tgithub.com/baidubce/bce-sdk-go v0.9.250 // indirect\n\tgithub.com/benbjohnson/clock v1.3.5 // indirect\n\tgithub.com/beorn7/perks v1.0.1 // indirect\n\tgithub.com/boltdb/bolt v1.3.1 // indirect\n\tgithub.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect\n\tgithub.com/bytedance/sonic v1.12.0 // indirect\n\tgithub.com/cenkalti/backoff/v4 v4.3.0 // indirect\n\tgithub.com/cenkalti/backoff/v5 v5.0.3 // indirect\n\tgithub.com/cespare/xxhash/v2 v2.3.0 // indirect\n\tgithub.com/clbanning/mxj/v2 v2.7.0 // indirect\n\tgithub.com/containerd/errdefs v1.0.0 // indirect\n\tgithub.com/containerd/errdefs/pkg v0.3.0 // indirect\n\tgithub.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd // indirect\n\tgithub.com/coreos/go-semver v0.3.1 // indirect\n\tgithub.com/coreos/go-systemd/v22 v22.5.0 // indirect\n\tgithub.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect\n\tgithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect\n\tgithub.com/deepmap/oapi-codegen v1.9.1 // indirect\n\tgithub.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect\n\tgithub.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect\n\tgithub.com/dimchansky/utfbom v1.1.1 // indirect\n\tgithub.com/distribution/reference v0.6.0 // indirect\n\tgithub.com/dnsimple/dnsimple-go/v4 v4.0.0 // indirect\n\tgithub.com/docker/go-units v0.5.0 // indirect\n\tgithub.com/emicklei/go-restful/v3 v3.13.0 // indirect\n\tgithub.com/evanphx/json-patch/v5 v5.9.11 // indirect\n\tgithub.com/exoscale/egoscale/v3 v3.1.27 // indirect\n\tgithub.com/fatih/color v1.18.0 // indirect\n\tgithub.com/fatih/structs v1.1.0 // indirect\n\tgithub.com/felixge/httpsnoop v1.0.4 // indirect\n\tgithub.com/fsnotify/fsnotify v1.9.0 // indirect\n\tgithub.com/fxamacker/cbor/v2 v2.9.0 // indirect\n\tgithub.com/gabriel-vasile/mimetype v1.4.3 // indirect\n\tgithub.com/ghodss/yaml v1.0.0 // indirect\n\tgithub.com/go-acme/alidns-20150109/v4 v4.6.1 // indirect\n\tgithub.com/go-acme/lego/v4 v4.28.0 // indirect\n\tgithub.com/go-acme/tencentclouddnspod v1.1.10 // indirect\n\tgithub.com/go-acme/tencentedgdeone v1.1.48 // indirect\n\tgithub.com/go-errors/errors v1.0.1 // indirect\n\tgithub.com/go-jose/go-jose/v4 v4.1.3 // indirect\n\tgithub.com/go-kit/kit v0.13.0 // indirect\n\tgithub.com/go-kit/log v0.2.1 // indirect\n\tgithub.com/go-logfmt/logfmt v0.5.1 // indirect\n\tgithub.com/go-logr/logr v1.4.3 // indirect\n\tgithub.com/go-logr/stdr v1.2.2 // indirect\n\tgithub.com/go-openapi/jsonpointer v0.21.2 // indirect\n\tgithub.com/go-openapi/jsonreference v0.21.0 // indirect\n\tgithub.com/go-openapi/swag v0.23.1 // indirect\n\tgithub.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect\n\tgithub.com/go-playground/locales v0.14.1 // indirect\n\tgithub.com/go-playground/universal-translator v0.18.1 // indirect\n\tgithub.com/go-playground/validator/v10 v10.23.0 // indirect\n\tgithub.com/go-resty/resty/v2 v2.16.5 // indirect\n\tgithub.com/go-viper/mapstructure/v2 v2.4.0 // indirect\n\tgithub.com/go-zookeeper/zk v1.0.3 // indirect\n\tgithub.com/gobwas/glob v0.2.3 // indirect\n\tgithub.com/goccy/go-json v0.10.2 // indirect\n\tgithub.com/goccy/go-yaml v1.18.0 // indirect\n\tgithub.com/gofrs/flock v0.13.0 // indirect\n\tgithub.com/gogo/protobuf v1.3.2 // indirect\n\tgithub.com/golang-jwt/jwt/v4 v4.5.2 // indirect\n\tgithub.com/golang-jwt/jwt/v5 v5.3.0 // indirect\n\tgithub.com/golang/protobuf v1.5.4 // indirect\n\tgithub.com/google/btree v1.1.3 // indirect\n\tgithub.com/google/gnostic-models v0.7.0 // indirect\n\tgithub.com/google/go-cmp v0.7.0 // indirect\n\tgithub.com/google/go-github/v28 v28.1.1 // indirect\n\tgithub.com/google/go-querystring v1.1.0 // indirect\n\tgithub.com/google/s2a-go v0.1.9 // indirect\n\tgithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect\n\tgithub.com/google/uuid v1.6.0 // indirect\n\tgithub.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect\n\tgithub.com/googleapis/gax-go/v2 v2.15.0 // indirect\n\tgithub.com/gophercloud/gophercloud v1.14.1 // indirect\n\tgithub.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect\n\tgithub.com/gorilla/mux v1.8.1 // indirect\n\tgithub.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect\n\tgithub.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect\n\tgithub.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect\n\tgithub.com/hashicorp/consul/api v1.26.1 // indirect\n\tgithub.com/hashicorp/cronexpr v1.1.2 // indirect\n\tgithub.com/hashicorp/errwrap v1.1.0 // indirect\n\tgithub.com/hashicorp/go-cleanhttp v0.5.2 // indirect\n\tgithub.com/hashicorp/go-hclog v1.6.3 // indirect\n\tgithub.com/hashicorp/go-immutable-radix v1.3.1 // indirect\n\tgithub.com/hashicorp/go-msgpack v0.5.5 // indirect\n\tgithub.com/hashicorp/go-msgpack/v2 v2.1.2 // indirect\n\tgithub.com/hashicorp/go-multierror v1.1.1 // indirect\n\tgithub.com/hashicorp/go-retryablehttp v0.7.8 // indirect\n\tgithub.com/hashicorp/go-rootcerts v1.0.2 // indirect\n\tgithub.com/hashicorp/go-sockaddr v1.0.2 // indirect\n\tgithub.com/hashicorp/go-uuid v1.0.3 // indirect\n\tgithub.com/hashicorp/go-version v1.7.0 // indirect\n\tgithub.com/hashicorp/golang-lru v1.0.2 // indirect\n\tgithub.com/hashicorp/hcl v1.0.1-vault-5 // indirect\n\tgithub.com/hashicorp/memberlist v0.5.1 // indirect\n\tgithub.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b // indirect\n\tgithub.com/hashicorp/raft v1.7.1 // indirect\n\tgithub.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702 // indirect\n\tgithub.com/hashicorp/serf v0.10.1 // indirect\n\tgithub.com/http-wasm/http-wasm-host-go v0.7.0 // indirect\n\tgithub.com/huandu/xstrings v1.5.0 // indirect\n\tgithub.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.173 // indirect\n\tgithub.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect\n\tgithub.com/imdario/mergo v0.3.16 // indirect\n\tgithub.com/influxdata/influxdb-client-go/v2 v2.7.0 // indirect\n\tgithub.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab // indirect\n\tgithub.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect\n\tgithub.com/infobloxopen/infoblox-go-client/v2 v2.10.0 // indirect\n\tgithub.com/jonboulle/clockwork v0.5.0 // indirect\n\tgithub.com/josharian/intern v1.0.0 // indirect\n\tgithub.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 // indirect\n\tgithub.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect\n\tgithub.com/klauspost/compress v1.18.1 // indirect\n\tgithub.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect\n\tgithub.com/kvtools/consul v1.0.2 // indirect\n\tgithub.com/kvtools/etcdv3 v1.0.3 // indirect\n\tgithub.com/kvtools/redis v1.2.0 // indirect\n\tgithub.com/kvtools/valkeyrie v1.0.0 // indirect\n\tgithub.com/kvtools/zookeeper v1.0.2 // indirect\n\tgithub.com/kylelemons/godebug v1.1.0 // indirect\n\tgithub.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect\n\tgithub.com/labbsr0x/goh v1.0.1 // indirect\n\tgithub.com/leodido/go-urn v1.4.0 // indirect\n\tgithub.com/linode/linodego v1.60.0 // indirect\n\tgithub.com/liquidweb/liquidweb-cli v0.6.9 // indirect\n\tgithub.com/liquidweb/liquidweb-go v1.6.4 // indirect\n\tgithub.com/magiconair/properties v1.8.7 // indirect\n\tgithub.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect\n\tgithub.com/mailgun/multibuf v0.1.2 // indirect\n\tgithub.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 // indirect\n\tgithub.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f // indirect\n\tgithub.com/mailru/easyjson v0.9.0 // indirect\n\tgithub.com/mattn/go-colorable v0.1.14 // indirect\n\tgithub.com/mattn/go-isatty v0.0.20 // indirect\n\tgithub.com/mattn/go-runewidth v0.0.16 // indirect\n\tgithub.com/miekg/dns v1.1.68 // indirect\n\tgithub.com/mimuret/golang-iij-dpf v0.9.1 // indirect\n\tgithub.com/mitchellh/copystructure v1.2.0 // indirect\n\tgithub.com/mitchellh/go-homedir v1.1.0 // indirect\n\tgithub.com/mitchellh/hashstructure v1.0.0 // indirect\n\tgithub.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect\n\tgithub.com/mitchellh/reflectwalk v1.0.2 // indirect\n\tgithub.com/moby/docker-image-spec v1.3.1 // indirect\n\tgithub.com/moby/moby/api v1.52.0 // indirect\n\tgithub.com/moby/moby/client v0.1.0 // indirect\n\tgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect\n\tgithub.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect\n\tgithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect\n\tgithub.com/namedotcom/go/v4 v4.0.2 // indirect\n\tgithub.com/nrdcg/auroradns v1.1.0 // indirect\n\tgithub.com/nrdcg/bunny-go v0.1.0 // indirect\n\tgithub.com/nrdcg/desec v0.11.1 // indirect\n\tgithub.com/nrdcg/dnspod-go v0.4.0 // indirect\n\tgithub.com/nrdcg/freemyip v0.3.0 // indirect\n\tgithub.com/nrdcg/goacmedns v0.2.0 // indirect\n\tgithub.com/nrdcg/goinwx v0.11.0 // indirect\n\tgithub.com/nrdcg/mailinabox v0.3.0 // indirect\n\tgithub.com/nrdcg/namesilo v0.5.0 // indirect\n\tgithub.com/nrdcg/nodion v0.1.0 // indirect\n\tgithub.com/nrdcg/oci-go-sdk/common/v1065 v1065.103.0 // indirect\n\tgithub.com/nrdcg/oci-go-sdk/dns/v1065 v1065.103.0 // indirect\n\tgithub.com/nrdcg/porkbun v0.4.0 // indirect\n\tgithub.com/nrdcg/vegadns v0.3.0 // indirect\n\tgithub.com/nzdjb/go-metaname v1.0.0 // indirect\n\tgithub.com/opencontainers/go-digest v1.0.0 // indirect\n\tgithub.com/opencontainers/image-spec v1.1.1 // indirect\n\tgithub.com/ovh/go-ovh v1.9.0 // indirect\n\tgithub.com/patrickmn/go-cache v2.1.0+incompatible // indirect\n\tgithub.com/pelletier/go-toml/v2 v2.2.4 // indirect\n\tgithub.com/peterhellberg/link v1.2.0 // indirect\n\tgithub.com/pires/go-proxyproto v0.8.1 // indirect\n\tgithub.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect\n\tgithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect\n\tgithub.com/pquerna/otp v1.5.0 // indirect\n\tgithub.com/prometheus/client_golang v1.23.0 // indirect\n\tgithub.com/prometheus/client_model v0.6.2 // indirect\n\tgithub.com/prometheus/common v0.65.0 // indirect\n\tgithub.com/prometheus/procfs v0.17.0 // indirect\n\tgithub.com/quic-go/qpack v0.5.1 // indirect\n\tgithub.com/quic-go/quic-go v0.55.0 // indirect\n\tgithub.com/regfish/regfish-dnsapi-go v0.1.1 // indirect\n\tgithub.com/rivo/uniseg v0.4.7 // indirect\n\tgithub.com/robertkrimen/otto v0.5.1 // indirect\n\tgithub.com/rs/cors v1.7.0 // indirect\n\tgithub.com/russross/blackfriday/v2 v2.1.0 // indirect\n\tgithub.com/sacloud/api-client-go v0.3.3 // indirect\n\tgithub.com/sacloud/go-http v0.1.9 // indirect\n\tgithub.com/sacloud/iaas-api-go v1.20.0 // indirect\n\tgithub.com/sacloud/packages-go v0.0.11 // indirect\n\tgithub.com/sagikazarmark/locafero v0.4.0 // indirect\n\tgithub.com/sagikazarmark/slog-shim v0.1.0 // indirect\n\tgithub.com/scaleway/scaleway-sdk-go v1.0.0-beta.35 // indirect\n\tgithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect\n\tgithub.com/selectel/domains-go v1.1.0 // indirect\n\tgithub.com/selectel/go-selvpcclient/v4 v4.1.0 // indirect\n\tgithub.com/sethvargo/go-retry v0.3.0 // indirect\n\tgithub.com/shopspring/decimal v1.4.0 // indirect\n\tgithub.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect\n\tgithub.com/softlayer/softlayer-go v1.2.1 // indirect\n\tgithub.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect\n\tgithub.com/sony/gobreaker v1.0.0 // indirect\n\tgithub.com/sourcegraph/conc v0.3.0 // indirect\n\tgithub.com/spf13/afero v1.11.0 // indirect\n\tgithub.com/spf13/cast v1.7.0 // indirect\n\tgithub.com/spf13/pflag v1.0.7 // indirect\n\tgithub.com/spf13/viper v1.18.2 // indirect\n\tgithub.com/spiffe/go-spiffe/v2 v2.5.0 // indirect\n\tgithub.com/stealthrocket/wasi-go v0.8.0 // indirect\n\tgithub.com/stealthrocket/wazergo v0.19.1 // indirect\n\tgithub.com/stretchr/objx v0.5.2 // indirect\n\tgithub.com/subosito/gotenv v1.6.0 // indirect\n\tgithub.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.48 // indirect\n\tgithub.com/tetratelabs/wazero v1.8.0 // indirect\n\tgithub.com/tidwall/resp v0.1.1 // indirect\n\tgithub.com/tjfoc/gmsm v1.4.1 // indirect\n\tgithub.com/traefik/grpc-web v0.16.0 // indirect\n\tgithub.com/traefik/yaegi v0.16.1 // indirect\n\tgithub.com/transip/gotransip/v6 v6.26.1 // indirect\n\tgithub.com/ugorji/go/codec v1.2.11 // indirect\n\tgithub.com/ultradns/ultradns-go-sdk v1.8.1-20250722213956-faef419 // indirect\n\tgithub.com/unrolled/render v1.0.2 // indirect\n\tgithub.com/unrolled/secure v1.0.9 // indirect\n\tgithub.com/valyala/bytebufferpool v1.0.0 // indirect\n\tgithub.com/vinyldns/go-vinyldns v0.9.16 // indirect\n\tgithub.com/volcengine/volc-sdk-golang v1.0.224 // indirect\n\tgithub.com/vulcand/oxy/v2 v2.0.3 // indirect\n\tgithub.com/vulcand/predicate v1.2.0 // indirect\n\tgithub.com/vultr/govultr/v3 v3.24.0 // indirect\n\tgithub.com/x448/float16 v0.8.4 // indirect\n\tgithub.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect\n\tgithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect\n\tgithub.com/xeipuuv/gojsonschema v1.2.0 // indirect\n\tgithub.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect\n\tgithub.com/yandex-cloud/go-genproto v0.34.0 // indirect\n\tgithub.com/yandex-cloud/go-sdk/services/dns v0.0.16 // indirect\n\tgithub.com/yandex-cloud/go-sdk/v2 v2.24.0 // indirect\n\tgithub.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect\n\tgithub.com/yuin/gopher-lua v1.1.1 // indirect\n\tgithub.com/zeebo/errs v1.4.0 // indirect\n\tgo.etcd.io/etcd/api/v3 v3.6.4 // indirect\n\tgo.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect\n\tgo.etcd.io/etcd/client/v3 v3.6.4 // indirect\n\tgo.mongodb.org/mongo-driver v1.13.1 // indirect\n\tgo.opentelemetry.io/auto/sdk v1.1.0 // indirect\n\tgo.opentelemetry.io/contrib/bridges/otellogrus v0.13.0 // indirect\n\tgo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect\n\tgo.opentelemetry.io/contrib/propagators/autoprop v0.63.0 // indirect\n\tgo.opentelemetry.io/contrib/propagators/aws v1.38.0 // indirect\n\tgo.opentelemetry.io/contrib/propagators/b3 v1.38.0 // indirect\n\tgo.opentelemetry.io/contrib/propagators/jaeger v1.38.0 // indirect\n\tgo.opentelemetry.io/contrib/propagators/ot v1.38.0 // indirect\n\tgo.opentelemetry.io/otel v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.14.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/log v0.14.0 // indirect\n\tgo.opentelemetry.io/otel/metric v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/sdk v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/sdk/log v0.14.0 // indirect\n\tgo.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect\n\tgo.opentelemetry.io/otel/trace v1.38.0 // indirect\n\tgo.opentelemetry.io/proto/otlp v1.7.1 // indirect\n\tgo.uber.org/multierr v1.11.0 // indirect\n\tgo.uber.org/ratelimit v0.3.1 // indirect\n\tgo.uber.org/zap v1.27.0 // indirect\n\tgo.yaml.in/yaml/v2 v2.4.2 // indirect\n\tgo.yaml.in/yaml/v3 v3.0.4 // indirect\n\tgolang.org/x/crypto v0.43.0 // indirect\n\tgolang.org/x/mod v0.29.0 // indirect\n\tgolang.org/x/net v0.46.0 // indirect\n\tgolang.org/x/oauth2 v0.32.0 // indirect\n\tgolang.org/x/sync v0.17.0 // indirect\n\tgolang.org/x/sys v0.37.0 // indirect\n\tgolang.org/x/term v0.36.0 // indirect\n\tgolang.org/x/text v0.30.0 // indirect\n\tgolang.org/x/time v0.14.0 // indirect\n\tgolang.org/x/tools v0.38.0 // indirect\n\tgomodules.xyz/jsonpatch/v2 v2.4.0 // indirect\n\tgoogle.golang.org/api v0.254.0 // indirect\n\tgoogle.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect\n\tgoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect\n\tgoogle.golang.org/grpc v1.76.0 // indirect\n\tgoogle.golang.org/protobuf v1.36.10 // indirect\n\tgopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect\n\tgopkg.in/inf.v0 v0.9.1 // indirect\n\tgopkg.in/ini.v1 v1.67.0 // indirect\n\tgopkg.in/ns1/ns1-go.v2 v2.15.1 // indirect\n\tgopkg.in/sourcemap.v1 v1.0.5 // indirect\n\tgopkg.in/yaml.v2 v2.4.0 // indirect\n\tk8s.io/api v0.34.1 // indirect\n\tk8s.io/apiextensions-apiserver v0.34.1 // indirect\n\tk8s.io/apimachinery v0.34.1 // indirect\n\tk8s.io/client-go v0.34.1 // indirect\n\tk8s.io/klog/v2 v2.130.1 // indirect\n\tk8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 // indirect\n\tk8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d // indirect\n\tknative.dev/networking v0.0.0-20241022012959-60e29ff520dc // indirect\n\tknative.dev/pkg v0.0.0-20241021183759-9b9d535af5ad // indirect\n\tmvdan.cc/xurls/v2 v2.5.0 // indirect\n\tnhooyr.io/websocket v1.8.7 // indirect\n\tsigs.k8s.io/gateway-api v1.4.0 // indirect\n\tsigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect\n\tsigs.k8s.io/randfill v1.0.0 // indirect\n\tsigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect\n\tsigs.k8s.io/yaml v1.6.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=\ncloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=\ncloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=\ncloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=\ncloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=\ncloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=\ncloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=\ncloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=\ncloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=\ncloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=\ncloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=\ncloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=\ncloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=\ncloud.google.com/go/auth v0.17.0 h1:74yCm7hCj2rUyyAocqnFzsAYXgJhrG26XCFimrc/Kz4=\ncloud.google.com/go/auth v0.17.0/go.mod h1:6wv/t5/6rOPAX4fJiRjKkJCvswLwdet7G8+UGXt7nCQ=\ncloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=\ncloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=\ncloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=\ncloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=\ncloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=\ncloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=\ncloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=\ncloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=\ncloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=\ncloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=\ncloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=\ncloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=\ncloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=\ncloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=\ncloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=\ncloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=\ncloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=\ncloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=\ncloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=\ncloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=\ncloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=\ncloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=\ndario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=\ndario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=\ndmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=\ngithub.com/AdamSLevy/jsonrpc2/v14 v14.1.0 h1:Dy3M9aegiI7d7PF1LUdjbVigJReo+QOceYsMyFh9qoE=\ngithub.com/AdamSLevy/jsonrpc2/v14 v14.1.0/go.mod h1:ZakZtbCXxCz82NJvq7MoREtiQesnDfrtF6RFUGzQfLo=\ngithub.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=\ngithub.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=\ngithub.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1 h1:5YTBM8QDVIBN3sxBil89WfdAAqDZbyJTgh688DSxX5w=\ngithub.com/Azure/azure-sdk-for-go/sdk/azcore v1.19.1/go.mod h1:YD5h/ldMsG0XiIw7PdyNhLxaM317eFh5yNLccNfGdyw=\ngithub.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0 h1:KpMC6LFL7mqpExyMC9jVOYRiVhLmamjeZfRsUpB7l4s=\ngithub.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.0/go.mod h1:J7MUC/wtRpfGVbQ5sIItY5/FuVWmvzlY21WAOfQnq/I=\ngithub.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=\ngithub.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=\ngithub.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 h1:9iefClla7iYpfYWdzPCRDozdmndjTm8DXdpCzPajMgA=\ngithub.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2/go.mod h1:XtLgD3ZD34DAaVIIAyG3objl5DynM3CQ/vMcbBNJZGI=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0/go.mod h1:AW8VEadnhw9xox+VaVd9sP7NjzOAnaZBLRH6Tq3cJ38=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 h1:yzrctSl9GMIQ5lHu7jc8olOsGjWDCsBpJhWqfGa/YIM=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0/go.mod h1:GE4m0rnnfwLGX0Y9A9A25Zx5N/90jneT5ABevqzhuFQ=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 h1:zLzoX5+W2l95UJoVwiyNS4dX8vHyQ6x2xRLoBBL9wMk=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0/go.mod h1:wVEOJfGTj0oPAUGA1JuRAvz/lxXQsWW16axmHPP47Bk=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 h1:Dd+RhdJn0OTtVGaeDLZpcumkIVCtA/3/Fo42+eoYvVM=\ngithub.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0/go.mod h1:5kakwfW5CjC9KK+Q4wjXAg+ShuIm2mBMua0ZFj2C8PE=\ngithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=\ngithub.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=\ngithub.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=\ngithub.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=\ngithub.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA=\ngithub.com/Azure/go-autorest/autorest v0.11.30 h1:iaZ1RGz/ALZtN5eq4Nr1SOFSlf2E4pDI3Tcsl+dZPVE=\ngithub.com/Azure/go-autorest/autorest v0.11.30/go.mod h1:t1kpPIOpIVX7annvothKvb0stsrXa37i7b+xpmBW8Fs=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8=\ngithub.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c=\ngithub.com/Azure/go-autorest/autorest/azure/auth v0.5.13 h1:Ov8avRZi2vmrE2JcXw+tu5K/yB41r7xK9GZDiBF7NdM=\ngithub.com/Azure/go-autorest/autorest/azure/auth v0.5.13/go.mod h1:5BAVfWLWXihP47vYrPuBKKf4cS0bXI+KM9Qx6ETDJYo=\ngithub.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc=\ngithub.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0=\ngithub.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=\ngithub.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=\ngithub.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=\ngithub.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=\ngithub.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=\ngithub.com/Azure/go-autorest/autorest/to v0.4.1 h1:CxNHBqdzTr7rLtdrtb5CMjJcDut+WNGCVv7OmS5+lTc=\ngithub.com/Azure/go-autorest/autorest/to v0.4.1/go.mod h1:EtaofgU4zmtvn1zT2ARsjRFdq9vXx0YWtmElwL+GZ9M=\ngithub.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=\ngithub.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=\ngithub.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=\ngithub.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=\ngithub.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=\ngithub.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=\ngithub.com/AzureAD/microsoft-authentication-library-for-go v1.5.0 h1:XkkQbfMyuH2jTSjQjSoihryI8GINRcs4xp8lNawg0FI=\ngithub.com/AzureAD/microsoft-authentication-library-for-go v1.5.0/go.mod h1:HKpQxkWaGLJ+D/5H8QRpyQXA1eKjxkFlOMwck5+33Jk=\ngithub.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=\ngithub.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=\ngithub.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=\ngithub.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=\ngithub.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=\ngithub.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=\ngithub.com/HdrHistogram/hdrhistogram-go v1.1.0/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=\ngithub.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM=\ngithub.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=\ngithub.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=\ngithub.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=\ngithub.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=\ngithub.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=\ngithub.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=\ngithub.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=\ngithub.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=\ngithub.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=\ngithub.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=\ngithub.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=\ngithub.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=\ngithub.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=\ngithub.com/Shopify/sarama v1.30.1/go.mod h1:hGgx05L/DiW8XYBXeJdKIN6V2QUy2H6JqME5VT1NLRw=\ngithub.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=\ngithub.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0=\ngithub.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=\ngithub.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=\ngithub.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=\ngithub.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=\ngithub.com/akamai/AkamaiOPEN-edgegrid-golang/v11 v11.1.0 h1:h/33OxYLqBk0BYmEbSUy7MlvgQR/m1w1/7OJFKoPL1I=\ngithub.com/akamai/AkamaiOPEN-edgegrid-golang/v11 v11.1.0/go.mod h1:rvh3imDA6EaQi+oM/GQHkQAOHbXPKJ7EWJvfjuw141Q=\ngithub.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=\ngithub.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=\ngithub.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=\ngithub.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=\ngithub.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo=\ngithub.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=\ngithub.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=\ngithub.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=\ngithub.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=\ngithub.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=\ngithub.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=\ngithub.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=\ngithub.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=\ngithub.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=\ngithub.com/alibabacloud-go/darabonba-openapi/v2 v2.1.12/go.mod h1:f2wDpbM7hK9SvLIH09zSKVU1TsyemUNOqErMscMMl7c=\ngithub.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13 h1:Q00FU3H94Ts0ZIHDmY+fYGgB7dV9D/YX6FGsgorQPgw=\ngithub.com/alibabacloud-go/darabonba-openapi/v2 v2.1.13/go.mod h1:lxFGfobinVsQ49ntjpgWghXmIF0/Sm4+wvBJ1h5RtaE=\ngithub.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=\ngithub.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=\ngithub.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=\ngithub.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=\ngithub.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=\ngithub.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=\ngithub.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=\ngithub.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=\ngithub.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=\ngithub.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=\ngithub.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=\ngithub.com/alibabacloud-go/openapi-util v0.1.1 h1:ujGErJjG8ncRW6XtBBMphzHTvCxn4DjrVw4m04HsS28=\ngithub.com/alibabacloud-go/openapi-util v0.1.1/go.mod h1:/UehBSE2cf1gYT43GV4E+RxTdLRzURImCYY0aRmlXpw=\ngithub.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=\ngithub.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=\ngithub.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=\ngithub.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=\ngithub.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=\ngithub.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=\ngithub.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=\ngithub.com/alibabacloud-go/tea v1.3.12/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=\ngithub.com/alibabacloud-go/tea v1.3.13 h1:WhGy6LIXaMbBM6VBYcsDCz6K/TPsT1Ri2hPmmZffZ94=\ngithub.com/alibabacloud-go/tea v1.3.13/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=\ngithub.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=\ngithub.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=\ngithub.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=\ngithub.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=\ngithub.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=\ngithub.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=\ngithub.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=\ngithub.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=\ngithub.com/aliyun/credentials-go v1.4.7 h1:T17dLqEtPUFvjDRRb5giVvLh6dFT8IcNFJJb7MeyCxw=\ngithub.com/aliyun/credentials-go v1.4.7/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=\ngithub.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=\ngithub.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=\ngithub.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=\ngithub.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=\ngithub.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=\ngithub.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=\ngithub.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=\ngithub.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=\ngithub.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=\ngithub.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=\ngithub.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=\ngithub.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=\ngithub.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=\ngithub.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=\ngithub.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=\ngithub.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=\ngithub.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=\ngithub.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=\ngithub.com/aws/aws-sdk-go-v2 v1.39.4 h1:qTsQKcdQPHnfGYBBs+Btl8QwxJeoWcOcPcixK90mRhg=\ngithub.com/aws/aws-sdk-go-v2 v1.39.4/go.mod h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM=\ngithub.com/aws/aws-sdk-go-v2/config v1.31.15 h1:gE3M4xuNXfC/9bG4hyowGm/35uQTi7bUKeYs5e/6uvU=\ngithub.com/aws/aws-sdk-go-v2/config v1.31.15/go.mod h1:HvnvGJoE2I95KAIW8kkWVPJ4XhdrlvwJpV6pEzFQa8o=\ngithub.com/aws/aws-sdk-go-v2/credentials v1.18.19 h1:Jc1zzwkSY1QbkEcLujwqRTXOdvW8ppND3jRBb/VhBQc=\ngithub.com/aws/aws-sdk-go-v2/credentials v1.18.19/go.mod h1:DIfQ9fAk5H0pGtnqfqkbSIzky82qYnGvh06ASQXXg6A=\ngithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11 h1:X7X4YKb+c0rkI6d4uJ5tEMxXgCZ+jZ/D6mvkno8c8Uw=\ngithub.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.11/go.mod h1:EqM6vPZQsZHYvC4Cai35UDg/f5NCEU+vp0WfbVqVcZc=\ngithub.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11 h1:7AANQZkF3ihM8fbdftpjhken0TP9sBzFbV/Ze/Y4HXA=\ngithub.com/aws/aws-sdk-go-v2/internal/configsources v1.4.11/go.mod h1:NTF4QCGkm6fzVwncpkFQqoquQyOolcyXfbpC98urj+c=\ngithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11 h1:ShdtWUZT37LCAA4Mw2kJAJtzaszfSHFb5n25sdcv4YE=\ngithub.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.11/go.mod h1:7bUb2sSr2MZ3M/N+VyETLTQtInemHXb/Fl3s8CLzm0Y=\ngithub.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=\ngithub.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=\ngithub.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o=\ngithub.com/aws/aws-sdk-go-v2/service/ec2 v1.203.1 h1:ZgY9zeVAe+54Qa7o1GXKRNTez79lffCeJSSinhl+qec=\ngithub.com/aws/aws-sdk-go-v2/service/ec2 v1.203.1/go.mod h1:0naMk66LtdeTmE+1CWQTKwtzOQ2t8mavOhMhR0Pv1m0=\ngithub.com/aws/aws-sdk-go-v2/service/ecs v1.53.15 h1:uH0DMwDjLGgjjYMk3M1MXHggk37trTiJIvwyJNP17Ig=\ngithub.com/aws/aws-sdk-go-v2/service/ecs v1.53.15/go.mod h1:49tE5yYdlAHqZIO8u5+u9Xy9k8IaV0v5cstZrjnX5+c=\ngithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2 h1:xtuxji5CS0JknaXoACOunXOYOQzgfTvGAc9s2QdCJA4=\ngithub.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.2/go.mod h1:zxwi0DIR0rcRcgdbl7E2MSOvxDyyXGBlScvBkARFaLQ=\ngithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11 h1:GpMf3z2KJa4RnJ0ew3Hac+hRFYLZ9DDjfgXjuW+pB54=\ngithub.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.11/go.mod h1:6MZP3ZI4QQsgUCFTwMZA2V0sEriNQ8k2hmoHF3qjimQ=\ngithub.com/aws/aws-sdk-go-v2/service/lightsail v1.50.2 h1:pr1dQ9vamhAf2mYOgiRRC/w9Ht4POFhy6+xXw7hOqwY=\ngithub.com/aws/aws-sdk-go-v2/service/lightsail v1.50.2/go.mod h1:A4Ch93K7Wam4Qe0Wl0XbPgcgoL5KIJtFIe7wHw6OPWE=\ngithub.com/aws/aws-sdk-go-v2/service/route53 v1.59.1 h1:KuoA/cmy/yK8n9v/d6WH36cZwGxFOrn0TmZ4lNN3MKQ=\ngithub.com/aws/aws-sdk-go-v2/service/route53 v1.59.1/go.mod h1:BymbICXBfXQHO6i+yTBhocA9a6DM0uMDQqYelqa9wzs=\ngithub.com/aws/aws-sdk-go-v2/service/ssm v1.56.13 h1:JfPeW7F6Y+VqBg6p+8zQv4wlgceguYu5ZT0USEGZ89g=\ngithub.com/aws/aws-sdk-go-v2/service/ssm v1.56.13/go.mod h1:EonGQFn66wZkJJrrKXrryrxoS3V30rcHvaWvc6oGHCI=\ngithub.com/aws/aws-sdk-go-v2/service/sso v1.29.8 h1:M5nimZmugcZUO9wG7iVtROxPhiqyZX6ejS1lxlDPbTU=\ngithub.com/aws/aws-sdk-go-v2/service/sso v1.29.8/go.mod h1:mbef/pgKhtKRwrigPPs7SSSKZgytzP8PQ6P6JAAdqyM=\ngithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3 h1:S5GuJZpYxE0lKeMHKn+BRTz6PTFpgThyJ+5mYfux7BM=\ngithub.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.3/go.mod h1:X4OF+BTd7HIb3L+tc4UlWHVrpgwZZIVENU15pRDVTI0=\ngithub.com/aws/aws-sdk-go-v2/service/sts v1.38.9 h1:Ekml5vGg6sHSZLZJQJagefnVe6PmqC2oiRkBq4F7fU0=\ngithub.com/aws/aws-sdk-go-v2/service/sts v1.38.9/go.mod h1:/e15V+o1zFHWdH3u7lpI3rVBcxszktIKuHKCY2/py+k=\ngithub.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=\ngithub.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M=\ngithub.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=\ngithub.com/aziontech/azionapi-go-sdk v0.143.0 h1:4eEBlYT10prgeCVTNR9FIc7f59Crbl2zrH1a4D1BUqU=\ngithub.com/aziontech/azionapi-go-sdk v0.143.0/go.mod h1:cA5DY/VP4X5Eu11LpQNzNn83ziKjja7QVMIl4J45feA=\ngithub.com/baidubce/bce-sdk-go v0.9.250 h1:fnvV5clsNCAP6pCauj0eNaUnoLVmjQGnco7rcMqp984=\ngithub.com/baidubce/bce-sdk-go v0.9.250/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=\ngithub.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=\ngithub.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=\ngithub.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=\ngithub.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=\ngithub.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=\ngithub.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=\ngithub.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=\ngithub.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=\ngithub.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=\ngithub.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=\ngithub.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=\ngithub.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=\ngithub.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=\ngithub.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=\ngithub.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=\ngithub.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=\ngithub.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=\ngithub.com/bytedance/sonic v1.12.0 h1:YGPgxF9xzaCNvd/ZKdQ28yRovhfMFZQjuk6fKBzZ3ls=\ngithub.com/bytedance/sonic v1.12.0/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=\ngithub.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=\ngithub.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=\ngithub.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=\ngithub.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=\ngithub.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=\ngithub.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=\ngithub.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=\ngithub.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=\ngithub.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=\ngithub.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=\ngithub.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=\ngithub.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=\ngithub.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=\ngithub.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=\ngithub.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=\ngithub.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=\ngithub.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=\ngithub.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=\ngithub.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=\ngithub.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=\ngithub.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=\ngithub.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=\ngithub.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=\ngithub.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=\ngithub.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=\ngithub.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=\ngithub.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=\ngithub.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=\ngithub.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=\ngithub.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=\ngithub.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=\ngithub.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=\ngithub.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=\ngithub.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=\ngithub.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=\ngithub.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=\ngithub.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd h1:0n+lFLh5zU0l6KSk3KpnDwfbPGAR44aRLgTbCnhRBHU=\ngithub.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd/go.mod h1:BbQgeDS5i0tNvypwEoF1oNjOJw8knRAE1DnVvjDstcQ=\ngithub.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e h1:D+uTEzDZc1Fhmd0Pq06c+O9+KkAyExw0eVmu/NOqaHU=\ngithub.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e/go.mod h1:s8kLgBQolDbsJOPVIGCEEv9zGAKUUf/685Gi0Qqg8z8=\ngithub.com/containous/minheap v0.0.0-20190809180810-6e71eb837595 h1:aPspFRO6b94To3gl4yTDOEtpjFwXI7V2W+z0JcNljQ4=\ngithub.com/containous/minheap v0.0.0-20190809180810-6e71eb837595/go.mod h1:+lHFbEasIiQVGzhVDVw/cn0ZaOzde2OwNncp1NhXV4c=\ngithub.com/containous/mux v0.0.0-20250523120546-41b6ec3aed59 h1:lJUOWjGohYjLKEfAz2nyI/dpzfKNPQLi5GLH7aaOZkw=\ngithub.com/containous/mux v0.0.0-20250523120546-41b6ec3aed59/go.mod h1:z8WW7n06n8/1xF9Jl9WmuDeZuHAhfL+bwarNjsciwwg=\ngithub.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=\ngithub.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=\ngithub.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=\ngithub.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=\ngithub.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=\ngithub.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=\ngithub.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=\ngithub.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=\ngithub.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=\ngithub.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=\ngithub.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=\ngithub.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=\ngithub.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=\ngithub.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=\ngithub.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=\ngithub.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=\ngithub.com/deepmap/oapi-codegen v1.9.1 h1:yHmEnA7jSTUMQgV+uN02WpZtwHnz2CBW3mZRIxr1vtI=\ngithub.com/deepmap/oapi-codegen v1.9.1/go.mod h1:PLqNAhdedP8ttRpBBkzLKU3bp+Fpy+tTgeAMlztR2cw=\ngithub.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=\ngithub.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=\ngithub.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=\ngithub.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=\ngithub.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=\ngithub.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=\ngithub.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=\ngithub.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=\ngithub.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=\ngithub.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=\ngithub.com/dnsimple/dnsimple-go/v4 v4.0.0 h1:nUCICZSyZDiiqimAAL+E8XL+0sKGks5VRki5S8XotRo=\ngithub.com/dnsimple/dnsimple-go/v4 v4.0.0/go.mod h1:AXT2yfAFOntJx6iMeo1J/zKBw0ggXFYBt4e97dqqPnc=\ngithub.com/docker/cli v29.0.0+incompatible h1:KgsN2RUFMNM8wChxryicn4p46BdQWpXOA1XLGBGPGAw=\ngithub.com/docker/cli v29.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=\ngithub.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=\ngithub.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=\ngithub.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=\ngithub.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=\ngithub.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=\ngithub.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=\ngithub.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=\ngithub.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=\ngithub.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=\ngithub.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=\ngithub.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=\ngithub.com/echovault/sugardb v0.17.0 h1:do6fmfoDIKjqBAGG4ohQ7C9NcynEHd9cUuqOCZrI4MI=\ngithub.com/echovault/sugardb v0.17.0/go.mod h1:HLaXt8GrOQYsSAdWSiawtf6As3lNDdWKzoBsROIDpyk=\ngithub.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=\ngithub.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=\ngithub.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=\ngithub.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=\ngithub.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=\ngithub.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=\ngithub.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=\ngithub.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=\ngithub.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=\ngithub.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=\ngithub.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=\ngithub.com/evanphx/json-patch v5.9.0+incompatible h1:fBXyNpNMuTTDdquAq/uisOr2lShz4oaXpDTX2bLe7ls=\ngithub.com/evanphx/json-patch v5.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=\ngithub.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU=\ngithub.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM=\ngithub.com/exoscale/egoscale/v3 v3.1.27 h1:vKdWZG8QFDc7rY7lCfcuudO+ovyp5psYjFwKVqmkhCE=\ngithub.com/exoscale/egoscale/v3 v3.1.27/go.mod h1:0iY8OxgHJCS5TKqDNhwOW95JBKCnBZl3YGU4Yt+NqkU=\ngithub.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=\ngithub.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=\ngithub.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=\ngithub.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=\ngithub.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=\ngithub.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=\ngithub.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=\ngithub.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=\ngithub.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=\ngithub.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=\ngithub.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=\ngithub.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=\ngithub.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=\ngithub.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo=\ngithub.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=\ngithub.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=\ngithub.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=\ngithub.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=\ngithub.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=\ngithub.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=\ngithub.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=\ngithub.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=\ngithub.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=\ngithub.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=\ngithub.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=\ngithub.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=\ngithub.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=\ngithub.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=\ngithub.com/getkin/kin-openapi v0.87.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=\ngithub.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=\ngithub.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=\ngithub.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=\ngithub.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=\ngithub.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=\ngithub.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=\ngithub.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=\ngithub.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=\ngithub.com/go-acme/alidns-20150109/v4 v4.6.1 h1:Dch3aWRcw4U62+jKPjPQN3iW3TPvgIywATbvHzojXeo=\ngithub.com/go-acme/alidns-20150109/v4 v4.6.1/go.mod h1:RBcqBA5IvUWtlpjx6dC6EkPVyBNLQ+mR18XoaP38BFY=\ngithub.com/go-acme/lego/v4 v4.28.0 h1:URKsCcybo7SjqqZckeBcDN9Vl29/bKS///75tcNkMHQ=\ngithub.com/go-acme/lego/v4 v4.28.0/go.mod h1:bzjilr03IgbaOwlH396hq5W56Bi0/uoRwW/JM8hP7m4=\ngithub.com/go-acme/tencentclouddnspod v1.1.10 h1:ERVJ4mc3cT4Nb3+n6H/c1AwZnChGBqLoymE0NVYscKI=\ngithub.com/go-acme/tencentclouddnspod v1.1.10/go.mod h1:Bo/0YQJ/99FM+44HmCQkByuptX1tJsJ9V14MGV/2Qco=\ngithub.com/go-acme/tencentedgdeone v1.1.48 h1:WLyLBsRVhSLFmtbEFXk0naLODSQn7X6J0Fc/qR8xVUk=\ngithub.com/go-acme/tencentedgdeone v1.1.48/go.mod h1:mu6tA+bPhlSd+CKUfzRikE0mfxmTlBI6dVTn9LY9dRI=\ngithub.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=\ngithub.com/go-cmd/cmd v1.0.5/go.mod h1:y8q8qlK5wQibcw63djSl/ntiHUHXHGdCkPk0j4QeW4s=\ngithub.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=\ngithub.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=\ngithub.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=\ngithub.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=\ngithub.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=\ngithub.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=\ngithub.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=\ngithub.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU=\ngithub.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg=\ngithub.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=\ngithub.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=\ngithub.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=\ngithub.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=\ngithub.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=\ngithub.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=\ngithub.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=\ngithub.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=\ngithub.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=\ngithub.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=\ngithub.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=\ngithub.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=\ngithub.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=\ngithub.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=\ngithub.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=\ngithub.com/go-openapi/jsonpointer v0.21.2 h1:AqQaNADVwq/VnkCmQg6ogE+M3FOsKTytwges0JdwVuA=\ngithub.com/go-openapi/jsonpointer v0.21.2/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=\ngithub.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=\ngithub.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=\ngithub.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=\ngithub.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=\ngithub.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=\ngithub.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=\ngithub.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=\ngithub.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=\ngithub.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=\ngithub.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=\ngithub.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=\ngithub.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=\ngithub.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=\ngithub.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=\ngithub.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=\ngithub.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=\ngithub.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=\ngithub.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=\ngithub.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=\ngithub.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=\ngithub.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=\ngithub.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=\ngithub.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=\ngithub.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=\ngithub.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=\ngithub.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=\ngithub.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=\ngithub.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=\ngithub.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=\ngithub.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=\ngithub.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=\ngithub.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=\ngithub.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=\ngithub.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=\ngithub.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=\ngithub.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=\ngithub.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=\ngithub.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b h1:/vQ+oYKu+JoyaMPDsv5FzwuL2wwWBgBbtj/YLCi4LuA=\ngithub.com/gobs/pretty v0.0.0-20180724170744-09732c25a95b/go.mod h1:Xo4aNUOrJnVruqWQJBtW6+bTBDTniY8yZum5rF3b5jw=\ngithub.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=\ngithub.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=\ngithub.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=\ngithub.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=\ngithub.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=\ngithub.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=\ngithub.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=\ngithub.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=\ngithub.com/goccy/go-json v0.7.8/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=\ngithub.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=\ngithub.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=\ngithub.com/goccy/go-yaml v1.9.8/go.mod h1:JubOolP3gh0HpiBc4BLRD4YmjEjHAmIIB2aaXKkTfoE=\ngithub.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=\ngithub.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=\ngithub.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=\ngithub.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=\ngithub.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=\ngithub.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=\ngithub.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=\ngithub.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=\ngithub.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=\ngithub.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=\ngithub.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=\ngithub.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=\ngithub.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=\ngithub.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=\ngithub.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=\ngithub.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=\ngithub.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=\ngithub.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=\ngithub.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=\ngithub.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=\ngithub.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=\ngithub.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=\ngithub.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=\ngithub.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=\ngithub.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=\ngithub.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=\ngithub.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=\ngithub.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=\ngithub.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=\ngithub.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=\ngithub.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=\ngithub.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=\ngithub.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=\ngithub.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=\ngithub.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=\ngithub.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=\ngithub.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=\ngithub.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=\ngithub.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=\ngithub.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=\ngithub.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=\ngithub.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=\ngithub.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=\ngithub.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=\ngithub.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=\ngithub.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=\ngithub.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=\ngithub.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=\ngithub.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=\ngithub.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=\ngithub.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=\ngithub.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=\ngithub.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=\ngithub.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=\ngithub.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=\ngithub.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=\ngithub.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=\ngithub.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=\ngithub.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=\ngithub.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=\ngithub.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=\ngithub.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=\ngithub.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=\ngithub.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=\ngithub.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=\ngithub.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=\ngithub.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=\ngithub.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=\ngithub.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=\ngithub.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=\ngithub.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=\ngithub.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=\ngithub.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=\ngithub.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=\ngithub.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=\ngithub.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=\ngithub.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=\ngithub.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=\ngithub.com/googleapis/gax-go/v2 v2.15.0 h1:SyjDc1mGgZU5LncH8gimWo9lW1DtIfPibOG81vgd/bo=\ngithub.com/googleapis/gax-go/v2 v2.15.0/go.mod h1:zVVkkxAQHa1RQpg9z2AUCMnKhi0Qld9rcmyfL1OZhoc=\ngithub.com/gophercloud/gophercloud v1.3.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=\ngithub.com/gophercloud/gophercloud v1.14.1 h1:DTCNaTVGl8/cFu58O1JwWgis9gtISAFONqpMKNg/Vpw=\ngithub.com/gophercloud/gophercloud v1.14.1/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=\ngithub.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 h1:sH7xkTfYzxIEgzq1tDHIMKRh1vThOEOGNsettdEeLbE=\ngithub.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56/go.mod h1:VSalo4adEk+3sNkmVJLnhHoOyOYYS8sTWLG4mv5BKto=\ngithub.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=\ngithub.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=\ngithub.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=\ngithub.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=\ngithub.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=\ngithub.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=\ngithub.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=\ngithub.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=\ngithub.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf h1:C1GPyPJrOlJlIrcaBBiBpDsqZena2Ks8spa5xZqr1XQ=\ngithub.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf/go.mod h1:zXqxTI6jXDdKnlf8s+nT+3c8LrwUEy3yNpO4XJL90lA=\ngithub.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=\ngithub.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=\ngithub.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=\ngithub.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=\ngithub.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=\ngithub.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=\ngithub.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=\ngithub.com/hashicorp/consul/api v1.26.1 h1:5oSXOO5fboPZeW5SN+TdGFP/BILDgBm19OrPZ/pICIM=\ngithub.com/hashicorp/consul/api v1.26.1/go.mod h1:B4sQTeaSO16NtynqrAdwOlahJ7IUDZM9cj2420xYL8A=\ngithub.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=\ngithub.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=\ngithub.com/hashicorp/consul/sdk v0.15.0 h1:2qK9nDrr4tiJKRoxPGhm6B7xJjLVIQqkjiab2M4aKjU=\ngithub.com/hashicorp/consul/sdk v0.15.0/go.mod h1:r/OmRRPbHOe0yxNahLw7G9x5WG17E1BIECMtCjcPSNo=\ngithub.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=\ngithub.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=\ngithub.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=\ngithub.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=\ngithub.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=\ngithub.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=\ngithub.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=\ngithub.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=\ngithub.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=\ngithub.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=\ngithub.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=\ngithub.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=\ngithub.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=\ngithub.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=\ngithub.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=\ngithub.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=\ngithub.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=\ngithub.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=\ngithub.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=\ngithub.com/hashicorp/go-msgpack/v2 v2.1.2 h1:4Ee8FTp834e+ewB71RDrQ0VKpyFdrKOjvYtnQ/ltVj0=\ngithub.com/hashicorp/go-msgpack/v2 v2.1.2/go.mod h1:upybraOAblm4S7rx0+jeNy+CWWhzywQsSRV5033mMu4=\ngithub.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=\ngithub.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=\ngithub.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=\ngithub.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=\ngithub.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=\ngithub.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=\ngithub.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=\ngithub.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=\ngithub.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=\ngithub.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=\ngithub.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=\ngithub.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=\ngithub.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=\ngithub.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=\ngithub.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=\ngithub.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=\ngithub.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=\ngithub.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=\ngithub.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=\ngithub.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=\ngithub.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=\ngithub.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=\ngithub.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=\ngithub.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=\ngithub.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=\ngithub.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=\ngithub.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=\ngithub.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=\ngithub.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=\ngithub.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=\ngithub.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=\ngithub.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=\ngithub.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0=\ngithub.com/hashicorp/memberlist v0.5.1 h1:mk5dRuzeDNis2bi6LLoQIXfMH7JQvAzt3mQD0vNZZUo=\ngithub.com/hashicorp/memberlist v0.5.1/go.mod h1:zGDXV6AqbDTKTM6yxW0I4+JtFzZAJVoIPvss4hV8F24=\ngithub.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b h1:R1UDhkwGltpSPY9bCBBxIMQd+NY9BkN0vFHnJo/8o8w=\ngithub.com/hashicorp/nomad/api v0.0.0-20231213195942-64e3dca9274b/go.mod h1:ijDwa6o1uG1jFSq6kERiX2PamKGpZzTmo0XOFNeFZgw=\ngithub.com/hashicorp/raft v1.1.0/go.mod h1:4Ak7FSPnuvmb0GV6vgIAJ4vYT4bek9bb6Q+7HVbyzqM=\ngithub.com/hashicorp/raft v1.7.1 h1:ytxsNx4baHsRZrhUcbt3+79zc4ly8qm7pi0393pSchY=\ngithub.com/hashicorp/raft v1.7.1/go.mod h1:hUeiEwQQR/Nk2iKDD0dkEhklSsu3jcAcqvPzPoZSAEM=\ngithub.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702 h1:RLKEcCuKcZ+qp2VlaaZsYZfLOmIiuJNpEi48Rl8u9cQ=\ngithub.com/hashicorp/raft-boltdb v0.0.0-20230125174641-2a8082862702/go.mod h1:nTakvJ4XYq45UXtn0DbwR4aU9ZdjlnIenpbs6Cd+FM0=\ngithub.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=\ngithub.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=\ngithub.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=\ngithub.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=\ngithub.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=\ngithub.com/http-wasm/http-wasm-host-go v0.7.0 h1:+1KrRyOO6tWiDB24QrtSYyDmzFLBBs3jioKaUT0mq1c=\ngithub.com/http-wasm/http-wasm-host-go v0.7.0/go.mod h1:adXKcLmL7yuavH/e0kBAp7b3TgAHTo/enCduyN5bXGM=\ngithub.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=\ngithub.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=\ngithub.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.173 h1:Y4ixGadyrK9xHw6Z+cyiiME3SBXepEcUoiT+B8C5FoQ=\ngithub.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.173/go.mod h1:M+yna96Fx9o5GbIUnF3OvVvQGjgfVSyeJbV9Yb1z/wI=\ngithub.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=\ngithub.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=\ngithub.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=\ngithub.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=\ngithub.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=\ngithub.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=\ngithub.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=\ngithub.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=\ngithub.com/influxdata/influxdb-client-go/v2 v2.7.0 h1:QgP5mlBE9sGnzplpnf96pr+p7uqlIlL4W2GAP3n+XZg=\ngithub.com/influxdata/influxdb-client-go/v2 v2.7.0/go.mod h1:Y/0W1+TZir7ypoQZYd2IrnVOKB3Tq6oegAQeSVN/+EU=\ngithub.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab h1:HqW4xhhynfjrtEiiSGcQUd6vrK23iMam1FO8rI7mwig=\ngithub.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=\ngithub.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=\ngithub.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=\ngithub.com/infobloxopen/infoblox-go-client/v2 v2.10.0 h1:AKsihjFT/t6Y0keEv3p59DACcOuh0inWXdUB0ZOzYH0=\ngithub.com/infobloxopen/infoblox-go-client/v2 v2.10.0/go.mod h1:NeNJpz09efw/edzqkVivGv1bWqBXTomqYBRFbP+XBqg=\ngithub.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=\ngithub.com/jarcoal/httpmock v1.4.1 h1:0Ju+VCFuARfFlhVXFc2HxlcQkfB+Xq12/EotHko+x2A=\ngithub.com/jarcoal/httpmock v1.4.1/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0=\ngithub.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=\ngithub.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=\ngithub.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=\ngithub.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=\ngithub.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=\ngithub.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=\ngithub.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=\ngithub.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=\ngithub.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=\ngithub.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=\ngithub.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=\ngithub.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=\ngithub.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=\ngithub.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=\ngithub.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=\ngithub.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=\ngithub.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=\ngithub.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=\ngithub.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=\ngithub.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=\ngithub.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12 h1:9Nu54bhS/H/Kgo2/7xNSUuC5G28VR8ljfrLKU2G4IjU=\ngithub.com/json-iterator/go v1.1.13-0.20220915233716-71ac16282d12/go.mod h1:TBzl5BIHNXfS9+C35ZyJaklL7mLDbgUkcgXzSLa8Tk0=\ngithub.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=\ngithub.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=\ngithub.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=\ngithub.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=\ngithub.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=\ngithub.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=\ngithub.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=\ngithub.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=\ngithub.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=\ngithub.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=\ngithub.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=\ngithub.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=\ngithub.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=\ngithub.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=\ngithub.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=\ngithub.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=\ngithub.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=\ngithub.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=\ngithub.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=\ngithub.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=\ngithub.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=\ngithub.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=\ngithub.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=\ngithub.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=\ngithub.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=\ngithub.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=\ngithub.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=\ngithub.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=\ngithub.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=\ngithub.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=\ngithub.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=\ngithub.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=\ngithub.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=\ngithub.com/kvtools/consul v1.0.2 h1:ltPgs4Ld09Xaa7zrOJ/TewBYKAsr11/LRFpErdkb8AA=\ngithub.com/kvtools/consul v1.0.2/go.mod h1:bFnzfGJ5ZIRRXCBGBmwhJlLdEWOlrjOcS1WjyAQzaJA=\ngithub.com/kvtools/etcdv3 v1.0.3 h1:bsaGf8Jsi8Xq6h/KVV/D7F/c1IuVQv2f7tuVxeA//fk=\ngithub.com/kvtools/etcdv3 v1.0.3/go.mod h1:ID4AIRgCuCRzzdITo9O5RKUtLwfu/zJvCvosrFcBK4U=\ngithub.com/kvtools/redis v1.2.0 h1:l2wT//fjNPXS66kENuUdIQrSReq4OQxmL4pKH4T65c4=\ngithub.com/kvtools/redis v1.2.0/go.mod h1:EPXcbf7IfiIH05eBDSrR9RKQQmxI83JKL4tsUhPECuk=\ngithub.com/kvtools/valkeyrie v1.0.0 h1:LAITop2wPoYCMitR24GZZsW0b57hmI+ePD18VRTtOf0=\ngithub.com/kvtools/valkeyrie v1.0.0/go.mod h1:bDi/OdhJCSbGPMsCgUQl881yuEweKCSItAtTBI+ZjpU=\ngithub.com/kvtools/zookeeper v1.0.2 h1:uK0CzQa+mtKGxDDH+DeqXo2HC1Kx4hWXZ7pX/zS4aTo=\ngithub.com/kvtools/zookeeper v1.0.2/go.mod h1:6TfxUwJ7IuBk5srgnoe528W0ftanNECHgOiShx/t0Aw=\ngithub.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=\ngithub.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=\ngithub.com/labbsr0x/bindman-dns-webhook v1.0.2 h1:I7ITbmQPAVwrDdhd6dHKi+MYJTJqPCK0jE6YNBAevnk=\ngithub.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=\ngithub.com/labbsr0x/goh v1.0.1 h1:97aBJkDjpyBZGPbQuOK5/gHcSFbcr5aRsq3RSRJFpPk=\ngithub.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=\ngithub.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=\ngithub.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A=\ngithub.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=\ngithub.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=\ngithub.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=\ngithub.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=\ngithub.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=\ngithub.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=\ngithub.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=\ngithub.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=\ngithub.com/lestrrat-go/codegen v1.0.2/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM=\ngithub.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=\ngithub.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=\ngithub.com/lestrrat-go/jwx v1.2.7/go.mod h1:bw24IXWbavc0R2RsOtpXL7RtMyP589yZ1+L7kd09ZGA=\ngithub.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=\ngithub.com/linode/linodego v1.60.0 h1:SgsebJFRCi+lSmYy+C40wmKZeJllGGm+W12Qw4+yVdI=\ngithub.com/linode/linodego v1.60.0/go.mod h1:1+Bt0oTz5rBnDOJbGhccxn7LYVytXTIIfAy7QYmijDs=\ngithub.com/liquidweb/go-lwApi v0.0.0-20190605172801-52a4864d2738/go.mod h1:0sYF9rMXb0vlG+4SzdiGMXHheCZxjguMq+Zb4S2BfBs=\ngithub.com/liquidweb/liquidweb-cli v0.6.9 h1:acbIvdRauiwbxIsOCEMXGwF75aSJDbDiyAWPjVnwoYM=\ngithub.com/liquidweb/liquidweb-cli v0.6.9/go.mod h1:cE1uvQ+x24NGUL75D0QagOFCG8Wdvmwu8aL9TLmA/eQ=\ngithub.com/liquidweb/liquidweb-go v1.6.4 h1:6S0m3hHSpiLqGD7AFSb7lH/W/qr1wx+tKil9fgIbjMc=\ngithub.com/liquidweb/liquidweb-go v1.6.4/go.mod h1:B934JPIIcdA+uTq2Nz5PgOtG6CuCaEvQKe/Ge/5GgZ4=\ngithub.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=\ngithub.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=\ngithub.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=\ngithub.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=\ngithub.com/mailgun/multibuf v0.1.2 h1:QE9kE27lK6LFZB4aYNVtUPlWVHVCT0zpgUr2uoq/+jk=\ngithub.com/mailgun/multibuf v0.1.2/go.mod h1:E+sUhIy69qgT6EM57kCPdUTlHnjTuxQBO/yf6af9Hes=\ngithub.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ=\ngithub.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51/go.mod h1:RYmqHbhWwIz3z9eVmQ2rx82rulEMG0t+Q1bzfc9DYN4=\ngithub.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f h1:ZZYhg16XocqSKPGNQAe0aeweNtFxuedbwwb4fSlg7h4=\ngithub.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f/go.mod h1:8heskWJ5c0v5J9WH89ADhyal1DOZcayll8fSbhB+/9A=\ngithub.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=\ngithub.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=\ngithub.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=\ngithub.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=\ngithub.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=\ngithub.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=\ngithub.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=\ngithub.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=\ngithub.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=\ngithub.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=\ngithub.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=\ngithub.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=\ngithub.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=\ngithub.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=\ngithub.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=\ngithub.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=\ngithub.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=\ngithub.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=\ngithub.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=\ngithub.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=\ngithub.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=\ngithub.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=\ngithub.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\ngithub.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=\ngithub.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=\ngithub.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=\ngithub.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0=\ngithub.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=\ngithub.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=\ngithub.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=\ngithub.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=\ngithub.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=\ngithub.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=\ngithub.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=\ngithub.com/miekg/dns v1.1.47/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=\ngithub.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=\ngithub.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=\ngithub.com/mimuret/golang-iij-dpf v0.9.1 h1:Gj6EhHJkOhr+q2RnvRPJsPMcjuVnWPSccEHyoEehU34=\ngithub.com/mimuret/golang-iij-dpf v0.9.1/go.mod h1:sl9KyOkESib9+KRD3HaGpgi1xk7eoN2+d96LCLsME2M=\ngithub.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=\ngithub.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=\ngithub.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=\ngithub.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=\ngithub.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=\ngithub.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=\ngithub.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=\ngithub.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=\ngithub.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=\ngithub.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=\ngithub.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=\ngithub.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=\ngithub.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=\ngithub.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=\ngithub.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=\ngithub.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=\ngithub.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=\ngithub.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=\ngithub.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE=\ngithub.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=\ngithub.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=\ngithub.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=\ngithub.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=\ngithub.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=\ngithub.com/moby/moby/api v1.52.0 h1:00BtlJY4MXkkt84WhUZPRqt5TvPbgig2FZvTbe3igYg=\ngithub.com/moby/moby/api v1.52.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=\ngithub.com/moby/moby/client v0.1.0 h1:nt+hn6O9cyJQqq5UWnFGqsZRTS/JirUqzPjEl0Bdc/8=\ngithub.com/moby/moby/client v0.1.0/go.mod h1:O+/tw5d4a1Ha/ZA/tPxIZJapJRUS6LNZ1wiVRxYHyUE=\ngithub.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=\ngithub.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=\ngithub.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=\ngithub.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=\ngithub.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=\ngithub.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=\ngithub.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=\ngithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=\ngithub.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=\ngithub.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=\ngithub.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=\ngithub.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=\ngithub.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=\ngithub.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=\ngithub.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=\ngithub.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=\ngithub.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=\ngithub.com/namedotcom/go/v4 v4.0.2 h1:4gNkPaPRG/2tqFNUUof7jAVsA6vDutFutEOd7ivnDwA=\ngithub.com/namedotcom/go/v4 v4.0.2/go.mod h1:J6sVueHMb0qbarPgdhrzEVhEaYp+R1SCaTGl2s6/J1Q=\ngithub.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q=\ngithub.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY=\ngithub.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g=\ngithub.com/nats-io/nats.go v1.12.1/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=\ngithub.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=\ngithub.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=\ngithub.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=\ngithub.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=\ngithub.com/nrdcg/auroradns v1.1.0 h1:KekGh8kmf2MNwqZVVYo/fw/ZONt8QMEmbMFOeljteWo=\ngithub.com/nrdcg/auroradns v1.1.0/go.mod h1:O7tViUZbAcnykVnrGkXzIJTHoQCHcgalgAe6X1mzHfk=\ngithub.com/nrdcg/bunny-go v0.1.0 h1:GAHTRpHaG/TxfLZlqoJ8OJFzw8rI74+jOTkzxWh0uHA=\ngithub.com/nrdcg/bunny-go v0.1.0/go.mod h1:u+C9dgsspgtWVaAz6QkyV17s9fxD8viwwKoxb9XMz1A=\ngithub.com/nrdcg/desec v0.11.1 h1:ilpKmCr4gGsLcyq3RHfHNmlRzm9fzT2XbWxoVaUCS0s=\ngithub.com/nrdcg/desec v0.11.1/go.mod h1:2LuxHlOcwML/7cntu0eimONmA1U+ZxFDAonoSXr4igQ=\ngithub.com/nrdcg/dnspod-go v0.4.0 h1:c/jn1mLZNKF3/osJ6mz3QPxTudvPArXTjpkmYj0uK6U=\ngithub.com/nrdcg/dnspod-go v0.4.0/go.mod h1:vZSoFSFeQVm2gWLMkyX61LZ8HI3BaqtHZWgPTGKr6KQ=\ngithub.com/nrdcg/freemyip v0.3.0 h1:0D2rXgvLwe2RRaVIjyUcQ4S26+cIS2iFwnhzDsEuuwc=\ngithub.com/nrdcg/freemyip v0.3.0/go.mod h1:c1PscDvA0ukBF0dwelU/IwOakNKnVxetpAQ863RMJoM=\ngithub.com/nrdcg/goacmedns v0.2.0 h1:ADMbThobzEMnr6kg2ohs4KGa3LFqmgiBA22/6jUWJR0=\ngithub.com/nrdcg/goacmedns v0.2.0/go.mod h1:T5o6+xvSLrQpugmwHvrSNkzWht0UGAwj2ACBMhh73Cg=\ngithub.com/nrdcg/goinwx v0.11.0 h1:GER0SE3POub7rxARt3Y3jRy1OON1hwF1LRxHz5xsFBw=\ngithub.com/nrdcg/goinwx v0.11.0/go.mod h1:0BXSC0FxVtU4aTjX0Zw3x0DK32tjugLzeNIAGtwXvPQ=\ngithub.com/nrdcg/mailinabox v0.3.0 h1:PHkC1elKXKAjEvdx2HHFMgcEGZFqudAl7aU3L2JDhM4=\ngithub.com/nrdcg/mailinabox v0.3.0/go.mod h1:1eFIGcM4lI+AfFOUpbs548SFGz1ZWoMOGbECBmkghw4=\ngithub.com/nrdcg/namesilo v0.5.0 h1:6QNxT/XxE+f5B+7QlfWorthNzOzcGlBLRQxqi6YeBrE=\ngithub.com/nrdcg/namesilo v0.5.0/go.mod h1:4UkwlwQfDt74kSGmhLaDylnBrD94IfflnpoEaj6T2qw=\ngithub.com/nrdcg/nodion v0.1.0 h1:zLKaqTn2X0aDuBHHfyA1zFgeZfiCpmu/O9DM73okavw=\ngithub.com/nrdcg/nodion v0.1.0/go.mod h1:inbuh3neCtIWlMPZHtEpe43TmRXxHV6+hk97iCZicms=\ngithub.com/nrdcg/oci-go-sdk/common/v1065 v1065.103.0 h1:GPwwX9GFIBjV4u1M3Cr8eKCP6drW01IsfQSDIz6SUk8=\ngithub.com/nrdcg/oci-go-sdk/common/v1065 v1065.103.0/go.mod h1:SfDIKzNQ5AGNMMOA3LGqSPnn63F6Gc4E4bsKArqymvg=\ngithub.com/nrdcg/oci-go-sdk/dns/v1065 v1065.103.0 h1:MjHla6lf1jpjGXORLpzMeo/tSmx0ejmjMjdjTByaDGY=\ngithub.com/nrdcg/oci-go-sdk/dns/v1065 v1065.103.0/go.mod h1:o1/kMADX0SlB4hJjWtcs3M6VIUOGR78yhPyiBv6oBkk=\ngithub.com/nrdcg/porkbun v0.4.0 h1:rWweKlwo1PToQ3H+tEO9gPRW0wzzgmI/Ob3n2Guticw=\ngithub.com/nrdcg/porkbun v0.4.0/go.mod h1:/QMskrHEIM0IhC/wY7iTCUgINsxdT2WcOphktJ9+Q54=\ngithub.com/nrdcg/vegadns v0.3.0 h1:11FQMw7xVIRUWO9o5+Z/5YZhmPWlm4oxUUH3F6EVqQU=\ngithub.com/nrdcg/vegadns v0.3.0/go.mod h1:NqSyRKZuJlAsv8VI/7rSubfPXN68NwaJ0aG9KxQVFVo=\ngithub.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=\ngithub.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=\ngithub.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=\ngithub.com/nzdjb/go-metaname v1.0.0 h1:sNASlZC1RM3nSudtBTE1a3ZVTDyTpjqI5WXRPrdZ9Hg=\ngithub.com/nzdjb/go-metaname v1.0.0/go.mod h1:0GR0LshZax1Lz4VrOrfNSE4dGvTp7HGjiemdczXT2H4=\ngithub.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=\ngithub.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=\ngithub.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=\ngithub.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=\ngithub.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=\ngithub.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=\ngithub.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=\ngithub.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=\ngithub.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=\ngithub.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0=\ngithub.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=\ngithub.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=\ngithub.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=\ngithub.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=\ngithub.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=\ngithub.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=\ngithub.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=\ngithub.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=\ngithub.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=\ngithub.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=\ngithub.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=\ngithub.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=\ngithub.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=\ngithub.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=\ngithub.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=\ngithub.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=\ngithub.com/ovh/go-ovh v1.9.0 h1:6K8VoL3BYjVV3In9tPJUdT7qMx9h0GExN9EXx1r2kKE=\ngithub.com/ovh/go-ovh v1.9.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=\ngithub.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=\ngithub.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=\ngithub.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=\ngithub.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=\ngithub.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=\ngithub.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=\ngithub.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=\ngithub.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=\ngithub.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=\ngithub.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=\ngithub.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c=\ngithub.com/peterhellberg/link v1.2.0/go.mod h1:gYfAh+oJgQu2SrZHg5hROVRQe1ICoK0/HHJTcE0edxc=\ngithub.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=\ngithub.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=\ngithub.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=\ngithub.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=\ngithub.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=\ngithub.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=\ngithub.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=\ngithub.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=\ngithub.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=\ngithub.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=\ngithub.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=\ngithub.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=\ngithub.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=\ngithub.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=\ngithub.com/pquerna/otp v1.5.0 h1:NMMR+WrmaqXU4EzdGJEE1aUUI0AMRzsp96fFFWNPwxs=\ngithub.com/pquerna/otp v1.5.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=\ngithub.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=\ngithub.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=\ngithub.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=\ngithub.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=\ngithub.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=\ngithub.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=\ngithub.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=\ngithub.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=\ngithub.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=\ngithub.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=\ngithub.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=\ngithub.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=\ngithub.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=\ngithub.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=\ngithub.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=\ngithub.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=\ngithub.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=\ngithub.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=\ngithub.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=\ngithub.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=\ngithub.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=\ngithub.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=\ngithub.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=\ngithub.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=\ngithub.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=\ngithub.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=\ngithub.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=\ngithub.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=\ngithub.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=\ngithub.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=\ngithub.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=\ngithub.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=\ngithub.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=\ngithub.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=\ngithub.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=\ngithub.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=\ngithub.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=\ngithub.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=\ngithub.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=\ngithub.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=\ngithub.com/redis/go-redis/v9 v9.16.0 h1:OotgqgLSRCmzfqChbQyG1PHC3tLNR89DG4jdOERSEP4=\ngithub.com/redis/go-redis/v9 v9.16.0/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0//kSOd3370=\ngithub.com/regfish/regfish-dnsapi-go v0.1.1 h1:TJFtbePHkd47q5GZwYl1h3DIYXmoxdLjW/SBsPtB5IE=\ngithub.com/regfish/regfish-dnsapi-go v0.1.1/go.mod h1:ubIgXSfqarSnl3XHSn8hIFwFF3h0yrq0ZiWD93Y2VjY=\ngithub.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=\ngithub.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=\ngithub.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=\ngithub.com/robertkrimen/otto v0.5.1 h1:avDI4ToRk8k1hppLdYFTuuzND41n37vPGJU7547dGf0=\ngithub.com/robertkrimen/otto v0.5.1/go.mod h1:bS433I4Q9p+E5pZLu7r17vP6FkE6/wLxBdmKjoqJXF8=\ngithub.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=\ngithub.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=\ngithub.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=\ngithub.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=\ngithub.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=\ngithub.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=\ngithub.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=\ngithub.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=\ngithub.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=\ngithub.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=\ngithub.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=\ngithub.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=\ngithub.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=\ngithub.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=\ngithub.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=\ngithub.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=\ngithub.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=\ngithub.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=\ngithub.com/sacloud/api-client-go v0.3.3 h1:ZpSAyGpITA8UFO3Hq4qMHZLGuNI1FgxAxo4sqBnCKDs=\ngithub.com/sacloud/api-client-go v0.3.3/go.mod h1:0p3ukcWYXRCc2AUWTl1aA+3sXLvurvvDqhRaLZRLBwo=\ngithub.com/sacloud/go-http v0.1.9 h1:Xa5PY8/pb7XWhwG9nAeXSrYXPbtfBWqawgzxD5co3VE=\ngithub.com/sacloud/go-http v0.1.9/go.mod h1:DpDG+MSyxYaBwPJ7l3aKLMzwYdTVtC5Bo63HActcgoE=\ngithub.com/sacloud/iaas-api-go v1.20.0 h1:L4TfAzoFSwxrD3QXX8UxJa2o+GZrP9b863K+voTy3tQ=\ngithub.com/sacloud/iaas-api-go v1.20.0/go.mod h1:XV995RM1I7k5AHb7UZrCVyDF/8bZXDxa+uk1EXoj/Zs=\ngithub.com/sacloud/packages-go v0.0.11 h1:hrRWLmfPM9w7GBs6xb5/ue6pEMl8t1UuDKyR/KfteHo=\ngithub.com/sacloud/packages-go v0.0.11/go.mod h1:XNF5MCTWcHo9NiqWnYctVbASSSZR3ZOmmQORIzcurJ8=\ngithub.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=\ngithub.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=\ngithub.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=\ngithub.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=\ngithub.com/scaleway/scaleway-sdk-go v1.0.0-beta.35 h1:8xfn1RzeI9yoCUuEwDy08F+No6PcKZGEDOQ6hrRyLts=\ngithub.com/scaleway/scaleway-sdk-go v1.0.0-beta.35/go.mod h1:47B1d/YXmSAxlJxUJxClzHR6b3T4M1WyCvwENPQNBWc=\ngithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=\ngithub.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=\ngithub.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=\ngithub.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=\ngithub.com/selectel/domains-go v1.1.0 h1:futG50J43ALLKQAnZk9H9yOtLGnSUh7c5hSvuC5gSHo=\ngithub.com/selectel/domains-go v1.1.0/go.mod h1:SugRKfq4sTpnOHquslCpzda72wV8u0cMBHx0C0l+bzA=\ngithub.com/selectel/go-selvpcclient/v4 v4.1.0 h1:22lBp+rzg9g2MP4iiGhpVAcCt0kMv7I7uV1W3taLSvQ=\ngithub.com/selectel/go-selvpcclient/v4 v4.1.0/go.mod h1:eFhL1KUW159KOJVeGO7k/Uxl0TYd/sBkWXjuF5WxmYk=\ngithub.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=\ngithub.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=\ngithub.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk=\ngithub.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI=\ngithub.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=\ngithub.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=\ngithub.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=\ngithub.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=\ngithub.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=\ngithub.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=\ngithub.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=\ngithub.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=\ngithub.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=\ngithub.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=\ngithub.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=\ngithub.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=\ngithub.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0=\ngithub.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=\ngithub.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 h1:hp2CYQUINdZMHdvTdXtPOY2ainKl4IoMcpAXEf2xj3Q=\ngithub.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=\ngithub.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=\ngithub.com/smartystreets/gunit v1.0.4 h1:tpTjnuH7MLlqhoD21vRoMZbMIi5GmBsAJDFyF67GhZA=\ngithub.com/smartystreets/gunit v1.0.4/go.mod h1:EH5qMBab2UclzXUcpR8b93eHsIlp9u+pDQIRp5DZNzQ=\ngithub.com/softlayer/softlayer-go v1.2.1 h1:8ucHxn5laVsVPb0/aMGnr6tOMt1I9BgEtU5mn70OGKw=\ngithub.com/softlayer/softlayer-go v1.2.1/go.mod h1:Gz9/ktcmB7Z8EJlu+QEJJpkv8lAmnhYdB9Tc6gedjmo=\ngithub.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e h1:3OgWYFw7jxCZPcvAg+4R8A50GZ+CCkARF10lxu2qDsQ=\ngithub.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e/go.mod h1:fKZCUVdirrxrBpwd9wb+lSoVixvpwAu8eHzbQB2tums=\ngithub.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=\ngithub.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=\ngithub.com/sony/gobreaker v1.0.0 h1:feX5fGGXSl3dYd4aHZItw+FpHLvvoaqkawKjVNiFMNQ=\ngithub.com/sony/gobreaker v1.0.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=\ngithub.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=\ngithub.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=\ngithub.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=\ngithub.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=\ngithub.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=\ngithub.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=\ngithub.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=\ngithub.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=\ngithub.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=\ngithub.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=\ngithub.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=\ngithub.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=\ngithub.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=\ngithub.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=\ngithub.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=\ngithub.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=\ngithub.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=\ngithub.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=\ngithub.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=\ngithub.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=\ngithub.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE=\ngithub.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g=\ngithub.com/stealthrocket/wasi-go v0.8.0 h1:Hwnv3CUoMhhRyero9vt1vfwaYa9tu/Z5kmCW4WeAmVI=\ngithub.com/stealthrocket/wasi-go v0.8.0/go.mod h1:PJ5oVs2E1ciOJnsTnav4nvTtEcJ4D1jUZAewS9pzuZg=\ngithub.com/stealthrocket/wazergo v0.19.1 h1:BPrITETPgSFwiytwmToO0MbUC/+RGC39JScz1JmmG6c=\ngithub.com/stealthrocket/wazergo v0.19.1/go.mod h1:riI0hxw4ndZA5e6z7PesHg2BtTftcZaMxRcoiGGipTs=\ngithub.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=\ngithub.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=\ngithub.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=\ngithub.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=\ngithub.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=\ngithub.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=\ngithub.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=\ngithub.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=\ngithub.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngithub.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=\ngithub.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=\ngithub.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807 h1:LUsDduamlucuNnWcaTbXQ6aLILFcLXADpOzeEH3U+OI=\ngithub.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=\ngithub.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=\ngithub.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=\ngithub.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=\ngithub.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.10/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=\ngithub.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.48 h1:aoRUrz2ag27jQWcOKHgeE+toSti6/xPqHKMLruOtJuM=\ngithub.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.1.48/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=\ngithub.com/tetratelabs/wazero v1.8.0 h1:iEKu0d4c2Pd+QSRieYbnQC9yiFlMS9D+Jr0LsRmcF4g=\ngithub.com/tetratelabs/wazero v1.8.0/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=\ngithub.com/tidwall/resp v0.1.1 h1:Ly20wkhqKTmDUPlyM1S7pWo5kk0tDu8OoC/vFArXmwE=\ngithub.com/tidwall/resp v0.1.1/go.mod h1:3/FrruOBAxPTPtundW0VXgmsQ4ZBA0Aw714lVYgwFa0=\ngithub.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=\ngithub.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=\ngithub.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=\ngithub.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=\ngithub.com/traefik/grpc-web v0.16.0 h1:eeUWZaFg6ZU0I9dWOYE2D5qkNzRBmXzzuRlxdltascY=\ngithub.com/traefik/grpc-web v0.16.0/go.mod h1:2ttniSv7pTgBWIU2HZLokxRfFX3SA60c/DTmQQgVml4=\ngithub.com/traefik/paerser v0.2.2 h1:cpzW/ZrQrBh3mdwD/jnp6aXASiUFKOVr6ldP+keJTcQ=\ngithub.com/traefik/paerser v0.2.2/go.mod h1:7BBDd4FANoVgaTZG+yh26jI6CA2nds7D/4VTEdIsh24=\ngithub.com/traefik/traefik/v3 v3.6.1 h1:2V3l5HXe3+9B5mGQ4HAe4lD2sx7PolFWCy6RNUE16SQ=\ngithub.com/traefik/traefik/v3 v3.6.1/go.mod h1:82/EIeYGZXjHvBfOizWI4VA1SV39fcVHRKNwDWHTD1w=\ngithub.com/traefik/yaegi v0.16.1 h1:f1De3DVJqIDKmnasUF6MwmWv1dSEEat0wcpXhD2On3E=\ngithub.com/traefik/yaegi v0.16.1/go.mod h1:4eVhbPb3LnD2VigQjhYbEJ69vDRFdT2HQNrXx8eEwUY=\ngithub.com/transip/gotransip/v6 v6.26.1 h1:MeqIjkTBBsZwWAK6giZyMkqLmKMclVHEuTNmoBdx4MA=\ngithub.com/transip/gotransip/v6 v6.26.1/go.mod h1:x0/RWGRK/zob817O3tfO2xhFoP1vu8YOHORx6Jpk80s=\ngithub.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=\ngithub.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=\ngithub.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=\ngithub.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=\ngithub.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=\ngithub.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=\ngithub.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=\ngithub.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=\ngithub.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=\ngithub.com/ultradns/ultradns-go-sdk v1.8.1-20250722213956-faef419 h1:/VaznPrb/b68e3iMvkr27fU7JqPKU4j7tIITZnjQX1k=\ngithub.com/ultradns/ultradns-go-sdk v1.8.1-20250722213956-faef419/go.mod h1:QN0/PdenvYWB0GRMz6JJbPeZz2Lph2iys1p8AFVHm2c=\ngithub.com/unrolled/render v1.0.2 h1:dGS3EmChQP3yOi1YeFNO/Dx+MbWZhdvhQJTXochM5bs=\ngithub.com/unrolled/render v1.0.2/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0obPf6NBdM=\ngithub.com/unrolled/secure v1.0.9 h1:BWRuEb1vDrBFFDdbCnKkof3gZ35I/bnHGyt0LB0TNyQ=\ngithub.com/unrolled/secure v1.0.9/go.mod h1:fO+mEan+FLB0CdEnHf6Q4ZZVNqG+5fuLFnP8p0BXDPI=\ngithub.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=\ngithub.com/urfave/cli/v2 v2.27.7 h1:bH59vdhbjLv3LAvIu6gd0usJHgoTTPhCFib8qqOwXYU=\ngithub.com/urfave/cli/v2 v2.27.7/go.mod h1:CyNAG/xg+iAOg0N4MPGZqVmv2rCoP267496AOXUZjA4=\ngithub.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=\ngithub.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=\ngithub.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=\ngithub.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=\ngithub.com/valyala/fasthttp v1.68.0 h1:v12Nx16iepr8r9ySOwqI+5RBJ/DqTxhOy1HrHoDFnok=\ngithub.com/valyala/fasthttp v1.68.0/go.mod h1:5EXiRfYQAoiO/khu4oU9VISC/eVY6JqmSpPJoHCKsz4=\ngithub.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=\ngithub.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=\ngithub.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4ulRMcQ=\ngithub.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q=\ngithub.com/volcengine/volc-sdk-golang v1.0.224 h1:k9Vtg64tQAgFTOGWzhyL0b0axuTuExXbLNVlslWlBZI=\ngithub.com/volcengine/volc-sdk-golang v1.0.224/go.mod h1:zHJlaqiMbIB+0mcrsZPTwOb3FB7S/0MCfqlnO8R7hlM=\ngithub.com/vulcand/oxy/v2 v2.0.3 h1:CPWVPfW4hVZXzwwiQzpFidbnJKpahjPHezM+7TkZRNw=\ngithub.com/vulcand/oxy/v2 v2.0.3/go.mod h1:k3t+xjyqmXVh88FdFDbYmUKMEvNpaejvBW14es6H70A=\ngithub.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50=\ngithub.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA=\ngithub.com/vultr/govultr/v3 v3.24.0 h1:fTTTj0VBve+Miy+wGhlb90M2NMDfpGFi6Frlj3HVy6M=\ngithub.com/vultr/govultr/v3 v3.24.0/go.mod h1:9WwnWGCKnwDlNjHjtt+j+nP+0QWq6hQXzaHgddqrLWY=\ngithub.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=\ngithub.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=\ngithub.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=\ngithub.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=\ngithub.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=\ngithub.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=\ngithub.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=\ngithub.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=\ngithub.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=\ngithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=\ngithub.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=\ngithub.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=\ngithub.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=\ngithub.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=\ngithub.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=\ngithub.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=\ngithub.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=\ngithub.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=\ngithub.com/yandex-cloud/go-genproto v0.34.0 h1:qhTJpPxOTKQbV44rIqoZSdzxDtZW27fkFjAcipEy8Zs=\ngithub.com/yandex-cloud/go-genproto v0.34.0/go.mod h1:0LDD/IZLIUIV4iPH+YcF+jysO3jkSvADFGm4dCAuwQo=\ngithub.com/yandex-cloud/go-sdk/services/dns v0.0.16 h1:0UYrBlQjTO2ct5xcSx6rqkQB95wRBPMVwxfqLQD1sUE=\ngithub.com/yandex-cloud/go-sdk/services/dns v0.0.16/go.mod h1:HlS3aIAdYEmJu2Ska/nzpcuv9LLVSMMXKGhzyLQwf5s=\ngithub.com/yandex-cloud/go-sdk/v2 v2.24.0 h1:G53N/RB5g/jw2xNN0egspnwd2ByHA1OVH6wbTx/tIlo=\ngithub.com/yandex-cloud/go-sdk/v2 v2.24.0/go.mod h1:ZRdpyOig8c/W3bNhwvkeXWWPeDScd9nmXv4AJzKvOsk=\ngithub.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=\ngithub.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=\ngithub.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=\ngithub.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=\ngithub.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=\ngithub.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=\ngithub.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=\ngithub.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=\ngithub.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=\ngithub.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=\ngo.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=\ngo.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=\ngo.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo=\ngo.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk=\ngo.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=\ngo.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0=\ngo.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI=\ngo.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=\ngo.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=\ngo.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A=\ngo.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo=\ngo.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=\ngo.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=\ngo.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=\ngo.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=\ngo.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=\ngo.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=\ngo.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=\ngo.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=\ngo.opentelemetry.io/collector/featuregate v1.41.0 h1:CL4UMsMQj35nMJC3/jUu8VvYB4MHirbAX4B0Z/fCVLY=\ngo.opentelemetry.io/collector/featuregate v1.41.0/go.mod h1:A72x92glpH3zxekaUybml1vMSv94BH6jQRn5+/htcjw=\ngo.opentelemetry.io/collector/pdata v1.41.0 h1:2zurAaY0FkURbLa1x7f7ag6HaNZYZKSmI4wgzDegLgo=\ngo.opentelemetry.io/collector/pdata v1.41.0/go.mod h1:h0OghaTYe4oRvLxK31Ny7gkyjJ1p8oniM5MiCzluQjc=\ngo.opentelemetry.io/contrib/bridges/otellogrus v0.13.0 h1:Nzvgkys5xSchtkWEeTQNixr9EVo+cbYCpSey2zMftXw=\ngo.opentelemetry.io/contrib/bridges/otellogrus v0.13.0/go.mod h1:nvmPavMmeFjktIIxQAsE265cQ9nQ5qhDV2mN5kfdPog=\ngo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=\ngo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=\ngo.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=\ngo.opentelemetry.io/contrib/propagators/autoprop v0.63.0 h1:S3+4UwR3Y1tUKklruMwOacAFInNvtuOexz4ZTmJNAyw=\ngo.opentelemetry.io/contrib/propagators/autoprop v0.63.0/go.mod h1:qpIuOggbbw2T9nKRaO1je/oTRKd4zslAcJonN8LYbTg=\ngo.opentelemetry.io/contrib/propagators/aws v1.38.0 h1:eRZ7asSbLc5dH7+TBzL6hFKb1dabz0IV51uUUwYRZts=\ngo.opentelemetry.io/contrib/propagators/aws v1.38.0/go.mod h1:wXqc9NTGcXapBExHBDVLEZlByu6quiQL8w7Tjgv8TCg=\ngo.opentelemetry.io/contrib/propagators/b3 v1.38.0 h1:uHsCCOSKl0kLrV2dLkFK+8Ywk9iKa/fptkytc6aFFEo=\ngo.opentelemetry.io/contrib/propagators/b3 v1.38.0/go.mod h1:wMRSZJZcY8ya9mApLLhwIMjqmApy2o/Ml+62lhvxyHU=\ngo.opentelemetry.io/contrib/propagators/jaeger v1.38.0 h1:nXGeLvT1QtCAhkASkP/ksjkTKZALIaQBIW+JSIw1KIc=\ngo.opentelemetry.io/contrib/propagators/jaeger v1.38.0/go.mod h1:oMvOXk78ZR3KEuPMBgp/ThAMDy9ku/eyUVztr+3G6Wo=\ngo.opentelemetry.io/contrib/propagators/ot v1.38.0 h1:k4gSyyohaDXI8F9BDXYC3uO2vr5sRNeQFMsN9Zn0EoI=\ngo.opentelemetry.io/contrib/propagators/ot v1.38.0/go.mod h1:2hDsuiHRO39SRUMhYGqmj64z/IuMRoxE4bBSFR82Lo8=\ngo.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=\ngo.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0 h1:OMqPldHt79PqWKOMYIAQs3CxAi7RLgPxwfFSwr4ZxtM=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0/go.mod h1:1biG4qiqTxKiUCtoWDPpL3fB3KxVwCiGw81j3nKMuHE=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.14.0 h1:QQqYw3lkrzwVsoEX0w//EhH/TCnpRdEenKBOOEIMjWc=\ngo.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.14.0/go.mod h1:gSVQcr17jk2ig4jqJ2DX30IdWH251JcNAecvrqTxH1s=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 h1:vl9obrcoWVKp/lwl8tRE33853I8Xru9HFbw/skNeLs8=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0/go.mod h1:GAXRxmLJcVM3u22IjTg74zWBrRCKq8BnOqUVLodpcpw=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 h1:Oe2z/BCg5q7k4iXC3cqJxKYg0ieRiOqF0cecFYdPTwk=\ngo.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0/go.mod h1:ZQM5lAJpOsKnYagGg/zV2krVqTtaVdYdDkhMoX6Oalg=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=\ngo.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=\ngo.opentelemetry.io/otel/log v0.14.0 h1:2rzJ+pOAZ8qmZ3DDHg73NEKzSZkhkGIua9gXtxNGgrM=\ngo.opentelemetry.io/otel/log v0.14.0/go.mod h1:5jRG92fEAgx0SU/vFPxmJvhIuDU9E1SUnEQrMlJpOno=\ngo.opentelemetry.io/otel/log/logtest v0.14.0 h1:BGTqNeluJDK2uIHAY8lRqxjVAYfqgcaTbVk1n3MWe5A=\ngo.opentelemetry.io/otel/log/logtest v0.14.0/go.mod h1:IuguGt8XVP4XA4d2oEEDMVDBBCesMg8/tSGWDjuKfoA=\ngo.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=\ngo.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=\ngo.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=\ngo.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=\ngo.opentelemetry.io/otel/sdk/log v0.14.0 h1:JU/U3O7N6fsAXj0+CXz21Czg532dW2V4gG1HE/e8Zrg=\ngo.opentelemetry.io/otel/sdk/log v0.14.0/go.mod h1:imQvII+0ZylXfKU7/wtOND8Hn4OpT3YUoIgqJVksUkM=\ngo.opentelemetry.io/otel/sdk/log/logtest v0.14.0 h1:Ijbtz+JKXl8T2MngiwqBlPaHqc4YCaP/i13Qrow6gAM=\ngo.opentelemetry.io/otel/sdk/log/logtest v0.14.0/go.mod h1:dCU8aEL6q+L9cYTqcVOk8rM9Tp8WdnHOPLiBgp0SGOA=\ngo.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=\ngo.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=\ngo.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=\ngo.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=\ngo.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=\ngo.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=\ngo.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=\ngo.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=\ngo.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=\ngo.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=\ngo.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=\ngo.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=\ngo.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=\ngo.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=\ngo.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=\ngo.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=\ngo.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=\ngo.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=\ngo.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=\ngo.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=\ngo.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=\ngo.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=\ngo.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0=\ngo.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk=\ngo.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=\ngo.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=\ngo.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=\ngo.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=\ngo.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=\ngo.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=\ngo.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=\ngo.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=\ngo.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=\ngolang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=\ngolang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=\ngolang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=\ngolang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=\ngolang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=\ngolang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=\ngolang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=\ngolang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=\ngolang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=\ngolang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=\ngolang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=\ngolang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=\ngolang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=\ngolang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=\ngolang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=\ngolang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=\ngolang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=\ngolang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=\ngolang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=\ngolang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=\ngolang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=\ngolang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=\ngolang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=\ngolang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=\ngolang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=\ngolang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=\ngolang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=\ngolang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=\ngolang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=\ngolang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=\ngolang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=\ngolang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=\ngolang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=\ngolang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=\ngolang.org/x/exp v0.0.0-20251017212417-90e834f514db h1:by6IehL4BH5k3e3SJmcoNbOobMey2SLpAF79iPOEBvw=\ngolang.org/x/exp v0.0.0-20251017212417-90e834f514db/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=\ngolang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=\ngolang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=\ngolang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=\ngolang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=\ngolang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=\ngolang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=\ngolang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=\ngolang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=\ngolang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=\ngolang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=\ngolang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=\ngolang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=\ngolang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=\ngolang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=\ngolang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=\ngolang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=\ngolang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=\ngolang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=\ngolang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=\ngolang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=\ngolang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=\ngolang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=\ngolang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=\ngolang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=\ngolang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=\ngolang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=\ngolang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=\ngolang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=\ngolang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=\ngolang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=\ngolang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=\ngolang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=\ngolang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=\ngolang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=\ngolang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=\ngolang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=\ngolang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=\ngolang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=\ngolang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=\ngolang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=\ngolang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=\ngolang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=\ngolang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=\ngolang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=\ngolang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=\ngolang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=\ngolang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=\ngolang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=\ngolang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=\ngolang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=\ngolang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=\ngolang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=\ngolang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=\ngolang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=\ngolang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=\ngolang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=\ngolang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=\ngolang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=\ngolang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220406163625-3f8b81556e12/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=\ngolang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=\ngolang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=\ngolang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=\ngolang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=\ngolang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=\ngolang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=\ngolang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=\ngolang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=\ngolang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=\ngolang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=\ngolang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=\ngolang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=\ngolang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=\ngolang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=\ngolang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=\ngolang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=\ngolang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=\ngolang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=\ngolang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=\ngolang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=\ngolang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=\ngolang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=\ngolang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=\ngolang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=\ngolang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=\ngolang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=\ngolang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngolang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=\ngolang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=\ngolang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=\ngolang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=\ngolang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=\ngolang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=\ngolang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=\ngolang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=\ngolang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=\ngolang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=\ngolang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=\ngolang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=\ngolang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=\ngolang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=\ngolang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=\ngolang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=\ngolang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=\ngolang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=\ngolang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=\ngolang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=\ngolang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=\ngolang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=\ngolang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=\ngolang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=\ngolang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=\ngolang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=\ngolang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=\ngolang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=\ngolang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=\ngolang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=\ngolang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngolang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=\ngomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=\ngomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=\ngonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=\ngonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0=\ngonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=\ngonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=\ngonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=\ngonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=\ngoogle.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=\ngoogle.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=\ngoogle.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=\ngoogle.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=\ngoogle.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=\ngoogle.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=\ngoogle.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=\ngoogle.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=\ngoogle.golang.org/api v0.254.0 h1:jl3XrGj7lRjnlUvZAbAdhINTLbsg5dbjmR90+pTQvt4=\ngoogle.golang.org/api v0.254.0/go.mod h1:5BkSURm3D9kAqjGvBNgf0EcbX6Rnrf6UArKkwBzAyqQ=\ngoogle.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=\ngoogle.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=\ngoogle.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=\ngoogle.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=\ngoogle.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=\ngoogle.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=\ngoogle.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=\ngoogle.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=\ngoogle.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=\ngoogle.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=\ngoogle.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=\ngoogle.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=\ngoogle.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=\ngoogle.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=\ngoogle.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=\ngoogle.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=\ngoogle.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=\ngoogle.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=\ngoogle.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=\ngoogle.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=\ngoogle.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=\ngoogle.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=\ngoogle.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=\ngoogle.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=\ngoogle.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=\ngoogle.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=\ngoogle.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=\ngoogle.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=\ngoogle.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=\ngoogle.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=\ngoogle.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=\ngoogle.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=\ngoogle.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=\ngoogle.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=\ngoogle.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=\ngoogle.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=\ngoogle.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=\ngoogle.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=\ngoogle.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=\ngoogle.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=\ngoogle.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=\ngoogle.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=\ngoogle.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=\ngoogle.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=\ngoogle.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=\ngoogle.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=\ngoogle.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngoogle.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=\ngoogle.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=\ngoogle.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=\ngoogle.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=\ngopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=\ngopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=\ngopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=\ngopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=\ngopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=\ngopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=\ngopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=\ngopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=\ngopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=\ngopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=\ngopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=\ngopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=\ngopkg.in/ns1/ns1-go.v2 v2.15.1 h1:8rri2TzAPYcVbBGXn48+dz1Xg30PzHfZ4k8A9JOS0Z0=\ngopkg.in/ns1/ns1-go.v2 v2.15.1/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=\ngopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=\ngopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=\ngopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=\ngopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=\ngopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=\ngopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=\ngopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=\ngopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=\ngopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=\ngotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=\nhonnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=\nhonnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=\nhonnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nhonnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=\nk8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=\nk8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=\nk8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI=\nk8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=\nk8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=\nk8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=\nk8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=\nk8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=\nk8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=\nk8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=\nk8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3 h1:liMHz39T5dJO1aOKHLvwaCjDbf07wVh6yaUlTpunnkE=\nk8s.io/kube-openapi v0.0.0-20250814151709-d7b6acb124c3/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=\nk8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d h1:wAhiDyZ4Tdtt7e46e9M5ZSAJ/MnPGPs+Ki1gHw4w1R0=\nk8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=\nknative.dev/networking v0.0.0-20241022012959-60e29ff520dc h1:0d9XXRLlyuHfINZLlYqo/BYe/+chqqNBMLKJldjTbtw=\nknative.dev/networking v0.0.0-20241022012959-60e29ff520dc/go.mod h1:G56j6VCLzfaN9yZ4IqfNyN4c3U1czvhUmKeZX4UjQ8Q=\nknative.dev/pkg v0.0.0-20241021183759-9b9d535af5ad h1:Nrjtr2H168rJeamH4QdyLMV1lEKHejNhaj1ymgQMfLk=\nknative.dev/pkg v0.0.0-20241021183759-9b9d535af5ad/go.mod h1:StJI72GWcm/iErmk4RqFJiOo8RLbVqPbHxUqeVwAzeo=\nmvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=\nmvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=\nnhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=\nnhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=\npgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=\npgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=\nrsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=\nrsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=\nrsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=\nrsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=\nsigs.k8s.io/gateway-api v1.4.0 h1:ZwlNM6zOHq0h3WUX2gfByPs2yAEsy/EenYJB78jpQfQ=\nsigs.k8s.io/gateway-api v1.4.0/go.mod h1:AR5RSqciWP98OPckEjOjh2XJhAe2Na4LHyXD2FUY7Qk=\nsigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=\nsigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=\nsigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=\nsigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=\nsigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco=\nsigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=\nsigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=\nsigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=\nsigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=\n"
  },
  {
    "path": "kv.go",
    "content": "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.com/traefik/traefik/v3/pkg/config/dynamic\"\n)\n\ntype KV struct {\n\tdata map[string]interface{}\n\tbase string\n}\n\nfunc NewKV() *KV {\n\treturn &KV{data: make(map[string]interface{})}\n}\n\nfunc (kv *KV) SetBase(b string) {\n\tkv.base = b\n}\n\nfunc (kv *KV) add(val interface{}, format string, a ...interface{}) {\n\tif val == nil {\n\t\treturn // todo: log it? debug?\n\t}\n\tstr := fmt.Sprintf(\"%s\", val)\n\tif str == \"\" {\n\t\treturn // todo: log it? debug?\n\t}\n\tif kv.base != \"\" {\n\t\tformat = kv.base + \"/\" + format\n\t}\n\n\tkey := fmt.Sprintf(format, a...)\n\tif strings.HasPrefix(key, \"traefik/tls/\") {\n\t\t// ignore tls options, only interested in things that can be set per-container\n\t\treturn\n\t}\n\n\tkv.data[key] = val\n}\n\n// ConfigToKV flattens the given configuration into a format suitable for\n// putting into a KV store such as redis\nfunc ConfigToKV(conf dynamic.Configuration) (map[string]interface{}, error) {\n\tkv := NewKV()\n\t_, err := walkTypedValue(kv, \"traefik\", reflect.TypeOf(conf), reflect.ValueOf(conf), walkOptions{})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create kv: %w\", err)\n\t}\n\n\treturn kv.data, nil\n}\n\nvar (\n\treKeyName         = regexp.MustCompile(`^traefik/(http|tcp|udp)/(router|service|middleware)s$`)\n\tjsonMarshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()\n\ttextMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()\n)\n\ntype walkOptions struct {\n\tallowEmpty bool\n}\n\nfunc walkTypedValue(kv *KV, path string, typ reflect.Type, val reflect.Value, opts walkOptions) (bool, error) {\n\tif typ == nil || !val.IsValid() {\n\t\treturn false, nil\n\t}\n\n\tfor typ.Kind() == reflect.Interface {\n\t\tif val.IsNil() {\n\t\t\treturn false, nil\n\t\t}\n\t\tval = val.Elem()\n\t\ttyp = val.Type()\n\t}\n\n\tif typ.Kind() == reflect.Pointer {\n\t\tif val.IsNil() {\n\t\t\treturn false, nil\n\t\t}\n\n\t\tadded, err := walkTypedValue(kv, path, typ.Elem(), val.Elem(), walkOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\n\t\tif !added && opts.allowEmpty && typ.Elem().Kind() == reflect.Struct {\n\t\t\tkv.add(\"true\", path)\n\t\t\treturn true, nil\n\t\t}\n\n\t\treturn added, nil\n\t}\n\n\tif isLeafType(typ) {\n\t\ts, ok, err := leafString(typ, val)\n\t\tif err != nil {\n\t\t\treturn false, fmt.Errorf(\"walk %s: %w\", path, err)\n\t\t}\n\t\tif ok {\n\t\t\tkv.add(s, path)\n\t\t\treturn true, nil\n\t\t}\n\t\treturn false, nil\n\t}\n\n\tswitch typ.Kind() {\n\tcase reflect.Struct:\n\t\treturn walkStructValue(kv, path, typ, val)\n\tcase reflect.Map:\n\t\treturn walkMapValue(kv, path, typ, val)\n\tcase reflect.Slice, reflect.Array:\n\t\treturn walkSliceValue(kv, path, typ, val)\n\tdefault:\n\t\treturn false, nil\n\t}\n}\n\nfunc walkStructValue(kv *KV, path string, typ reflect.Type, val reflect.Value) (bool, error) {\n\taddedAny := false\n\n\tfor i := 0; i < typ.NumField(); i++ {\n\t\tfield := typ.Field(i)\n\t\tif field.PkgPath != \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tfieldName, omitEmpty, skip := jsonFieldName(field)\n\t\tif skip {\n\t\t\tcontinue\n\t\t}\n\n\t\tfieldValue := val.Field(i)\n\t\tif omitEmpty && isEmptyJSONValue(fieldValue) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif field.Anonymous && fieldName == field.Name {\n\t\t\tadded, err := walkTypedValue(kv, path, field.Type, fieldValue, walkOptions{})\n\t\t\tif err != nil {\n\t\t\t\treturn false, err\n\t\t\t}\n\t\t\taddedAny = addedAny || added\n\t\t\tcontinue\n\t\t}\n\n\t\tchildPath := joinPath(path, fieldName)\n\t\tadded, err := walkTypedValue(kv, childPath, field.Type, fieldValue, walkOptions{allowEmpty: field.Tag.Get(\"label\") == \"allowEmpty\"})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\taddedAny = addedAny || added\n\t}\n\n\treturn addedAny, nil\n}\n\nfunc walkMapValue(kv *KV, path string, typ reflect.Type, val reflect.Value) (bool, error) {\n\tif val.IsNil() || val.Len() == 0 {\n\t\treturn false, nil\n\t}\n\n\tif typ.Key().Kind() != reflect.String {\n\t\treturn false, fmt.Errorf(\"unsupported map key type %s at %s\", typ.Key(), path)\n\t}\n\n\taddedAny := false\n\titer := val.MapRange()\n\tfor iter.Next() {\n\t\tkey := iter.Key().String()\n\t\tif reKeyName.MatchString(path) {\n\t\t\tkey = stripDocker(key)\n\t\t}\n\n\t\tadded, err := walkTypedValue(kv, joinPath(path, key), typ.Elem(), iter.Value(), walkOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\taddedAny = addedAny || added\n\t}\n\n\treturn addedAny, nil\n}\n\nfunc walkSliceValue(kv *KV, path string, typ reflect.Type, val reflect.Value) (bool, error) {\n\tif typ.Kind() == reflect.Slice && val.IsNil() {\n\t\treturn false, nil\n\t}\n\n\tif val.Len() == 0 {\n\t\treturn false, nil\n\t}\n\n\taddedAny := false\n\tfor i := 0; i < val.Len(); i++ {\n\t\tadded, err := walkTypedValue(kv, fmt.Sprintf(\"%s/%d\", path, i), typ.Elem(), val.Index(i), walkOptions{})\n\t\tif err != nil {\n\t\t\treturn false, err\n\t\t}\n\t\taddedAny = addedAny || added\n\t}\n\n\treturn addedAny, nil\n}\n\nfunc isLeafType(typ reflect.Type) bool {\n\tif typ.Implements(textMarshalerType) || reflect.PointerTo(typ).Implements(textMarshalerType) ||\n\t\ttyp.Implements(jsonMarshalerType) || reflect.PointerTo(typ).Implements(jsonMarshalerType) {\n\t\treturn true\n\t}\n\tswitch typ.Kind() {\n\tcase reflect.Bool,\n\t\treflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,\n\t\treflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,\n\t\treflect.Float32, reflect.Float64,\n\t\treflect.String:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc leafString(typ reflect.Type, val reflect.Value) (string, bool, error) {\n\t// Custom text marshaler (e.g., ptypes.Duration) — preferred, gives raw text\n\tif v, ok := marshalerValue(val, textMarshalerType); ok {\n\t\tb, err := v.(encoding.TextMarshaler).MarshalText()\n\t\tif err != nil {\n\t\t\treturn \"\", false, err\n\t\t}\n\t\ts := string(b)\n\t\treturn s, s != \"\", nil\n\t}\n\n\t// json.Marshaler fallback (without TextMarshaler); use JSON roundtrip\n\tif v, ok := marshalerValue(val, jsonMarshalerType); ok {\n\t\tb, err := json.Marshal(v)\n\t\tif err != nil {\n\t\t\treturn \"\", false, err\n\t\t}\n\t\tvar s string\n\t\tif err := json.Unmarshal(b, &s); err == nil {\n\t\t\treturn s, s != \"\", nil\n\t\t}\n\t\ts = strings.Trim(string(b), `\"`)\n\t\treturn s, s != \"\", nil\n\t}\n\n\t// Primitives\n\tswitch typ.Kind() {\n\tcase reflect.String:\n\t\ts := val.String()\n\t\treturn s, s != \"\", nil\n\tcase reflect.Bool:\n\t\treturn strconv.FormatBool(val.Bool()), true, nil\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\treturn strconv.FormatInt(val.Int(), 10), true, nil\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:\n\t\treturn strconv.FormatUint(val.Uint(), 10), true, nil\n\tcase reflect.Float32, reflect.Float64:\n\t\treturn strconv.FormatFloat(val.Float(), 'f', -1, 64), true, nil\n\t}\n\treturn \"\", false, nil\n}\n\n// marshalerValue returns val (or pointer-to-val) as an interface{} if it implements iface.\nfunc marshalerValue(val reflect.Value, iface reflect.Type) (interface{}, bool) {\n\tif !val.IsValid() {\n\t\treturn nil, false\n\t}\n\ttyp := val.Type()\n\tif typ.Implements(iface) && val.CanInterface() {\n\t\treturn val.Interface(), true\n\t}\n\tif val.CanAddr() && val.Addr().Type().Implements(iface) {\n\t\treturn val.Addr().Interface(), true\n\t}\n\tif reflect.PointerTo(typ).Implements(iface) {\n\t\tp := reflect.New(typ)\n\t\tp.Elem().Set(val)\n\t\treturn p.Interface(), true\n\t}\n\treturn nil, false\n}\n\nfunc joinPath(base, child string) string {\n\treturn base + \"/\" + child\n}\n\nfunc jsonFieldName(field reflect.StructField) (string, bool, bool) {\n\ttag := field.Tag.Get(\"json\")\n\tif tag == \"-\" {\n\t\treturn \"\", false, true\n\t}\n\n\tparts := strings.Split(tag, \",\")\n\tname := field.Name\n\tif len(parts) > 0 && parts[0] != \"\" {\n\t\tname = parts[0]\n\t}\n\n\tomitEmpty := false\n\tfor _, opt := range parts[1:] {\n\t\tif opt == \"omitempty\" {\n\t\t\tomitEmpty = true\n\t\t\tbreak\n\t\t}\n\t}\n\n\treturn name, omitEmpty, false\n}\n\nfunc isEmptyJSONValue(val reflect.Value) bool {\n\tif !val.IsValid() {\n\t\treturn true\n\t}\n\n\tswitch val.Kind() {\n\tcase reflect.Array, reflect.Map, reflect.Slice, reflect.String:\n\t\treturn val.Len() == 0\n\tcase reflect.Bool:\n\t\treturn !val.Bool()\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\treturn val.Int() == 0\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:\n\t\treturn val.Uint() == 0\n\tcase reflect.Float32, reflect.Float64:\n\t\treturn val.Float() == 0\n\tcase reflect.Interface, reflect.Pointer:\n\t\treturn val.IsNil()\n\tdefault:\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "kv_test.go",
    "content": "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/testify/require\"\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n)\n\nfunc Test_configToKV(t *testing.T) {\n\tcfg := &dynamic.Configuration{}\n\t_, err := toml.DecodeFile(\"./fixtures/sample.toml\", &cfg)\n\trequire.NoError(t, err)\n\n\tgot, err := ConfigToKV(*cfg)\n\trequire.NoError(t, err)\n\trequire.NotNil(t, got)\n\n\trequire.Contains(t, got, \"traefik/http/services/Service0/loadBalancer/healthCheck/port\")\n\trequire.Contains(t, got, \"traefik/http/middlewares/Middleware15/forwardAuth/authRequestHeaders/1\")\n\trequire.NotContains(t, got, \"traefik/tls/options/TLS0/sniStrict\")\n\n\t// should not include @docker in names\n\tcfg = &dynamic.Configuration{}\n\terr = json.Unmarshal([]byte(NGINX_CONF_JSON), cfg)\n\trequire.NoError(t, err)\n\n\tgot, err = ConfigToKV(*cfg)\n\trequire.NoError(t, err)\n\t// dumpKV(got)\n\trequire.NotContains(t, got, \"traefik/http/routers/nginx@docker/service\")\n\trequire.NotContains(t, got, \"traefik/http/services/nginx@docker/loadBalancer/passHostHeader\")\n\n\t// t.Fail()\n}\n\nfunc dumpKV(kv map[string]interface{}) {\n\tfor k, v := range kv {\n\t\tfmt.Printf(\"%s = %s\\n\", k, v)\n\t}\n}\n"
  },
  {
    "path": "kv_walk_test.go",
    "content": "package traefikkop\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n\tptypes \"github.com/traefik/paerser/types\"\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n)\n\nfunc TestConfigToKVAllowEmptyLabel(t *testing.T) {\n\tcfg := dynamic.Configuration{\n\t\tHTTP: &dynamic.HTTPConfiguration{\n\t\t\tRouters: map[string]*dynamic.Router{\n\t\t\t\t\"musicassistant@docker\": {\n\t\t\t\t\tRule:        \"Host(`musicassistant.example.com`)\",\n\t\t\t\t\tService:     \"musicassistant\",\n\t\t\t\t\tEntryPoints: []string{\"websecure\"},\n\t\t\t\t\tTLS:         &dynamic.RouterTLSConfig{},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tTCP: &dynamic.TCPConfiguration{},\n\t\tUDP: &dynamic.UDPConfiguration{},\n\t\tTLS: &dynamic.TLSConfiguration{},\n\t}\n\n\tgot, err := ConfigToKV(cfg)\n\trequire.NoError(t, err)\n\trequire.Equal(t, \"true\", got[\"traefik/http/routers/musicassistant/tls\"])\n}\n\nfunc TestConfigToKVUsesJSONLeafEncoding(t *testing.T) {\n\tcfg := dynamic.Configuration{\n\t\tHTTP: &dynamic.HTTPConfiguration{\n\t\t\tServices: map[string]*dynamic.Service{\n\t\t\t\t\"musicassistant@docker\": {\n\t\t\t\t\tLoadBalancer: &dynamic.ServersLoadBalancer{\n\t\t\t\t\t\tResponseForwarding: &dynamic.ResponseForwarding{\n\t\t\t\t\t\t\tFlushInterval: ptypes.Duration(5 * time.Second),\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tTCP: &dynamic.TCPConfiguration{},\n\t\tUDP: &dynamic.UDPConfiguration{},\n\t\tTLS: &dynamic.TLSConfiguration{},\n\t}\n\n\tgot, err := ConfigToKV(cfg)\n\trequire.NoError(t, err)\n\trequire.Equal(t, \"5s\", got[\"traefik/http/services/musicassistant/loadBalancer/responseForwarding/flushInterval\"])\n}\n"
  },
  {
    "path": "multi_provider.go",
    "content": "package traefikkop\n\nimport (\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n\t\"github.com/traefik/traefik/v3/pkg/provider\"\n\t\"github.com/traefik/traefik/v3/pkg/safe\"\n)\n\n// MultiProvider simply wraps an array of providers (more generic than\n// ProviderAggregator)\ntype MultiProvider struct {\n\tupstreamProviders []provider.Provider\n}\n\nfunc NewMultiProvider(upstream []provider.Provider) *MultiProvider {\n\treturn &MultiProvider{upstream}\n}\n\nfunc (p MultiProvider) Init() error {\n\tfor _, provider := range p.upstreamProviders {\n\t\terr := provider.Init()\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (p MultiProvider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {\n\tfor _, provider := range p.upstreamProviders {\n\t\tprovider.Provide(configurationChan, pool)\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "multi_provider_test.go",
    "content": "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\"github.com/traefik/traefik/v3/pkg/provider\"\n\t\"github.com/traefik/traefik/v3/pkg/safe\"\n)\n\nfunc TestMultiProvider_ProvideCounts(t *testing.T) {\n\tvar count1, count2 int32\n\tp1 := &noopProvider{calls: &count1}\n\tp2 := &noopProvider{calls: &count2}\n\tmp := NewMultiProvider([]provider.Provider{p1, p2})\n\tmp.Init()\n\n\tch := make(chan dynamic.Message)\n\tpool := safe.NewPool(context.Background())\n\tdefer pool.Stop()\n\n\tmp.Provide(ch, pool)\n\n\tif atomic.LoadInt32(&count1) != 1 {\n\t\tt.Errorf(\"expected p1 to be called once, got %d\", count1)\n\t}\n\tif atomic.LoadInt32(&count2) != 1 {\n\t\tt.Errorf(\"expected p2 to be called once, got %d\", count2)\n\t}\n}\n"
  },
  {
    "path": "polling_provider.go",
    "content": "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/dynamic\"\n\t\"github.com/traefik/traefik/v3/pkg/observability/logs\"\n\t\"github.com/traefik/traefik/v3/pkg/provider\"\n\t\"github.com/traefik/traefik/v3/pkg/safe\"\n)\n\n// PollingProvider simply wraps the target upstream provider with a poller.\ntype PollingProvider struct {\n\trefreshInterval  time.Duration\n\tupstreamProvider provider.Provider\n\tstore            TraefikStore\n}\n\nfunc NewPollingProvider(refreshInterval time.Duration, upstream provider.Provider, store TraefikStore) *PollingProvider {\n\treturn &PollingProvider{refreshInterval, upstream, store}\n}\n\nfunc (p PollingProvider) Init() error {\n\treturn p.upstreamProvider.Init()\n}\n\nfunc (p PollingProvider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {\n\tif p.refreshInterval == 0 {\n\t\tlog.Info().Msg(\"Disabling polling provider (interval=0)\")\n\t\treturn nil\n\t}\n\n\tlog.Info().Msgf(\"starting polling provider with %s interval\", p.refreshInterval.String())\n\tticker := time.NewTicker(p.refreshInterval)\n\n\tpool.GoCtx(func(ctx context.Context) {\n\t\tlogger := log.With().Str(logs.ProviderName, \"docker\").Logger()\n\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase <-ticker.C:\n\t\t\t\tlogger.Debug().Msg(\"tick\")\n\t\t\t\tp.upstreamProvider.Provide(configurationChan, pool)\n\n\t\t\t\t// Try to push the last config if Redis restarted\n\t\t\t\terr := p.store.KeepConfAlive()\n\t\t\t\tif err != nil {\n\t\t\t\t\tlogger.Warn().Msgf(\"Failed to push cached config: %s\", err)\n\t\t\t\t}\n\n\t\t\tcase <-ctx.Done():\n\t\t\t\tticker.Stop()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t})\n\n\treturn nil\n}\n"
  },
  {
    "path": "polling_provider_test.go",
    "content": "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/dynamic\"\n\t\"github.com/traefik/traefik/v3/pkg/safe\"\n)\n\n// noopProvider counts how many times Provide is called.\ntype noopProvider struct {\n\tcalls *int32\n}\n\nfunc (n *noopProvider) Init() error {\n\treturn nil\n}\n\nfunc (n *noopProvider) Provide(configurationChan chan<- dynamic.Message, pool *safe.Pool) error {\n\tatomic.AddInt32(n.calls, 1)\n\treturn nil\n}\n\nfunc TestPollingProvider_CountsPolls(t *testing.T) {\n\tvar callCount int32\n\tupstream := &noopProvider{calls: &callCount}\n\tstore := &testStore{}\n\tinterval := 50 * time.Millisecond\n\tpp := NewPollingProvider(interval, upstream, store)\n\tpp.Init()\n\n\tch := make(chan dynamic.Message)\n\tpool := safe.NewPool(context.Background())\n\tdefer pool.Stop()\n\n\t_, cancel := context.WithCancel(context.Background())\n\tdefer cancel()\n\n\t// Run polling in a goroutine\n\tgo func() {\n\t\tpp.Provide(ch, pool)\n\t}()\n\n\t// Let it poll a few times\n\ttime.Sleep(220 * time.Millisecond)\n\tcancel()\n\n\tcalls := atomic.LoadInt32(&callCount)\n\tif calls < 3 || calls > 6 {\n\t\tt.Errorf(\"expected 3-6 polls, got %d\", calls)\n\t}\n}\n"
  },
  {
    "path": "store.go",
    "content": "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\"\n\t\"github.com/redis/go-redis/v9\"\n\t\"github.com/rs/zerolog\"\n\t\"github.com/rs/zerolog/log\"\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n)\n\ntype TraefikStore interface {\n\tStore(conf dynamic.Configuration) error\n\tGet(key string) (string, error)\n\tGets(key string) (map[string]string, error)\n\tPing() error\n\tKeepConfAlive() error\n}\n\nfunc collectKeys(m interface{}) []string {\n\tmk := reflect.ValueOf(m).MapKeys()\n\t// set := mapset.NewSet()\n\tset := make([]string, len(mk))\n\tfor i := 0; i < len(mk); i++ {\n\t\t// set.Add(mk[i].String())\n\t\tset[i] = mk[i].String()\n\t}\n\treturn set\n}\n\ntype RedisStore struct {\n\tHostname string\n\tTTL      time.Duration // TTL in seconds, 0 means no TTL\n\n\tclient     *redis.Client\n\tlastConfig *dynamic.Configuration\n}\n\nfunc NewRedisStore(hostname string, addr string, ttl int, user string, pass string, db int) TraefikStore {\n\tlog.Info().Msgf(\"creating new redis store at %s for hostname %s with %dsec TTL\", addr, hostname, ttl)\n\n\tstore := &RedisStore{\n\t\tHostname: hostname,\n\t\tTTL:      time.Duration(ttl) * time.Second,\n\n\t\tclient: redis.NewClient(&redis.Options{\n\t\t\tClientName:      \"\",\n\t\t\tDisableIdentity: true,\n\t\t\tAddr:            addr,\n\t\t\tUsername:        user,\n\t\t\tPassword:        pass,\n\t\t\tDB:              db,\n\t\t}),\n\t}\n\treturn store\n}\n\nfunc (s *RedisStore) Ping() error {\n\treturn s.client.Ping(context.Background()).Err()\n}\n\n// sk returns the 'set key' for keeping track of our services/routers/middlewares\n// e.g., traefik_http_routers@culture.local\nfunc (s RedisStore) sk(b string) string {\n\treturn fmt.Sprintf(\"traefik_%s@%s\", b, s.Hostname)\n}\n\nfunc (s *RedisStore) Get(key string) (string, error) {\n\tval, err := s.client.Get(context.Background(), key).Result()\n\tif err != nil {\n\t\tif errors.Is(err, redis.Nil) {\n\t\t\treturn \"\", nil // key does not exist\n\t\t}\n\t\treturn \"\", errors.Wrapf(err, \"failed to get key %s\", key)\n\t}\n\treturn val, nil\n}\n\nfunc (s *RedisStore) Gets(key string) (map[string]string, error) {\n\tkeys, err := s.client.Keys(context.Background(), key).Result()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to get keys matching %s\", key)\n\t}\n\tif len(keys) == 0 {\n\t\treturn nil, nil // no keys found\n\t}\n\tvals := make(map[string]string)\n\tfor _, k := range keys {\n\t\tval, err := s.Get(k)\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to get value for key %s\", k)\n\t\t}\n\t\tvals[k] = val\n\t}\n\treturn vals, nil\n}\n\n// traefik/http/services/gitea/loadBalancer/servers/0/url\n// traefik/tcp/services/gitea-ssh/loadBalancer/servers/0/address\n// traefik/udp/services/helloudp/loadBalancer/servers/0/address\nvar svcAddrRe = regexp.MustCompile(`^traefik/(tcp|udp|http)/services/([^/]+)/loadBalancer/servers/\\d+/(address|url)$`)\n\nfunc (s *RedisStore) Store(conf dynamic.Configuration) error {\n\ts.removeOldKeys(conf.HTTP.Middlewares, \"http_middlewares\")\n\ts.removeOldKeys(conf.HTTP.Routers, \"http_routers\")\n\ts.removeOldKeys(conf.HTTP.Services, \"http_services\")\n\ts.removeOldKeys(conf.TCP.Middlewares, \"tcp_middlewares\")\n\ts.removeOldKeys(conf.TCP.Routers, \"tcp_routers\")\n\ts.removeOldKeys(conf.TCP.Services, \"tcp_services\")\n\ts.removeOldKeys(conf.UDP.Routers, \"udp_routers\")\n\ts.removeOldKeys(conf.UDP.Services, \"udp_services\")\n\n\tkv, err := ConfigToKV(conf)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tsortedKeys := collectKeys(kv)\n\tsort.Strings(sortedKeys)\n\tfor _, k := range sortedKeys {\n\t\tv := kv[k]\n\t\tlog.Debug().Msgf(\"writing %s = %s\", k, v)\n\n\t\tif matches := svcAddrRe.FindStringSubmatch(k); matches != nil {\n\t\t\tlog.Info().Str(\"service\", matches[2]).Str(\"service-type\", matches[1]).Msgf(\"publishing %s\", v)\n\t\t}\n\n\t\ts.client.Set(context.Background(), k, v, s.TTL)\n\t}\n\n\ts.swapKeys(s.sk(\"http_middlewares\"))\n\ts.swapKeys(s.sk(\"http_routers\"))\n\ts.swapKeys(s.sk(\"http_services\"))\n\ts.swapKeys(s.sk(\"tcp_middlewares\"))\n\ts.swapKeys(s.sk(\"tcp_routers\"))\n\ts.swapKeys(s.sk(\"tcp_services\"))\n\ts.swapKeys(s.sk(\"udp_routers\"))\n\ts.swapKeys(s.sk(\"udp_services\"))\n\n\t// Update sentinel key with current timestamp\n\ts.client.Set(context.Background(), s.sk(\"kop_last_update\"), time.Now().Unix(), s.TTL)\n\n\t// Store a copy of the configuration in case redis restarts\n\tconfigCopy := conf\n\ts.lastConfig = &configCopy\n\n\treturn nil\n}\n\n// NeedsUpdate checks if Redis needs a full configuration refresh\n// by checking for the sentinel key's existence\nfunc (s *RedisStore) NeedsUpdate() bool {\n\t// Check if sentinel key exists\n\texists, err := s.client.Exists(context.Background(), s.sk(\"kop_last_update\")).Result()\n\tif err != nil {\n\t\tlog.Warn().Msgf(\"Failed to check Redis status: %s\", err)\n\t}\n\treturn exists == 0\n}\n\n// Push the last configuration if needed\nfunc (s *RedisStore) KeepConfAlive() error {\n\tif s.lastConfig == nil {\n\t\treturn nil // No config to push yet\n\t}\n\n\tif s.NeedsUpdate() {\n\t\tlog.Warn().Msg(\"Redis seems to have restarted and needs to be updated. Pushing last known configuration\")\n\t\treturn s.Store(*s.lastConfig)\n\t}\n\n\treturn nil\n}\n\nfunc (s *RedisStore) swapKeys(setkey string) error {\n\t// store router name list by renaming\n\terr := s.client.Rename(context.Background(), setkey+\"_new\", setkey).Err()\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"no such key\") {\n\t\t\ts.client.Unlink(context.Background(), setkey)\n\t\t\treturn nil\n\t\t}\n\t\treturn errors.Wrap(err, \"rename failed\")\n\t}\n\treturn nil\n}\n\n// k returns the actual config key path\n// e.g., traefik/http/routers/nginx@docker\nfunc (s RedisStore) k(sk, b string) string {\n\tk := strings.ReplaceAll(fmt.Sprintf(\"traefik_%s\", sk), \"_\", \"/\")\n\tb = stripDocker(b)\n\treturn fmt.Sprintf(\"%s/%s\", k, b)\n}\n\nfunc (s *RedisStore) removeKeys(setkey string, keys []string) error {\n\tif len(keys) == 0 {\n\t\treturn nil\n\t}\n\tlog.Debug().Func(func(e *zerolog.Event) {\n\t\te.Msgf(\"removing keys from %s: %s\", setkey, strings.Join(keys, \",\"))\n\t})\n\tfor _, removeKey := range keys {\n\t\tkeyPath := s.k(setkey, removeKey) + \"/*\"\n\t\tlog.Debug().Msgf(\"removing keys matching %s\", keyPath)\n\t\tres, err := s.client.Keys(context.Background(), keyPath).Result()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"fetch failed\")\n\t\t}\n\t\tif err := s.client.Unlink(context.Background(), res...).Err(); err != nil {\n\t\t\treturn errors.Wrap(err, \"unlink failed\")\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (s *RedisStore) removeOldKeys(m interface{}, setname string) error {\n\tsetkey := s.sk(setname)\n\t// store new keys in temp set\n\tnewkeys := collectKeys(m)\n\tif len(newkeys) == 0 {\n\t\tres, err := s.client.SMembers(context.Background(), setkey).Result()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"fetch failed\")\n\t\t}\n\t\treturn s.removeKeys(setname, res)\n\n\t} else {\n\t\t// make a diff and remove\n\t\terr := s.client.SAdd(context.Background(), setkey+\"_new\", mkslice(newkeys)...).Err()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"add failed\")\n\t\t}\n\n\t\t// diff the existing keys with the new ones\n\t\tres, err := s.client.SDiff(context.Background(), setkey, setkey+\"_new\").Result()\n\t\tif err != nil {\n\t\t\treturn errors.Wrap(err, \"diff failed\")\n\t\t}\n\t\treturn s.removeKeys(setname, res)\n\t}\n}\n\n// mkslice converts a string slice to an interface slice\nfunc mkslice(old []string) []interface{} {\n\tnew := make([]interface{}, len(old))\n\tfor i, v := range old {\n\t\tnew[i] = v\n\t}\n\treturn new\n}\n"
  },
  {
    "path": "store_test.go",
    "content": "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/echovault/sugardb/sugardb\"\n\t\"github.com/stretchr/testify/assert\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n)\n\nconst NGINX_CONF_JSON = `{\"http\":{\"routers\":{\"nginx@docker\":{\"service\":\"nginx\",\"rule\":\"Host('nginx.local')\"}},\"services\":{\"nginx@docker\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.20.0.2:80\"}],\"passHostHeader\":true}}}},\"tcp\":{},\"udp\":{},\"tls\":{\"options\":{\"default\":{\"clientAuth\":{},\"alpnProtocols\":[\"h2\",\"http/1.1\",\"acme-tls/1\"]}}}}`\nconst NGINX_CONF_JSON_DIFFRENT_SERVICE_NAME = `{\"http\":{\"routers\":{\"nginx@docker\":{\"service\":\"nginx-nginx\",\"rule\":\"Host('nginx.local')\"}},\"services\":{\"nginx-nginx@docker\":{\"loadBalancer\":{\"servers\":[{\"url\":\"http://172.20.0.2:80\"}],\"passHostHeader\":true}}}},\"tcp\":{},\"udp\":{},\"tls\":{\"options\":{\"default\":{\"clientAuth\":{},\"alpnProtocols\":[\"h2\",\"http/1.1\",\"acme-tls/1\"]}}}}`\n\nfunc Test_collectKeys(t *testing.T) {\n\tcfg := &dynamic.Configuration{}\n\t_, err := toml.DecodeFile(\"./fixtures/sample.toml\", &cfg)\n\trequire.NoError(t, err)\n\n\tkeys := collectKeys(cfg.HTTP.Middlewares)\n\trequire.NotEmpty(t, keys)\n\trequire.Contains(t, keys, \"Middleware21\")\n\n\trequire.Contains(t, collectKeys(cfg.HTTP.Services), \"Service0\")\n\n\tcfg = &dynamic.Configuration{}\n\terr = json.Unmarshal([]byte(NGINX_CONF_JSON), cfg)\n\trequire.NoError(t, err)\n\tkeys = collectKeys(cfg.HTTP.Routers)\n\trequire.Len(t, keys, 1)\n}\n\n// keys := collectKeys(cfg.HTTP.Middlewares)\n// require.NotEmpty(t, keys)\n// require.True(t, keys.Contains(\"Middleware21\"))\n\n// require.True(t, collectKeys(cfg.HTTP.Services).Contains(\"Service0\"))\n\nfunc Test_redisStore(t *testing.T) {\n\tl, err := getAvailablePort()\n\tassert.NoError(t, err)\n\tport := l.Addr().(*net.TCPAddr).Port\n\tassert.NoError(t, l.Close())\n\n\tserver, err := sugardb.NewSugarDB(sugardb.WithPort(uint16(port)))\n\tif err != nil {\n\t\tassert.NoError(t, err)\n\t}\n\n\tgo server.Start()\n\tdefer server.ShutDown()\n\n\tstore := NewRedisStore(\"localhost\", fmt.Sprintf(\"localhost:%d\", port), 0, \"\", \"\", 0)\n\tprocessFileWithConfig(t, store, nil, \"hellodetect.yml\")\n\tassertServiceIPs(t, store, []svc{\n\t\t{\"hello-detect\", \"http\", \"http://192.168.100.100:5577\"},\n\t\t{\"hello-detect2\", \"http\", \"http://192.168.100.100:5577\"},\n\t})\n}\n"
  },
  {
    "path": "testing/docker-compose.yml",
    "content": "services:\n  # Redis for use in testing, if we don't have one available locally\n  redis:\n    image: \"redis:alpine\"\n    restart: unless-stopped\n    ports:\n      - 6380:6379\n\n  # Service with two routers+services listening on different ports.\n  helloworld:\n    image: helloworld\n    build:\n      dockerfile: ./helloworld/Dockerfile\n      context: ./\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n      - 5566:5566\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello1.rule=Host(`hello1.local`)\"\n      - \"traefik.http.routers.hello1.service=hello1\"\n      - \"traefik.http.routers.hello1.tls=true\"\n      - \"traefik.http.routers.hello1.tls.certresolver=default\"\n      - \"traefik.http.services.hello1.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello1.loadbalancer.server.port=5555\"\n      - \"traefik.http.routers.hello2.rule=Host(`hello2.local`)\"\n      - \"traefik.http.routers.hello2.service=hello2\"\n      - \"traefik.http.routers.hello2.tls=true\"\n      - \"traefik.http.routers.hello2.tls.certresolver=default\"\n      - \"traefik.http.services.hello2.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.hello2.loadbalancer.server.port=5566\"\n\n  # This service is the same as above except that it does not have a label\n  # which explicitly maps the port and so it fails to correctly determine which\n  # port to tell traefik to connect to. i.e., both services connect to 5555.\n  #\n  # This scenario will *not* be handled correctly by traefik-kop as we have no\n  # fallback way to determine the port.\n  hellodetect:\n    image: helloworld\n    build:\n      dockerfile: ./helloworld/Dockerfile\n      context: ./\n    restart: unless-stopped\n    ports:\n      - 5577:5555\n      - 5588:5566\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.hello-detect.rule=Host(`hello-detect.local`)\"\n      - \"traefik.http.routers.hello-detect.service=hello-detect\"\n      - \"traefik.http.routers.hello-detect.tls=true\"\n      - \"traefik.http.routers.hello-detect.tls.certresolver=default\"\n      - \"traefik.http.services.hello-detect.loadbalancer.server.scheme=http\"\n      - \"traefik.http.routers.hello-detect2.rule=Host(`hello-detect2.local`)\"\n      - \"traefik.http.routers.hello-detect2.service=hello-detect2\"\n      - \"traefik.http.routers.hello-detect2.tls=true\"\n      - \"traefik.http.routers.hello-detect2.tls.certresolver=default\"\n      - \"traefik.http.services.hello-detect2.loadbalancer.server.scheme=http\"\n\n  # Hello service with IP bind override\n  helloip:\n    image: helloworld\n    build:\n      dockerfile: ./helloworld/Dockerfile\n      context: ./\n    restart: unless-stopped\n    ports:\n      - 5599:5555\n    labels:\n      # - \"kop.bind.ip=6.6.6.6\"\n      - \"kop.helloip.bind.ip=4.4.4.4\"\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.helloip.rule=Host(`helloip.local`)\"\n      - \"traefik.http.routers.helloip.service=helloip\"\n      - \"traefik.http.routers.helloip.tls=true\"\n      - \"traefik.http.routers.helloip.tls.certresolver=default\"\n      - \"traefik.http.services.helloip.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.helloip.loadbalancer.server.port=5599\"\n\n  # Test case for #52 (typo in port label, uppercase 'B')\n  hellotcp:\n    image: helloworld\n    build:\n      dockerfile: ./helloworld/Dockerfile\n      context: ./\n    restart: unless-stopped\n    ports:\n      - 5555:5555\n      - 5566:5566\n      - 5577:5577\n      - 5578:5578/udp\n    labels:\n      # web\n      - traefik.enable=true\n      - traefik.http.routers.helloweb.rule=Host(\"helloweb.example.com\")\n      - traefik.http.routers.helloweb.service=helloweb\n      - traefik.http.services.helloweb.loadbalancer.server.port=5555\n      # web 2\n      - traefik.http.routers.helloweb2.rule=Host(\"helloweb2.example.com\")\n      - traefik.http.routers.helloweb2.service=helloweb2\n      - traefik.http.services.helloweb2.loadbalancer.server.port=5566\n      # tcp\n      - traefik.tcp.routers.hellotcp.entrypoints=tcp\n      - traefik.tcp.routers.hellotcp.rule=HostSNI(\"*\")\n      - traefik.tcp.routers.hellotcp.service=hellotcp\n      - traefik.tcp.services.hellotcp.loadBalancer.server.port=5577\n      # udp\n      - traefik.udp.routers.helloudp.entrypoints=udp\n      - traefik.udp.routers.helloudp.service=helloudp\n      - traefik.udp.services.helloudp.loadBalancer.server.port=5578\n\n  # Basic nginx with a simple healthcheck\n  nginx:\n    image: \"nginx:alpine\"\n    restart: unless-stopped\n    ports:\n      - 8088:80\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-s\", \"localhost:80\"]\n      timeout: 10s\n      interval: 2s\n      retries: 10\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.nginx.rule=Host(`nginx.local`)\"\n      - \"traefik.http.routers.nginx.tls=true\"\n      - \"traefik.http.routers.nginx.tls.certresolver=default\"\n      - \"traefik.http.services.nginx.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.nginx.loadbalancer.server.port=8088\"\n\n  # Pihole to test a specific bug report\n  pihole:\n    image: \"pihole/pihole:latest\"\n    restart: unless-stopped\n    ports:\n      - 8089:80\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.pihole.rule=Host(`pihole.local`)\"\n      - \"traefik.http.routers.pihole.tls=true\"\n      - \"traefik.http.routers.pihole.tls.certresolver=default\"\n      - \"traefik.http.services.pihole.loadbalancer.server.scheme=http\"\n      - \"traefik.http.services.pihole.loadbalancer.server.port=8089\"\n\n  gitea:\n    image: gitea/gitea\n    labels:\n      traefik.enable: true\n      # http\n      traefik.http.routers.gitea.rule: \"Host(`git.domain`)\"\n      traefik.http.routers.gitea.entrypoints: webs\n      traefik.http.routers.gitea.service: gitea@redis\n      traefik.http.services.gitea.loadbalancer.server.port: 20080\n      # tcp\n      traefik.tcp.routers.gitea-ssh.rule: \"HostSNI(`*`)\"\n      traefik.tcp.routers.gitea-ssh.entrypoints: ssh\n      traefik.tcp.routers.gitea-ssh.service: gitea-ssh@redis\n      traefik.tcp.services.gitea-ssh.loadbalancer.server.port: 20022\n\n  ephemeral:\n    image: \"nginx:alpine\"\n    restart: \"no\"\n    ports:\n      - 80\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.ephemeral.rule=Host(`ephemeral.local`)\"\n      - \"traefik.http.routers.ephemeral.tls=true\"\n      - \"traefik.http.routers.ephemeral.tls.certresolver=default\"\n      # not explicitly set, let kop figure it out\n      # - \"traefik.http.services.ephemeral.loadbalancer.server.scheme=http\"\n      # - \"traefik.http.services.ephemeral.loadbalancer.server.port=8099\"\n\n  nginx_prefix:\n    image: \"nginx:alpine\"\n    restart: unless-stopped\n    ports:\n      - 8090:80\n    labels:\n      - \"kop.baz.traefik.enable=true\"\n      - \"kop.baz.traefik.http.routers.nginx.rule=Host(`nginx.local`)\"\n      - \"kop.baz.traefik.http.routers.nginx.tls=true\"\n      - \"kop.baz.traefik.http.routers.nginx.tls.certresolver=default\"\n      - \"kop.baz.traefik.http.services.nginx.loadbalancer.server.scheme=http\"\n      - \"kop.baz.traefik.http.services.nginx.loadbalancer.server.port=8088\"\n"
  },
  {
    "path": "testing/helloworld/Dockerfile",
    "content": "FROM golang:alpine AS builder\n\nCOPY * /go/\nRUN go build -o helloworld ./\n\nFROM alpine:latest\n\nCOPY --from=builder /go/helloworld /helloworld\n\nENTRYPOINT [\"/helloworld\"]\n"
  },
  {
    "path": "testing/helloworld/README.md",
    "content": "# helloworld\n\nSimple helloworld service for testing a container which listens on multiple\nports (5555, 5566).\n"
  },
  {
    "path": "testing/helloworld/go.mod",
    "content": "module github.com/jittering/traefik-kop/testing/helloworld\n\ngo 1.22.3\n"
  },
  {
    "path": "testing/helloworld/main.go",
    "content": "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(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tio.WriteString(w, \"Hello from port 5555\")\n\t})\n\tfmt.Println(\"listening on port 5555\")\n\tgo http.ListenAndServe(\":5555\", mux)\n\n\tmux2 := http.NewServeMux()\n\tmux2.HandleFunc(\"/\", func(w http.ResponseWriter, r *http.Request) {\n\t\tio.WriteString(w, \"Hello from port 5566\")\n\t})\n\tfmt.Println(\"listening on port 5566\")\n\tgo http.ListenAndServe(\":5566\", mux2)\n\n\t// TCP listener on port 5577\n\tgo func() {\n\t\tln, err := net.Listen(\"tcp\", \":5577\")\n\t\tif err != nil {\n\t\t\tfmt.Println(\"Error starting TCP listener:\", err)\n\t\t\treturn\n\t\t}\n\t\tfmt.Println(\"listening on TCP port 5577\")\n\t\tfor {\n\t\t\tconn, err := ln.Accept()\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(\"Error accepting connection:\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tgo func(c net.Conn) {\n\t\t\t\tdefer c.Close()\n\t\t\t\tc.Write([]byte(\"hello world\\n\"))\n\t\t\t}(conn)\n\t\t}\n\t}()\n\n\t// UDP listener on port 5578\n\tgo func() {\n\t\taddr, err := net.ResolveUDPAddr(\"udp\", \":5578\")\n\t\tif err != nil {\n\t\t\tfmt.Println(\"Error resolving UDP address:\", err)\n\t\t\treturn\n\t\t}\n\t\tconn, err := net.ListenUDP(\"udp\", addr)\n\t\tif err != nil {\n\t\t\tfmt.Println(\"Error starting UDP listener:\", err)\n\t\t\treturn\n\t\t}\n\t\tdefer conn.Close()\n\t\tfmt.Println(\"listening on UDP port 5578\")\n\t\tbuffer := make([]byte, 1024)\n\t\tfor {\n\t\t\t_, clientAddr, err := conn.ReadFromUDP(buffer)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(\"Error reading from UDP:\", err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tresponse := []byte(\"hello world\\n\")\n\t\t\t_, err = conn.WriteToUDP(response, clientAddr)\n\t\t\tif err != nil {\n\t\t\t\tfmt.Println(\"Error writing to UDP:\", err)\n\t\t\t}\n\t\t}\n\t}()\n\n\t// Block forever\n\tselect {}\n}\n"
  },
  {
    "path": "testing/internal/Makefile",
    "content": "\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",
    "content": "# Test case for issue #51\n# https://github.com/jittering/traefik-kop/issues/51\n#\n# kop fails to start if outbound IP cannot be detected. uncomment BIND_IP to resolve.\nservices:\n  kop:\n    build: \"../../\"\n    restart: unless-stopped\n    environment:\n      - \"DEBUG=1\"\n      - \"REDIS_ADDR=redis:6379\"\n      # - \"BIND_IP=192.168.1.17\"\n    depends_on:\n      - redis\n    networks:\n      - kop_test\n      - default\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock:ro\n  redis:\n    image: redis:7-alpine\n    networks:\n      - kop_test\n      - default\n    healthcheck:\n      test: ['CMD', 'redis-cli', 'ping']\n\nnetworks:\n  default:\n    internal: true\n  kop_test:\n    internal: true\n"
  },
  {
    "path": "testing/kop/docker-compose.yml",
    "content": "# Compose file for testing traefik-kop itself from within a container env\nversion: \"3\"\n\nservices:\n  traefik-kop:\n    image: \"ghcr.io/jittering/traefik-kop:0.12.2-next-amd64\"\n    restart: unless-stopped\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n    environment:\n      REDIS_ADDR: \"172.28.183.97:6380\"\n      BIND_IP: \"172.28.183.97\"\n      DEBUG: \"1\"\n      DOCKER_CONFIG: |\n        ---\n        docker:\n          exposedByDefault: false\n          useBindPortIP: true\n"
  },
  {
    "path": "testing/publish-random.sh",
    "content": "#!/bin/bash\n\n# Test a docker run command\n\ndocker run --rm -it \\\n  --label \"traefik.enable=true\" \\\n  --label \"traefik.http.routers.nginx.rule=Host(\\`nginx.local\\`)\" \\\n  --label \"traefik.http.routers.nginx.tls=true\" \\\n  --label \"traefik.http.routers.nginx.tls.certresolver=default\" \\\n  --publish-all \\\n  nginx:alpine\n"
  },
  {
    "path": "traefik_kop.go",
    "content": "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/docker/api/types/container\"\n\t\"github.com/docker/docker/client\"\n\t\"github.com/rs/zerolog/log\"\n\tptypes \"github.com/traefik/paerser/types\"\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n\t\"github.com/traefik/traefik/v3/pkg/config/static\"\n\t\"github.com/traefik/traefik/v3/pkg/provider\"\n\t\"github.com/traefik/traefik/v3/pkg/provider/aggregator\"\n\t\"github.com/traefik/traefik/v3/pkg/provider/docker\"\n\t\"github.com/traefik/traefik/v3/pkg/safe\"\n\t\"github.com/traefik/traefik/v3/pkg/server\"\n\t\"golang.org/x/exp/slices\"\n)\n\nvar Version = \"\"\n\n// const defaultThrottleDuration = 5 * time.Second\n\n// newDockerProvider creates a provider via yaml config or returns a default\n// which connects to docker over a unix socket\nfunc newDockerProvider(config Config) *docker.Provider {\n\tdp, err := loadDockerConfig(config.DockerConfig)\n\tif err != nil {\n\t\tlog.Fatal().Msgf(\"failed to read docker config: %s\", err)\n\n\t}\n\n\tif dp == nil {\n\t\tdp = &docker.Provider{}\n\t}\n\n\t// set defaults\n\tif dp.Endpoint == \"\" {\n\t\tdp.Endpoint = config.DockerHost\n\t}\n\tif dp.HTTPClientTimeout.String() != \"0s\" && strings.HasPrefix(dp.Endpoint, \"unix://\") {\n\t\t// force to 0 for unix socket\n\t\tdp.HTTPClientTimeout = ptypes.Duration(defaultTimeout)\n\t}\n\tdp.Watch = true // always\n\n\treturn dp\n}\n\n// createConfigHandler returns a function that processes new traefik configurations\nfunc createConfigHandler(config Config, store TraefikStore, dp *docker.Provider, dockerClient client.APIClient) func(conf dynamic.Configuration) {\n\treturn func(conf dynamic.Configuration) {\n\t\t// logrus.Printf(\"got new conf..\\n\")\n\t\t// fmt.Printf(\"%s\\n\", dumpJson(conf))\n\t\tlog.Info().Msg(\"refreshing traefik-kop configuration\")\n\n\t\tdc := &dockerCache{\n\t\t\tclient:  dockerClient,\n\t\t\tlist:    nil,\n\t\t\tdetails: make(map[string]container.InspectResponse),\n\t\t}\n\n\t\tfilterServices(dc, &conf, config.Namespace)\n\n\t\tif !dp.UseBindPortIP && !config.SkipReplace {\n\t\t\t// if not using traefik's built in IP/Port detection, use our own\n\t\t\treplaceIPs(dc, &conf, config.BindIP)\n\t\t} else {\n\t\t\tlog.Debug().Msgf(\"skipping IP replacement (useBindPortIP=%v, skipReplace=%v)\", dp.UseBindPortIP, config.SkipReplace)\n\t\t}\n\n\t\tmergeLoadBalancers(dc, &conf, store)\n\n\t\terr := store.Store(conf)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n}\n\n// Start the main traefik-kop run-loop\nfunc Start(config Config) {\n\tdockerClient, err := createDockerClient(config.DockerHost)\n\tif err != nil {\n\t\tlog.Fatal().Msgf(\"failed to create docker client: %s\", err)\n\t}\n\n\tif config.DockerPrefix != \"\" {\n\t\t// use proxy to filter by label prefix\n\t\t//\n\t\t// Docker client is used in two places:\n\t\t// \t\t- Docker Provider which is used by traefik\n\t\t//    - dockerCache used by traefik-kop to lookup container info\n\t\t//\n\t\t// The real docker client is only used by the proxy.\n\t\t// All other usage goes via docker client connecting to the proxy.\n\n\t\tdockerProxy := createProxy(dockerClient, config.DockerPrefix)\n\t\t_, dockerProxyAddr := dockerProxy.start()\n\t\tconfig.DockerHost = dockerProxyAddr\n\t\tdockerClient, err = createDockerClient(dockerProxyAddr)\n\t\tif err != nil {\n\t\t\tlog.Fatal().Msgf(\"failed to create docker client for proxy: %s\", err)\n\t\t}\n\t}\n\n\tdp := newDockerProvider(config)\n\tstore := NewRedisStore(config.Hostname, config.RedisAddr, config.RedisTTL, config.RedisUser, config.RedisPass, config.RedisDB)\n\terr = store.Ping()\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), config.RedisAddr) {\n\t\t\tlog.Fatal().Msgf(\"failed to connect to redis: %s\", err)\n\t\t}\n\t\tlog.Fatal().Msgf(\"failed to connect to redis at %s: %s\", config.RedisAddr, err)\n\t}\n\n\tproviders := &static.Providers{\n\t\tDocker: dp,\n\t}\n\tproviderAggregator := aggregator.NewProviderAggregator(*providers)\n\n\tctx := context.Background()\n\troutinesPool := safe.NewPool(ctx)\n\n\thandleConfigChange := createConfigHandler(config, store, dp, dockerClient)\n\n\tpollingDockerProvider := newDockerProvider(config)\n\tpollingDockerProvider.Watch = false\n\tmultiProvider := NewMultiProvider([]provider.Provider{\n\t\tproviderAggregator,\n\t\tNewPollingProvider(\n\t\t\ttime.Second*time.Duration(config.PollInterval),\n\t\t\tpollingDockerProvider,\n\t\t\tstore,\n\t\t),\n\t})\n\n\t// initialize all providers\n\terr = multiProvider.Init()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\twatcher := server.NewConfigurationWatcher(\n\t\troutinesPool,\n\t\tmultiProvider,\n\t\t[]string{},\n\t\t\"docker\",\n\t)\n\twatcher.AddListener(handleConfigChange)\n\twatcher.Start()\n\n\tselect {} // go forever\n}\n\n// keepContainer returns true if the container should be kept based on namespace filtering\n//\n// Containers are kept if:\n//   - No namespaces are configured in traefik-kop and the container has no kop.namespace label (not\n//     using namespaces at all)\n//   - The container has a kop.namespace label that matches one of the configured namespaces\n//\n// ns is traefik-kop's configured namespaces to match against.\nfunc keepContainer(ns []string, container container.InspectResponse) bool {\n\tcontainerNS := splitStringArr(container.Config.Labels[\"kop.namespace\"])\n\tif len(ns) == 0 && len(containerNS) == 0 {\n\t\treturn true\n\t}\n\tfor _, v := range ns {\n\t\tif slices.Contains(containerNS, v) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// filter out services by namespace\n//\n// ns is traefik-kop's configured namespaces to match against.\nfunc filterServices(dc *dockerCache, conf *dynamic.Configuration, ns []string) {\n\tnsStr := strings.Join(ns, \", \")\n\n\tif conf.HTTP != nil && conf.HTTP.Services != nil {\n\t\tfor svcName := range conf.HTTP.Services {\n\t\t\tcontainer, err := dc.findContainerByServiceName(\"http\", svcName, getRouterOfService(conf, svcName, \"http\"))\n\t\t\tif err != nil {\n\t\t\t\tlog.Warn().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !keepContainer(ns, container) {\n\t\t\t\tlog.Info().Msgf(\"skipping service %s (not in namespace %s)\", svcName, nsStr)\n\t\t\t\tdelete(conf.HTTP.Services, svcName)\n\t\t\t}\n\t\t}\n\t}\n\n\tif conf.HTTP != nil && conf.HTTP.Routers != nil {\n\t\tfor routerName, router := range conf.HTTP.Routers {\n\t\t\tsvcName := router.Service\n\t\t\tcontainer, err := dc.findContainerByServiceName(\"http\", svcName, routerName)\n\t\t\tif err != nil {\n\t\t\t\tlog.Warn().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !keepContainer(ns, container) {\n\t\t\t\tlog.Info().Msgf(\"skipping router %s (not in namespace %s)\", routerName, nsStr)\n\t\t\t\tdelete(conf.HTTP.Routers, routerName)\n\t\t\t}\n\t\t}\n\t}\n\n\tif conf.TCP != nil && conf.TCP.Services != nil {\n\t\tfor svcName := range conf.TCP.Services {\n\t\t\tcontainer, err := dc.findContainerByServiceName(\"tcp\", svcName, getRouterOfService(conf, svcName, \"tcp\"))\n\t\t\tif err != nil {\n\t\t\t\tlog.Warn().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !keepContainer(ns, container) {\n\t\t\t\tlog.Info().Msgf(\"skipping service %s (not in namespace %s)\", svcName, nsStr)\n\t\t\t\tdelete(conf.TCP.Services, svcName)\n\t\t\t}\n\t\t}\n\t}\n\n\tif conf.TCP != nil && conf.TCP.Routers != nil {\n\t\tfor routerName, router := range conf.TCP.Routers {\n\t\t\tsvcName := router.Service\n\t\t\tcontainer, err := dc.findContainerByServiceName(\"tcp\", svcName, routerName)\n\t\t\tif err != nil {\n\t\t\t\tlog.Warn().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !keepContainer(ns, container) {\n\t\t\t\tlog.Info().Msgf(\"skipping router %s (not in namespace %s)\", routerName, nsStr)\n\t\t\t\tdelete(conf.TCP.Routers, routerName)\n\t\t\t}\n\t\t}\n\t}\n\n\tif conf.UDP != nil && conf.UDP.Services != nil {\n\t\tfor svcName := range conf.UDP.Services {\n\t\t\tcontainer, err := dc.findContainerByServiceName(\"udp\", svcName, getRouterOfService(conf, svcName, \"udp\"))\n\t\t\tif err != nil {\n\t\t\t\tlog.Warn().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !keepContainer(ns, container) {\n\t\t\t\tlog.Warn().Msgf(\"service %s is not running: removing from config\", svcName)\n\t\t\t\tdelete(conf.UDP.Services, svcName)\n\t\t\t}\n\t\t}\n\t}\n\n\tif conf.UDP != nil && conf.UDP.Routers != nil {\n\t\tfor routerName, router := range conf.UDP.Routers {\n\t\t\tsvcName := router.Service\n\t\t\tcontainer, err := dc.findContainerByServiceName(\"udp\", svcName, routerName)\n\t\t\tif err != nil {\n\t\t\t\tlog.Warn().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif !keepContainer(ns, container) {\n\t\t\t\tlog.Info().Msgf(\"skipping router %s (not in namespace %s)\", routerName, nsStr)\n\t\t\t\tdelete(conf.UDP.Routers, routerName)\n\t\t\t}\n\t\t}\n\t}\n}\n\n// replaceIPs for all service endpoints\n//\n// By default, traefik finds the local/internal docker IP for each container.\n// Since we are exposing these services to an external node/server, we need\n// to replace any IPs with the correct IP for this server, as configured at startup.\n//\n// When using CNI, as indicated by the container label `traefik.docker.network`,\n// we will stick with the container IP.\nfunc replaceIPs(dc *dockerCache, conf *dynamic.Configuration, ip string) {\n\t// modify HTTP URLs\n\tif conf.HTTP != nil && conf.HTTP.Services != nil {\n\t\tfor svcName, svc := range conf.HTTP.Services {\n\t\t\tlog := log.With().Str(\"service\", svcName).Str(\"service-type\", \"http\").Logger()\n\t\t\tlog.Debug().Msgf(\"found http service: %s\", svcName)\n\t\t\tfor i := range svc.LoadBalancer.Servers {\n\t\t\t\tip, changed := getKopOverrideBinding(dc, conf, \"http\", svcName, ip)\n\t\t\t\tif !changed {\n\t\t\t\t\t// override with container IP if we have a routable IP\n\t\t\t\t\tip = getContainerNetworkIP(dc, conf, \"http\", svcName, ip)\n\t\t\t\t}\n\n\t\t\t\t// replace ip into URLs\n\t\t\t\tserver := &svc.LoadBalancer.Servers[i]\n\t\t\t\tif server.URL != \"\" {\n\t\t\t\t\t// the URL IP will initially refer to the container-local IP\n\t\t\t\t\t//\n\t\t\t\t\t// the URL Port will initially be the configured port number, either\n\t\t\t\t\t// explicitly via traefik label or detected by traefik. We cannot\n\t\t\t\t\t// determine how the port was set without looking at the traefik\n\t\t\t\t\t// labels ourselves.\n\t\t\t\t\tlog.Debug().Msgf(\"using load balancer URL for port detection: %s\", server.URL)\n\t\t\t\t\tu, _ := url.Parse(server.URL)\n\t\t\t\t\tp := getContainerPort(dc, conf, \"http\", svcName, u.Port())\n\t\t\t\t\tif p != \"\" {\n\t\t\t\t\t\tu.Host = ip + \":\" + p\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.Host = ip\n\t\t\t\t\t}\n\t\t\t\t\tserver.URL = u.String()\n\t\t\t\t} else {\n\t\t\t\t\tscheme := \"http\"\n\t\t\t\t\tif server.Scheme != \"\" {\n\t\t\t\t\t\tscheme = server.Scheme\n\t\t\t\t\t}\n\t\t\t\t\tserver.URL = fmt.Sprintf(\"%s://%s\", scheme, ip)\n\t\t\t\t\tport := getContainerPort(dc, conf, \"http\", svcName, server.Port)\n\t\t\t\t\tif port != \"\" {\n\t\t\t\t\t\tserver.URL += \":\" + server.Port\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif conf.HTTP.Routers != nil {\n\t\t\t\tfor routerName, router := range conf.HTTP.Routers {\n\t\t\t\t\tif router.Service+\"@docker\" == svcName && (router.TLS == nil || strings.TrimSpace(router.TLS.CertResolver) == \"\") {\n\t\t\t\t\t\tlog.Warn().Msgf(\"router %s has no TLS cert resolver\", routerName)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// TCP\n\tif conf.TCP != nil && conf.TCP.Services != nil {\n\t\tfor svcName, svc := range conf.TCP.Services {\n\t\t\tlog := log.With().Str(\"service\", svcName).Str(\"service-type\", \"tcp\").Logger()\n\t\t\tlog.Debug().Msgf(\"found tcp service: %s\", svcName)\n\t\t\tfor i := range svc.LoadBalancer.Servers {\n\t\t\t\t// override with container IP if we have a routable IP\n\t\t\t\tip = getContainerNetworkIP(dc, conf, \"tcp\", svcName, ip)\n\n\t\t\t\tserver := &svc.LoadBalancer.Servers[i]\n\t\t\t\tserver.Port = getContainerPort(dc, conf, \"tcp\", svcName, server.Port)\n\t\t\t\tlog.Debug().Msgf(\"using ip '%s' and port '%s' for %s\", ip, server.Port, svcName)\n\t\t\t\tserver.Address = ip\n\t\t\t\tif server.Port != \"\" {\n\t\t\t\t\tserver.Address += \":\" + server.Port\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// UDP\n\tif conf.UDP != nil && conf.UDP.Services != nil {\n\t\tfor svcName, svc := range conf.UDP.Services {\n\t\t\tlog := log.With().Str(\"service\", svcName).Str(\"service-type\", \"udp\").Logger()\n\t\t\tlog.Debug().Msgf(\"found udp service: %s\", svcName)\n\t\t\tfor i := range svc.LoadBalancer.Servers {\n\t\t\t\t// override with container IP if we have a routable IP\n\t\t\t\tip = getContainerNetworkIP(dc, conf, \"udp\", svcName, ip)\n\n\t\t\t\tserver := &svc.LoadBalancer.Servers[i]\n\t\t\t\tserver.Port = getContainerPort(dc, conf, \"udp\", svcName, server.Port)\n\t\t\t\tlog.Debug().Msgf(\"using ip '%s' and port '%s' for %s\", ip, server.Port, svcName)\n\t\t\t\tserver.Address = ip\n\t\t\t\tif server.Port != \"\" {\n\t\t\t\t\tserver.Address += \":\" + server.Port\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n// Get the matching router name for the given service.\n//\n// It is possible that no traefik service was explicitly configured, only a\n// router. In this case, we need to use the router name to find the traefik\n// labels to identify the container.\nfunc getRouterOfService(conf *dynamic.Configuration, svcName string, svcType string) string {\n\tsvcName = stripDocker(svcName)\n\tname := \"\"\n\n\tif svcType == \"http\" {\n\t\tfor routerName, router := range conf.HTTP.Routers {\n\t\t\tif router.Service == svcName {\n\t\t\t\tname = routerName\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t} else if svcType == \"tcp\" {\n\t\tfor routerName, router := range conf.TCP.Routers {\n\t\t\tif router.Service == svcName {\n\t\t\t\tname = routerName\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t} else if svcType == \"udp\" {\n\t\tfor routerName, router := range conf.UDP.Routers {\n\t\t\tif router.Service == svcName {\n\t\t\t\tname = routerName\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tlog.Debug().Msgf(\"found router '%s' for service %s\", name, svcName)\n\treturn name\n}\n\n// Get host-port binding from container, if not explicitly set via labels\n//\n// The `port` param is the value which was either set via label or inferred by\n// traefik during its config parsing (possibly an container-internal port). The\n// purpose of this method is to see if we can find a better match, specifically\n// by looking at the host-port bindings in the docker config.\nfunc getContainerPort(dc *dockerCache, conf *dynamic.Configuration, svcType string, svcName string, port string) string {\n\tlog := log.With().Str(\"service\", svcName).Str(\"service-type\", svcType).Logger()\n\tcontainer, err := dc.findContainerByServiceName(svcType, svcName, getRouterOfService(conf, svcName, svcType))\n\tif err != nil {\n\t\tlog.Warn().Msgf(\"failed to find host-port: %s\", err)\n\t\treturn port\n\t}\n\tif p := isPortSet(container, svcType, svcName); p != \"\" {\n\t\tlog.Debug().Msgf(\"using explicitly set port %s for %s\", p, svcName)\n\t\treturn p\n\t}\n\texposedPort, err := getPortBinding(container)\n\tif err != nil {\n\t\tif strings.Contains(err.Error(), \"no host-port binding\") {\n\t\t\tlog.Debug().Err(err)\n\t\t} else {\n\t\t\tlog.Warn().Err(err)\n\t\t}\n\t\tlog.Debug().Msgf(\"using existing port %s\", port)\n\t\treturn port\n\t}\n\tif exposedPort == \"\" {\n\t\tlog.Warn().Msgf(\"failed to find host-port for service %s\", svcName)\n\t\treturn port\n\t}\n\tlog.Debug().Msgf(\"overriding service port from container host-port: using %s (was %s) for %s\", exposedPort, port, svcName)\n\treturn exposedPort\n}\n\n// Gets the container IP when it is configured to use a network-routable address\n// (i.e., via CNI plugins such as calico or weave)\n//\n// If not configured, returns the globally bound hostIP\nfunc getContainerNetworkIP(dc *dockerCache, conf *dynamic.Configuration, svcType string, svcName string, hostIP string) string {\n\tcontainer, err := dc.findContainerByServiceName(svcType, svcName, getRouterOfService(conf, svcName, svcType))\n\tif err != nil {\n\t\tlog.Debug().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\treturn hostIP\n\t}\n\n\tnetworkName := container.Config.Labels[\"traefik.docker.network\"]\n\tif networkName == \"\" {\n\t\tlog.Debug().Msgf(\"no network label set for %s\", svcName)\n\t\treturn hostIP\n\t}\n\n\tif container.NetworkSettings != nil {\n\t\tnetworkEndpoint := container.NetworkSettings.Networks[networkName]\n\t\tif networkEndpoint != nil {\n\t\t\tnetworkIP := networkEndpoint.IPAddress\n\t\t\tlog.Debug().Msgf(\"found network name '%s' with container IP '%s' for service %s\", networkName, networkIP, svcName)\n\t\t\treturn networkIP\n\t\t}\n\t}\n\t// fallback\n\tlog.Debug().Msgf(\"container IP not found for %s\", svcName)\n\treturn hostIP\n}\n\n// Check for explicit IP binding set via label\n//\n// Label can be one of two keys:\n// - kop.<service name>.bind.ip = 2.2.2.2\n// - kop.bind.ip = 2.2.2.2\n//\n// For a container with only a single exposed service, or where all services use\n// the same IP, the latter is sufficient.\nfunc getKopOverrideBinding(dc *dockerCache, conf *dynamic.Configuration, svcType string, svcName string, hostIP string) (string, bool) {\n\tcontainer, err := dc.findContainerByServiceName(svcType, svcName, getRouterOfService(conf, svcName, svcType))\n\tif err != nil {\n\t\tlog.Debug().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\treturn hostIP, false\n\t}\n\n\tsvcName = stripDocker(svcName)\n\tsvcNeedle := fmt.Sprintf(\"kop.%s.bind.ip\", svcName)\n\tif ip := container.Config.Labels[svcNeedle]; ip != \"\" {\n\t\tlog.Debug().Msgf(\"found label %s with IP '%s' for service %s\", svcNeedle, ip, svcName)\n\t\treturn ip, true\n\t}\n\n\tif ip := container.Config.Labels[\"kop.bind.ip\"]; ip != \"\" {\n\t\tlog.Debug().Msgf(\"found label %s with IP '%s' for service %s\", \"kop.bind.ip\", ip, svcName)\n\t\treturn ip, true\n\t}\n\n\treturn hostIP, false\n}\n\n// mergeLoadBalancers merges load balancer servers for all protocols (http, tcp, udp) with the LBs\n// found in the Traefik store (redis). This allows kops running on multiple nodes to add their respective\n// IPs so that traefik can properly distribute the load.\nfunc mergeLoadBalancers(dc *dockerCache, conf *dynamic.Configuration, store TraefikStore) {\n\tmergeGenericLoadBalancers(dc, conf, \"http\", conf.HTTP, store, func(server interface{}) string {\n\t\tif s, ok := server.(dynamic.Server); ok {\n\t\t\treturn s.URL\n\t\t}\n\t\treturn \"\"\n\t}, func(url string) interface{} {\n\t\treturn dynamic.Server{URL: url}\n\t})\n\n\tmergeGenericLoadBalancers(dc, conf, \"tcp\", conf.TCP, store, func(server interface{}) string {\n\t\tif s, ok := server.(dynamic.TCPServer); ok {\n\t\t\treturn s.Address\n\t\t}\n\t\treturn \"\"\n\t}, func(addr string) interface{} {\n\t\treturn dynamic.TCPServer{Address: addr}\n\t})\n\n\tmergeGenericLoadBalancers(dc, conf, \"udp\", conf.UDP, store, func(server interface{}) string {\n\t\tif s, ok := server.(dynamic.UDPServer); ok {\n\t\t\treturn s.Address\n\t\t}\n\t\treturn \"\"\n\t}, func(addr string) interface{} {\n\t\treturn dynamic.UDPServer{Address: addr}\n\t})\n}\n\n// mergeGenericLoadBalancers merges servers for a given protocol using generic logic\nfunc mergeGenericLoadBalancers(\n\tdc *dockerCache,\n\tconf *dynamic.Configuration,\n\tsvcType string,\n\tsvcConf interface{},\n\tstore TraefikStore,\n\tgetKey func(interface{}) string,\n\tmakeServer func(string) interface{},\n) {\n\tif svcConf == nil {\n\t\treturn\n\t}\n\n\t// Use reflection to access Services map\n\tv := reflect.ValueOf(svcConf)\n\tservicesField := v.Elem().FieldByName(\"Services\")\n\tif !servicesField.IsValid() || servicesField.IsNil() {\n\t\treturn\n\t}\n\n\tfor _, key := range servicesField.MapKeys() {\n\t\tsvcName := key.String()\n\n\t\tcontainer, err := dc.findContainerByServiceName(svcType, svcName, getRouterOfService(conf, svcName, svcType))\n\t\tif err != nil {\n\t\t\tlog.Debug().Msgf(\"failed to find container for service '%s': %s\", svcName, err)\n\t\t\tcontinue\n\t\t}\n\n\t\tmerge, _ := strconv.ParseBool(container.Config.Labels[\"kop.merge-lbs\"])\n\t\tif !merge {\n\t\t\t// backwards compat - allow traefik prefix due to earlier typo\n\t\t\tmerge, _ = strconv.ParseBool(container.Config.Labels[\"traefik.merge-lbs\"])\n\t\t}\n\t\tif !merge {\n\t\t\tcontinue\n\t\t}\n\n\t\t// Get existing keys from store\n\t\tvar storeKey string\n\t\tswitch svcType {\n\t\tcase \"http\":\n\t\t\tstoreKey = fmt.Sprintf(\"traefik/http/services/%s/loadBalancer/servers/*/url\", stripDocker(svcName))\n\t\tcase \"tcp\", \"udp\":\n\t\t\tstoreKey = fmt.Sprintf(\"traefik/%s/services/%s/loadBalancer/servers/*/address\", svcType, stripDocker(svcName))\n\t\t}\n\t\texistingKeys, err := store.Gets(storeKey)\n\t\tif err != nil {\n\t\t\tlog.Warn().Msgf(\"failed to get existing servers for service %s: %s\", svcName, err)\n\t\t\tcontinue\n\t\t}\n\t\tif len(existingKeys) == 0 {\n\t\t\tlog.Debug().Msgf(\"no existing servers found for service %s, skip merge\", svcName)\n\t\t\tcontinue\n\t\t}\n\n\t\t// collect list of urls or addresses\n\t\tkeySet := make(map[string]struct{})\n\t\tfor _, k := range existingKeys {\n\t\t\tkeySet[k] = struct{}{}\n\t\t}\n\n\t\t// Add our config hosts\n\t\tsvc := servicesField.MapIndex(key)\n\t\tif !svc.IsValid() || svc.IsNil() {\n\t\t\tcontinue\n\t\t}\n\t\tlbField := svc.Elem().FieldByName(\"LoadBalancer\")\n\t\tif !lbField.IsValid() || lbField.IsNil() {\n\t\t\tcontinue\n\t\t}\n\t\tserversField := lbField.Elem().FieldByName(\"Servers\")\n\t\tif !serversField.IsValid() {\n\t\t\tcontinue\n\t\t}\n\t\tfor i := 0; i < serversField.Len(); i++ {\n\t\t\tserver := serversField.Index(i).Interface()\n\t\t\tk := getKey(server)\n\t\t\tif k != \"\" {\n\t\t\t\tkeySet[k] = struct{}{}\n\t\t\t}\n\t\t}\n\n\t\t// Create merged list\n\t\tnewServers := reflect.MakeSlice(serversField.Type(), 0, len(keySet))\n\t\tfor k := range keySet {\n\t\t\tnewServers = reflect.Append(newServers, reflect.ValueOf(makeServer(k)))\n\t\t}\n\t\tserversField.Set(newServers)\n\t\tif newServers.Len() > len(existingKeys) {\n\t\t\tlog.Debug().Msgf(\"merged %d %s servers into service %s\", newServers.Len()-len(existingKeys), svcType, svcName)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "traefik_kop_test.go",
    "content": "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.com/docker/docker/api/types\"\n\t\"github.com/docker/docker/api/types/container\"\n\t\"github.com/docker/docker/client\"\n\t\"github.com/docker/go-connections/nat\"\n\t\"github.com/rs/zerolog\"\n\t\"github.com/rs/zerolog/log\"\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/stretchr/testify/require\"\n\t\"github.com/traefik/traefik/v3/pkg/config/dynamic\"\n)\n\nfunc init() {\n\tlogrus.SetLevel(logrus.DebugLevel)\n\tzerolog.SetGlobalLevel(zerolog.DebugLevel)\n}\n\ntype fakeDockerClient struct {\n\tclient.APIClient\n\tcontainers []container.Summary\n\tcontainer  container.InspectResponse\n\terr        error\n}\n\nfunc (c *fakeDockerClient) ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) {\n\treturn c.containers, nil\n}\n\nfunc (c *fakeDockerClient) ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error) {\n\treturn c.container, c.err\n}\n\nfunc Test_replaceIPs(t *testing.T) {\n\tcfg := &dynamic.Configuration{}\n\terr := json.Unmarshal([]byte(NGINX_CONF_JSON), cfg)\n\trequire.NoError(t, err)\n\trequire.Contains(t, cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"172.20.0.2\")\n\n\tfc := &dockerCache{client: &fakeDockerClient{}, list: nil, details: make(map[string]container.InspectResponse)}\n\n\t// replace and test check again\n\treplaceIPs(fc, cfg, \"7.7.7.7\")\n\trequire.NotContains(t, cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"172.20.0.2\")\n\n\t// full url\n\trequire.Equal(t, \"http://7.7.7.7:80\", cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL)\n\n\t// test again with larger fixture, tcp service\n\tcfg = &dynamic.Configuration{}\n\t_, err = toml.DecodeFile(\"./fixtures/sample.toml\", &cfg)\n\trequire.NoError(t, err)\n\trequire.Equal(t, \"foobar\", cfg.TCP.Services[\"TCPService0\"].LoadBalancer.Servers[0].Address)\n\treplaceIPs(fc, cfg, \"7.7.7.7\")\n\trequire.Equal(t, \"7.7.7.7\", cfg.TCP.Services[\"TCPService0\"].LoadBalancer.Servers[0].Address)\n}\n\nfunc createTestClient(labels map[string]string) *fakeDockerClient {\n\treturn &fakeDockerClient{\n\t\tcontainers: []container.Summary{\n\t\t\tcontainer.Summary{\n\t\t\t\tID: \"foobar_id\",\n\t\t\t},\n\t\t},\n\t\tcontainer: container.InspectResponse{\n\t\t\tContainerJSONBase: &types.ContainerJSONBase{\n\t\t\t\tID:         \"foobar_id\",\n\t\t\t\tHostConfig: &container.HostConfig{},\n\t\t\t},\n\t\t\tConfig: &container.Config{\n\t\t\t\tLabels: labels,\n\t\t\t},\n\t\t},\n\t}\n\n}\n\nfunc Test_replacePorts(t *testing.T) {\n\tlog.Debug().Msg(\"Testing replacePorts\")\n\n\tportLabel := \"traefik.http.services.nginx.loadbalancer.server.port\"\n\tdc := createTestClient(map[string]string{\n\t\t\"traefik.http.services.nginx.loadbalancer.server.scheme\": \"http\",\n\t\tportLabel: \"8888\",\n\t})\n\n\tfc := &dockerCache{client: dc, list: nil, details: make(map[string]container.InspectResponse)}\n\n\tcfg := &dynamic.Configuration{}\n\terr := json.Unmarshal([]byte(NGINX_CONF_JSON), cfg)\n\trequire.NoError(t, err)\n\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"172.20.0.2:80\"))\n\n\t// explicit label present\n\tlog.Debug().Msg(\"explicit label present\")\n\treplaceIPs(fc, cfg, \"4.4.4.4\")\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:8888\"), \"URL '%s' should end with '%s'\", cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:8888\")\n\n\t// without label but no port binding\n\tlog.Debug().Msg(\"without label but no port binding\")\n\tdelete(dc.container.Config.Labels, portLabel)\n\tjson.Unmarshal([]byte(NGINX_CONF_JSON), cfg)\n\treplaceIPs(fc, cfg, \"4.4.4.4\")\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:80\"))\n\n\t// with port binding\n\tlog.Debug().Msg(\"with port binding\")\n\tportMap := nat.PortMap{\n\t\t\"80\": []nat.PortBinding{\n\t\t\t{HostIP: \"172.20.0.2\", HostPort: \"8888\"},\n\t\t},\n\t}\n\n\tdc.container.HostConfig.PortBindings = portMap\n\tlogJSON(\"container\", dc.container)\n\tjson.Unmarshal([]byte(NGINX_CONF_JSON), cfg)\n\treplaceIPs(fc, cfg, \"4.4.4.4\")\n\trequire.False(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:80\"))\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:8888\"))\n}\n\nfunc Test_replacePortsNoService(t *testing.T) {\n\n\tportMap := nat.PortMap{\n\t\t\"80\": []nat.PortBinding{\n\t\t\t{HostIP: \"172.20.0.2\", HostPort: \"8888\"},\n\t\t},\n\t}\n\n\tdc := createTestClient(map[string]string{\n\t\t\"traefik.http.routers.nginx.entrypoints\": \"web-secure\",\n\t})\n\tfc := &dockerCache{client: dc, list: nil, details: make(map[string]container.InspectResponse)}\n\n\tcfg := &dynamic.Configuration{}\n\terr := json.Unmarshal([]byte(NGINX_CONF_JSON_DIFFRENT_SERVICE_NAME), cfg)\n\trequire.NoError(t, err)\n\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx-nginx@docker\"].LoadBalancer.Servers[0].URL, \"172.20.0.2:80\"))\n\n\t// explicit label present\n\treplaceIPs(fc, cfg, \"4.4.4.4\")\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx-nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:80\"))\n\n\t// without label but no port binding\n\tjson.Unmarshal([]byte(NGINX_CONF_JSON_DIFFRENT_SERVICE_NAME), cfg)\n\treplaceIPs(fc, cfg, \"4.4.4.4\")\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx-nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:80\"))\n\n\t// with port binding\n\tdc.container.HostConfig.PortBindings = portMap\n\tjson.Unmarshal([]byte(NGINX_CONF_JSON_DIFFRENT_SERVICE_NAME), cfg)\n\treplaceIPs(fc, cfg, \"4.4.4.4\")\n\trequire.False(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx-nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:80\"))\n\trequire.True(t, strings.HasSuffix(cfg.HTTP.Services[\"nginx-nginx@docker\"].LoadBalancer.Servers[0].URL, \"4.4.4.4:8888\"))\n}\n"
  },
  {
    "path": "util.go",
    "content": "package traefikkop\n\nimport (\n\t\"encoding/json\"\n\t\"strings\"\n)\n\nfunc dumpJson(o interface{}) []byte {\n\tout, err := json.Marshal(o)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn out\n}\n\nfunc splitStringArr(str string) []string {\n\ttrimmed := strings.TrimSpace(str)\n\tif trimmed != \"\" {\n\t\ttrimmedVals := strings.Split(trimmed, \",\")\n\t\tsplitArr := make([]string, len(trimmedVals))\n\t\tfor i, v := range trimmedVals {\n\t\t\tsplitArr[i] = strings.TrimSpace(v)\n\t\t}\n\t\treturn splitArr\n\t}\n\treturn []string{}\n}\n"
  }
]