1
0
Fork 0

Compare commits

...

3 commits

Author SHA1 Message Date
b4ef1baf65
feat: custom label shorthands 2025-06-11 15:25:54 +03:00
c826cc97e6
feat: callbacks 2025-06-11 15:25:54 +03:00
c69246d93e
chore: remove github for local deployments 2025-06-11 15:25:42 +03:00
33 changed files with 2062 additions and 1030 deletions

3
.github/FUNDING.yml vendored
View file

@ -1,3 +0,0 @@
# These are supported funding model platforms
github: traefik

View file

@ -1,77 +0,0 @@
<!-- PLEASE FOLLOW THE ISSUE TEMPLATE TO HELP TRIAGE AND SUPPORT! -->
### Do you want to request a *feature* or report a *bug*?
<!--
DO NOT FILE ISSUES FOR GENERAL SUPPORT QUESTIONS.
The issue tracker is for reporting bugs and feature requests only.
For end-user related support questions, please refer to one of the following:
- the Traefik community forum: https://community.traefik.io/
-->
Bug
<!--
The configurations between 1.X and 2.X are NOT compatible.
Please have a look here https://doc.traefik.io/traefik/getting-started/configuration-overview/.
-->
### What did you do?
<!--
HOW TO WRITE A GOOD BUG REPORT?
- Respect the issue template as much as possible.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use Markdown syntax https://help.github.com/articles/github-flavored-markdown
-->
### What did you expect to see?
### What did you see instead?
### Output of `traefik version`: (_What version of Traefik are you using?_)
<!--
`latest` is not considered as a valid version.
For the Traefik Docker image:
docker run [IMAGE] version
ex: docker run traefik version
-->
```
(paste your output here)
```
### What is your environment & configuration (arguments, toml, provider, platform, ...)?
```toml
# (paste your configuration here)
```
<!--
Add more configuration information here.
-->
### If applicable, please paste the log output in DEBUG level (`--log.level=DEBUG` switch)
```
(paste your output here)
```

View file

