Documentation
¶
Index ¶
- Constants
- Variables
- func BuildConnectorConfigMap(tun *cloudflarev1alpha1.CloudflareTunnel, renderedConfig []byte, ...) *corev1.ConfigMap
- func BuildConnectorDeployment(tun *cloudflarev1alpha1.CloudflareTunnel, configHash string) *appsv1.Deployment
- func BuildConnectorPodDisruptionBudget(tun *cloudflarev1alpha1.CloudflareTunnel) *policyv1.PodDisruptionBudget
- func BuildConnectorServiceAccount(tun *cloudflarev1alpha1.CloudflareTunnel) *corev1.ServiceAccount
- func ListZonesClusterWide(ctx context.Context, c client.Client) ([]cloudflarev1alpha1.CloudflareZone, error)
- func LoadCredentials(ctx context.Context, c client.Client, factory CredentialFactory, ...) (cfclient.Credentials, *ctrl.Result, error)
- func MergeCloudflareAnnotations(parent, child map[string]string) map[string]string
- func ReconcileConnectorAndRules(ctx context.Context, c client.Client, tun *cloudflarev1alpha1.CloudflareTunnel, ...) error
- func ResolveZoneForHostname(hostname string, zones []cloudflarev1alpha1.CloudflareZone) (*cloudflarev1alpha1.CloudflareZone, error)
- func ResolveZoneID(ctx context.Context, k8sClient client.Client, obj zoneReferencer) (string, error)
- type AggregationResult
- type CloudflareDNSRecordReconciler
- type CloudflareRulesetReconciler
- type CloudflareTunnelReconciler
- type CloudflareZoneConfigReconciler
- type CloudflareZoneReconciler
- type ConnectorResourceNames
- type CredentialFactory
- type ErrorRouting
- type HTTPRouteSourceReconciler
- type RegistryAction
- type RegistryConfig
- type RuleDecision
- type RuleDecisionStatus
- type ServiceSourceReconciler
- type TargetKind
- type TargetSpec
Constants ¶
const ( AnnotationTarget = "cloudflare.io/target" AnnotationZoneRef = "cloudflare.io/zone-ref" AnnotationZoneRefNamespace = "cloudflare.io/zone-ref-namespace" AnnotationTunnelRefNamespace = "cloudflare.io/tunnel-ref-namespace" AnnotationTunnelUpstream = "cloudflare.io/tunnel-upstream" AnnotationHostnames = "cloudflare.io/hostnames" AnnotationPort = "cloudflare.io/port" AnnotationScheme = "cloudflare.io/scheme" AnnotationProxied = "cloudflare.io/proxied" AnnotationTTL = "cloudflare.io/ttl" AnnotationAdopt = "cloudflare.io/adopt" AnnotationPrefix = "cloudflare.io/" // AnnotationValueTrue is the canonical "true" value for boolean annotation flags // such as cloudflare.io/adopt. AnnotationValueTrue = "true" // AnnotationRegistryFor marks an emitted TXT-registry CloudflareDNSRecord // so the DNS controller does not re-emit a TXT for it. AnnotationRegistryFor = "cloudflare.io/registry-for" // AnnotationConfigHash goes on the connector Deployment's pod template // and the rendered ConfigMap so config changes trigger rollouts. AnnotationConfigHash = "cloudflare.io/config-hash" )
Cloudflare-operator annotation keys (v1).
These form the public, stable annotation vocabulary that source controllers (httproute_source, service_source) consume. Once shipped, semantics do not change in breaking ways — new features get new keys.
const ( LabelSourceKind = "cloudflare.io/source-kind" LabelSourceNamespace = "cloudflare.io/source-namespace" LabelSourceName = "cloudflare.io/source-name" LabelManagedBy = "cloudflare.io/managed-by" )
Labels applied to emitted CloudflareDNSRecord / CloudflareTunnelRule CRs for source-based discovery via label selectors.
const DefaultConnectorImage = defaultConnectorRepo + ":" + defaultConnectorTag
DefaultConnectorImage is used when spec.connector.image is unset.
Variables ¶
var ( // ErrForeignTXTOwner indicates a companion TXT record exists whose owner // field does not match TxtOwnerID. The operator refuses to overwrite. ErrForeignTXTOwner = errors.New("record exists with foreign TXT owner") // ErrTXTRegistryGap indicates a DNS record exists at the target name+type // but has no companion ownership TXT, and the CR has not opted in to adopt. ErrTXTRegistryGap = errors.New("record exists without ownership TXT and source is not opted in to adopt") // ErrSourceLabelsMissing is returned by writeRegistryTXT when the managed // CloudflareDNSRecord is missing the cloudflare.io/source-* labels needed // to build the registry payload. ErrSourceLabelsMissing = errors.New("managed CR is missing cloudflare.io/source-* labels") )
Sentinel errors returned for classifiable failure verdicts. Callers MUST use errors.Is for comparison — never compare error strings.
var ErrAmbiguousZone = errors.New("ambiguous CloudflareZone for hostname")
ErrAmbiguousZone is returned by ResolveZoneForHostname when two or more CloudflareZones share an identical spec.Name matching the hostname. This is a configuration error, not a transient one.
var ErrInvalidTarget = errors.New("invalid cloudflare.io/target value")
ErrInvalidTarget is returned by ParseTarget on malformed input.
var ErrNoGatewayAddress = errors.New("no Gateway address populated in status")
ErrNoGatewayAddress is returned when a target=address reconcile cannot proceed because the parent Gateway has no status addresses populated yet.
var ErrNoMatchingZone = errors.New("no CloudflareZone matches hostname")
ErrNoMatchingZone is returned by ResolveZoneForHostname when no CloudflareZone's spec.name is a suffix of the hostname.
var ErrNoServicePorts = errors.New("service has no ports")
ErrNoServicePorts is returned by resolveServiceBackend when the Service has no ports defined.
var ErrPortNotFound = errors.New("port not found on Service")
ErrPortNotFound is returned by resolveServiceBackend when the requested port name or number is not present on the Service.
var ErrUnownedDeployment = stderrors.New("refusing to adopt Deployment not owned by this tunnel")
ErrUnownedDeployment is returned when reconcileConnectorResources finds an existing Deployment that is not owned by the reconciled CloudflareTunnel. Tests MUST use errors.Is(err, ErrUnownedDeployment) to assert this case.
var ErrUnownedPDB = stderrors.New("refusing to adopt PodDisruptionBudget not owned by this tunnel")
ErrUnownedPDB is returned when applyOwnedPDB finds an existing PodDisruptionBudget that is not owned by the reconciled CloudflareTunnel. Tests MUST use errors.Is(err, ErrUnownedPDB) to assert this case.
var ErrZoneRefNotReady = errors.New("zone reference is not ready")
ErrZoneRefNotReady is returned by ResolveZoneID when the referenced CloudflareZone exists but has not yet populated its status.ZoneID. Callers can check with errors.Is to log this as an Info-level "waiting on dependency" rather than an Error, since it resolves on its own once the zone reconciles.
Functions ¶
func BuildConnectorConfigMap ¶ added in v0.6.0
func BuildConnectorConfigMap(tun *cloudflarev1alpha1.CloudflareTunnel, renderedConfig []byte, configHash string) *corev1.ConfigMap
BuildConnectorConfigMap produces the desired ConfigMap carrying the rendered cloudflared config.yaml.
func BuildConnectorDeployment ¶ added in v0.6.0
func BuildConnectorDeployment(tun *cloudflarev1alpha1.CloudflareTunnel, configHash string) *appsv1.Deployment
BuildConnectorDeployment produces the desired Deployment running cloudflared.
Replicas: when cspec is nil (defensive path), default to 2. When cspec is non-nil, use cspec.Replicas directly — this preserves a user-set value of 0 (scale-down intent). The apiserver default of 2 fires only on field-absent creates, so by the time the controller reads the spec the value is always meaningful.
Image: see resolveConnectorImage for the four-case partial-override matrix.
Resources: cspec.Resources.Requests and cspec.Resources.Limits are defaulted independently so a user supplying only Requests still gets the Memory limit safety floor (and vice versa). Defaults: 10m CPU + 128Mi Memory requests, 256Mi Memory limit.
Note: cspec.Resources is shallow-copied into the container; ResourceList and other map fields share storage with the input. Build* functions never mutate the spec in place, so this aliasing is safe.
func BuildConnectorPodDisruptionBudget ¶ added in v0.11.0
func BuildConnectorPodDisruptionBudget(tun *cloudflarev1alpha1.CloudflareTunnel) *policyv1.PodDisruptionBudget
BuildConnectorPodDisruptionBudget returns the PDB that protects the cloudflared connector deployment from voluntary disruption (node drain, autoscaler scale-down, manual evict).
Returns nil when:
- tun.Spec.Connector is unset (connector disabled), or
- replicas < 2.
At replicas == 1 a minAvailable:1 PDB blocks all voluntary disruptions (strictly worse than no PDB) and maxUnavailable:1 permits all evictions (no protection). Skipping the PDB entirely is the correct call. The reconciler treats nil as "ensure absent" so transitions from replicas:2 to replicas:1 cleanly delete the PDB.
func BuildConnectorServiceAccount ¶ added in v0.6.0
func BuildConnectorServiceAccount(tun *cloudflarev1alpha1.CloudflareTunnel) *corev1.ServiceAccount
BuildConnectorServiceAccount produces the desired ServiceAccount for tun.
func ListZonesClusterWide ¶ added in v0.6.0
func ListZonesClusterWide(ctx context.Context, c client.Client) ([]cloudflarev1alpha1.CloudflareZone, error)
ListZonesClusterWide returns all CloudflareZone CRs in the cluster.
func LoadCredentials ¶ added in v0.13.0
func LoadCredentials( ctx context.Context, c client.Client, factory CredentialFactory, secretName, namespace string, recorder record.EventRecorder, obj client.Object, conditions *[]metav1.Condition, requeue time.Duration, ) (cfclient.Credentials, *ctrl.Result, error)
LoadCredentials fetches Cloudflare credentials for a CR and centralizes the failure-mode plumbing every reconciler would otherwise duplicate.
Returns:
creds: populated on the success path; zero value on any error.
halt: non-nil when the caller MUST return immediately. Reconcilers use the pattern:
creds, halt, err := LoadCredentials(...) if halt != nil { return *halt, err }
err: surfaced from failReconcile. Always nil on the success path. Always nil on the SecretNotFound and SecretNotLabeled paths (failReconcile swallows status-write errors and returns a timed requeue, matching existing controller behavior).
Failure-mode mapping:
- cfclient.ErrSecretNotLabeled → ReasonSecretNotLabeled, recorder event with the actionable label-the-Secret guidance, requeue.
- apierrors.IsNotFound (wrapped) → ReasonSecretNotFound, requeue.
- any other error → ReasonReconcileError, requeue.
recorder may be nil; the helper silently skips event emission in that case. In production every reconciler MUST provide a non-nil recorder — the guard exists for tests and out-of-tree callers.
func MergeCloudflareAnnotations ¶ added in v0.6.0
MergeCloudflareAnnotations merges parent (e.g. Gateway) and child (e.g. Route) annotations, keeping only the cloudflare.io/* subset. Child values override parent values on the same key.
func ReconcileConnectorAndRules ¶ added in v0.6.0
func ReconcileConnectorAndRules(ctx context.Context, c client.Client, tun *cloudflarev1alpha1.CloudflareTunnel, preStatus *cloudflarev1alpha1.CloudflareTunnelStatus) error
ReconcileConnectorAndRules performs the Task 8 additions to the tunnel reconcile: aggregates CloudflareTunnelRule CRs for this tunnel, renders config.yaml, reconciles the connector workload (when enabled) or deletes any previously-managed connector resources (when disabled), and writes per-rule + per-tunnel status.
When Spec.Connector == nil or Spec.Connector.Enabled == false, every operator-owned connector resource for this tunnel is deleted via cleanupConnectorResources — including resources from prior spec.connector.nameOverride values, which share the connector label set.
Pure controller-runtime operation: no Cloudflare API calls. Called by Reconcile after tunnel provisioning has populated TunnelID/TunnelCNAME. preStatus is the status snapshot taken before Reconcile began; it is used by writeTunnelAggStatus to set LastSyncedAt only when status actually changed.
func ResolveZoneForHostname ¶ added in v0.6.0
func ResolveZoneForHostname(hostname string, zones []cloudflarev1alpha1.CloudflareZone) (*cloudflarev1alpha1.CloudflareZone, error)
ResolveZoneForHostname picks the CloudflareZone with the longest spec.name suffix match against hostname. If two zones are equally-specific, returns an error (expected in practice only when zones are literally identical; CR names are unique by namespace so this is rare but guarded).
func ResolveZoneID ¶
func ResolveZoneID(ctx context.Context, k8sClient client.Client, obj zoneReferencer) (string, error)
ResolveZoneID returns the Cloudflare zone ID for obj: either its inline Spec.ZoneID, or the ZoneID from the CloudflareZone it references via Spec.ZoneRef. The lookup namespace is ref.Namespace when set, otherwise it falls back to obj's own namespace. Returns ErrZoneRefNotReady (wrapped) when the referenced zone exists but hasn't populated ZoneID yet.
Types ¶
type AggregationResult ¶ added in v0.6.0
type AggregationResult struct {
// Rendered is the cloudflared config.yaml content.
Rendered []byte
// ConfigHash is sha256 of Rendered, hex-encoded.
ConfigHash string
// Decisions maps ruleKey -> per-rule verdict.
Decisions map[types.NamespacedName]RuleDecision
}
AggregationResult is the output of Aggregate.
func Aggregate ¶ added in v0.6.0
func Aggregate(tunnelID string, rules []cloudflarev1alpha1.CloudflareTunnelRule, routing *cloudflarev1alpha1.TunnelRoutingSpec) AggregationResult
Aggregate produces the rendered config.yaml content and per-rule verdicts for a set of CloudflareTunnelRule CRs targeting the same tunnel, plus the tunnel's spec.routing defaults. tunnelID is the parent tunnel's Status.TunnelID; it is included in the rendered config.yaml header and therefore contributes to ConfigHash.
Ordering rules (spec §4.3):
- Rules sorted by spec.priority desc, then metadata.name asc.
- Duplicate hostnames resolved by first writer (creationTimestamp asc, then UID asc); losers get RuleDuplicateHostname.
- config.yaml order: included rules, then either spec.routing.defaultBackend (if set) OR a final http_status:404 catch-all — never both. When defaultBackend is set it IS the catch-all (cloudflared treats an entry without `hostname:` as a wildcard); appending http_status:404 after it would render that 404 unreachable and, when no rules precede the defaultBackend, cloudflared rejects the config outright (#66).
type CloudflareDNSRecordReconciler ¶
type CloudflareDNSRecordReconciler struct {
client.Client
Scheme *runtime.Scheme
Recorder record.EventRecorder
ClientFactory CredentialFactory
IPResolver *ipresolver.Resolver
DNSClientFn func(apiToken string) cfclient.DNSClient
// Registry holds optional TXT-registry configuration. The zero value
// (TxtOwnerID == "") disables all registry behaviour.
Registry RegistryConfig
}
CloudflareDNSRecordReconciler reconciles a CloudflareDNSRecord object
func (*CloudflareDNSRecordReconciler) Reconcile ¶
func (r *CloudflareDNSRecordReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile moves the current state of the cluster closer to the desired state for a CloudflareDNSRecord resource. It handles the full lifecycle of DNS records including creation, updates, adoption of existing records, and deletion.
func (*CloudflareDNSRecordReconciler) SetupWithManager ¶
func (r *CloudflareDNSRecordReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type CloudflareRulesetReconciler ¶
type CloudflareRulesetReconciler struct {
client.Client
Scheme *runtime.Scheme
Recorder record.EventRecorder
ClientFactory CredentialFactory
RulesetClientFn func(apiToken string) cfclient.RulesetClient
}
CloudflareRulesetReconciler reconciles a CloudflareRuleset object
func (*CloudflareRulesetReconciler) Reconcile ¶
func (r *CloudflareRulesetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile moves the current state of the cluster closer to the desired state for a CloudflareRuleset resource. It handles the full lifecycle of rulesets including creation, updates, adoption of existing rulesets, and deletion.
func (*CloudflareRulesetReconciler) SetupWithManager ¶
func (r *CloudflareRulesetReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type CloudflareTunnelReconciler ¶
type CloudflareTunnelReconciler struct {
client.Client
// APIReader bypasses the manager's label-filtered cache for reads
// that need to see the actual API-server state regardless of the
// cloudflare.io/managed=true label gate (introduced in PR #87).
// Used by ensureCredentialsSecretExists to detect pre-existing
// unlabeled Secrets that the cache would otherwise hide.
APIReader client.Reader
Scheme *runtime.Scheme
Recorder record.EventRecorder
ClientFactory CredentialFactory
TunnelClientFn func(apiToken string) cfclient.TunnelClient
}
CloudflareTunnelReconciler reconciles a CloudflareTunnel object
func (*CloudflareTunnelReconciler) Reconcile ¶
func (r *CloudflareTunnelReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile moves the current state of the cluster closer to the desired state for a CloudflareTunnel resource. It handles the full lifecycle of tunnels including creation, adoption of existing tunnels, credential Secret generation, and deletion.
func (*CloudflareTunnelReconciler) SetupWithManager ¶
func (r *CloudflareTunnelReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type CloudflareZoneConfigReconciler ¶
type CloudflareZoneConfigReconciler struct {
client.Client
Scheme *runtime.Scheme
Recorder record.EventRecorder
ClientFactory CredentialFactory
ZoneClientFn func(apiToken string) cfclient.ZoneClient
}
CloudflareZoneConfigReconciler reconciles a CloudflareZoneConfig object
func (*CloudflareZoneConfigReconciler) Reconcile ¶
func (r *CloudflareZoneConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile moves the current state of the cluster closer to the desired state for a CloudflareZoneConfig resource. It handles applying zone settings to Cloudflare and tracking the applied settings count.
func (*CloudflareZoneConfigReconciler) SetupWithManager ¶
func (r *CloudflareZoneConfigReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type CloudflareZoneReconciler ¶
type CloudflareZoneReconciler struct {
client.Client
Scheme *runtime.Scheme
Recorder record.EventRecorder
ClientFactory CredentialFactory
ZoneLifecycleClientFn func(apiToken string) cfclient.ZoneLifecycleClient
}
CloudflareZoneReconciler reconciles a CloudflareZone object
func (*CloudflareZoneReconciler) SetupWithManager ¶
func (r *CloudflareZoneReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager sets up the controller with the Manager.
type ConnectorResourceNames ¶ added in v0.6.0
type ConnectorResourceNames struct {
Deployment string
ConfigMap string
ServiceAccount string
PodDisruptionBudget string
}
ConnectorResourceNames are the deterministic names of the resources the connector sub-reconciler manages for a given CloudflareTunnel.
func ConnectorNames ¶ added in v0.6.0
func ConnectorNames(tun *cloudflarev1alpha1.CloudflareTunnel) ConnectorResourceNames
ConnectorNames returns the deterministic resource names for tun.
When tun.Spec.Connector.NameOverride is set, the Deployment and ServiceAccount are named exactly NameOverride and the ConfigMap is named "<NameOverride>-config". When unset, names fall back to the "cloudflared-<tunnel.metadata.name>" family so the workload type is visible in `kubectl get pods` output cluster-wide.
type CredentialFactory ¶ added in v0.13.0
type CredentialFactory interface {
GetCredentials(ctx context.Context, secretName, namespace string) (cfclient.Credentials, error)
}
CredentialFactory is the subset of cfclient.ClientFactory that LoadCredentials needs. Defined as an interface so reconciler tests can substitute a stub without standing up a real ClientFactory.
type ErrorRouting ¶ added in v0.12.0
ErrorRouting is the routing decision produced by ClassifyCloudflareError.
Reconcilers use the fields as follows:
- Reason: passed to failReconcile (and optionally to a Recorder event) as the condition reason.
- RequeueAfter: passed as the requeue duration. A zero value means "use the reconciler's existing default" — preserves current behavior for the catch-all case. ResetRemoteID==true overrides this: callers should requeue immediately after clearing the stored ID.
- ResetRemoteID: when true, the reconciler MUST clear its stored remote-ID status field before calling failReconcile. The helper does not perform the write because the field name varies per CRD.
func ClassifyCloudflareError ¶ added in v0.12.0
func ClassifyCloudflareError(err error) ErrorRouting
ClassifyCloudflareError walks the predicate ladder (first match wins) and returns the routing decision for err. Predicate order is significant where multiple predicates can match the same status code: the more-specific predicate MUST come first so the failure gets a distinct condition reason rather than the catch-all. Currently:
- IsTunnelHasActiveConnections (400 + code 1022) before IsBadRequest (any 400)
- IsPlanTierRequired (403 + code 1015) before IsPermissionDenied (any 403)
nil err returns the zero ErrorRouting{}; callers MUST gate on err != nil before calling. The zero value's empty Reason would write an invalid "" into the Ready condition if persisted.
type HTTPRouteSourceReconciler ¶ added in v0.6.0
type HTTPRouteSourceReconciler struct {
client.Client
Recorder record.EventRecorder
TxtOwnerID string
AffixConfig cfclient.AffixConfig
}
HTTPRouteSourceReconciler watches HTTPRoutes that carry cloudflare.io/* annotations (either directly or inherited from a parent Gateway) and emits CloudflareDNSRecord + CloudflareTunnelRule CRs.
func (*HTTPRouteSourceReconciler) Reconcile ¶ added in v0.6.0
func (r *HTTPRouteSourceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile processes a single HTTPRoute reconcile request.
func (*HTTPRouteSourceReconciler) SetupWithManager ¶ added in v0.6.0
func (r *HTTPRouteSourceReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager registers the HTTPRouteSourceReconciler with the manager.
type RegistryAction ¶ added in v0.6.0
type RegistryAction string
RegistryAction is the verdict returned by RegistryDecide. Using string constants gives self-documenting log/event output without a separate String() method.
const ( // RegistryActionCreate: no existing DNS record found — proceed to create. RegistryActionCreate RegistryAction = "Create" // RegistryActionReconcile: existing record is owned by us — reconcile content drift. RegistryActionReconcile RegistryAction = "Reconcile" // RegistryActionAdopt: existing TXT is owned by a listed import-owner — rewrite TXT and claim. RegistryActionAdopt RegistryAction = "Adopt" // RegistryActionAdoptOrphan: existing DNS record has no TXT and cloudflare.io/adopt is set. RegistryActionAdoptOrphan RegistryAction = "AdoptOrphan" // RegistryActionRefuseForeignOwner: existing TXT is owned by someone else — do not touch. RegistryActionRefuseForeignOwner RegistryAction = "RefuseForeignOwner" // RegistryActionRefuseNoTXT: existing record has no TXT and adopt is not opted in. RegistryActionRefuseNoTXT RegistryAction = "RefuseNoTXT" )
func RegistryDecide ¶ added in v0.6.0
func RegistryDecide( cfg RegistryConfig, existing *cfclient.DNSRecord, existingTXTContent string, adoptOptIn bool, ) RegistryAction
RegistryDecide applies the §11.3 decision table and returns the action the controller should take for the current reconcile pass.
Parameters:
- cfg: full RegistryConfig (used for TxtOwnerID, TxtImportOwners, TxtImportDecryptKeys)
- existing: the current DNS record at name+type, nil if absent
- existingTXTContent: raw wire content from the companion TXT record, "" if absent
- adoptOptIn: true when the CloudflareDNSRecord carries cloudflare.io/adopt="true"
DecryptPayload errors and DecodeRegistryPayload errors both route to RegistryActionRefuseForeignOwner. This conservatively conflates "foreign-controller wrote an encrypted blob with a key we don't hold" with "TXT corruption" — both cases require human intervention and should not block adoption candidates.
type RegistryConfig ¶ added in v0.6.0
type RegistryConfig struct {
// TxtOwnerID is the ownership token written into companion TXT records.
// Required to enable registry behaviour. When empty, all registry checks
// are skipped and the controller behaves identically to pre-registry releases.
TxtOwnerID string
// TxtImportOwners enumerates prior controllers (e.g. "external-dns") whose
// TXT records this operator may adopt. A TXT whose payload.Owner appears in
// this list, and whose payload is otherwise valid, results in
// RegistryActionAdopt — this controller rewrites the TXT to claim the record.
TxtImportOwners []string // restore — plan §11.3
// AffixConfig controls companion-TXT name derivation.
// The zero value matches external-dns's default affix scheme.
AffixConfig cfclient.AffixConfig
// TxtEncryptAESKey is an optional 32-byte AES-256 key. When non-nil,
// companion TXT payloads are AES-CBC encrypted before writing.
// When nil (the default), payloads are written as plaintext.
TxtEncryptAESKey []byte
// TxtImportDecryptKeys is a list of AES-256 keys tried in order when
// decoding an existing companion TXT. Supports key rotation: include the
// old key here and the new key in TxtEncryptAESKey.
// When empty/nil, only plaintext incoming TXTs can be read. Encrypted TXT
// records will fail to decrypt and route to RefuseForeignOwner.
TxtImportDecryptKeys [][]byte
}
RegistryConfig holds TXT-registry configuration for the DNS record controller. The zero value is valid and disables registry behaviour entirely (TxtOwnerID == "" short-circuits all registry logic).
type RuleDecision ¶ added in v0.6.0
type RuleDecision struct {
Status RuleDecisionStatus
Message string
ResolvedBackend string // URL actually written to config.yaml; "" if not included
}
RuleDecision records why a rule was or was not included.
type RuleDecisionStatus ¶ added in v0.6.0
type RuleDecisionStatus string
RuleDecisionStatus is the per-rule verdict from an aggregation pass.
const ( // RuleIncluded means the rule is present in the rendered config.yaml. RuleIncluded RuleDecisionStatus = "Included" // RuleDuplicateHostname means the rule was excluded because a // higher-precedence rule already claimed one of its hostnames. RuleDuplicateHostname RuleDecisionStatus = "DuplicateHostname" // RuleInvalid means the rule's spec did not pass semantic validation // (exactly-one-backend rule, non-empty hostnames). RuleInvalid RuleDecisionStatus = "Invalid" )
type ServiceSourceReconciler ¶ added in v0.6.0
type ServiceSourceReconciler struct {
client.Client
Recorder record.EventRecorder
TxtOwnerID string
AffixConfig cfclient.AffixConfig
}
ServiceSourceReconciler watches Services that carry cloudflare.io/* annotations and emits CloudflareDNSRecord + CloudflareTunnelRule CRs.
func (*ServiceSourceReconciler) Reconcile ¶ added in v0.6.0
func (r *ServiceSourceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error)
Reconcile processes a single Service reconcile request.
func (*ServiceSourceReconciler) SetupWithManager ¶ added in v0.6.0
func (r *ServiceSourceReconciler) SetupWithManager(mgr ctrl.Manager) error
SetupWithManager registers the ServiceSourceReconciler with the manager.
type TargetKind ¶ added in v0.6.0
type TargetKind string
TargetKind is the kind field of a parsed cloudflare.io/target value.
const ( TargetKindTunnel TargetKind = "tunnel" TargetKindCNAME TargetKind = "cname" TargetKindAddress TargetKind = "address" )
type TargetSpec ¶ added in v0.6.0
type TargetSpec struct {
Kind TargetKind
Name string // populated when Kind=Tunnel
CNAME string // populated when Kind=CNAME
}
TargetSpec is a parsed cloudflare.io/target annotation value.
tunnel:<name> -> Kind=Tunnel, Name=<name> cname:<fqdn> -> Kind=CNAME, CNAME=<fqdn> address -> Kind=Address
func ParseTarget ¶ added in v0.6.0
func ParseTarget(raw string) (TargetSpec, error)
ParseTarget parses a cloudflare.io/target value. Kinds are matched case-sensitively ("tunnel", "cname", "address") — callers MUST use the lowercase canonical form.
Source Files
¶
- annotations.go
- cloudflarednsrecord_controller.go
- cloudflareruleset_controller.go
- cloudflaretunnel_aggregation.go
- cloudflaretunnel_controller.go
- cloudflarezone_controller.go
- cloudflarezoneconfig_controller.go
- connector.go
- credential_load.go
- dns_registry_decision.go
- error_routing.go
- hostname_zone.go
- httproute_source_controller.go
- reconcile_helpers.go
- service_source_controller.go
- source_helpers.go
- tunnel_aggregator.go
- zoneref.go