From 9a3cd780d88e08fb938b352e406cc9ee0098df0e Mon Sep 17 00:00:00 2001 From: michaelawyu Date: Wed, 11 Dec 2024 12:43:53 +0800 Subject: [PATCH] interface: add the new takeover option never, plus some minor changes (#984) --- .../v1beta1/clusterresourceplacement_types.go | 82 ++++++++++++++++--- apis/placement/v1beta1/work_types.go | 13 +-- .../v1beta1/zz_generated.deepcopy.go | 10 +++ ...ment.kubernetes-fleet.io_appliedworks.yaml | 6 +- ...etes-fleet.io_clusterresourcebindings.yaml | 54 ++++++++++-- ...es-fleet.io_clusterresourceplacements.yaml | 54 ++++++++++-- ...etes-fleet.io_clusterstagedupdateruns.yaml | 50 +++++++++-- .../placement.kubernetes-fleet.io_works.yaml | 60 ++++++++++++-- .../placement_status_test.go | 4 +- .../controller_integration_test.go | 8 +- .../workgenerator/controller_test.go | 14 ++-- 11 files changed, 294 insertions(+), 61 deletions(-) diff --git a/apis/placement/v1beta1/clusterresourceplacement_types.go b/apis/placement/v1beta1/clusterresourceplacement_types.go index 4eba23dd7..149f1c65b 100644 --- a/apis/placement/v1beta1/clusterresourceplacement_types.go +++ b/apis/placement/v1beta1/clusterresourceplacement_types.go @@ -535,8 +535,19 @@ type ApplyStrategy struct { // differences. No actual apply ops would be executed, and resources will be left alone as they // are on the member clusters. // + // If configuration differences are found on a resource, Fleet will consider this as an apply + // error, which might block rollout depending on the specified rollout strategy. + // // Use ComparisonOption setting to control how the difference is calculated. // + // ClientSideApply and ServerSideApply apply strategies only work when Fleet can assume + // ownership of a resource (e.g., the resource is created by Fleet, or Fleet has taken over + // the resource). See the comments on the WhenToTakeOver field for more information. + // ReportDiff apply strategy, however, will function regardless of Fleet's ownership + // status. One may set up a CRP with the ReportDiff strategy and the Never takeover option, + // and this will turn Fleet into a detection tool that reports only configuration differences + // but do not touch any resources on the member cluster side. + // // For a comparison between the different strategies and usage examples, refer to the // Fleet documentation. // @@ -545,10 +556,14 @@ type ApplyStrategy struct { // +kubebuilder:validation:Optional Type ApplyStrategyType `json:"type,omitempty"` - // AllowCoOwnership defines whether to apply the resource if it already exists in the target cluster and is not - // solely owned by fleet (i.e., metadata.ownerReferences contains only fleet custom resources). - // If true, apply the resource and add fleet as a co-owner. - // If false, leave the resource unchanged and fail the apply. + // AllowCoOwnership controls whether co-ownership between Fleet and other agents are allowed + // on a Fleet-managed resource. If set to false, Fleet will refuse to apply manifests to + // a resource that has been owned by one or more non-Fleet agents. + // + // Note that Fleet does not support the case where one resource is being placed multiple + // times by different CRPs on the same member cluster. An apply error will be returned if + // Fleet finds that a resource has been owned by another placement attempt by Fleet, even + // with the AllowCoOwnership setting set to true. AllowCoOwnership bool `json:"allowCoOwnership,omitempty"` // ServerSideApplyConfig defines the configuration for server side apply. It is honored only when type is ServerSideApply. @@ -571,8 +586,9 @@ type ApplyStrategy struct { // // * IfNoDiff: with this action, Fleet will apply the hub cluster manifests to the member // clusters if (and only if) pre-existing resources look the same as the hub cluster manifests. + // // This is a safer option as pre-existing resources that are inconsistent with the hub cluster - // manifests will not be overwritten; in fact, Fleet will ignore them until the inconsistencies + // manifests will not be overwritten; Fleet will ignore them until the inconsistencies // are resolved properly: any change you make to the hub cluster manifests would not be // applied, and if you delete the manifests or even the ClusterResourcePlacement itself // from the hub cluster, these pre-existing resources would not be taken away. @@ -597,8 +613,24 @@ type ApplyStrategy struct { // If appropriate, you may also delete the object from the member cluster; Fleet will recreate // it using the hub cluster manifest. // + // * Never: with this action, Fleet will not apply a hub cluster manifest to the member + // clusters if there is a corresponding pre-existing resource. However, if a manifest + // has never been applied yet; or it has a corresponding resource which Fleet has assumed + // ownership, apply op will still be executed. + // + // This is the safest option; one will have to remove the pre-existing resources (so that + // Fleet can re-create them) or switch to a different + // WhenToTakeOver option before Fleet starts processing the corresponding hub cluster + // manifests. + // + // If you prefer Fleet stop processing all manifests, use this option along with the + // ReportDiff apply strategy type. This setup would instruct Fleet to touch nothing + // on the member cluster side but still report configuration differences between the + // hub cluster and member clusters. Fleet will not give up ownership + // that it has already assumed though. + // // +kubebuilder:default=Always - // +kubebuilder:validation:Enum=Always;IfNoDiff + // +kubebuilder:validation:Enum=Always;IfNoDiff;Never // +kubebuilder:validation:Optional WhenToTakeOver WhenToTakeOverType `json:"whenToTakeOver,omitempty"` } @@ -676,14 +708,35 @@ type ServerSideApplyConfig struct { type WhenToTakeOverType string const ( - // WhenToTakeOverTypeIfNoDiff will apply manifests from the hub cluster only if there is no difference - // between the current resource snapshot version on the hub cluster and the existing - // resources on the member cluster. Otherwise, we will report the difference. + // WhenToTakeOverTypeIfNoDiff instructs Fleet to apply a manifest with a corresponding + // pre-existing resource on a member cluster if and only if the pre-existing resource + // looks the same as the manifest. Should there be any inconsistency, Fleet will skip + // the apply op; no change will be made on the resource and Fleet will not claim + // ownership on it. + // + // Note that this will not stop Fleet from processing other manifests in the same + // placement that do not concern the takeover process (e.g., the manifests that have + // not been created yet, or that are already under the management of Fleet). WhenToTakeOverTypeIfNoDiff WhenToTakeOverType = "IfNoDiff" - // WhenToTakeOverTypeAlways will always apply the resource to the member cluster regardless - // if there are differences between the resource on the hub cluster and the existing resources on the member cluster. + // WhenToTakeOverTypeAlways instructs Fleet to always apply manifests to a member cluster, + // even if there are some corresponding pre-existing resources. Some fields on these + // resources might be overwritten, and Fleet will claim ownership on them. WhenToTakeOverTypeAlways WhenToTakeOverType = "Always" + + // WhenToTakeOverTypeNever instructs Fleet to never apply a manifest to a member cluster + // if there is a corresponding pre-existing resource. + // + // Note that this will not stop Fleet from processing other manifests in the same placement + // that do not concern the takeover process (e.g., the manifests that have not been created + // yet, or that are already under the management of Fleet). + // + // If you would like Fleet to stop processing manifests all together and do not assume + // ownership on any pre-existing resources, use this option along with the ReportDiff + // apply strategy type. This setup would instruct Fleet to touch nothing on the member + // cluster side but still report configuration differences between the hub cluster + // and member clusters. Fleet will not give up ownership that it has already assumed, though. + WhenToTakeOverTypeNever WhenToTakeOverType = "Never" ) // +enum @@ -978,8 +1031,11 @@ type DiffedResourcePlacement struct { // TargetClusterObservedGeneration is the generation of the resource on the target cluster // that contains the configuration differences. - // +kubebuilder:validation:Required - TargetClusterObservedGeneration int64 `json:"targetClusterObservedGeneration"` + // + // This might be nil if the resource has not been created yet on the target cluster. + // + // +kubebuilder:validation:Optional + TargetClusterObservedGeneration *int64 `json:"targetClusterObservedGeneration"` // FirstDiffedObservedTime is the first time the resource on the target cluster is // observed to have configuration differences. diff --git a/apis/placement/v1beta1/work_types.go b/apis/placement/v1beta1/work_types.go index 2a7c38200..05ae59a59 100644 --- a/apis/placement/v1beta1/work_types.go +++ b/apis/placement/v1beta1/work_types.go @@ -102,14 +102,14 @@ type WorkResourceIdentifier struct { // Kind is the kind of the resource. Kind string `json:"kind,omitempty"` - // Resource is the resource type of the resource + // Resource is the resource type of the resource. Resource string `json:"resource,omitempty"` // Namespace is the namespace of the resource, the resource is cluster scoped if the value - // is empty + // is empty. Namespace string `json:"namespace,omitempty"` - // Name is the name of the resource + // Name is the name of the resource. Name string `json:"name,omitempty"` } @@ -124,7 +124,6 @@ type DriftDetails struct { // ObservedInMemberClusterGeneration is the generation of the applied manifest on the member // cluster side. - // // +kubebuilder:validation:Required ObservedInMemberClusterGeneration int64 `json:"observedInMemberClusterGeneration"` @@ -157,8 +156,10 @@ type DiffDetails struct { // ObservedInMemberClusterGeneration is the generation of the applied manifest on the member // cluster side. // - // +kubebuilder:validation:Required - ObservedInMemberClusterGeneration int64 `json:"observedInMemberClusterGeneration"` + // This might be nil if the resource has not been created yet in the member cluster. + // + // +kubebuilder:validation:Optional + ObservedInMemberClusterGeneration *int64 `json:"observedInMemberClusterGeneration"` // FirsftDiffedObservedTime is the timestamp when the configuration difference // was first detected. diff --git a/apis/placement/v1beta1/zz_generated.deepcopy.go b/apis/placement/v1beta1/zz_generated.deepcopy.go index 803ac0287..f4d51c817 100644 --- a/apis/placement/v1beta1/zz_generated.deepcopy.go +++ b/apis/placement/v1beta1/zz_generated.deepcopy.go @@ -618,6 +618,11 @@ func (in *ClusterSelectorTerm) DeepCopy() *ClusterSelectorTerm { func (in *DiffDetails) DeepCopyInto(out *DiffDetails) { *out = *in in.ObservationTime.DeepCopyInto(&out.ObservationTime) + if in.ObservedInMemberClusterGeneration != nil { + in, out := &in.ObservedInMemberClusterGeneration, &out.ObservedInMemberClusterGeneration + *out = new(int64) + **out = **in + } in.FirstDiffedObservedTime.DeepCopyInto(&out.FirstDiffedObservedTime) if in.ObservedDiffs != nil { in, out := &in.ObservedDiffs, &out.ObservedDiffs @@ -641,6 +646,11 @@ func (in *DiffedResourcePlacement) DeepCopyInto(out *DiffedResourcePlacement) { *out = *in in.ResourceIdentifier.DeepCopyInto(&out.ResourceIdentifier) in.ObservationTime.DeepCopyInto(&out.ObservationTime) + if in.TargetClusterObservedGeneration != nil { + in, out := &in.TargetClusterObservedGeneration, &out.TargetClusterObservedGeneration + *out = new(int64) + **out = **in + } in.FirstDiffedObservedTime.DeepCopyInto(&out.FirstDiffedObservedTime) if in.ObservedDiffs != nil { in, out := &in.ObservedDiffs, &out.ObservedDiffs diff --git a/config/crd/bases/placement.kubernetes-fleet.io_appliedworks.yaml b/config/crd/bases/placement.kubernetes-fleet.io_appliedworks.yaml index 126d7a161..dbebb0ff3 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_appliedworks.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_appliedworks.yaml @@ -189,12 +189,12 @@ spec: description: Kind is the kind of the resource. type: string name: - description: Name is the name of the resource + description: Name is the name of the resource. type: string namespace: description: |- Namespace is the namespace of the resource, the resource is cluster scoped if the value - is empty + is empty. type: string ordinal: description: |- @@ -202,7 +202,7 @@ spec: to a manifest even though manifest cannot be parsed successfully. type: integer resource: - description: Resource is the resource type of the resource + description: Resource is the resource type of the resource. type: string uid: description: |- diff --git a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml index 45c007b07..07ccc748f 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml @@ -430,10 +430,15 @@ spec: properties: allowCoOwnership: description: |- - AllowCoOwnership defines whether to apply the resource if it already exists in the target cluster and is not - solely owned by fleet (i.e., metadata.ownerReferences contains only fleet custom resources). - If true, apply the resource and add fleet as a co-owner. - If false, leave the resource unchanged and fail the apply. + AllowCoOwnership controls whether co-ownership between Fleet and other agents are allowed + on a Fleet-managed resource. If set to false, Fleet will refuse to apply manifests to + a resource that has been owned by one or more non-Fleet agents. + + + Note that Fleet does not support the case where one resource is being placed multiple + times by different CRPs on the same member cluster. An apply error will be returned if + Fleet finds that a resource has been owned by another placement attempt by Fleet, even + with the AllowCoOwnership setting set to true. type: boolean comparisonOption: default: PartialComparison @@ -533,9 +538,22 @@ spec: are on the member clusters. + If configuration differences are found on a resource, Fleet will consider this as an apply + error, which might block rollout depending on the specified rollout strategy. + + Use ComparisonOption setting to control how the difference is calculated. + ClientSideApply and ServerSideApply apply strategies only work when Fleet can assume + ownership of a resource (e.g., the resource is created by Fleet, or Fleet has taken over + the resource). See the comments on the WhenToTakeOver field for more information. + ReportDiff apply strategy, however, will function regardless of Fleet's ownership + status. One may set up a CRP with the ReportDiff strategy and the Never takeover option, + and this will turn Fleet into a detection tool that reports only configuration differences + but do not touch any resources on the member cluster side. + + For a comparison between the different strategies and usage examples, refer to the Fleet documentation. enum: @@ -618,8 +636,10 @@ spec: * IfNoDiff: with this action, Fleet will apply the hub cluster manifests to the member clusters if (and only if) pre-existing resources look the same as the hub cluster manifests. + + This is a safer option as pre-existing resources that are inconsistent with the hub cluster - manifests will not be overwritten; in fact, Fleet will ignore them until the inconsistencies + manifests will not be overwritten; Fleet will ignore them until the inconsistencies are resolved properly: any change you make to the hub cluster manifests would not be applied, and if you delete the manifests or even the ClusterResourcePlacement itself from the hub cluster, these pre-existing resources would not be taken away. @@ -647,9 +667,29 @@ spec: If appropriate, you may also delete the object from the member cluster; Fleet will recreate it using the hub cluster manifest. + + + * Never: with this action, Fleet will not apply a hub cluster manifest to the member + clusters if there is a corresponding pre-existing resource. However, if a manifest + has never been applied yet; or it has a corresponding resource which Fleet has assumed + ownership, apply op will still be executed. + + + This is the safest option; one will have to remove the pre-existing resources (so that + Fleet can re-create them) or switch to a different + WhenToTakeOver option before Fleet starts processing the corresponding hub cluster + manifests. + + + If you prefer Fleet stop processing all manifests, use this option along with the + ReportDiff apply strategy type. This setup would instruct Fleet to touch nothing + on the member cluster side but still report configuration differences between the + hub cluster and member clusters. Fleet will not give up ownership + that it has already assumed though. enum: - Always - IfNoDiff + - Never type: string type: object clusterDecision: @@ -933,6 +973,9 @@ spec: description: |- TargetClusterObservedGeneration is the generation of the resource on the target cluster that contains the configuration differences. + + + This might be nil if the resource has not been created yet on the target cluster. format: int64 type: integer version: @@ -943,7 +986,6 @@ spec: - kind - name - observationTime - - targetClusterObservedGeneration - version type: object maxItems: 100 diff --git a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml index 57d323c99..3bdca95ca 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml @@ -1758,10 +1758,15 @@ spec: properties: allowCoOwnership: description: |- - AllowCoOwnership defines whether to apply the resource if it already exists in the target cluster and is not - solely owned by fleet (i.e., metadata.ownerReferences contains only fleet custom resources). - If true, apply the resource and add fleet as a co-owner. - If false, leave the resource unchanged and fail the apply. + AllowCoOwnership controls whether co-ownership between Fleet and other agents are allowed + on a Fleet-managed resource. If set to false, Fleet will refuse to apply manifests to + a resource that has been owned by one or more non-Fleet agents. + + + Note that Fleet does not support the case where one resource is being placed multiple + times by different CRPs on the same member cluster. An apply error will be returned if + Fleet finds that a resource has been owned by another placement attempt by Fleet, even + with the AllowCoOwnership setting set to true. type: boolean comparisonOption: default: PartialComparison @@ -1861,9 +1866,22 @@ spec: are on the member clusters. + If configuration differences are found on a resource, Fleet will consider this as an apply + error, which might block rollout depending on the specified rollout strategy. + + Use ComparisonOption setting to control how the difference is calculated. + ClientSideApply and ServerSideApply apply strategies only work when Fleet can assume + ownership of a resource (e.g., the resource is created by Fleet, or Fleet has taken over + the resource). See the comments on the WhenToTakeOver field for more information. + ReportDiff apply strategy, however, will function regardless of Fleet's ownership + status. One may set up a CRP with the ReportDiff strategy and the Never takeover option, + and this will turn Fleet into a detection tool that reports only configuration differences + but do not touch any resources on the member cluster side. + + For a comparison between the different strategies and usage examples, refer to the Fleet documentation. enum: @@ -1946,8 +1964,10 @@ spec: * IfNoDiff: with this action, Fleet will apply the hub cluster manifests to the member clusters if (and only if) pre-existing resources look the same as the hub cluster manifests. + + This is a safer option as pre-existing resources that are inconsistent with the hub cluster - manifests will not be overwritten; in fact, Fleet will ignore them until the inconsistencies + manifests will not be overwritten; Fleet will ignore them until the inconsistencies are resolved properly: any change you make to the hub cluster manifests would not be applied, and if you delete the manifests or even the ClusterResourcePlacement itself from the hub cluster, these pre-existing resources would not be taken away. @@ -1975,9 +1995,29 @@ spec: If appropriate, you may also delete the object from the member cluster; Fleet will recreate it using the hub cluster manifest. + + + * Never: with this action, Fleet will not apply a hub cluster manifest to the member + clusters if there is a corresponding pre-existing resource. However, if a manifest + has never been applied yet; or it has a corresponding resource which Fleet has assumed + ownership, apply op will still be executed. + + + This is the safest option; one will have to remove the pre-existing resources (so that + Fleet can re-create them) or switch to a different + WhenToTakeOver option before Fleet starts processing the corresponding hub cluster + manifests. + + + If you prefer Fleet stop processing all manifests, use this option along with the + ReportDiff apply strategy type. This setup would instruct Fleet to touch nothing + on the member cluster side but still report configuration differences between the + hub cluster and member clusters. Fleet will not give up ownership + that it has already assumed though. enum: - Always - IfNoDiff + - Never type: string type: object rollingUpdate: @@ -2371,6 +2411,9 @@ spec: description: |- TargetClusterObservedGeneration is the generation of the resource on the target cluster that contains the configuration differences. + + + This might be nil if the resource has not been created yet on the target cluster. format: int64 type: integer version: @@ -2381,7 +2424,6 @@ spec: - kind - name - observationTime - - targetClusterObservedGeneration - version type: object maxItems: 100 diff --git a/config/crd/bases/placement.kubernetes-fleet.io_clusterstagedupdateruns.yaml b/config/crd/bases/placement.kubernetes-fleet.io_clusterstagedupdateruns.yaml index 6eb3c730a..f52084ea5 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_clusterstagedupdateruns.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_clusterstagedupdateruns.yaml @@ -89,10 +89,15 @@ spec: properties: allowCoOwnership: description: |- - AllowCoOwnership defines whether to apply the resource if it already exists in the target cluster and is not - solely owned by fleet (i.e., metadata.ownerReferences contains only fleet custom resources). - If true, apply the resource and add fleet as a co-owner. - If false, leave the resource unchanged and fail the apply. + AllowCoOwnership controls whether co-ownership between Fleet and other agents are allowed + on a Fleet-managed resource. If set to false, Fleet will refuse to apply manifests to + a resource that has been owned by one or more non-Fleet agents. + + + Note that Fleet does not support the case where one resource is being placed multiple + times by different CRPs on the same member cluster. An apply error will be returned if + Fleet finds that a resource has been owned by another placement attempt by Fleet, even + with the AllowCoOwnership setting set to true. type: boolean comparisonOption: default: PartialComparison @@ -192,9 +197,22 @@ spec: are on the member clusters. + If configuration differences are found on a resource, Fleet will consider this as an apply + error, which might block rollout depending on the specified rollout strategy. + + Use ComparisonOption setting to control how the difference is calculated. + ClientSideApply and ServerSideApply apply strategies only work when Fleet can assume + ownership of a resource (e.g., the resource is created by Fleet, or Fleet has taken over + the resource). See the comments on the WhenToTakeOver field for more information. + ReportDiff apply strategy, however, will function regardless of Fleet's ownership + status. One may set up a CRP with the ReportDiff strategy and the Never takeover option, + and this will turn Fleet into a detection tool that reports only configuration differences + but do not touch any resources on the member cluster side. + + For a comparison between the different strategies and usage examples, refer to the Fleet documentation. enum: @@ -277,8 +295,10 @@ spec: * IfNoDiff: with this action, Fleet will apply the hub cluster manifests to the member clusters if (and only if) pre-existing resources look the same as the hub cluster manifests. + + This is a safer option as pre-existing resources that are inconsistent with the hub cluster - manifests will not be overwritten; in fact, Fleet will ignore them until the inconsistencies + manifests will not be overwritten; Fleet will ignore them until the inconsistencies are resolved properly: any change you make to the hub cluster manifests would not be applied, and if you delete the manifests or even the ClusterResourcePlacement itself from the hub cluster, these pre-existing resources would not be taken away. @@ -306,9 +326,29 @@ spec: If appropriate, you may also delete the object from the member cluster; Fleet will recreate it using the hub cluster manifest. + + + * Never: with this action, Fleet will not apply a hub cluster manifest to the member + clusters if there is a corresponding pre-existing resource. However, if a manifest + has never been applied yet; or it has a corresponding resource which Fleet has assumed + ownership, apply op will still be executed. + + + This is the safest option; one will have to remove the pre-existing resources (so that + Fleet can re-create them) or switch to a different + WhenToTakeOver option before Fleet starts processing the corresponding hub cluster + manifests. + + + If you prefer Fleet stop processing all manifests, use this option along with the + ReportDiff apply strategy type. This setup would instruct Fleet to touch nothing + on the member cluster side but still report configuration differences between the + hub cluster and member clusters. Fleet will not give up ownership + that it has already assumed though. enum: - Always - IfNoDiff + - Never type: string type: object conditions: diff --git a/config/crd/bases/placement.kubernetes-fleet.io_works.yaml b/config/crd/bases/placement.kubernetes-fleet.io_works.yaml index de85a3e7f..4aab8a4fb 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_works.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_works.yaml @@ -338,10 +338,15 @@ spec: properties: allowCoOwnership: description: |- - AllowCoOwnership defines whether to apply the resource if it already exists in the target cluster and is not - solely owned by fleet (i.e., metadata.ownerReferences contains only fleet custom resources). - If true, apply the resource and add fleet as a co-owner. - If false, leave the resource unchanged and fail the apply. + AllowCoOwnership controls whether co-ownership between Fleet and other agents are allowed + on a Fleet-managed resource. If set to false, Fleet will refuse to apply manifests to + a resource that has been owned by one or more non-Fleet agents. + + + Note that Fleet does not support the case where one resource is being placed multiple + times by different CRPs on the same member cluster. An apply error will be returned if + Fleet finds that a resource has been owned by another placement attempt by Fleet, even + with the AllowCoOwnership setting set to true. type: boolean comparisonOption: default: PartialComparison @@ -441,9 +446,22 @@ spec: are on the member clusters. + If configuration differences are found on a resource, Fleet will consider this as an apply + error, which might block rollout depending on the specified rollout strategy. + + Use ComparisonOption setting to control how the difference is calculated. + ClientSideApply and ServerSideApply apply strategies only work when Fleet can assume + ownership of a resource (e.g., the resource is created by Fleet, or Fleet has taken over + the resource). See the comments on the WhenToTakeOver field for more information. + ReportDiff apply strategy, however, will function regardless of Fleet's ownership + status. One may set up a CRP with the ReportDiff strategy and the Never takeover option, + and this will turn Fleet into a detection tool that reports only configuration differences + but do not touch any resources on the member cluster side. + + For a comparison between the different strategies and usage examples, refer to the Fleet documentation. enum: @@ -526,8 +544,10 @@ spec: * IfNoDiff: with this action, Fleet will apply the hub cluster manifests to the member clusters if (and only if) pre-existing resources look the same as the hub cluster manifests. + + This is a safer option as pre-existing resources that are inconsistent with the hub cluster - manifests will not be overwritten; in fact, Fleet will ignore them until the inconsistencies + manifests will not be overwritten; Fleet will ignore them until the inconsistencies are resolved properly: any change you make to the hub cluster manifests would not be applied, and if you delete the manifests or even the ClusterResourcePlacement itself from the hub cluster, these pre-existing resources would not be taken away. @@ -555,9 +575,29 @@ spec: If appropriate, you may also delete the object from the member cluster; Fleet will recreate it using the hub cluster manifest. + + + * Never: with this action, Fleet will not apply a hub cluster manifest to the member + clusters if there is a corresponding pre-existing resource. However, if a manifest + has never been applied yet; or it has a corresponding resource which Fleet has assumed + ownership, apply op will still be executed. + + + This is the safest option; one will have to remove the pre-existing resources (so that + Fleet can re-create them) or switch to a different + WhenToTakeOver option before Fleet starts processing the corresponding hub cluster + manifests. + + + If you prefer Fleet stop processing all manifests, use this option along with the + ReportDiff apply strategy type. This setup would instruct Fleet to touch nothing + on the member cluster side but still report configuration differences between the + hub cluster and member clusters. Fleet will not give up ownership + that it has already assumed though. enum: - Always - IfNoDiff + - Never type: string type: object workload: @@ -809,12 +849,14 @@ spec: description: |- ObservedInMemberClusterGeneration is the generation of the applied manifest on the member cluster side. + + + This might be nil if the resource has not been created yet in the member cluster. format: int64 type: integer required: - firstDiffedObservedTime - observationTime - - observedInMemberClusterGeneration type: object driftDetails: description: |- @@ -899,12 +941,12 @@ spec: description: Kind is the kind of the resource. type: string name: - description: Name is the name of the resource + description: Name is the name of the resource. type: string namespace: description: |- Namespace is the namespace of the resource, the resource is cluster scoped if the value - is empty + is empty. type: string ordinal: description: |- @@ -912,7 +954,7 @@ spec: to a manifest even though manifest cannot be parsed successfully. type: integer resource: - description: Resource is the resource type of the resource + description: Resource is the resource type of the resource. type: string version: description: Version is the version of the resource. diff --git a/pkg/controllers/clusterresourceplacement/placement_status_test.go b/pkg/controllers/clusterresourceplacement/placement_status_test.go index f53db0361..b625a5b3b 100644 --- a/pkg/controllers/clusterresourceplacement/placement_status_test.go +++ b/pkg/controllers/clusterresourceplacement/placement_status_test.go @@ -4142,7 +4142,7 @@ func TestSetResourcePlacementStatusPerCluster(t *testing.T) { Namespace: "ns-1", }, ObservationTime: metav1.Time{Time: time.Now()}, - TargetClusterObservedGeneration: 2, + TargetClusterObservedGeneration: ptr.To(int64(2)), FirstDiffedObservedTime: metav1.Time{Time: time.Now()}, ObservedDiffs: []fleetv1beta1.PatchDetail{ { @@ -4243,7 +4243,7 @@ func TestSetResourcePlacementStatusPerCluster(t *testing.T) { Namespace: "ns-1", }, ObservationTime: metav1.Time{Time: time.Now()}, - TargetClusterObservedGeneration: 2, + TargetClusterObservedGeneration: ptr.To(int64(2)), FirstDiffedObservedTime: metav1.Time{Time: time.Now()}, ObservedDiffs: []fleetv1beta1.PatchDetail{ { diff --git a/pkg/controllers/workgenerator/controller_integration_test.go b/pkg/controllers/workgenerator/controller_integration_test.go index 1a6a61da7..20c9a214c 100644 --- a/pkg/controllers/workgenerator/controller_integration_test.go +++ b/pkg/controllers/workgenerator/controller_integration_test.go @@ -1892,7 +1892,7 @@ func verifyBindStatusNotAppliedWithTwoPlacements(binding *placementv1beta1.Clust }, ObservationTime: metav1.Time{Time: specificTime}, FirstDiffedObservedTime: metav1.Time{Time: specificTime}, - TargetClusterObservedGeneration: 2, + TargetClusterObservedGeneration: ptr.To(int64(2)), ObservedDiffs: []placementv1beta1.PatchDetail{ configmapPatchDetail, }, @@ -1906,7 +1906,7 @@ func verifyBindStatusNotAppliedWithTwoPlacements(binding *placementv1beta1.Clust Namespace: "svc-namespace", }, ObservationTime: metav1.Time{Time: specificTime}, - TargetClusterObservedGeneration: 1, + TargetClusterObservedGeneration: ptr.To(int64(1)), FirstDiffedObservedTime: metav1.Time{Time: specificTime}, ObservedDiffs: []placementv1beta1.PatchDetail{ servicePatchDetail, @@ -2436,7 +2436,7 @@ func markWorkWithFailedToApplyAndNotAvailable(work *placementv1beta1.Work, hasDi work.Status.ManifestConditions[0].DiffDetails = &placementv1beta1.DiffDetails{ ObservationTime: metav1.Time{Time: specificTime}, FirstDiffedObservedTime: metav1.Time{Time: specificTime}, - ObservedInMemberClusterGeneration: 2, + ObservedInMemberClusterGeneration: ptr.To(int64(2)), ObservedDiffs: []placementv1beta1.PatchDetail{ configmapPatchDetail, }, @@ -2444,7 +2444,7 @@ func markWorkWithFailedToApplyAndNotAvailable(work *placementv1beta1.Work, hasDi work.Status.ManifestConditions[1].DiffDetails = &placementv1beta1.DiffDetails{ ObservationTime: metav1.Time{Time: specificTime}, FirstDiffedObservedTime: metav1.Time{Time: specificTime}, - ObservedInMemberClusterGeneration: 1, + ObservedInMemberClusterGeneration: ptr.To(int64(1)), ObservedDiffs: []placementv1beta1.PatchDetail{ servicePatchDetail, }, diff --git a/pkg/controllers/workgenerator/controller_test.go b/pkg/controllers/workgenerator/controller_test.go index 5fbcc54c7..8c1795ee2 100644 --- a/pkg/controllers/workgenerator/controller_test.go +++ b/pkg/controllers/workgenerator/controller_test.go @@ -1362,7 +1362,7 @@ func TestSetBindingStatus(t *testing.T) { }, DiffDetails: &fleetv1beta1.DiffDetails{ ObservationTime: metav1.NewTime(timeNow), - ObservedInMemberClusterGeneration: 2, + ObservedInMemberClusterGeneration: ptr.To(int64(2)), FirstDiffedObservedTime: metav1.NewTime(timeNow.Add(-time.Hour)), ObservedDiffs: []fleetv1beta1.PatchDetail{ { @@ -1402,7 +1402,7 @@ func TestSetBindingStatus(t *testing.T) { }, DiffDetails: &fleetv1beta1.DiffDetails{ ObservationTime: metav1.NewTime(timeNow), - ObservedInMemberClusterGeneration: 2, + ObservedInMemberClusterGeneration: ptr.To(int64(2)), FirstDiffedObservedTime: metav1.NewTime(timeNow.Add(-time.Second)), ObservedDiffs: []fleetv1beta1.PatchDetail{ { @@ -1468,7 +1468,7 @@ func TestSetBindingStatus(t *testing.T) { Namespace: "svc-namespace", }, ObservationTime: metav1.NewTime(timeNow), - TargetClusterObservedGeneration: 2, + TargetClusterObservedGeneration: ptr.To(int64(2)), FirstDiffedObservedTime: metav1.NewTime(timeNow.Add(-time.Hour)), ObservedDiffs: []fleetv1beta1.PatchDetail{ { @@ -2428,7 +2428,7 @@ func TestExtractDiffedResourcePlacementsFromWork(t *testing.T) { }, DiffDetails: &fleetv1beta1.DiffDetails{ ObservationTime: metav1.NewTime(timeNow), - ObservedInMemberClusterGeneration: 12, + ObservedInMemberClusterGeneration: ptr.To(int64(12)), FirstDiffedObservedTime: metav1.NewTime(timeNow.Add(-time.Hour)), ObservedDiffs: []fleetv1beta1.PatchDetail{ { @@ -2464,7 +2464,7 @@ func TestExtractDiffedResourcePlacementsFromWork(t *testing.T) { Namespace: "svc-namespace", }, ObservationTime: metav1.NewTime(timeNow), - TargetClusterObservedGeneration: 12, + TargetClusterObservedGeneration: ptr.To(int64(12)), FirstDiffedObservedTime: metav1.NewTime(timeNow.Add(-time.Hour)), ObservedDiffs: []fleetv1beta1.PatchDetail{ { @@ -2545,7 +2545,7 @@ func TestExtractDiffedResourcePlacementsFromWork(t *testing.T) { }, DiffDetails: &fleetv1beta1.DiffDetails{ ObservationTime: metav1.NewTime(timeNow), - ObservedInMemberClusterGeneration: 12, + ObservedInMemberClusterGeneration: ptr.To(int64(12)), FirstDiffedObservedTime: metav1.NewTime(timeNow.Add(-time.Hour)), ObservedDiffs: []fleetv1beta1.PatchDetail{ { @@ -2596,7 +2596,7 @@ func TestExtractDiffedResourcePlacementsFromWork(t *testing.T) { }, }, ObservationTime: metav1.NewTime(timeNow), - TargetClusterObservedGeneration: 12, + TargetClusterObservedGeneration: ptr.To(int64(12)), FirstDiffedObservedTime: metav1.NewTime(timeNow.Add(-time.Hour)), ObservedDiffs: []fleetv1beta1.PatchDetail{ {