@ -1,82 +0,0 @@
name: Bug Report (Traefik)
description: Create a report to help us improve.
body:
- type: checkboxes
id: terms
attributes:
label: Welcome!
description: |
The issue tracker is for reporting bugs and feature requests only.
For end-user related support questions, please use the [Traefik community forum](https://community.traefik.io/).
All new/updated issues are triaged regularly by the maintainers.
All issues closed by a bot are subsequently double-checked by the maintainers.
DO NOT FILE ISSUES FOR GENERAL SUPPORT QUESTIONS.
options:
- label: Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any.
required: true
- label: Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any.
required: true
- type: textarea
attributes:
label: What did you do?
description: |
How to write a good bug report?
- Respect the issue template as much as possible.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
placeholder: What did you do?
validations:
required: true
- type: textarea
attributes:
label: What did you see instead?
placeholder: What did you see instead?
validations:
required: true
- type: textarea
attributes:
label: What version of Traefik are you using?
description: |
`latest` is not considered as a valid version.
Output of `traefik version`.
For the Traefik Docker image (`docker run [IMAGE] version`), example:
```console
$ docker run traefik version
```
placeholder: Paste your output here.
validations:
required: true
- type: textarea
attributes:
label: What is your environment & configuration?
description: arguments, toml, provider, platform, ...
placeholder: Add information here.
value: |
```yaml
# (paste your configuration here)
```
Add more configuration information here.
validations:
required: true
- type: textarea
attributes:
label: If applicable, please paste the log output in DEBUG level
description: "`--log.level=DEBUG` switch."
placeholder: Paste your output here.
validations:
required: false

View file

@ -1,8 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Traefik Community Support
url: https://community.traefik.io/
about: If you have a question, or are looking for advice, please post on our Discuss forum! The community loves to chime in to help. Happy Coding!
- name: Traefik Helm Chart Issues
url: https://github.com/traefik/traefik-helm-chart
about: Are you submitting an issue or feature enhancement for the Traefik helm chart? Please post in the traefik-helm-chart GitHub Issues.

View file

@ -1,33 +0,0 @@
name: Feature Request (Traefik)
description: Suggest an idea for this project.
body:
- type: checkboxes
id: terms
attributes:
label: Welcome!
description: |
The issue tracker is for reporting bugs and feature requests only. For end-user related support questions, please refer to one of the following:
- the Traefik community forum: https://community.traefik.io/
DO NOT FILE ISSUES FOR GENERAL SUPPORT QUESTIONS.
options:
- label: Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any.
required: true
- label: Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any.
required: true
- type: textarea
attributes:
label: What did you expect to see?
description: |
How to write a good issue?
- Respect the issue template as much as possible.
- The title should be short and descriptive.
- Explain the conditions which led you to report this issue: the context.
- The context should lead to something, an idea or a problem that youre facing.
- Remain clear and concise.
- Format your messages to help the reader focus on what matters and understand the structure of your message, use [Markdown syntax](https://help.github.com/articles/github-flavored-markdown)
placeholder: What did you expect to see?
validations:
required: true

View file

@ -1,37 +0,0 @@
<!--
PLEASE READ THIS MESSAGE.
Documentation fixes or enhancements:
- for Traefik v2: use branch v2.11
- for Traefik v3: use branch v3.4
Bug fixes:
- for Traefik v2: use branch v2.11
- for Traefik v3: use branch v3.4
Enhancements:
- for Traefik v2: we only accept bug fixes
- for Traefik v3: use branch master
HOW TO WRITE A GOOD PULL REQUEST? https://doc.traefik.io/traefik/contributing/submitting-pull-requests/
-->
### What does this PR do?
<!-- A brief description of the change being made with this pull request. -->
### Motivation
<!-- What inspired you to submit this pull request? -->
### More
- [ ] Added/updated tests
- [ ] Added/updated documentation
### Additional Notes
<!-- Anything else we should know when reviewing? -->

View file

@ -1,7 +0,0 @@
### What does this PR do?
Merge v{{.Version}} into master
### Motivation
Be sync.

View file

@ -1,7 +0,0 @@
### What does this PR do?
Prepare release v{{.Version}}.
### Motivation
Create a new release.

View file

@ -1,81 +0,0 @@
name: Build Binaries
on:
pull_request:
branches:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'script/gcg/**'
env:
GO_VERSION: '1.23'
CGO_ENABLED: 0
jobs:
build-webui:
uses: ./.github/workflows/template-webui.yaml
build:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ darwin, freebsd, linux, openbsd, windows ]
arch: [ amd64, arm64 ]
include:
- os: freebsd
arch: 386
- os: linux
arch: 386
- os: linux
arch: arm
goarm: 6
- os: linux
arch: arm
goarm: 7
- os: linux
arch: ppc64le
- os: linux
arch: riscv64
- os: linux
arch: s390x
- os: openbsd
arch: 386
- os: windows
arch: 386
needs:
- build-webui
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
env:
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Build
env:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
GOARM: ${{ matrix.goarm }}
run: make binary

View file

@ -1,25 +0,0 @@
name: Check Documentation
on:
pull_request:
branches:
- '*'
jobs:
docs:
name: Check, verify and build documentation
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check documentation
run: make docs-pull-images docs
env:
# These variables are not passed to workflows that are triggered by a pull request from a fork.
DOCS_VERIFY_SKIP: ${{ vars.DOCS_VERIFY_SKIP }}
DOCS_LINT_SKIP: ${{ vars.DOCS_LINT_SKIP }}

View file

@ -1,70 +0,0 @@
name: "CodeQL"
on:
push:
branches:
- master
- v*
schedule:
- cron: '11 22 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: setup go
uses: actions/setup-go@v5
if: ${{ matrix.language == 'go' }}
with:
go-version-file: 'go.mod'
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# 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)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# 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
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View file

@ -1,52 +0,0 @@
name: Build and Publish Documentation
on:
push:
branches:
- master
- v*
env:
STRUCTOR_VERSION: v1.13.2
MIXTUS_VERSION: v0.4.1
jobs:
docs:
name: Doc Process
runs-on: ubuntu-latest
if: github.repository == 'traefik/traefik'
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Install Structor ${{ env.STRUCTOR_VERSION }}
run: curl -sSfL https://raw.githubusercontent.com/traefik/structor/master/godownloader.sh | sh -s -- -b $HOME/bin ${STRUCTOR_VERSION}
- name: Install Seo-doc
run: curl -sSfL https://raw.githubusercontent.com/traefik/seo-doc/master/godownloader.sh | sh -s -- -b "${HOME}/bin"
- name: Install Mixtus ${{ env.MIXTUS_VERSION }}
run: curl -sSfL https://raw.githubusercontent.com/traefik/mixtus/master/godownloader.sh | sh -s -- -b $HOME/bin ${MIXTUS_VERSION}
- name: Build documentation
run: $HOME/bin/structor -o traefik -r traefik --dockerfile-url="https://raw.githubusercontent.com/traefik/traefik/v1.7/docs.Dockerfile" --menu.js-url="https://raw.githubusercontent.com/traefik/structor/master/traefik-menu.js.gotmpl" --rqts-url="https://raw.githubusercontent.com/traefik/structor/master/requirements-override.txt" --force-edit-url --exp-branch=master --debug
env:
STRUCTOR_LATEST_TAG: ${{ vars.STRUCTOR_LATEST_TAG }}
- name: Apply seo
run: $HOME/bin/seo -path=./site -product=traefik
- name: Publish documentation
run: $HOME/bin/mixtus --dst-doc-path="./traefik" --dst-owner=traefik --dst-repo-name=doc --git-user-email="30906710+traefiker@users.noreply.github.com" --git-user-name=traefiker --src-doc-path="./site" --src-owner=traefik --src-repo-name=traefik
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN_REPO }}

