1 /* 2 Copyright 2021 The Flux authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1beta2 18 19 import ( 20 "time" 21 22 "github.com/fluxcd/pkg/apis/kustomize" 23 "github.com/fluxcd/pkg/apis/meta" 24 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 ) 27 28 const ( 29 KustomizationKind = "Kustomization" 30 KustomizationFinalizer = "finalizers.fluxcd.io" 31 MaxConditionMessageLength = 20000 32 EnabledValue = "enabled" 33 DisabledValue = "disabled" 34 MergeValue = "merge" 35 ) 36 37 // KustomizationSpec defines the configuration to calculate the desired state from a Source using Kustomize. 38 type KustomizationSpec struct { 39 // CommonMetadata specifies the common labels and annotations that are applied to all resources. 40 // Any existing label or annotation will be overridden if its key matches a common one. 41 // +optional 42 CommonMetadata *CommonMetadata `json:"commonMetadata,omitempty"` 43 44 // DependsOn may contain a meta.NamespacedObjectReference slice 45 // with references to Kustomization resources that must be ready before this 46 // Kustomization can be reconciled. 47 // +optional 48 DependsOn []meta.NamespacedObjectReference `json:"dependsOn,omitempty"` 49 50 // Decrypt Kubernetes secrets before applying them on the cluster. 51 // +optional 52 Decryption *Decryption `json:"decryption,omitempty"` 53 54 // The interval at which to reconcile the Kustomization. 55 // +kubebuilder:validation:Type=string 56 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 57 // +required 58 Interval metav1.Duration `json:"interval"` 59 60 // The interval at which to retry a previously failed reconciliation. 61 // When not specified, the controller uses the KustomizationSpec.Interval 62 // value to retry failures. 63 // +kubebuilder:validation:Type=string 64 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 65 // +optional 66 RetryInterval *metav1.Duration `json:"retryInterval,omitempty"` 67 68 // The KubeConfig for reconciling the Kustomization on a remote cluster. 69 // When used in combination with KustomizationSpec.ServiceAccountName, 70 // forces the controller to act on behalf of that Service Account at the 71 // target cluster. 72 // If the --default-service-account flag is set, its value will be used as 73 // a controller level fallback for when KustomizationSpec.ServiceAccountName 74 // is empty. 75 // +optional 76 KubeConfig *meta.KubeConfigReference `json:"kubeConfig,omitempty"` 77 78 // Path to the directory containing the kustomization.yaml file, or the 79 // set of plain YAMLs a kustomization.yaml should be generated for. 80 // Defaults to 'None', which translates to the root path of the SourceRef. 81 // +optional 82 Path string `json:"path,omitempty"` 83 84 // PostBuild describes which actions to perform on the YAML manifest 85 // generated by building the kustomize overlay. 86 // +optional 87 PostBuild *PostBuild `json:"postBuild,omitempty"` 88 89 // Prune enables garbage collection. 90 // +required 91 Prune bool `json:"prune"` 92 93 // A list of resources to be included in the health assessment. 94 // +optional 95 HealthChecks []meta.NamespacedObjectKindReference `json:"healthChecks,omitempty"` 96 97 // Strategic merge and JSON patches, defined as inline YAML objects, 98 // capable of targeting objects based on kind, label and annotation selectors. 99 // +optional 100 Patches []kustomize.Patch `json:"patches,omitempty"` 101 102 // Strategic merge patches, defined as inline YAML objects. 103 // Deprecated: Use Patches instead. 104 // +optional 105 PatchesStrategicMerge []apiextensionsv1.JSON `json:"patchesStrategicMerge,omitempty"` 106 107 // JSON 6902 patches, defined as inline YAML objects. 108 // Deprecated: Use Patches instead. 109 // +optional 110 PatchesJSON6902 []kustomize.JSON6902Patch `json:"patchesJson6902,omitempty"` 111 112 // Images is a list of (image name, new name, new tag or digest) 113 // for changing image names, tags or digests. This can also be achieved with a 114 // patch, but this operator is simpler to specify. 115 // +optional 116 Images []kustomize.Image `json:"images,omitempty"` 117 118 // The name of the Kubernetes service account to impersonate 119 // when reconciling this Kustomization. 120 // +optional 121 ServiceAccountName string `json:"serviceAccountName,omitempty"` 122 123 // Reference of the source where the kustomization file is. 124 // +required 125 SourceRef CrossNamespaceSourceReference `json:"sourceRef"` 126 127 // This flag tells the controller to suspend subsequent kustomize executions, 128 // it does not apply to already started executions. Defaults to false. 129 // +optional 130 Suspend bool `json:"suspend,omitempty"` 131 132 // TargetNamespace sets or overrides the namespace in the 133 // kustomization.yaml file. 134 // +kubebuilder:validation:MinLength=1 135 // +kubebuilder:validation:MaxLength=63 136 // +kubebuilder:validation:Optional 137 // +optional 138 TargetNamespace string `json:"targetNamespace,omitempty"` 139 140 // Timeout for validation, apply and health checking operations. 141 // Defaults to 'Interval' duration. 142 // +kubebuilder:validation:Type=string 143 // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" 144 // +optional 145 Timeout *metav1.Duration `json:"timeout,omitempty"` 146 147 // Force instructs the controller to recreate resources 148 // when patching fails due to an immutable field change. 149 // +kubebuilder:default:=false 150 // +optional 151 Force bool `json:"force,omitempty"` 152 153 // Wait instructs the controller to check the health of all the reconciled resources. 154 // When enabled, the HealthChecks are ignored. Defaults to false. 155 // +optional 156 Wait bool `json:"wait,omitempty"` 157 158 // Components specifies relative paths to specifications of other Components. 159 // +optional 160 Components []string `json:"components,omitempty"` 161 162 // Deprecated: Not used in v1beta2. 163 // +kubebuilder:validation:Enum=none;client;server 164 // +optional 165 Validation string `json:"validation,omitempty"` 166 } 167 168 // CommonMetadata defines the common labels and annotations. 169 type CommonMetadata struct { 170 // Annotations to be added to the object's metadata. 171 // +optional 172 Annotations map[string]string `json:"annotations,omitempty"` 173 174 // Labels to be added to the object's metadata. 175 // +optional 176 Labels map[string]string `json:"labels,omitempty"` 177 } 178 179 // Decryption defines how decryption is handled for Kubernetes manifests. 180 type Decryption struct { 181 // Provider is the name of the decryption engine. 182 // +kubebuilder:validation:Enum=sops 183 // +required 184 Provider string `json:"provider"` 185 186 // The secret name containing the private OpenPGP keys used for decryption. 187 // +optional 188 SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"` 189 } 190 191 // PostBuild describes which actions to perform on the YAML manifest 192 // generated by building the kustomize overlay. 193 type PostBuild struct { 194 // Substitute holds a map of key/value pairs. 195 // The variables defined in your YAML manifests 196 // that match any of the keys defined in the map 197 // will be substituted with the set value. 198 // Includes support for bash string replacement functions 199 // e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. 200 // +optional 201 Substitute map[string]string `json:"substitute,omitempty"` 202 203 // SubstituteFrom holds references to ConfigMaps and Secrets containing 204 // the variables and their values to be substituted in the YAML manifests. 205 // The ConfigMap and the Secret data keys represent the var names and they 206 // must match the vars declared in the manifests for the substitution to happen. 207 // +optional 208 SubstituteFrom []SubstituteReference `json:"substituteFrom,omitempty"` 209 } 210 211 // SubstituteReference contains a reference to a resource containing 212 // the variables name and value. 213 type SubstituteReference struct { 214 // Kind of the values referent, valid values are ('Secret', 'ConfigMap'). 215 // +kubebuilder:validation:Enum=Secret;ConfigMap 216 // +required 217 Kind string `json:"kind"` 218 219 // Name of the values referent. Should reside in the same namespace as the 220 // referring resource. 221 // +kubebuilder:validation:MinLength=1 222 // +kubebuilder:validation:MaxLength=253 223 // +required 224 Name string `json:"name"` 225 226 // Optional indicates whether the referenced resource must exist, or whether to 227 // tolerate its absence. If true and the referenced resource is absent, proceed 228 // as if the resource was present but empty, without any variables defined. 229 // +kubebuilder:default:=false 230 // +optional 231 Optional bool `json:"optional,omitempty"` 232 } 233 234 // KustomizationStatus defines the observed state of a kustomization. 235 type KustomizationStatus struct { 236 meta.ReconcileRequestStatus `json:",inline"` 237 238 // ObservedGeneration is the last reconciled generation. 239 // +optional 240 ObservedGeneration int64 `json:"observedGeneration,omitempty"` 241 242 // +optional 243 Conditions []metav1.Condition `json:"conditions,omitempty"` 244 245 // The last successfully applied revision. 246 // Equals the Revision of the applied Artifact from the referenced Source. 247 // +optional 248 LastAppliedRevision string `json:"lastAppliedRevision,omitempty"` 249 250 // LastAttemptedRevision is the revision of the last reconciliation attempt. 251 // +optional 252 LastAttemptedRevision string `json:"lastAttemptedRevision,omitempty"` 253 254 // Inventory contains the list of Kubernetes resource object references that have been successfully applied. 255 // +optional 256 Inventory *ResourceInventory `json:"inventory,omitempty"` 257 } 258 259 // GetTimeout returns the timeout with default. 260 func (in Kustomization) GetTimeout() time.Duration { 261 duration := in.Spec.Interval.Duration - 30*time.Second 262 if in.Spec.Timeout != nil { 263 duration = in.Spec.Timeout.Duration 264 } 265 if duration < 30*time.Second { 266 return 30 * time.Second 267 } 268 return duration 269 } 270 271 // GetRetryInterval returns the retry interval 272 func (in Kustomization) GetRetryInterval() time.Duration { 273 if in.Spec.RetryInterval != nil { 274 return in.Spec.RetryInterval.Duration 275 } 276 return in.GetRequeueAfter() 277 } 278 279 // GetRequeueAfter returns the duration after which the Kustomization must be 280 // reconciled again. 281 func (in Kustomization) GetRequeueAfter() time.Duration { 282 return in.Spec.Interval.Duration 283 } 284 285 // GetDependsOn returns the list of dependencies across-namespaces. 286 func (in Kustomization) GetDependsOn() []meta.NamespacedObjectReference { 287 return in.Spec.DependsOn 288 } 289 290 // GetConditions returns the status conditions of the object. 291 func (in Kustomization) GetConditions() []metav1.Condition { 292 return in.Status.Conditions 293 } 294 295 // SetConditions sets the status conditions on the object. 296 func (in *Kustomization) SetConditions(conditions []metav1.Condition) { 297 in.Status.Conditions = conditions 298 } 299 300 // GetStatusConditions returns a pointer to the Status.Conditions slice. 301 // Deprecated: use GetConditions instead. 302 func (in *Kustomization) GetStatusConditions() *[]metav1.Condition { 303 return &in.Status.Conditions 304 } 305 306 // +genclient 307 // +kubebuilder:object:root=true 308 // +kubebuilder:resource:shortName=ks 309 // +kubebuilder:subresource:status 310 // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="" 311 // +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="" 312 // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="" 313 // +kubebuilder:deprecatedversion:warning="v1beta2 Kustomization is deprecated, upgrade to v1" 314 315 // Kustomization is the Schema for the kustomizations API. 316 type Kustomization struct { 317 metav1.TypeMeta `json:",inline"` 318 metav1.ObjectMeta `json:"metadata,omitempty"` 319 320 Spec KustomizationSpec `json:"spec,omitempty"` 321 // +kubebuilder:default:={"observedGeneration":-1} 322 Status KustomizationStatus `json:"status,omitempty"` 323 } 324 325 // +kubebuilder:object:root=true 326 327 // KustomizationList contains a list of kustomizations. 328 type KustomizationList struct { 329 metav1.TypeMeta `json:",inline"` 330 metav1.ListMeta `json:"metadata,omitempty"` 331 Items []Kustomization `json:"items"` 332 } 333 334 func init() { 335 SchemeBuilder.Register(&Kustomization{}, &KustomizationList{}) 336 } 337