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
COPY ./dist/$TARGETPLATFORM/traefik /
COPY ./traefik.yml /etc/traefik/traefik.yml
EXPOSE 80
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">
<picture>
@ -42,14 +46,14 @@ Pointing Traefik at your orchestrator should be the _only_ configuration step yo
Imagine that you have deployed a bunch of microservices with the help of an orchestrator (like Swarm or Kubernetes) or a service registry (like etcd or consul).
Now you want users to access these microservices, and you need a reverse proxy.
Traditional reverse-proxies require that you configure _each_ route that will connect paths and subdomains to _each_ microservice.
In an environment where you add, remove, kill, upgrade, or scale your services _many_ times a day, the task of keeping the routes up to date becomes tedious.
Traditional reverse-proxies require that you configure _each_ route that will connect paths and subdomains to _each_ microservice.
In an environment where you add, remove, kill, upgrade, or scale your services _many_ times a day, the task of keeping the routes up to date becomes tedious.
**This is when Traefik can help you!**
Traefik listens to your service registry/orchestrator API and instantly generates the routes so your microservices are connected to the outside world -- without further intervention from your part.
Traefik listens to your service registry/orchestrator API and instantly generates the routes so your microservices are connected to the outside world -- without further intervention from your part.
**Run Traefik and let it do the work for you!**
**Run Traefik and let it do the work for you!**
_(But if you'd rather configure some of your routes manually, Traefik supports that too!)_
![Architecture](docs/content/assets/img/traefik-architecture.png)

View file

@ -49,6 +49,7 @@ import (
"github.com/traefik/traefik/v3/pkg/tcp"
traefiktls "github.com/traefik/traefik/v3/pkg/tls"
"github.com/traefik/traefik/v3/pkg/version"
"github.com/traefik/traefik/v3/pkg/updater"
)
func main() {
@ -199,6 +200,8 @@ func setupServer(staticConfiguration *static.Configuration) (*server.Server, err
tsProviders := initTailscaleProviders(staticConfiguration, providerAggregator)
updaterProvider := updater.New(staticConfiguration);
// Observability
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
}

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-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-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-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 |
@ -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-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-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-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 | |
@ -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-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-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-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 |

View file

@ -390,6 +390,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```)
@ -795,6 +798,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.
@ -1242,6 +1257,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

@ -390,6 +390,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```)
@ -795,6 +798,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.
@ -1242,6 +1257,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
@ -98,6 +99,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"
@ -116,6 +127,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:
@ -107,6 +110,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
@ -124,6 +134,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

@ -113,6 +113,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

@ -48,8 +48,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