diff --git a/api/v1alpha1/multiclusterservice_types.go b/api/v1alpha1/multiclusterservice_types.go index a1d8c73fe..4603e7dcf 100644 --- a/api/v1alpha1/multiclusterservice_types.go +++ b/api/v1alpha1/multiclusterservice_types.go @@ -16,6 +16,7 @@ package v1alpha1 import ( sveltosv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1" + libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -92,6 +93,16 @@ type ServiceSpec struct { StopOnConflict bool `json:"stopOnConflict,omitempty"` // Reload instances via rolling upgrade when a ConfigMap/Secret mounted as volume is modified. Reload bool `json:"reload,omitempty"` + + // +kubebuilder:default:=Continuous + // +kubebuilder:validation:Enum:=OneTime;Continuous;ContinuousWithDriftDetection;DryRun + + // SyncMode specifies how services are synced in the target cluster. + SyncMode string `json:"syncMode,omitempty"` + // DriftIgnore specifies resources to ignore for drift detection. + DriftIgnore []libsveltosv1beta1.PatchSelector `json:"driftIgnore,omitempty"` + // DriftExclusions specifies specific configurations of resources to ignore for drift detection. + DriftExclusions []sveltosv1beta1.DriftExclusion `json:"driftExclusions,omitempty"` } // MultiClusterServiceSpec defines the desired state of MultiClusterService diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9b02c951e..b94934b7c 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -22,6 +22,7 @@ import ( "github.com/fluxcd/helm-controller/api/v2" apiv1 "github.com/fluxcd/source-controller/api/v1" "github.com/projectsveltos/addon-controller/api/v1beta1" + apiv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" corev1 "k8s.io/api/core/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -1321,6 +1322,18 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { *out = make([]v1beta1.TemplateResourceRef, len(*in)) copy(*out, *in) } + if in.DriftIgnore != nil { + in, out := &in.DriftIgnore, &out.DriftIgnore + *out = make([]apiv1beta1.PatchSelector, len(*in)) + copy(*out, *in) + } + if in.DriftExclusions != nil { + in, out := &in.DriftExclusions, &out.DriftExclusions + *out = make([]v1beta1.DriftExclusion, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec. diff --git a/internal/controller/clusterdeployment_controller.go b/internal/controller/clusterdeployment_controller.go index c8db82a3c..69a3b1823 100644 --- a/internal/controller/clusterdeployment_controller.go +++ b/internal/controller/clusterdeployment_controller.go @@ -526,7 +526,10 @@ func (r *ClusterDeploymentReconciler) updateServices(ctx context.Context, mc *kc TemplateResourceRefs: append( getProjectTemplateResourceRefs(mc, cred), mc.Spec.ServiceSpec.TemplateResourceRefs..., ), - PolicyRefs: getProjectPolicyRefs(mc, cred), + PolicyRefs: getProjectPolicyRefs(mc, cred), + SyncMode: mc.Spec.ServiceSpec.SyncMode, + DriftIgnore: mc.Spec.ServiceSpec.DriftIgnore, + DriftExclusions: mc.Spec.ServiceSpec.DriftExclusions, }); err != nil { return ctrl.Result{}, fmt.Errorf("failed to reconcile Profile: %w", err) } diff --git a/internal/controller/multiclusterservice_controller.go b/internal/controller/multiclusterservice_controller.go index 0a80d98d4..08c408894 100644 --- a/internal/controller/multiclusterservice_controller.go +++ b/internal/controller/multiclusterservice_controller.go @@ -139,6 +139,9 @@ func (r *MultiClusterServiceReconciler) reconcileUpdate(ctx context.Context, mcs StopOnConflict: mcs.Spec.ServiceSpec.StopOnConflict, Reload: mcs.Spec.ServiceSpec.Reload, TemplateResourceRefs: mcs.Spec.ServiceSpec.TemplateResourceRefs, + SyncMode: mcs.Spec.ServiceSpec.SyncMode, + DriftIgnore: mcs.Spec.ServiceSpec.DriftIgnore, + DriftExclusions: mcs.Spec.ServiceSpec.DriftExclusions, }); err != nil { return ctrl.Result{}, fmt.Errorf("failed to reconcile ClusterProfile: %w", err) } diff --git a/internal/sveltos/profile.go b/internal/sveltos/profile.go index b762cb01f..279bc13c2 100644 --- a/internal/sveltos/profile.go +++ b/internal/sveltos/profile.go @@ -32,12 +32,19 @@ import ( "github.com/K0rdent/kcm/internal/utils" ) +const driftIgnorePatch = `- op: add + path: /metadata/annotations/projectsveltos.io~1driftDetectionIgnore + value: ok` + type ReconcileProfileOpts struct { OwnerReference *metav1.OwnerReference + SyncMode string LabelSelector metav1.LabelSelector HelmChartOpts []HelmChartOpts TemplateResourceRefs []sveltosv1beta1.TemplateResourceRef PolicyRefs []sveltosv1beta1.PolicyRef + DriftIgnore []libsveltosv1beta1.PatchSelector + DriftExclusions []sveltosv1beta1.DriftExclusion Priority int32 StopOnConflict bool Reload bool @@ -239,8 +246,17 @@ func GetSpec(opts *ReconcileProfileOpts) (*sveltosv1beta1.Spec, error) { ContinueOnConflict: !opts.StopOnConflict, HelmCharts: make([]sveltosv1beta1.HelmChart, 0, len(opts.HelmChartOpts)), Reloader: opts.Reload, + SyncMode: sveltosv1beta1.SyncMode(opts.SyncMode), TemplateResourceRefs: opts.TemplateResourceRefs, PolicyRefs: opts.PolicyRefs, + DriftExclusions: opts.DriftExclusions, + } + + for _, target := range opts.DriftIgnore { + spec.Patches = append(spec.Patches, libsveltosv1beta1.Patch{ + Target: &target, + Patch: driftIgnorePatch, + }) } for _, hc := range opts.HelmChartOpts { diff --git a/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_clusterdeployments.yaml b/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_clusterdeployments.yaml index aa35ec4eb..c862229c5 100644 --- a/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_clusterdeployments.yaml +++ b/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_clusterdeployments.yaml @@ -78,6 +78,107 @@ spec: serviceSpec: description: ServiceSpec is spec related to deployment of services. properties: + driftExclusions: + description: DriftExclusions specifies specific configurations + of resources to ignore for drift detection. + items: + properties: + paths: + description: Paths is a slice of JSON6902 paths to exclude + from configuration drift evaluation. + items: + type: string + type: array + target: + description: Target points to the resources that the paths + refers 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: + - paths + type: object + type: array + driftIgnore: + description: DriftIgnore specifies resources to ignore for drift + detection. + items: + 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 + type: array priority: default: 100 description: |- @@ -172,6 +273,16 @@ spec: By default the remaining services will be deployed even if conflict is detected. If set to true, the deployment will stop after encountering the first conflict. type: boolean + syncMode: + default: Continuous + description: SyncMode specifies how services are synced in the + target cluster. + enum: + - OneTime + - Continuous + - ContinuousWithDriftDetection + - DryRun + type: string templateResourceRefs: description: |- TemplateResourceRefs is a list of resources to collect from the management cluster, diff --git a/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_multiclusterservices.yaml b/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_multiclusterservices.yaml index 894392566..4d96424e8 100644 --- a/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_multiclusterservices.yaml +++ b/templates/provider/kcm/templates/crds/k0rdent.mirantis.com_multiclusterservices.yaml @@ -90,6 +90,107 @@ spec: serviceSpec: description: ServiceSpec is spec related to deployment of services. properties: + driftExclusions: + description: DriftExclusions specifies specific configurations + of resources to ignore for drift detection. + items: + properties: + paths: + description: Paths is a slice of JSON6902 paths to exclude + from configuration drift evaluation. + items: + type: string + type: array + target: + description: Target points to the resources that the paths + refers 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: + - paths + type: object + type: array + driftIgnore: + description: DriftIgnore specifies resources to ignore for drift + detection. + items: + 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 + type: array priority: default: 100 description: |- @@ -184,6 +285,16 @@ spec: By default the remaining services will be deployed even if conflict is detected. If set to true, the deployment will stop after encountering the first conflict. type: boolean + syncMode: + default: Continuous + description: SyncMode specifies how services are synced in the + target cluster. + enum: + - OneTime + - Continuous + - ContinuousWithDriftDetection + - DryRun + type: string templateResourceRefs: description: |- TemplateResourceRefs is a list of resources to collect from the management cluster,