Documentation
¶
Overview ¶
Package v1alpha3 contains API Schema definitions for the configbutler.ai v1alpha3 API group. +kubebuilder:object:generate=true +groupName=configbutler.ai
Index ¶
- Constants
- Variables
- type AgeEncryptionSpec
- type AgeRecipientsSpec
- type ClusterProvider
- func (p *ClusterProvider) AllowsNamespace(nsName string, nsLabels map[string]string) (bool, error)
- func (p *ClusterProvider) AllowsSourceNamespaceOverride() bool
- func (p *ClusterProvider) AuditRoute() string
- func (in *ClusterProvider) DeepCopy() *ClusterProvider
- func (in *ClusterProvider) DeepCopyInto(out *ClusterProvider)
- func (in *ClusterProvider) DeepCopyObject() runtime.Object
- func (p *ClusterProvider) IsInCluster() bool
- type ClusterProviderAttribution
- type ClusterProviderList
- type ClusterProviderReference
- type ClusterProviderSpec
- type ClusterProviderStatus
- type ClusterResourceRule
- type ClusterWatchRule
- type ClusterWatchRuleList
- type ClusterWatchRuleSpec
- type ClusterWatchRuleStatus
- type CommitMessageSpec
- type CommitRequest
- type CommitRequestList
- type CommitRequestSpec
- type CommitRequestStatus
- type CommitSigningSpec
- type CommitSpec
- type CommitterSpec
- type EncryptionSpec
- type GitProvider
- type GitProviderList
- type GitProviderReference
- type GitProviderSpec
- type GitProviderStatus
- type GitTarget
- func (g *GitTarget) AllowsSourceNamespace(nsName string, nsLabels map[string]string) (bool, error)
- func (g *GitTarget) DeclaresSourceNamespacePolicy() bool
- func (in *GitTarget) DeepCopy() *GitTarget
- func (in *GitTarget) DeepCopyInto(out *GitTarget)
- func (in *GitTarget) DeepCopyObject() runtime.Object
- func (g *GitTarget) EffectivePruneMode() PruneMode
- func (g *GitTarget) IsLocalSource() bool
- func (g *GitTarget) SourceCluster() string
- type GitTargetList
- type GitTargetPlacementSpec
- type GitTargetRetentionStatus
- type GitTargetSpec
- type GitTargetStatus
- type GitTargetStreamsStatus
- type KnownHostsReference
- type LocalSecretReference
- type LocalTargetReference
- type NamespaceMatcher
- func (m *NamespaceMatcher) Declared() bool
- func (in *NamespaceMatcher) DeepCopy() *NamespaceMatcher
- func (in *NamespaceMatcher) DeepCopyInto(out *NamespaceMatcher)
- func (m *NamespaceMatcher) HasSelector() bool
- func (m *NamespaceMatcher) Matches(nsName string, nsLabels map[string]string) (bool, error)
- func (m *NamespaceMatcher) MatchesName(nsName string) bool
- func (m *NamespaceMatcher) SelectorAdmits(nsLabels map[string]string) (bool, error)
- func (m *NamespaceMatcher) ValidateNames() error
- type NamespacedTargetReference
- type OperationType
- type PruneMode
- type PrunePolicy
- type PushStrategy
- type ResourceRule
- func (in *ResourceRule) DeepCopy() *ResourceRule
- func (in *ResourceRule) DeepCopyInto(out *ResourceRule)
- func (r *ResourceRule) DescribeSourceNamespace(ruleNamespace string) string
- func (r *ResourceRule) EffectiveSourceNamespace(ruleNamespace string) string
- func (r *ResourceRule) IsSourceNamespaceWildcard() bool
- func (r *ResourceRule) OverridesSourceNamespace(ruleNamespace string) bool
- type ResourceScope
- type WatchRule
- type WatchRuleList
- type WatchRuleSpec
- type WatchRuleStatus
- type WatchRuleStreamsStatus
Constants ¶
const DefaultClusterProviderName = "default"
DefaultClusterProviderName is the conventionally opinionated ClusterProvider name that an omitted GitTarget.spec.clusterProviderRef points at. That defaulting is its ONLY special behavior: it is an ordinary user-created object that may omit kubeConfig (the operator's own in-cluster config) or set it to mirror a remote cluster, its audit route defaults to its name like every other provider's, and it is never created by the operator.
const SourceNamespaceWildcard = "*"
SourceNamespaceWildcard is the literal rules[].sourceNamespace token meaning "every source namespace this rule's GitTarget admits" — resolved live through GitTarget.spec.allowedSourceNamespaces, never "every namespace that exists".
Variables ¶
var ( // GroupVersion is group version used to register these objects. GroupVersion = schema.GroupVersion{Group: "configbutler.ai", Version: "v1alpha3"} // SchemeBuilder is used to add go types to the GroupVersionKind scheme. SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} // AddToScheme adds the types in this group-version to the given scheme. AddToScheme = SchemeBuilder.AddToScheme )
Functions ¶
This section is empty.
Types ¶
type AgeEncryptionSpec ¶
type AgeEncryptionSpec struct {
// Enabled toggles age-based recipient resolution and bootstrap behavior.
// +optional
// +kubebuilder:default=false
Enabled bool `json:"enabled,omitempty"`
// Recipients defines how recipients are resolved.
// +optional
Recipients AgeRecipientsSpec `json:"recipients,omitempty"`
}
AgeEncryptionSpec configures age recipient resolution behavior.
func (*AgeEncryptionSpec) DeepCopy ¶
func (in *AgeEncryptionSpec) DeepCopy() *AgeEncryptionSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgeEncryptionSpec.
func (*AgeEncryptionSpec) DeepCopyInto ¶
func (in *AgeEncryptionSpec) DeepCopyInto(out *AgeEncryptionSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type AgeRecipientsSpec ¶
type AgeRecipientsSpec struct {
// PublicKeys is a static list of age recipients (age1...).
// +optional
// +kubebuilder:validation:items:MinLength=1
PublicKeys []string `json:"publicKeys,omitempty"`
// ExtractFromSecret derives recipients from all *.agekey entries in encryption.secretRef.
// +optional
// +kubebuilder:default=false
ExtractFromSecret bool `json:"extractFromSecret,omitempty"`
// GenerateWhenMissing creates a date-named *.agekey entry in encryption.secretRef when no *.agekey exists.
// +optional
// +kubebuilder:default=false
GenerateWhenMissing bool `json:"generateWhenMissing,omitempty"`
}
AgeRecipientsSpec defines age recipient source and key generation behavior.
func (*AgeRecipientsSpec) DeepCopy ¶
func (in *AgeRecipientsSpec) DeepCopy() *AgeRecipientsSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgeRecipientsSpec.
func (*AgeRecipientsSpec) DeepCopyInto ¶
func (in *AgeRecipientsSpec) DeepCopyInto(out *AgeRecipientsSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ClusterProvider ¶ added in v0.38.0
type ClusterProvider struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
// spec defines the desired state of ClusterProvider.
// +required
Spec ClusterProviderSpec `json:"spec"`
// status defines the observed state of ClusterProvider.
// +optional
Status ClusterProviderStatus `json:"status,omitempty,omitzero"`
}
ClusterProvider is the cluster-scoped, read-side peer of GitProvider: it names a SOURCE cluster a GitTarget mirrors FROM, and owns that cluster's connectivity credential (spec.kubeConfig), namespace-access authorization (spec.allowedNamespaces), and per-cluster status. Its NAME is the cluster's identity for the watch data plane, and the DEFAULT for its audit route: attribution facts are partitioned by spec.attribution.auditRoute, which falls back to this name. Several providers may name one cluster by declaring one route, which is what an API server with a single audit webhook backend requires. No name is special: "default" is merely what an omitted GitTarget.spec.clusterProviderRef points at, and it may just as well name a remote cluster, since in-cluster-ness follows from spec.kubeConfig (omitted = in-cluster) rather than from the name.
It is cluster-scoped and requires platform-admin permissions to create. A GitTarget may reference it only from a namespace spec.allowedNamespaces admits — deny-by-default, enforced at admission and again before any watch starts.
func (*ClusterProvider) AllowsNamespace ¶ added in v0.38.0
AllowsNamespace reports whether a namespace (by name and labels) may reference this provider from a GitTarget, per spec.allowedNamespaces. It is DENY-BY-DEFAULT: a provider with no allowedNamespaces policy (neither names nor selector) admits no namespace. Names and selector are ORed. Enforced on every reconcile and NOWHERE else: checkSourceAuthorization in internal/controller/gittarget_source_cluster.go is the only non-test caller, and it returns before DeclareForGitTarget, so an unauthorized target starts no watch and writes no Git. Reconcile-time is deliberate rather than incidental — it re-evaluates continuously, so it also covers a policy tightened after the GitTarget was created, which an admission webhook could not see. There is no admission webhook for this (docs/spec/where-validation-lives.md). A malformed selector is a configuration error surfaced to the caller (not a silent allow). A malformed selector is a configuration error surfaced to the caller (not a silent allow).
It is one of two thin wrappers over NamespaceMatcher.Matches — the other being GitTarget.AllowsSourceNamespace — so the control-cluster and source-cluster policies can never drift in their deny-by-default, names-OR-selector semantics. The labels passed here are always CONTROL-cluster Namespace labels.
func (*ClusterProvider) AllowsSourceNamespaceOverride ¶ added in v0.39.0
func (p *ClusterProvider) AllowsSourceNamespaceOverride() bool
AllowsSourceNamespaceOverride reports whether this provider delegates source-namespace selection to the GitTargets it admits. See the field's documentation: false (the default) means a WatchRule mirroring through this provider may watch only its own namespace.
func (*ClusterProvider) AuditRoute ¶ added in v0.39.0
func (p *ClusterProvider) AuditRoute() string
AuditRoute is the identity this provider's attribution facts are keyed under: the route its cluster's audit events arrive on, defaulting to the provider's own name. It is resolved through this method rather than read off the field so no caller ever handles the empty case, the same shape as (api/v1alpha3).GitTarget.SourceCluster().
The default is what makes this change invisible to an existing install: one ClusterProvider per cluster already partitions its facts by name, so an unset field resolves exactly what it always resolved. Deliberately NOT conditional on locality: defaulting an in-cluster provider to the literal "default" would make that name reserved for the local cluster again, a rule this project enforced with CEL and then reversed before shipping (docs/finished/multi-cluster-author-attribution.md).
func (*ClusterProvider) DeepCopy ¶ added in v0.38.0
func (in *ClusterProvider) DeepCopy() *ClusterProvider
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProvider.
func (*ClusterProvider) DeepCopyInto ¶ added in v0.38.0
func (in *ClusterProvider) DeepCopyInto(out *ClusterProvider)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*ClusterProvider) DeepCopyObject ¶ added in v0.38.0
func (in *ClusterProvider) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (*ClusterProvider) IsInCluster ¶ added in v0.38.0
func (p *ClusterProvider) IsInCluster() bool
IsInCluster reports whether this provider represents the operator's own (in-cluster) cluster — i.e. it has no kubeConfig. The provider name is irrelevant: any name, including "default", may either omit kubeConfig for the in-cluster client or set it for a remote cluster.
type ClusterProviderAttribution ¶ added in v0.39.0
type ClusterProviderAttribution struct {
// AuditRoute is the route this cluster's audit events arrive on. The sender is the API server's
// webhook backend (https://kubernetes.io/docs/tasks/debug/debug-cluster/audit/#webhook-backend),
// and this is the <name> segment its configured URL ends in: /audit-webhook/<name>. When several
// logical clusters share one backend it is instead the value of the audit-event annotation named
// by --author-attribution-audit-route-annotation-key.
//
// It partitions the attribution facts, so two ClusterProviders carrying the same route read one
// cluster's facts, and two carrying different routes can never cross-credit an author.
//
// Empty means metadata.name. Set it when several ClusterProviders name one cluster, since an API
// server has one webhook backend and so posts under one route: every other provider for that
// cluster must be pointed at the same route or it resolves no authors at all. Set it also when
// the events are labelled for something other than this object, such as a kcp logical cluster.
// +optional
// +kubebuilder:validation:MaxLength=253
// +kubebuilder:validation:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
AuditRoute string `json:"auditRoute,omitempty"`
}
ClusterProviderAttribution holds the per-cluster author-attribution settings. It exists as a block so later per-cluster knobs (grace, mode) have a home beside auditRoute.
func (*ClusterProviderAttribution) DeepCopy ¶ added in v0.39.0
func (in *ClusterProviderAttribution) DeepCopy() *ClusterProviderAttribution
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProviderAttribution.
func (*ClusterProviderAttribution) DeepCopyInto ¶ added in v0.39.0
func (in *ClusterProviderAttribution) DeepCopyInto(out *ClusterProviderAttribution)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ClusterProviderList ¶ added in v0.38.0
type ClusterProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ClusterProvider `json:"items"`
}
ClusterProviderList contains a list of ClusterProvider.
func (*ClusterProviderList) DeepCopy ¶ added in v0.38.0
func (in *ClusterProviderList) DeepCopy() *ClusterProviderList
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProviderList.
func (*ClusterProviderList) DeepCopyInto ¶ added in v0.38.0
func (in *ClusterProviderList) DeepCopyInto(out *ClusterProviderList)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*ClusterProviderList) DeepCopyObject ¶ added in v0.38.0
func (in *ClusterProviderList) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type ClusterProviderReference ¶ added in v0.38.0
type ClusterProviderReference struct {
// API Group of the referent.
// +kubebuilder:default=configbutler.ai
// +kubebuilder:validation:Enum=configbutler.ai
Group string `json:"group,omitempty"`
// Kind of the referent.
// Optional because this reference currently only supports a single kind (ClusterProvider).
// +optional
// +kubebuilder:validation:Enum=ClusterProvider
// +kubebuilder:default=ClusterProvider
Kind string `json:"kind,omitempty"`
// Name of the referent.
// +required
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
}
ClusterProviderReference references the cluster-scoped ClusterProvider a GitTarget sources FROM. It is the read-side peer of GitProviderReference (which names the WRITE destination): a GitTarget names one ClusterProvider by name and its author-attribution facts, kube client, and namespace authorization all follow from that single reference. Group and Kind are typed (with defaults) for consistency with the project's other typed references.
func (*ClusterProviderReference) DeepCopy ¶ added in v0.38.0
func (in *ClusterProviderReference) DeepCopy() *ClusterProviderReference
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProviderReference.
func (*ClusterProviderReference) DeepCopyInto ¶ added in v0.38.0
func (in *ClusterProviderReference) DeepCopyInto(out *ClusterProviderReference)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ClusterProviderSpec ¶ added in v0.38.0
type ClusterProviderSpec struct {
// KubeConfig names the SOURCE CLUSTER this provider represents and the credentials to reach it
// (Flux's meta.KubeConfigReference, embedded verbatim). OMITTED means the operator's own
// in-cluster cluster, for any provider name. IMMUTABLE.
//
// The referenced Secret is resolved from the operator's namespace, so a cluster's credential
// never has to live on that cluster. Only secretRef is honored; configMapRef is rejected. When
// secretRef.key is empty the resolver reads "value" then "value.yaml" (Flux's order). Unsafe
// kubeconfigs (exec auth, insecure-skip-tls-verify) are rejected with Validated=False unless the
// operator opts in via flags.
// +optional
KubeConfig *meta.KubeConfigReference `json:"kubeConfig,omitempty"`
// AllowedNamespaces is the deny-by-default policy for which CONTROL-CLUSTER namespaces may
// reference this provider from a GitTarget. Empty (or omitted) means no namespace may
// reference it. Its selector matches labels on Namespaces in the control cluster — the
// cluster the operator's own CRs live in — never on the source cluster this provider names.
// +optional
AllowedNamespaces *NamespaceMatcher `json:"allowedNamespaces,omitempty"`
// AllowSourceNamespaceOverride delegates SOURCE-namespace selection to the GitTargets this
// provider admits. While false (the default) a WatchRule mirroring through this provider may
// watch only its OWN namespace, whatever any GitTarget policy says.
//
// It grants no access by itself: an admitted GitTarget must still admit the namespace in its
// spec.allowedSourceNamespaces, and the source credential's own RBAC remains the hard maximum.
// What it delegates is the AUTHORITY to choose, so set it only when the owners of admitted
// GitTargets are trusted to pick a subset of what that credential may read. Every
// cross-namespace request needs it, including a rules[].sourceNamespace of "*". It does not
// apply to ClusterWatchRule, which selects no namespaces at all.
// +optional
// +kubebuilder:default=false
AllowSourceNamespaceOverride bool `json:"allowSourceNamespaceOverride,omitempty"`
// QPS overrides the operator's outgoing kube-client query-per-second throttle for this
// cluster's watches and discovery. Omitted, the operator-wide --source-cluster-qps applies.
// Ignored when kubeConfig is omitted (the in-cluster client is not per-provider).
// +optional
// +kubebuilder:validation:Minimum=1
QPS *int32 `json:"qps,omitempty"`
// Burst overrides the operator's outgoing kube-client burst for this cluster. Omitted, the
// operator-wide --source-cluster-burst applies. Ignored when kubeConfig is omitted.
// +optional
// +kubebuilder:validation:Minimum=1
Burst *int32 `json:"burst,omitempty"`
// Attribution groups this cluster's author-attribution settings. The block is spelled
// "attribution" rather than "authorAttribution" even though the operator flags are
// --author-attribution-*: the prefix groups a flat flag namespace, and a block on a
// source-cluster object already supplies that scope.
// +optional
Attribution *ClusterProviderAttribution `json:"attribution,omitempty"`
}
ClusterProviderSpec defines the desired state of ClusterProvider.
kubeConfig is IMMUTABLE and OPTIONAL: which physical cluster a provider name means must not silently change under the GitTargets bound to it, and an OMITTED kubeConfig means the operator's own (in-cluster) cluster. That choice is free for EVERY name, "default" included — a provider named "default" may just as well carry a kubeConfig and mirror a remote cluster. The name is an identity, not a claim about which cluster it points at.
+kubebuilder:validation:XValidation:rule="has(self.kubeConfig) == has(oldSelf.kubeConfig) && (!has(self.kubeConfig) || self.kubeConfig == oldSelf.kubeConfig)",message="spec.kubeConfig is immutable; delete and recreate the ClusterProvider to point a name at a different cluster"
configMapRef (Flux workload-identity auth) is present in meta.KubeConfigReference's schema but deferred here; reject it so the v1alpha3 contract is "secretRef only". +kubebuilder:validation:XValidation:rule="!has(self.kubeConfig) || !has(self.kubeConfig.configMapRef)",message="spec.kubeConfig.configMapRef (workload-identity auth) is not yet supported; use secretRef"
secretRef.name comes from the external meta.KubeConfigReference schema, which marks it required but permits the empty string; an empty name can never resolve a Secret, so reject it here. +kubebuilder:validation:XValidation:rule="!has(self.kubeConfig) || !has(self.kubeConfig.secretRef) || size(self.kubeConfig.secretRef.name) > 0",message="spec.kubeConfig.secretRef.name must not be empty"
func (*ClusterProviderSpec) DeepCopy ¶ added in v0.38.0
func (in *ClusterProviderSpec) DeepCopy() *ClusterProviderSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProviderSpec.
func (*ClusterProviderSpec) DeepCopyInto ¶ added in v0.38.0
func (in *ClusterProviderSpec) DeepCopyInto(out *ClusterProviderSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ClusterProviderStatus ¶ added in v0.38.0
type ClusterProviderStatus struct {
// ObservedGeneration is the latest generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Conditions report the provider's readiness: Validated (kubeconfig inputs are safe and
// resolvable, asserted without a network dial) plus the aggregated Ready and the kstatus
// Reconciling/Stalled pair. Runtime reachability/discovery health and a last-audit-event
// timestamp are deferred until authenticated remote ingest wires them from the watch engine.
// +optional
// +listType=map
// +listMapKey=type
// +patchMergeKey=type
// +patchStrategy=merge
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
}
ClusterProviderStatus defines the observed state of ClusterProvider.
func (*ClusterProviderStatus) DeepCopy ¶ added in v0.38.0
func (in *ClusterProviderStatus) DeepCopy() *ClusterProviderStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterProviderStatus.
func (*ClusterProviderStatus) DeepCopyInto ¶ added in v0.38.0
func (in *ClusterProviderStatus) DeepCopyInto(out *ClusterProviderStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ClusterResourceRule ¶
type ClusterResourceRule struct {
// Operations to watch. If empty, watches all operations (CREATE, UPDATE, DELETE).
// Supports: CREATE, UPDATE, DELETE, or * (wildcard for all operations).
// Examples:
// - ["CREATE", "UPDATE"] watches only creation and updates
// - ["*"] or [] watches all operations
// +optional
Operations []OperationType `json:"operations,omitempty"`
// APIGroups to match. Empty string ("") matches the core API group.
// If omitted, GitOps Reverser resolves the resource name across all served API groups.
// Wildcards supported: "*" matches all groups.
// Examples:
// - [""] matches core API (nodes, namespaces)
// - ["rbac.authorization.k8s.io"] matches RBAC resources
// - ["*"] matches all groups
// - [] resolves a named resource only when it is served by one API group
// +optional
APIGroups []string `json:"apiGroups,omitempty"`
// APIVersions to match. If empty, uses the preferred served version for each group/resource.
// Wildcards supported: "*" matches all versions.
// Examples:
// - ["v1"] matches only v1 version
// - ["*"] matches all served versions
// - [] matches the preferred served version
// +optional
APIVersions []string `json:"apiVersions,omitempty"`
// Resources to match (plural names like "nodes", "clusterroles").
// This field is required and determines which resource types trigger this rule.
// Wildcard semantics follow Kubernetes admission webhook patterns:
// - "*" matches all resources
// - "nodes" matches exactly nodes
// - "pods" matches exactly pods (for namespaced scope)
//
// Note: Subresources cannot be added here. Values containing "/" (for example
// "pods/log" or "pods/*") are rejected by the API because subresources are
// not supported for list/watch snapshot planning. Prefix/suffix wildcards
// like "pod*" or "*.example.com" are NOT supported. Use exact matches or the
// "*" wildcard for broad matching.
// +required
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:items:MinLength=1
// +kubebuilder:validation:items:Pattern=`^[^/]*$`
Resources []string `json:"resources"`
// Scope is REMOVED as a choice: a ClusterWatchRule is cluster-scoped only, so "Cluster" is the
// only accepted value and also the default, making the field omittable. To watch NAMESPACED
// resources, use a WatchRule in the tenant namespace and set spec.rules[].sourceNamespace.
//
// Deprecated: ClusterWatchRule is cluster-scope-only; use WatchRule with
// spec.rules[].sourceNamespace for namespaced resources. Removed one release from now, or at
// v1beta1.
// +optional
// +kubebuilder:default=Cluster
// +kubebuilder:validation:Enum=Cluster
Scope ResourceScope `json:"scope,omitempty"`
}
ClusterResourceRule defines which CLUSTER-SCOPED resources to watch. It deliberately has no sourceNamespace: cluster-scoped objects have no namespace, so there is nothing to select.
func (*ClusterResourceRule) DeepCopy ¶
func (in *ClusterResourceRule) DeepCopy() *ClusterResourceRule
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterResourceRule.
func (*ClusterResourceRule) DeepCopyInto ¶
func (in *ClusterResourceRule) DeepCopyInto(out *ClusterResourceRule)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ClusterWatchRule ¶
type ClusterWatchRule struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata.
// +optional
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
// spec defines the desired state of ClusterWatchRule.
// +required
Spec ClusterWatchRuleSpec `json:"spec"`
// status defines the observed state of ClusterWatchRule.
// +optional
Status ClusterWatchRuleStatus `json:"status,omitempty"`
}
ClusterWatchRule selects CLUSTER-SCOPED resources on the source cluster its GitTarget mirrors from — Nodes, PersistentVolumes, StorageClasses, ClusterRoles, CRDs, and the like. Scope is carried by the rule KIND, so it has no per-rule scope choice and no source-namespace selection.
It is cluster-scoped and requires cluster-admin permissions. Its targetRef names a GitTarget (namespace required), whose namespace must be admitted by that target's ClusterProvider. To mirror NAMESPACED resources use a WatchRule in the tenant namespace and set spec.rules[].sourceNamespace, whose "*" reaches every namespace the GitTarget admits.
func (*ClusterWatchRule) DeepCopy ¶
func (in *ClusterWatchRule) DeepCopy() *ClusterWatchRule
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWatchRule.
func (*ClusterWatchRule) DeepCopyInto ¶
func (in *ClusterWatchRule) DeepCopyInto(out *ClusterWatchRule)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*ClusterWatchRule) DeepCopyObject ¶
func (in *ClusterWatchRule) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type ClusterWatchRuleList ¶
type ClusterWatchRuleList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ClusterWatchRule `json:"items"`
}
ClusterWatchRuleList contains a list of ClusterWatchRule.
func (*ClusterWatchRuleList) DeepCopy ¶
func (in *ClusterWatchRuleList) DeepCopy() *ClusterWatchRuleList
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWatchRuleList.
func (*ClusterWatchRuleList) DeepCopyInto ¶
func (in *ClusterWatchRuleList) DeepCopyInto(out *ClusterWatchRuleList)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*ClusterWatchRuleList) DeepCopyObject ¶
func (in *ClusterWatchRuleList) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type ClusterWatchRuleSpec ¶
type ClusterWatchRuleSpec struct {
// TargetRef references the GitTarget to use.
// Must specify namespace.
// +required
TargetRef NamespacedTargetReference `json:"targetRef"`
// Rules define which CLUSTER-SCOPED resources to watch.
// Multiple rules create a logical OR - a resource matching ANY rule is watched.
// A rule that resolves to no cluster-scoped type simply watches nothing; use a WatchRule with
// spec.rules[].sourceNamespace for namespaced resources.
// +required
// +kubebuilder:validation:MinItems=1
Rules []ClusterResourceRule `json:"rules"`
}
ClusterWatchRuleSpec defines the desired state of ClusterWatchRule.
func (*ClusterWatchRuleSpec) DeclaresNamespacedScope ¶ added in v0.39.0
func (s *ClusterWatchRuleSpec) DeclaresNamespacedScope() bool
DeclaresNamespacedScope reports whether a STORED ClusterWatchRule still selects namespaced resources through the removed scope choice. Admission rejects the value, but an object written before this release keeps it in etcd, so the compile path must refuse it rather than let the rule resolve as if it had asked for cluster scope.
It keys on the STORED value, not on what the selector happens to resolve: `resources: ["*"]` legitimately resolves cluster-scoped records, so inferring the refusal from the resolution would be ambiguous exactly where it matters.
func (*ClusterWatchRuleSpec) DeepCopy ¶
func (in *ClusterWatchRuleSpec) DeepCopy() *ClusterWatchRuleSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWatchRuleSpec.
func (*ClusterWatchRuleSpec) DeepCopyInto ¶
func (in *ClusterWatchRuleSpec) DeepCopyInto(out *ClusterWatchRuleSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ClusterWatchRuleStatus ¶
type ClusterWatchRuleStatus struct {
// ObservedGeneration is the latest generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Conditions represent the latest available observations of the ClusterWatchRule's state.
// +optional
// +listType=map
// +listMapKey=type
// +patchMergeKey=type
// +patchStrategy=merge
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
// Streams is the bounded stream-readiness roll-up for the types this rule resolves.
// +optional
Streams *WatchRuleStreamsStatus `json:"streams,omitempty"`
}
ClusterWatchRuleStatus defines the observed state of ClusterWatchRule.
func (*ClusterWatchRuleStatus) DeepCopy ¶
func (in *ClusterWatchRuleStatus) DeepCopy() *ClusterWatchRuleStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterWatchRuleStatus.
func (*ClusterWatchRuleStatus) DeepCopyInto ¶
func (in *ClusterWatchRuleStatus) DeepCopyInto(out *ClusterWatchRuleStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type CommitMessageSpec ¶
type CommitMessageSpec struct {
// EventTemplate is a Go text/template string for per-event commit messages
// (used when commitWindow is "0s"; one event per commit).
// Available variables: Operation, Group, Version, Resource, Namespace, Name,
// APIVersion, Username, GitTarget.
// +optional
EventTemplate string `json:"eventTemplate,omitempty"`
// ReconcileTemplate is a Go text/template string for reconcile commit messages
// (the mark-and-sweep reconcile path; one commit per synced type).
// Available variables: Count, GitTarget, Group, Version, Resource, APIVersion, Revision.
// Group/Version/Resource/APIVersion name the synced type for a per-type reconcile and
// Revision is the cluster resourceVersion the reconcile was pinned to; both are empty
// for a whole-target reconcile or a pure sweep, so a template referencing them must
// render cleanly when they are absent (the default guards them with {{if}}).
// +optional
ReconcileTemplate string `json:"reconcileTemplate,omitempty"`
// GroupTemplate is a Go text/template string for grouped commit messages
// (the commit-window path; one commit per (author, gitTarget) group
// produced by the batching pipeline).
// Available variables: Author, GitTarget, Count, Operations (map of
// CREATE/UPDATE/DELETE counts), Resources (slice of {Group, Version,
// Resource, Namespace, Name}).
// +optional
GroupTemplate string `json:"groupTemplate,omitempty"`
}
CommitMessageSpec configures commit message formatting.
func (*CommitMessageSpec) DeepCopy ¶
func (in *CommitMessageSpec) DeepCopy() *CommitMessageSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitMessageSpec.
func (*CommitMessageSpec) DeepCopyInto ¶
func (in *CommitMessageSpec) DeepCopyInto(out *CommitMessageSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type CommitRequest ¶
type CommitRequest struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
// spec defines the desired state of CommitRequest
// +required
Spec CommitRequestSpec `json:"spec"`
// status defines the observed state of CommitRequest
// +optional
Status CommitRequestStatus `json:"status,omitempty,omitzero"`
}
CommitRequest is a one-shot "save" signal: creating one finalizes the open commit window for the referenced GitTarget instead of waiting for the silence timer. The resulting commit SHA is reported back in status.
func (*CommitRequest) DeepCopy ¶
func (in *CommitRequest) DeepCopy() *CommitRequest
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitRequest.
func (*CommitRequest) DeepCopyInto ¶
func (in *CommitRequest) DeepCopyInto(out *CommitRequest)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*CommitRequest) DeepCopyObject ¶
func (in *CommitRequest) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type CommitRequestList ¶
type CommitRequestList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []CommitRequest `json:"items"`
}
CommitRequestList contains a list of CommitRequest.
func (*CommitRequestList) DeepCopy ¶
func (in *CommitRequestList) DeepCopy() *CommitRequestList
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitRequestList.
func (*CommitRequestList) DeepCopyInto ¶
func (in *CommitRequestList) DeepCopyInto(out *CommitRequestList)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*CommitRequestList) DeepCopyObject ¶
func (in *CommitRequestList) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type CommitRequestSpec ¶
type CommitRequestSpec struct {
// TargetRef names the GitTarget whose open commit window to finalize.
// The GitTarget must be in the same namespace as this CommitRequest.
// +required
TargetRef LocalTargetReference `json:"targetRef"`
// Message is an optional commit message for the finalized commit. When
// omitted, the generated grouped-commit message is used.
//
// When present it is limited to 1-1024 Unicode characters and used
// verbatim as the commit message. Newlines are allowed so a subject and
// body can be supplied; all other ASCII control characters (including tab
// and carriage return) are rejected.
// +optional
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=1024
// +kubebuilder:validation:Pattern=`^[^\x00-\x09\x0B-\x1F\x7F]*$`
Message string `json:"message,omitempty"`
// CloseDelaySeconds optionally delays closing the open commit window for this
// many seconds after the CommitRequest attaches to a matching open window, acting as
// an extra collect window: matching changes that arrive in the meantime still join
// that window and are included in the resulting commit. Omitted or 0 closes the
// window as soon as the CommitRequest attaches. The window can still be closed
// earlier by another author's change or by the provider's commit window timer,
// exactly as without a CommitRequest.
// +optional
// +kubebuilder:validation:Minimum=0
// +kubebuilder:validation:Maximum=300
CloseDelaySeconds int32 `json:"closeDelaySeconds,omitempty"`
}
CommitRequestSpec defines the desired state of CommitRequest. The spec is immutable after creation: a CEL validation rule rejects any update that changes it, so a delayed audit event always acts on the spec the object was created with.
+kubebuilder:validation:XValidation:rule="self == oldSelf",message="CommitRequest spec is immutable after creation"
func (*CommitRequestSpec) DeepCopy ¶
func (in *CommitRequestSpec) DeepCopy() *CommitRequestSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitRequestSpec.
func (*CommitRequestSpec) DeepCopyInto ¶
func (in *CommitRequestSpec) DeepCopyInto(out *CommitRequestSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type CommitRequestStatus ¶
type CommitRequestStatus struct {
// ObservedGeneration is the most recent generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Conditions report the request's progress and terminal outcome: the Ready
// summary, the kstatus Reconciling/Stalled pair, and the domain conditions
// AuthorAttributed and Pushed.
// +optional
// +listType=map
// +listMapKey=type
// +patchStrategy=merge
// +patchMergeKey=type
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
// Branch is the Git branch the GitTarget commits to. Populated once the
// finalize resolves.
// +optional
Branch string `json:"branch,omitempty"`
// SHA is the resulting commit SHA. Set when the commit was pushed (Pushed=True).
// +optional
SHA string `json:"sha,omitempty"`
}
CommitRequestStatus defines the observed state of CommitRequest. Progress and outcome are reported entirely through conditions (kstatus-compatible), so the object carries no lifecycle phase string:
- Ready (summary): True once the request reached a terminal outcome that is not an error — a pushed commit, or a benign no-commit (nothing to save, already present, or a foreign open window). False while in progress or when it failed.
- Reconciling / Stalled: the kstatus progress / blocked pair. Reconciling=True while finalizing; Stalled=True when the finalize failed and needs attention.
- AuthorAttributed (domain): binary and settled immediately. True (AttributedFromAdmission) when the submitter captured at admission named the commit author; False (CommitterFallback) when capture ran but no admission record exists, or False (AuthorCaptureDisabled) when capture is disabled. In either False case the request claims no actor. False is not a failure and does not affect Ready; the final Git author remains the matching watch window's author.
- Pushed (domain): True once the commit is in the remote repository.
func (*CommitRequestStatus) DeepCopy ¶
func (in *CommitRequestStatus) DeepCopy() *CommitRequestStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitRequestStatus.
func (*CommitRequestStatus) DeepCopyInto ¶
func (in *CommitRequestStatus) DeepCopyInto(out *CommitRequestStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type CommitSigningSpec ¶
type CommitSigningSpec struct {
// SecretRef references the Secret containing the signing key material.
// Expected keys will be defined by the signing implementation.
SecretRef LocalSecretReference `json:"secretRef"`
// GenerateWhenMissing causes the operator to generate signing key material
// in the referenced Secret when it is missing.
// +optional
// +kubebuilder:default=false
GenerateWhenMissing bool `json:"generateWhenMissing,omitempty"`
}
CommitSigningSpec configures commit signing.
func (*CommitSigningSpec) DeepCopy ¶
func (in *CommitSigningSpec) DeepCopy() *CommitSigningSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitSigningSpec.
func (*CommitSigningSpec) DeepCopyInto ¶
func (in *CommitSigningSpec) DeepCopyInto(out *CommitSigningSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type CommitSpec ¶
type CommitSpec struct {
// Committer configures the operator identity written as the commit committer.
// When signing is enabled, Email must be a verified address on the account
// that owns the signing key.
// +optional
Committer *CommitterSpec `json:"committer,omitempty"`
// Message configures commit message formatting.
// +optional
Message *CommitMessageSpec `json:"message,omitempty"`
// Signing configures commit signing.
// +optional
Signing *CommitSigningSpec `json:"signing,omitempty"`
}
CommitSpec configures how gitops-reverser creates commits for a GitProvider.
func (*CommitSpec) DeepCopy ¶
func (in *CommitSpec) DeepCopy() *CommitSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitSpec.
func (*CommitSpec) DeepCopyInto ¶
func (in *CommitSpec) DeepCopyInto(out *CommitSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type CommitterSpec ¶
type CommitterSpec struct {
// Name is the git committer name.
// +optional
// +kubebuilder:default="GitOps Reverser"
Name string `json:"name,omitempty"`
// Email is the git committer email.
// +optional
// +kubebuilder:default="noreply@configbutler.ai"
Email string `json:"email,omitempty"`
}
CommitterSpec configures the bot identity used as the commit committer.
func (*CommitterSpec) DeepCopy ¶
func (in *CommitterSpec) DeepCopy() *CommitterSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommitterSpec.
func (*CommitterSpec) DeepCopyInto ¶
func (in *CommitterSpec) DeepCopyInto(out *CommitterSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type EncryptionSpec ¶
type EncryptionSpec struct {
// Provider selects the encryption provider.
// +kubebuilder:default=sops
// +kubebuilder:validation:Enum=sops
Provider string `json:"provider"`
// SecretRef references namespace-local Secret data used by the encryption provider.
// +optional
SecretRef LocalSecretReference `json:"secretRef,omitempty"`
// Age configures age-specific encryption behavior for SOPS.
// +optional
Age *AgeEncryptionSpec `json:"age,omitempty"`
}
EncryptionSpec configures Secret encryption behavior for git writes.
func (*EncryptionSpec) DeepCopy ¶
func (in *EncryptionSpec) DeepCopy() *EncryptionSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EncryptionSpec.
func (*EncryptionSpec) DeepCopyInto ¶
func (in *EncryptionSpec) DeepCopyInto(out *EncryptionSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitProvider ¶
type GitProvider struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
// spec defines the desired state of GitProvider
// +required
Spec GitProviderSpec `json:"spec"`
// status defines the observed state of GitProvider
// +optional
Status GitProviderStatus `json:"status,omitempty,omitzero"`
}
GitProvider is the Schema for the gitproviders API.
func (*GitProvider) DeepCopy ¶
func (in *GitProvider) DeepCopy() *GitProvider
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitProvider.
func (*GitProvider) DeepCopyInto ¶
func (in *GitProvider) DeepCopyInto(out *GitProvider)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*GitProvider) DeepCopyObject ¶
func (in *GitProvider) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type GitProviderList ¶
type GitProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []GitProvider `json:"items"`
}
GitProviderList contains a list of GitProvider.
func (*GitProviderList) DeepCopy ¶
func (in *GitProviderList) DeepCopy() *GitProviderList
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitProviderList.
func (*GitProviderList) DeepCopyInto ¶
func (in *GitProviderList) DeepCopyInto(out *GitProviderList)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*GitProviderList) DeepCopyObject ¶
func (in *GitProviderList) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type GitProviderReference ¶
type GitProviderReference struct {
// API Group of the referent.
// +kubebuilder:default=configbutler.ai
// +kubebuilder:validation:Enum=configbutler.ai
Group string `json:"group,omitempty"`
// Kind of the referent.
// Optional because this reference currently only supports a single kind (GitProvider).
// Keeping it optional allows users to omit it while still benefiting from CRD defaulting.
// +optional
// +kubebuilder:validation:Enum=GitProvider
// +kubebuilder:default=GitProvider
Kind string `json:"kind,omitempty"`
// Name of the referent.
// +required
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
}
GitProviderReference references the GitProvider that backs a GitTarget. Many GitTargets may reference the same GitProvider; the reference is always to a GitProvider in the GitTarget's own namespace. Group and Kind are typed (with defaults) for consistency with the project's other local references and so the schema is explicit about what it accepts — currently only configbutler.ai/GitProvider.
func (*GitProviderReference) DeepCopy ¶
func (in *GitProviderReference) DeepCopy() *GitProviderReference
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitProviderReference.
func (*GitProviderReference) DeepCopyInto ¶
func (in *GitProviderReference) DeepCopyInto(out *GitProviderReference)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitProviderSpec ¶
type GitProviderSpec struct {
// URL of the repository (HTTP/SSH).
// Immutable: delete and recreate the GitProvider to point at a different repository.
// +kubebuilder:validation:MinLength=1
URL string `json:"url"`
// SecretRef for authentication credentials (may be nil for public repos)
SecretRef *LocalSecretReference `json:"secretRef,omitempty"`
// KnownHostsRef optionally points at a namespace-local ConfigMap or Secret holding SSH
// known_hosts, so host trust can be centralized across GitProviders on the same host instead
// of repeated in every credentials Secret. It is used only for SSH and ignored for HTTP auth.
// Host keys are resolved in priority order: the credentials Secret's own known_hosts, then this
// ref, then the install-level default known-hosts ConfigMap; if none yields valid keys, SSH
// fails closed.
// +optional
KnownHostsRef *KnownHostsReference `json:"knownHostsRef,omitempty"`
// AllowedBranches restricts which branches can be written to.
// +required
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:items:MinLength=1
AllowedBranches []string `json:"allowedBranches"`
// Push controls how events are coalesced into commits before pushing.
// +optional
Push *PushStrategy `json:"push,omitempty"`
// Commit configures commit identity, message formatting, and signing behavior.
// +optional
Commit *CommitSpec `json:"commit,omitempty"`
}
GitProviderSpec defines the desired state of GitProvider.
Only the repository URL is immutable. The URL is the destination identity that every referencing GitTarget materializes into; changing it would silently point those targets at a different repository and orphan their existing materialization (the same reason a GitTarget's destination is immutable). To repoint, delete and recreate the GitProvider. Everything else here is operational and deliberately stays mutable — notably allowedBranches (widening or narrowing the writable set is a normal change that must not require tearing down every GitTarget), plus auth, push tuning, and commit identity/signing.
+kubebuilder:validation:XValidation:rule="self.url == oldSelf.url",message="spec.url is immutable; delete and recreate the GitProvider to point at a different repository"
func (*GitProviderSpec) DeepCopy ¶
func (in *GitProviderSpec) DeepCopy() *GitProviderSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitProviderSpec.
func (*GitProviderSpec) DeepCopyInto ¶
func (in *GitProviderSpec) DeepCopyInto(out *GitProviderSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitProviderStatus ¶
type GitProviderStatus struct {
// ObservedGeneration is the latest generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Conditions report repository validation and commit configuration readiness:
// the Ready summary plus the kstatus Reconciling/Stalled pair.
// +optional
// +listType=map
// +listMapKey=type
// +patchMergeKey=type
// +patchStrategy=merge
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
// SigningPublicKey is the operator's SSH signing public key in authorized_keys format.
// Register this as a signing key on your git platform.
// Only populated when commit.signing is configured and a signing key is available.
// +optional
SigningPublicKey string `json:"signingPublicKey,omitempty"`
}
GitProviderStatus defines the observed state of GitProvider.
func (*GitProviderStatus) DeepCopy ¶
func (in *GitProviderStatus) DeepCopy() *GitProviderStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitProviderStatus.
func (*GitProviderStatus) DeepCopyInto ¶
func (in *GitProviderStatus) DeepCopyInto(out *GitProviderStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitTarget ¶
type GitTarget struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
// spec defines the desired state of GitTarget
// +required
Spec GitTargetSpec `json:"spec"`
// status defines the observed state of GitTarget
// +optional
Status GitTargetStatus `json:"status,omitempty,omitzero"`
}
GitTarget is the Schema for the gittargets API.
func (*GitTarget) AllowsSourceNamespace ¶ added in v0.39.0
AllowsSourceNamespace reports whether a SOURCE-cluster namespace (by name and by the labels it carries IN THE SOURCE CLUSTER) may be mirrored into this target, per spec.allowedSourceNamespaces.
It is the source-side twin of ClusterProvider.AllowsNamespace, and both are thin wrappers over NamespaceMatcher.Matches so the two policies cannot drift. It answers only the POLICY question: the delegation flag, the provider's own admission of this target's namespace, and the three-valued "can the labels be read at all" question are the caller's (see internal/authz). An undeclared policy admits nothing here — callers apply the legacy rule themselves.
func (*GitTarget) DeclaresSourceNamespacePolicy ¶ added in v0.39.0
DeclaresSourceNamespacePolicy reports whether this target declares spec.allowedSourceNamespaces at all. A declared policy is EXHAUSTIVE — it bounds every WatchRule item writing here, with no self-namespace exception — while an absent one leaves a WatchRule its own namespace. Callers must branch on this rather than on emptiness: a declared-but-empty policy admits nothing.
func (*GitTarget) DeepCopy ¶
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitTarget.
func (*GitTarget) DeepCopyInto ¶
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*GitTarget) DeepCopyObject ¶
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (*GitTarget) EffectivePruneMode ¶ added in v0.39.0
EffectivePruneMode is the mode this GitTarget's writes are subject to, with the omitted-field default applied. It is the only supported way to read the policy: reading spec.prune.mode directly would treat a legacy GitTarget as if it had no mode rather than OnEvent.
func (*GitTarget) IsLocalSource ¶ added in v0.38.0
IsLocalSource reports whether this GitTarget references the "default" ClusterProvider, which the watch data plane maps to its local cluster context. It is a NAME test, not a claim about the physical cluster: a "default" provider may carry a kubeConfig. It only supplies the pre-discovery default for SourceClusterReachable, which the watch manager overwrites as soon as it is wired.
func (*GitTarget) SourceCluster ¶ added in v0.38.0
SourceCluster is the identity the watch data plane keys a GitTarget's source cluster on: the referenced ClusterProvider's NAME. It defaults to "default" when clusterProviderRef is unset — so a source-cluster-unaware caller still gets a concrete, non-empty name, and there is no "" sentinel. That name is a convention, not a claim about which physical cluster it is. The name keys the GVK→GVR registry and the watch context. It is NOT the attribution partition: facts are keyed by the referenced ClusterProvider's AuditRoute(), which defaults to this name but may differ when several providers share one cluster's single audit stream.
type GitTargetList ¶
type GitTargetList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []GitTarget `json:"items"`
}
GitTargetList contains a list of GitTarget.
func (*GitTargetList) DeepCopy ¶
func (in *GitTargetList) DeepCopy() *GitTargetList
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitTargetList.
func (*GitTargetList) DeepCopyInto ¶
func (in *GitTargetList) DeepCopyInto(out *GitTargetList)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*GitTargetList) DeepCopyObject ¶
func (in *GitTargetList) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type GitTargetPlacementSpec ¶
type GitTargetPlacementSpec struct {
// ByType maps an exact resource type key ("{group}/{version}/{resource}", e.g.
// "v1/configmaps", "apps/v1/deployments", or "v1/secrets"; core resources omit
// the group) to the path template used for a new resource of that type. A path
// selected for a sensitive resource (Secrets, plus any operator-configured
// sensitive type) must be identity-complete so it cannot collide two distinct
// sensitive resources onto one file.
// +optional
ByType map[string]string `json:"byType,omitempty"`
// Default is the path template used for a new resource whose type has no ByType
// entry. Omitted, it falls through to sibling-layout inference and then the
// built-in canonical path. A bundling default (one that is not identity-complete,
// such as "all.yaml") is only valid when a sensitive resource can never reach it
// — give every sensitive type an explicit identity-complete ByType entry.
// +optional
Default string `json:"default,omitempty"`
}
GitTargetPlacementSpec declares where NEW resources are written when no document for their identity exists yet in Git — one exact-type map plus a fallback default template (Option B2 of docs/spec/gittarget-new-file-placement-rules.md). There is deliberately no separate "sensitive" placement block: sensitivity is a write-safety classification the controller owns (encrypt the content, keep the path identity-complete, never append or co-mingle), not a second placement namespace the user has to configure. A user routes Secrets the same way they route anything else — by naming their type in ByType. When a resource's type has no ByType entry and no Default, placement falls back to following the layout already established by sibling resources in the repository, and finally to the canonical, versionless {namespaceOrCluster}/{group}/{resource}/{name}.yaml path when there is nothing to follow. Because that fallback omits the API version, objects that differ only by version share a file; a target that watches several versions of the same group/resource and wants them separated must use a ByType/Default template that includes {version}.
func (*GitTargetPlacementSpec) DeepCopy ¶
func (in *GitTargetPlacementSpec) DeepCopy() *GitTargetPlacementSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitTargetPlacementSpec.
func (*GitTargetPlacementSpec) DeepCopyInto ¶
func (in *GitTargetPlacementSpec) DeepCopyInto(out *GitTargetPlacementSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitTargetRetentionStatus ¶ added in v0.39.0
type GitTargetRetentionStatus struct {
// Mode is the EFFECTIVE spec.prune.mode this roll-up was produced under. It is reported here
// rather than left to be read from the spec because a GitTarget that predates spec.prune has
// no stored value at all, so the spec alone cannot explain why documents are being kept.
// +optional
Mode PruneMode `json:"mode,omitempty"`
// RetainedDocuments is how many managed documents the policy kept that a converged mirror
// would not hold. Zero means a resync ran and found nothing to retain — the mirror is
// converged. An ABSENT retention block means something different: no resync has reported yet.
RetainedDocuments int32 `json:"retainedDocuments"`
// ObservedTime is when this roll-up was last computed. A retention that begins just after a
// reconcile is not visible until the next one, so read this before treating a zero as live.
// +optional
ObservedTime *metav1.Time `json:"observedTime,omitempty"`
}
GitTargetRetentionStatus is a bounded roll-up of what this GitTarget's prune policy kept.
func (*GitTargetRetentionStatus) DeepCopy ¶ added in v0.39.0
func (in *GitTargetRetentionStatus) DeepCopy() *GitTargetRetentionStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitTargetRetentionStatus.
func (*GitTargetRetentionStatus) DeepCopyInto ¶ added in v0.39.0
func (in *GitTargetRetentionStatus) DeepCopyInto(out *GitTargetRetentionStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitTargetSpec ¶
type GitTargetSpec struct {
// ProviderRef references the GitProvider that backs this target.
// Immutable: delete and recreate the GitTarget to change its destination.
// +required
ProviderRef GitProviderReference `json:"providerRef"`
// Branch to use for this target.
// Must be one of the allowed branches in the provider.
// Immutable: delete and recreate the GitTarget to change its destination.
// +required
// +kubebuilder:validation:MinLength=1
Branch string `json:"branch"`
// Path within the repository to write resources to, relative to the repository
// root. Required and must be non-empty — there is no default, so a GitTarget can
// never silently write to the repository root. To deliberately target the
// repository root, set it to "." (the ArgoCD/Flux convention); an empty string is
// rejected because it is too easy to leave blank by accident to be a deliberate
// root choice. Any leading slash (absolute path) and ".." are rejected, and a
// trailing slash is normalized away.
// Immutable: delete and recreate the GitTarget to change its destination.
// +required
// +kubebuilder:validation:MinLength=1
Path string `json:"path"`
// Encryption defines encryption settings for Secret resource writes.
// +optional
Encryption *EncryptionSpec `json:"encryption,omitempty"`
// Placement declares where NEW resources are written. It has no effect on a
// resource that already has a document in Git — that document is always
// updated in place at its existing location, wherever that is. Mutable: a
// change only affects resources created after the change.
// +optional
Placement *GitTargetPlacementSpec `json:"placement,omitempty"`
// ClusterProviderRef names the SOURCE cluster this GitTarget mirrors FROM, by referencing a
// cluster-scoped ClusterProvider by name. That ClusterProvider owns the cluster's connectivity
// credential, namespace-access authorization, and author-attribution mode. The default provider
// name is "default" and must exist; it may be in-cluster or remote.
// Immutable: a folder's source cluster is part of what the folder means; delete and recreate.
// +kubebuilder:default={name: "default"}
// +optional
ClusterProviderRef *ClusterProviderReference `json:"clusterProviderRef,omitempty"`
// AllowedSourceNamespaces bounds which SOURCE-cluster namespaces may be mirrored INTO this
// target. It belongs to the DESTINATION, not to any requesting rule: once declared it is
// exhaustive for every WatchRule that writes here, with no exception for a rule's own namespace.
//
// Omitted and empty differ. Omitted declares no policy, and a WatchRule keeps its own namespace;
// a declared-but-empty policy admits nothing; `selector: {}` admits every source namespace.
// Selector labels are read in the SOURCE cluster, so evaluating one needs Namespace
// get/list/watch for that cluster's credential, while exact names need no such access. This is
// also what a rules[].sourceNamespace of "*" resolves through. Naming any namespace other than
// the WatchRule's own — including "*" — additionally requires the ClusterProvider to set
// spec.allowSourceNamespaceOverride. It does NOT bound ClusterWatchRule, whose cluster-scoped
// objects have no namespace. Full resolution table: docs/configuration.md.
// +optional
AllowedSourceNamespaces *NamespaceMatcher `json:"allowedSourceNamespaces,omitempty"`
// Prune controls which deletion paths may remove documents from this target's folder: an
// explicit source DELETE event, and the resync mark-and-sweep that infers a deletion from a
// desired snapshot. Omitted, it is `mode: OnEvent` — observed deletes are mirrored, inferred
// ones are not — for a stored GitTarget as well as a new one.
// +optional
Prune *PrunePolicy `json:"prune,omitempty"`
}
GitTargetSpec defines the desired state of GitTarget.
The destination fields — providerRef, branch, and path — are immutable. A GitTarget materializes the watched resources at exactly one (provider, branch, folder); changing where it writes would orphan the old materialization and require migrating manifests between repositories/branches/folders. Instead of reconciling that move, the destination is fixed: to relocate a GitTarget, delete it and create a new one. This keeps the one-owner-per-folder invariant and the initial-snapshot gate simple — a successful snapshot can never be silently invalidated by a destination change.
+kubebuilder:validation:XValidation:rule="self.providerRef == oldSelf.providerRef",message="spec.providerRef is immutable; delete and recreate the GitTarget to change its destination" +kubebuilder:validation:XValidation:rule="self.branch == oldSelf.branch",message="spec.branch is immutable; delete and recreate the GitTarget to change its destination" +kubebuilder:validation:XValidation:rule="self.path == oldSelf.path",message="spec.path is immutable; delete and recreate the GitTarget to change its destination"
spec.clusterProviderRef names the SOURCE cluster a GitTarget mirrors FROM (see its field doc). It is immutable — a folder's source cluster is part of what the folder means, like providerRef/branch/path above — and defaults to a ClusterProvider named "default", so it is always populated (never nil) and always jumpable. +kubebuilder:validation:XValidation:rule="self.clusterProviderRef == oldSelf.clusterProviderRef",message="spec.clusterProviderRef is immutable; delete and recreate the GitTarget to change the cluster it mirrors"
func (*GitTargetSpec) DeepCopy ¶
func (in *GitTargetSpec) DeepCopy() *GitTargetSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitTargetSpec.
func (*GitTargetSpec) DeepCopyInto ¶
func (in *GitTargetSpec) DeepCopyInto(out *GitTargetSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitTargetStatus ¶
type GitTargetStatus struct {
// ObservedGeneration is the latest generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Conditions represent the latest available observations of an object's state
// +optional
// +listType=map
// +listMapKey=type
// +patchMergeKey=type
// +patchStrategy=merge
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
// LastPushTime is the timestamp of the last successful push.
// +optional
LastPushTime *metav1.Time `json:"lastPushTime,omitempty"`
// Streams is the bounded data-plane roll-up over this GitTarget's tracked types.
// Counts, never a per-type list, so it stays bounded however many types are watched.
// +optional
Streams *GitTargetStreamsStatus `json:"streams,omitempty"`
// Retention reports documents a resync kept because this target's spec.prune.mode suppressed
// the mark-and-sweep. It covers the INFERRED deletion path only: under `never`, a suppressed
// source DELETE is not counted here, so a `never` target can report zero while still declining
// to mirror deletes. It is informational either way — retention is the configured behavior,
// never a fault, and no condition changes state because of it.
// +optional
Retention *GitTargetRetentionStatus `json:"retention,omitempty"`
}
GitTargetStatus defines the observed state of GitTarget.
func (*GitTargetStatus) DeepCopy ¶
func (in *GitTargetStatus) DeepCopy() *GitTargetStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitTargetStatus.
func (*GitTargetStatus) DeepCopyInto ¶
func (in *GitTargetStatus) DeepCopyInto(out *GitTargetStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type GitTargetStreamsStatus ¶
type GitTargetStreamsStatus struct {
// Summary is the display-only ready/total ratio, e.g. "3/4".
//
// It restates Ready and Total, which the API conventions would normally rule out. It exists
// solely to feed the Streams printer column: a column can read one JSONPath, not format two.
// Do not compute anything from it — read ready and total.
// +optional
Summary string `json:"summary,omitempty"`
// Total is how many types this target tracks.
Total int32 `json:"total"`
// Ready is how many tracked types are Streaming.
Ready int32 `json:"ready"`
// Replaying is how many tracked types are still replaying their initial events.
Replaying int32 `json:"replaying"`
// Blocked is how many tracked types cannot currently be watched.
Blocked int32 `json:"blocked"`
}
GitTargetStreamsStatus is a bounded roll-up of the stream readiness state for the types this GitTarget tracks.
func (*GitTargetStreamsStatus) DeepCopy ¶
func (in *GitTargetStreamsStatus) DeepCopy() *GitTargetStreamsStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitTargetStreamsStatus.
func (*GitTargetStreamsStatus) DeepCopyInto ¶
func (in *GitTargetStreamsStatus) DeepCopyInto(out *GitTargetStreamsStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type KnownHostsReference ¶
type KnownHostsReference struct {
// Kind of the referent: ConfigMap (default) or Secret.
// +optional
// +kubebuilder:validation:Enum=ConfigMap;Secret
// +kubebuilder:default=ConfigMap
Kind string `json:"kind,omitempty"`
// Name of the ConfigMap or Secret.
// +required
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
}
KnownHostsReference points at a namespace-local ConfigMap or Secret that holds SSH known_hosts host-trust material. The data is read from the "known_hosts" key, falling back to "ssh_known_hosts" (the key Argo CD's argocd-ssh-known-hosts-cm ConfigMap uses, for host keys copied out of it).
func (*KnownHostsReference) DeepCopy ¶
func (in *KnownHostsReference) DeepCopy() *KnownHostsReference
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KnownHostsReference.
func (*KnownHostsReference) DeepCopyInto ¶
func (in *KnownHostsReference) DeepCopyInto(out *KnownHostsReference)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type LocalSecretReference ¶
type LocalSecretReference struct {
// Group of the referent.
// +kubebuilder:default=""
// +optional
Group string `json:"group,omitempty"`
// Kind of the referent.
// +kubebuilder:validation:Enum=Secret
// +kubebuilder:default=Secret
// +optional
Kind string `json:"kind,omitempty"`
// Name of the Secret.
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
}
LocalSecretReference is a typed reference to a Secret in the same namespace.
func (*LocalSecretReference) DeepCopy ¶
func (in *LocalSecretReference) DeepCopy() *LocalSecretReference
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalSecretReference.
func (*LocalSecretReference) DeepCopyInto ¶
func (in *LocalSecretReference) DeepCopyInto(out *LocalSecretReference)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type LocalTargetReference ¶
type LocalTargetReference struct {
// API Group of the referent.
// +kubebuilder:default=configbutler.ai
// +kubebuilder:validation:Enum=configbutler.ai
Group string `json:"group,omitempty"`
// Kind of the referent.
// Optional because this reference currently only supports a single kind (GitTarget).
// Keeping it optional allows users to omit it while still benefiting from CRD defaulting.
// +optional
// +kubebuilder:validation:Enum=GitTarget
// +kubebuilder:default=GitTarget
Kind string `json:"kind,omitempty"`
// Name of the referent.
// +required
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
}
func (*LocalTargetReference) DeepCopy ¶
func (in *LocalTargetReference) DeepCopy() *LocalTargetReference
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LocalTargetReference.
func (*LocalTargetReference) DeepCopyInto ¶
func (in *LocalTargetReference) DeepCopyInto(out *LocalTargetReference)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type NamespaceMatcher ¶ added in v0.39.0
type NamespaceMatcher struct {
// Names is an explicit allow-list of namespace names. Entries are namespace names (DNS-1123
// labels), never patterns — `*` is rejected. To admit every namespace, declare `selector: {}`.
// +optional
// +listType=set
// +kubebuilder:validation:items:MinLength=1
// +kubebuilder:validation:items:MaxLength=63
// +kubebuilder:validation:items:Pattern=`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`
Names []string `json:"names,omitempty"`
// Selector is a label selector matched against Namespace labels; a namespace whose labels
// match is admitted. ORed with Names.
// +optional
Selector *metav1.LabelSelector `json:"selector,omitempty"`
}
NamespaceMatcher is the one deny-by-default namespace-policy SHAPE this API uses wherever a field bounds "which namespaces". It carries an explicit name allow-list and a label selector, ORed: a namespace is admitted if it is listed OR its labels match.
It is deny-by-default and the empty matcher is NOT "unrestricted": a matcher with neither names nor selector admits NOTHING. Every use of this shape is authorization, and the fail-open reading is the catastrophic one — so an absent field means "no policy declared" (which each call site interprets in its own legacy terms) while a declared-but-empty one means "admit nothing".
Two fields use it, and they mean namespaces in DIFFERENT clusters — which is exactly why the shape is shared but the fields are not:
- ClusterProvider.spec.allowedNamespaces — control-cluster namespaces that may create a GitTarget using the provider. Selector labels come from the CONTROL cluster.
- GitTarget.spec.allowedSourceNamespaces — source-cluster namespaces that may be mirrored into this target, by any rule kind. Selector labels come from the SOURCE cluster.
Because the two clusters differ, the LABEL half cannot be evaluated by one shared helper: only the caller knows which cluster's Namespace labels to read. Matches therefore takes the labels rather than fetching them, and MatchesName exists so an exact-name policy stays answerable when the labels cannot be read at all (see the source-scope service's degradation path).
func (*NamespaceMatcher) Declared ¶ added in v0.39.0
func (m *NamespaceMatcher) Declared() bool
Declared reports whether a policy exists at all. A nil matcher is "no policy declared"; a non-nil one is a declared policy even when it is empty (and an empty declared policy admits nothing). The distinction is load-bearing: an absent field keeps a caller's legacy scope, while a declared one is exhaustive.
func (*NamespaceMatcher) DeepCopy ¶ added in v0.39.0
func (in *NamespaceMatcher) DeepCopy() *NamespaceMatcher
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceMatcher.
func (*NamespaceMatcher) DeepCopyInto ¶ added in v0.39.0
func (in *NamespaceMatcher) DeepCopyInto(out *NamespaceMatcher)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*NamespaceMatcher) HasSelector ¶ added in v0.39.0
func (m *NamespaceMatcher) HasSelector() bool
HasSelector reports whether the matcher declares a label selector, i.e. whether evaluating it requires reading the Namespace's labels in that field's own cluster.
func (*NamespaceMatcher) Matches ¶ added in v0.39.0
Matches reports whether a namespace (by name and by the labels it carries IN THE CLUSTER THIS FIELD DESCRIBES) is admitted. Names are checked before the selector, so the answer never depends on the labels when a name already admits. A malformed selector is returned as an error rather than a silent allow or a silent deny — it is a configuration mistake the operator must see. A nil matcher admits nothing.
func (*NamespaceMatcher) MatchesName ¶ added in v0.39.0
func (m *NamespaceMatcher) MatchesName(nsName string) bool
MatchesName reports whether nsName is in the matcher's explicit Names allow-list.
It is separate from Matches on purpose: the name half needs NO Namespace read, so a policy that admits by name keeps working against a cluster whose Namespace list/watch is Forbidden. Callers that can fail to read labels must consult this FIRST and only then fall through to the selector. A nil matcher matches nothing.
func (*NamespaceMatcher) SelectorAdmits ¶ added in v0.39.0
func (m *NamespaceMatcher) SelectorAdmits(nsLabels map[string]string) (bool, error)
SelectorAdmits reports whether the matcher's SELECTOR half alone — ignoring Names — admits a namespace carrying these labels. It exists for ENUMERATION: expanding a wildcard means asking this of every namespace in a snapshot, which Matches cannot do because its name check would short-circuit per candidate.
A nil matcher or a nil selector admits nothing; a present-but-EMPTY selector admits everything. That asymmetry is not incidental — LabelSelectorAsSelector returns labels.Nothing() for nil and labels.Everything() for an empty selector, which is exactly the absent-versus-declared distinction this type is built around, and `selector: {}` is the deliberate "every namespace" declaration.
func (*NamespaceMatcher) ValidateNames ¶ added in v0.39.0
func (m *NamespaceMatcher) ValidateNames() error
ValidateNames reports the first entry in Names that could never be a namespace name, or nil when every entry could be one.
The schema rejects these at admission, so this is the DEFENSIVE half: an object stored before that validation shipped keeps its value in etcd, where the only two options are to refuse it loudly or to honour the entries that happen to be valid. The second is silent narrowing — a policy that mirrors less than its author asked for, with nothing in status saying so — which is why callers must treat a non-nil error as "this policy cannot be evaluated as written" rather than as a smaller policy.
type NamespacedTargetReference ¶
type NamespacedTargetReference struct {
// API Group of the referent.
// +kubebuilder:validation:Enum=configbutler.ai
// +kubebuilder:default=configbutler.ai
Group string `json:"group,omitempty"`
// Kind of the referent.
// Optional because this reference currently only supports a single kind (GitTarget).
// Keeping it optional allows users to omit it while still benefiting from CRD defaulting.
// +optional
// +kubebuilder:validation:Enum=GitTarget
// +kubebuilder:default=GitTarget
Kind string `json:"kind,omitempty"`
// Name of the referent.
// +required
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
// Required because ClusterWatchRule has no namespace.
// +required
// +kubebuilder:validation:MinLength=1
Namespace string `json:"namespace"`
}
func (*NamespacedTargetReference) DeepCopy ¶
func (in *NamespacedTargetReference) DeepCopy() *NamespacedTargetReference
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespacedTargetReference.
func (*NamespacedTargetReference) DeepCopyInto ¶
func (in *NamespacedTargetReference) DeepCopyInto(out *NamespacedTargetReference)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type OperationType ¶
type OperationType string
OperationType specifies the type of operation that triggers a watch event. +kubebuilder:validation:Enum=CREATE;UPDATE;DELETE;*
const ( // OperationCreate matches resource creation events. OperationCreate OperationType = "CREATE" // OperationUpdate matches resource update events. OperationUpdate OperationType = "UPDATE" // OperationDelete matches resource deletion events. OperationDelete OperationType = "DELETE" // OperationAll matches all operation types. OperationAll OperationType = "*" )
type PruneMode ¶ added in v0.39.0
type PruneMode string
PruneMode enumerates which of the two deletion paths may remove a managed document from a GitTarget's folder.
| source DELETE event | resync mark-and-sweep Never | suppressed | suppressed OnEvent | applied | suppressed Always | applied | applied
const ( // PruneNever removes nothing: neither an explicit source DELETE nor an inferred sweep drop. // The folder becomes an archive that only ever gains and updates documents. PruneNever PruneMode = "Never" // PruneOnEvent mirrors an observed source DELETE but never infers a deletion from a desired // snapshot. It is the effective default. PruneOnEvent PruneMode = "OnEvent" // PruneAlways enables both paths: full desired-state convergence, including removing a Git // document whose resource is absent from the snapshot. PruneAlways PruneMode = "Always" )
func (PruneMode) AppliesEventDeletes ¶ added in v0.39.0
AppliesEventDeletes reports whether an explicit source DELETE event may remove its managed document. True for OnEvent and Always. Call OrDefault first if the value may be unset.
func (PruneMode) MoreRestrictiveOf ¶ added in v0.39.0
MoreRestrictiveOf returns whichever of the two modes authorizes less deletion.
It exists for one situation: a write that was planned under one policy and is applied — or replayed after a rebase — under another. Taking the minimum makes the two directions behave the way an operator means them, and they are NOT symmetric:
- LOOSENING must not escalate an already-planned write. A resync planned under `OnEvent` chose to keep its orphans against a desired snapshot that is now stale; someone declaring `Always` afterwards must not turn that stale plan into deletions. The new policy applies to the next resync, which gathers a fresh snapshot.
- TIGHTENING must apply immediately. `Always` -> `OnEvent` is what an operator reaches for to stop deletions that have not landed yet; a policy change that queued work could outrun would not be a stop button at all.
func (PruneMode) OrDefault ¶ added in v0.39.0
OrDefault resolves the EMPTY mode — unset, which is not a mode — to the documented default.
It exists because the empty string is the one value that must not be read literally: both predicates below answer false for it, which is `Never`'s behaviour, not `OnEvent`'s. Any value that has travelled through a struct literal, a retained pending write, or a stored object written before the schema default therefore passes through here first. An UNRECOGNIZED value is deliberately left alone — see SweepsOrphans.
func (PruneMode) SweepsOrphans ¶ added in v0.39.0
SweepsOrphans reports whether a resync may drop a managed document that its desired snapshot did not contain — the inferred mark-and-sweep deletion. True only for Always.
An unrecognized value (an object stored under a schema that allowed more than this build does) reads as false here and as false in AppliesEventDeletes: an unknown policy retains everything, because the failure mode of guessing wrong in the other direction is deleting a tenant's manifests. The empty string is NOT such a value — it is unset, and OrDefault resolves it.
type PrunePolicy ¶ added in v0.39.0
type PrunePolicy struct {
// Mode selects which deletion paths are enabled. `Never` removes nothing; `OnEvent` mirrors an
// observed source DELETE but never infers a deletion from a resync snapshot; `Always` enables
// both, restoring full desired-state convergence. Omitted, it is `OnEvent`.
// +optional
// +kubebuilder:validation:Enum=Never;OnEvent;Always
// +kubebuilder:default=OnEvent
Mode PruneMode `json:"mode,omitempty"`
}
PrunePolicy declares which deletion paths may remove documents from a GitTarget's folder.
func (*PrunePolicy) DeepCopy ¶ added in v0.39.0
func (in *PrunePolicy) DeepCopy() *PrunePolicy
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrunePolicy.
func (*PrunePolicy) DeepCopyInto ¶ added in v0.39.0
func (in *PrunePolicy) DeepCopyInto(out *PrunePolicy)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*PrunePolicy) EffectiveMode ¶ added in v0.39.0
func (p *PrunePolicy) EffectiveMode() PruneMode
EffectiveMode resolves the declared mode to the one the controller acts on. A nil policy (the field was never written) and an empty mode (written without a mode, or stored before the schema default existed) both resolve to PruneOnEvent, so an unedited legacy GitTarget is safe.
The nil receiver is deliberate: it makes the omitted case answerable without every call site repeating a nil check, which is where a "safe unless someone forgot" default goes wrong.
type PushStrategy ¶
type PushStrategy struct {
// CommitWindow is the rolling silence window used to coalesce events into
// a single commit per (author, gitTarget). The timer resets on every event
// arrival and a flush is triggered after this many seconds of silence.
// Setting "0s" opts into per-event commits in the steady-state.
// Defaults to "5s".
// +optional
CommitWindow *string `json:"commitWindow,omitempty"`
}
PushStrategy defines how events are coalesced into commits before pushing.
func (*PushStrategy) DeepCopy ¶
func (in *PushStrategy) DeepCopy() *PushStrategy
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PushStrategy.
func (*PushStrategy) DeepCopyInto ¶
func (in *PushStrategy) DeepCopyInto(out *PushStrategy)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type ResourceRule ¶
type ResourceRule struct {
// Operations to watch. If empty, watches all operations (CREATE, UPDATE, DELETE).
// Supports: CREATE, UPDATE, DELETE, or * (wildcard for all operations).
// Examples:
// - ["CREATE", "UPDATE"] watches only creation and updates, ignoring deletions
// - ["*"] or [] watches all operations
// +optional
Operations []OperationType `json:"operations,omitempty"`
// APIGroups to match. Empty string ("") matches the core API group.
// If omitted, GitOps Reverser resolves the resource name across all served API groups.
// Wildcards supported: "*" matches all groups.
// Examples:
// - [""] matches core API (pods, services, configmaps)
// - ["apps"] matches apps API group (deployments, statefulsets)
// - ["", "apps"] matches both core and apps groups
// - ["*"] matches all groups
// - [] resolves a named resource only when it is served by one API group
// +optional
APIGroups []string `json:"apiGroups,omitempty"`
// APIVersions to match. If empty, uses the preferred served version for each group/resource.
// Wildcards supported: "*" matches all versions.
// Examples:
// - ["v1"] matches only v1 version
// - ["v1", "v1beta1"] matches both versions
// - ["*"] matches all served versions
// - [] matches the preferred served version
//
// Multi-version note: the built-in cold-start Git path is versionless, so two
// objects that differ only by API version resolve to the same file. To watch
// several versions of a group/resource and keep them in separate files, give the
// GitTarget a placement template that includes {version} (see GitTargetPlacementSpec).
// +optional
APIVersions []string `json:"apiVersions,omitempty"`
// Resources to match (plural names like "pods", "configmaps").
// This field is required and determines which resource types trigger this rule.
// Wildcard semantics follow Kubernetes admission webhook patterns:
// - "*" matches all resources
// - "pods" matches exactly pods (case-insensitive)
//
// For custom resources, use the exact plural resource name and set apiGroups
// when more than one served API group exposes that name.
//
// Note: Subresources cannot be added here. Values containing "/" (for example
// "pods/log" or "pods/*") are rejected by the API because subresources are
// not supported for list/watch snapshot planning. Prefix/suffix wildcards
// like "pod*" or "*.example.com" are NOT supported. Use exact matches or the
// "*" wildcard for broad matching.
// +required
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:items:MinLength=1
// +kubebuilder:validation:items:Pattern=`^[^/]*$`
Resources []string `json:"resources"`
// SourceNamespace is the namespace this item watches IN THE SOURCE CLUSTER its GitTarget
// mirrors from: omitted for this WatchRule's own namespace, an exact name for one other, or
// "*" for every namespace the GitTarget's spec.allowedSourceNamespaces currently admits.
//
// "*" never means "every namespace that exists" — it expands to exactly what that policy
// admits, so a target declaring no policy denies it. Naming any namespace other than this
// rule's own, "*" included, additionally requires the GitTarget's ClusterProvider to admit the
// target's namespace AND to set spec.allowSourceNamespaceOverride. Once the GitTarget declares
// a policy it is exhaustive, so even an omitted sourceNamespace is checked against it.
//
// This changes only which namespace is WATCHED, never where objects are written: Git placement
// follows each mirrored object's own namespace.
// +optional
// +kubebuilder:validation:MaxLength=63
// +kubebuilder:validation:Pattern=`^(\*|[a-z0-9]([-a-z0-9]*[a-z0-9])?)$`
SourceNamespace string `json:"sourceNamespace,omitempty"`
}
ResourceRule defines a set of namespaced resources to watch. Omitted API groups and versions are resolved from the served Kubernetes API surface. All fields except Resources are optional.
func (*ResourceRule) DeepCopy ¶
func (in *ResourceRule) DeepCopy() *ResourceRule
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRule.
func (*ResourceRule) DeepCopyInto ¶
func (in *ResourceRule) DeepCopyInto(out *ResourceRule)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*ResourceRule) DescribeSourceNamespace ¶ added in v0.39.0
func (r *ResourceRule) DescribeSourceNamespace(ruleNamespace string) string
DescribeSourceNamespace renders this item's requested source namespace for an operator-facing message. An omitted value is spelled out rather than shown as an empty string.
func (*ResourceRule) EffectiveSourceNamespace ¶ added in v0.39.0
func (r *ResourceRule) EffectiveSourceNamespace(ruleNamespace string) string
EffectiveSourceNamespace is the source-cluster namespace this ITEM names, given the namespace of the WatchRule that carries it: spec.rules[].sourceNamespace when set, and the rule's OWN namespace otherwise. For a wildcard item it returns "*" — the caller must expand that through the GitTarget's policy rather than treat it as a namespace name.
It is controller logic rather than an API-server default because an apiserver default cannot refer to metadata.namespace.
func (*ResourceRule) IsSourceNamespaceWildcard ¶ added in v0.39.0
func (r *ResourceRule) IsSourceNamespaceWildcard() bool
IsSourceNamespaceWildcard reports whether this item asks to follow its GitTarget's admitted set.
func (*ResourceRule) OverridesSourceNamespace ¶ added in v0.39.0
func (r *ResourceRule) OverridesSourceNamespace(ruleNamespace string) bool
OverridesSourceNamespace reports whether this item asks for a source namespace OTHER than the WatchRule's own — the case that needs the ClusterProvider's delegation flag. A sourceNamespace that merely restates the rule's own namespace is not an override and stays the legacy case; "*" always is one, even against a policy that happens to list only that namespace, because a later policy edit would otherwise widen the watch with no platform-admin opt-in.
type ResourceScope ¶
type ResourceScope string
ResourceScope names a Kubernetes resource's scope. It is an INTERNAL matching vocabulary: the resolver uses both constants to align a rule's selector with the discovered scope of each type (a WatchRule always resolves Namespaced records, a ClusterWatchRule always Cluster ones). The only field that still exposes it — ClusterResourceRule.scope — is narrowed to Cluster alone, so "Namespaced" is no longer a public choice anywhere in the API.
const ( // ResourceScopeCluster indicates cluster-scoped resources (Nodes, ClusterRoles, etc.). ResourceScopeCluster ResourceScope = "Cluster" // ResourceScopeNamespaced indicates namespaced resources (Pods, Deployments, etc.). ResourceScopeNamespaced ResourceScope = "Namespaced" )
type WatchRule ¶
type WatchRule struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
// spec defines the desired state of WatchRule
// +required
Spec WatchRuleSpec `json:"spec"`
// status defines the observed state of WatchRule
// +optional
Status WatchRuleStatus `json:"status,omitempty"`
}
WatchRule selects NAMESPACED resources on the source cluster its GitTarget mirrors from, with filtering by operation, API group, version, and source namespace. Scope is carried by the rule KIND: a WatchRule never selects cluster-scoped types — use a ClusterWatchRule for those.
Each spec.rules[] item watches its own source namespace: this WatchRule's OWN namespace when omitted, an explicit name, or "*" for every namespace the GitTarget admits. Anything other than its own namespace passes the gate described on rules[].sourceNamespace. RBAC controls who may create or modify WatchRules per namespace.
func (*WatchRule) DeepCopy ¶
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchRule.
func (*WatchRule) DeepCopyInto ¶
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*WatchRule) DeepCopyObject ¶
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type WatchRuleList ¶
type WatchRuleList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []WatchRule `json:"items"`
}
WatchRuleList contains a list of WatchRule.
func (*WatchRuleList) DeepCopy ¶
func (in *WatchRuleList) DeepCopy() *WatchRuleList
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchRuleList.
func (*WatchRuleList) DeepCopyInto ¶
func (in *WatchRuleList) DeepCopyInto(out *WatchRuleList)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (*WatchRuleList) DeepCopyObject ¶
func (in *WatchRuleList) DeepCopyObject() runtime.Object
DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
type WatchRuleSpec ¶
type WatchRuleSpec struct {
// TargetRef references the GitTarget to use.
// Must be in the same namespace.
// +required
TargetRef LocalTargetReference `json:"targetRef"`
// Rules define which resources to watch, and in which source namespaces.
// Multiple rules create a logical OR - a resource matching ANY rule is watched.
// Each rule can specify operations, API groups, versions, resource types, and a source namespace.
// +required
// +kubebuilder:validation:MinItems=1
Rules []ResourceRule `json:"rules"`
}
WatchRuleSpec defines the desired state of WatchRule. WatchRule selects NAMESPACED resources on its GitTarget's source cluster. Each rules[] item carries its own source namespace: omitted for this WatchRule's own namespace, an explicit name, or "*" for every namespace the GitTarget admits.
func (*WatchRuleSpec) DeepCopy ¶
func (in *WatchRuleSpec) DeepCopy() *WatchRuleSpec
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchRuleSpec.
func (*WatchRuleSpec) DeepCopyInto ¶
func (in *WatchRuleSpec) DeepCopyInto(out *WatchRuleSpec)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type WatchRuleStatus ¶
type WatchRuleStatus struct {
// ObservedGeneration is the latest generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// Conditions represent the latest available observations of an object's state
// +optional
// +listType=map
// +listMapKey=type
// +patchMergeKey=type
// +patchStrategy=merge
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
// Streams is the bounded stream-readiness roll-up for the types this rule resolves.
// +optional
Streams *WatchRuleStreamsStatus `json:"streams,omitempty"`
}
WatchRuleStatus defines the observed state of WatchRule.
func (*WatchRuleStatus) DeepCopy ¶
func (in *WatchRuleStatus) DeepCopy() *WatchRuleStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchRuleStatus.
func (*WatchRuleStatus) DeepCopyInto ¶
func (in *WatchRuleStatus) DeepCopyInto(out *WatchRuleStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
type WatchRuleStreamsStatus ¶
type WatchRuleStreamsStatus struct {
// Summary is the display-only ready/total ratio.
// +optional
Summary string `json:"summary,omitempty"`
// Total is how many types this rule resolves.
Total int32 `json:"total"`
// Ready is how many resolved types are Streaming.
Ready int32 `json:"ready"`
// Replaying is how many resolved types are still replaying their initial events.
Replaying int32 `json:"replaying"`
// Blocked is how many resolved types cannot currently be watched.
Blocked int32 `json:"blocked"`
// PendingSample is a bounded sample of types not yet ready.
// +optional
// +kubebuilder:validation:MaxItems=5
PendingSample []string `json:"pendingSample,omitempty"`
}
WatchRuleStreamsStatus is a bounded roll-up of the stream-readiness state for the types a WatchRule or ClusterWatchRule resolves.
func (*WatchRuleStreamsStatus) DeepCopy ¶
func (in *WatchRuleStreamsStatus) DeepCopy() *WatchRuleStreamsStatus
DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WatchRuleStreamsStatus.
func (*WatchRuleStreamsStatus) DeepCopyInto ¶
func (in *WatchRuleStreamsStatus) DeepCopyInto(out *WatchRuleStreamsStatus)
DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.