diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 0c06fbc5..2bc112c9 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -103,7 +103,7 @@ jobs: - name: Run tests for removing kubectl managed fields run: | kubectl create ns managed-fields - kustomize build github.com/stefanprodan/podinfo//kustomize?ref=6.0.0 > /tmp/podinfo.yaml + kustomize build github.com/stefanprodan/podinfo//kustomize?ref=6.3.5 > /tmp/podinfo.yaml kubectl -n managed-fields apply -f /tmp/podinfo.yaml kubectl -n managed-fields apply -f ./config/testdata/managed-fields kubectl -n managed-fields wait kustomization/podinfo --for=condition=ready --timeout=4m diff --git a/Makefile b/Makefile index bc20eb54..263638bd 100644 --- a/Makefile +++ b/Makefile @@ -130,7 +130,7 @@ manifests: controller-gen # Generate API reference documentation api-docs: gen-crd-api-reference-docs - $(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1beta2 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/kustomize.md + $(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1/kustomize.md # Run go mod tidy tidy: diff --git a/PROJECT b/PROJECT index 97afa1d1..4d16c7e8 100644 --- a/PROJECT +++ b/PROJECT @@ -1,6 +1,9 @@ domain: toolkit.fluxcd.io repo: github.com/fluxcd/kustomize-controller resources: +- group: kustomize + kind: Kustomization + version: v1 - group: kustomize kind: Kustomization version: v1beta2 diff --git a/README.md b/README.md index d79a193a..2f7eb07f 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ the controller performs actions to reconcile the cluster current state with the ## Specifications -* [API](docs/spec/v1beta2/README.md) +* [API](docs/spec/v1/README.md) * [Controller](docs/spec/README.md) ## Guides diff --git a/api/v1/condition_types.go b/api/v1/condition_types.go new file mode 100644 index 00000000..39bbf116 --- /dev/null +++ b/api/v1/condition_types.go @@ -0,0 +1,51 @@ +/* +Copyright 2023 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +const ( + // HealthyCondition represents the last recorded + // health assessment result. + HealthyCondition string = "Healthy" + + // PruneFailedReason represents the fact that the + // pruning of the Kustomization failed. + PruneFailedReason string = "PruneFailed" + + // ArtifactFailedReason represents the fact that the + // source artifact download failed. + ArtifactFailedReason string = "ArtifactFailed" + + // BuildFailedReason represents the fact that the + // kustomize build failed. + BuildFailedReason string = "BuildFailed" + + // HealthCheckFailedReason represents the fact that + // one of the health checks failed. + HealthCheckFailedReason string = "HealthCheckFailed" + + // DependencyNotReadyReason represents the fact that + // one of the dependencies is not ready. + DependencyNotReadyReason string = "DependencyNotReady" + + // ReconciliationSucceededReason represents the fact that + // the reconciliation succeeded. + ReconciliationSucceededReason string = "ReconciliationSucceeded" + + // ReconciliationFailedReason represents the fact that + // the reconciliation failed. + ReconciliationFailedReason string = "ReconciliationFailed" +) diff --git a/api/v1/doc.go b/api/v1/doc.go new file mode 100644 index 00000000..fa70fe1d --- /dev/null +++ b/api/v1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2023 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains API Schema definitions for the kustomize.toolkit.fluxcd.io +// v1 API group. +// +kubebuilder:object:generate=true +// +groupName=kustomize.toolkit.fluxcd.io +package v1 diff --git a/api/v1/groupversion_info.go b/api/v1/groupversion_info.go new file mode 100644 index 00000000..e8f6b39f --- /dev/null +++ b/api/v1/groupversion_info.go @@ -0,0 +1,33 @@ +/* +Copyright 2023 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "kustomize.toolkit.fluxcd.io", Version: "v1"} + + // 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 +) diff --git a/api/v1/inventory_types.go b/api/v1/inventory_types.go new file mode 100644 index 00000000..69e52146 --- /dev/null +++ b/api/v1/inventory_types.go @@ -0,0 +1,34 @@ +/* +Copyright 2023 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +// ResourceInventory contains a list of Kubernetes resource object references +// that have been applied by a Kustomization. +type ResourceInventory struct { + // Entries of Kubernetes resource object references. + Entries []ResourceRef `json:"entries"` +} + +// ResourceRef contains the information necessary to locate a resource within a cluster. +type ResourceRef struct { + // ID is the string representation of the Kubernetes resource object's metadata, + // in the format '___'. + ID string `json:"id"` + + // Version is the API version of the Kubernetes resource object's kind. + Version string `json:"v"` +} diff --git a/api/v1/kustomization_types.go b/api/v1/kustomization_types.go new file mode 100644 index 00000000..15e86bca --- /dev/null +++ b/api/v1/kustomization_types.go @@ -0,0 +1,318 @@ +/* +Copyright 2023 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "time" + + "github.com/fluxcd/pkg/apis/kustomize" + "github.com/fluxcd/pkg/apis/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + KustomizationKind = "Kustomization" + KustomizationFinalizer = "finalizers.fluxcd.io" + MaxConditionMessageLength = 20000 + EnabledValue = "enabled" + DisabledValue = "disabled" + MergeValue = "merge" +) + +// KustomizationSpec defines the configuration to calculate the desired state +// from a Source using Kustomize. +type KustomizationSpec struct { + // CommonMetadata specifies the common labels and annotations that are + // applied to all resources. Any existing label or annotation will be + // overridden if its key matches a common one. + // +optional + CommonMetadata *CommonMetadata `json:"commonMetadata,omitempty"` + + // DependsOn may contain a meta.NamespacedObjectReference slice + // with references to Kustomization resources that must be ready before this + // Kustomization can be reconciled. + // +optional + DependsOn []meta.NamespacedObjectReference `json:"dependsOn,omitempty"` + + // Decrypt Kubernetes secrets before applying them on the cluster. + // +optional + Decryption *Decryption `json:"decryption,omitempty"` + + // The interval at which to reconcile the Kustomization. + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" + // +required + Interval metav1.Duration `json:"interval"` + + // The interval at which to retry a previously failed reconciliation. + // When not specified, the controller uses the KustomizationSpec.Interval + // value to retry failures. + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" + // +optional + RetryInterval *metav1.Duration `json:"retryInterval,omitempty"` + + // The KubeConfig for reconciling the Kustomization on a remote cluster. + // When used in combination with KustomizationSpec.ServiceAccountName, + // forces the controller to act on behalf of that Service Account at the + // target cluster. + // If the --default-service-account flag is set, its value will be used as + // a controller level fallback for when KustomizationSpec.ServiceAccountName + // is empty. + // +optional + KubeConfig *meta.KubeConfigReference `json:"kubeConfig,omitempty"` + + // Path to the directory containing the kustomization.yaml file, or the + // set of plain YAMLs a kustomization.yaml should be generated for. + // Defaults to 'None', which translates to the root path of the SourceRef. + // +optional + Path string `json:"path,omitempty"` + + // PostBuild describes which actions to perform on the YAML manifest + // generated by building the kustomize overlay. + // +optional + PostBuild *PostBuild `json:"postBuild,omitempty"` + + // Prune enables garbage collection. + // +required + Prune bool `json:"prune"` + + // A list of resources to be included in the health assessment. + // +optional + HealthChecks []meta.NamespacedObjectKindReference `json:"healthChecks,omitempty"` + + // Strategic merge and JSON patches, defined as inline YAML objects, + // capable of targeting objects based on kind, label and annotation selectors. + // +optional + Patches []kustomize.Patch `json:"patches,omitempty"` + + // Images is a list of (image name, new name, new tag or digest) + // for changing image names, tags or digests. This can also be achieved with a + // patch, but this operator is simpler to specify. + // +optional + Images []kustomize.Image `json:"images,omitempty"` + + // The name of the Kubernetes service account to impersonate + // when reconciling this Kustomization. + // +optional + ServiceAccountName string `json:"serviceAccountName,omitempty"` + + // Reference of the source where the kustomization file is. + // +required + SourceRef CrossNamespaceSourceReference `json:"sourceRef"` + + // This flag tells the controller to suspend subsequent kustomize executions, + // it does not apply to already started executions. Defaults to false. + // +optional + Suspend bool `json:"suspend,omitempty"` + + // TargetNamespace sets or overrides the namespace in the + // kustomization.yaml file. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Optional + // +optional + TargetNamespace string `json:"targetNamespace,omitempty"` + + // Timeout for validation, apply and health checking operations. + // Defaults to 'Interval' duration. + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" + // +optional + Timeout *metav1.Duration `json:"timeout,omitempty"` + + // Force instructs the controller to recreate resources + // when patching fails due to an immutable field change. + // +kubebuilder:default:=false + // +optional + Force bool `json:"force,omitempty"` + + // Wait instructs the controller to check the health of all the reconciled + // resources. When enabled, the HealthChecks are ignored. Defaults to false. + // +optional + Wait bool `json:"wait,omitempty"` + + // Components specifies relative paths to specifications of other Components. + // +optional + Components []string `json:"components,omitempty"` +} + +// CommonMetadata defines the common labels and annotations. +type CommonMetadata struct { + // Annotations to be added to the object's metadata. + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + + // Labels to be added to the object's metadata. + // +optional + Labels map[string]string `json:"labels,omitempty"` +} + +// Decryption defines how decryption is handled for Kubernetes manifests. +type Decryption struct { + // Provider is the name of the decryption engine. + // +kubebuilder:validation:Enum=sops + // +required + Provider string `json:"provider"` + + // The secret name containing the private OpenPGP keys used for decryption. + // +optional + SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"` +} + +// PostBuild describes which actions to perform on the YAML manifest +// generated by building the kustomize overlay. +type PostBuild struct { + // Substitute holds a map of key/value pairs. + // The variables defined in your YAML manifests that match any of the keys + // defined in the map will be substituted with the set value. + // Includes support for bash string replacement functions + // e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}. + // +optional + Substitute map[string]string `json:"substitute,omitempty"` + + // SubstituteFrom holds references to ConfigMaps and Secrets containing + // the variables and their values to be substituted in the YAML manifests. + // The ConfigMap and the Secret data keys represent the var names, and they + // must match the vars declared in the manifests for the substitution to + // happen. + // +optional + SubstituteFrom []SubstituteReference `json:"substituteFrom,omitempty"` +} + +// SubstituteReference contains a reference to a resource containing +// the variables name and value. +type SubstituteReference struct { + // Kind of the values referent, valid values are ('Secret', 'ConfigMap'). + // +kubebuilder:validation:Enum=Secret;ConfigMap + // +required + Kind string `json:"kind"` + + // Name of the values referent. Should reside in the same namespace as the + // referring resource. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +required + Name string `json:"name"` + + // Optional indicates whether the referenced resource must exist, or whether to + // tolerate its absence. If true and the referenced resource is absent, proceed + // as if the resource was present but empty, without any variables defined. + // +kubebuilder:default:=false + // +optional + Optional bool `json:"optional,omitempty"` +} + +// KustomizationStatus defines the observed state of a kustomization. +type KustomizationStatus struct { + meta.ReconcileRequestStatus `json:",inline"` + + // ObservedGeneration is the last reconciled generation. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // The last successfully applied revision. + // Equals the Revision of the applied Artifact from the referenced Source. + // +optional + LastAppliedRevision string `json:"lastAppliedRevision,omitempty"` + + // LastAttemptedRevision is the revision of the last reconciliation attempt. + // +optional + LastAttemptedRevision string `json:"lastAttemptedRevision,omitempty"` + + // Inventory contains the list of Kubernetes resource object references that + // have been successfully applied. + // +optional + Inventory *ResourceInventory `json:"inventory,omitempty"` +} + +// GetTimeout returns the timeout with default. +func (in Kustomization) GetTimeout() time.Duration { + duration := in.Spec.Interval.Duration - 30*time.Second + if in.Spec.Timeout != nil { + duration = in.Spec.Timeout.Duration + } + if duration < 30*time.Second { + return 30 * time.Second + } + return duration +} + +// GetRetryInterval returns the retry interval +func (in Kustomization) GetRetryInterval() time.Duration { + if in.Spec.RetryInterval != nil { + return in.Spec.RetryInterval.Duration + } + return in.GetRequeueAfter() +} + +// GetRequeueAfter returns the duration after which the Kustomization must be +// reconciled again. +func (in Kustomization) GetRequeueAfter() time.Duration { + return in.Spec.Interval.Duration +} + +// GetDependsOn returns the list of dependencies across-namespaces. +func (in Kustomization) GetDependsOn() []meta.NamespacedObjectReference { + return in.Spec.DependsOn +} + +// GetConditions returns the status conditions of the object. +func (in Kustomization) GetConditions() []metav1.Condition { + return in.Status.Conditions +} + +// SetConditions sets the status conditions on the object. +func (in *Kustomization) SetConditions(conditions []metav1.Condition) { + in.Status.Conditions = conditions +} + +// +genclient +// +genclient:Namespaced +// +kubebuilder:storageversion +// +kubebuilder:object:root=true +// +kubebuilder:resource:shortName=ks +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="" + +// Kustomization is the Schema for the kustomizations API. +type Kustomization struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KustomizationSpec `json:"spec,omitempty"` + // +kubebuilder:default:={"observedGeneration":-1} + Status KustomizationStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// KustomizationList contains a list of kustomizations. +type KustomizationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Kustomization `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Kustomization{}, &KustomizationList{}) +} diff --git a/api/v1/reference_types.go b/api/v1/reference_types.go new file mode 100644 index 00000000..cf0d9abd --- /dev/null +++ b/api/v1/reference_types.go @@ -0,0 +1,48 @@ +/* +Copyright 2023 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import "fmt" + +// CrossNamespaceSourceReference contains enough information to let you locate the +// typed Kubernetes resource object at cluster level. +type CrossNamespaceSourceReference struct { + // API version of the referent. + // +optional + APIVersion string `json:"apiVersion,omitempty"` + + // Kind of the referent. + // +kubebuilder:validation:Enum=OCIRepository;GitRepository;Bucket + // +required + Kind string `json:"kind"` + + // Name of the referent. + // +required + Name string `json:"name"` + + // Namespace of the referent, defaults to the namespace of the Kubernetes + // resource object that contains the reference. + // +optional + Namespace string `json:"namespace,omitempty"` +} + +func (s *CrossNamespaceSourceReference) String() string { + if s.Namespace != "" { + return fmt.Sprintf("%s/%s/%s", s.Kind, s.Namespace, s.Name) + } + return fmt.Sprintf("%s/%s", s.Kind, s.Name) +} diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go new file mode 100644 index 00000000..5731df8a --- /dev/null +++ b/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,331 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + "github.com/fluxcd/pkg/apis/kustomize" + "github.com/fluxcd/pkg/apis/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CommonMetadata) DeepCopyInto(out *CommonMetadata) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CommonMetadata. +func (in *CommonMetadata) DeepCopy() *CommonMetadata { + if in == nil { + return nil + } + out := new(CommonMetadata) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CrossNamespaceSourceReference) DeepCopyInto(out *CrossNamespaceSourceReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CrossNamespaceSourceReference. +func (in *CrossNamespaceSourceReference) DeepCopy() *CrossNamespaceSourceReference { + if in == nil { + return nil + } + out := new(CrossNamespaceSourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Decryption) DeepCopyInto(out *Decryption) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(meta.LocalObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Decryption. +func (in *Decryption) DeepCopy() *Decryption { + if in == nil { + return nil + } + out := new(Decryption) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Kustomization) DeepCopyInto(out *Kustomization) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Kustomization. +func (in *Kustomization) DeepCopy() *Kustomization { + if in == nil { + return nil + } + out := new(Kustomization) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Kustomization) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KustomizationList) DeepCopyInto(out *KustomizationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Kustomization, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KustomizationList. +func (in *KustomizationList) DeepCopy() *KustomizationList { + if in == nil { + return nil + } + out := new(KustomizationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KustomizationList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KustomizationSpec) DeepCopyInto(out *KustomizationSpec) { + *out = *in + if in.CommonMetadata != nil { + in, out := &in.CommonMetadata, &out.CommonMetadata + *out = new(CommonMetadata) + (*in).DeepCopyInto(*out) + } + if in.DependsOn != nil { + in, out := &in.DependsOn, &out.DependsOn + *out = make([]meta.NamespacedObjectReference, len(*in)) + copy(*out, *in) + } + if in.Decryption != nil { + in, out := &in.Decryption, &out.Decryption + *out = new(Decryption) + (*in).DeepCopyInto(*out) + } + out.Interval = in.Interval + if in.RetryInterval != nil { + in, out := &in.RetryInterval, &out.RetryInterval + *out = new(metav1.Duration) + **out = **in + } + if in.KubeConfig != nil { + in, out := &in.KubeConfig, &out.KubeConfig + *out = new(meta.KubeConfigReference) + **out = **in + } + if in.PostBuild != nil { + in, out := &in.PostBuild, &out.PostBuild + *out = new(PostBuild) + (*in).DeepCopyInto(*out) + } + if in.HealthChecks != nil { + in, out := &in.HealthChecks, &out.HealthChecks + *out = make([]meta.NamespacedObjectKindReference, len(*in)) + copy(*out, *in) + } + if in.Patches != nil { + in, out := &in.Patches, &out.Patches + *out = make([]kustomize.Patch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Images != nil { + in, out := &in.Images, &out.Images + *out = make([]kustomize.Image, len(*in)) + copy(*out, *in) + } + out.SourceRef = in.SourceRef + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(metav1.Duration) + **out = **in + } + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KustomizationSpec. +func (in *KustomizationSpec) DeepCopy() *KustomizationSpec { + if in == nil { + return nil + } + out := new(KustomizationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KustomizationStatus) DeepCopyInto(out *KustomizationStatus) { + *out = *in + out.ReconcileRequestStatus = in.ReconcileRequestStatus + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Inventory != nil { + in, out := &in.Inventory, &out.Inventory + *out = new(ResourceInventory) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KustomizationStatus. +func (in *KustomizationStatus) DeepCopy() *KustomizationStatus { + if in == nil { + return nil + } + out := new(KustomizationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PostBuild) DeepCopyInto(out *PostBuild) { + *out = *in + if in.Substitute != nil { + in, out := &in.Substitute, &out.Substitute + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.SubstituteFrom != nil { + in, out := &in.SubstituteFrom, &out.SubstituteFrom + *out = make([]SubstituteReference, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostBuild. +func (in *PostBuild) DeepCopy() *PostBuild { + if in == nil { + return nil + } + out := new(PostBuild) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceInventory) DeepCopyInto(out *ResourceInventory) { + *out = *in + if in.Entries != nil { + in, out := &in.Entries, &out.Entries + *out = make([]ResourceRef, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceInventory. +func (in *ResourceInventory) DeepCopy() *ResourceInventory { + if in == nil { + return nil + } + out := new(ResourceInventory) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRef) DeepCopyInto(out *ResourceRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRef. +func (in *ResourceRef) DeepCopy() *ResourceRef { + if in == nil { + return nil + } + out := new(ResourceRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubstituteReference) DeepCopyInto(out *SubstituteReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubstituteReference. +func (in *SubstituteReference) DeepCopy() *SubstituteReference { + if in == nil { + return nil + } + out := new(SubstituteReference) + in.DeepCopyInto(out) + return out +} diff --git a/api/v1beta1/kustomization_types.go b/api/v1beta1/kustomization_types.go index 49160a89..84fc52e1 100644 --- a/api/v1beta1/kustomization_types.go +++ b/api/v1beta1/kustomization_types.go @@ -278,6 +278,7 @@ const ( // +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="" // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="" // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="" +// +kubebuilder:deprecatedversion:warning="v1beta1 Kustomization is deprecated, upgrade to v1" // Kustomization is the Schema for the kustomizations API. type Kustomization struct { diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index f48e1530..d325cf3f 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2021 The Flux authors +Copyright 2023 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/api/v1beta2/kustomization_types.go b/api/v1beta2/kustomization_types.go index 582fe009..e529704d 100644 --- a/api/v1beta2/kustomization_types.go +++ b/api/v1beta2/kustomization_types.go @@ -305,13 +305,13 @@ func (in *Kustomization) GetStatusConditions() *[]metav1.Condition { // +genclient // +genclient:Namespaced -// +kubebuilder:storageversion // +kubebuilder:object:root=true // +kubebuilder:resource:shortName=ks // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="" // +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="" // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="" +// +kubebuilder:deprecatedversion:warning="v1beta2 Kustomization is deprecated, upgrade to v1" // Kustomization is the Schema for the kustomizations API. type Kustomization struct { diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index 5d153cd3..7a148980 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2021 The Flux authors +Copyright 2023 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml b/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml index e8f2a0cc..f5b6ec48 100644 --- a/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml +++ b/config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml @@ -17,6 +17,488 @@ spec: singular: kustomization scope: Namespaced versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: Kustomization is the Schema for the kustomizations API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KustomizationSpec defines the configuration to calculate + the desired state from a Source using Kustomize. + properties: + commonMetadata: + description: CommonMetadata specifies the common labels and annotations + that are applied to all resources. Any existing label or annotation + will be overridden if its key matches a common one. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be added to the object's metadata. + type: object + labels: + additionalProperties: + type: string + description: Labels to be added to the object's metadata. + type: object + type: object + components: + description: Components specifies relative paths to specifications + of other Components. + items: + type: string + type: array + decryption: + description: Decrypt Kubernetes secrets before applying them on the + cluster. + properties: + provider: + description: Provider is the name of the decryption engine. + enum: + - sops + type: string + secretRef: + description: The secret name containing the private OpenPGP keys + used for decryption. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + required: + - provider + type: object + dependsOn: + description: DependsOn may contain a meta.NamespacedObjectReference + slice with references to Kustomization resources that must be ready + before this Kustomization can be reconciled. + items: + description: NamespacedObjectReference contains enough information + to locate the referenced Kubernetes resource object in any namespace. + properties: + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - name + type: object + type: array + force: + default: false + description: Force instructs the controller to recreate resources + when patching fails due to an immutable field change. + type: boolean + healthChecks: + description: A list of resources to be included in the health assessment. + items: + description: NamespacedObjectKindReference contains enough information + to locate the typed referenced Kubernetes resource object in any + namespace. + properties: + apiVersion: + description: API version of the referent, if not specified the + Kubernetes preferred version will be used. + type: string + kind: + description: Kind of the referent. + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, when not specified it + acts as LocalObjectReference. + type: string + required: + - kind + - name + type: object + type: array + images: + description: Images is a list of (image name, new name, new tag or + digest) for changing image names, tags or digests. This can also + be achieved with a patch, but this operator is simpler to specify. + items: + description: Image contains an image name, a new name, a new tag + or digest, which will replace the original name and tag. + properties: + digest: + description: Digest is the value used to replace the original + image tag. If digest is present NewTag value is ignored. + type: string + name: + description: Name is a tag-less image name. + type: string + newName: + description: NewName is the value used to replace the original + name. + type: string + newTag: + description: NewTag is the value used to replace the original + tag. + type: string + required: + - name + type: object + type: array + interval: + description: The interval at which to reconcile the Kustomization. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + kubeConfig: + description: The KubeConfig for reconciling the Kustomization on a + remote cluster. When used in combination with KustomizationSpec.ServiceAccountName, + forces the controller to act on behalf of that Service Account at + the target cluster. If the --default-service-account flag is set, + its value will be used as a controller level fallback for when KustomizationSpec.ServiceAccountName + is empty. + properties: + secretRef: + description: SecretRef holds the name of a secret that contains + a key with the kubeconfig file as the value. If no key is set, + the key will default to 'value'. It is recommended that the + kubeconfig is self-contained, and the secret is regularly updated + if credentials such as a cloud-access-token expire. Cloud specific + `cmd-path` auth helpers will not function without adding binaries + and credentials to the Pod that is responsible for reconciling + Kubernetes resources. + properties: + key: + description: Key in the Secret, when not specified an implementation-specific + default key is used. + type: string + name: + description: Name of the Secret. + type: string + required: + - name + type: object + required: + - secretRef + type: object + patches: + description: Strategic merge and JSON patches, defined as inline YAML + objects, capable of targeting objects based on kind, label and annotation + selectors. + items: + description: Patch contains an inline StrategicMerge or JSON6902 + patch, and the target the patch should be applied to. + properties: + patch: + description: Patch contains an inline StrategicMerge patch or + an inline JSON6902 patch with an array of operation objects. + type: string + target: + description: Target points to the resources that the patch document + should be applied to. + properties: + annotationSelector: + description: AnnotationSelector is a string that follows + the label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource annotations. + type: string + group: + description: Group is the API group to select resources + from. Together with Version and Kind it is capable of + unambiguously identifying and/or selecting resources. + https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + kind: + description: Kind of the API Group to select resources from. + Together with Group and Version it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + labelSelector: + description: LabelSelector is a string that follows the + label selection expression https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#api + It matches with the resource labels. + type: string + name: + description: Name to match resources with. + type: string + namespace: + description: Namespace to select resources from. + type: string + version: + description: Version of the API Group to select resources + from. Together with Group and Kind it is capable of unambiguously + identifying and/or selecting resources. https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/api-group.md + type: string + type: object + required: + - patch + type: object + type: array + path: + description: Path to the directory containing the kustomization.yaml + file, or the set of plain YAMLs a kustomization.yaml should be generated + for. Defaults to 'None', which translates to the root path of the + SourceRef. + type: string + postBuild: + description: PostBuild describes which actions to perform on the YAML + manifest generated by building the kustomize overlay. + properties: + substitute: + additionalProperties: + type: string + description: Substitute holds a map of key/value pairs. The variables + defined in your YAML manifests that match any of the keys defined + in the map will be substituted with the set value. Includes + support for bash string replacement functions e.g. ${var:=default}, + ${var:position} and ${var/substring/replacement}. + type: object + substituteFrom: + description: SubstituteFrom holds references to ConfigMaps and + Secrets containing the variables and their values to be substituted + in the YAML manifests. The ConfigMap and the Secret data keys + represent the var names, and they must match the vars declared + in the manifests for the substitution to happen. + items: + description: SubstituteReference contains a reference to a resource + containing the variables name and value. + properties: + kind: + description: Kind of the values referent, valid values are + ('Secret', 'ConfigMap'). + enum: + - Secret + - ConfigMap + type: string + name: + description: Name of the values referent. Should reside + in the same namespace as the referring resource. + maxLength: 253 + minLength: 1 + type: string + optional: + default: false + description: Optional indicates whether the referenced resource + must exist, or whether to tolerate its absence. If true + and the referenced resource is absent, proceed as if the + resource was present but empty, without any variables + defined. + type: boolean + required: + - kind + - name + type: object + type: array + type: object + prune: + description: Prune enables garbage collection. + type: boolean + retryInterval: + description: The interval at which to retry a previously failed reconciliation. + When not specified, the controller uses the KustomizationSpec.Interval + value to retry failures. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + serviceAccountName: + description: The name of the Kubernetes service account to impersonate + when reconciling this Kustomization. + type: string + sourceRef: + description: Reference of the source where the kustomization file + is. + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: Kind of the referent. + enum: + - OCIRepository + - GitRepository + - Bucket + type: string + name: + description: Name of the referent. + type: string + namespace: + description: Namespace of the referent, defaults to the namespace + of the Kubernetes resource object that contains the reference. + type: string + required: + - kind + - name + type: object + suspend: + description: This flag tells the controller to suspend subsequent + kustomize executions, it does not apply to already started executions. + Defaults to false. + type: boolean + targetNamespace: + description: TargetNamespace sets or overrides the namespace in the + kustomization.yaml file. + maxLength: 63 + minLength: 1 + type: string + timeout: + description: Timeout for validation, apply and health checking operations. + Defaults to 'Interval' duration. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + wait: + description: Wait instructs the controller to check the health of + all the reconciled resources. When enabled, the HealthChecks are + ignored. Defaults to false. + type: boolean + required: + - interval + - prune + - sourceRef + type: object + status: + default: + observedGeneration: -1 + description: KustomizationStatus defines the observed state of a kustomization. + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + inventory: + description: Inventory contains the list of Kubernetes resource object + references that have been successfully applied. + properties: + entries: + description: Entries of Kubernetes resource object references. + items: + description: ResourceRef contains the information necessary + to locate a resource within a cluster. + properties: + id: + description: ID is the string representation of the Kubernetes + resource object's metadata, in the format '___'. + type: string + v: + description: Version is the API version of the Kubernetes + resource object's kind. + type: string + required: + - id + - v + type: object + type: array + required: + - entries + type: object + lastAppliedRevision: + description: The last successfully applied revision. Equals the Revision + of the applied Artifact from the referenced Source. + type: string + lastAttemptedRevision: + description: LastAttemptedRevision is the revision of the last reconciliation + attempt. + type: string + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last reconciled generation. + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} - additionalPrinterColumns: - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready @@ -27,6 +509,8 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date + deprecated: true + deprecationWarning: v1beta1 Kustomization is deprecated, upgrade to v1 name: v1beta1 schema: openAPIV3Schema: @@ -566,6 +1050,8 @@ spec: - jsonPath: .status.conditions[?(@.type=="Ready")].message name: Status type: string + deprecated: true + deprecationWarning: v1beta2 Kustomization is deprecated, upgrade to v1 name: v1beta2 schema: openAPIV3Schema: @@ -1137,6 +1623,6 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: status: {} diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index faba8968..151ee30c 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -2,8 +2,8 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: kustomize-system resources: -- https://github.com/fluxcd/source-controller/releases/download/v0.36.0/source-controller.crds.yaml -- https://github.com/fluxcd/source-controller/releases/download/v0.36.0/source-controller.deployment.yaml +- https://github.com/fluxcd/source-controller/releases/download/v1.0.0-rc.1/source-controller.crds.yaml +- https://github.com/fluxcd/source-controller/releases/download/v1.0.0-rc.1/source-controller.deployment.yaml - ../crd - ../rbac - ../manager diff --git a/config/samples/kustomize_v1beta1_kustomization.yaml b/config/samples/kustomize_v1_kustomization.yaml similarity index 85% rename from config/samples/kustomize_v1beta1_kustomization.yaml rename to config/samples/kustomize_v1_kustomization.yaml index 35164984..d296984b 100644 --- a/config/samples/kustomize_v1beta1_kustomization.yaml +++ b/config/samples/kustomize_v1_kustomization.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: webapp-dev @@ -12,7 +12,7 @@ spec: wait: true timeout: 2m --- -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: webapp-production diff --git a/config/samples/source_v1beta1_gitrepository.yaml b/config/samples/source_v1_gitrepository.yaml similarity index 76% rename from config/samples/source_v1beta1_gitrepository.yaml rename to config/samples/source_v1_gitrepository.yaml index 60b5a4d4..431f8382 100644 --- a/config/samples/source_v1beta1_gitrepository.yaml +++ b/config/samples/source_v1_gitrepository.yaml @@ -1,4 +1,4 @@ -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: webapp-latest @@ -8,7 +8,7 @@ spec: ref: branch: master --- -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: webapp-releases diff --git a/config/testdata/crds-crs/cert-manager.yaml b/config/testdata/crds-crs/cert-manager.yaml index 1cec3dc5..0f43c6f7 100644 --- a/config/testdata/crds-crs/cert-manager.yaml +++ b/config/testdata/crds-crs/cert-manager.yaml @@ -1,4 +1,4 @@ -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: certs @@ -8,7 +8,7 @@ spec: ref: tag: "v1.1.0" --- -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: certs diff --git a/config/testdata/dependencies/backend.yaml b/config/testdata/dependencies/backend.yaml index 15ceba5e..820cb29b 100644 --- a/config/testdata/dependencies/backend.yaml +++ b/config/testdata/dependencies/backend.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: backend @@ -11,9 +11,8 @@ spec: sourceRef: kind: GitRepository name: webapp - validation: server healthChecks: - kind: Deployment name: backend namespace: webapp - timeout: 2m \ No newline at end of file + timeout: 2m diff --git a/config/testdata/dependencies/common.yaml b/config/testdata/dependencies/common.yaml index 5c5ac249..f605aa8c 100644 --- a/config/testdata/dependencies/common.yaml +++ b/config/testdata/dependencies/common.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: common @@ -9,4 +9,3 @@ spec: sourceRef: kind: GitRepository name: webapp - validation: client diff --git a/config/testdata/dependencies/frontend.yaml b/config/testdata/dependencies/frontend.yaml index b26f6709..38d0bfeb 100644 --- a/config/testdata/dependencies/frontend.yaml +++ b/config/testdata/dependencies/frontend.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: frontend @@ -12,9 +12,8 @@ spec: sourceRef: kind: GitRepository name: webapp - validation: server healthChecks: - kind: Deployment name: frontend namespace: webapp - timeout: 2m \ No newline at end of file + timeout: 2m diff --git a/config/testdata/dependencies/source.yaml b/config/testdata/dependencies/source.yaml index b6dd9a63..5d1e3a54 100644 --- a/config/testdata/dependencies/source.yaml +++ b/config/testdata/dependencies/source.yaml @@ -1,4 +1,4 @@ -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: webapp @@ -6,4 +6,4 @@ spec: interval: 10m url: https://github.com/stefanprodan/podinfo ref: - semver: ">=3.2.3" + semver: ">=6.3.5" diff --git a/config/testdata/impersonation/test.yaml b/config/testdata/impersonation/test.yaml index 0aa96029..3c3c6465 100644 --- a/config/testdata/impersonation/test.yaml +++ b/config/testdata/impersonation/test.yaml @@ -33,7 +33,7 @@ subjects: name: gotk-reconciler namespace: impersonation --- -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: podinfo @@ -42,9 +42,9 @@ spec: interval: 5m url: https://github.com/stefanprodan/podinfo ref: - tag: "6.3.0" + tag: "6.3.5" --- -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: podinfo diff --git a/config/testdata/managed-fields/podinfo.yaml b/config/testdata/managed-fields/podinfo.yaml index 1f065fc0..7e3c5a8c 100644 --- a/config/testdata/managed-fields/podinfo.yaml +++ b/config/testdata/managed-fields/podinfo.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: podinfo @@ -12,7 +12,7 @@ spec: timeout: 1m targetNamespace: managed-fields --- -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: podinfo @@ -20,4 +20,4 @@ spec: interval: 5m url: https://github.com/stefanprodan/podinfo ref: - semver: "6.0.0" + semver: "6.3.5" diff --git a/config/testdata/oci/podinfo.yaml b/config/testdata/oci/podinfo.yaml index fc80f79f..da480a80 100644 --- a/config/testdata/oci/podinfo.yaml +++ b/config/testdata/oci/podinfo.yaml @@ -7,9 +7,9 @@ spec: interval: 10m url: oci://ghcr.io/stefanprodan/manifests/podinfo ref: - tag: "6.3.0" + tag: "6.3.5" --- -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: oci @@ -17,7 +17,7 @@ metadata: spec: targetNamespace: oci interval: 10m - path: "./kustomize" + path: "./" prune: true sourceRef: kind: OCIRepository diff --git a/config/testdata/overlays/production.yaml b/config/testdata/overlays/production.yaml index 96381c72..d051cd76 100644 --- a/config/testdata/overlays/production.yaml +++ b/config/testdata/overlays/production.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: webapp-production @@ -9,7 +9,6 @@ spec: sourceRef: kind: GitRepository name: webapp-releases - validation: client healthChecks: - kind: Deployment name: backend @@ -19,7 +18,7 @@ spec: namespace: production timeout: 2m --- -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: webapp-releases @@ -27,4 +26,4 @@ spec: interval: 5m url: https://github.com/stefanprodan/podinfo ref: - semver: ">=3.2.3" + semver: ">=6.3.5" diff --git a/config/testdata/overlays/staging.yaml b/config/testdata/overlays/staging.yaml index 81dc44e2..70aa176c 100644 --- a/config/testdata/overlays/staging.yaml +++ b/config/testdata/overlays/staging.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: webapp-staging @@ -9,7 +9,6 @@ spec: sourceRef: kind: GitRepository name: webapp-releases - validation: client healthChecks: - kind: Deployment name: backend @@ -19,7 +18,7 @@ spec: namespace: staging timeout: 2m --- -apiVersion: source.toolkit.fluxcd.io/v1beta1 +apiVersion: source.toolkit.fluxcd.io/v1 kind: GitRepository metadata: name: webapp-latest diff --git a/config/testdata/status-defaults/empty-kustomization.yaml b/config/testdata/status-defaults/empty-kustomization.yaml index 80620f12..d4fd9197 100644 --- a/config/testdata/status-defaults/empty-kustomization.yaml +++ b/config/testdata/status-defaults/empty-kustomization.yaml @@ -1,4 +1,4 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta1 +apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: status-defaults diff --git a/docs/api/kustomize.md b/docs/api/v1/kustomize.md similarity index 78% rename from docs/api/kustomize.md rename to docs/api/v1/kustomize.md index d5b0ec9d..76c1804b 100644 --- a/docs/api/kustomize.md +++ b/docs/api/v1/kustomize.md @@ -1,17 +1,18 @@ -