View file

@ -1,70 +0,0 @@
name: Build experimental image on branch
on:
push:
branches:
- master
- v*
env:
GO_VERSION: '1.23'
CGO_ENABLED: 0
jobs:
build-webui:
if: github.repository == 'traefik/traefik'
uses: ./.github/workflows/template-webui.yaml
experimental:
if: github.repository == 'traefik/traefik'
name: Build experimental image on branch
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
env:
ImageOS: ${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.goarm }}
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Build
run: make generate binary
- name: Branch name
run: echo ${GITHUB_REF##*/}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Build docker experimental image
env:
DOCKER_BUILDX_ARGS: "--push"
run: |
make multi-arch-image-experimental-${GITHUB_REF##*/}

View file

@ -1,138 +0,0 @@
name: Release
on:
push:
tags:
- 'v*.*.*'
env:
GO_VERSION: '1.23'
CGO_ENABLED: 0
VERSION: ${{ github.ref_name }}
TRAEFIKER_EMAIL: "traefiker@traefik.io"
CODENAME: chaource
jobs:
build-webui:
if: github.ref_type == 'tag' && github.repository == 'traefik/traefik'
uses: ./.github/workflows/template-webui.yaml
build:
if: github.ref_type == 'tag' && github.repository == 'traefik/traefik'
runs-on: ubuntu-latest
strategy:
matrix:
os: [ linux-amd64, linux-386, linux-arm, linux-arm64, linux-ppc64le, linux-s390x, linux-riscv64, darwin, windows-amd64, windows-arm64, windows-386, freebsd, openbsd ]
needs:
- build-webui
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
env:
# Ensure cache consistency on Linux, see https://github.com/actions/setup-go/pull/383
ImageOS: ${{ matrix.os }}
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Go generate
run: go generate
- name: Generate goreleaser file
run: |
GORELEASER_CONFIG_FILE_PATH=$(go run ./internal/release "${{ matrix.os }}")
echo "GORELEASER_CONFIG_FILE_PATH=$GORELEASER_CONFIG_FILE_PATH" >> $GITHUB_ENV
- name: Build with goreleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
# 'latest', 'nightly', or a semver
version: '~> v2'
args: release --clean --timeout="90m" --config "${{ env.GORELEASER_CONFIG_FILE_PATH }}"
- name: Artifact binaries
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.os }}-binaries
path: |
dist/**/*_checksums.txt
dist/**/*.tar.gz
dist/**/*.zip
retention-days: 1
release:
if: github.ref_type == 'tag' && github.repository == 'traefik/traefik'
runs-on: ubuntu-latest
needs:
- build
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Artifact webui
uses: actions/download-artifact@v4
with:
name: webui.tar.gz
- name: Untar webui
run: |
tar xvf webui.tar.gz
rm webui.tar.gz
- name: Retrieve the secret and decode it to a file
env:
TRAEFIKER_RSA: ${{ secrets.TRAEFIKER_RSA }}
run: |
mkdir -p ~/.ssh
echo "${TRAEFIKER_RSA}" | base64 --decode > ~/.ssh/traefiker_rsa
- name: Download All Artifacts
uses: actions/download-artifact@v4
with:
path: dist/
pattern: "*-binaries"
merge-multiple: true
- name: Publish Release
env:
GH_TOKEN: ${{ github.token }}
run: |
cat dist/**/*_checksums.txt >> "dist/traefik_${VERSION}_checksums.txt"
rm dist/**/*_checksums.txt
tar cfz "dist/traefik-${VERSION}.src.tar.gz" \
--exclude-vcs \
--exclude .idea \
--exclude .travis \
--exclude .semaphoreci \
--exclude .github \
--exclude dist .
chown -R "$(id -u)":"$(id -g)" dist/
gh release create ${VERSION} ./dist/**/traefik*.{zip,tar.gz} ./dist/traefik*.{tar.gz,txt} --repo traefik/traefik --title ${VERSION} --notes ${VERSION}
./script/deploy.sh

