Documentation
¶
Overview ¶
Package common provides base infrastructure for Sync Controllers. Sync Controllers are responsible for: - Watching CloudflareSyncState resources - Aggregating configuration from multiple sources - Debouncing rapid changes - Syncing to Cloudflare API with incremental detection - Updating SyncState status
Index ¶
- Constants
- func ComputeConfigHash(config interface{}) (string, error)
- func ComputeConfigHashDeterministic(config interface{}) (string, error)
- func CreateAPIClient(ctx context.Context, c client.Client, syncState *v1alpha2.CloudflareSyncState) (*cf.API, error)
- func ExtractFirstSourceConfig[T any](syncState *v1alpha2.CloudflareSyncState) (*T, error)
- func FilterSourcesByKind(sources []v1alpha2.ConfigSource, kinds ...string) []v1alpha2.ConfigSource
- func GeneratePendingID(resourceName string) string
- func HandleNotFoundOnUpdate(err error) bool
- func HashChanged(previous, current string) bool
- func IsManagedByOperator(description string) bool
- func IsPendingID(cloudflareID string) bool
- func MustComputeHash(config interface{}) string
- func ParseSourceConfig[T any](source *v1alpha2.ConfigSource) (*T, error)
- func PredicateForResourceType(resourceType v1alpha2.SyncResourceType) predicate.Predicate
- func RequeueAfterError(_ error) time.Duration
- func RequeueAfterSuccess() time.Duration
- func RequireAccountID(syncState *v1alpha2.CloudflareSyncState) (string, error)
- func RequireZoneID(syncState *v1alpha2.CloudflareSyncState) (string, error)
- func UpdateCloudflareID(ctx context.Context, c client.Client, syncState *v1alpha2.CloudflareSyncState, ...)
- type AggregatedEntries
- type AggregatedResult
- type Aggregator
- type BaseSyncController
- func (c *BaseSyncController) GetSyncState(ctx context.Context, name string) (*v1alpha2.CloudflareSyncState, error)
- func (c *BaseSyncController) SetSyncStatus(ctx context.Context, syncState *v1alpha2.CloudflareSyncState, ...) error
- func (*BaseSyncController) ShouldSync(syncState *v1alpha2.CloudflareSyncState, newHash string) bool
- func (*BaseSyncController) StoreAggregatedConfig(syncState *v1alpha2.CloudflareSyncState, config interface{}) error
- func (c *BaseSyncController) UpdateSyncStatus(ctx context.Context, syncState *v1alpha2.CloudflareSyncState, ...) error
- type Debouncer
- func (d *Debouncer) Cancel(key string) bool
- func (d *Debouncer) Debounce(key string, fn func())
- func (d *Debouncer) DebounceRequest(key string, req ctrl.Request, enqueue func(ctrl.Request)) bool
- func (d *Debouncer) Flush()
- func (d *Debouncer) GetDelay() time.Duration
- func (d *Debouncer) IsPending(key string) bool
- func (d *Debouncer) PendingCount() int
- type Entry
- type EntryAggregator
- type OwnershipMarker
- type SettingOwnership
- type SettingValue
- type SettingsAggregator
- type SyncError
- type SyncResult
Constants ¶
const DefaultDebounceDelay = 500 * time.Millisecond
DefaultDebounceDelay is the default delay before executing debounced operations. This allows multiple rapid changes to be coalesced into a single API call.
const PendingIDPrefix = "pending-"
PendingIDPrefix is the prefix used for Cloudflare IDs that haven't been created yet. When a SyncState is first created, the CloudflareID is set to "pending-<resource-name>" to indicate that the resource needs to be created in Cloudflare.
Variables ¶
This section is empty.
Functions ¶
func ComputeConfigHash ¶
ComputeConfigHash computes a SHA256 hash of the given configuration. The hash is used to detect changes and avoid unnecessary API calls. Returns a hex-encoded string of the hash.
func ComputeConfigHashDeterministic ¶
ComputeConfigHashDeterministic computes a deterministic hash by normalizing the JSON. This handles cases where map iteration order differs.
func CreateAPIClient ¶
func CreateAPIClient( ctx context.Context, c client.Client, syncState *v1alpha2.CloudflareSyncState, ) (*cf.API, error)
CreateAPIClient creates a Cloudflare API client from the credentials reference in a SyncState. This is the standard pattern used by all Sync Controllers.
func ExtractFirstSourceConfig ¶
func ExtractFirstSourceConfig[T any](syncState *v1alpha2.CloudflareSyncState) (*T, error)
ExtractFirstSourceConfig extracts configuration from the first source in a SyncState. This is the standard pattern for 1:1 mapping resources (DNS, Gateway, Device, etc.) where each Kubernetes resource maps to exactly one Cloudflare resource.
Returns an error if: - No sources are present - JSON unmarshaling fails - Configuration is empty/nil
func FilterSourcesByKind ¶
func FilterSourcesByKind(sources []v1alpha2.ConfigSource, kinds ...string) []v1alpha2.ConfigSource
FilterSourcesByKind returns sources matching the specified kinds.
func GeneratePendingID ¶
GeneratePendingID creates a pending ID for a new resource. The resource name is appended to distinguish between multiple pending resources.
func HandleNotFoundOnUpdate ¶
HandleNotFoundOnUpdate is a helper for the common pattern where an update fails because the resource was deleted externally. It returns true if the error indicates the resource was not found, allowing the caller to recreate it.
func HashChanged ¶
HashChanged compares two hashes and returns true if they differ. An empty previous hash always indicates a change.
func IsManagedByOperator ¶ added in v0.24.0
IsManagedByOperator checks if a description indicates operator management
func IsPendingID ¶
IsPendingID checks if the given Cloudflare ID indicates a resource that hasn't been created yet. Resources start with a pending ID and are updated with the real Cloudflare ID after successful creation.
func MustComputeHash ¶
func MustComputeHash(config interface{}) string
MustComputeHash computes a hash, panicking on error. Only use this for known-good configurations during initialization.
func ParseSourceConfig ¶
func ParseSourceConfig[T any](source *v1alpha2.ConfigSource) (*T, error)
ParseSourceConfig parses a source's configuration into the target struct. This is a helper for Sync Controllers to extract typed configuration.
func PredicateForResourceType ¶
func PredicateForResourceType(resourceType v1alpha2.SyncResourceType) predicate.Predicate
PredicateForResourceType creates a predicate that filters CloudflareSyncState events by resource type. This is the standard predicate used by all Sync Controllers to ensure they only process SyncStates of their specific type.
Usage:
ctrl.NewControllerManagedBy(mgr).
For(&v1alpha2.CloudflareSyncState{}).
WithEventFilter(common.PredicateForResourceType(v1alpha2.SyncResourceDNSRecord)).
Complete(r)
func RequeueAfterError ¶
RequeueAfterError returns a requeue duration appropriate for the error type. Permanent errors get longer delays, transient errors get shorter delays.
func RequeueAfterSuccess ¶
RequeueAfterSuccess returns a requeue duration for periodic refresh. Most syncs don't need periodic refresh (they're event-driven), so this returns 0.
func RequireAccountID ¶
func RequireAccountID(syncState *v1alpha2.CloudflareSyncState) (string, error)
RequireAccountID validates that the SyncState has an AccountID specified. This is required for account-scoped resources (Gateway, Device, Access, etc.).
func RequireZoneID ¶
func RequireZoneID(syncState *v1alpha2.CloudflareSyncState) (string, error)
RequireZoneID validates that the SyncState has a ZoneID specified. This is required for zone-scoped resources (DNS, Ruleset, etc.).
func UpdateCloudflareID ¶
func UpdateCloudflareID( ctx context.Context, c client.Client, syncState *v1alpha2.CloudflareSyncState, newID string, )
UpdateCloudflareID updates the CloudflareID in the SyncState spec. This is called after successfully creating a resource in Cloudflare to record the actual ID. Errors are logged but not returned since this is a non-fatal operation that will be corrected on the next reconcile.
Types ¶
type AggregatedEntries ¶ added in v0.24.0
type AggregatedEntries struct {
// Entries is the list of merged entries
Entries []Entry
// ByOwner groups entries by their owner for efficient lookup
ByOwner map[string][]Entry
// SourceCount is the number of sources that contributed entries
SourceCount int
}
AggregatedEntries contains the merged entries with ownership information
func (*AggregatedEntries) GetOwnerEntries ¶ added in v0.24.0
func (a *AggregatedEntries) GetOwnerEntries(owner v1alpha2.SourceReference) []Entry
GetOwnerEntries returns entries owned by the specified source.
func (*AggregatedEntries) RemoveOwner ¶ added in v0.24.0
func (a *AggregatedEntries) RemoveOwner(owner v1alpha2.SourceReference) []Entry
RemoveOwner returns entries without those owned by the specified source. This is used during deletion to remove only the deleted source's entries.
type AggregatedResult ¶ added in v0.24.0
type AggregatedResult[T any] struct { // Config is the merged configuration Config *T // SourceCount is the number of sources that contributed to this config SourceCount int // SourceRefs contains references to all contributing sources SourceRefs []v1alpha2.SourceReference }
AggregatedResult wraps the aggregated configuration with metadata
type Aggregator ¶ added in v0.24.0
type Aggregator[T any] struct { // MergeFunc defines how to merge a source config into the aggregated result. // It receives the current aggregated result and a source config, and returns // the updated aggregated result. MergeFunc func(aggregated *T, source *T, sourceRef v1alpha2.SourceReference, priority int) *T // FinalizeFunc is called after all sources are merged to perform any // final processing (e.g., sorting, deduplication, adding defaults). // Optional - if nil, no finalization is performed. FinalizeFunc func(aggregated *T) *T }
Aggregator provides common aggregation logic for Sync Controllers. It supports merging configurations from multiple sources with priority ordering.
func (*Aggregator[T]) Aggregate ¶ added in v0.24.0
func (a *Aggregator[T]) Aggregate(syncState *v1alpha2.CloudflareSyncState) (*AggregatedResult[T], error)
Aggregate merges all sources in a SyncState using the configured merge function. Sources are processed in priority order (lower priority number = higher precedence).
Algorithm: 1. Sort sources by priority (ascending) 2. Initialize empty aggregated result 3. For each source, parse config and call MergeFunc 4. Call FinalizeFunc if configured 5. Return aggregated result with metadata
func (*Aggregator[T]) AggregateWithFilter ¶ added in v0.24.0
func (a *Aggregator[T]) AggregateWithFilter( syncState *v1alpha2.CloudflareSyncState, kinds ...string, ) (*AggregatedResult[T], error)
AggregateWithFilter aggregates only sources matching the specified kinds.
type BaseSyncController ¶
BaseSyncController provides common functionality for all Sync Controllers. Each resource type (Tunnel, DNS, Access, etc.) extends this with specific aggregation and sync logic.
func NewBaseSyncController ¶
func NewBaseSyncController(c client.Client) *BaseSyncController
NewBaseSyncController creates a new BaseSyncController
func NewBaseSyncControllerWithDelay ¶
func NewBaseSyncControllerWithDelay(c client.Client, delay time.Duration) *BaseSyncController
NewBaseSyncControllerWithDelay creates a BaseSyncController with custom debounce delay
func (*BaseSyncController) GetSyncState ¶
func (c *BaseSyncController) GetSyncState(ctx context.Context, name string) (*v1alpha2.CloudflareSyncState, error)
GetSyncState retrieves a CloudflareSyncState by name
func (*BaseSyncController) SetSyncStatus ¶
func (c *BaseSyncController) SetSyncStatus( ctx context.Context, syncState *v1alpha2.CloudflareSyncState, status v1alpha2.SyncStatus, ) error
SetSyncStatus updates the SyncState status to the specified state. This is a convenience method for setting just the status without result.
func (*BaseSyncController) ShouldSync ¶
func (*BaseSyncController) ShouldSync(syncState *v1alpha2.CloudflareSyncState, newHash string) bool
ShouldSync determines if a sync is needed by comparing config hashes. Returns true if the configuration has changed since the last sync.
func (*BaseSyncController) StoreAggregatedConfig ¶
func (*BaseSyncController) StoreAggregatedConfig( syncState *v1alpha2.CloudflareSyncState, config interface{}, ) error
StoreAggregatedConfig stores the aggregated configuration in the SyncState status. This is useful for debugging and observability.
func (*BaseSyncController) UpdateSyncStatus ¶
func (c *BaseSyncController) UpdateSyncStatus( ctx context.Context, syncState *v1alpha2.CloudflareSyncState, status v1alpha2.SyncStatus, result *SyncResult, syncErr error, ) error
UpdateSyncStatus updates the SyncState status with the sync result. It handles both success and error cases, setting appropriate conditions.
type Debouncer ¶
type Debouncer struct {
// contains filtered or unexported fields
}
Debouncer coalesces multiple events into a single operation. When an event occurs, it waits for the delay period. If another event occurs during this period, the timer resets. The operation only executes when no new events occur within the delay period.
This is useful for: - Reducing Cloudflare API calls when multiple resources change rapidly - Handling bulk operations (e.g., creating multiple Ingresses) - Avoiding rate limiting from the Cloudflare API
func NewDebouncer ¶
NewDebouncer creates a new Debouncer with the specified delay. Use DefaultDebounceDelay for the standard 500ms delay.
func (*Debouncer) Cancel ¶
Cancel cancels a pending debounced operation. Returns true if an operation was cancelled, false if none was pending.
func (*Debouncer) Debounce ¶
Debounce schedules a function to be called after the delay. If called again with the same key before the delay expires, the timer is reset and only the latest function will be called.
The key should uniquely identify the operation (e.g., SyncState name).
func (*Debouncer) DebounceRequest ¶
DebounceRequest schedules a reconciliation request after the delay. Returns true if a new debounce was scheduled, false if one was already pending.
func (*Debouncer) Flush ¶
func (d *Debouncer) Flush()
Flush immediately executes all pending operations. This is useful during shutdown or testing.
func (*Debouncer) PendingCount ¶
PendingCount returns the number of pending debounced operations.
type Entry ¶ added in v0.24.0
type Entry struct {
// Data is the actual entry data (will be type-asserted by the caller)
Data interface{}
// Owner identifies the source that contributed this entry
Owner v1alpha2.SourceReference
// Priority from the source
Priority int
}
Entry represents a single entry with ownership tracking
type EntryAggregator ¶ added in v0.24.0
type EntryAggregator[T any] struct { // ExtractEntries extracts entries from a source config ExtractEntries func(config *T) []Entry // SetEntries sets entries in the aggregated config SetEntries func(config *T, entries []Entry) // EntryKey returns a unique key for deduplication (optional) // If nil, no deduplication is performed EntryKey func(entry Entry) string }
EntryAggregator provides aggregation for list-based configurations (e.g., split tunnel entries, ruleset rules, DNS records). It tracks ownership of each entry to support incremental deletion.
func (*EntryAggregator[T]) Aggregate ¶ added in v0.24.0
func (a *EntryAggregator[T]) Aggregate(syncState *v1alpha2.CloudflareSyncState) (*AggregatedEntries, error)
Aggregate merges entries from all sources, tracking ownership of each entry.
type OwnershipMarker ¶ added in v0.24.0
OwnershipMarker provides utilities for embedding ownership information in Cloudflare resource descriptions for tracking purposes.
func NewOwnershipMarker ¶ added in v0.24.0
func NewOwnershipMarker(ref v1alpha2.SourceReference) OwnershipMarker
NewOwnershipMarker creates a marker from a SourceReference
func (OwnershipMarker) AppendToDescription ¶ added in v0.24.0
func (m OwnershipMarker) AppendToDescription(description string) string
AppendToDescription appends the ownership marker to a description
func (OwnershipMarker) IsOwnedBy ¶ added in v0.24.0
func (m OwnershipMarker) IsOwnedBy(description string) bool
IsOwnedBy checks if a description contains the ownership marker
func (OwnershipMarker) String ¶ added in v0.24.0
func (m OwnershipMarker) String() string
String returns the marker in format "managed-by:Kind/Namespace/Name"
type SettingOwnership ¶ added in v0.24.0
type SettingOwnership struct {
// Settings maps setting key to its value and owner
Settings map[string]SettingValue
}
SettingOwnership tracks which source owns each setting
func (*SettingOwnership) GetSettingsWithoutOwner ¶ added in v0.24.0
func (o *SettingOwnership) GetSettingsWithoutOwner(owner v1alpha2.SourceReference) map[string]interface{}
GetSettingsWithoutOwner returns settings not owned by the specified source. Used during deletion to preserve other sources' settings.
type SettingValue ¶ added in v0.24.0
type SettingValue struct {
Value interface{}
Owner v1alpha2.SourceReference
Priority int
}
SettingValue contains a setting value with ownership
type SettingsAggregator ¶ added in v0.24.0
type SettingsAggregator[T any] struct { // GetSettings extracts settings map from config GetSettings func(config *T) map[string]interface{} // ApplySettings applies merged settings to config ApplySettings func(config *T, settings map[string]interface{}) }
SettingsAggregator provides aggregation for key-value settings where higher priority sources override lower priority ones.
func (*SettingsAggregator[T]) Aggregate ¶ added in v0.24.0
func (a *SettingsAggregator[T]) Aggregate(syncState *v1alpha2.CloudflareSyncState) (*SettingOwnership, error)
Aggregate merges settings from all sources, with higher priority sources winning.
type SyncError ¶
type SyncError struct {
Op string // Operation that failed (e.g., "aggregate", "sync", "updateStatus")
Err error // Underlying error
Retries int // Number of retries attempted
}
SyncError wraps an error with additional sync context
type SyncResult ¶
type SyncResult struct {
// ConfigVersion is the version returned by Cloudflare after update
ConfigVersion int
// ConfigHash is the hash of the synced configuration
ConfigHash string
}
SyncResult contains the result of a successful sync operation