mirror of
https://github.com/traefik/traefik
synced 2026-02-03 06:30:31 +00:00
Merge v2.11 into v3.6
This commit is contained in:
@@ -51,12 +51,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
env:
|
env:
|
||||||
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
|
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
|
||||||
with:
|
with:
|
||||||
@@ -64,7 +64,7 @@ jobs:
|
|||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Artifact webui
|
- name: Artifact webui
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||||
with:
|
with:
|
||||||
name: webui.tar.gz
|
name: webui.tar.gz
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
run: ./docs/scripts/lint.sh docs
|
run: ./docs/scripts/lint.sh docs
|
||||||
|
|
||||||
- name: Setup python
|
- name: Setup python
|
||||||
uses: actions/setup-python@v6
|
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
|
||||||
with:
|
with:
|
||||||
python-version: '3.12'
|
python-version: '3.12'
|
||||||
cache: 'pip'
|
cache: 'pip'
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
mkdocs build --strict
|
mkdocs build --strict
|
||||||
|
|
||||||
- name: Setup ruby
|
- name: Setup ruby
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ruby/setup-ruby@e69dcf3ded5967f30d7ef595704928d91cdae930 # v1.285.0
|
||||||
with:
|
with:
|
||||||
ruby-version: '3.4'
|
ruby-version: '3.4'
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
|
|
||||||
# Comes from https://github.com/gjtorikian/html-proofer?tab=readme-ov-file#caching-with-continuous-integration
|
# Comes from https://github.com/gjtorikian/html-proofer?tab=readme-ov-file#caching-with-continuous-integration
|
||||||
- name: Cache HTMLProofer
|
- name: Cache HTMLProofer
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: tmp/.htmlproofer
|
path: tmp/.htmlproofer
|
||||||
key: ${{ runner.os }}-htmlproofer
|
key: ${{ runner.os }}-htmlproofer
|
||||||
|
|||||||
@@ -28,17 +28,17 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
|
|
||||||
- name: setup go
|
- name: setup go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
if: ${{ matrix.language == 'go' }}
|
if: ${{ matrix.language == 'go' }}
|
||||||
with:
|
with:
|
||||||
go-version-file: 'go.mod'
|
go-version-file: 'go.mod'
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@4bdb89f48054571735e3792627da6195c57459e2 # v3.31.10
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
@@ -52,7 +52,7 @@ jobs:
|
|||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v3
|
uses: github/codeql-action/autobuild@4bdb89f48054571735e3792627da6195c57459e2 # v3.31.10
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
@@ -65,6 +65,6 @@ jobs:
|
|||||||
# ./location_of_script_within_repo/buildscript.sh
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@4bdb89f48054571735e3792627da6195c57459e2 # v3.31.10
|
||||||
with:
|
with:
|
||||||
category: "/language:${{matrix.language}}"
|
category: "/language:${{matrix.language}}"
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|||||||
@@ -23,12 +23,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
env:
|
env:
|
||||||
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
|
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
|
||||||
with:
|
with:
|
||||||
@@ -42,19 +42,19 @@ jobs:
|
|||||||
run: echo ${GITHUB_REF##*/}
|
run: echo ${GITHUB_REF##*/}
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||||
|
|
||||||
- name: Artifact webui
|
- name: Artifact webui
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||||
with:
|
with:
|
||||||
name: webui.tar.gz
|
name: webui.tar.gz
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
env:
|
env:
|
||||||
# Ensure cache consistency on Linux, see https://github.com/actions/setup-go/pull/383
|
# Ensure cache consistency on Linux, see https://github.com/actions/setup-go/pull/383
|
||||||
ImageOS: ${{ matrix.os }}
|
ImageOS: ${{ matrix.os }}
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Artifact webui
|
- name: Artifact webui
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||||
with:
|
with:
|
||||||
name: webui.tar.gz
|
name: webui.tar.gz
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ jobs:
|
|||||||
echo "GORELEASER_CONFIG_FILE_PATH=$GORELEASER_CONFIG_FILE_PATH" >> $GITHUB_ENV
|
echo "GORELEASER_CONFIG_FILE_PATH=$GORELEASER_CONFIG_FILE_PATH" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build with goreleaser
|
- name: Build with goreleaser
|
||||||
uses: goreleaser/goreleaser-action@v6
|
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
|
||||||
with:
|
with:
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
# 'latest', 'nightly', or a semver
|
# 'latest', 'nightly', or a semver
|
||||||
@@ -71,7 +71,7 @@ jobs:
|
|||||||
args: release --clean --timeout="90m" --config "${{ env.GORELEASER_CONFIG_FILE_PATH }}"
|
args: release --clean --timeout="90m" --config "${{ env.GORELEASER_CONFIG_FILE_PATH }}"
|
||||||
|
|
||||||
- name: Artifact binaries
|
- name: Artifact binaries
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.os }}-binaries
|
name: ${{ matrix.os }}-binaries
|
||||||
path: |
|
path: |
|
||||||
@@ -89,12 +89,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Artifact webui
|
- name: Artifact webui
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||||
with:
|
with:
|
||||||
name: webui.tar.gz
|
name: webui.tar.gz
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ jobs:
|
|||||||
echo "${TRAEFIKER_RSA}" | base64 --decode > ~/.ssh/traefiker_rsa
|
echo "${TRAEFIKER_RSA}" | base64 --decode > ~/.ssh/traefiker_rsa
|
||||||
|
|
||||||
- name: Download All Artifacts
|
- name: Download All Artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: dist/
|
path: dist/
|
||||||
pattern: "*-binaries"
|
pattern: "*-binaries"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ jobs:
|
|||||||
run: corepack enable
|
run: corepack enable
|
||||||
|
|
||||||
- name: Setup node
|
- name: Setup node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: webui/.nvmrc
|
node-version-file: webui/.nvmrc
|
||||||
cache: yarn
|
cache: yarn
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
tar czvf webui.tar.gz ./webui/static/
|
tar czvf webui.tar.gz ./webui/static/
|
||||||
|
|
||||||
- name: Artifact webui
|
- name: Artifact webui
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: webui.tar.gz
|
name: webui.tar.gz
|
||||||
path: webui.tar.gz
|
path: webui.tar.gz
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -38,14 +38,14 @@ jobs:
|
|||||||
run: make binary-linux-amd64
|
run: make binary-linux-amd64
|
||||||
|
|
||||||
- name: Save go cache build
|
- name: Save go cache build
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
key: ${{ runner.os }}-go-build-cache-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
|
key: ${{ runner.os }}-go-build-cache-${{ env.GO_VERSION }}-${{ hashFiles('**/go.sum') }}
|
||||||
|
|
||||||
- name: Artifact traefik binary
|
- name: Artifact traefik binary
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
name: traefik
|
name: traefik
|
||||||
path: ./dist/linux/amd64/traefik
|
path: ./dist/linux/amd64/traefik
|
||||||
@@ -63,18 +63,18 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: Download traefik binary
|
- name: Download traefik binary
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||||
with:
|
with:
|
||||||
name: traefik
|
name: traefik
|
||||||
path: ./dist/linux/amd64/
|
path: ./dist/linux/amd64/
|
||||||
@@ -83,7 +83,7 @@ jobs:
|
|||||||
run: chmod +x ./dist/linux/amd64/traefik
|
run: chmod +x ./dist/linux/amd64/traefik
|
||||||
|
|
||||||
- name: Restore go cache build
|
- name: Restore go cache build
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
@@ -91,7 +91,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Generate go test Slice
|
- name: Generate go test Slice
|
||||||
id: test_split
|
id: test_split
|
||||||
uses: hashicorp-forge/go-test-split-action@v2.0.0
|
uses: hashicorp-forge/go-test-split-action@720a77701f0d1b2973126510492a6aad11ed0d5a # v2.0.0
|
||||||
with:
|
with:
|
||||||
packages: ./integration
|
packages: ./integration
|
||||||
total: ${{ matrix.parallel }}
|
total: ${{ matrix.parallel }}
|
||||||
|
|||||||
@@ -20,12 +20,12 @@ jobs:
|
|||||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -46,12 +46,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -65,7 +65,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
run: corepack enable
|
run: corepack enable
|
||||||
|
|
||||||
- name: Set up Node.js ${{ env.NODE_VERSION }}
|
- name: Set up Node.js ${{ env.NODE_VERSION }}
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||||
with:
|
with:
|
||||||
node-version-file: webui/.nvmrc
|
node-version-file: webui/.nvmrc
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
|
|||||||
@@ -17,18 +17,18 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v7
|
uses: golangci/golangci-lint-action@9fae48acfc02a90574d7c304a1758ef9895495fa # v7.0.1
|
||||||
with:
|
with:
|
||||||
version: "${{ env.GOLANGCI_LINT_VERSION }}"
|
version: "${{ env.GOLANGCI_LINT_VERSION }}"
|
||||||
|
|
||||||
@@ -37,12 +37,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -58,12 +58,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Go ${{ env.GO_VERSION }}
|
- name: Set up Go ${{ env.GO_VERSION }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
|
||||||
with:
|
with:
|
||||||
go-version: ${{ env.GO_VERSION }}
|
go-version: ${{ env.GO_VERSION }}
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ docs: docs-clean docs-image docs-lint docs-build docs-verify
|
|||||||
# Writer Mode: build and serve docs on http://localhost:8000 with livereload
|
# Writer Mode: build and serve docs on http://localhost:8000 with livereload
|
||||||
.PHONY: docs-serve
|
.PHONY: docs-serve
|
||||||
docs-serve: docs-image
|
docs-serve: docs-image
|
||||||
docker run $(DOCKER_RUN_DOC_OPTS) $(TRAEFIK_DOCS_BUILD_IMAGE) mkdocs serve
|
docker run $(DOCKER_RUN_DOC_OPTS) $(TRAEFIK_DOCS_BUILD_IMAGE) mkdocs serve -a 0.0.0.0:8000
|
||||||
|
|
||||||
## Pull image for doc building
|
## Pull image for doc building
|
||||||
.PHONY: docs-pull-images
|
.PHONY: docs-pull-images
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ click==8.1.7
|
|||||||
colorama==0.4.6
|
colorama==0.4.6
|
||||||
ghp-import==2.1.0
|
ghp-import==2.1.0
|
||||||
importlib_metadata==7.1.0
|
importlib_metadata==7.1.0
|
||||||
Jinja2==3.1.3
|
Jinja2==3.1.6
|
||||||
Markdown==3.3.6
|
Markdown==3.3.6
|
||||||
MarkupSafe==2.1.5
|
MarkupSafe==2.1.5
|
||||||
mergedeep==1.3.4
|
mergedeep==1.3.4
|
||||||
@@ -21,4 +21,4 @@ PyYAML==6.0.1
|
|||||||
pyyaml_env_tag==0.1
|
pyyaml_env_tag==0.1
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
watchdog==4.0.0
|
watchdog==4.0.0
|
||||||
zipp==3.18.1
|
zipp==3.19.1
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ require (
|
|||||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||||
github.com/containerd/containerd v1.7.23 // indirect
|
github.com/containerd/containerd v1.7.29 // indirect
|
||||||
github.com/containerd/errdefs v1.0.0 // indirect
|
github.com/containerd/errdefs v1.0.0 // indirect
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||||
github.com/containerd/log v0.1.0 // indirect
|
github.com/containerd/log v0.1.0 // indirect
|
||||||
|
|||||||
@@ -297,8 +297,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ=
|
github.com/containerd/containerd v1.7.29 h1:90fWABQsaN9mJhGkoVnuzEY+o1XDPbg9BTC9QTAHnuE=
|
||||||
github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
|
github.com/containerd/containerd v1.7.29/go.mod h1:azUkWcOvHrWvaiUjSQH0fjzuHIwSPg1WL5PshGP4Szs=
|
||||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||||
|
|||||||
@@ -413,13 +413,13 @@ func TestPrometheusMetricRemoval(t *testing.T) {
|
|||||||
th.WithRouter("foo@providerName", th.WithServiceName("bar")),
|
th.WithRouter("foo@providerName", th.WithServiceName("bar")),
|
||||||
th.WithRouter("router2", th.WithServiceName("bar@providerName")),
|
th.WithRouter("router2", th.WithServiceName("bar@providerName")),
|
||||||
),
|
),
|
||||||
th.WithLoadBalancerServices(
|
th.WithServices(
|
||||||
th.WithService("bar@providerName", th.WithServers(
|
th.WithService("bar@providerName", th.WithServiceServersLoadBalancer(th.WithServers(
|
||||||
th.WithServer("http://localhost:9000"),
|
th.WithServer("http://localhost:9000"),
|
||||||
th.WithServer("http://localhost:9999"),
|
th.WithServer("http://localhost:9999"),
|
||||||
th.WithServer("http://localhost:9998"),
|
th.WithServer("http://localhost:9998"),
|
||||||
)),
|
))),
|
||||||
th.WithService("service1", th.WithServers(th.WithServer("http://localhost:9000"))),
|
th.WithService("service1", th.WithServiceServersLoadBalancer(th.WithServers(th.WithServer("http://localhost:9000")))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -429,8 +429,8 @@ func TestPrometheusMetricRemoval(t *testing.T) {
|
|||||||
th.WithRouters(
|
th.WithRouters(
|
||||||
th.WithRouter("foo@providerName", th.WithServiceName("bar")),
|
th.WithRouter("foo@providerName", th.WithServiceName("bar")),
|
||||||
),
|
),
|
||||||
th.WithLoadBalancerServices(
|
th.WithServices(
|
||||||
th.WithService("bar@providerName", th.WithServers(th.WithServer("http://localhost:9000"))),
|
th.WithService("bar@providerName", th.WithServiceServersLoadBalancer(th.WithServers(th.WithServer("http://localhost:9000")))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -500,8 +500,8 @@ func TestPrometheusMetricRemoveEndpointForRecoveredService(t *testing.T) {
|
|||||||
|
|
||||||
conf1 := dynamic.Configuration{
|
conf1 := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithLoadBalancerServices(
|
th.WithServices(
|
||||||
th.WithService("service1", th.WithServers(th.WithServer("http://localhost:9000"))),
|
th.WithService("service1", th.WithServiceServersLoadBalancer(th.WithServers(th.WithServer("http://localhost:9000")))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -512,8 +512,8 @@ func TestPrometheusMetricRemoveEndpointForRecoveredService(t *testing.T) {
|
|||||||
|
|
||||||
conf3 := dynamic.Configuration{
|
conf3 := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithLoadBalancerServices(
|
th.WithServices(
|
||||||
th.WithService("service1", th.WithServers(th.WithServer("http://localhost:9001"))),
|
th.WithService("service1", th.WithServiceServersLoadBalancer(th.WithServers(th.WithServer("http://localhost:9001")))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@@ -539,8 +539,8 @@ func TestPrometheusRemovedMetricsReset(t *testing.T) {
|
|||||||
|
|
||||||
conf1 := dynamic.Configuration{
|
conf1 := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithLoadBalancerServices(th.WithService("service",
|
th.WithServices(
|
||||||
th.WithServers(th.WithServer("http://localhost:9000"))),
|
th.WithService("service", th.WithServiceServersLoadBalancer(th.WithServers(th.WithServer("http://localhost:9000")))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func TestNewConfigurationWatcher(t *testing.T) {
|
|||||||
th.WithServiceName("scv"),
|
th.WithServiceName("scv"),
|
||||||
th.WithObservability())),
|
th.WithObservability())),
|
||||||
th.WithMiddlewares(),
|
th.WithMiddlewares(),
|
||||||
th.WithLoadBalancerServices(),
|
th.WithServices(),
|
||||||
),
|
),
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
Routers: map[string]*dynamic.TCPRouter{},
|
Routers: map[string]*dynamic.TCPRouter{},
|
||||||
@@ -126,7 +126,9 @@ func TestWaitForRequiredProvider(t *testing.T) {
|
|||||||
config := &dynamic.Configuration{
|
config := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,14 +172,18 @@ func TestIgnoreTransientConfiguration(t *testing.T) {
|
|||||||
config := &dynamic.Configuration{
|
config := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedConfig := dynamic.Configuration{
|
expectedConfig := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar@mock")),
|
th.WithServices(
|
||||||
|
th.WithService("bar@mock", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
th.WithMiddlewares(),
|
th.WithMiddlewares(),
|
||||||
),
|
),
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
@@ -202,7 +208,9 @@ func TestIgnoreTransientConfiguration(t *testing.T) {
|
|||||||
expectedConfig3 := dynamic.Configuration{
|
expectedConfig3 := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar-config3@mock")),
|
th.WithServices(
|
||||||
|
th.WithService("bar-config3@mock", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
th.WithMiddlewares(),
|
th.WithMiddlewares(),
|
||||||
),
|
),
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
@@ -227,14 +235,18 @@ func TestIgnoreTransientConfiguration(t *testing.T) {
|
|||||||
config2 := &dynamic.Configuration{
|
config2 := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("baz", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("baz", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("toto")),
|
th.WithServices(
|
||||||
|
th.WithService("toto", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
config3 := &dynamic.Configuration{
|
config3 := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar-config3")),
|
th.WithServices(
|
||||||
|
th.WithService("bar-config3", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
watcher := NewConfigurationWatcher(routinesPool, &mockProvider{}, []string{}, "")
|
watcher := NewConfigurationWatcher(routinesPool, &mockProvider{}, []string{}, "")
|
||||||
@@ -318,7 +330,9 @@ func TestListenProvidersThrottleProviderConfigReload(t *testing.T) {
|
|||||||
Configuration: &dynamic.Configuration{
|
Configuration: &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo"+strconv.Itoa(i), th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo"+strconv.Itoa(i), th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -378,7 +392,9 @@ func TestListenProvidersSkipsSameConfigurationForProvider(t *testing.T) {
|
|||||||
Configuration: &dynamic.Configuration{
|
Configuration: &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -410,14 +426,18 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
|
|||||||
configuration := &dynamic.Configuration{
|
configuration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
transientConfiguration := &dynamic.Configuration{
|
transientConfiguration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("bad", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("bad", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bad")),
|
th.WithServices(
|
||||||
|
th.WithService("bad", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,7 +469,9 @@ func TestListenProvidersDoesNotSkipFlappingConfiguration(t *testing.T) {
|
|||||||
expected := dynamic.Configuration{
|
expected := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar@mock")),
|
th.WithServices(
|
||||||
|
th.WithService("bar@mock", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
th.WithMiddlewares(),
|
th.WithMiddlewares(),
|
||||||
),
|
),
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
@@ -480,14 +502,18 @@ func TestListenProvidersIgnoreSameConfig(t *testing.T) {
|
|||||||
configuration := &dynamic.Configuration{
|
configuration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
transientConfiguration := &dynamic.Configuration{
|
transientConfiguration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("bad", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("bad", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bad")),
|
th.WithServices(
|
||||||
|
th.WithService("bad", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +566,9 @@ func TestListenProvidersIgnoreSameConfig(t *testing.T) {
|
|||||||
expected := dynamic.Configuration{
|
expected := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
th.WithRouters(th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar@mock")),
|
th.WithServices(
|
||||||
|
th.WithService("bar@mock", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
th.WithMiddlewares(),
|
th.WithMiddlewares(),
|
||||||
),
|
),
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
@@ -581,7 +609,9 @@ func TestApplyConfigUnderStress(t *testing.T) {
|
|||||||
case watcher.allProvidersConfigs <- dynamic.Message{ProviderName: "mock", Configuration: &dynamic.Configuration{
|
case watcher.allProvidersConfigs <- dynamic.Message{ProviderName: "mock", Configuration: &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo"+strconv.Itoa(i), th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo"+strconv.Itoa(i), th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}}:
|
}}:
|
||||||
}
|
}
|
||||||
@@ -616,28 +646,36 @@ func TestListenProvidersIgnoreIntermediateConfigs(t *testing.T) {
|
|||||||
configuration := &dynamic.Configuration{
|
configuration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
transientConfiguration := &dynamic.Configuration{
|
transientConfiguration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("bad", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("bad", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bad")),
|
th.WithServices(
|
||||||
|
th.WithService("bad", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
transientConfiguration2 := &dynamic.Configuration{
|
transientConfiguration2 := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("bad2", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("bad2", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bad2")),
|
th.WithServices(
|
||||||
|
th.WithService("bad2", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
finalConfiguration := &dynamic.Configuration{
|
finalConfiguration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("final", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("final", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("final")),
|
th.WithServices(
|
||||||
|
th.WithService("final", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,7 +714,9 @@ func TestListenProvidersIgnoreIntermediateConfigs(t *testing.T) {
|
|||||||
expected := dynamic.Configuration{
|
expected := dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("final@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
th.WithRouters(th.WithRouter("final@mock", th.WithEntryPoints("ep"), th.WithObservability())),
|
||||||
th.WithLoadBalancerServices(th.WithService("final@mock")),
|
th.WithServices(
|
||||||
|
th.WithService("final@mock", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
th.WithMiddlewares(),
|
th.WithMiddlewares(),
|
||||||
),
|
),
|
||||||
TCP: &dynamic.TCPConfiguration{
|
TCP: &dynamic.TCPConfiguration{
|
||||||
@@ -709,7 +749,9 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
|
|||||||
configuration := &dynamic.Configuration{
|
configuration := &dynamic.Configuration{
|
||||||
HTTP: th.BuildConfiguration(
|
HTTP: th.BuildConfiguration(
|
||||||
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
th.WithRouters(th.WithRouter("foo", th.WithEntryPoints("ep"))),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,9 +784,9 @@ func TestListenProvidersPublishesConfigForEachProvider(t *testing.T) {
|
|||||||
th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability()),
|
th.WithRouter("foo@mock", th.WithEntryPoints("ep"), th.WithObservability()),
|
||||||
th.WithRouter("foo@mock2", th.WithEntryPoints("ep"), th.WithObservability()),
|
th.WithRouter("foo@mock2", th.WithEntryPoints("ep"), th.WithObservability()),
|
||||||
),
|
),
|
||||||
th.WithLoadBalancerServices(
|
th.WithServices(
|
||||||
th.WithService("bar@mock"),
|
th.WithService("bar@mock", th.WithServiceServersLoadBalancer()),
|
||||||
th.WithService("bar@mock2"),
|
th.WithService("bar@mock2", th.WithServiceServersLoadBalancer()),
|
||||||
),
|
),
|
||||||
th.WithMiddlewares(),
|
th.WithMiddlewares(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"slices"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containous/alice"
|
"github.com/containous/alice"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@@ -38,12 +36,7 @@ import (
|
|||||||
"github.com/traefik/traefik/v3/pkg/middlewares/stripprefix"
|
"github.com/traefik/traefik/v3/pkg/middlewares/stripprefix"
|
||||||
"github.com/traefik/traefik/v3/pkg/middlewares/stripprefixregex"
|
"github.com/traefik/traefik/v3/pkg/middlewares/stripprefixregex"
|
||||||
"github.com/traefik/traefik/v3/pkg/server/provider"
|
"github.com/traefik/traefik/v3/pkg/server/provider"
|
||||||
)
|
"github.com/traefik/traefik/v3/pkg/server/recursion"
|
||||||
|
|
||||||
type middlewareStackType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
middlewareStackKey middlewareStackType = iota
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Builder the middleware builder.
|
// Builder the middleware builder.
|
||||||
@@ -75,7 +68,7 @@ func (b *Builder) BuildChain(ctx context.Context, middlewares []string) *alice.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if constructorContext, err = checkRecursion(constructorContext, middlewareName); err != nil {
|
if constructorContext, err = recursion.CheckRecursion(constructorContext, "middleware", middlewareName); err != nil {
|
||||||
b.configs[middlewareName].AddError(err, true)
|
b.configs[middlewareName].AddError(err, true)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -98,17 +91,6 @@ func (b *Builder) BuildChain(ctx context.Context, middlewares []string) *alice.C
|
|||||||
return &chain
|
return &chain
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkRecursion(ctx context.Context, middlewareName string) (context.Context, error) {
|
|
||||||
currentStack, ok := ctx.Value(middlewareStackKey).([]string)
|
|
||||||
if !ok {
|
|
||||||
currentStack = []string{}
|
|
||||||
}
|
|
||||||
if slices.Contains(currentStack, middlewareName) {
|
|
||||||
return ctx, fmt.Errorf("could not instantiate middleware %s: recursion detected in %s", middlewareName, strings.Join(append(currentStack, middlewareName), "->"))
|
|
||||||
}
|
|
||||||
return context.WithValue(ctx, middlewareStackKey, append(currentStack, middlewareName)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// it is the responsibility of the caller to make sure that b.configs[middlewareName].Middleware exists.
|
// it is the responsibility of the caller to make sure that b.configs[middlewareName].Middleware exists.
|
||||||
func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (alice.Constructor, error) {
|
func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (alice.Constructor, error) {
|
||||||
config := b.configs[middlewareName]
|
config := b.configs[middlewareName]
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ func TestBuilder_BuildChainWithContext(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedError: errors.New("could not instantiate middleware m1: recursion detected in m1->m2->m3->m1"),
|
expectedError: errors.New("could not instantiate middleware m1: recursion detected in middleware:m1->middleware:m2->middleware:m3->middleware:m1"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Detects recursion in Middleware chain",
|
desc: "Detects recursion in Middleware chain",
|
||||||
@@ -197,9 +197,10 @@ func TestBuilder_BuildChainWithContext(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedError: errors.New("could not instantiate middleware m1@provider: recursion detected in m1@provider->m2@provider2->m3@provider->m1@provider"),
|
expectedError: errors.New("could not instantiate middleware m1@provider: recursion detected in middleware:m1@provider->middleware:m2@provider2->middleware:m3@provider->middleware:m1@provider"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
desc: "Detects recursion in Middleware chain",
|
||||||
buildChain: []string{"ok", "m0"},
|
buildChain: []string{"ok", "m0"},
|
||||||
configuration: map[string]*dynamic.Middleware{
|
configuration: map[string]*dynamic.Middleware{
|
||||||
"ok": {
|
"ok": {
|
||||||
@@ -211,7 +212,7 @@ func TestBuilder_BuildChainWithContext(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedError: errors.New("could not instantiate middleware m0: recursion detected in m0->m0"),
|
expectedError: errors.New("could not instantiate middleware m0: recursion detected in middleware:m0->middleware:m0"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "Detects MiddlewareChain that references a Chain that references a Chain with a missing middleware",
|
desc: "Detects MiddlewareChain that references a Chain that references a Chain with a missing middleware",
|
||||||
@@ -238,7 +239,7 @@ func TestBuilder_BuildChainWithContext(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedError: errors.New("could not instantiate middleware m2: recursion detected in m0->m1->m2->m3->m2"),
|
expectedError: errors.New("could not instantiate middleware m2: recursion detected in middleware:m0->middleware:m1->middleware:m2->middleware:m3->middleware:m2"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "--",
|
desc: "--",
|
||||||
@@ -250,7 +251,7 @@ func TestBuilder_BuildChainWithContext(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedError: errors.New("could not instantiate middleware m0: recursion detected in m0->m0"),
|
expectedError: errors.New("could not instantiate middleware m0: recursion detected in middleware:m0->middleware:m0"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package recursion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type stackType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
stackKey stackType = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
func CheckRecursion(ctx context.Context, itemType, itemName string) (context.Context, error) {
|
||||||
|
currentStack, ok := ctx.Value(stackKey).([]string)
|
||||||
|
if !ok {
|
||||||
|
currentStack = []string{}
|
||||||
|
}
|
||||||
|
name := itemType + ":" + itemName
|
||||||
|
if slices.Contains(currentStack, name) {
|
||||||
|
return ctx, fmt.Errorf("could not instantiate %s %s: recursion detected in %s", itemType, itemName, strings.Join(append(currentStack, name), "->"))
|
||||||
|
}
|
||||||
|
return context.WithValue(ctx, stackKey, append(currentStack, name)), nil
|
||||||
|
}
|
||||||
@@ -46,8 +46,8 @@ func TestReuseService(t *testing.T) {
|
|||||||
th.WithMiddlewares(th.WithMiddleware("basicauth",
|
th.WithMiddlewares(th.WithMiddleware("basicauth",
|
||||||
th.WithBasicAuth(&dynamic.BasicAuth{Users: []string{"foo:bar"}}),
|
th.WithBasicAuth(&dynamic.BasicAuth{Users: []string{"foo:bar"}}),
|
||||||
)),
|
)),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar",
|
th.WithServices(
|
||||||
th.WithServers(th.WithServer(testServer.URL))),
|
th.WithService("bar", th.WithServiceServersLoadBalancer(th.WithServers(th.WithServer(testServer.URL)))),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -98,8 +98,8 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||||||
th.WithServiceName("bar"),
|
th.WithServiceName("bar"),
|
||||||
th.WithRule(routeRule)),
|
th.WithRule(routeRule)),
|
||||||
),
|
),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar",
|
th.WithServices(
|
||||||
th.WithServers(th.WithServer(testServerURL))),
|
th.WithService("bar", th.WithServiceServersLoadBalancer(th.WithServers(th.WithServer(testServerURL)))),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -121,7 +121,9 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||||||
th.WithServiceName("bar"),
|
th.WithServiceName("bar"),
|
||||||
th.WithRule(routeRule)),
|
th.WithRule(routeRule)),
|
||||||
),
|
),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
th.WithServices(
|
||||||
|
th.WithService("bar", th.WithServiceServersLoadBalancer()),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
expectedStatusCode: http.StatusServiceUnavailable,
|
expectedStatusCode: http.StatusServiceUnavailable,
|
||||||
@@ -135,27 +137,13 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||||||
th.WithServiceName("bar"),
|
th.WithServiceName("bar"),
|
||||||
th.WithRule(routeRule)),
|
th.WithRule(routeRule)),
|
||||||
),
|
),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar",
|
th.WithServices(
|
||||||
th.WithSticky("test")),
|
th.WithService("bar", th.WithServiceServersLoadBalancer(th.WithSticky("test"))),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
expectedStatusCode: http.StatusServiceUnavailable,
|
expectedStatusCode: http.StatusServiceUnavailable,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
desc: "Empty Backend LB",
|
|
||||||
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
|
||||||
return th.BuildConfiguration(
|
|
||||||
th.WithRouters(th.WithRouter("foo",
|
|
||||||
th.WithEntryPoints("web"),
|
|
||||||
th.WithServiceName("bar"),
|
|
||||||
th.WithRule(routeRule)),
|
|
||||||
),
|
|
||||||
th.WithLoadBalancerServices(th.WithService("bar")),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
expectedStatusCode: http.StatusServiceUnavailable,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
desc: "Empty Backend LB Sticky",
|
desc: "Empty Backend LB Sticky",
|
||||||
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
config: func(testServerURL string) *dynamic.HTTPConfiguration {
|
||||||
@@ -165,8 +153,8 @@ func TestServerResponseEmptyBackend(t *testing.T) {
|
|||||||
th.WithServiceName("bar"),
|
th.WithServiceName("bar"),
|
||||||
th.WithRule(routeRule)),
|
th.WithRule(routeRule)),
|
||||||
),
|
),
|
||||||
th.WithLoadBalancerServices(th.WithService("bar",
|
th.WithServices(
|
||||||
th.WithSticky("test")),
|
th.WithService("bar", th.WithServiceServersLoadBalancer(th.WithSticky("test"))),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -256,6 +244,61 @@ func TestInternalServices(t *testing.T) {
|
|||||||
assert.Equal(t, http.StatusOK, responseRecorderOk.Result().StatusCode, "status code")
|
assert.Equal(t, http.StatusOK, responseRecorderOk.Result().StatusCode, "status code")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecursionService(t *testing.T) {
|
||||||
|
testServer := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
rw.WriteHeader(http.StatusOK)
|
||||||
|
}))
|
||||||
|
defer testServer.Close()
|
||||||
|
|
||||||
|
staticConfig := static.Configuration{
|
||||||
|
EntryPoints: map[string]*static.EntryPoint{
|
||||||
|
"web": {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamicConfigs := th.BuildConfiguration(
|
||||||
|
th.WithRouters(
|
||||||
|
th.WithRouter("foo@provider1",
|
||||||
|
th.WithEntryPoints("web"),
|
||||||
|
th.WithServiceName("bar"),
|
||||||
|
th.WithRule("Path(`/ok`)")),
|
||||||
|
),
|
||||||
|
th.WithMiddlewares(th.WithMiddleware("customerror",
|
||||||
|
th.WithErrorPage(&dynamic.ErrorPage{Service: "bar"}),
|
||||||
|
)),
|
||||||
|
th.WithServices(
|
||||||
|
th.WithService("bar@provider1", th.WithServiceWRR(th.WithWRRServices(th.WithWRRService("foo")))),
|
||||||
|
th.WithService("foo@provider1", th.WithServiceWRR(th.WithWRRServices(th.WithWRRService("bar")))),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
transportManager := service.NewTransportManager(nil)
|
||||||
|
transportManager.Update(map[string]*dynamic.ServersTransport{"default@internal": {}})
|
||||||
|
|
||||||
|
managerFactory := service.NewManagerFactory(staticConfig, nil, nil, transportManager, nil, nil)
|
||||||
|
tlsManager := tls.NewManager(nil)
|
||||||
|
|
||||||
|
dialerManager := tcp.NewDialerManager(nil)
|
||||||
|
dialerManager.Update(map[string]*dynamic.TCPServersTransport{"default@internal": {}})
|
||||||
|
factory, err := NewRouterFactory(staticConfig, managerFactory, tlsManager, nil, nil, dialerManager)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
rtConf := runtime.NewConfig(dynamic.Configuration{HTTP: dynamicConfigs})
|
||||||
|
entryPointsHandlers, _ := factory.CreateRouters(rtConf)
|
||||||
|
|
||||||
|
// Test that the /ok path returns a status 404.
|
||||||
|
responseRecorderOk := &httptest.ResponseRecorder{}
|
||||||
|
requestOk := httptest.NewRequest(http.MethodGet, testServer.URL+"/ok", nil)
|
||||||
|
entryPointsHandlers["web"].GetHTTPHandler().ServeHTTP(responseRecorderOk, requestOk)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusNotFound, responseRecorderOk.Result().StatusCode, "status code")
|
||||||
|
|
||||||
|
require.NotNil(t, rtConf.Routers["foo@provider1"])
|
||||||
|
assert.Contains(t, rtConf.Routers["foo@provider1"].Err, "building HTTP service \"foo\": building HTTP service \"bar\": could not instantiate service bar@provider1: recursion detected in service:bar@provider1->service:foo@provider1->service:bar@provider1")
|
||||||
|
require.NotNil(t, rtConf.Services["bar@provider1"])
|
||||||
|
assert.Contains(t, rtConf.Services["bar@provider1"].Err, "could not instantiate service bar@provider1: recursion detected in service:bar@provider1->service:foo@provider1->service:bar@provider1")
|
||||||
|
}
|
||||||
|
|
||||||
type proxyBuilderMock struct{}
|
type proxyBuilderMock struct{}
|
||||||
|
|
||||||
func (p proxyBuilderMock) Build(_ string, _ *url.URL, _, _ bool, _ time.Duration) (http.Handler, error) {
|
func (p proxyBuilderMock) Build(_ string, _ *url.URL, _, _ bool, _ time.Duration) (http.Handler, error) {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/traefik/traefik/v3/pkg/server/cookie"
|
"github.com/traefik/traefik/v3/pkg/server/cookie"
|
||||||
"github.com/traefik/traefik/v3/pkg/server/middleware"
|
"github.com/traefik/traefik/v3/pkg/server/middleware"
|
||||||
"github.com/traefik/traefik/v3/pkg/server/provider"
|
"github.com/traefik/traefik/v3/pkg/server/provider"
|
||||||
|
"github.com/traefik/traefik/v3/pkg/server/recursion"
|
||||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/failover"
|
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/failover"
|
||||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/hrw"
|
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/hrw"
|
||||||
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/leasttime"
|
"github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/leasttime"
|
||||||
@@ -122,6 +123,12 @@ func (m *Manager) BuildHTTP(rootCtx context.Context, serviceName string) (http.H
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errRecursion error
|
||||||
|
if ctx, errRecursion = recursion.CheckRecursion(ctx, "service", serviceName); errRecursion != nil {
|
||||||
|
conf.AddError(errRecursion, true)
|
||||||
|
return nil, errRecursion
|
||||||
|
}
|
||||||
|
|
||||||
var lb http.Handler
|
var lb http.Handler
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@@ -319,7 +326,7 @@ func (m *Manager) getServiceHandler(ctx context.Context, service dynamic.WRRServ
|
|||||||
|
|
||||||
svcHandler, err := m.BuildHTTP(ctx, service.Name)
|
svcHandler, err := m.BuildHTTP(ctx, service.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("building HTTP service: %w", err)
|
return nil, fmt.Errorf("building HTTP service %q: %w", service.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if service.Headers != nil {
|
if service.Headers != nil {
|
||||||
|
|||||||
+61
-11
@@ -66,32 +66,75 @@ func WithObservability() func(*dynamic.Router) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithLoadBalancerServices is a helper to create a configuration.
|
// WithServices is a helper to create a configuration.
|
||||||
func WithLoadBalancerServices(opts ...func(service *dynamic.ServersLoadBalancer) string) func(*dynamic.HTTPConfiguration) {
|
func WithServices(opts ...func(service *dynamic.Service) string) func(*dynamic.HTTPConfiguration) {
|
||||||
return func(c *dynamic.HTTPConfiguration) {
|
return func(c *dynamic.HTTPConfiguration) {
|
||||||
c.Services = make(map[string]*dynamic.Service)
|
c.Services = make(map[string]*dynamic.Service)
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
b := &dynamic.ServersLoadBalancer{}
|
b := &dynamic.Service{}
|
||||||
b.SetDefaults()
|
|
||||||
|
|
||||||
name := opt(b)
|
name := opt(b)
|
||||||
c.Services[name] = &dynamic.Service{
|
c.Services[name] = b
|
||||||
LoadBalancer: b,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithService is a helper to create a configuration.
|
// WithService is a helper to create a configuration.
|
||||||
func WithService(name string, opts ...func(*dynamic.ServersLoadBalancer)) func(*dynamic.ServersLoadBalancer) string {
|
func WithService(name string, opts ...func(*dynamic.Service)) func(*dynamic.Service) string {
|
||||||
return func(r *dynamic.ServersLoadBalancer) string {
|
return func(s *dynamic.Service) string {
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(r)
|
opt(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WithServiceServersLoadBalancer(opts ...func(*dynamic.ServersLoadBalancer)) func(*dynamic.Service) {
|
||||||
|
return func(s *dynamic.Service) {
|
||||||
|
b := &dynamic.ServersLoadBalancer{}
|
||||||
|
b.SetDefaults()
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.LoadBalancer = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithServiceWRR(opts ...func(*dynamic.WeightedRoundRobin)) func(*dynamic.Service) {
|
||||||
|
return func(s *dynamic.Service) {
|
||||||
|
b := &dynamic.WeightedRoundRobin{}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Weighted = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithWRRServices is a helper to create a configuration.
|
||||||
|
func WithWRRServices(opts ...func(*dynamic.WRRService)) func(*dynamic.WeightedRoundRobin) {
|
||||||
|
return func(b *dynamic.WeightedRoundRobin) {
|
||||||
|
for _, opt := range opts {
|
||||||
|
service := dynamic.WRRService{}
|
||||||
|
opt(&service)
|
||||||
|
b.Services = append(b.Services, service)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithWRRService is a helper to create a configuration.
|
||||||
|
func WithWRRService(name string, opts ...func(*dynamic.WRRService)) func(*dynamic.WRRService) {
|
||||||
|
return func(s *dynamic.WRRService) {
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(s)
|
||||||
|
}
|
||||||
|
s.Name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithMiddlewares is a helper to create a configuration.
|
// WithMiddlewares is a helper to create a configuration.
|
||||||
func WithMiddlewares(opts ...func(*dynamic.Middleware) string) func(*dynamic.HTTPConfiguration) {
|
func WithMiddlewares(opts ...func(*dynamic.Middleware) string) func(*dynamic.HTTPConfiguration) {
|
||||||
return func(c *dynamic.HTTPConfiguration) {
|
return func(c *dynamic.HTTPConfiguration) {
|
||||||
@@ -121,6 +164,13 @@ func WithBasicAuth(auth *dynamic.BasicAuth) func(*dynamic.Middleware) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithErrorPage is a helper to create a configuration.
|
||||||
|
func WithErrorPage(errorPage *dynamic.ErrorPage) func(*dynamic.Middleware) {
|
||||||
|
return func(r *dynamic.Middleware) {
|
||||||
|
r.Errors = errorPage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithEntryPoints is a helper to create a configuration.
|
// WithEntryPoints is a helper to create a configuration.
|
||||||
func WithEntryPoints(eps ...string) func(*dynamic.Router) {
|
func WithEntryPoints(eps ...string) func(*dynamic.Router) {
|
||||||
return func(f *dynamic.Router) {
|
return func(f *dynamic.Router) {
|
||||||
|
|||||||
Reference in New Issue
Block a user