Documentation
¶
Overview ¶
Package sandboxrender turns an EmbeddedSandboxTemplate + overrides into the concrete Pool spec consumed by the SandboxPool controller.
Callers are:
- SandboxEnv Reconciler (renders member pools from the Template + overrides)
- any other path that needs to apply pool-level overrides on top of a template snapshot
The package intentionally returns plain errors (no domain.AppError) so the controller layer can use it without taking a service-package dependency; HTTP-layer callers wrap into domain.AppError at the boundary.
Index ¶
- Constants
- func Apply(emb *agentsv1alpha1.EmbeddedSandboxTemplate, opts Options) error
- func RewriteImageForCluster(image, currentClusterID string, store RegistryStore) string
- func ValidateContainerImage(image string) error
- func VolumeNameFor(claimName string, readOnly bool) string
- type Options
- type RegistryRewrite
- type RegistryStore
- type RewriteSkipReason
Constants ¶
const ReservedVolumeNamePrefix = agentsv1alpha1.ReservedVolumeNamePrefix
ReservedVolumeNamePrefix namespaces every volume this renderer injects.
Defined in the API package because rejecting a Template that uses the prefix is part of the API contract; re-exported here so renderer callers do not have to reach for the API package for a naming detail.
Variables ¶
This section is empty.
Functions ¶
func Apply ¶
func Apply(emb *agentsv1alpha1.EmbeddedSandboxTemplate, opts Options) error
Apply mutates emb in place by applying opts.
Errors are deterministic input-validation failures — the caller should surface them as 400 Bad Request. Apply does NOT mutate emb if it returns a non-nil error (best-effort: validation runs before mutation per field).
func RewriteImageForCluster ¶ added in v0.0.10
func RewriteImageForCluster(image, currentClusterID string, store RegistryStore) string
RewriteImageForCluster rewrites the registry host of image when the image belongs to a private registry owned by a different cluster.
Rewrite rules:
- Parse the image reference to extract its registry host.
- Look up the host in the store. If not found → public registry, return as-is.
- If the owning cluster equals currentClusterID → already local, return as-is.
- Find a registry of the same Type in currentClusterID. If none found → warn and return as-is (never block the request).
- Replace the registry host prefix and return the rewritten image.
The operation is idempotent: after a successful rewrite the host belongs to currentClusterID, so rule 3 short-circuits a second call.
Only the host prefix is replaced — repository path, tag and digest are preserved verbatim. Rewriting a public image into a mirror that inserts a path prefix is therefore out of scope (see RegistryEntry.Host, which forbids a path component).
func ValidateContainerImage ¶
ValidateContainerImage checks that image is a syntactically valid Docker/OCI image reference (e.g. "nginx:1.25", "ghcr.io/org/repo@sha256:abc..."). Empty strings are silently accepted (callers skip empty images before calling this).
func VolumeNameFor ¶ added in v0.0.10
VolumeNameFor derives the corev1.Volume name for one volume *source*.
The name is:
- deterministic — the revision hash depends on it, so it must not vary between renders of the same input;
- DNS-1123 label safe and at most 63 characters;
- distinct for the read-only and read-write forms of the same claim, which must be two separate volumes because readOnly lives on the volume source.
The digest is taken over the raw claim name so two claims that differ only in a character the sanitiser folds (e.g. "a.b" and "a-b") cannot collide.
Types ¶
type Options ¶
type Options struct {
// Image overrides containers[0].image. Empty = no-op.
Image string
// InlineResources, when non-nil, replaces containers[0].resources with
// the given ResourceRequirements. Used when a Member declares its own
// resource sizing independent of the Template. Future work: when an
// InstanceType catalog provider is wired in, the Reconciler will
// resolve InstanceType + Multiplier to ResourceRequirements before
// calling Apply, so this field stays the single resource-sizing knob
// the renderer consumes.
InlineResources *corev1.ResourceRequirements
// Volumes are the Env-level PVC mounts. Grouped into corev1.Volume entries
// by volume source (claimName + readOnly) and appended to
// containers[0].volumeMounts only — never to init containers, and never to
// an injected sidecar, which may hold brokered credentials.
Volumes []agentsv1alpha1.EnvVolumeMount
// ImageRegistry, when non-nil, supplies per-cluster registry rewriting.
// Whether it is applied is decided by RewriteImages.
ImageRegistry *RegistryRewrite
// RewriteImages turns rewriting on for every image this render produces:
// the Template's own (IdleImage, containers, initContainers) and the
// caller-supplied Image override. Ignored when ImageRegistry is nil.
//
// Opt-in, and deliberately covering the override too. The rewrite is a bare
// registry-host swap, so only the Template author knows whether the same
// repository path exists in every region's mirror — and an Env that
// deliberately points its override at another region's registry (because
// that is where the image lives) must not have it silently redirected to a
// mirror that may not carry it. The failure would surface minutes later as
// ImagePullBackOff on the next claim, not as an error on write.
RewriteImages bool
}
Options is the render-input for Apply. Caller composes the values from whatever source-of-truth they have (e.g. Env-level overrides for Image, Member-level InlineResources for per-Pool sizing).
func (Options) Empty ¶
Empty returns true when Options carries no observable effect; callers can use this to skip rendering when no overrides apply.
Every field must be represented here. Forgetting one means an Env whose only override is that field renders to nothing and the feature silently no-ops.
type RegistryRewrite ¶ added in v0.0.10
type RegistryRewrite struct {
// LocalClusterID is the cluster the rendered Pool will run in. Empty
// disables rewriting (the operator was started without --local-cluster-id).
LocalClusterID string
// Store resolves registry hosts to owning clusters and back. Nil disables
// rewriting.
Store RegistryStore
}
RegistryRewrite carries everything needed to rewrite an image to the local cluster's registry. A nil *RegistryRewrite means "do not rewrite".
func (*RegistryRewrite) Rewrite ¶ added in v0.0.10
func (r *RegistryRewrite) Rewrite(image string) string
Rewrite returns image rewritten to the local cluster's registry, or image unchanged when r is nil or the rewrite does not apply. Safe on a nil receiver so callers can hold an unconditional *RegistryRewrite field.
type RegistryStore ¶ added in v0.0.10
type RegistryStore interface {
LookupRegistry(host string) (clusterID, typ string, ok bool)
RegistryForType(clusterID, typ string) (host string, ok bool)
}
RegistryStore is the subset of cluster.Store used by RewriteImageForCluster. Extracted as an interface so tests can inject a lightweight fake without depending on the full Store implementation.
This interface lives here rather than in the apiserver service package so the renderer can rewrite template-owned images without the renderer's callers (pkg/controllers/...) taking a dependency on pkg/apiserver/service — that direction is an import cycle, since the service package depends on the renderer through envmember/poolrender.
type RewriteSkipReason ¶ added in v0.0.10
type RewriteSkipReason string
RewriteSkipReason classifies why RewriteImageForCluster left an image unchanged. It exists so callers can distinguish the benign cases (a public image, or an image already local) from the one that will surface minutes later as ImagePullBackOff: the image belongs to a peer cluster's registry and this cluster has no counterpart to rewrite it to.
const ( // RewriteApplied means the image was rewritten. RewriteApplied RewriteSkipReason = "applied" // RewriteSkipNotApplicable covers empty input, a disabled rewriter, an // unparseable reference, an implicit Docker Hub name, an unknown (public) // registry host, and an image already owned by the local cluster. RewriteSkipNotApplicable RewriteSkipReason = "not_applicable" // RewriteSkipNoLocalRegistry means the host is a known peer cluster's // registry but the local cluster declares no registry of the same Type. // The image is kept as-is and will be pulled cross-region, if at all. RewriteSkipNoLocalRegistry RewriteSkipReason = "no_local_registry" )
func ClassifyRewrite ¶ added in v0.0.10
func ClassifyRewrite(image, currentClusterID string, store RegistryStore) RewriteSkipReason
ClassifyRewrite reports what RewriteImageForCluster would do with image, without performing the rewrite. Used for metrics and for warning events.