From c826cc97e65487ba65992cd74af0b45ee0d97ecf Mon Sep 17 00:00:00 2001 From: "Arthur K." Date: Wed, 11 Jun 2025 15:04:44 +0300 Subject: [PATCH] feat: callbacks --- cmd/traefik/traefik.go | 6 + .../reference/static-configuration/cli-ref.md | 3 + .../reference/static-configuration/env-ref.md | 3 + .../reference/static-configuration/file.toml | 1 + .../reference/static-configuration/file.yaml | 3 + pkg/config/static/static_config.go | 1 + pkg/updater/provider.go | 49 + schema.json | 1851 +++++++++++++++++ 8 files changed, 1917 insertions(+) create mode 100644 pkg/updater/provider.go create mode 100644 schema.json diff --git a/cmd/traefik/traefik.go b/cmd/traefik/traefik.go index 77930754b..413907f17 100644 --- a/cmd/traefik/traefik.go +++ b/cmd/traefik/traefik.go @@ -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 } diff --git a/docs/content/reference/static-configuration/cli-ref.md b/docs/content/reference/static-configuration/cli-ref.md index b35cbc982..2eaa9861b 100644 --- a/docs/content/reference/static-configuration/cli-ref.md +++ b/docs/content/reference/static-configuration/cli-ref.md @@ -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```) diff --git a/docs/content/reference/static-configuration/env-ref.md b/docs/content/reference/static-configuration/env-ref.md index 8f6e25c05..474fdc9ef 100644 --- a/docs/content/reference/static-configuration/env-ref.md +++ b/docs/content/reference/static-configuration/env-ref.md @@ -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```) diff --git a/docs/content/reference/static-configuration/file.toml b/docs/content/reference/static-configuration/file.toml index e548ee76d..8e96fd52e 100644 --- a/docs/content/reference/static-configuration/file.toml +++ b/docs/content/reference/static-configuration/file.toml @@ -3,6 +3,7 @@ [global] checkNewVersion = true sendAnonymousUsage = true + updaterCallbacks = ["foobar", "foobar"] [serversTransport] insecureSkipVerify = true diff --git a/docs/content/reference/static-configuration/file.yaml b/docs/content/reference/static-configuration/file.yaml index 760802591..3c79d9089 100644 --- a/docs/content/reference/static-configuration/file.yaml +++ b/docs/content/reference/static-configuration/file.yaml @@ -3,6 +3,9 @@ global: checkNewVersion: true sendAnonymousUsage: true + updaterCallbacks: + - foobar + - foobar serversTransport: insecureSkipVerify: true rootCAs: diff --git a/pkg/config/static/static_config.go b/pkg/config/static/static_config.go index af60efbb8..73f740472 100644 --- a/pkg/config/static/static_config.go +++ b/pkg/config/static/static_config.go @@ -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. diff --git a/pkg/updater/provider.go b/pkg/updater/provider.go new file mode 100644 index 000000000..26d1fc469 --- /dev/null +++ b/pkg/updater/provider.go @@ -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() + } + }) + } +} diff --git a/schema.json b/schema.json new file mode 100644 index 000000000..0f8823ad9 --- /dev/null +++ b/schema.json @@ -0,0 +1,1851 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://json.schemastore.org/traefik-v3.json", + "$defs": { + "CertificateResolverTailscaleStruct": { + "additionalProperties": false, + "type": "object" + }, + "acmeConfiguration": { + "additionalProperties": false, + "properties": { + "caCertificates": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "caServer": { + "type": "string" + }, + "caServerName": { + "type": "string" + }, + "caSystemCertPool": { + "type": "boolean" + }, + "certificatesDuration": { + "type": "integer" + }, + "dnsChallenge": { + "$ref": "#/$defs/acmeDNSChallenge" + }, + "eab": { + "$ref": "#/$defs/acmeEAB" + }, + "email": { + "type": "string" + }, + "httpChallenge": { + "$ref": "#/$defs/acmeHTTPChallenge" + }, + "keyType": { + "type": "string" + }, + "preferredChain": { + "type": "string" + }, + "storage": { + "type": "string" + }, + "tlsChallenge": { + "$ref": "#/$defs/acmeTLSChallenge" + } + }, + "type": "object" + }, + "acmeDNSChallenge": { + "additionalProperties": false, + "properties": { + "delayBeforeCheck": { + "type": "string" + }, + "disablePropagationCheck": { + "type": "boolean" + }, + "propagation": { + "$ref": "#/$defs/acmePropagation" + }, + "provider": { + "type": "string" + }, + "resolvers": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + }, + "type": "object" + }, + "acmeEAB": { + "additionalProperties": false, + "properties": { + "hmacEncoded": { + "type": "string" + }, + "kid": { + "type": "string" + } + }, + "type": "object" + }, + "acmeHTTPChallenge": { + "additionalProperties": false, + "properties": { + "entryPoint": { + "type": "string" + } + }, + "type": "object" + }, + "acmePropagation": { + "additionalProperties": false, + "properties": { + "delayBeforeChecks": { + "type": "string" + }, + "disableANSChecks": { + "type": "boolean" + }, + "disableChecks": { + "type": "boolean" + }, + "requireAllRNS": { + "type": "boolean" + } + }, + "type": "object" + }, + "acmeTLSChallenge": { + "additionalProperties": false, + "type": "object" + }, + "consulProviderBuilder": { + "additionalProperties": false, + "properties": { + "endpoints": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "namespaces": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "rootKey": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + }, + "token": { + "type": "string" + } + }, + "type": "object" + }, + "consulcatalogEndpointConfig": { + "additionalProperties": false, + "properties": { + "address": { + "type": "string" + }, + "datacenter": { + "type": "string" + }, + "endpointWaitTime": { + "type": "string" + }, + "httpAuth": { + "$ref": "#/$defs/consulcatalogEndpointHTTPAuthConfig" + }, + "scheme": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + }, + "token": { + "type": "string" + } + }, + "type": "object" + }, + "consulcatalogEndpointHTTPAuthConfig": { + "additionalProperties": false, + "properties": { + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "type": "object" + }, + "consulcatalogProviderBuilder": { + "additionalProperties": false, + "properties": { + "cache": { + "type": "boolean" + }, + "connectAware": { + "type": "boolean" + }, + "connectByDefault": { + "type": "boolean" + }, + "constraints": { + "type": "string" + }, + "defaultRule": { + "type": "string" + }, + "endpoint": { + "$ref": "#/$defs/consulcatalogEndpointConfig" + }, + "exposedByDefault": { + "type": "boolean" + }, + "namespaces": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "prefix": { + "type": "string" + }, + "refreshInterval": { + "type": "string" + }, + "requireConsistent": { + "type": "boolean" + }, + "serviceName": { + "type": "string" + }, + "stale": { + "type": "boolean" + }, + "strictChecks": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "watch": { + "type": "boolean" + } + }, + "type": "object" + }, + "crdProvider": { + "additionalProperties": false, + "properties": { + "allowCrossNamespace": { + "type": "boolean" + }, + "allowEmptyServices": { + "type": "boolean" + }, + "allowExternalNameServices": { + "type": "boolean" + }, + "certAuthFilePath": { + "type": "string" + }, + "disableClusterScopeResources": { + "type": "boolean" + }, + "endpoint": { + "type": "string" + }, + "ingressClass": { + "type": "string" + }, + "labelSelector": { + "type": "string" + }, + "namespaces": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "nativeLBByDefault": { + "type": "boolean" + }, + "throttleDuration": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "type": "object" + }, + "dockerProvider": { + "additionalProperties": false, + "properties": { + "allowEmptyServices": { + "type": "boolean" + }, + "constraints": { + "type": "string" + }, + "defaultRule": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "exposedByDefault": { + "type": "boolean" + }, + "httpClientTimeout": { + "type": "string" + }, + "network": { + "type": "string" + }, + "password": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + }, + "useBindPortIP": { + "type": "boolean" + }, + "username": { + "type": "string" + }, + "watch": { + "type": "boolean" + }, + "labelMap": { + "type": "array", + "items": { + "type": "object", + "properties": { + "from": { + "type": "string", + "description": "Shorthand label." + }, + "to": { + "type": "string", + "description": "Full label with templates." + }, + "value": { + "type": "string", + "description": "Optional override; used instead of user input if set." + } + }, + "required": ["from", "to"], + "additionalProperties": false + } + } + }, + "type": "object" + }, + "dockerSwarmProvider": { + "additionalProperties": false, + "properties": { + "allowEmptyServices": { + "type": "boolean" + }, + "constraints": { + "type": "string" + }, + "defaultRule": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "exposedByDefault": { + "type": "boolean" + }, + "httpClientTimeout": { + "type": "string" + }, + "network": { + "type": "string" + }, + "password": { + "type": "string" + }, + "refreshSeconds": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + }, + "useBindPortIP": { + "type": "boolean" + }, + "username": { + "type": "string" + }, + "watch": { + "type": "boolean" + } + }, + "type": "object" + }, + "ecsProvider": { + "additionalProperties": false, + "properties": { + "accessKeyID": { + "type": "string" + }, + "autoDiscoverClusters": { + "type": "boolean" + }, + "clusters": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "constraints": { + "type": "string" + }, + "defaultRule": { + "type": "string" + }, + "ecsAnywhere": { + "type": "boolean" + }, + "exposedByDefault": { + "type": "boolean" + }, + "healthyTasksOnly": { + "type": "boolean" + }, + "refreshSeconds": { + "type": "integer" + }, + "region": { + "type": "string" + }, + "secretAccessKey": { + "type": "string" + } + }, + "type": "object" + }, + "etcdProvider": { + "additionalProperties": false, + "properties": { + "endpoints": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "password": { + "type": "string" + }, + "rootKey": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + }, + "username": { + "type": "string" + } + }, + "type": "object" + }, + "fileProvider": { + "additionalProperties": false, + "properties": { + "debugLogGeneratedTemplate": { + "type": "boolean" + }, + "directory": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "watch": { + "type": "boolean" + } + }, + "type": "object" + }, + "gatewayProvider": { + "additionalProperties": false, + "properties": { + "certAuthFilePath": { + "type": "string" + }, + "endpoint": { + "type": "string" + }, + "experimentalChannel": { + "type": "boolean" + }, + "labelSelector": { + "type": "string" + }, + "namespaces": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "nativeLBByDefault": { + "type": "boolean" + }, + "statusAddress": { + "$ref": "#/$defs/gatewayStatusAddress" + }, + "throttleDuration": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "type": "object" + }, + "gatewayServiceRef": { + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + } + }, + "type": "object" + }, + "gatewayStatusAddress": { + "additionalProperties": false, + "properties": { + "hostname": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "service": { + "$ref": "#/$defs/gatewayServiceRef" + } + }, + "type": "object" + }, + "httpProvider": { + "additionalProperties": false, + "properties": { + "endpoint": { + "type": "string" + }, + "headers": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "pollInterval": { + "type": "string" + }, + "pollTimeout": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + } + }, + "required": ["endpoint"], + "type": "object" + }, + "ingressEndpointIngress": { + "additionalProperties": false, + "properties": { + "hostname": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "publishedService": { + "type": "string" + } + }, + "type": "object" + }, + "ingressProvider": { + "additionalProperties": false, + "properties": { + "allowEmptyServices": { + "type": "boolean" + }, + "allowExternalNameServices": { + "type": "boolean" + }, + "certAuthFilePath": { + "type": "string" + }, + "disableClusterScopeResources": { + "type": "boolean" + }, + "disableIngressClassLookup": { + "type": "boolean" + }, + "endpoint": { + "type": "string" + }, + "ingressClass": { + "type": "string" + }, + "ingressEndpoint": { + "$ref": "#/$defs/ingressEndpointIngress" + }, + "labelSelector": { + "type": "string" + }, + "namespaces": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "nativeLBByDefault": { + "type": "boolean" + }, + "throttleDuration": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "type": "object" + }, + "nomadEndpointConfig": { + "additionalProperties": false, + "properties": { + "address": { + "type": "string" + }, + "endpointWaitTime": { + "type": "string" + }, + "region": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + }, + "token": { + "type": "string" + } + }, + "type": "object" + }, + "nomadProviderBuilder": { + "additionalProperties": false, + "properties": { + "allowEmptyServices": { + "type": "boolean" + }, + "constraints": { + "type": "string" + }, + "defaultRule": { + "type": "string" + }, + "endpoint": { + "$ref": "#/$defs/nomadEndpointConfig" + }, + "exposedByDefault": { + "type": "boolean" + }, + "namespaces": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "prefix": { + "type": "string" + }, + "refreshInterval": { + "type": "string" + }, + "stale": { + "type": "boolean" + }, + "throttleDuration": { + "type": "string" + }, + "watch": { + "type": "boolean" + } + }, + "type": "object" + }, + "pingHandler": { + "additionalProperties": false, + "properties": { + "entryPoint": { + "type": "string" + }, + "manualRouting": { + "type": "boolean" + }, + "terminatingStatusCode": { + "type": "integer" + } + }, + "type": "object" + }, + "pluginsDescriptor": { + "additionalProperties": false, + "properties": { + "moduleName": { + "type": "string" + }, + "settings": { + "$ref": "#/$defs/pluginsSettings" + }, + "version": { + "type": "string" + } + }, + "type": "object" + }, + "pluginsLocalDescriptor": { + "additionalProperties": false, + "properties": { + "moduleName": { + "type": "string" + }, + "settings": { + "$ref": "#/$defs/pluginsSettings" + } + }, + "type": "object" + }, + "pluginsSettings": { + "additionalProperties": false, + "properties": { + "envs": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "mounts": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + }, + "type": "object" + }, + "redisProvider": { + "additionalProperties": false, + "properties": { + "db": { + "type": "integer" + }, + "endpoints": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "password": { + "type": "string" + }, + "rootKey": { + "type": "string" + }, + "sentinel": { + "$ref": "#/$defs/redisSentinel" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + }, + "username": { + "type": "string" + } + }, + "type": "object" + }, + "redisSentinel": { + "additionalProperties": false, + "properties": { + "latencyStrategy": { + "type": "boolean" + }, + "masterName": { + "type": "string" + }, + "password": { + "type": "string" + }, + "randomStrategy": { + "type": "boolean" + }, + "replicaStrategy": { + "type": "boolean" + }, + "useDisconnectedReplicas": { + "type": "boolean" + }, + "username": { + "type": "string" + } + }, + "type": "object" + }, + "restProvider": { + "additionalProperties": false, + "properties": { + "insecure": { + "type": "boolean" + } + }, + "type": "object" + }, + "staticAPI": { + "additionalProperties": false, + "properties": { + "basePath": { + "type": "string" + }, + "dashboard": { + "type": "boolean" + }, + "debug": { + "type": "boolean" + }, + "disableDashboardAd": { + "type": "boolean" + }, + "insecure": { + "type": "boolean" + } + }, + "type": "object" + }, + "staticCertificateResolver": { + "additionalProperties": false, + "properties": { + "acme": { + "$ref": "#/$defs/acmeConfiguration" + }, + "tailscale": { + "$ref": "#/$defs/CertificateResolverTailscaleStruct" + } + }, + "type": "object" + }, + "staticCore": { + "additionalProperties": false, + "properties": { + "defaultRuleSyntax": { + "type": "string" + } + }, + "type": "object" + }, + "staticEntryPoint": { + "additionalProperties": false, + "properties": { + "address": { + "type": "string" + }, + "allowACMEByPass": { + "type": "boolean" + }, + "asDefault": { + "type": "boolean" + }, + "forwardedHeaders": { + "$ref": "#/$defs/staticForwardedHeaders" + }, + "http": { + "$ref": "#/$defs/staticHTTPConfig" + }, + "http2": { + "$ref": "#/$defs/staticHTTP2Config" + }, + "http3": { + "$ref": "#/$defs/staticHTTP3Config" + }, + "observability": { + "$ref": "#/$defs/staticObservabilityConfig" + }, + "proxyProtocol": { + "$ref": "#/$defs/staticProxyProtocol" + }, + "reusePort": { + "type": "boolean" + }, + "transport": { + "$ref": "#/$defs/staticEntryPointsTransport" + }, + "udp": { + "$ref": "#/$defs/staticUDPConfig" + } + }, + "type": "object" + }, + "staticEntryPointsTransport": { + "additionalProperties": false, + "properties": { + "keepAliveMaxRequests": { + "type": "integer" + }, + "keepAliveMaxTime": { + "type": "string" + }, + "lifeCycle": { + "$ref": "#/$defs/staticLifeCycle" + }, + "respondingTimeouts": { + "$ref": "#/$defs/staticRespondingTimeouts" + } + }, + "type": "object" + }, + "staticExperimental": { + "additionalProperties": false, + "properties": { + "abortOnPluginFailure": { + "type": "boolean" + }, + "fastProxy": { + "$ref": "#/$defs/staticFastProxyConfig" + }, + "kubernetesGateway": { + "type": "boolean" + }, + "localPlugins": { + "additionalProperties": { + "$ref": "#/$defs/pluginsLocalDescriptor" + }, + "type": "object" + }, + "otlplogs": { + "type": "boolean" + }, + "plugins": { + "additionalProperties": { + "$ref": "#/$defs/pluginsDescriptor" + }, + "type": "object" + } + }, + "type": "object" + }, + "staticFastProxyConfig": { + "additionalProperties": false, + "properties": { + "debug": { + "type": "boolean" + } + }, + "type": "object" + }, + "staticForwardedHeaders": { + "additionalProperties": false, + "properties": { + "connection": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "insecure": { + "type": "boolean" + }, + "trustedIPs": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + }, + "type": "object" + }, + "staticForwardingTimeouts": { + "additionalProperties": false, + "properties": { + "dialTimeout": { + "type": "string" + }, + "idleConnTimeout": { + "type": "string" + }, + "responseHeaderTimeout": { + "type": "string" + } + }, + "type": "object" + }, + "staticGlobal": { + "additionalProperties": false, + "properties": { + "checkNewVersion": { + "type": "boolean" + }, + "sendAnonymousUsage": { + "type": "boolean" + }, + "updaterCallbacks": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "type": "object" + }, + "staticHTTP2Config": { + "additionalProperties": false, + "properties": { + "maxConcurrentStreams": { + "type": "integer" + } + }, + "type": "object" + }, + "staticHTTP3Config": { + "additionalProperties": false, + "properties": { + "advertisedPort": { + "type": "integer" + } + }, + "type": "object" + }, + "staticHTTPConfig": { + "additionalProperties": false, + "properties": { + "encodeQuerySemicolons": { + "type": "boolean" + }, + "maxHeaderBytes": { + "type": "integer" + }, + "middlewares": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "redirections": { + "$ref": "#/$defs/staticRedirections" + }, + "tls": { + "$ref": "#/$defs/staticTLSConfig" + } + }, + "type": "object" + }, + "staticLifeCycle": { + "additionalProperties": false, + "properties": { + "graceTimeOut": { + "type": "string" + }, + "requestAcceptGraceTimeout": { + "type": "string" + } + }, + "type": "object" + }, + "staticObservabilityConfig": { + "additionalProperties": false, + "properties": { + "accessLogs": { + "type": "boolean" + }, + "metrics": { + "type": "boolean" + }, + "tracing": { + "type": "boolean" + } + }, + "type": "object" + }, + "staticProviders": { + "additionalProperties": false, + "properties": { + "consul": { + "$ref": "#/$defs/consulProviderBuilder" + }, + "consulCatalog": { + "$ref": "#/$defs/consulcatalogProviderBuilder" + }, + "docker": { + "$ref": "#/$defs/dockerProvider" + }, + "ecs": { + "$ref": "#/$defs/ecsProvider" + }, + "etcd": { + "$ref": "#/$defs/etcdProvider" + }, + "file": { + "$ref": "#/$defs/fileProvider" + }, + "http": { + "$ref": "#/$defs/httpProvider" + }, + "kubernetesCRD": { + "$ref": "#/$defs/crdProvider" + }, + "kubernetesGateway": { + "$ref": "#/$defs/gatewayProvider" + }, + "kubernetesIngress": { + "$ref": "#/$defs/ingressProvider" + }, + "nomad": { + "$ref": "#/$defs/nomadProviderBuilder" + }, + "plugin": { + "additionalProperties": { + "additionalProperties": {}, + "type": "object" + }, + "type": "object" + }, + "providersThrottleDuration": { + "type": "string" + }, + "redis": { + "$ref": "#/$defs/redisProvider" + }, + "rest": { + "$ref": "#/$defs/restProvider" + }, + "swarm": { + "$ref": "#/$defs/dockerSwarmProvider" + }, + "zooKeeper": { + "$ref": "#/$defs/zkProvider" + } + }, + "type": "object" + }, + "staticProxyProtocol": { + "additionalProperties": false, + "properties": { + "insecure": { + "type": "boolean" + }, + "trustedIPs": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + }, + "type": "object" + }, + "staticRedirectEntryPoint": { + "additionalProperties": false, + "properties": { + "permanent": { + "type": "boolean" + }, + "priority": { + "type": "integer" + }, + "scheme": { + "type": "string" + }, + "to": { + "type": "string" + } + }, + "type": "object" + }, + "staticRedirections": { + "additionalProperties": false, + "properties": { + "entryPoint": { + "$ref": "#/$defs/staticRedirectEntryPoint" + } + }, + "type": "object" + }, + "staticRespondingTimeouts": { + "additionalProperties": false, + "properties": { + "idleTimeout": { + "type": "string" + }, + "readTimeout": { + "type": "string" + }, + "writeTimeout": { + "type": "string" + } + }, + "type": "object" + }, + "staticServersTransport": { + "additionalProperties": false, + "properties": { + "forwardingTimeouts": { + "$ref": "#/$defs/staticForwardingTimeouts" + }, + "insecureSkipVerify": { + "type": "boolean" + }, + "maxIdleConnsPerHost": { + "type": "integer" + }, + "rootCAs": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "spiffe": { + "$ref": "#/$defs/staticSpiffe" + } + }, + "type": "object" + }, + "staticSpiffe": { + "additionalProperties": false, + "properties": { + "ids": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "trustDomain": { + "type": "string" + } + }, + "type": "object" + }, + "staticSpiffeClientConfig": { + "additionalProperties": false, + "properties": { + "workloadAPIAddr": { + "type": "string" + } + }, + "type": "object" + }, + "staticTCPServersTransport": { + "additionalProperties": false, + "properties": { + "dialKeepAlive": { + "type": "string" + }, + "dialTimeout": { + "type": "string" + }, + "terminationDelay": { + "type": "string" + }, + "tls": { + "$ref": "#/$defs/staticTLSClientConfig" + } + }, + "type": "object" + }, + "staticTLSClientConfig": { + "additionalProperties": false, + "properties": { + "insecureSkipVerify": { + "type": "boolean" + }, + "rootCAs": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "spiffe": { + "$ref": "#/$defs/staticSpiffe" + } + }, + "type": "object" + }, + "staticTLSConfig": { + "additionalProperties": false, + "properties": { + "certResolver": { + "type": "string" + }, + "domains": { + "items": { + "$ref": "#/$defs/typesDomain" + }, + "type": ["array", "null"] + }, + "options": { + "type": "string" + } + }, + "type": "object" + }, + "staticTracing": { + "additionalProperties": false, + "properties": { + "addInternals": { + "type": "boolean" + }, + "capturedRequestHeaders": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "capturedResponseHeaders": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "globalAttributes": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "otlp": { + "$ref": "#/$defs/typesOTelTracing" + }, + "resourceAttributes": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "safeQueryParams": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "sampleRate": { + "type": "number" + }, + "serviceName": { + "type": "string" + } + }, + "type": "object" + }, + "staticUDPConfig": { + "additionalProperties": false, + "properties": { + "timeout": { + "type": "string" + } + }, + "type": "object" + }, + "typesAccessLog": { + "additionalProperties": false, + "properties": { + "addInternals": { + "type": "boolean" + }, + "bufferingSize": { + "type": "integer" + }, + "fields": { + "$ref": "#/$defs/typesAccessLogFields" + }, + "filePath": { + "type": "string" + }, + "filters": { + "$ref": "#/$defs/typesAccessLogFilters" + }, + "format": { + "type": "string" + }, + "otlp": { + "$ref": "#/$defs/typesOTelLog" + } + }, + "type": "object" + }, + "typesAccessLogFields": { + "additionalProperties": false, + "properties": { + "defaultMode": { + "type": "string" + }, + "headers": { + "$ref": "#/$defs/typesFieldHeaders" + }, + "names": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + } + }, + "type": "object" + }, + "typesAccessLogFilters": { + "additionalProperties": false, + "properties": { + "minDuration": { + "type": "string" + }, + "retryAttempts": { + "type": "boolean" + }, + "statusCodes": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + }, + "type": "object" + }, + "typesClientTLS": { + "additionalProperties": false, + "properties": { + "ca": { + "type": "string" + }, + "cert": { + "type": "string" + }, + "insecureSkipVerify": { + "type": "boolean" + }, + "key": { + "type": "string" + } + }, + "type": "object" + }, + "typesDatadog": { + "additionalProperties": false, + "properties": { + "addEntryPointsLabels": { + "type": "boolean" + }, + "addRoutersLabels": { + "type": "boolean" + }, + "addServicesLabels": { + "type": "boolean" + }, + "address": { + "type": "string" + }, + "prefix": { + "type": "string" + }, + "pushInterval": { + "type": "string" + } + }, + "type": "object" + }, + "typesDomain": { + "additionalProperties": false, + "properties": { + "main": { + "type": "string" + }, + "sans": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + } + }, + "type": "object" + }, + "typesFieldHeaders": { + "additionalProperties": false, + "properties": { + "defaultMode": { + "type": "string" + }, + "names": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + } + }, + "type": "object" + }, + "typesHostResolverConfig": { + "additionalProperties": false, + "properties": { + "cnameFlattening": { + "type": "boolean" + }, + "resolvConfig": { + "type": "string" + }, + "resolvDepth": { + "type": "integer" + } + }, + "type": "object" + }, + "typesInfluxDB2": { + "additionalProperties": false, + "properties": { + "addEntryPointsLabels": { + "type": "boolean" + }, + "addRoutersLabels": { + "type": "boolean" + }, + "addServicesLabels": { + "type": "boolean" + }, + "additionalLabels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "address": { + "type": "string" + }, + "bucket": { + "type": "string" + }, + "org": { + "type": "string" + }, + "pushInterval": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "type": "object" + }, + "typesMetrics": { + "additionalProperties": false, + "properties": { + "addInternals": { + "type": "boolean" + }, + "datadog": { + "$ref": "#/$defs/typesDatadog" + }, + "influxDB2": { + "$ref": "#/$defs/typesInfluxDB2" + }, + "otlp": { + "$ref": "#/$defs/typesOTLP" + }, + "prometheus": { + "$ref": "#/$defs/typesPrometheus" + }, + "statsD": { + "$ref": "#/$defs/typesStatsd" + } + }, + "type": "object" + }, + "typesOTLP": { + "additionalProperties": false, + "properties": { + "addEntryPointsLabels": { + "type": "boolean" + }, + "addRoutersLabels": { + "type": "boolean" + }, + "addServicesLabels": { + "type": "boolean" + }, + "explicitBoundaries": { + "items": { + "type": "number" + }, + "type": ["array", "null"] + }, + "grpc": { + "$ref": "#/$defs/typesOTelGRPC" + }, + "http": { + "$ref": "#/$defs/typesOTelHTTP" + }, + "pushInterval": { + "type": "string" + }, + "serviceName": { + "type": "string" + } + }, + "type": "object" + }, + "typesOTelGRPC": { + "additionalProperties": false, + "properties": { + "endpoint": { + "type": "string" + }, + "headers": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "insecure": { + "type": "boolean" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + } + }, + "type": "object" + }, + "typesOTelHTTP": { + "additionalProperties": false, + "properties": { + "endpoint": { + "type": "string" + }, + "headers": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "tls": { + "$ref": "#/$defs/typesClientTLS" + } + }, + "type": "object" + }, + "typesOTelLog": { + "additionalProperties": false, + "properties": { + "grpc": { + "$ref": "#/$defs/typesOTelGRPC" + }, + "http": { + "$ref": "#/$defs/typesOTelHTTP" + }, + "resourceAttributes": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "serviceName": { + "type": "string" + } + }, + "type": "object" + }, + "typesOTelTracing": { + "additionalProperties": false, + "properties": { + "grpc": { + "$ref": "#/$defs/typesOTelGRPC" + }, + "http": { + "$ref": "#/$defs/typesOTelHTTP" + } + }, + "type": "object" + }, + "typesPrometheus": { + "additionalProperties": false, + "properties": { + "addEntryPointsLabels": { + "type": "boolean" + }, + "addRoutersLabels": { + "type": "boolean" + }, + "addServicesLabels": { + "type": "boolean" + }, + "buckets": { + "items": { + "type": "number" + }, + "type": ["array", "null"] + }, + "entryPoint": { + "type": "string" + }, + "headerLabels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "manualRouting": { + "type": "boolean" + } + }, + "type": "object" + }, + "typesStatsd": { + "additionalProperties": false, + "properties": { + "addEntryPointsLabels": { + "type": "boolean" + }, + "addRoutersLabels": { + "type": "boolean" + }, + "addServicesLabels": { + "type": "boolean" + }, + "address": { + "type": "string" + }, + "prefix": { + "type": "string" + }, + "pushInterval": { + "type": "string" + } + }, + "type": "object" + }, + "typesTraefikLog": { + "additionalProperties": false, + "properties": { + "compress": { + "type": "boolean" + }, + "filePath": { + "type": "string" + }, + "format": { + "type": "string" + }, + "level": { + "type": "string" + }, + "maxAge": { + "type": "integer" + }, + "maxBackups": { + "type": "integer" + }, + "maxSize": { + "type": "integer" + }, + "noColor": { + "type": "boolean" + }, + "otlp": { + "$ref": "#/$defs/typesOTelLog" + } + }, + "type": "object" + }, + "zkProvider": { + "additionalProperties": false, + "properties": { + "endpoints": { + "items": { + "type": "string" + }, + "type": ["array", "null"] + }, + "password": { + "type": "string" + }, + "rootKey": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "type": "object" + } + }, + "title": "Traefik v3 Static Configuration", + "properties": { + "accessLog": { + "$ref": "#/$defs/typesAccessLog" + }, + "api": { + "$ref": "#/$defs/staticAPI" + }, + "certificatesResolvers": { + "additionalProperties": { + "$ref": "#/$defs/staticCertificateResolver" + }, + "type": "object" + }, + "core": { + "$ref": "#/$defs/staticCore" + }, + "entryPoints": { + "additionalProperties": { + "$ref": "#/$defs/staticEntryPoint" + }, + "type": "object" + }, + "experimental": { + "$ref": "#/$defs/staticExperimental" + }, + "global": { + "$ref": "#/$defs/staticGlobal" + }, + "hostResolver": { + "$ref": "#/$defs/typesHostResolverConfig" + }, + "log": { + "$ref": "#/$defs/typesTraefikLog" + }, + "metrics": { + "$ref": "#/$defs/typesMetrics" + }, + "ping": { + "$ref": "#/$defs/pingHandler" + }, + "providers": { + "$ref": "#/$defs/staticProviders" + }, + "serversTransport": { + "$ref": "#/$defs/staticServersTransport" + }, + "spiffe": { + "$ref": "#/$defs/staticSpiffeClientConfig" + }, + "tcpServersTransport": { + "$ref": "#/$defs/staticTCPServersTransport" + }, + "tracing": { + "$ref": "#/$defs/staticTracing" + } + }, + "type": "object" +}