1
0
Fork 0

Compare commits

...

3 commits

Author SHA1 Message Date
0c2d49f5f4
feat: custom label shorthands 2025-11-07 05:22:46 +03:00
585158380f
feat: callbacks 2025-11-07 05:22:18 +03:00
9e1e49f16f
chore: stuff for local deployment 2025-11-07 05:21:40 +03:00
23 changed files with 2079 additions and 263 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,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,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

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

View file

@ -1,3 +1,7 @@
# My modified version of Traefik
slightly modified version of traefik, will be rebased on the latest tag from time to time
this version includes callbacks to external services on configuration update and custom docker label mappings
feel free to check out last 2 commits, they are like 100sloc together
<p align="center"> <p align="center">
<picture> <picture>

View file

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

View file

@ -137,6 +137,7 @@ THIS FILE MUST NOT BE EDITED BY HAND
| <a id="opt-experimental-plugins-name-version" href="#opt-experimental-plugins-name-version" title="#opt-experimental-plugins-name-version">experimental.plugins._name_.version</a> | plugin's version. | | | <a id="opt-experimental-plugins-name-version" href="#opt-experimental-plugins-name-version" title="#opt-experimental-plugins-name-version">experimental.plugins._name_.version</a> | plugin's version. | |
| <a id="opt-global-checknewversion" href="#opt-global-checknewversion" title="#opt-global-checknewversion">global.checknewversion</a> | Periodically check if a new version has been released. | true | | <a id="opt-global-checknewversion" href="#opt-global-checknewversion" title="#opt-global-checknewversion">global.checknewversion</a> | Periodically check if a new version has been released. | true |
| <a id="opt-global-sendanonymoususage" href="#opt-global-sendanonymoususage" title="#opt-global-sendanonymoususage">global.sendanonymoususage</a> | Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. | false | | <a id="opt-global-sendanonymoususage" href="#opt-global-sendanonymoususage" title="#opt-global-sendanonymoususage">global.sendanonymoususage</a> | Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. | false |
| <a id="opt-global-updatercallbacks" href="#opt-global-updatercallbacks" title="#opt-global-updatercallbacks">global.updatercallbacks</a> | Callback urls for updater script (example: https://localhost:8080/callback) | |
| <a id="opt-hostresolver" href="#opt-hostresolver" title="#opt-hostresolver">hostresolver</a> | Enable CNAME Flattening. | false | | <a id="opt-hostresolver" href="#opt-hostresolver" title="#opt-hostresolver">hostresolver</a> | Enable CNAME Flattening. | false |
| <a id="opt-hostresolver-cnameflattening" href="#opt-hostresolver-cnameflattening" title="#opt-hostresolver-cnameflattening">hostresolver.cnameflattening</a> | A flag to enable/disable CNAME flattening | false | | <a id="opt-hostresolver-cnameflattening" href="#opt-hostresolver-cnameflattening" title="#opt-hostresolver-cnameflattening">hostresolver.cnameflattening</a> | A flag to enable/disable CNAME flattening | false |
| <a id="opt-hostresolver-resolvconfig" href="#opt-hostresolver-resolvconfig" title="#opt-hostresolver-resolvconfig">hostresolver.resolvconfig</a> | resolv.conf used for DNS resolving | /etc/resolv.conf | | <a id="opt-hostresolver-resolvconfig" href="#opt-hostresolver-resolvconfig" title="#opt-hostresolver-resolvconfig">hostresolver.resolvconfig</a> | resolv.conf used for DNS resolving | /etc/resolv.conf |
@ -272,6 +273,10 @@ THIS FILE MUST NOT BE EDITED BY HAND
| <a id="opt-providers-docker-endpoint" href="#opt-providers-docker-endpoint" title="#opt-providers-docker-endpoint">providers.docker.endpoint</a> | Docker server endpoint. Can be a TCP or a Unix socket endpoint. | unix:///var/run/docker.sock | | <a id="opt-providers-docker-endpoint" href="#opt-providers-docker-endpoint" title="#opt-providers-docker-endpoint">providers.docker.endpoint</a> | Docker server endpoint. Can be a TCP or a Unix socket endpoint. | unix:///var/run/docker.sock |
| <a id="opt-providers-docker-exposedbydefault" href="#opt-providers-docker-exposedbydefault" title="#opt-providers-docker-exposedbydefault">providers.docker.exposedbydefault</a> | Expose containers by default. | true | | <a id="opt-providers-docker-exposedbydefault" href="#opt-providers-docker-exposedbydefault" title="#opt-providers-docker-exposedbydefault">providers.docker.exposedbydefault</a> | Expose containers by default. | true |
| <a id="opt-providers-docker-httpclienttimeout" href="#opt-providers-docker-httpclienttimeout" title="#opt-providers-docker-httpclienttimeout">providers.docker.httpclienttimeout</a> | Client timeout for HTTP connections. | 0 | | <a id="opt-providers-docker-httpclienttimeout" href="#opt-providers-docker-httpclienttimeout" title="#opt-providers-docker-httpclienttimeout">providers.docker.httpclienttimeout</a> | Client timeout for HTTP connections. | 0 |
| <a id="opt-providers-docker-labelmap" href="#opt-providers-docker-labelmap" title="#opt-providers-docker-labelmap">providers.docker.labelmap</a> | Label shorthands. | |
| <a id="opt-providers-docker-labelmap0-from" href="#opt-providers-docker-labelmap0-from" title="#opt-providers-docker-labelmap0-from">providers.docker.labelmap[0].from</a> | Shorthand label. | |
| <a id="opt-providers-docker-labelmap0-to" href="#opt-providers-docker-labelmap0-to" title="#opt-providers-docker-labelmap0-to">providers.docker.labelmap[0].to</a> | Full label with templates. | |
| <a id="opt-providers-docker-labelmap0-value" href="#opt-providers-docker-labelmap0-value" title="#opt-providers-docker-labelmap0-value">providers.docker.labelmap[0].value</a> | Optional override; used instead of user input if set. | |
| <a id="opt-providers-docker-network" href="#opt-providers-docker-network" title="#opt-providers-docker-network">providers.docker.network</a> | Default Docker network used. | | | <a id="opt-providers-docker-network" href="#opt-providers-docker-network" title="#opt-providers-docker-network">providers.docker.network</a> | Default Docker network used. | |
| <a id="opt-providers-docker-password" href="#opt-providers-docker-password" title="#opt-providers-docker-password">providers.docker.password</a> | Password for Basic HTTP authentication. | | | <a id="opt-providers-docker-password" href="#opt-providers-docker-password" title="#opt-providers-docker-password">providers.docker.password</a> | Password for Basic HTTP authentication. | |
| <a id="opt-providers-docker-tls-ca" href="#opt-providers-docker-tls-ca" title="#opt-providers-docker-tls-ca">providers.docker.tls.ca</a> | TLS CA | | | <a id="opt-providers-docker-tls-ca" href="#opt-providers-docker-tls-ca" title="#opt-providers-docker-tls-ca">providers.docker.tls.ca</a> | TLS CA | |
@ -421,6 +426,10 @@ THIS FILE MUST NOT BE EDITED BY HAND
| <a id="opt-providers-swarm-endpoint" href="#opt-providers-swarm-endpoint" title="#opt-providers-swarm-endpoint">providers.swarm.endpoint</a> | Docker server endpoint. Can be a TCP or a Unix socket endpoint. | unix:///var/run/docker.sock | | <a id="opt-providers-swarm-endpoint" href="#opt-providers-swarm-endpoint" title="#opt-providers-swarm-endpoint">providers.swarm.endpoint</a> | Docker server endpoint. Can be a TCP or a Unix socket endpoint. | unix:///var/run/docker.sock |
| <a id="opt-providers-swarm-exposedbydefault" href="#opt-providers-swarm-exposedbydefault" title="#opt-providers-swarm-exposedbydefault">providers.swarm.exposedbydefault</a> | Expose containers by default. | true | | <a id="opt-providers-swarm-exposedbydefault" href="#opt-providers-swarm-exposedbydefault" title="#opt-providers-swarm-exposedbydefault">providers.swarm.exposedbydefault</a> | Expose containers by default. | true |
| <a id="opt-providers-swarm-httpclienttimeout" href="#opt-providers-swarm-httpclienttimeout" title="#opt-providers-swarm-httpclienttimeout">providers.swarm.httpclienttimeout</a> | Client timeout for HTTP connections. | 0 | | <a id="opt-providers-swarm-httpclienttimeout" href="#opt-providers-swarm-httpclienttimeout" title="#opt-providers-swarm-httpclienttimeout">providers.swarm.httpclienttimeout</a> | Client timeout for HTTP connections. | 0 |
| <a id="opt-providers-swarm-labelmap" href="#opt-providers-swarm-labelmap" title="#opt-providers-swarm-labelmap">providers.swarm.labelmap</a> | Label shorthands. | |
| <a id="opt-providers-swarm-labelmap0-from" href="#opt-providers-swarm-labelmap0-from" title="#opt-providers-swarm-labelmap0-from">providers.swarm.labelmap[0].from</a> | Shorthand label. | |
| <a id="opt-providers-swarm-labelmap0-to" href="#opt-providers-swarm-labelmap0-to" title="#opt-providers-swarm-labelmap0-to">providers.swarm.labelmap[0].to</a> | Full label with templates. | |
| <a id="opt-providers-swarm-labelmap0-value" href="#opt-providers-swarm-labelmap0-value" title="#opt-providers-swarm-labelmap0-value">providers.swarm.labelmap[0].value</a> | Optional override; used instead of user input if set. | |
| <a id="opt-providers-swarm-network" href="#opt-providers-swarm-network" title="#opt-providers-swarm-network">providers.swarm.network</a> | Default Docker network used. | | | <a id="opt-providers-swarm-network" href="#opt-providers-swarm-network" title="#opt-providers-swarm-network">providers.swarm.network</a> | Default Docker network used. | |
| <a id="opt-providers-swarm-password" href="#opt-providers-swarm-password" title="#opt-providers-swarm-password">providers.swarm.password</a> | Password for Basic HTTP authentication. | | | <a id="opt-providers-swarm-password" href="#opt-providers-swarm-password" title="#opt-providers-swarm-password">providers.swarm.password</a> | Password for Basic HTTP authentication. | |
| <a id="opt-providers-swarm-refreshseconds" href="#opt-providers-swarm-refreshseconds" title="#opt-providers-swarm-refreshseconds">providers.swarm.refreshseconds</a> | Polling interval for swarm mode. | 15 | | <a id="opt-providers-swarm-refreshseconds" href="#opt-providers-swarm-refreshseconds" title="#opt-providers-swarm-refreshseconds">providers.swarm.refreshseconds</a> | Polling interval for swarm mode. | 15 |

View file

@ -390,6 +390,9 @@ Periodically check if a new version has been released. (Default: ```true```)
`--global.sendanonymoususage`: `--global.sendanonymoususage`:
Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```) 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`: `--hostresolver`:
Enable CNAME Flattening. (Default: ```false```) Enable CNAME Flattening. (Default: ```false```)
@ -795,6 +798,18 @@ Expose containers by default. (Default: ```true```)
`--providers.docker.httpclienttimeout`: `--providers.docker.httpclienttimeout`:
Client timeout for HTTP connections. (Default: ```0```) 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`: `--providers.docker.network`:
Default Docker network used. Default Docker network used.
@ -1242,6 +1257,18 @@ Expose containers by default. (Default: ```true```)
`--providers.swarm.httpclienttimeout`: `--providers.swarm.httpclienttimeout`:
Client timeout for HTTP connections. (Default: ```0```) 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`: `--providers.swarm.network`:
Default Docker network used. Default Docker network used.

View file

@ -390,6 +390,9 @@ Periodically check if a new version has been released. (Default: ```true```)
`TRAEFIK_GLOBAL_SENDANONYMOUSUSAGE`: `TRAEFIK_GLOBAL_SENDANONYMOUSUSAGE`:
Periodically send anonymous usage statistics. If the option is not specified, it will be disabled by default. (Default: ```false```) 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`: `TRAEFIK_HOSTRESOLVER`:
Enable CNAME Flattening. (Default: ```false```) Enable CNAME Flattening. (Default: ```false```)
@ -795,6 +798,18 @@ Expose containers by default. (Default: ```true```)
`TRAEFIK_PROVIDERS_DOCKER_HTTPCLIENTTIMEOUT`: `TRAEFIK_PROVIDERS_DOCKER_HTTPCLIENTTIMEOUT`:
Client timeout for HTTP connections. (Default: ```0```) 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`: `TRAEFIK_PROVIDERS_DOCKER_NETWORK`:
Default Docker network used. Default Docker network used.
@ -1242,6 +1257,18 @@ Expose containers by default. (Default: ```true```)
`TRAEFIK_PROVIDERS_SWARM_HTTPCLIENTTIMEOUT`: `TRAEFIK_PROVIDERS_SWARM_HTTPCLIENTTIMEOUT`:
Client timeout for HTTP connections. (Default: ```0```) 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`: `TRAEFIK_PROVIDERS_SWARM_NETWORK`:
Default Docker network used. Default Docker network used.

View file

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

View file

@ -3,6 +3,9 @@
global: global:
checkNewVersion: true checkNewVersion: true
sendAnonymousUsage: true sendAnonymousUsage: true
updaterCallbacks:
- foobar
- foobar
serversTransport: serversTransport:
insecureSkipVerify: true insecureSkipVerify: true
rootCAs: rootCAs:
@ -107,6 +110,13 @@ providers:
useBindPortIP: true useBindPortIP: true
watch: true watch: true
defaultRule: foobar defaultRule: foobar
labelMap:
- from: foobar
to: foobar
value: foobar
- from: foobar
to: foobar
value: foobar
username: foobar username: foobar
password: foobar password: foobar
endpoint: foobar endpoint: foobar
@ -124,6 +134,13 @@ providers:
useBindPortIP: true useBindPortIP: true
watch: true watch: true
defaultRule: foobar defaultRule: foobar
labelMap:
- from: foobar
to: foobar
value: foobar
- from: foobar
to: foobar
value: foobar
username: foobar username: foobar
password: foobar password: foobar
endpoint: foobar endpoint: foobar

View file

@ -113,6 +113,7 @@ type CertificateResolver struct {
type Global 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"` 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"` 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. // 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) return reflect.DeepEqual(configuration.Stores[storeName], store)
} }
// MakeDefaultRuleTemplate creates the default rule template. // MakeAnyTemplate creates a template with any name
func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*template.Template, error) { func MakeAnyTemplate(name string, value string, funcMap template.FuncMap) (*template.Template, error) {
defaultFuncMap := sprig.TxtFuncMap() defaultFuncMap := sprig.TxtFuncMap()
defaultFuncMap["normalize"] = Normalize defaultFuncMap["normalize"] = Normalize
@ -405,7 +405,12 @@ func MakeDefaultRuleTemplate(defaultRule string, funcMap template.FuncMap) (*tem
defaultFuncMap[k] = fn 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. // BuildTCPRouterConfiguration builds a router configuration.

View file

@ -1,6 +1,7 @@
package docker package docker
import ( import (
"bytes"
"context" "context"
"errors" "errors"
"fmt" "fmt"
@ -28,15 +29,50 @@ func NewDynConfBuilder(configuration Shared, apiClient client.APIClient, swarm b
return &DynConfBuilder{Shared: configuration, apiClient: apiClient, swarm: swarm} 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 { func (p *DynConfBuilder) build(ctx context.Context, containersInspected []dockerData) *dynamic.Configuration {
configurations := make(map[string]*dynamic.Configuration) configurations := make(map[string]*dynamic.Configuration)
for _, container := range containersInspected { 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 containerName := getServiceName(container) + "-" + container.ID
logger := log.Ctx(ctx).With().Str("container", containerName).Logger() logger := log.Ctx(ctx).With().Str("container", containerName).Logger()
ctxContainer := logger.WithContext(ctx) ctxContainer := logger.WithContext(ctx)
p.applyLabels(&container, model)
if !p.keepContainer(ctxContainer, container) { if !p.keepContainer(ctxContainer, container) {
continue continue
} }
@ -83,18 +119,6 @@ func (p *DynConfBuilder) build(ctx context.Context, containersInspected []docker
continue 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) provider.BuildRouterConfiguration(ctx, confFromLabel.HTTP, serviceName, p.defaultRuleTpl, model)
configurations[containerName] = confFromLabel configurations[containerName] = confFromLabel

View file

@ -48,8 +48,15 @@ func (p *Provider) Init() error {
if err != nil { if err != nil {
return fmt.Errorf("error while parsing default rule: %w", err) return fmt.Errorf("error while parsing default rule: %w", err)
} }
p.defaultRuleTpl = defaultRuleTpl 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 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"` 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"` 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 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 { func inspectContainers(ctx context.Context, dockerClient client.ContainerAPIClient, containerID string) dockerData {
containerInspected, err := dockerClient.ContainerInspect(ctx, containerID) containerInspected, err := dockerClient.ContainerInspect(ctx, containerID)
if err != nil { 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