View file

@ -1,26 +0,0 @@
name: Sync Docker Images
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *" # Run every day
jobs:
sync:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
if: github.repository == 'traefik/traefik'
steps:
- uses: actions/checkout@v4
- uses: imjasonh/setup-crane@v0.4
- name: Sync
run: |
EXCLUDED_TAGS="1.7.9-alpine v1.0.0-beta.392 v1.0.0-beta.404 v1.0.0-beta.704 v1.0.0-rc1 v1.7.9-alpine"
EXCLUDED_REGEX=$(echo $EXCLUDED_TAGS | sed 's/ /|/g')
diff <(crane ls traefik) <(crane ls ghcr.io/traefik/traefik) | grep '^<' | awk '{print $2}' | while read -r tag; do [[ "$tag" =~ ^($EXCLUDED_REGEX)$ ]] || (echo "Processing image: traefik:$tag"; crane cp "traefik:$tag" "ghcr.io/traefik/traefik:$tag"); done
crane cp traefik:latest ghcr.io/traefik/traefik:latest

View file

@ -1,37 +0,0 @@
name: Build Web UI
on:
workflow_call: {}
jobs:
build-webui:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: webui/.nvmrc
cache: yarn
cache-dependency-path: webui/yarn.lock
- name: Build webui
working-directory: ./webui
run: |
yarn install
yarn build
- name: Package webui
run: |
tar czvf webui.tar.gz ./webui/static/
- name: Artifact webui
uses: actions/upload-artifact@v4
with:
name: webui.tar.gz
path: webui.tar.gz
retention-days: 1

View file

@ -1,39 +0,0 @@
name: Test K8s Gateway API conformance
on:
pull_request:
branches:
- '*'
paths:
- '.github/workflows/test-conformance.yaml'
- 'pkg/provider/kubernetes/gateway/**'
- 'integration/fixtures/k8s-conformance/**'
- 'integration/k8s_conformance_test.go'
env:
GO_VERSION: '1.23'
CGO_ENABLED: 0
jobs:
test-conformance:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Avoid generating webui
run: touch webui/static/index.html
- name: K8s Gateway API conformance test and report
run: |
make test-gateway-api-conformance
git diff --exit-code

View file

@ -1,78 +0,0 @@
name: Test Integration
on:
pull_request:
branches:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'script/gcg/**'
env:
GO_VERSION: '1.23'
CGO_ENABLED: 0
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Avoid generating webui
run: touch webui/static/index.html
- name: Build binary
run: make binary
test-integration:
runs-on: ubuntu-latest
needs:
- build
strategy:
fail-fast: true
matrix:
parallel: [12]
index: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Avoid generating webui
run: touch webui/static/index.html
- name: Build binary
run: make binary
- name: Generate go test Slice
id: test_split
uses: hashicorp-forge/go-test-split-action@v2.0.0
with:
packages: ./integration
total: ${{ matrix.parallel }}
index: ${{ matrix.index }}
- name: Run Integration tests
run: |
TESTS=$(echo "${{ steps.test_split.outputs.run}}" | sed 's/\$/\$\$/g')
TESTFLAGS="-run \"${TESTS}\"" make test-integration

View file

@ -1,57 +0,0 @@
name: Test Unit
on:
pull_request:
branches:
- '*'
paths-ignore:
- 'docs/**'
- '**.md'
- 'script/gcg/**'
env:
GO_VERSION: '1.23'
jobs:
test-unit:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Avoid generating webui
run: touch webui/static/index.html
- name: Tests
run: make test-unit
test-ui-unit:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v4
with:
node-version-file: webui/.nvmrc
cache: 'yarn'
cache-dependency-path: webui/yarn.lock
- name: UI unit tests
run: |
yarn --cwd webui install
yarn --cwd webui test:unit:ci

View file

@ -1,87 +0,0 @@
name: Validate
on:
pull_request:
branches:
- '*'
env:
GO_VERSION: '1.23'
GOLANGCI_LINT_VERSION: v2.0.2
MISSPELL_VERSION: v0.6.0
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: "${{ env.GOLANGCI_LINT_VERSION }}"
validate:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Install misspell ${{ env.MISSPELL_VERSION }}
run: curl -sfL https://raw.githubusercontent.com/golangci/misspell/HEAD/install-misspell.sh | sh -s -- -b $(go env GOPATH)/bin ${MISSPELL_VERSION}
- name: Avoid generating webui
run: touch webui/static/index.html
- name: Validate
run: make validate-files
validate-generate:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: go generate
run: |
make generate
git diff --exit-code
- name: go mod tidy
run: |
go mod tidy
git diff --exit-code
- name: make generate-crd
run: |
make generate-crd
git diff --exit-code

View file

@ -5,6 +5,7 @@ RUN apk add --no-cache --no-progress ca-certificates tzdata
ARG TARGETPLATFORM
COPY ./dist/$TARGETPLATFORM/traefik /
COPY ./traefik.yml /etc/traefik/traefik.yml
EXPOSE 80
VOLUME ["/tmp"]

View file

@ -49,6 +49,7 @@ import (
"github.com/traefik/traefik/v3/pkg/tracing"
"github.com/traefik/traefik/v3/pkg/types"
"github.com/traefik/traefik/v3/pkg/version"
"github.com/traefik/traefik/v3/pkg/updater"
)
func main() {
@ -197,6 +198,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
tsProviders := initTailscaleProviders(staticConfiguration, providerAggregator)
updaterProvider := updater.New(staticConfiguration);
// Observability
metricRegistries := registerMetricClients(staticConfiguration.Metrics)
@ -386,6 +389,9 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
}
})
// Updater
watcher.AddListener(updaterProvider.HandleConfigUpdate)
return server.NewServer(routinesPool, serverEntryPointsTCP, serverEntryPointsUDP, watcher, observabilityMgr), nil
}

View file

@ -369,6 +369,9 @@ Periodically check if a new version has been released. (Default: ```true```)
`--global.sendanonymoususage`:
Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```)
`--global.updatercallbacks`:
Callback urls for updater script (example: https://localhost:8080/callback)
`--hostresolver`:
Enable CNAME Flattening. (Default: ```false```)
@ -765,6 +768,18 @@ Expose containers by default. (Default: ```true```)
`--providers.docker.httpclienttimeout`:
Client timeout for HTTP connections. (Default: ```0```)
`--providers.docker.labelmap`:
Label shorthands.
`--providers.docker.labelmap[n].from`:
Shorthand label.
`--providers.docker.labelmap[n].to`:
Full label with templates.
`--providers.docker.labelmap[n].value`:
Optional override; used instead of user input if set.
`--providers.docker.network`:
Default Docker network used.
@ -1164,6 +1179,18 @@ Expose containers by default. (Default: ```true```)
`--providers.swarm.httpclienttimeout`:
Client timeout for HTTP connections. (Default: ```0```)
`--providers.swarm.labelmap`:
Label shorthands.
`--providers.swarm.labelmap[n].from`:
Shorthand label.
`--providers.swarm.labelmap[n].to`:
Full label with templates.
`--providers.swarm.labelmap[n].value`:
Optional override; used instead of user input if set.
`--providers.swarm.network`:
Default Docker network used.

View file

@ -369,6 +369,9 @@ Periodically check if a new version has been released. (Default: ```true```)
`TRAEFIK_GLOBAL_SENDANONYMOUSUSAGE`:
Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```)
`TRAEFIK_GLOBAL_UPDATERCALLBACKS`:
Callback urls for updater script (example: https://localhost:8080/callback)
`TRAEFIK_HOSTRESOLVER`:
Enable CNAME Flattening. (Default: ```false```)
@ -765,6 +768,18 @@ Expose containers by default. (Default: ```true```)
`TRAEFIK_PROVIDERS_DOCKER_HTTPCLIENTTIMEOUT`:
Client timeout for HTTP connections. (Default: ```0```)
`TRAEFIK_PROVIDERS_DOCKER_LABELMAP`:
Label shorthands.
`TRAEFIK_PROVIDERS_DOCKER_LABELMAP_n_FROM`:
Shorthand label.
`TRAEFIK_PROVIDERS_DOCKER_LABELMAP_n_TO`:
Full label with templates.
`TRAEFIK_PROVIDERS_DOCKER_LABELMAP_n_VALUE`:
Optional override; used instead of user input if set.
`TRAEFIK_PROVIDERS_DOCKER_NETWORK`:
Default Docker network used.
@ -1164,6 +1179,18 @@ Expose containers by default. (Default: ```true```)
`TRAEFIK_PROVIDERS_SWARM_HTTPCLIENTTIMEOUT`:
Client timeout for HTTP connections. (Default: ```0```)
`TRAEFIK_PROVIDERS_SWARM_LABELMAP`:
Label shorthands.
`TRAEFIK_PROVIDERS_SWARM_LABELMAP_n_FROM`:
Shorthand label.
`TRAEFIK_PROVIDERS_SWARM_LABELMAP_n_TO`:
Full label with templates.
`TRAEFIK_PROVIDERS_SWARM_LABELMAP_n_VALUE`:
Optional override; used instead of user input if set.
`TRAEFIK_PROVIDERS_SWARM_NETWORK`:
Default Docker network used.

View file

@ -3,6 +3,7 @@
[global]
checkNewVersion = true
sendAnonymousUsage = true
updaterCallbacks = ["foobar", "foobar"]
[serversTransport]
insecureSkipVerify = true
@ -97,6 +98,16 @@
password = "foobar"
endpoint = "foobar"
httpClientTimeout = "42s"
[[providers.docker.labelMap]]
from = "foobar"
to = "foobar"
value = "foobar"
[[providers.docker.labelMap]]
from = "foobar"
to = "foobar"
value = "foobar"
[providers.docker.tls]
ca = "foobar"
cert = "foobar"
@ -115,6 +126,16 @@
endpoint = "foobar"
httpClientTimeout = "42s"
refreshSeconds = "42s"
[[providers.swarm.labelMap]]
from = "foobar"
to = "foobar"
value = "foobar"
[[providers.swarm.labelMap]]
from = "foobar"
to = "foobar"
value = "foobar"
[providers.swarm.tls]
ca = "foobar"
cert = "foobar"

View file

@ -3,6 +3,9 @@
global:
checkNewVersion: true
sendAnonymousUsage: true
updaterCallbacks:
- foobar
- foobar
serversTransport:
insecureSkipVerify: true
rootCAs:
@ -106,6 +109,13 @@ providers:
useBindPortIP: true
watch: true
defaultRule: foobar
labelMap:
- from: foobar
to: foobar
value: foobar
- from: foobar
to: foobar
value: foobar
username: foobar
password: foobar
endpoint: foobar
@ -123,6 +133,13 @@ providers:
useBindPortIP: true
watch: true
defaultRule: foobar
labelMap:
- from: foobar
to: foobar
value: foobar
- from: foobar
to: foobar
value: foobar
username: foobar
password: foobar
endpoint: foobar

View file

@ -108,6 +108,7 @@ type CertificateResolver struct {
type Global struct {
CheckNewVersion bool `description:"Periodically check if a new version has been released." json:"checkNewVersion,omitempty" toml:"checkNewVersion,omitempty" yaml:"checkNewVersion,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
SendAnonymousUsage bool `description:"Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default." json:"sendAnonymousUsage,omitempty" toml:"sendAnonymousUsage,omitempty" yaml:"sendAnonymousUsage,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
UpdaterCallbacks []string `description:"Callback urls for updater script (example: https://localhost:8080/callback)" json:"updaterCallbacks,omitempty" toml:"updaterCallbacks,omitempty" yaml:"updaterCallbacks,omitempty" label:"allowEmpty" file:"allowEmpty" export:"true"`
}
// ServersTransport options to configure communication between Traefik and the servers.

View file

@ -396,8 +396,8 @@ func AddStore(configuration *dynamic.TLSConfiguration, storeName string, store t
return reflect.DeepEqual(configuration.Stores[storeName], store)
}
// MakeDefaultRuleTemplate creates the default rule template.
func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*template.Template, error) {
// MakeAnyTemplate creates a template with any name
func MakeAnyTemplate(name string, value string, funcMap template.FuncMap) (*template.Template, error) {
defaultFuncMap := sprig.TxtFuncMap()
defaultFuncMap["normalize"] = Normalize
@ -405,7 +405,12 @@ func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*tem
defaultFuncMap[k] = fn
}
return template.New("defaultRule").Funcs(defaultFuncMap).Parse(defaultRule)
return template.New(name).Funcs(defaultFuncMap).Parse(value)
}
// MakeDefaultRuleTemplate creates the default rule template.
func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*template.Template, error) {
return MakeAnyTemplate("defaultRule", defaultRule, funcMap)
}
// BuildTCPRouterConfiguration builds a router configuration.

