Documentation
¶
Overview ¶
Package stores provides abstractions for accessing and composing resource stores.
Package stores provides abstractions for accessing and composing resource stores.
This package defines:
- StoreProvider: Interface for accessing stores by name
- RealStoreProvider: Implementation that returns actual stores
- CompositeStoreProvider: Implementation that overlays proposed changes on real stores
- ValidationContext: Unified container for K8s and HTTP overlays
- OverlayStoreProvider: Implementation that applies ValidationContext overlays
These abstractions enable "what if" scenarios by allowing components to render and validate configurations with proposed changes without modifying actual state.
Index ¶
- type CompositeStore
- func (s *CompositeStore) Add(_ interface{}, _ []string) error
- func (s *CompositeStore) Clear() error
- func (s *CompositeStore) Delete(_ ...string) error
- func (s *CompositeStore) Get(keys ...string) ([]interface{}, error)
- func (s *CompositeStore) List() ([]interface{}, error)
- func (s *CompositeStore) Update(_ interface{}, _ []string) error
- type CompositeStoreProvider
- type ContentOverlay
- type GenericStoreGetter
- type HTTPContentOverlay
- type KeyExtractor
- type ModCounter
- type OverlayStoreProvider
- type ReadOnlyStoreError
- type RealStoreProvider
- type Store
- type StoreOverlay
- type StoreProvider
- type StoreProviderFunc
- type TypesStoreAdapter
- func (a *TypesStoreAdapter) Add(resource interface{}, keys []string) error
- func (a *TypesStoreAdapter) Clear() error
- func (a *TypesStoreAdapter) Delete(keys ...string) error
- func (a *TypesStoreAdapter) Get(keys ...string) ([]interface{}, error)
- func (a *TypesStoreAdapter) List() ([]interface{}, error)
- func (a *TypesStoreAdapter) ModCount() (uint64, bool)
- func (a *TypesStoreAdapter) Update(resource interface{}, keys []string) error
- type ValidationContext
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CompositeStore ¶
type CompositeStore struct {
// contains filtered or unexported fields
}
CompositeStore wraps a base store with an overlay, providing a unified view that reflects both the actual state and proposed changes.
Read operations (Get, List) return the merged view. Write operations are not supported and will return an error.
Thread Safety ¶
CompositeStore itself is not thread-safe, but this is by design:
- A new CompositeStore is created for each validation request (not shared across goroutines)
- The base store must be thread-safe (k8s.Store uses sync.RWMutex internally)
- The overlay must not be modified after construction (immutable during validation)
This design avoids synchronization overhead since each request gets its own instance.
func NewCompositeStore ¶
func NewCompositeStore(base Store, overlay *StoreOverlay) *CompositeStore
NewCompositeStore creates a new CompositeStore.
Parameters:
- base: The underlying store with actual state
- overlay: The proposed changes to apply on top
func NewCompositeStoreWithKeyExtractor ¶
func NewCompositeStoreWithKeyExtractor(base Store, overlay *StoreOverlay, keyExtractor KeyExtractor) *CompositeStore
NewCompositeStoreWithKeyExtractor creates a new CompositeStore with a key extractor.
The key extractor is needed for stores that use multi-key indexing. Without it, additions and modifications cannot be properly matched with Get() queries.
func (*CompositeStore) Add ¶
func (s *CompositeStore) Add(_ interface{}, _ []string) error
Add is not supported on CompositeStore. CompositeStore is read-only; modifications should be made through the overlay.
func (*CompositeStore) Clear ¶
func (s *CompositeStore) Clear() error
Clear is not supported on CompositeStore. CompositeStore is read-only; modifications should be made through the overlay.
func (*CompositeStore) Delete ¶
func (s *CompositeStore) Delete(_ ...string) error
Delete is not supported on CompositeStore. CompositeStore is read-only; modifications should be made through the overlay.
func (*CompositeStore) Get ¶
func (s *CompositeStore) Get(keys ...string) ([]interface{}, error)
Get returns resources matching the given keys.
The result includes:
- Resources from the base store (excluding deletions)
- Modifications (replacing base resources with same keys)
- Additions that match the keys
func (*CompositeStore) List ¶
func (s *CompositeStore) List() ([]interface{}, error)
List returns all resources from the merged view.
func (*CompositeStore) Update ¶
func (s *CompositeStore) Update(_ interface{}, _ []string) error
Update is not supported on CompositeStore. CompositeStore is read-only; modifications should be made through the overlay.
type CompositeStoreProvider ¶
type CompositeStoreProvider struct {
// contains filtered or unexported fields
}
CompositeStoreProvider wraps a base StoreProvider with overlays.
When GetStore is called, if an overlay exists for that store name, a CompositeStore is returned that applies the overlay on top of the base store. Otherwise, the base store is returned unchanged.
This enables "what if" scenarios: render and validate with proposed changes without modifying the actual stores.
func NewCompositeStoreProvider ¶
func NewCompositeStoreProvider(base StoreProvider, overlays map[string]*StoreOverlay) *CompositeStoreProvider
NewCompositeStoreProvider creates a new CompositeStoreProvider.
Parameters:
- base: The underlying store provider
- overlays: Map of store name to overlay (proposed changes)
func (*CompositeStoreProvider) GetStore ¶
func (p *CompositeStoreProvider) GetStore(name string) Store
GetStore returns a store for the given name.
If an overlay exists for this store, returns a CompositeStore that applies the overlay on top of the base store. Otherwise, returns the base store unchanged.
func (*CompositeStoreProvider) StoreNames ¶
func (p *CompositeStoreProvider) StoreNames() []string
StoreNames returns the names of all available stores. This includes stores from the base provider plus any overlay-only stores.
func (*CompositeStoreProvider) Validate ¶
func (p *CompositeStoreProvider) Validate() error
Validate checks that all overlays reference valid stores. Returns an error if any overlay references a store that doesn't exist in the base provider.
type ContentOverlay ¶
type ContentOverlay interface {
// IsEmpty returns true if the overlay contains no pending changes.
IsEmpty() bool
}
ContentOverlay is a marker interface for overlay types.
Both K8s overlays (StoreOverlay) and HTTP overlays implement this interface, enabling unified handling in validation pipelines.
type GenericStoreGetter ¶
GenericStoreGetter is an interface for types that can provide stores by name. It matches the signature of resourcestore.Manager.GetStore().
type HTTPContentOverlay ¶
type HTTPContentOverlay interface {
ContentOverlay
// GetContent returns content for the given URL.
// Returns pending content if available, otherwise accepted content.
GetContent(url string) (string, bool)
// PendingURLs returns the list of URLs with pending content.
PendingURLs() []string
// HasPendingURL returns true if the given URL has pending content.
HasPendingURL(url string) bool
}
HTTPContentOverlay represents HTTP content changes awaiting validation.
This interface abstracts the HTTP overlay to avoid circular imports between pkg/stores and pkg/httpstore. The httpstore.HTTPOverlay type implements this.
type KeyExtractor ¶
KeyExtractor extracts index keys from a resource. The keys are used to index resources in the store.
type ModCounter ¶
type ModCounter interface {
// ModCount returns the modification counter and whether tracking is supported.
// The counter is incremented on every mutation (Add, Update, Delete, Clear).
// Returns (count, true) if tracking is supported, (0, false) otherwise.
ModCount() (uint64, bool)
}
ModCounter is an optional interface for stores that track modifications. Stores implementing this interface enable caching layers to detect changes without polling or re-processing all data.
The bool return value indicates whether modification tracking is supported. If supported=false, callers MUST NOT cache based on the returned count, as the store may change without the count changing.
type OverlayStoreProvider ¶
type OverlayStoreProvider struct {
// contains filtered or unexported fields
}
OverlayStoreProvider applies ValidationContext overlays to a base provider.
Unlike CompositeStoreProvider which only handles K8s overlays, this provider also exposes HTTP overlay for use by the render service.
Usage:
ctx := NewValidationContext(k8sOverlays).WithHTTPOverlay(httpOverlay)
provider := NewOverlayStoreProvider(baseProvider, ctx)
// K8s stores automatically have overlays applied
store := provider.GetStore("ingress") // Returns CompositeStore if overlay exists
// HTTP overlay is accessible for render service
httpOverlay := provider.GetHTTPOverlay() // Returns HTTPContentOverlay
func NewOverlayStoreProvider ¶
func NewOverlayStoreProvider(base StoreProvider, context *ValidationContext) *OverlayStoreProvider
NewOverlayStoreProvider creates a provider that applies ValidationContext overlays.
Parameters:
- base: The underlying store provider
- context: ValidationContext containing K8s and/or HTTP overlays
If context is nil, behaves identically to the base provider.
func (*OverlayStoreProvider) GetHTTPOverlay ¶
func (p *OverlayStoreProvider) GetHTTPOverlay() HTTPContentOverlay
GetHTTPOverlay returns the HTTP content overlay from the ValidationContext.
Returns nil if:
- ValidationContext is nil
- No HTTP overlay was set
The render service uses this to determine whether to include pending HTTP content.
func (*OverlayStoreProvider) GetStore ¶
func (p *OverlayStoreProvider) GetStore(name string) Store
GetStore returns a store for the given name.
If a K8s overlay exists for this store in the ValidationContext, returns a CompositeStore that applies the overlay on top of the base store. Otherwise, returns the base store unchanged.
func (*OverlayStoreProvider) IsValidationMode ¶
func (p *OverlayStoreProvider) IsValidationMode() bool
IsValidationMode returns true if this provider has a non-empty ValidationContext.
This can be used by components to detect whether they're rendering for validation (with proposed changes) vs production (with actual state).
func (*OverlayStoreProvider) StoreNames ¶
func (p *OverlayStoreProvider) StoreNames() []string
StoreNames returns the names of all available stores.
func (*OverlayStoreProvider) Validate ¶
func (p *OverlayStoreProvider) Validate() error
Validate checks that all K8s overlays reference valid stores. Returns an error if any overlay references a store that doesn't exist in the base provider.
type ReadOnlyStoreError ¶
type ReadOnlyStoreError struct {
Operation string
}
ReadOnlyStoreError indicates an attempt to modify a read-only store.
func (*ReadOnlyStoreError) Error ¶
func (e *ReadOnlyStoreError) Error() string
type RealStoreProvider ¶
type RealStoreProvider struct {
// contains filtered or unexported fields
}
RealStoreProvider provides access to actual (non-overlaid) stores.
This is the default implementation used during normal reconciliation.
func NewRealStoreProvider ¶
func NewRealStoreProvider(stores map[string]Store) *RealStoreProvider
NewRealStoreProvider creates a new RealStoreProvider with the given stores.
func (*RealStoreProvider) GetStore ¶
func (p *RealStoreProvider) GetStore(name string) Store
GetStore returns the store for the given name.
func (*RealStoreProvider) StoreNames ¶
func (p *RealStoreProvider) StoreNames() []string
StoreNames returns the names of all available stores.
type Store ¶
type Store interface {
// Get retrieves all resources matching the provided index keys.
Get(keys ...string) ([]interface{}, error)
// List returns all resources in the store.
List() ([]interface{}, error)
// Add inserts a new resource into the store with the provided index keys.
Add(resource interface{}, keys []string) error
// Update modifies an existing resource in the store.
Update(resource interface{}, keys []string) error
// Delete removes a resource from the store using its index keys.
Delete(keys ...string) error
// Clear removes all resources from the store.
Clear() error
}
Store defines the interface for storing and retrieving indexed resources.
This interface mirrors pkg/k8s/Store but is defined here to maintain package independence. Go's implicit interface satisfaction means any type implementing these methods (like k8s/Store) automatically satisfies this.
type StoreOverlay ¶
type StoreOverlay struct {
// Additions are new resources to add to the store.
Additions []runtime.Object
// Modifications are existing resources with updated content.
Modifications []runtime.Object
// Deletions are keys identifying resources to remove.
// Uses NamespacedName for consistent key format.
Deletions []ktypes.NamespacedName
// contains filtered or unexported fields
}
StoreOverlay represents proposed changes to a store.
This enables "what if" scenarios: validate configurations with proposed changes without modifying the actual store state.
Resources are pre-converted to template-friendly format (floats to ints) at construction time to avoid repeated conversion during Get()/List() calls.
func NewStoreOverlay ¶
func NewStoreOverlay() *StoreOverlay
NewStoreOverlay creates a new empty StoreOverlay.
func NewStoreOverlayForCreate ¶
func NewStoreOverlayForCreate(obj runtime.Object) *StoreOverlay
NewStoreOverlayForCreate creates a StoreOverlay for a CREATE operation. The resource is pre-converted to template-friendly format.
func NewStoreOverlayForDelete ¶
func NewStoreOverlayForDelete(namespace, name string) *StoreOverlay
NewStoreOverlayForDelete creates a StoreOverlay for a DELETE operation.
func NewStoreOverlayForUpdate ¶
func NewStoreOverlayForUpdate(obj runtime.Object) *StoreOverlay
NewStoreOverlayForUpdate creates a StoreOverlay for an UPDATE operation. The resource is pre-converted to template-friendly format.
func (*StoreOverlay) AddAddition ¶
func (o *StoreOverlay) AddAddition(obj runtime.Object)
AddAddition adds a resource to the additions list and pre-converts it. Use this method instead of directly modifying the Additions field to ensure the pre-converted slice stays in sync.
func (*StoreOverlay) AddModification ¶
func (o *StoreOverlay) AddModification(obj runtime.Object)
AddModification adds a resource to the modifications list and pre-converts it. Use this method instead of directly modifying the Modifications field to ensure the pre-converted slice stays in sync.
func (*StoreOverlay) IsEmpty ¶
func (o *StoreOverlay) IsEmpty() bool
IsEmpty returns true if the overlay contains no changes.
type StoreProvider ¶
type StoreProvider interface {
// GetStore returns the store for the given name.
// Returns nil if no store exists with that name.
GetStore(name string) Store
// StoreNames returns the names of all available stores.
StoreNames() []string
}
StoreProvider provides access to stores by name.
This abstraction decouples consumers from how stores are obtained, enabling composition and overlaying of proposed changes.
func NewStoreProviderFromGetter ¶
func NewStoreProviderFromGetter(getter GenericStoreGetter, storeNames []string) StoreProvider
NewStoreProviderFromGetter creates a StoreProvider from any type that can get stores by name.
This is useful for integrating with resourcestore.Manager which returns k8s/types.Store:
manager := resourcestore.NewManager(...) provider := stores.NewStoreProviderFromGetter(manager, manager.StoreNames())
type StoreProviderFunc ¶
StoreProviderFunc is a function type that implements StoreProvider. It allows wrapping a function as a StoreProvider.
func (StoreProviderFunc) GetStore ¶
func (f StoreProviderFunc) GetStore(name string) Store
GetStore implements StoreProvider by calling the function.
func (StoreProviderFunc) StoreNames ¶
func (f StoreProviderFunc) StoreNames() []string
StoreNames is not implemented for function providers.
type TypesStoreAdapter ¶
type TypesStoreAdapter struct {
// Inner is the underlying store to delegate to.
// It must implement Get, List, Add, Update, Delete, Clear methods
// with the same signatures as stores.Store.
Inner interface {
Get(keys ...string) ([]interface{}, error)
List() ([]interface{}, error)
Add(resource interface{}, keys []string) error
Update(resource interface{}, keys []string) error
Delete(keys ...string) error
Clear() error
}
}
TypesStoreAdapter wraps any type implementing the Store interface methods.
This adapter is needed because k8s/types.Store and stores.Store are identical interfaces defined in different packages. Go's structural typing means concrete types implement both, but interface VALUES cannot be directly assigned across package boundaries.
Example:
typesStore := someManager.GetStore("ingresses") // returns types.Store
storesStore := &TypesStoreAdapter{Inner: typesStore} // now implements stores.Store
func (*TypesStoreAdapter) Add ¶
func (a *TypesStoreAdapter) Add(resource interface{}, keys []string) error
Add implements Store by delegating to Inner.
func (*TypesStoreAdapter) Clear ¶
func (a *TypesStoreAdapter) Clear() error
Clear implements Store by delegating to Inner.
func (*TypesStoreAdapter) Delete ¶
func (a *TypesStoreAdapter) Delete(keys ...string) error
Delete implements Store by delegating to Inner.
func (*TypesStoreAdapter) Get ¶
func (a *TypesStoreAdapter) Get(keys ...string) ([]interface{}, error)
Get implements Store by delegating to Inner.
func (*TypesStoreAdapter) List ¶
func (a *TypesStoreAdapter) List() ([]interface{}, error)
List implements Store by delegating to Inner.
func (*TypesStoreAdapter) ModCount ¶
func (a *TypesStoreAdapter) ModCount() (uint64, bool)
ModCount implements ModCounter by delegating to Inner if it supports ModCount. Returns (0, false) if the inner store does not support modification tracking, which signals to callers that they MUST NOT cache based on the count.
func (*TypesStoreAdapter) Update ¶
func (a *TypesStoreAdapter) Update(resource interface{}, keys []string) error
Update implements Store by delegating to Inner.
type ValidationContext ¶
type ValidationContext struct {
// K8sOverlays maps store names to their proposed changes.
K8sOverlays map[string]*StoreOverlay
// HTTPOverlay contains pending HTTP content changes.
// Nil means no HTTP content changes to validate.
HTTPOverlay HTTPContentOverlay
}
ValidationContext is a unified container for all overlay types.
It holds both K8s store overlays and HTTP content overlays, enabling the render pipeline to apply proposed changes transparently during validation.
Usage:
// For K8s-only validation (webhook admission) ctx := NewValidationContext(k8sOverlays) // For HTTP content validation ctx := NewValidationContext(nil).WithHTTPOverlay(httpOverlay) // For combined validation ctx := NewValidationContext(k8sOverlays).WithHTTPOverlay(httpOverlay)
func NewValidationContext ¶
func NewValidationContext(overlays map[string]*StoreOverlay) *ValidationContext
NewValidationContext creates a ValidationContext with K8s overlays.
Parameters:
- overlays: Map of store name to proposed K8s changes (can be nil)
Returns a ValidationContext ready for use or further configuration.
func (*ValidationContext) HasHTTPOverlay ¶
func (c *ValidationContext) HasHTTPOverlay() bool
HasHTTPOverlay returns true if an HTTP overlay is present.
func (*ValidationContext) HasK8sOverlays ¶
func (c *ValidationContext) HasK8sOverlays() bool
HasK8sOverlays returns true if any K8s overlays are present.
func (*ValidationContext) IsEmpty ¶
func (c *ValidationContext) IsEmpty() bool
IsEmpty returns true if the context contains no overlays.
A context is empty if it has no K8s overlays AND no HTTP overlay.
func (*ValidationContext) WithHTTPOverlay ¶
func (c *ValidationContext) WithHTTPOverlay(overlay HTTPContentOverlay) *ValidationContext
WithHTTPOverlay adds an HTTP overlay to the validation context.
Returns the same ValidationContext for method chaining:
ctx := NewValidationContext(overlays).WithHTTPOverlay(httpOverlay)