Kustomize API reference

+

Kustomize API reference v1

Packages:

-

kustomize.toolkit.fluxcd.io/v1beta2

-

Package v1beta2 contains API Schema definitions for the kustomize.toolkit.fluxcd.io v1beta2 API group.

+

kustomize.toolkit.fluxcd.io/v1

+

Package v1 contains API Schema definitions for the kustomize.toolkit.fluxcd.io +v1 API group.

Resource Types: -

Kustomization +

Kustomization

Kustomization is the Schema for the kustomizations API.

@@ -29,7 +30,7 @@ Resource Types: apiVersion
string -kustomize.toolkit.fluxcd.io/v1beta2 +kustomize.toolkit.fluxcd.io/v1 @@ -59,7 +60,7 @@ Refer to the Kubernetes API documentation for the fields of the spec
- + KustomizationSpec @@ -72,15 +73,16 @@ KustomizationSpec commonMetadata
- + CommonMetadata (Optional) -

CommonMetadata specifies the common labels and annotations that are applied to all resources. -Any existing label or annotation will be overridden if its key matches a common one.

+

CommonMetadata specifies the common labels and annotations that are +applied to all resources. Any existing label or annotation will be +overridden if its key matches a common one.

@@ -103,7 +105,7 @@ Kustomization can be reconciled.

decryption
- + Decryption @@ -180,7 +182,7 @@ Defaults to ‘None’, which translates to the root path of the SourceR postBuild
- + PostBuild @@ -233,36 +235,6 @@ capable of targeting objects based on kind, label and annotation selectors.

-patchesStrategicMerge
- - -[]Kubernetes pkg/apis/apiextensions/v1.JSON - - - - -(Optional) -

Strategic merge patches, defined as inline YAML objects. -Deprecated: Use Patches instead.

- - - - -patchesJson6902
- - -[]github.com/fluxcd/pkg/apis/kustomize.JSON6902Patch - - - - -(Optional) -

JSON 6902 patches, defined as inline YAML objects. -Deprecated: Use Patches instead.

- - - - images
@@ -294,7 +266,7 @@ when reconciling this Kustomization.

sourceRef
-
+ CrossNamespaceSourceReference @@ -366,8 +338,8 @@ bool (Optional) -

Wait instructs the controller to check the health of all the reconciled resources. -When enabled, the HealthChecks are ignored. Defaults to false.

+

Wait instructs the controller to check the health of all the reconciled +resources. When enabled, the HealthChecks are ignored. Defaults to false.

@@ -382,18 +354,6 @@ When enabled, the HealthChecks are ignored. Defaults to false.

Components specifies relative paths to specifications of other Components.

- - -validation
- -string - - - -(Optional) -

Deprecated: Not used in v1beta2.

- - @@ -401,7 +361,7 @@ string status
- + KustomizationStatus @@ -413,11 +373,11 @@ KustomizationStatus
-

CommonMetadata +

CommonMetadata

(Appears on: -KustomizationSpec) +KustomizationSpec)

CommonMetadata defines the common labels and annotations.

@@ -458,11 +418,11 @@ map[string]string
-

CrossNamespaceSourceReference +

CrossNamespaceSourceReference

(Appears on: -KustomizationSpec) +KustomizationSpec)

CrossNamespaceSourceReference contains enough information to let you locate the typed Kubernetes resource object at cluster level.

@@ -519,18 +479,19 @@ string (Optional) -

Namespace of the referent, defaults to the namespace of the Kubernetes resource object that contains the reference.

+

Namespace of the referent, defaults to the namespace of the Kubernetes +resource object that contains the reference.

-

Decryption +

Decryption

(Appears on: -KustomizationSpec) +KustomizationSpec)

Decryption defines how decryption is handled for Kubernetes manifests.

@@ -572,13 +533,14 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
-

KustomizationSpec +

KustomizationSpec

(Appears on: -Kustomization) +Kustomization)

-

KustomizationSpec defines the configuration to calculate the desired state from a Source using Kustomize.

+

KustomizationSpec defines the configuration to calculate the desired state +from a Source using Kustomize.

@@ -593,15 +555,16 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference @@ -624,7 +587,7 @@ Kustomization can be reconciled.

- - - - - - - - @@ -903,27 +836,15 @@ When enabled, the HealthChecks are ignored. Defaults to false.

Components specifies relative paths to specifications of other Components.

- - - -
commonMetadata
- + CommonMetadata
(Optional) -

CommonMetadata specifies the common labels and annotations that are applied to all resources. -Any existing label or annotation will be overridden if its key matches a common one.

+

CommonMetadata specifies the common labels and annotations that are +applied to all resources. Any existing label or annotation will be +overridden if its key matches a common one.

decryption
- + Decryption @@ -701,7 +664,7 @@ Defaults to ‘None’, which translates to the root path of the SourceR
postBuild
- + PostBuild @@ -754,36 +717,6 @@ capable of targeting objects based on kind, label and annotation selectors.

-patchesStrategicMerge
- - -[]Kubernetes pkg/apis/apiextensions/v1.JSON - - -
-(Optional) -

Strategic merge patches, defined as inline YAML objects. -Deprecated: Use Patches instead.

-
-patchesJson6902
- - -[]github.com/fluxcd/pkg/apis/kustomize.JSON6902Patch - - -
-(Optional) -

JSON 6902 patches, defined as inline YAML objects. -Deprecated: Use Patches instead.

-
images
@@ -815,7 +748,7 @@ when reconciling this Kustomization.

sourceRef
- + CrossNamespaceSourceReference @@ -887,8 +820,8 @@ bool
(Optional) -

Wait instructs the controller to check the health of all the reconciled resources. -When enabled, the HealthChecks are ignored. Defaults to false.

+

Wait instructs the controller to check the health of all the reconciled +resources. When enabled, the HealthChecks are ignored. Defaults to false.

-validation
- -string - -
-(Optional) -

Deprecated: Not used in v1beta2.

-
-

KustomizationStatus +

KustomizationStatus

(Appears on: -Kustomization) +Kustomization)

KustomizationStatus defines the observed state of a kustomization.

@@ -1005,25 +926,26 @@ string inventory
- + ResourceInventory (Optional) -

Inventory contains the list of Kubernetes resource object references that have been successfully applied.

+

Inventory contains the list of Kubernetes resource object references that +have been successfully applied.

-

PostBuild +

PostBuild

(Appears on: -KustomizationSpec) +KustomizationSpec)

PostBuild describes which actions to perform on the YAML manifest generated by building the kustomize overlay.

@@ -1047,9 +969,8 @@ map[string]string (Optional)

Substitute holds a map of key/value pairs. -The variables defined in your YAML manifests -that match any of the keys defined in the map -will be substituted with the set value. +The variables defined in your YAML manifests that match any of the keys +defined in the map will be substituted with the set value. Includes support for bash string replacement functions e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}.

@@ -1058,7 +979,7 @@ e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}.

substituteFrom
- + []SubstituteReference @@ -1067,21 +988,23 @@ e.g. ${var:=default}, ${var:position} and ${var/substring/replacement}.

(Optional)

SubstituteFrom holds references to ConfigMaps and Secrets containing the variables and their values to be substituted in the YAML manifests. -The ConfigMap and the Secret data keys represent the var names and they -must match the vars declared in the manifests for the substitution to happen.

+The ConfigMap and the Secret data keys represent the var names, and they +must match the vars declared in the manifests for the substitution to +happen.

-

ResourceInventory +

ResourceInventory

(Appears on: -KustomizationStatus) +KustomizationStatus)

-

ResourceInventory contains a list of Kubernetes resource object references that have been applied by a Kustomization.

+

ResourceInventory contains a list of Kubernetes resource object references +that have been applied by a Kustomization.

@@ -1096,7 +1019,7 @@ must match the vars declared in the manifests for the substitution to happen.

entries
- + []ResourceRef @@ -1109,11 +1032,11 @@ must match the vars declared in the manifests for the substitution to happen.

-

ResourceRef +

ResourceRef

(Appears on: -ResourceInventory) +ResourceInventory)

ResourceRef contains the information necessary to locate a resource within a cluster.

@@ -1153,11 +1076,11 @@ string
-

SubstituteReference +

SubstituteReference

(Appears on: -PostBuild) +PostBuild)

SubstituteReference contains a reference to a resource containing the variables name and value.

diff --git a/docs/spec/README.md b/docs/spec/README.md index c980280b..166d7311 100644 --- a/docs/spec/README.md +++ b/docs/spec/README.md @@ -1,53 +1,7 @@ # Kustomize Controller -The kustomize-controller is a Kubernetes operator, specialized in running -continuous delivery pipelines for infrastructure and workloads -defined with Kubernetes manifests and assembled with Kustomize. +## API Specification -## Motivation - -The main goal is to provide an automated operator that can -bootstrap and continuously reconcile the cluster state -from multiple sources (e.g. infrastructure and application repositories). - -When provisioning a new cluster, one may wish to install workloads in a specific order, -for example a validation controller such as OPA Gatekeeper should be up and running before -applying other manifests on the cluster. Another example is a service mesh admission controller, -the proxy injector must be functional before deploying applications into the mesh. - -When a cluster is shared with multiple teams, a cluster admin may wish to assign roles and service -accounts to each team. The manifests owned by a team will be applied on the cluster using -the team's account thus ensuring isolation between teams. For example, an admin can -restrict the operations performed on the cluster by a team to a single namespace. - -When dealing with an incident, one may wish to suspend the reconciliation of some workloads and -pin the reconciliation of others to a specific Git revision, without having to stop the reconciler -and affect the whole cluster. - -When operating a cluster, different teams may wish to receive notification about the status -of their CD pipelines. For example, the on-call team would receive alerts about all -failures in the prod namespace, while the frontend team may wish to be alerted when a new version -of the frontend app was deployed and if the deployment is healthy, no matter the namespace. - -## Design - -The reconciliation process can be defined with a Kubernetes custom resource -that describes a pipeline such as: -- **check** if depends-on conditions are meet -- **fetch** manifests from source-controller -- **generate** `kustomization.yaml` if needed -- **build** the manifests using the Kustomize SDK -- **decrypt** Kubernetes secrets using Mozilla SOPS SDK -- **impersonate** the tenant's Kubernetes account -- **validate** the resulting objects using server-side apply dry-run -- **detect drift** between the desired and state and cluster state -- **correct drift** by applying the objects using server-side apply -- **prune** the objects removed from source -- **wait** for the applied changes to rollout using Kubernetes kstatus library -- **report** the reconciliation result in the `status` sub-resource -- **alert** if something went wrong by sending events to Kubernetes API and notification-controller -- **notify** if the cluster state changed by sending events to Kubernetes API and notification-controller - -## Specifications - -The latest API specifications can be found [here](v1beta2/README.md). +[v1beta1](v1beta2/README.md). +[v1beta2](v1beta2/README.md). +[v1](v1/README.md). diff --git a/docs/spec/v1/README.md b/docs/spec/v1/README.md new file mode 100644 index 00000000..8c64134d --- /dev/null +++ b/docs/spec/v1/README.md @@ -0,0 +1,17 @@ +# kustomize.toolkit.fluxcd.io/v1 + +This is the v1 API specification for defining continuous delivery pipelines +of Kubernetes objects generated with Kustomize. + +## Specification + +- [Kustomization CRD](kustomization.md) + + [Example](kustomization.md#example) + + [Writing a Kustomization spec](kustomization.md#writing-a-kustomization-spec) + + [Working with Kustomizations](kustomization.md#working-with-kustomizations) + * [Recommended settings](kustomization.md#recommended-settings) + + [Kustomization Status](kustomization.md#kustomization-status) + +## Implementation + +* [kustomize-controller](https://github.com/fluxcd/kustomize-controller/) diff --git a/docs/spec/v1/kustomization.md b/docs/spec/v1/kustomization.md new file mode 100644 index 00000000..d8ccb109 --- /dev/null +++ b/docs/spec/v1/kustomization.md @@ -0,0 +1,1782 @@ +# Kustomization + + + +The `Kustomization` API defines a pipeline for fetching, decrypting, building, +validating and applying Kustomize overlays or plain Kubernetes manifests. +The `Kustomization` Custom Resource Definition is the +counterpart of Kustomize's `kustomization.yaml` config file. + +## Example + +The following is an example of a Flux Kustomization that reconciles the +Kubernetes manifests stored in a Git repository. + +```yaml +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: podinfo + namespace: default +spec: + interval: 5m + url: https://github.com/stefanprodan/podinfo + ref: + branch: master +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: podinfo + namespace: default +spec: + interval: 10m + targetNamespace: default + sourceRef: + kind: GitRepository + name: podinfo + path: "./kustomize" + prune: true + timeout: 1m +``` + +In the above example: + +- A Flux GitRepository named `podinfo` is created that clones the `master` + branch and makes the repository content available as an Artifact inside the cluster. +- A Flux Kustomization named `podinfo` is created that watches the + GitRepository for Artifact changes. +- The Kustomization builds the YAML manifests located at the specified `.spec.path`, + sets the namespace of all objects to the `.spec.targetNamespace`, + validates the objects against the Kubernetes API and finally applies them on + the cluster. +- As specified by `.spec.interval`, every ten minutes, the Kustomization runs a + server-side apply dry-run to detect and correct drift inside the cluster. +- When the Git revision changes, the manifests are reconciled automatically. If + previously applied objects are missing from the current revision, these + objects are deleted from the cluster when `.spec.prune` is enabled. + +You can run this example by saving the manifest into `podinfo.yaml`. + +1. Apply the resource on the cluster: + + ```sh + kubectl apply -f podinfo.yaml + ``` + +2. Run `kubectl get gitrepositories` to see the source status: + + ```console + NAME URL READY STATUS + podinfo https://github.com/stefanprodan/podinfo True stored artifact for revision 'master@sha1:450796ddb2ab6724ee1cc32a4be56da032d1cca0' + ``` + +3. Run `kubectl get kustomizations` to see the reconciliation status: + + ```console + NAME READY STATUS + podinfo True Applied revision: master@sha1:450796ddb2ab6724ee1cc32a4be56da032d1cca0 + ``` + +4. Run `kubectl describe kustomization podinfo` to see the reconciliation status + conditions and events: + + ```console + ... + Status: + Conditions: + Last Transition Time: 2023-03-07T11:14:41Z + Message: Applied revision: master@sha1:450796ddb2ab6724ee1cc32a4be56da032d1cca0 + Reason: ReconciliationSucceeded + Status: True + Type: Ready + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Progressing 1m48s kustomize-controller Service/default/podinfo created + Deployment/default/podinfo created + HorizontalPodAutoscaler/default/podinfo created + Normal ReconciliationSucceeded 1m48s kustomize-controller Reconciliation finished in 176.163666ms, next run in 10m0s + ``` + +## Writing a Kustomization spec + +As with all other Kubernetes config, a Kustomization needs `apiVersion`, +`kind`, and `metadata` fields. The name of a Kustomization object must be a +valid [DNS subdomain name](https://kubernetes.io/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). + +A Kustomization also needs a +[`.spec` section](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status). + +### Source reference + +`.spec.sourceRef` is used to refer to the Source object which has the required +Artifact containing the YAML manifests. It has two required fields: + +- `kind`: The Kind of the referred Source object. Supported Source types: + + [GitRepository](https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/gitrepositories.md) + + [OCIRepository](https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1beta2/ocirepositories.md) + + [Bucket](https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1beta2/buckets.md) +- `name`: The Name of the referred Source object. + +#### Cross-namespace references + +By default, the Source object is assumed to be in the same namespace as the +Kustomization. To refer to a Source object in a different namespace, specify +the namespace using `.spec.sourceRef.namespace`. + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: webapp + namespace: apps +spec: + interval: 5m + path: "./deploy" + sourceRef: + kind: GitRepository + name: webapp + namespace: shared +``` + +On multi-tenant clusters, platform admins can disable cross-namespace references +by starting kustomize-controller with the `--no-cross-namespace-refs=true` flag. + +### Prune + +`.spec.prune` is a required boolean field to enable/disable garbage collection +for a Kustomization. + +Garbage collection means that the Kubernetes objects that were previously +applied on the cluster but are missing from the current source revision, are +removed from the cluster automatically. Garbage collection is also performed +when a Kustomization object is deleted, triggering a removal of all Kubernetes +objects previously applied on the cluster. The removal of the Kubernetes +objects is done in the background, i.e. it doesn't block the reconciliation of +the Kustomization. + +To enable garbage collection for a Kustomization, set this field to `true`. + +You can disable pruning for certain resources by either labelling or +annotating them with: + +```yaml +kustomize.toolkit.fluxcd.io/prune: disabled +``` + +For details on how the controller tracks Kubernetes objects and determines what +to garbage collect, see [`.status.inventory`](#inventory). + +### Interval + +`.spec.interval` is a required field that specifies the interval at which the +Kustomization is reconciled, i.e. the controller fetches the source with the +Kubernetes manifests, builds the Kustomization and applies it on the cluster, +correcting any existing drift in the process. The minimum value should be 60 +seconds. + +After successfully reconciling the object, the controller requeues it for +inspection after the specified interval. The value must be in a +[Go recognized duration string format](https://pkg.go.dev/time#ParseDuration), +e.g. `10m0s` to reconcile the object every 10 minutes. + +If the `.metadata.generation` of a resource changes (due to e.g. a change to +the spec) or the Source revision changes (which generates a Kubernetes event), +this is handled instantly outside the interval window. + +### Retry interval + +`.spec.retryInterval` is an optional field to specify the interval at which to +retry a failed reconciliation. Unlike `.spec.interval`, this field is +exclusively meant for failure retries. If not specified, it defaults to +`.spec.interval`. + +### Path + +`.spec.path` is an optional field to specify the path to the directory in the +Source Artifact containing the `kustomization.yaml` file, or the set of plain +YAMLs for which a `kustomization.yaml` should be generated. +It defaults to blank, which translates to the root of the Source Artifact. + +For more details on the generation of the file, see [generating a +`kustomization.yaml` file](#generating-a-kustomizationyaml-file). + +### Target namespace + +`.spec.targetNamespace` is an optional field to specify the target namespace for +all the objects that are part of the Kustomization. It either configures or +overrides the [Kustomize `namespace`](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/namespace/). + +While `.spec.targetNamespace` is optional, if this field is non-empty then the +Kubernetes namespace being pointed to must exist prior to the Kustomization +being applied, kustomize-controller will not create the namespace. + +### Suspend + +`.spec.suspend` is an optional boolean field to suspend the reconciliation of the +Kustomization. When a Kustomization is suspended, new Source revisions are not +applied to the cluster and drift detection/correction is paused. +To resume normal reconciliation, set it back to `false` or remove the field. + +For more information, see [suspending and resuming](#suspending-and-resuming). + +### Health checks + +`.spec.healthChecks` is an optional list used to refer to resources for which the +controller will perform health checks used to determine the rollout status of +[deployed workloads](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#deployment-status) +and the `Ready` status of custom resources. + +A health check entry can reference one of the following types: + +- Kubernetes built-in kinds: Deployment, DaemonSet, StatefulSet, + PersistentVolumeClaim, Pod, PodDisruptionBudget, Job, CronJob, Service, + Secret, ConfigMap, CustomResourceDefinition +- Flux kinds: HelmRelease, HelmRepository, GitRepository, etc. +- Custom resources that are compatible with [kstatus](https://github.com/kubernetes-sigs/cli-utils/tree/master/pkg/kstatus) + +Assuming the Kustomization source contains a Kubernetes Deployment named +`backend`, a health check can be defined as follows: + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: backend + namespace: default +spec: + interval: 5m + prune: true + sourceRef: + kind: GitRepository + name: webapp + healthChecks: + - apiVersion: apps/v1 + kind: Deployment + name: backend + namespace: dev +``` + +After applying the kustomize build output, the controller verifies if the +rollout was completed successfully. If the deployment was successful, the +Kustomization `Ready` condition is marked as `True`, if the rollout failed, +or if it takes more than the specified timeout to complete, then the +Kustomization `Ready` condition is set to `False`. If the deployment becomes +healthy on the next execution, then the Kustomization is marked as ready. + +When a Kustomization contains HelmRelease objects, instead of checking the +underlying Deployments, you can define a health check that waits for the +HelmReleases to be reconciled with: + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: webapp + namespace: default +spec: + interval: 15m + path: "./releases/" + prune: true + sourceRef: + kind: GitRepository + name: webapp + healthChecks: + - apiVersion: helm.toolkit.fluxcd.io/v2beta1 + kind: HelmRelease + name: frontend + namespace: dev + - apiVersion: helm.toolkit.fluxcd.io/v2beta1 + kind: HelmRelease + name: backend + namespace: dev + timeout: 5m +``` + +If all the HelmRelease objects are successfully installed or upgraded, then +the Kustomization will be marked as ready. + +### Wait + +`.spec.wait` is an optional boolean field to perform health checks for __all__ +reconciled resources as part of the Kustomization. If set to `true`, +`.spec.healthChecks` is ignored. + +### Timeout + +`.spec.timeout` is an optional field to specify a timeout duration for any +operation like building, applying, health checking, etc. performed during the +reconciliation process. + +### Dependencies + +`.spec.dependsOn` is an optional list used to refer to other Kustomization +objects that the Kustomization depends on. If specified, then the Kustomization +is only applied after the referred Kustomizations are ready, i.e. have the +`Ready` condition marked as `True`. The readiness state of a Kustomization is +determined by its last applied status condition. + +This is helpful when there is a need to make sure other resources exist before +the workloads defined in a Kustomization are deployed. For example, before +installing objects of a certain custom resource kind, the CRDs and the related +controller must exist in the cluster. + +For example, assuming we have two Kustomizations: + +- cert-manager: reconciles the cert-manager CRDs and controller +- certs: reconciles the cert-manager custom resources + +You can instruct the controller to apply the `cert-manager` Kustomization before +`certs` by defining a `dependsOn` relationship between the two: + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cert-manager + namespace: flux-system +spec: + interval: 5m + path: "./cert-manager/controller" + prune: true + sourceRef: + kind: GitRepository + name: flux-system + healthChecks: + - apiVersion: apps/v1 + kind: Deployment + name: cert-manager + namespace: cert-manager +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: certs + namespace: flux-system +spec: + dependsOn: + - name: cert-manager + interval: 5m + path: "./cert-manager/certs" + prune: true + sourceRef: + kind: GitRepository + name: flux-system +``` + +If `.spec.healthChecks` is non-empty or `.spec.wait` is set to `true`, a +Kustomization will be applied after all its dependencies' health checks have +passed. For example, this can be used to ensure a service mesh proxy injector +is running before deploying applications inside the mesh. + +**Note:** Circular dependencies between Kustomizations must be avoided, +otherwise the interdependent Kustomizations will never be applied on the cluster. + +### Service Account reference + +`.spec.serviceAccountName` is an optional field used to specify the +ServiceAccount to be impersonated while reconciling the Kustomization. For more +details, see [Role-based Access Control](#role-based-access-control). + +### Common metadata + +`.spec.commonMetadata` is an optional field used to specify any metadata that +should be applied to all the Kustomization's resources. It has two optional fields: + +- `labels`: A map used for setting [labels](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) + on an object. Any existing label will be overridden if it matches with a key in + this map. +- `annotations`: A map used for setting [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) + on an object. Any existing annotation will be overridden if it matches with a key + in this map. + +### Patches + +`.spec.patches` is an optional list used to specify [Kustomize `patches`](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/) +as inline YAML objects. This enables patching resources using either a +[strategic merge](https://kubectl.docs.kubernetes.io/references/kustomize/glossary#patchstrategicmerge) +patch or a [JSON6902](https://kubectl.docs.kubernetes.io/references/kustomize/glossary#patchjson6902) +patch. A patch can target a single resource or multiple resources. Each item in +the list must have the two fields mentioned below: + +- `patch`: Patch contains an inline strategic merge patch or an inline JSON6902 patch with an array of operation objects. +- `target`: Target points to the resources that the patch document should be applied to. + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: podinfo + namespace: flux-system +spec: + # ...omitted for brevity + patches: + - patch: |- + apiVersion: apps/v1 + kind: Deployment + metadata: + name: not-used + spec: + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "true" + target: + kind: Deployment + labelSelector: "app.kubernetes.io/part-of=my-app" + - patch: | + - op: add + path: /spec/template/spec/securityContext + value: + runAsUser: 10000 + fsGroup: 1337 + - op: add + path: /spec/template/spec/containers/0/securityContext + value: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + runAsNonRoot: true + capabilities: + drop: + - ALL + target: + kind: Deployment + name: podinfo + namespace: apps +``` + +### Images + +`.spec.images` is an optional list used to specify +[Kustomize `images`](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/images/). +This allows overwriting the name, tag or digest of container images without creating patches. + +```yaml +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: podinfo + namespace: flux-system +spec: + # ...omitted for brevity + images: + - name: podinfo + newName: my-registry/podinfo + newTag: v1 + - name: podinfo + newTag: 1.8.0 + - name: podinfo + newName: my-podinfo + - name: podinfo + digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3 +``` + +### Components + +`.spec.components` is an optional list used to specify +[Kustomize `components`](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/components/). +This allows using reusable pieces of configuration logic that can be included +from multiple overlays. + +```yaml +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: podinfo + namespace: flux-system +spec: + # ...omitted for brevity + components: + - ingress + - tls +``` + +**Note:** The component paths must be local and relative to the source root. + +**Warning:** Components are an alpha feature in Kustomize and are therefore +considered experimental in Flux. No guarantees are provided as the feature may +be modified in backwards incompatible ways or removed without warning. + +### Post build variable substitution + +With `.spec.postBuild.substitute` you can provide a map of key-value pairs +holding the variables to be substituted in the final YAML manifest, after +kustomize build. + +With `.spec.postBuild.substituteFrom` you can provide a list of ConfigMaps and +Secrets from which the variables are loaded. The ConfigMap and Secret data keys +are used as the variable names. + +The `.spec.postBuild.substituteFrom.optional` field indicates how the +controller should handle a referenced ConfigMap or Secret being absent +at reconciliation time. The controller's default behavior ― with +`optional` unspecified or set to `false` ― it has failed reconciliation if +the referenced object is missing. By setting the `optional` field to +`true`, you can indicate that the controller should use the referenced +object if it's there, but also tolerate its absence, treating that +absence as if the object had been present but empty, defining no +variables. + +This offers basic templating for your manifests including support +for [bash string replacement functions](https://github.com/drone/envsubst) e.g.: + +- `${var:=default}` +- `${var:position}` +- `${var:position:length}` +- `${var/substring/replacement}` + +**Note:** The name of a variable can contain only alphanumeric and underscore +characters. The controller validates the variable names using this regular +expression: `^[_[:alpha:]][_[:alpha:][:digit:]]*$`. + +For example, assuming we have manifests with the following variables: + +```yaml +--- +apiVersion: v1 +kind: Namespace +metadata: + name: apps + labels: + environment: ${cluster_env:=dev} + region: "${cluster_region}" +``` + +You can specify the variables and their values in the Kustomization definition using +`.spec.postBuild.substitute` and/or `.spec.postBuild.substituteFrom`: + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: apps +spec: + interval: 5m + path: "./apps/" + postBuild: + substitute: + cluster_env: "prod" + cluster_region: "eu-central-1" + substituteFrom: + - kind: ConfigMap + name: cluster-vars + # Use this ConfigMap if it exists, but proceed if it doesn't. + optional: true + - kind: Secret + name: cluster-secret-vars + # Fail if this Secret does not exist. +``` + +**Note:** For substituting variables in a secret, `.spec.stringData` field must be used i.e: + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: secret + namespace: flux-system +type: Opaque +stringData: + token: ${token} +``` + +The var values which are specified in-line with `substitute` +take precedence over the ones derived from `substituteFrom`. + +**Note:** If you want to avoid var substitutions in scripts embedded in +ConfigMaps or container commands, you must use the format `$var` instead of +`${var}`. If you want to keep the curly braces you can use `$${var}` which +will print out `${var}`. + +All the undefined variables in the format `${var}` will be substituted with an +empty string unless a default value is provided e.g. `${var:=default}`. + +You can disable the variable substitution for certain resources by either +labelling or annotating them with: + +```yaml +kustomize.toolkit.fluxcd.io/substitute: disabled +``` + +Substitution of variables only happens if at least a single variable or resource +to substitute from is defined. This may cause issues if you rely on expressions +which should evaluate to a default value, even if no other variables are +configured. To work around this, one can set an arbitrary key/value pair to +enable the substitution of variables. For example: + +```yaml +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: apps +spec: + ... + postBuild: + substitute: + var_substitution_enabled: "true" +``` + +You can replicate the controller post-build substitutions locally using +[kustomize](https://github.com/kubernetes-sigs/kustomize) +and Drone's [envsubst](https://github.com/drone/envsubst): + +```console +$ go install github.com/drone/envsubst/cmd/envsubst + +$ export cluster_region=eu-central-1 +$ kustomize build ./apps/ | $GOPATH/bin/envsubst +--- +apiVersion: v1 +kind: Namespace +metadata: + name: apps + labels: + environment: dev + region: eu-central-1 +``` + +### Force + +`.spec.force` is an optional boolean field. If set to `true`, the controller +will replace the resources in-cluster if the patching fails due to immutable +field changes. + +It can also be enabled for specific resources by labelling or annotating them +with: + +```yaml +kustomize.toolkit.fluxcd.io/force: enabled +``` + +### KubeConfig reference + +`.spec.kubeConfig.secretRef.Name` is an optional field to specify the name of +the secret containing a KubeConfig. If specified, objects will be applied, +health-checked, pruned, and deleted for the default cluster specified in that +KubeConfig instead of using the in-cluster ServiceAccount. + +The secret defined in the `kubeConfig.SecretRef` must exist in the same +namespace as the Kustomization. On every reconciliation, the KubeConfig bytes +will be loaded from the `.secretRef.key` key (default: `value` or `value.yaml`) +of the Secret’s data , and the Secret can thus be regularly updated if +cluster-access-tokens have to rotate due to expiration. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: prod-kubeconfig +type: Opaque +stringData: + value.yaml: | + apiVersion: v1 + kind: Config + # ...omitted for brevity +``` + +**Note:** The KubeConfig should be self-contained and not rely on binaries, +environment, or credential files from the kustomize-controller Pod. +This matches the constraints of KubeConfigs from current Cluster API providers. +KubeConfigs with `cmd-path` in them likely won't work without a custom, +per-provider installation of kustomize-controller. + +When both `.spec.kubeConfig` and `.spec.ServiceAccountName` are specified, +the controller will impersonate the service account on the target cluster. + +For more information, see [remote clusters/Cluster-API](#remote-clusterscluster-api). + +### Decryption + +`.spec.decryption` is an optional field to specify the configuration to decrypt +Secrets that are a part of the Kustomization. + +Since Secrets are either plain text or `base64` encoded, it's unsafe to store +them in plain text in a public or private Git repository. In order to store +them safely, you can use [Mozilla SOPS](https://github.com/mozilla/sops) and +encrypt your Kubernetes Secret data with [age](https://age-encryption.org/v1/) +and/or [OpenPGP](https://www.openpgp.org) keys, or with provider implementations +like Azure Key Vault, GCP KMS or Hashicorp Vault. + +**Note:** You should encrypt only the `data/stringData` section of the Kubernetes +Secret, encrypting the `metadata`, `kind` or `apiVersion` fields is not supported. +An easy way to do this is by appending `--encrypted-regex '^(data|stringData)$'` +to your `sops --encrypt` command. + +It has two required fields: + +- `.secretRef.name`: The name of the secret that contains the keys to be used for + decryption. +- `.provider`: The secrets decryption provider to be used. The only supported + value at the moment is `sops`. + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: sops-encrypted + namespace: default +spec: + interval: 5m + path: "./" + sourceRef: + kind: GitRepository + name: repository-with-secrets + decryption: + provider: sops + secretRef: + name: sops-keys +``` + +**Note:** For information on Secrets decryption at a controller level, please +refer to [controller global decryption](#controller-global-decryption). + +The Secret's `.data` section is expected to contain entries with decryption +keys (for age and OpenPGP), or credentials (for any of the supported provider +implementations). The controller identifies the type of the entry by the suffix +of the key (e.g. `.agekey`), or a fixed key (e.g. `sops.vault-token`). + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +data: + # Exemplary age private key + identity.agekey: + # Exemplary Hashicorp Vault token + sops.vault-token: +``` + +#### age Secret entry + +To specify an age private key in a Kubernetes Secret, suffix the key of the +`.data` entry with `.agekey`. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +data: + # Exemplary age private key + identity.agekey: +``` + +#### OpenPGP Secret entry + +To specify an OpenPGP (passwordless) keyring in armor format in a Kubernetes +Secret, suffix the key of the `.data` entry with `.asc`. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +data: + # Exemplary OpenPGP keyring + identity.asc: +``` + +#### AWS KMS Secret entry + +To specify credentials for an AWS user account linked to the IAM role with access +to KMS, append a `.data` entry with a fixed `sops.aws-kms` key. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +data: + sops.aws-kms: | + aws_access_key_id: some-access-key-id + aws_secret_access_key: some-aws-secret-access-key + aws_session_token: some-aws-session-token # this field is optional +``` + +#### Azure Key Vault Secret entry + +To specify credentials for Azure Key Vault in a Secret, append a `.data` entry +with a fixed `sops.azure-kv` key. The value can contain a variety of JSON or +YAML formats depending on the authentication method you want to utilize. + +##### Service Principal with Secret + +To configure a Service Principal with Secret credentials to access the Azure +Key Vault, a JSON or YAML object with `tenantId`, `clientId` and `clientSecret` +fields must be configured as the `sops.azure-kv` value. It optionally supports +`authorityHost` to configure an authority host other than the Azure Public Cloud +endpoint. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +stringData: + # Exemplary Azure Service Principal with Secret + sops.azure-kv: | + tenantId: some-tenant-id + clientId: some-client-id + clientSecret: some-client-secret +``` + +##### Service Principal with Certificate + +To configure a Service Principal with Certificate credentials to access the +Azure Key Vault, a JSON or YAML object with `tenantId`, `clientId` and +`clientCertificate` fields must be configured as the `sops.azure-kv` value. +It optionally supports `clientCertificateSendChain` and `authorityHost` to +control the sending of the certificate chain, or to specify an authority host +other than the Azure Public Cloud endpoint. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +stringData: + # Exemplary Azure Service Principal with Certificate + sops.azure-kv: | + tenantId: some-tenant-id + clientId: some-client-id + clientCertificate: +``` + +##### `az` generated Service Principal + +To configure a Service Principal [generated using +`az`](https://docs.microsoft.com/en-us/azure/aks/kubernetes-service-principal?tabs=azure-cli#manually-create-a-service-principal), +the output of the command can be directly used as a `sops.azure-kv` value. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +stringData: + # Exemplary Azure Service Principal generated with `az` + sops.azure-kv: | + { + "appId": "559513bd-0c19-4c1a-87cd-851a26afd5fc", + "displayName": "myAKSClusterServicePrincipal", + "name": "http://myAKSClusterServicePrincipal", + "password": "e763725a-5eee-40e8-a466-dc88d980f415", + "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db48" + } +``` + +##### Managed Identity with Client ID + +To configure a Managed Identity making use of a Client ID, a JSON or YAML +object with a `clientId` must be configured as the `sops.azure-kv` value. It +optionally supports `authorityHost` to configure an authority host other than +the Azure Public Cloud endpoint. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +stringData: + # Exemplary Azure Managed Identity with Client ID + sops.azure-kv: | + clientId: some-client-id +``` + +#### GCP KMS Secret entry + +To specify credentials for GCP KMS in a Kubernetes Secret, append a `.data` +entry with a fixed `sops.gcp-kms` key and the service account keys as its value. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +stringData: + # Exemplary GCP Service Account credentials file + sops.gcp-kms: | + { + "type": "service_account", + "project_id": "", + "private_key_id": "", + "private_key": "" + } +``` + +#### Hashicorp Vault Secret entry + +To specify credentials for Hashicorp Vault in a Kubernetes Secret, append a +`.data` entry with a fixed `sops.vault-token` key and the token as value. + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: sops-keys + namespace: default +data: + # Exemplary Hashicorp Vault Secret token + sops.vault-token: +``` + +## Working with Kustomizations + +### Recommended settings + +When deploying applications to production environments, it is recommended +to configure the following fields, while adjusting them to your desires for +responsiveness: + +```yaml +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: webapp + namespace: apps +spec: + interval: 1m0s # check for new commits every minute and apply changes + url: https://github.com/org/webapp # clone over HTTPS + secretRef: # use token auth + name: webapp-git-token # Flux user PAT (read-only access) + ref: + branch: main + ignore: | + # exclude all + /* + # include deploy dir + !/deploy +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: webapp + namespace: apps +spec: + interval: 60m0s # detect drift and undo kubectl edits every hour + wait: true # wait for all applied resources to become ready + timeout: 3m0s # give up waiting after three minutes + retryInterval: 2m0s # retry every two minutes on apply or waiting failures + prune: true # remove stale resources from cluster + force: false # enable this to recreate resources on immutable fields changes + targetNamespace: apps # set the namespace for all resources + sourceRef: + kind: GitRepository + name: webapp + namespace: apps + path: "./deploy/production" +``` + +### Generating a `kustomization.yaml` file + +If your repository contains plain Kubernetes manifests without a +`kustomization.yaml`, the file is automatically generated for all the +Kubernetes manifests in the directory tree specified in [`.spec.path`](#path). + +All YAML files present under that path must be valid Kubernetes manifests, +unless they're excluded either by way of the [`.sourceignore`](https://fluxcd.io/flux/components/source/gitrepositories/#sourceignore-file) +file or the [`.spec.ignore`](https://fluxcd.io/flux/components/source/gitrepositories/#ignore) +field on the corresponding Source object. + +Example of excluding CI workflows and SOPS config files: + +```yaml +apiVersion: source.toolkit.fluxcd.io/v1 +kind: GitRepository +metadata: + name: podinfo + namespace: default +spec: + interval: 5m + url: https://github.com/stefanprodan/podinfo + ignore: | + .github/ + .sops.yaml + .gitlab-ci.yml +``` + +It is recommended to generate the `kustomization.yaml` on your own and store it +in Git, this way you can validate your manifests in CI +([example script](https://github.com/fluxcd/flux2-multi-tenancy/blob/main/scripts/validate.sh)). +Assuming your manifests are inside `apps/my-app`, you can generate a +`kustomization.yaml` with: + +```sh +cd apps/my-app + +# create kustomization.yaml +kustomize create --autodetect --recursive +``` + +### Role-based access control + +By default, a Kustomization apply runs under the cluster admin account and can +create, modify and delete cluster level objects (namespaces, CRDs, etc) and +namespaced objects (deployments, ingresses, etc). For certain Kustomizations a +cluster admin may wish to control what types of Kubernetes objects can be +reconciled and under which namespaces. +To restrict a Kustomization, one can assign a service account under which the +reconciliation is performed using [`.spec.serviceAccountName`](#service-account-reference). + +Assuming you want to restrict a group of Kustomizations to a single namespace, +you can create an account with a role binding that grants access only to that namespace: + +```yaml +--- +apiVersion: v1 +kind: Namespace +metadata: + name: webapp +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: flux + namespace: webapp +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: webapp-reconciler + namespace: webapp +rules: + - apiGroups: ['*'] + resources: ['*'] + verbs: ['*'] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: webapp-reconciler + namespace: webapp +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: webapp-reconciler +subjects: +- kind: ServiceAccount + name: flux + namespace: webapp +``` + +**Note:** The namespace, RBAC and service account manifests should be +placed in a Git source and applied with a Kustomization. The Kustomizations that +are running under that service account should depend on the one that contains the account. + +Create a Kustomization that prevents altering the cluster state outside the +`webapp` namespace: + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: backend + namespace: webapp +spec: + serviceAccountName: flux + dependsOn: + - name: rbac + interval: 5m + path: "./webapp/backend/" + prune: true + sourceRef: + kind: GitRepository + name: webapp +``` + +When the controller reconciles the `backend` Kustomization, it will impersonate +the `flux` ServiceAccount. If the Kustomization contains cluster level objects +like CRDs or objects belonging to a different namespace, the reconciliation will +fail since the account it runs under has no permissions to alter objects outside +the `webapp` namespace. + +#### Enforcing impersonation + +On multi-tenant clusters, platform admins can enforce impersonation with the +`--default-service-account` flag. + +When the flag is set, all Kustomizations which don't have [`.spec.serviceAccountName`](#service-account-reference) +specified will use the service account name provided by +`--default-service-account=` in the namespace of the object. + +### Remote clusters/Cluster-API + +With the [`.spec.kubeConfig` field](#kubeconfig-reference) a Kustomization can be fully +reconciled on a remote cluster. This composes well with Cluster API bootstrap +providers such as CAPBK (kubeadm), CAPA (AWS) and others. + +To reconcile a Kustomization to a CAPI controlled cluster, put the +`Kustomization` in the same namespace as your `Cluster` object, and set the +`kubeConfig.secretRef.name` to `-kubeconfig`: + +```yaml +apiVersion: cluster.x-k8s.io/v1alpha3 +kind: Cluster +metadata: + name: stage # the kubeconfig Secret will contain the Cluster name + namespace: capi-stage +spec: + clusterNetwork: + pods: + cidrBlocks: + - 10.100.0.0/16 + serviceDomain: stage-cluster.local + services: + cidrBlocks: + - 10.200.0.0/12 + controlPlaneRef: + apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 + kind: KubeadmControlPlane + name: stage-control-plane + namespace: capi-stage + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: DockerCluster + name: stage + namespace: capi-stage +--- +# ... unrelated Cluster API objects omitted for brevity ... +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cluster-addons + namespace: capi-stage +spec: + interval: 5m + path: "./config/addons/" + prune: true + sourceRef: + kind: GitRepository + name: cluster-addons + kubeConfig: + secretRef: + name: stage-kubeconfig # Cluster API creates this for the matching Cluster +``` + +The Cluster and Kustomization can be created at the same time. +The Kustomization will eventually reconcile once the cluster is available. + +If you wish to target clusters created by other means than CAPI, you can create +a ServiceAccount on the remote cluster, generate a KubeConfig for that account +and then create a secret on the cluster where kustomize-controller is running. +For example: + +```sh +kubectl create secret generic prod-kubeconfig \ + --from-file=value.yaml=./kubeconfig +``` + +### Controller global decryption + +Other than [authentication using a Secret reference](#decryption), +it is possible to specify global decryption settings on the +kustomize-controller Pod. When the controller fails to find credentials on the +Kustomization object itself, it will fall back to these defaults. + +#### AWS KMS + +While making use of the [IAM OIDC provider](https://eksctl.io/usage/iamserviceaccounts/) +on your EKS cluster, you can create an IAM Role and Service Account with access +to AWS KMS (using at least `kms:Decrypt` and `kms:DescribeKey`). Once these are +created, you can annotate the kustomize-controller Service Account with the +Role ARN, granting the controller permission to decrypt the Secrets. Please refer +to the [SOPS guide](https://fluxcd.io/flux/guides/mozilla-sops/#aws) for detailed steps. + +```sh +kubectl -n flux-system annotate serviceaccount kustomize-controller \ + --field-manager=flux-client-side-apply \ + eks.amazonaws.com/role-arn='arn:aws:iam:::role/' +``` + +Furthermore, you can also use the usual [environment variables used for specifying AWS +credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html#envvars-list), +by patching the kustomize-controller Deployment: + +```yaml +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kustomize-controller + namespace: flux-system +spec: + template: + spec: + containers: + - name: manager + env: + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: aws-creds + key: awsAccessKeyID + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: aws-creds + key: awsSecretAccessKey + - name: AWS_SESSION_TOKEN + valueFrom: + secretKeyRef: + name: aws-creds + key: awsSessionToken +``` + +In addition to this, the +[general SOPS documentation around KMS AWS applies](https://github.com/mozilla/sops#27kms-aws-profiles), +allowing you to specify e.g. a `SOPS_KMS_ARN` environment variable. + +**Note:**: If you are mounting a secret containing the AWS credentials as a +file in the `kustomize-controller` Pod, you need to specify an environment +variable `$HOME`, since the AWS credentials file is expected to be present at +`~/.aws`. For example: + +```yaml +env: + - name: HOME + value: /home/{$USER} +``` + +#### Azure Key Vault + +While making use of [AAD Pod Identity](https://github.com/Azure/aad-pod-identity), +you can bind a Managed Identity to Flux's kustomize-controller. Once the +`AzureIdentity` and `AzureIdentityBinding` for this are created, you can patch +the controller's Deployment with the `aadpodidbinding` label set to the +selector of the binding, and the `AZURE_AUTH_METHOD` environment variable set +to `msi`. + +```yaml +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kustomize-controller + namespace: flux-system +spec: + template: + metadata: + labels: + aadpodidbinding: sops-akv-decryptor # match the AzureIdentityBinding selector + spec: + containers: + - name: manager + env: + - name: AZURE_AUTH_METHOD + value: msi +``` + +In addition to this, the [default SOPS Azure Key Vault flow is +followed](https://github.com/mozilla/sops#encrypting-using-azure-key-vault), +allowing you to specify a variety of other environment variables. + +#### GCP KMS + +While making use of Google Cloud Platform, the [`GOOGLE_APPLICATION_CREDENTIALS` +environment variable](https://cloud.google.com/docs/authentication/production) +is automatically taken into account. +[Granting permissions](https://cloud.google.com/kms/docs/reference/permissions-and-roles) +to the Service Account attached to this will therefore be sufficient to decrypt +data. When running outside GCP, it is possible to manually patch the +kustomize-controller Deployment with a valid set of (mounted) credentials. + +```yaml +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kustomize-controller + namespace: flux-system +spec: + template: + spec: + containers: + - name: manager + env: + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /var/gcp/credentials.json + volumeMounts: + - name: gcp-credentials + mountPath: /var/gcp/ + readOnly: true + volumes: + - name: gcp-credentials + secret: + secretName: mysecret + items: + - key: credentials + path: credentials.json +``` + +#### Hashicorp Vault + +To configure a global default for Hashicorp Vault, patch the controller's +Deployment with a `VAULT_TOKEN` environment variable. + +```yaml +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kustomize-controller + namespace: flux-system +spec: + template: + spec: + containers: + - name: manager + env: + - name: VAULT_TOKEN + value: +``` + +### Kustomize secretGenerator + +SOPS encrypted data can be stored as a base64 encoded Secret, which enables the +use of [Kustomize `secretGenerator`](https://github.com/kubernetes-sigs/kustomize/tree/main/examples/secretGeneratorPlugin.md) +as follows: + +```console +$ echo "my-secret-token" | sops -e /dev/stdin > token.encrypted +$ cat < kustomization.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +secretGenerator: + - name: token + files: + - token=token.encrypted +EOF +``` + +Commit and push `token.encrypted` and `kustomization.yaml` to Git. + +The kustomize-controller scans the values of Kubernetes Secrets, and when it +detects that the values are SOPS encrypted, it decrypts them before applying +them on the cluster. + +For secrets in `.json`, `.yaml` `.ini` and `.env` format, make sure you specify +the input type when encrypting them with SOPS: + +```sh +sops -e --input-type=json config.json > config.json.encrypted +sops -e --input-type=yaml config.yaml > config.yaml.encrypted +sops -e --input-type=env config.env > config.env.encrypted +``` + +For kustomize-controller to be able to decrypt a JSON config, you need to set +the file extension to `.json`: + +```yaml +kind: Kustomization +secretGenerator: + - name: config + files: + - config.json=config.json.encrypted +``` + +For dotenv files, use the `envs` directive: + +```yaml +kind: Kustomization +secretGenerator: + - name: config + envs: + - config.env.encrypted +``` + +For Docker config files, you need to specify both input and output type as JSON: + +```sh +sops -e --input-type=json --output-type=json ghcr.dockerconfigjson > ghcr.dockerconfigjson.encrypted +``` + +To generate an image pull secret, use the `.dockerconfigjson` as the secret key: + +```yaml +kind: Kustomization +secretGenerator: + - name: ghcr-auth + type: kubernetes.io/dockerconfigjson + files: + - .dockerconfigjson=ghcr.dockerconfigjson.encrypted +``` + +### Triggering a reconcile + +To manually tell the kustomize-controller to reconcile a Kustomization outside +the [specified interval window](#interval), it can be annotated with +`reconcile.fluxcd.io/requestedAt: `. Annotating the resource +queues the Kustomization for reconciliation if the `` differs +from the last value the controller acted on, as reported in +[`.status.lastHandledReconcileAt`](#last-handled-reconcile-at). + +Using `kubectl`: + +```sh +kubectl annotate --field-manager=flux-client-side-apply --overwrite kustomization/ reconcile.fluxcd.io/requestedAt="$(date +%s)" +``` + +Using `flux`: + +```sh +flux reconcile kustomization +``` + +### Customizing reconciliation + +You can configure the controller to ignore in-cluster resources by labelling or +annotating them with: + +```yaml +kustomize.toolkit.fluxcd.io/reconcile: disabled +``` + +**Note:** When the `kustomize.toolkit.fluxcd.io/reconcile` annotation is set to +`disabled`, the controller will no longer apply changes from the source, nor +will it prune the resource. To resume reconciliation, set the annotation to +`enabled` in the source or remove it from the in-cluster object. + +If you use `kubectl` to edit an object managed by Flux, all changes will be +reverted when the controller reconciles a Flux Kustomization containing that +object. In order to preserve fields added with `kubectl`, you have to specify +a field manager named `flux-client-side-apply` e.g.: + +```sh +kubectl apply --field-manager=flux-client-side-apply +``` + +Another option is to annotate or label objects with: + +```yaml +kustomize.toolkit.fluxcd.io/ssa: merge +``` + +**Note:** The fields defined in manifests will always be overridden, the above +procedure works only for adding new fields that don’t overlap with the desired +state. + +For lists fields which are atomic (e.g. `.spec.tolerations` in PodSpec), Kubernetes +doesn't allow different managers for such fields, therefore any changes to these +fields will be undone, even if you specify a manager. For more context, please +see the Kubernetes enhancement document: +[555-server-side-apply](https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/555-server-side-apply/README.md#lists). + +To learn how to handle patching failures due to immutable field changes, refer +to [`.spec.force`](#force). + +### Waiting for `Ready` + +When a change is applied, it is possible to wait for the Kustomization to reach +a `Ready` state using `kubectl`: + +```sh +kubectl wait kustomization/ --for=condition=ready --timeout=1m +``` + +### Suspending and resuming + +When you find yourself in a situation where you temporarily want to pause the +reconciliation of a Kustomization, you can suspend it using [`.spec.suspend`](#suspend). + +#### Suspend a Kustomization + +In your YAML declaration: + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: +spec: + suspend: true +``` + +Using `kubectl`: + +```sh +kubectl patch kustomization --field-manager=flux-client-side-apply -p '{\"spec\": {\"suspend\" : true }}' +``` + +Using `flux`: + +```sh +flux suspend kustomization +``` + +#### Resume a Kustomization + +In your YAML declaration, comment out (or remove) the field: + +```yaml +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: +spec: + # suspend: true +``` + +**Note:** Setting the field value to `false` has the same effect as removing +it, but does not allow for "hot patching" using e.g. `kubectl` while practicing +GitOps; as the manually applied patch would be overwritten by the declared +state in Git. + +Using `kubectl`: + +```sh +kubectl patch kustomization --field-manager=flux-client-side-apply -p '{\"spec\" : {\"suspend\" : false }}' +``` + +Using `flux`: + +```sh +flux resume kustomization +``` + +### Debugging a Kustomization + +There are several ways to gather information about a Kustomization for +debugging purposes. + +#### Describe the Kustomization + +Describing a Kustomization using +`kubectl describe kustomization ` +displays the latest recorded information for the resource in the `Status` and +`Events` sections: + +```console +... +Status: +... + Conditions: + Last Transition Time: 2023-03-29T06:09:32Z + Message: Fetching manifests for revision master/67e2c98a60dc92283531412a9e604dd4bae005a9 with a timeout of 4m30s + Observed Generation: 3 + Reason: ProgressingWithRetry + Status: True + Type: Reconciling + Last Transition Time: 2023-03-29T06:09:32Z + Message: kustomization path not found: stat /tmp/kustomization-1464362706/invalid: no such file or directory + Observed Generation: 3 + Reason: ArtifactFailed + Status: False + Type: Ready + Last Applied Revision: master/67e2c98a60dc92283531412a9e604dd4bae005a9 + Last Attempted Revision: master/67e2c98a60dc92283531412a9e604dd4bae005a9 + Observed Generation: 2 +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Warning ArtifactFailed 2s kustomize-controller kustomization path not found: stat /tmp/kustomization-1464362706/invalid: no such file or directory + +``` + +#### Trace emitted Events + +To view events for specific Kustomization(s), `kubectl events` can be used +to list the Events for specific objects. For example, running + +```sh +kubectl events -n flux-system --for kustomization/podinfo +``` + +lists + +```console +LAST SEEN TYPE REASON OBJECT MESSAGE +31s Warning ArtifactFailed kustomization/podinfo kustomization path not found: stat /tmp/kustomization-3011588360/invalid: no such file or directory +26s Normal ArtifactFailed kustomization/podinfo HorizontalPodAutoscaler/default/podinfo deleted... +18s Warning ArtifactFailed kustomization/podinfo kustomization path not found: stat /tmp/kustomization-3336282420/invalid: no such file or directory +9s Normal Progressing kustomization/podinfo Service/default/podinfo created... +9s Normal ReconciliationSucceeded kustomization/podinfo Reconciliation finished in 75.190237ms, next run in 5m0s +``` + +You can also use the `flux events` command to view all events for a +Kustomization and its related Source. For example, + +```sh +flux events --for Kustomization/podinfo +``` + +will list all events for the `podinfo` Kustomization in the `flux-system` +namespace and its related Source object, the `podinfo` GitRepository. + +```console +LAST SEEN TYPE REASON OBJECT MESSAGE +3m2s Warning ArtifactFailed Kustomization/podinfo kustomization path not found: stat /tmp/kustomization-3336282420/invalid: no such file or directory + +2m53s Normal ReconciliationSucceeded Kustomization/podinfo Reconciliation finished in 75.190237ms, next run in 5m0s + +2m53s Normal Progressing Kustomization/podinfo Service/default/podinfo created + Deployment/default/podinfo created + HorizontalPodAutoscaler/default/podinfo created + +19s (x17 over 8m24s) Normal GitOperationSucceeded GitRepository/podinfo no changes since last reconcilation: observed revision 'master/67e2c98a60dc92283531412a9e604dd4bae005a9' +``` + +Besides being reported in Events, the reconciliation errors are also logged by +the controller. The Flux CLI offer commands for filtering the logs for a +specific Kustomization, e.g. +`flux logs --level=error --kind=Kustomization --name=`. + +## Kustomization Status + +### Conditions + +A Kustomization enters various states during its lifecycle, reflected as +[Kubernetes Conditions][typical-status-properties]. +It can be [reconciling](#reconciling-kustomization) while applying the Kustomization on the cluster, it can be [ready](#ready-kustomization), or it can [fail during +reconciliation](#failed-kustomization). + +The Kustomization API is compatible with the [kstatus specification][kstatus-spec], +and reports `Reconciling` and `Stalled` conditions where applicable to +provide better (timeout) support to solutions polling the Kustomization to +become `Ready`. + +#### Reconciling Kustomization + +The kustomize-controller marks a Kustomization as _reconciling_ when it starts +the reconciliation of the same. The Condition added to the Kustomization's +`.status.conditions` has the following attributes: + +- `type: Reconciling` +- `status: "True"` +- `reason: Progressing` | `reason: ProgressingWithRetry` + +The Condition `message` is updated during the course of the reconciliation to +report the action being performed at any particular moment such as +building manifests, detecting drift, etc. + +The `Ready` Condition's `status` is also marked as `Unkown`. + +#### Ready Kustomization + +The kustomize-controller marks a Kustomization as _ready_ when a Kustomization +is successfully reconciled, i.e. the source was fetched, the kustomization was +built and applied on the cluster and all health checks are observed to be passing. + +When the Kustomization is "ready", the controller sets a Condition with the +following attributes in the Kustomization’s `.status.conditions`: + +- `type: Ready` +- `status: "True"` +- `reason: ReconciliationSucceeded` + +#### Failed Kustomization + +The kustomize-controller may get stuck trying to reconcile and apply a +Kustomization without completing. This can occur due to some of the following factors: + +- The Source object does not exist on the cluster. +- The Source has not produced an Artifact yet. +- The Kustomization's dependencies aren't ready yet. +- The specified path does not exist in the Artifact. +- Building the kustomization fails. +- Garbage collection fails. +- Running a health check failed. + +When this happens, the controller sets the `Ready` Condition status to False +and adds a Condition with the following attributes to the Kustomization’s +`.status.conditions`: + +- `type: Ready | HealthyCondition` +- `status: "False"` +- `reason: PruneFailed | ArtifactFailed | BuildFailed | HealthCheckFailed | DependencyNotReady | ReconciliationFailed ` + +The `message` field of the Condition will contain more information about why +the reconciliation failed. + +While the Kustomization has one or more of these Conditions, the controller +will continue to attempt a reconciliation of the Kustomization with an +exponential backoff, until it succeeds and the Kustomization marked as [ready](#ready-kustomization). + +Note that a Kustomization can be [reconciling](#reconciling-kustomization) +while failing at the same time, for example, due to a newly introduced +configuration issue in the Kustomization spec. When a reconciliation fails, the +`Reconciling` Condition `reason` would be `ProgressingWithRetry`. When the +reconciliation is performed again after the failure, the `reason` is updated to `Progressing`. + +### Inventory + +In order to perform operations such as drift detection, garbage collection, etc. +kustomize-controller needs to keep track of all Kubernetes objects that are +reconciled as part of a Kustomization. To do this, it maintains an inventory +containing the list of Kubernetes resource object references that have been +successfully applied and records it in `.status.inventory`. The inventory +records are in the format `____`. + +```console +Status: + Inventory: + Entries: + Id: default_podinfo__Service + V: v1 + Id: default_podinfo_apps_Deployment + V: v1 + Id: default_podinfo_autoscaling_HorizontalPodAutoscaler + V: v2 +``` + +### Last applied revision + +`.status.lastAppliedRevision` is the last revision of the Artifact from the +referred Source object that was successfully applied to the cluster. + +### Last attempted revision + +`.status.lastAttemptedRevision` is the last revision of the Artifact from the +referred Source object that was attempted to be applied to the cluster. + +### Observed Generation + +The kustomize-controller reports an [observed generation][typical-status-properties] +in the Kustomization's `.status.observedGeneration`. The observed generation is +the latest `.metadata.generation` which resulted in either a [ready state](#ready-kustomization), +or stalled due to an error it can not recover from without human +intervention. + +### Last Handled Reconcile At + +The kustomize-controller reports the last `reconcile.fluxcd.io/requestedAt` +annotation value it acted on in the `.status.lastHandledReconcileAt` field. + +For practical information about this field, see [triggering a reconcile](#triggering-a-reconcile). + +[typical-status-properties]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties +[kstatus-spec]: https://github.com/kubernetes-sigs/cli-utils/tree/master/pkg/kstatus diff --git a/go.mod b/go.mod index 7208b391..ed93e285 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/fluxcd/pkg/ssa v0.27.0 github.com/fluxcd/pkg/tar v0.2.0 github.com/fluxcd/pkg/testserver v0.4.0 - github.com/fluxcd/source-controller/api v0.36.1 + github.com/fluxcd/source-controller/api v1.0.0-rc.1 github.com/hashicorp/vault/api v1.9.0 github.com/onsi/gomega v1.27.5 github.com/opencontainers/go-digest v1.0.0 @@ -47,7 +47,6 @@ require ( google.golang.org/grpc v1.54.0 google.golang.org/protobuf v1.30.0 k8s.io/api v0.26.3 - k8s.io/apiextensions-apiserver v0.26.3 k8s.io/apimachinery v0.26.3 k8s.io/client-go v0.26.3 sigs.k8s.io/cli-utils v0.34.0 @@ -205,6 +204,7 @@ require ( gopkg.in/urfave/cli.v1 v1.20.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.26.3 // indirect k8s.io/cli-runtime v0.25.4 // indirect k8s.io/component-base v0.26.3 // indirect k8s.io/klog/v2 v2.90.1 // indirect diff --git a/go.sum b/go.sum index 3663f087..a4411267 100644 --- a/go.sum +++ b/go.sum @@ -232,8 +232,8 @@ github.com/fluxcd/pkg/tar v0.2.0 h1:HEUHgONQYsJGeZZ4x6h5nQU9Aox1I4T3bOp1faWTqf8= github.com/fluxcd/pkg/tar v0.2.0/go.mod h1:w0/TOC7kwBJhnSJn7TCABkc/I7ib1f2Yz6vOsbLBnhw= github.com/fluxcd/pkg/testserver v0.4.0 h1:pDZ3gistqYhwlf3sAjn1Q8NzN4Qe6I1BEmHMHi46lMg= github.com/fluxcd/pkg/testserver v0.4.0/go.mod h1:gjOKX41okmrGYOa4oOF2fiLedDAfPo1XaG/EzrUUGBI= -github.com/fluxcd/source-controller/api v0.36.1 h1:/ul69kJNEwrFG1Cwk2P/GwgraIxOETCL+tP+zMtxTu8= -github.com/fluxcd/source-controller/api v0.36.1/go.mod h1:GktZmd5Dfxo84vPFBdLDl0bBtiJRODfd47uugK0romU= +github.com/fluxcd/source-controller/api v1.0.0-rc.1 h1:MZaP5utClMG95Aw/AVu1l05WEfmpEw/RIlCLnkCQl14= +github.com/fluxcd/source-controller/api v1.0.0-rc.1/go.mod h1:CvGNdS8g/MqwpERUK6aJp4lndsrm+JBzGpoyyZ4u0c8= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= diff --git a/hack/api-docs/template/pkg.tpl b/hack/api-docs/template/pkg.tpl index 61d05f77..d3c3d073 100644 --- a/hack/api-docs/template/pkg.tpl +++ b/hack/api-docs/template/pkg.tpl @@ -1,5 +1,10 @@ {{ define "packages" }} -

Kustomize API reference

+

Kustomize API reference + {{- with (index .packages 0) -}} + {{ with (index .GoPackages 0 ) -}} + {{ printf " %s" .Name -}} + {{ end -}} + {{ end }}

{{ with .packages}}

Packages:

diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt index 923f609e..e4b53a5f 100644 --- a/hack/boilerplate.go.txt +++ b/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright 2021 The Flux authors +Copyright 2023 The Flux authors Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/internal/controllers/kustomization_acl_test.go b/internal/controllers/kustomization_acl_test.go index 3c02229f..7e780909 100644 --- a/internal/controllers/kustomization_acl_test.go +++ b/internal/controllers/kustomization_acl_test.go @@ -25,14 +25,14 @@ import ( apiacl "github.com/fluxcd/pkg/apis/acl" "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_NoCrossNamespaceRefs(t *testing.T) { diff --git a/internal/controllers/kustomization_controller.go b/internal/controllers/kustomization_controller.go index 4247874f..48e5891a 100644 --- a/internal/controllers/kustomization_controller.go +++ b/internal/controllers/kustomization_controller.go @@ -60,9 +60,10 @@ import ( "github.com/fluxcd/pkg/runtime/predicates" "github.com/fluxcd/pkg/ssa" "github.com/fluxcd/pkg/tar" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" + sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" "github.com/fluxcd/kustomize-controller/internal/decryptor" "github.com/fluxcd/kustomize-controller/internal/inventory" ) @@ -110,7 +111,7 @@ func (r *KustomizationReconciler) SetupWithManager(mgr ctrl.Manager, opts Kustom // Index the Kustomizations by the OCIRepository references they (may) point at. if err := mgr.GetCache().IndexField(context.TODO(), &kustomizev1.Kustomization{}, ociRepositoryIndexKey, - r.indexBy(sourcev1.OCIRepositoryKind)); err != nil { + r.indexBy(sourcev1b2.OCIRepositoryKind)); err != nil { return fmt.Errorf("failed setting index fields: %w", err) } @@ -122,7 +123,7 @@ func (r *KustomizationReconciler) SetupWithManager(mgr ctrl.Manager, opts Kustom // Index the Kustomizations by the Bucket references they (may) point at. if err := mgr.GetCache().IndexField(context.TODO(), &kustomizev1.Kustomization{}, bucketIndexKey, - r.indexBy(sourcev1.BucketKind)); err != nil { + r.indexBy(sourcev1b2.BucketKind)); err != nil { return fmt.Errorf("failed setting index fields: %w", err) } @@ -141,7 +142,7 @@ func (r *KustomizationReconciler) SetupWithManager(mgr ctrl.Manager, opts Kustom predicate.Or(predicate.GenerationChangedPredicate{}, predicates.ReconcileRequestedPredicate{}), )). Watches( - &source.Kind{Type: &sourcev1.OCIRepository{}}, + &source.Kind{Type: &sourcev1b2.OCIRepository{}}, handler.EnqueueRequestsFromMapFunc(r.requestsForRevisionChangeOf(ociRepositoryIndexKey)), builder.WithPredicates(SourceRevisionChangePredicate{}), ). @@ -151,7 +152,7 @@ func (r *KustomizationReconciler) SetupWithManager(mgr ctrl.Manager, opts Kustom builder.WithPredicates(SourceRevisionChangePredicate{}), ). Watches( - &source.Kind{Type: &sourcev1.Bucket{}}, + &source.Kind{Type: &sourcev1b2.Bucket{}}, handler.EnqueueRequestsFromMapFunc(r.requestsForRevisionChangeOf(bucketIndexKey)), builder.WithPredicates(SourceRevisionChangePredicate{}), ). @@ -517,8 +518,8 @@ func (r *KustomizationReconciler) getSource(ctx context.Context, } switch obj.Spec.SourceRef.Kind { - case sourcev1.OCIRepositoryKind: - var repository sourcev1.OCIRepository + case sourcev1b2.OCIRepositoryKind: + var repository sourcev1b2.OCIRepository err := r.Client.Get(ctx, namespacedName, &repository) if err != nil { if apierrors.IsNotFound(err) { @@ -537,8 +538,8 @@ func (r *KustomizationReconciler) getSource(ctx context.Context, return src, fmt.Errorf("unable to get source '%s': %w", namespacedName, err) } src = &repository - case sourcev1.BucketKind: - var bucket sourcev1.Bucket + case sourcev1b2.BucketKind: + var bucket sourcev1b2.Bucket err := r.Client.Get(ctx, namespacedName, &bucket) if err != nil { if apierrors.IsNotFound(err) { @@ -1018,7 +1019,7 @@ func (r *KustomizationReconciler) finalizeStatus(ctx context.Context, if conditions.IsFalse(obj, meta.ReadyCondition) && conditions.Has(obj, meta.ReconcilingCondition) { rc := conditions.Get(obj, meta.ReconcilingCondition) - rc.Reason = kustomizev1.ProgressingWithRetryReason + rc.Reason = meta.ProgressingWithRetryReason conditions.Set(obj, rc) } diff --git a/internal/controllers/kustomization_decryptor_test.go b/internal/controllers/kustomization_decryptor_test.go index d082d0ed..aee2c3aa 100644 --- a/internal/controllers/kustomization_decryptor_test.go +++ b/internal/controllers/kustomization_decryptor_test.go @@ -25,7 +25,7 @@ import ( "time" "github.com/fluxcd/pkg/apis/meta" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" "github.com/hashicorp/vault/api" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -33,7 +33,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_Decryptor(t *testing.T) { diff --git a/internal/controllers/kustomization_dependson_test.go b/internal/controllers/kustomization_dependson_test.go index de40ed50..06180528 100644 --- a/internal/controllers/kustomization_dependson_test.go +++ b/internal/controllers/kustomization_dependson_test.go @@ -24,14 +24,14 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_DependsOn(t *testing.T) { diff --git a/internal/controllers/kustomization_fetcher_test.go b/internal/controllers/kustomization_fetcher_test.go index 3bf0794a..451f66c3 100644 --- a/internal/controllers/kustomization_fetcher_test.go +++ b/internal/controllers/kustomization_fetcher_test.go @@ -25,14 +25,14 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_ArtifactDownload(t *testing.T) { diff --git a/internal/controllers/kustomization_force_test.go b/internal/controllers/kustomization_force_test.go index 0644037c..f1eada91 100644 --- a/internal/controllers/kustomization_force_test.go +++ b/internal/controllers/kustomization_force_test.go @@ -24,7 +24,7 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" apimeta "k8s.io/apimachinery/pkg/api/meta" @@ -32,7 +32,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_Force(t *testing.T) { diff --git a/internal/controllers/kustomization_fuzzer_test.go b/internal/controllers/kustomization_fuzzer_test.go index 6160deff..bc3eaabb 100644 --- a/internal/controllers/kustomization_fuzzer_test.go +++ b/internal/controllers/kustomization_fuzzer_test.go @@ -57,11 +57,11 @@ import ( "github.com/fluxcd/pkg/runtime/controller" "github.com/fluxcd/pkg/runtime/testenv" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" fuzz "github.com/AdaLogics/go-fuzz-headers" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) var ( diff --git a/internal/controllers/kustomization_impersonation_test.go b/internal/controllers/kustomization_impersonation_test.go index 56d14961..0de24e95 100644 --- a/internal/controllers/kustomization_impersonation_test.go +++ b/internal/controllers/kustomization_impersonation_test.go @@ -24,7 +24,7 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -34,7 +34,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_Impersonation(t *testing.T) { diff --git a/internal/controllers/kustomization_indexers.go b/internal/controllers/kustomization_indexers.go index f4524400..5212f031 100644 --- a/internal/controllers/kustomization_indexers.go +++ b/internal/controllers/kustomization_indexers.go @@ -24,9 +24,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/fluxcd/pkg/runtime/dependency" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func (r *KustomizationReconciler) requestsForRevisionChangeOf(indexKey string) func(obj client.Object) []reconcile.Request { diff --git a/internal/controllers/kustomization_inventory_test.go b/internal/controllers/kustomization_inventory_test.go index 1dc0438c..11a62a11 100644 --- a/internal/controllers/kustomization_inventory_test.go +++ b/internal/controllers/kustomization_inventory_test.go @@ -29,14 +29,14 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" apimeta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_Inventory(t *testing.T) { diff --git a/internal/controllers/kustomization_prune_test.go b/internal/controllers/kustomization_prune_test.go index 1a5b0b72..2d8ee81a 100644 --- a/internal/controllers/kustomization_prune_test.go +++ b/internal/controllers/kustomization_prune_test.go @@ -24,7 +24,7 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -32,7 +32,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_Prune(t *testing.T) { diff --git a/internal/controllers/kustomization_transformer_test.go b/internal/controllers/kustomization_transformer_test.go index 284c03ed..9c8972a5 100644 --- a/internal/controllers/kustomization_transformer_test.go +++ b/internal/controllers/kustomization_transformer_test.go @@ -26,16 +26,15 @@ import ( "github.com/fluxcd/pkg/apis/kustomize" "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_CommonMetadata(t *testing.T) { @@ -471,25 +470,6 @@ metadata: `, }, }, - PatchesJSON6902: []kustomize.JSON6902Patch{ - { - Patch: []kustomize.JSON6902{ - {Op: "add", Path: "/metadata/labels/patch3", Value: &apiextensionsv1.JSON{Raw: []byte(`"json6902"`)}}, - {Op: "replace", Path: "/spec/replicas", Value: &apiextensionsv1.JSON{Raw: []byte("2")}}, - }, - Target: kustomize.Selector{ - Group: "apps", - Version: "v1", - Kind: "Deployment", - Name: "podinfo", - }, - }, - }, - PatchesStrategicMerge: []apiextensionsv1.JSON{ - { - Raw: []byte(`{"kind":"Deployment","apiVersion":"apps/v1","metadata":{"name":"podinfo","labels":{"patch4":"strategic-merge"}}}`), - }, - }, }, } @@ -507,9 +487,6 @@ metadata: t.Run("applies patches", func(t *testing.T) { g.Expect(deployment.ObjectMeta.Labels["patch1"]).To(Equal("inline-json")) g.Expect(deployment.ObjectMeta.Labels["patch2"]).To(Equal("inline-yaml")) - g.Expect(deployment.ObjectMeta.Labels["patch3"]).To(Equal("json6902")) - g.Expect(deployment.ObjectMeta.Labels["patch4"]).To(Equal("strategic-merge")) - g.Expect(*deployment.Spec.Replicas).To(Equal(int32(2))) g.Expect(deployment.Spec.Template.Spec.Containers[0].Image).To(ContainSubstring("5.2.0")) g.Expect(deployment.Spec.Template.Spec.Containers[1].Image).To(ContainSubstring("sha256:2832f53c577d44753e97b0ed5f00e7e3a06979c9fab77d0e78bdac4b612b14fb")) }) diff --git a/internal/controllers/kustomization_validation_test.go b/internal/controllers/kustomization_validation_test.go index 42fd1b09..414d6f4c 100644 --- a/internal/controllers/kustomization_validation_test.go +++ b/internal/controllers/kustomization_validation_test.go @@ -23,13 +23,13 @@ import ( "time" "github.com/fluxcd/pkg/apis/meta" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_Validation(t *testing.T) { diff --git a/internal/controllers/kustomization_varsub_test.go b/internal/controllers/kustomization_varsub_test.go index 2c92cd36..2e562d84 100644 --- a/internal/controllers/kustomization_varsub_test.go +++ b/internal/controllers/kustomization_varsub_test.go @@ -23,7 +23,7 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" apimeta "k8s.io/apimachinery/pkg/api/meta" @@ -31,7 +31,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_Varsub(t *testing.T) { diff --git a/internal/controllers/kustomization_wait_test.go b/internal/controllers/kustomization_wait_test.go index 3f0da707..7efc8f0f 100644 --- a/internal/controllers/kustomization_wait_test.go +++ b/internal/controllers/kustomization_wait_test.go @@ -32,9 +32,9 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/runtime/conditions" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func TestKustomizationReconciler_WaitConditions(t *testing.T) { @@ -43,6 +43,7 @@ func TestKustomizationReconciler_WaitConditions(t *testing.T) { revision := "v1.0.0" resultK := &kustomizev1.Kustomization{} reconcileRequestAt := metav1.Now().String() + timeout := 60 * time.Second err := createNamespace(id) g.Expect(err).NotTo(HaveOccurred(), "failed to create test namespace") @@ -181,7 +182,7 @@ parameters: } expectedMessage := "Running health checks" - g.Expect(conditions.GetReason(resultK, meta.ReconcilingCondition)).To(BeIdenticalTo(kustomizev1.ProgressingWithRetryReason)) + g.Expect(conditions.GetReason(resultK, meta.ReconcilingCondition)).To(BeIdenticalTo(meta.ProgressingWithRetryReason)) g.Expect(conditions.GetMessage(resultK, meta.ReconcilingCondition)).To(ContainSubstring(expectedMessage)) g.Expect(resultK.Status.LastHandledReconcileAt).To(BeIdenticalTo(reconcileRequestAt)) diff --git a/internal/controllers/source_predicate.go b/internal/controllers/source_predicate.go index 3d27cf2f..314eb634 100644 --- a/internal/controllers/source_predicate.go +++ b/internal/controllers/source_predicate.go @@ -20,7 +20,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" ) type SourceRevisionChangePredicate struct { diff --git a/internal/controllers/suite_test.go b/internal/controllers/suite_test.go index ab2879c3..a0d9a41b 100644 --- a/internal/controllers/suite_test.go +++ b/internal/controllers/suite_test.go @@ -45,9 +45,10 @@ import ( "github.com/fluxcd/pkg/runtime/controller" "github.com/fluxcd/pkg/runtime/testenv" "github.com/fluxcd/pkg/testserver" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" + sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func init() { @@ -77,8 +78,9 @@ var ( func runInContext(registerControllers func(*testenv.Environment), run func() error, crdPath string) error { var err error - utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme)) utilruntime.Must(kustomizev1.AddToScheme(scheme.Scheme)) + utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme)) + utilruntime.Must(sourcev1b2.AddToScheme(scheme.Scheme)) if debugMode { controllerLog.SetLogger(zap.New(zap.WriteTo(os.Stderr), zap.UseDevMode(false))) @@ -205,7 +207,7 @@ func randStringRunes(n int) string { func isReconcileRunning(k *kustomizev1.Kustomization) bool { return conditions.IsReconciling(k) && - conditions.GetReason(k, meta.ReconcilingCondition) != kustomizev1.ProgressingWithRetryReason + conditions.GetReason(k, meta.ReconcilingCondition) != meta.ProgressingWithRetryReason } func isReconcileSuccess(k *kustomizev1.Kustomization) bool { @@ -228,7 +230,7 @@ func isReconcileFailure(k *kustomizev1.Kustomization) bool { return isHandled && conditions.IsReconciling(k) && conditions.IsFalse(k, meta.ReadyCondition) && conditions.GetObservedGeneration(k, meta.ReadyCondition) == k.Generation && - conditions.GetReason(k, meta.ReconcilingCondition) == kustomizev1.ProgressingWithRetryReason + conditions.GetReason(k, meta.ReconcilingCondition) == meta.ProgressingWithRetryReason } func logStatus(t *testing.T, k *kustomizev1.Kustomization) { diff --git a/internal/decryptor/decryptor.go b/internal/decryptor/decryptor.go index 45a95125..70b61375 100644 --- a/internal/decryptor/decryptor.go +++ b/internal/decryptor/decryptor.go @@ -46,7 +46,7 @@ import ( kustypes "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/yaml" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" "github.com/fluxcd/kustomize-controller/internal/sops/age" "github.com/fluxcd/kustomize-controller/internal/sops/awskms" "github.com/fluxcd/kustomize-controller/internal/sops/azkv" @@ -105,8 +105,7 @@ var ( } ) -// Decryptor performs decryption operations for a -// v1beta2.Kustomization. +// Decryptor performs decryption operations for a v1.Kustomization. // The only supported decryption provider at present is // DecryptionProviderSOPS. type Decryptor struct { @@ -115,8 +114,8 @@ type Decryptor struct { root string // client is the Kubernetes client used to e.g. retrieve Secrets with. client client.Client - // kustomization is the v1beta2.Kustomization we are decrypting for. - // The v1beta2.Decryption of the object is used to ImportKeys(). + // kustomization is the v1.Kustomization we are decrypting for. + // The v1.Decryption of the object is used to ImportKeys(). kustomization *kustomizev1.Kustomization // maxFileSize is the max size in bytes a file is allowed to have to be // decrypted. Defaults to maxEncryptedFileSize. @@ -187,7 +186,7 @@ func IsEncryptedSecret(object *unstructured.Unstructured) bool { } // ImportKeys imports the DecryptionProviderSOPS keys from the data values of -// the Secret referenced in the Kustomization's v1beta2.Decryption spec. +// the Secret referenced in the Kustomization's v1.Decryption spec. // It returns an error if the Secret cannot be retrieved, or if one of the // imports fails. // Imports do not have an effect after the first call to SopsDecryptWithFormat(), diff --git a/internal/decryptor/decryptor_test.go b/internal/decryptor/decryptor_test.go index 83fa2596..322b856a 100644 --- a/internal/decryptor/decryptor_test.go +++ b/internal/decryptor/decryptor_test.go @@ -45,9 +45,10 @@ import ( kustypes "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/yaml" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" - "github.com/fluxcd/kustomize-controller/internal/sops/age" "github.com/fluxcd/pkg/apis/meta" + + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" + "github.com/fluxcd/kustomize-controller/internal/sops/age" ) func TestIsEncryptedSecret(t *testing.T) { diff --git a/internal/inventory/inventory.go b/internal/inventory/inventory.go index 2a01820e..0845fbde 100644 --- a/internal/inventory/inventory.go +++ b/internal/inventory/inventory.go @@ -26,7 +26,7 @@ import ( "github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/ssa" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" ) func New() *kustomizev1.ResourceInventory { diff --git a/main.go b/main.go index a88876da..4e0a9a7a 100644 --- a/main.go +++ b/main.go @@ -43,9 +43,10 @@ import ( "github.com/fluxcd/pkg/runtime/logger" "github.com/fluxcd/pkg/runtime/pprof" "github.com/fluxcd/pkg/runtime/probes" - sourcev1 "github.com/fluxcd/source-controller/api/v1beta2" + sourcev1 "github.com/fluxcd/source-controller/api/v1" + sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2" - kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2" + kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" "github.com/fluxcd/kustomize-controller/internal/controllers" "github.com/fluxcd/kustomize-controller/internal/features" "github.com/fluxcd/kustomize-controller/internal/statusreaders" @@ -63,6 +64,7 @@ func init() { _ = clientgoscheme.AddToScheme(scheme) _ = sourcev1.AddToScheme(scheme) + _ = sourcev1b2.AddToScheme(scheme) _ = kustomizev1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme }