common

package
v0.34.2 Latest Latest
Warning

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

Go to latest
Published: Jan 24, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package common provides shared utilities for controllers in the simplified 3-layer architecture. Controllers can directly call Cloudflare API using the APIClientFactory.

Package common provides shared utilities for controllers in the simplified 3-layer architecture.

Architecture Overview

The new architecture simplifies the operator from 6 layers to 3 layers:

Old: CRD → Controller → Service → SyncState → SyncController → CF API
New: CRD → Controller → CF API

Key Components

  • APIClientFactory: Creates and manages Cloudflare API clients
  • Requeue utilities: Standard intervals and backoff for reconciliation
  • Re-exports from parent controller package: Status, Finalizer, Event, Deletion utilities

Usage Pattern

Controllers should follow this pattern:

func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    obj := &v1alpha2.MyResource{}
    if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }

    // Handle deletion
    if !obj.DeletionTimestamp.IsZero() {
        return r.handleDeletion(ctx, obj)
    }

    // Get API client
    apiResult, err := r.APIFactory.GetClient(ctx, common.APIClientOptions{
        CloudflareDetails: &obj.Spec.Cloudflare,
        Namespace:         obj.Namespace,
        StatusAccountID:   obj.Status.AccountID,
    })
    if err != nil {
        return r.setErrorStatus(ctx, obj, err)
    }

    // Ensure finalizer
    if added, err := controller.EnsureFinalizer(ctx, r.Client, obj, FinalizerName); err != nil {
        return ctrl.Result{}, err
    } else if added {
        return ctrl.Result{Requeue: true}, nil
    }

    // Direct API call
    result, err := apiResult.API.SomeOperation(ctx, ...)
    if err != nil {
        return r.setErrorStatus(ctx, obj, err)
    }

    // Direct status write (no intermediate layer!)
    return r.setSuccessStatus(ctx, obj, result)
}

Benefits

  • Simpler data flow: One CRD → One controller → Direct API call
  • No intermediate SyncState: Status written directly to original CRD
  • Independent polling: Each controller has its own Informer, no interference
  • Less code: ~13,000 lines removed (service + sync layers)
  • Easier debugging: Direct data path, no need to correlate multiple resources

Index

Constants

View Source
const (
	// RequeueIntervalShort is used for quick retries after transient errors.
	RequeueIntervalShort = 10 * time.Second

	// RequeueIntervalMedium is used for polling in-progress operations.
	RequeueIntervalMedium = 30 * time.Second

	// RequeueIntervalLong is used for rate limit backoff or long-running operations.
	RequeueIntervalLong = 1 * time.Minute

	// RequeueIntervalVeryLong is used for permanent errors that might recover.
	RequeueIntervalVeryLong = 5 * time.Minute

	// PollingIntervalDeployment is used for polling deployment status.
	PollingIntervalDeployment = 30 * time.Second

	// PollingIntervalDNS is used for polling DNS propagation.
	PollingIntervalDNS = 1 * time.Minute
)

Standard requeue intervals for controllers.

Variables

View Source
var OperatorNamespace = "cloudflare-operator-system"

OperatorNamespace is the namespace where the operator runs. This is used for cluster-scoped resources that need to look up secrets.

Functions

func IsFailure

func IsFailure(stage string) bool

IsFailure checks if the stage indicates a failure.

func IsInProgress

func IsInProgress(stage string) bool

IsInProgress checks if the stage indicates an in-progress deployment. This is used to determine if polling should continue.

func IsSuccess

func IsSuccess(stage string) bool

IsSuccess checks if the stage indicates a successful completion.

func IsTerminal

func IsTerminal(stage string) bool

IsTerminal checks if the stage indicates a terminal state. Terminal states don't require further polling.

func NoRequeue

func NoRequeue() ctrl.Result

NoRequeue returns a result indicating no requeue needed.

func RequeueForError

func RequeueForError(err error, retryCount int) ctrl.Result

RequeueForError returns an appropriate requeue result based on the error type. It uses exponential backoff for transient errors.

func RequeueLong

func RequeueLong() ctrl.Result

RequeueLong returns a result for long-term retry.

func RequeueMedium

func RequeueMedium() ctrl.Result

RequeueMedium returns a result for medium-term retry.

func RequeueResult

func RequeueResult(after time.Duration) ctrl.Result

RequeueResult returns a ctrl.Result for requeuing after the specified duration.

func RequeueShort

func RequeueShort() ctrl.Result

RequeueShort returns a result for quick retry.

func RequeueVeryLong

func RequeueVeryLong() ctrl.Result

RequeueVeryLong returns a result for very long retry.

func RequeueWithBackoff

func RequeueWithBackoff(baseDelay time.Duration, retryCount int, maxDelay time.Duration) ctrl.Result

RequeueWithBackoff returns a result with exponential backoff delay.

func SetOperatorNamespace

func SetOperatorNamespace(ns string)

SetOperatorNamespace sets the operator namespace. This should be called during operator initialization.

func ShouldRequeueForError

func ShouldRequeueForError(err error) bool

ShouldRequeueForError returns true if the error warrants a requeue. Permanent errors (NotFound, Auth, Validation) return false.

Types

type APIClientFactory

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

APIClientFactory creates and caches Cloudflare API clients. It provides a simple interface for controllers to get API clients without dealing with credentials resolution complexity.

func NewAPIClientFactory

func NewAPIClientFactory(c client.Client, log logr.Logger) *APIClientFactory

NewAPIClientFactory creates a new APIClientFactory.

func (*APIClientFactory) GetClient

GetClient returns a Cloudflare API client based on the provided options. It resolves credentials and creates or reuses a cached client.

func (*APIClientFactory) GetClientForCredentials

func (f *APIClientFactory) GetClientForCredentials(ctx context.Context, credentialsName string) (*APIClientResult, error)

GetClientForCredentials returns a Cloudflare API client for the given CloudflareCredentials name. This is a simplified version for resources that only need credentials name.

type APIClientOptions

type APIClientOptions struct {
	// CloudflareDetails contains the Cloudflare configuration from the resource spec.
	// Used for resources with full CloudflareDetails (Tunnel, PagesProject, etc.)
	CloudflareDetails *networkingv1alpha2.CloudflareDetails

	// CredentialsRef is a simple reference to CloudflareCredentials.
	// Used for resources with simplified credentials (R2Bucket, etc.)
	CredentialsRef *networkingv1alpha2.CredentialsReference

	// Namespace is the namespace for resolving legacy inline secrets.
	// For cluster-scoped resources, leave empty or use OperatorNamespace.
	Namespace string

	// AccountID override from status (already validated).
	StatusAccountID string

	// ZoneID override from status (already validated).
	StatusZoneID string
}

APIClientOptions contains options for getting an API client.

type APIClientResult

type APIClientResult struct {
	// API is the Cloudflare API client.
	API *cf.API

	// AccountID is the resolved Cloudflare account ID.
	AccountID string

	// ZoneID is the resolved Cloudflare zone ID (may be empty).
	ZoneID string

	// Domain is the resolved Cloudflare domain (may be empty).
	Domain string

	// CredentialsName is the name of the CloudflareCredentials used.
	CredentialsName string
}

APIClientResult contains the API client and resolved metadata.

Jump to

Keyboard shortcuts

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