View file

@ -1,6 +1,7 @@
package docker
import (
"bytes"
"context"
"errors"
"fmt"
@ -28,15 +29,50 @@ func NewDynConfBuilder(configuration Shared, apiClient client.APIClient, swarm b
return &DynConfBuilder{Shared: configuration, apiClient: apiClient, swarm: swarm}
}
func (p *DynConfBuilder) applyLabels(container *dockerData, model interface{}) {
for _, item := range p.LabelMap {
value, ok := container.Labels[item.From]
if !ok { // label doesn't exist
continue
}
writer := &bytes.Buffer{}
if err := item.toTpl.Execute(writer, model); err != nil {
continue // should never happen?
}
to := writer.String()
if item.Value != nil {
container.Labels[to] = *item.Value
} else {
container.Labels[to] = value
}
}
}
func (p *DynConfBuilder) build(ctx context.Context, containersInspected []dockerData) *dynamic.Configuration {
configurations := make(map[string]*dynamic.Configuration)
for _, container := range containersInspected {
serviceName := getServiceName(container)
model := struct {
Name string
ContainerName string
Labels *map[string]string
}{
Name: serviceName,
ContainerName: strings.TrimPrefix(container.Name, "/"),
Labels: &container.Labels,
}
containerName := getServiceName(container) + "-" + container.ID
logger := log.Ctx(ctx).With().Str("container", containerName).Logger()
ctxContainer := logger.WithContext(ctx)
p.applyLabels(&container, model)
if !p.keepContainer(ctxContainer, container) {
continue
}
@ -83,18 +119,6 @@ func (p *DynConfBuilder) build(ctx context.Context, containersInspected []docker
continue
}
serviceName := getServiceName(container)
model := struct {
Name string
ContainerName string
Labels map[string]string
}{
Name: serviceName,
ContainerName: strings.TrimPrefix(container.Name, "/"),
Labels: container.Labels,
}
provider.BuildRouterConfiguration(ctx, confFromLabel.HTTP, serviceName, p.defaultRuleTpl, model)
configurations[containerName] = confFromLabel

View file

@ -49,8 +49,15 @@ func (p *Provider) Init() error {
if err != nil {
return fmt.Errorf("error while parsing default rule: %w", err)
}
p.defaultRuleTpl = defaultRuleTpl
for _, item := range p.LabelMap {
toTpl, err := provider.MakeAnyTemplate(item.From, item.To, nil)
if err != nil {
return fmt.Errorf("error while parsing label %v: %w", item.To, err)
}
item.toTpl = toTpl
}
return nil
}

View file

@ -33,9 +33,19 @@ type Shared struct {
Watch bool `description:"Watch Docker events." json:"watch,omitempty" toml:"watch,omitempty" yaml:"watch,omitempty" export:"true"`
DefaultRule string `description:"Default rule." json:"defaultRule,omitempty" toml:"defaultRule,omitempty" yaml:"defaultRule,omitempty"`
LabelMap []*LabelMapItem `description:"Label shorthands." json:"labelMap,omitempty" toml:"labelMap,omitempty" yaml:"labelMap,omitempty"`
defaultRuleTpl *template.Template
}
type LabelMapItem struct {
From string `description:"Shorthand label." json:"from,omitempty" toml:"from,omitempty" yaml:"from,omitempty"`
To string `description:"Full label with templates." json:"to,omitempty" toml:"to,omitempty" yaml:"to,omitempty"`
Value *string `description:"Optional override; used instead of user input if set." json:"value,omitempty" toml:"value,omitempty" yaml:"value,omitempty"`
toTpl *template.Template
}
func inspectContainers(ctx context.Context, dockerClient client.ContainerAPIClient, containerID string) dockerData {
containerInspected, err := dockerClient.ContainerInspect(ctx, containerID)
if err != nil {

49
pkg/updater/provider.go Normal file
View file

@ -0,0 +1,49 @@
package updater
import (
"bytes"
"encoding/json"
"net/http"
"github.com/rs/zerolog/log"
"github.com/traefik/traefik/v3/pkg/config/dynamic"
"github.com/traefik/traefik/v3/pkg/config/static"
"github.com/traefik/traefik/v3/pkg/safe"
)
type Updater struct {
callbackUrls []string
}
func New(config *static.Configuration) *Updater {
updater := &Updater{
callbackUrls: config.Global.UpdaterCallbacks,
}
return updater
}
func (u *Updater) HandleConfigUpdate(cfg dynamic.Configuration) {
body, err := json.Marshal(cfg)
if err != nil {
// should never happen?
log.Error().Err(err).Msg("Error while marshalling dynamic configuration data to json")
return
}
requestBody := bytes.NewBuffer(body)
for _, url := range u.callbackUrls {
safe.Go(func() {
resp, err := http.Post(url, "application/json", requestBody)
if err != nil {
log.Error().Err(err).Str("url", url).Msg("Error while sending configuration data to callback")
} else {
log.Debug().Str("url", url).Msg("Configuration data sent")
resp.Body.Close()
}
})
}
}

1851
schema.json Normal file

File diff suppressed because it is too large Load diff