Repository navigation
Expand file tree
/
Copy pathgitprovider_types.go
More file actions
324 lines (279 loc) · 14.7 KB
/
Copy pathgitprovider_types.go
File metadata and controls
324 lines (279 loc) · 14.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// SPDX-License-Identifier: Apache-2.0
package v1alpha3
import (
meta "github.com/fluxcd/pkg/apis/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// 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"
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)
//
// An OMITTED secretRef means anonymous access. An empty name is refused rather than treated as
// one: a typo there would otherwise downgrade a private repository to anonymous silently, and
// the failure would surface as an authentication error against the remote rather than as a
// mistake in this object.
// +optional
// +kubebuilder:validation:XValidation:rule="self.name != ''",message="spec.secretRef.name must not be empty; omit secretRef entirely for anonymous access"
SecretRef *meta.LocalObjectReference `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"`
// Commit configures the commit identity and signing behavior this connection uses. Message
// formatting moved to GitTarget.spec.commit.message.
// +optional
Commit *CommitSpec `json:"commit,omitempty"`
}
// 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).
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"`
}
// EncryptionSpec configures Secret encryption behavior for git writes.
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.
// +kubebuilder:validation:XValidation:rule="self.name != ''",message="encryption.secretRef.name must not be empty"
// +optional
SecretRef meta.LocalObjectReference `json:"secretRef,omitempty"`
// Age configures age-specific encryption behavior for SOPS.
// +optional
Age *AgeEncryptionSpec `json:"age,omitempty"`
}
// AgeEncryptionSpec configures age recipient resolution behavior.
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"`
}
// AgeRecipientsSpec defines age recipient source and key generation behavior.
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"`
}
// GitProviderStatus defines the observed state of GitProvider.
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"`
// Branches lists the branches this repository's GitTargets are configured to write, with how
// many reference each. It answers what the repository is being used for, so it includes a
// branch whose targets are blocked or suspended and excludes a branch nothing references any
// more.
//
// It is not the branches that exist on the remote, and not the workers currently running: it
// moves only when somebody edits a GitTarget. An EMPTY list beside Ready=True is the state
// this exists to make legible — configured and unused, which looks nothing like broken and
// previously took a GitTarget listing to tell apart. An ABSENT list is the third state and a
// different one: no inventory has been read yet, so nothing here has been measured.
// +optional
// +listType=map
// +listMapKey=name
Branches []GitProviderBranchStatus `json:"branches"`
// LastVerifiedAt is when the credential and the repository were last proved together: the
// connectivity check listed the remote's refs with this provider's credential and the remote
// answered. It is never cleared — a failure is already carried by Ready=False with a reason —
// so the pair "not ready, last verified 11 minutes ago" says how long the connection has been
// broken, which is the sentence an operator otherwise has to infer.
//
// The check runs on the steady reconcile interval, so a provider's resourceVersion moves at
// that cadence. Providers are few and the check was already running; this adds no request.
// +optional
LastVerifiedAt *metav1.Time `json:"lastVerifiedAt,omitempty"`
}
// GitProviderBranchStatus is one branch of this repository that GitTargets are configured to
// write, and how many of them write it.
type GitProviderBranchStatus struct {
// Name is the branch.
// +required
// +kubebuilder:validation:MinLength=1
Name string `json:"name"`
// GitTargetCount is how many GitTargets are configured to write this branch. More than one means
// they share a branch worker, and each still reports its own folder's health on its own
// conditions.
// +required
// +kubebuilder:validation:Minimum=0
GitTargetCount int32 `json:"gitTargetCount"`
}
// CommitSpec configures the commit identity and signing a GitProvider uses. Message formatting
// lives on the GitTarget (spec.commit.message), because it describes the folder rather than the
// connection.
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"`
// Signing configures commit signing.
// +optional
Signing *CommitSigningSpec `json:"signing,omitempty"`
}
// CommitterSpec configures the bot identity used as the commit committer.
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"`
}
// CommitMessageSpec configures commit message formatting. It is set on
// GitTarget.spec.commit.message; the identically-shaped GitProvider.spec.commit.message is
// retained only to reject a manifest that still sets it there.
// +kubebuilder:validation:XValidation:rule="!has(self.eventTemplate)",message="eventTemplate is retired; migrate to liveTemplate"
// +kubebuilder:validation:XValidation:rule="!has(self.groupTemplate)",message="groupTemplate is retired; migrate to liveTemplate"
type CommitMessageSpec struct {
// LiveTemplate formats every live window, including one resource and a 0s window.
// Fields: Author (raw username, possibly empty), GitTarget, Count, Operations, Resources.
// Count is retained input entries after coalescing, before comparison with Git.
// Resources exposes Operation, Group, Version, Resource, Namespace, Name, APIVersion,
// ResourceVersion — the version of the state this commit wrote, which lags the object's
// current one and is empty for a producer that observed none — and Generation, the desired
// state's counter, which is 0 for a kind without a spec. Guard both with {{with}}.
// A literal CommitRequest message overrides this template without changing authorship.
// +optional
LiveTemplate string `json:"liveTemplate,omitempty"`
// Rationale, kept out of the doc comment (and so out of the CRD schema) by the blank line
// below: a CommitRequest is created by whoever holds create on it in a namespace, so its
// author supplies the message but must not set commit-message policy. Framing the message
// rather than parsing it keeps that split — the operator owns the wording, the requester owns
// the words, and nothing a requester writes is ever executed. Rejecting a template that never
// renders RequestMessage is what keeps the split honest in the other direction: silently
// discarding a requester's stated reason would be worse than having no template at all.
// RequestTemplate frames a CommitRequest's message instead of committing it verbatim. It
// renders only for a commit window whose attached request supplied a message; every other
// window uses liveTemplate or reconcileTemplate.
//
// It receives the same fields as liveTemplate, plus RequestMessage carrying the request's
// message unaltered. That message is never parsed as a template, so template syntax inside it
// stays literal.
//
// Omitted, a request's message is committed exactly as supplied. A template that never renders
// RequestMessage is rejected. One that fails to render at commit time commits the message
// verbatim instead, counted as message_source="commit_request_fallback".
// +optional
RequestTemplate string `json:"requestTemplate,omitempty"`
// ReconcileTemplate formats atomic snapshots and resyncs.
// Fields: Count, GitTarget, Group, Version, Resource, APIVersion, Namespace, ResourceVersion.
// ResourceVersion is the snapshot LIST's version, not any one object's. Type and Namespace
// fields are empty for whole-target snapshots, and ResourceVersion can be empty.
// Guard optional fields so the message remains meaningful for every snapshot scope.
// Revision was renamed to ResourceVersion in v0.48.0; a template still naming it is rejected.
// +optional
ReconcileTemplate string `json:"reconcileTemplate,omitempty"`
// EventTemplate is retired. Remove it and migrate resource fields into liveTemplate's Resources.
// +optional
EventTemplate string `json:"eventTemplate,omitempty"`
// GroupTemplate is retired. Remove it and copy its value to liveTemplate.
// +optional
GroupTemplate string `json:"groupTemplate,omitempty"`
}
// CommitSigningSpec configures commit signing.
type CommitSigningSpec struct {
// SecretRef references the Secret containing the signing key material.
// +kubebuilder:validation:XValidation:rule="self.name != ''",message="commit.signing.secretRef.name must not be empty"
// Expected keys will be defined by the signing implementation.
SecretRef meta.LocalObjectReference `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"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="URL",type=string,JSONPath=`.spec.url`
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
// +kubebuilder:printcolumn:name="Reason",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].reason`
// +kubebuilder:printcolumn:name="Verified",type=date,JSONPath=`.status.lastVerifiedAt`,priority=1
// +kubebuilder:printcolumn:name="Message",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].message`,priority=1
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// GitProvider is the Schema for the gitproviders API.
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"`
}
// +kubebuilder:object:root=true
// GitProviderList contains a list of GitProvider.
type GitProviderList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []GitProvider `json:"items"`
}
func init() {
SchemeBuilder.Register(&GitProvider{}, &GitProviderList{})
}