k8s

package
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package k8s resolves cadish `k8s://service.namespace:port` upstream targets to the live set of ready pod IP:port endpoints via the Kubernetes API (EndpointSlices), using a client-go SharedInformer with a warm local cache and event-driven re-resolution. It is built lazily — only when a loaded Cadishfile actually contains a k8s:// target — so a non-Kubernetes cadish pays nothing.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewClientset

func NewClientset(opts Options) (kubernetes.Interface, error)

NewClientset builds just the typed clientset with real auth (in-cluster, else kubeconfig), without any informers. The ingress controller (which builds its own informer factories from the clientset) uses this to avoid constructing an unused EndpointSlice factory.

func RESTConfig

func RESTConfig(kubeconfig string) (*rest.Config, error)

RESTConfig resolves auth (explicit kubeconfig, else in-cluster, else KUBECONFIG / ~/.kube/config) and returns the rest.Config. The Gateway API controller uses it to build its own gateway-api typed clientset over the SAME auth as the core clientset, keeping this package the single owner of auth resolution.

Types

type CertPEM added in v0.2.3

type CertPEM struct {
	Cert, Key []byte
	Leaf      *x509.Certificate
}

CertPEM is a validated BYO keypair (the raw Secret bytes) plus the parsed leaf, threaded from the per-reconcile validation gate to injection so the keypair is read and parsed once.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client wraps a clientset and a SharedInformerFactory over EndpointSlices and Services, exposing a warm EndpointCache and an event-poke fan-out. (The Service informer exists to translate a numeric port reference to a multi-port Service into the right EndpointSlice port, which slices key by NAME only — CAD-11.)

func NewClient

func NewClient(opts Options) (*Client, error)

NewClient builds a Client with real auth (in-cluster, else kubeconfig).

func NewClientWithInterface

func NewClientWithInterface(cs kubernetes.Interface, opts Options) *Client

NewClientWithInterface builds a Client over an injected clientset (the test seam for fake.NewSimpleClientset).

func (*Client) Cache

func (c *Client) Cache() *EndpointCache

Cache returns the warm endpoint cache.

func (*Client) Clientset

func (c *Client) Clientset() kubernetes.Interface

Clientset returns the underlying typed clientset. The ingress controller (Layer 2) builds its own SharedInformerFactory from this one clientset to add the networking/secret/configmap informers, reusing Layer 1's API connection.

func (*Client) Close

func (c *Client) Close()

Close stops the informers (idempotent).

func (*Client) Factory

func (c *Client) Factory() informers.SharedInformerFactory

Factory returns the EndpointSlice SharedInformerFactory. (The ingress controller builds a SEPARATE factory for its own informers because this one is already started for EndpointSlices and informers must be registered before Start.)

func (*Client) OnServiceChange

func (c *Client) OnServiceChange(fn func(namespace, service string)) (cancel func())

OnServiceChange registers fn for endpoint-change pokes and returns a cancel func that DEREGISTERS it (FIX 4). Registration is keyed by an opaque token, so a pool that is rebuilt (k8s:// fingerprint change) can remove its listener instead of leaking it — the append-only registry previously pinned every dead *lb.Upstream forever. Safe to call before or during Start (the RLock/copy in fire keeps the fan-out race-clean); the returned cancel is idempotent.

func (*Client) Resolver

func (c *Client) Resolver() lb.EndpointResolver

Resolver returns an lb.EndpointResolver backed by this client's warm cache and event fan-out.

func (*Client) Start

func (c *Client) Start(ctx context.Context) error

Start runs the informers and blocks until caches sync or SyncTimeout elapses. It is guarded by a sync.Once: only the first call registers the event handler and starts the factory; a second call is a no-op that replays the first call's error (so re-registering the event handler / re-starting the factory can never double-fire pokes).

type EndpointCache

type EndpointCache struct {
	// contains filtered or unexported fields
}

EndpointCache resolves (namespace, service, port) to ready pod endpoints by reading the warm EndpointSlice informer cache (no API call per resolve). Named ports are mapped to numbers from the slices' own port list; a NUMERIC reference to a MULTI-port Service is first translated to the Service port's name via the warm Service informer cache (CAD-11), because slices key ports by name only.

func (*EndpointCache) Endpoints

func (c *EndpointCache) Endpoints(namespace, service, port string) ([]lb.Endpoint, error)

Endpoints returns the ready endpoints for service in namespace at port (a number passed through, or a named port resolved via the slice's port list). It unions across the service's EndpointSlices and de-duplicates by IP:port.

type Options

type Options struct {
	Kubeconfig  string
	SyncTimeout time.Duration
}

Options configures the K8s client. Kubeconfig empty ⇒ in-cluster first, then KUBECONFIG, then ~/.kube/config.

type TLSSecretGate added in v0.2.3

type TLSSecretGate struct {
	// contains filtered or unexported fields
}

TLSSecretGate validates each referenced kubernetes.io/tls Secret ONCE per reconcile. It is the single implementation shared by the Ingress and Gateway controllers (formerly a verbatim-duplicated `tlsSecretGate` in each): Usable parses tls.crt/tls.key and reports whether it is a usable keypair; Covers answers per-host SAN coverage (F10) from the cached leaf. A present-but-CORRUPT Secret is reported UNUSABLE, so its host falls through to ACME issuance (design D61: "absent OR unusable → ACME") rather than being classified BYO and left dark. The validated PEM is cached in `good` and reused by injection (no re-read, no re-parse); `bad` records present-but-unparseable Secrets for warning Events.

func NewTLSSecretGate added in v0.2.3

func NewTLSSecretGate(sec corelisters.SecretLister) *TLSSecretGate

NewTLSSecretGate builds a gate reading Secrets from sec.

func (*TLSSecretGate) Bad added in v0.2.3

func (g *TLSSecretGate) Bad() map[string]string

Bad returns the map of present-but-corrupt Secrets (ns/name → parse error) so the controller can surface warning Events. The returned map is the gate's own; treat it as read-only.

func (*TLSSecretGate) Covers added in v0.2.3

func (g *TLSSecretGate) Covers(ns, name, host string) bool

Covers reports whether the Secret ns/name's certificate SANs cover host (F10). It is only ever consulted for a Secret the gate already classified usable (its leaf is in `good`), so a cache miss (or a nil leaf) reports false → the host is treated as not covered and falls back to ACME. x509.Certificate.VerifyHostname implements SAN matching (including single-label "*.suffix" wildcards).

func (*TLSSecretGate) Good added in v0.2.3

func (g *TLSSecretGate) Good(ns, name string) (CertPEM, bool)

Good returns the validated keypair for ns/name (ok=false when the Secret was never classified usable this reconcile). Injection uses it to avoid a Secret re-read.

func (*TLSSecretGate) Usable added in v0.2.3

func (g *TLSSecretGate) Usable(ns, name string) bool

Usable reports whether ns/name is an existing Secret carrying a PARSEABLE TLS keypair. It is memoized so a Secret referenced by several Ingresses/listeners is parsed only once. A missing, non-TLS, or corrupt Secret reports false (→ the host falls back to ACME).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL