Documentation
¶
Overview ¶
Package traefik implements subdomain and path routing with TLS.
Built last, deliberately: it is the second implementation of the routing interface, and building it is the test of whether that abstraction holds. If Traefik requires changing the interface, the interface was wrong.
The generated config points at Pando's proxy, never at the workload — the workload address is right there and would appear to work, which is exactly the trap.
Package traefik routes apps through a Traefik edge (R-160, R-164, R-165).
Traefik sits in front of Pando and forwards to Pando's proxy. It never points at a workload, and that is the single most important thing about this file. R-023 makes Pando's proxy the only enforcement point for every request to every app; a Traefik router pointing straight at a container would be a path to an app that skips authorization entirely, and it would work, which is why the instinct to do it is dangerous. `RouteRequest.ProxyUpstream` is in the request precisely so an adapter is *told* where to point rather than discovering it.
Configuration is written as Traefik's file provider — one YAML file per app in a watched directory. Chosen over the Docker label provider because labels live on the workload container, which would mean this adapter reaching into the runtime adapter's objects: two adapters owning one thing, and a route that disappears when a deploy recreates the container.
Index ¶
- Constants
- func Info() api.KindInfo
- type Adapter
- func (a *Adapter) Capabilities(context.Context) (api.RoutingCapabilities, error)
- func (a *Adapter) Category() api.Category
- func (a *Adapter) Configure(_ context.Context, raw json.RawMessage) error
- func (a *Adapter) Edge(ctx context.Context, r api.EdgeRequest) (api.EdgePlan, bool, error)
- func (a *Adapter) Ensure(ctx context.Context, r api.RouteRequest) (api.RouteHandle, error)
- func (a *Adapter) HealthCheck(ctx context.Context) error
- func (a *Adapter) Kind() string
- func (a *Adapter) Observe(ctx context.Context, h api.RouteHandle) (api.RouteState, error)
- func (a *Adapter) Remove(ctx context.Context, h api.RouteHandle) error
- type Config
Constants ¶
const ( DeliveryKubernetesAPI = string(api.EdgeConfigKubernetesAPI) )
Ways the adapter's routes reach Traefik.
const ( CertsNone = "none" CertsHTTP = "http" CertsDNS = "dns" )
Certificate modes.
const DefaultImage = "traefik:v3.7.15"
DefaultImage is the Traefik this release of Pando runs.
const Kind = "traefik"
Kind is the adapter's kind string.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Adapter ¶
type Adapter struct {
// contains filtered or unexported fields
}
Adapter writes Traefik file-provider configuration, and by default describes the Traefik Pando runs to read it (R-174, managed.go).
func (*Adapter) Capabilities ¶
Capabilities: subdomain and path, with TLS when certificates are configured.
SupportsWildcardTLS is true only for a Traefik Pando runs with DNS-01: a wildcard needs a DNS provider's credentials, and a Traefik somebody else runs may or may not have them — this adapter cannot see. Saying yes without them would produce a plan that succeeds and an app nobody can reach over HTTPS.
func (*Adapter) Edge ¶
Edge describes the Traefik Pando runs, and routes every hostname that is not an app's to the console. A Traefik somebody else runs has no edge, and the console route is withdrawn: that Traefik's other hostnames are not Pando's.
func (*Adapter) Ensure ¶
func (a *Adapter) Ensure(ctx context.Context, r api.RouteRequest) (api.RouteHandle, error)
Ensure writes the router for an app.
Idempotent by construction: the file is named for the app and rewritten whole, so applying the same route twice leaves the same file. The reconciler calls this on every pass and must not accumulate anything.
func (*Adapter) HealthCheck ¶
HealthCheck verifies the configuration directory is writable.
Not whether Traefik is running: Pando does not manage Traefik and cannot see it. What it can check is the one thing it is responsible for — that a route it writes will land somewhere Traefik reads. A directory that has become read-only produces routes that silently never appear, which is the failure this catches.
func (*Adapter) Observe ¶
func (a *Adapter) Observe(ctx context.Context, h api.RouteHandle) (api.RouteState, error)
Observe reports whether the route file is there.
It reports what exists and never remediates — the reconciler decides what to do about drift (design 05). An adapter that quietly rewrote a missing file here would make drift undetectable.
type Config ¶
type Config struct {
// Managed means Pando runs Traefik itself (R-174): the default. False is
// a Traefik somebody else runs, which Pando only writes route files for —
// an install that already has Traefik on :80 and :443 for other things.
// A pointer so an unset value is the default rather than false.
Managed *bool `json:"managed,omitempty"`
// Delivery is how routes reach Traefik: shared_mount, files in Dir, which
// Traefik mounts (Docker, the default); or kubernetes_api, IngressRoute
// objects in Namespace (the Kubernetes runtime, kubernetes.go). Core says
// which the runtime offers, and Edge refuses a mismatch.
Delivery string `json:"delivery,omitempty"`
// Namespace holds the IngressRoutes, with delivery kubernetes_api.
Namespace string `json:"namespace,omitempty"`
// Kubeconfig connects to the cluster from outside it, with delivery
// kubernetes_api. Empty is the cluster Pando runs in.
Kubeconfig string `json:"kubeconfig,omitempty"`
// APIQPS and APIBurst limit the requests a second made to the cluster's
// API with delivery kubernetes_api, and how many may be made at once
// above that. Unset, client-go allows 5 and 10.
APIQPS int `json:"api_qps,omitempty"`
APIBurst int `json:"api_burst,omitempty"`
// Dir is the directory Traefik's file provider watches. Pando writes one
// file per app here and Traefik picks them up; there is no API call and no
// reload signal.
Dir string `json:"dir"`
// BaseDomain is what a subdomain app's hostname is carved out of, when the
// route request does not carry one.
BaseDomain string `json:"base_domain,omitempty"`
// For a Traefik somebody else runs: the entrypoint routers attach to and
// the ACME resolver it has configured. Empty CertResolver means Pando asks
// for no certificate and Traefik serves whatever it already has — the
// honest behavior when issuance is the edge's business (O-5). A Traefik
// Pando runs has its own entrypoints and resolver, and ignores both.
EntryPoint string `json:"entrypoint,omitempty"`
CertResolver string `json:"cert_resolver,omitempty"`
// Image is the Traefik image. Pinned by Pando's release; set to override.
Image string `json:"image,omitempty"`
// HTTPPort and HTTPSPort are the host ports Traefik takes.
HTTPPort int `json:"http_port,omitempty"`
HTTPSPort int `json:"https_port,omitempty"`
// ConsoleHostname is the hostname the console is served on over HTTPS.
// Every hostname that is not an app's reaches the console anyway; this is
// the one a certificate is asked for on its behalf.
ConsoleHostname string `json:"console_hostname,omitempty"`
// Certificates is how Traefik gets them (R-169): "http" (HTTP-01, per
// hostname), "dns" (DNS-01, a wildcard for the base domain), or "none".
// Neither challenge is a silent default: none serves plain HTTP on :80,
// and the adapter says so.
Certificates string `json:"certificates,omitempty"`
// ACMEEmail is the address Let's Encrypt registers the account to.
ACMEEmail string `json:"acme_email,omitempty"`
// DNSProvider is the DNS-01 provider's code, as Traefik names it.
DNSProvider string `json:"dns_provider,omitempty"`
// Credentials arrive from encrypted storage (R-190), never from config.
Credentials struct {
// DNS is the provider's credentials as KEY=value lines, one per line.
DNS string `json:"dns_credentials,omitempty"`
} `json:"credentials,omitempty"`
}
Config is the adapter's configuration.