From 406971106974745b02cf07542d98c45aef2220d1 Mon Sep 17 00:00:00 2001 From: michaelawyu Date: Sun, 29 Sep 2024 21:46:22 +0800 Subject: [PATCH 1/2] Drafted changes --- apis/placement/v1beta1/binding_types.go | 12 + .../v1beta1/clusterresourceplacement_types.go | 109 ++++++- apis/placement/v1beta1/work_types.go | 10 + .../v1beta1/zz_generated.deepcopy.go | 36 ++- ....kubernetes-fleet.io_approvalrequests.yaml | 14 +- ...etes-fleet.io_clusterresourcebindings.yaml | 134 +++++++++ ...es-fleet.io_clusterresourceplacements.yaml | 86 +++++- ....kubernetes-fleet.io_stagedupdateruns.yaml | 278 ++++++++++++++---- ...netes-fleet.io_stagedupdatestrategies.yaml | 16 +- .../placement.kubernetes-fleet.io_works.yaml | 41 +++ 10 files changed, 631 insertions(+), 105 deletions(-) diff --git a/apis/placement/v1beta1/binding_types.go b/apis/placement/v1beta1/binding_types.go index 1beda3f9f..1693fe9f8 100644 --- a/apis/placement/v1beta1/binding_types.go +++ b/apis/placement/v1beta1/binding_types.go @@ -93,6 +93,18 @@ type ResourceBindingStatus struct { // +optional FailedPlacements []FailedResourcePlacement `json:"failedPlacements,omitempty"` + // DriftedOrDiffedPlacements is a list of all the resources that: + // * have drifted from the desired state as kept in the hub cluster, as detected + // by Fleet with the drift detection features enabled; or + // * have configuration differences from the desired state as kept in the hub cluster, as + // found by Fleet during the takeover process, or with the ReportDiff apply strategy. + // + // To control the object size, only the first 100 drifted or diffed resources will be included. + // This field is only meaningful if the `ClusterName` is not empty. + // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=100 + DriftedOrDiffedResourcePlacement []DriftedOrDiffedResourcePlacement `json:"driftedOrDiffedResourcePlacement,omitempty"` + // +patchMergeKey=type // +patchStrategy=merge // +listType=map diff --git a/apis/placement/v1beta1/clusterresourceplacement_types.go b/apis/placement/v1beta1/clusterresourceplacement_types.go index 01c8b4552..2e87ff479 100644 --- a/apis/placement/v1beta1/clusterresourceplacement_types.go +++ b/apis/placement/v1beta1/clusterresourceplacement_types.go @@ -865,12 +865,17 @@ type ResourcePlacementStatus struct { // +kubebuilder:validation:MaxItems=100 FailedPlacements []FailedResourcePlacement `json:"failedPlacements,omitempty"` - // DriftedPlacements is a list of all the resources whose label/annotation and spec fields have changed on the - // target cluster after it is successfully applied. + // DriftedOrDiffedPlacements is a list of all the resources that: + // * have drifted from the desired state as kept in the hub cluster, as detected + // by Fleet with the drift detection features enabled; or + // * have configuration differences from the desired state as kept in the hub cluster, as + // found by Fleet during the takeover process, or with the ReportDiff apply strategy. + // + // To control the object size, only the first 100 drifted or diffed resources will be included. // This field is only meaningful if the `ClusterName` is not empty. // +kubebuilder:validation:Optional // +kubebuilder:validation:MaxItems=100 - DriftedPlacements []DriftedResourcePlacement `json:"driftedPlacements,omitempty"` + DriftedOrDiffedPlacements []DriftedOrDiffedResourcePlacement `json:"driftedPlacements,omitempty"` // Conditions is an array of current observed conditions for ResourcePlacementStatus. // +kubebuilder:validation:Optional @@ -888,36 +893,110 @@ type FailedResourcePlacement struct { Condition metav1.Condition `json:"condition"` } -// DriftedResourcePlacement contains the drifted resource details. -type DriftedResourcePlacement struct { +// DriftedOrDiffedResourceOwnership explains the ownership of a resource with drifts or +// configuration differences. In other words, it helps report whether the resource is under +// the management of Fleet. +// +enum +type DriftedOrDiffedResourceOwnership string + +const ( + // DriftedOrDiffedResourceOwnershipManagedByFleet means the resource is currently managed + // by Fleet. Fleet will attempt to apply manifest from the hub cluster to the resource ( + // if applicable); the resource will be deleted if its corresponding placement has been + // deleted. + DriftedOrDiffedResourceOwnershipManagedByFleet DriftedOrDiffedResourceOwnership = "ManagedByFleet" + + // DriftedOrDiffedResourceOwnershipStandalone means the resource is not managed by Fleet; + // it might be created manually before Fleet starts managing the cluster. Fleet will not + // attempt to apply manifest from the hub cluster to the resource; the resource will also be + // left alone even if its corresponding placement has been deleted. + DriftedOrDiffedResourceOwnershipStandalone DriftedOrDiffedResourceOwnership = "Standalone" +) + +// JSONPatchOp is the operation of a JSON patch. Fleet uses JSON patches to describe drifts +// and configuration differences found in the resources; in the case of Fleet, only +// the Add, Remove, and Replace operations are used. +// +enum +type JSONPatchOp string + +const ( + // JSONPatchOpAdd is the Add operation in a JSON patch. + JSONPatchOpAdd JSONPatchOp = "add" + + // JSONPatchOpRemove is the Remove operation in a JSON patch. + JSONPatchOpRemove JSONPatchOp = "remove" + + // JSONPatchOpReplace is the Replace operation in a JSON patch. + JSONPatchOpReplace JSONPatchOp = "replace" +) + +// ObservedDriftOrDiffDetail contains the details of observed drifts or configuration differences. +// Each detail entry is a JSON patch that specifies how the live state (the state on the member +// cluster side) compares against the desired state (the state kept in the hub cluster manifest). +type ObservedDriftOrDiffDetail struct { + // Op is the JSON patch operation. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=add;remove;replace + Op JSONPatchOp `json:"op"` + + // The JSON path that points to a field that has drifted or has configuration differences. + // +kubebuilder:validation:Required + Path string `json:"path"` + + // The value that the drift or configuration difference entails. + // + // For the JSON patch operation Add and Replace, the value will be the added/replacement value; + // for the JSON patch operation Remove, this field will be empty. + // +kubebuilder:validation:Optional + Value string `json:"value,omitempty"` +} + +// DriftedOrDiffedResourcePlacement contains the details of resources with drifts or configuration +// differences. +type DriftedOrDiffedResourcePlacement struct { // The resource that has drifted. // +kubebuilder:validation:Required ResourceIdentifier `json:",inline"` - // ObservationTime is the time we observe the drift that is described in the observedDifferences field. + // ObservationTime is the time we observe the drifts or configuration differences that are + // described in the observedDifferences field. // +kubebuilder:validation:Required // +kubebuilder:validation:Type=string // +kubebuilder:validation:Format=date-time ObservationTime metav1.Time `json:"observationTime"` // TargetClusterObservedGeneration is the generation of the resource on the target cluster - // that contains this drift. + // that contains the drifts or configuration differences. // +kubebuilder:validation:Required TargetClusterObservedGeneration int64 `json:"targetClusterObservedGeneration"` - // FirstDriftObservedTime is the first time the resource on the target cluster is observed to have - // been different from the resource to be applied from the hub. + // Ownership describes the ownership of the resource with drifts or configuration differences. + // Two options are available: + // * ManagedByFleet: the resource is currently managed by Fleet. Fleet will attempt to apply + // manifest from the hub cluster to the resource (if applicable); the resource will be deleted + // if its corresponding placement has been deleted. + // * Standalone: the resource is not managed by Fleet; it might be created manually before Fleet + // starts managing the cluster. Fleet will not attempt to apply manifest from the hub cluster to + // the resource; the resource will also be left alone even if its corresponding placement has been + // deleted. + Ownership DriftedOrDiffedResourceOwnership `json:"ownership"` + + // FirstDriftOrDiffObservedTime is the first time the resource on the target cluster is + // observed to have drifts or configuration differences. // +kubebuilder:validation:Required // +kubebuilder:validation:Type=string // +kubebuilder:validation:Format=date-time - FirstDriftObservedTime metav1.Time `json:"firstDriftObservedTime"` + FirstDriftOrDiffObservedTime metav1.Time `json:"firstDriftOrDiffObservedTime"` - // ObservedDifferences contains the details of difference between the resource on the target cluster and - // the resource to be applied from the hub. We will truncate the difference details if it exceeds 8192 bytes. - // We will also emit an event with the difference details. - // +kubebuilder:validation:maxLength=8192 + // ObservedDriftsOrDifferences explains the details about the observed drifts or configuration + // differences. Fleet might truncate the details as appropriate to control object size. + // + // Each detail entry is a JSON patch that specifies how the live state (the state on the member + // cluster side) compares against the desired state (the state kept in the hub cluster manifest). + // + // An event about the details will be emitted as well. // +kubebuilder:validation:Optional - ObservedDifferences string `json:"observedDifferences,omitempty"` + ObservedDriftsOrDiffs []ObservedDriftOrDiffDetail `json:"observedDriftsOrDiffs,omitempty"` } // Toleration allows ClusterResourcePlacement to tolerate any taint that matches diff --git a/apis/placement/v1beta1/work_types.go b/apis/placement/v1beta1/work_types.go index de054ca71..4fd8bd9b5 100644 --- a/apis/placement/v1beta1/work_types.go +++ b/apis/placement/v1beta1/work_types.go @@ -123,6 +123,16 @@ type ManifestCondition struct { // Conditions represents the conditions of this resource on spoke cluster // +required Conditions []metav1.Condition `json:"conditions"` + + // ObservedDriftsOrDifferences explains the details about the observed drifts or configuration + // differences. Fleet might truncate the details as appropriate to control object size. + // + // Each detail entry is a JSON patch that specifies how the live state (the state on the member + // cluster side) compares against the desired state (the state kept in the hub cluster manifest). + // + // An event about the details will be emitted as well. + // +kubebuilder:validation:Optional + ObservedDriftsOrDiffs []ObservedDriftOrDiffDetail `json:"observedDriftsOrDiffs,omitempty"` } // +genclient diff --git a/apis/placement/v1beta1/zz_generated.deepcopy.go b/apis/placement/v1beta1/zz_generated.deepcopy.go index 48d0fdc6a..40cdf08a6 100644 --- a/apis/placement/v1beta1/zz_generated.deepcopy.go +++ b/apis/placement/v1beta1/zz_generated.deepcopy.go @@ -615,19 +615,24 @@ func (in *ClusterSelectorTerm) DeepCopy() *ClusterSelectorTerm { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DriftedResourcePlacement) DeepCopyInto(out *DriftedResourcePlacement) { +func (in *DriftedOrDiffedResourcePlacement) DeepCopyInto(out *DriftedOrDiffedResourcePlacement) { *out = *in in.ResourceIdentifier.DeepCopyInto(&out.ResourceIdentifier) in.ObservationTime.DeepCopyInto(&out.ObservationTime) - in.FirstDriftObservedTime.DeepCopyInto(&out.FirstDriftObservedTime) + in.FirstDriftOrDiffObservedTime.DeepCopyInto(&out.FirstDriftOrDiffObservedTime) + if in.ObservedDriftsOrDiffs != nil { + in, out := &in.ObservedDriftsOrDiffs, &out.ObservedDriftsOrDiffs + *out = make([]ObservedDriftOrDiffDetail, len(*in)) + copy(*out, *in) + } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DriftedResourcePlacement. -func (in *DriftedResourcePlacement) DeepCopy() *DriftedResourcePlacement { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DriftedOrDiffedResourcePlacement. +func (in *DriftedOrDiffedResourcePlacement) DeepCopy() *DriftedOrDiffedResourcePlacement { if in == nil { return nil } - out := new(DriftedResourcePlacement) + out := new(DriftedOrDiffedResourcePlacement) in.DeepCopyInto(out) return out } @@ -718,6 +723,21 @@ func (in *NamespacedName) DeepCopy() *NamespacedName { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObservedDriftOrDiffDetail) DeepCopyInto(out *ObservedDriftOrDiffDetail) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObservedDriftOrDiffDetail. +func (in *ObservedDriftOrDiffDetail) DeepCopy() *ObservedDriftOrDiffDetail { + if in == nil { + return nil + } + out := new(ObservedDriftOrDiffDetail) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PlacementPolicy) DeepCopyInto(out *PlacementPolicy) { *out = *in @@ -949,9 +969,9 @@ func (in *ResourcePlacementStatus) DeepCopyInto(out *ResourcePlacementStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.DriftedPlacements != nil { - in, out := &in.DriftedPlacements, &out.DriftedPlacements - *out = make([]DriftedResourcePlacement, len(*in)) + if in.DriftedOrDiffedPlacements != nil { + in, out := &in.DriftedOrDiffedPlacements, &out.DriftedOrDiffedPlacements + *out = make([]DriftedOrDiffedResourcePlacement, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/config/crd/bases/placement.kubernetes-fleet.io_approvalrequests.yaml b/config/crd/bases/placement.kubernetes-fleet.io_approvalrequests.yaml index e258f33a1..1c199f1b8 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_approvalrequests.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_approvalrequests.yaml @@ -21,11 +21,11 @@ spec: schema: openAPIV3Schema: description: |- - ApprovalRequest defines a request for the approval from the user. + ApprovalRequest defines a request for user approval. The request object MUST have the following labels: - - `TargetUpdateRun` which points to the update run that this approval request is for. - - `TargetStage` which is the name of the stage that this approval request is for. - - `IsLatestUpdateRunApproval` which indicates whether this approval request is the latest one related to this update run. + - `TargetUpdateRun`: Points to the update run that this approval request is for. + - `TargetStage`: The name of the stage that this approval request is for. + - `IsLatestUpdateRunApproval`: Indicates whether this approval request is the latest one related to this update run. properties: apiVersion: description: |- @@ -63,12 +63,12 @@ spec: - message: The spec field is immutable rule: self == oldSelf status: - description: The desired state of ApprovalRequest. + description: The observed state of ApprovalRequest. properties: conditions: description: |- - Conditions is an array of current observed conditions for the specific type of post update task. - Known conditions are "Approved", and "ApprovalAccepted". + Conditions is an array of current observed conditions for the specific type of post-update task. + Known conditions are "Approved" and "ApprovalAccepted". items: description: "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis struct is intended for diff --git a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml index 2a09a6ebf..7b53fbc6e 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourcebindings.yaml @@ -823,6 +823,140 @@ spec: x-kubernetes-list-map-keys: - type x-kubernetes-list-type: map + driftedOrDiffedResourcePlacement: + description: |- + DriftedOrDiffedPlacements is a list of all the resources that: + * have drifted from the desired state as kept in the hub cluster, as detected + by Fleet with the drift detection features enabled; or + * have configuration differences from the desired state as kept in the hub cluster, as + found by Fleet during the takeover process, or with the ReportDiff apply strategy. + + + To control the object size, only the first 100 drifted or diffed resources will be included. + This field is only meaningful if the `ClusterName` is not empty. + items: + description: |- + DriftedOrDiffedResourcePlacement contains the details of resources with drifts or configuration + differences. + properties: + envelope: + description: Envelope identifies the envelope object that contains + this resource. + properties: + name: + description: Name of the envelope object. + type: string + namespace: + description: Namespace is the namespace of the envelope + object. Empty if the envelope object is cluster scoped. + type: string + type: + default: ConfigMap + description: Type of the envelope object. + enum: + - ConfigMap + type: string + required: + - name + type: object + firstDriftOrDiffObservedTime: + description: |- + FirstDriftOrDiffObservedTime is the first time the resource on the target cluster is + observed to have drifts or configuration differences. + format: date-time + type: string + group: + description: Group is the group name of the selected resource. + type: string + kind: + description: Kind represents the Kind of the selected resources. + type: string + name: + description: Name of the target resource. + type: string + namespace: + description: Namespace is the namespace of the resource. Empty + if the resource is cluster scoped. + type: string + observationTime: + description: |- + ObservationTime is the time we observe the drifts or configuration differences that are + described in the observedDifferences field. + format: date-time + type: string + observedDriftsOrDiffs: + description: |- + ObservedDriftsOrDifferences explains the details about the observed drifts or configuration + differences. Fleet might truncate the details as appropriate to control object size. + + + Each detail entry is a JSON patch that specifies how the live state (the state on the member + cluster side) compares against the desired state (the state kept in the hub cluster manifest). + + + An event about the details will be emitted as well. + items: + description: |- + ObservedDriftOrDiffDetail contains the details of observed drifts or configuration differences. + Each detail entry is a JSON patch that specifies how the live state (the state on the member + cluster side) compares against the desired state (the state kept in the hub cluster manifest). + properties: + op: + description: Op is the JSON patch operation. + enum: + - add + - remove + - replace + type: string + path: + description: The JSON path that points to a field that + has drifted or has configuration differences. + type: string + value: + description: |- + The value that the drift or configuration difference entails. + + + For the JSON patch operation Add and Replace, the value will be the added/replacement value; + for the JSON patch operation Remove, this field will be empty. + type: string + required: + - op + - path + type: object + type: array + ownership: + description: |- + Ownership describes the ownership of the resource with drifts or configuration differences. + Two options are available: + * ManagedByFleet: the resource is currently managed by Fleet. Fleet will attempt to apply + manifest from the hub cluster to the resource (if applicable); the resource will be deleted + if its corresponding placement has been deleted. + * Standalone: the resource is not managed by Fleet; it might be created manually before Fleet + starts managing the cluster. Fleet will not attempt to apply manifest from the hub cluster to + the resource; the resource will also be left alone even if its corresponding placement has been + deleted. + type: string + targetClusterObservedGeneration: + description: |- + TargetClusterObservedGeneration is the generation of the resource on the target cluster + that contains the drifts or configuration differences. + format: int64 + type: integer + version: + description: Version is the version of the selected resource. + type: string + required: + - firstDriftOrDiffObservedTime + - kind + - name + - observationTime + - ownership + - targetClusterObservedGeneration + - version + type: object + maxItems: 100 + type: array failedPlacements: description: |- FailedPlacements is a list of all the resources failed to be placed to the given cluster or the resource is unavailable. diff --git a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml index 3ef0d05dd..71e4020cf 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml @@ -2261,12 +2261,19 @@ spec: type: array driftedPlacements: description: |- - DriftedPlacements is a list of all the resources whose label/annotation and spec fields have changed on the - target cluster after it is successfully applied. + DriftedOrDiffedPlacements is a list of all the resources that: + * have drifted from the desired state as kept in the hub cluster, as detected + by Fleet with the drift detection features enabled; or + * have configuration differences from the desired state as kept in the hub cluster, as + found by Fleet during the takeover process, or with the ReportDiff apply strategy. + + + To control the object size, only the first 100 drifted or diffed resources will be included. This field is only meaningful if the `ClusterName` is not empty. items: - description: DriftedResourcePlacement contains the drifted - resource details. + description: |- + DriftedOrDiffedResourcePlacement contains the details of resources with drifts or configuration + differences. properties: envelope: description: Envelope identifies the envelope object that @@ -2289,10 +2296,10 @@ spec: required: - name type: object - firstDriftObservedTime: + firstDriftOrDiffObservedTime: description: |- - FirstDriftObservedTime is the first time the resource on the target cluster is observed to have - been different from the resource to be applied from the hub. + FirstDriftOrDiffObservedTime is the first time the resource on the target cluster is + observed to have drifts or configuration differences. format: date-time type: string group: @@ -2310,30 +2317,79 @@ spec: Empty if the resource is cluster scoped. type: string observationTime: - description: ObservationTime is the time we observe the - drift that is described in the observedDifferences field. + description: |- + ObservationTime is the time we observe the drifts or configuration differences that are + described in the observedDifferences field. format: date-time type: string - observedDifferences: + observedDriftsOrDiffs: + description: |- + ObservedDriftsOrDifferences explains the details about the observed drifts or configuration + differences. Fleet might truncate the details as appropriate to control object size. + + + Each detail entry is a JSON patch that specifies how the live state (the state on the member + cluster side) compares against the desired state (the state kept in the hub cluster manifest). + + + An event about the details will be emitted as well. + items: + description: |- + ObservedDriftOrDiffDetail contains the details of observed drifts or configuration differences. + Each detail entry is a JSON patch that specifies how the live state (the state on the member + cluster side) compares against the desired state (the state kept in the hub cluster manifest). + properties: + op: + description: Op is the JSON patch operation. + enum: + - add + - remove + - replace + type: string + path: + description: The JSON path that points to a field + that has drifted or has configuration differences. + type: string + value: + description: |- + The value that the drift or configuration difference entails. + + + For the JSON patch operation Add and Replace, the value will be the added/replacement value; + for the JSON patch operation Remove, this field will be empty. + type: string + required: + - op + - path + type: object + type: array + ownership: description: |- - ObservedDifferences contains the details of difference between the resource on the target cluster and - the resource to be applied from the hub. We will truncate the difference details if it exceeds 8192 bytes. - We will also emit an event with the difference details. + Ownership describes the ownership of the resource with drifts or configuration differences. + Two options are available: + * ManagedByFleet: the resource is currently managed by Fleet. Fleet will attempt to apply + manifest from the hub cluster to the resource (if applicable); the resource will be deleted + if its corresponding placement has been deleted. + * Standalone: the resource is not managed by Fleet; it might be created manually before Fleet + starts managing the cluster. Fleet will not attempt to apply manifest from the hub cluster to + the resource; the resource will also be left alone even if its corresponding placement has been + deleted. type: string targetClusterObservedGeneration: description: |- TargetClusterObservedGeneration is the generation of the resource on the target cluster - that contains this drift. + that contains the drifts or configuration differences. format: int64 type: integer version: description: Version is the version of the selected resource. type: string required: - - firstDriftObservedTime + - firstDriftOrDiffObservedTime - kind - name - observationTime + - ownership - targetClusterObservedGeneration - version type: object diff --git a/config/crd/bases/placement.kubernetes-fleet.io_stagedupdateruns.yaml b/config/crd/bases/placement.kubernetes-fleet.io_stagedupdateruns.yaml index 0e6ad363b..6f4c9bef6 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_stagedupdateruns.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_stagedupdateruns.yaml @@ -21,12 +21,11 @@ spec: schema: openAPIV3Schema: description: |- - StagedUpdateRun defines a stage by stage update run that applies the selected resources by the - corresponding ClusterResourcePlacement to its selected clusters. We remove the resources from the clusters that are - unselected after all the stages explicitly defined in the updateStrategy complete. - Each StagedUpdateRun object corresponds to a single "release" of a certain version of the resources. - The release is abandoned if the StagedUpdateRun object is deleted or the scheduling decision (i.e., the selected clusters) changes. - The name of the StagedUpdateRun needs to conform to [RFC 1123](https://tools.ietf.org/html/rfc1123). + StagedUpdateRun represents a stage by stage update process that applies selected resources to specified clusters. + Resources from unselected clusters are removed after all stages in the update strategy are completed. + Each StagedUpdateRun object corresponds to a single release of a specific resource version. + The release is abandoned if the StagedUpdateRun object is deleted or the scheduling decision changes. + The name of the StagedUpdateRun must conform to RFC 1123. properties: apiVersion: description: |- @@ -51,8 +50,8 @@ spec: placementRef: description: |- A reference to the placement that this update run is applied to. - There can be multiple active update runs for each placement but - it's up to the devOps to make sure they don't conflict with each other. + There can be multiple active update runs for each placement, but + it's up to the DevOps team to ensure they don't conflict with each other. properties: name: description: Name is the name of the referenced placement. @@ -63,14 +62,14 @@ spec: resourceSnapshotIndex: description: |- The resource snapshot index of the selected resources to be updated across clusters. - The index represents a group of resourceSnapshots that includes all the resources a ResourcePlacement selected. + The index represents a group of resource snapshots that includes all the resources a ResourcePlacement selected. type: string stagedRolloutStrategyRef: description: |- The reference to the update strategy that specifies the stages and the sequence - in which the selected resources will be updated on the member clusters. We will compute - the stages according to the referenced strategy when we first start the update run - and record the computed stages in the status field. + in which the selected resources will be updated on the member clusters. The stages + are computed according to the referenced strategy when the update run starts + and recorded in the status field. properties: name: description: Name is the name of the namespaced scope resource. @@ -96,17 +95,65 @@ spec: appliedStrategy: description: |- ApplyStrategy is the apply strategy that the stagedUpdateRun is using. - It is the same as the apply strategy in the CRP when we first start the staged update run. - We will NOT update the apply strategy during the update run even if the apply strategy changes in the CRP. + It is the same as the apply strategy in the CRP when the staged update run starts. + The apply strategy is not updated during the update run even if it changes in the CRP. properties: actionType: - default: AlwaysApply - description: TakeoverAction describes the action to take when - we place the selected resources on the target cluster the first - time. + default: Always + description: |- + WhenToTakeOver determines the action to take when Fleet applies resources to a member + cluster for the first time and finds out that the resource already exists in the cluster. + + + This setting is most relevant in cases where you would like Fleet to manage pre-existing + resources on a member cluster. + + + Available options include: + + + * Always: with this action, Fleet will apply the hub cluster manifests to the member + clusters even if the affected resources already exist. This is the default action. + + + Note that this might lead to fields being overwritten on the member clusters, if they + are specified in the hub cluster manifests. + + + * 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 + 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. + + + Fleet will check for inconsistencies in accordance with the ComparisonOption setting. See also + the comments on the ComparisonOption field for more information. + + + If a diff has been found in a field that is **managed** by Fleet (i.e., the field + **is specified ** in the hub cluster manifest), consider one of the following actions: + * set the field in the member cluster to be of the same value as that in the hub cluster + manifest. + * update the hub cluster manifest so that its field value matches with that in the member + cluster. + * switch to the Always action, which will allow Fleet to overwrite the field with the + value in the hub cluster manifest. + + + If a diff has been found in a field that is **not managed** by Fleet (i.e., the field + **is not specified** in the hub cluster manifest), consider one of the following actions: + * remove the field from the member cluster. + * update the hub cluster manifest so that the field is included in the hub cluster manifest. + + + If appropriate, you may also delete the object from the member cluster; Fleet will recreate + it using the hub cluster manifest. enum: - - AlwaysApply - - ApplyIfNoDiff + - Always + - IfNoDiff type: string allowCoOwnership: description: |- @@ -115,6 +162,48 @@ spec: If true, apply the resource and add fleet as a co-owner. If false, leave the resource unchanged and fail the apply. type: boolean + compareOption: + default: PartialComparison + description: |- + ComparisonOption controls how Fleet compares the desired state of a resource, as kept in + a hub cluster manifest, with the current state of the resource (if applicable) in the + member cluster. + + + Available options are: + + + * PartialComparison: with this option, Fleet will compare only fields that are managed by + Fleet, i.e., the fields that are specified explicitly in the hub cluster manifest. + Unmanaged fields are ignored. This is the default option. + + + * FullComparison: with this option, Fleet will compare all fields of the resource, + even if the fields are absent from the hub cluster manifest. + + + Consider using the PartialComparison option if you would like to: + + + * use the default values for certain fields; or + * let another agent, e.g., HPAs, VPAs, etc., on the member cluster side manage some fields; or + * allow ad-hoc or cluster-specific settings on the member cluster side. + + + To use the FullComparison option, it is recommended that you: + + + * specify all fields as appropriate in the hub cluster, even if you are OK with using default + values; + * make sure that no fields are managed by agents other than Fleet on the member cluster + side, such as HPAs, VPAs, or other controllers. + + + See the Fleet documentation for further explanations and usage examples. + enum: + - PartialComparison + - FullComparison + type: string serverSideApplyConfig: description: ServerSideApplyConfig defines the configuration for server side apply. It is honored only when type is ServerSideApply. @@ -134,19 +223,104 @@ spec: type: default: ClientSideApply description: |- - Type defines the type of strategy to use. Default to ClientSideApply. - Server-side apply is more powerful and flexible than client-side apply. - You SHOULD use server-side apply to safely resolve any potential drift between the - original applied resource version and the current resource on the member cluster. - Read more about the differences between server-side apply and client-side apply: - https://kubernetes.io/docs/reference/using-api/server-side-apply/#comparison-with-client-side-apply. - You can also use ReportDiff to only report the difference between the resource on the member cluster - and the resource to be applied from the hub on all the selected clusters. + Type is the apply strategy to use; it determines how Fleet applies manifests from the + hub cluster to a member cluster. + + + Available options are: + + + * ClientSideApply: Fleet uses three-way merge to apply manifests, similar to how kubectl + performs a client-side apply. This is the default option. + + + Note that this strategy requires that Fleet keep the last applied configuration in the + annoation of an applied resource. If the object gets so large that apply ops can no longer + be executed, Fleet will switch to server-side apply. + + + Use ComparisonOption and WhenToApply settings to control when an apply op can be executed. + + + * ServerSideApply: Fleet uses server-side apply to apply manifests; Fleet itself will + become the field manager for specified fields in the manifests. Specify + ServerSideApplyConfig as appropriate if you would like Fleet to take over field + ownership upon conflicts. This is the recommended option for most scenarios; it might + help reduce object size and safely resolve conflicts between field values. For more + information, please refer to the Kubernetes documentation + (https://kubernetes.io/docs/reference/using-api/server-side-apply/#comparison-with-client-side-apply). + + + Use ComparisonOption and WhenToApply settings to control when an apply op can be executed. + + + * ReportDiff: Fleet will compare the desired state of a resource as kept in the hub cluster + with its current state (if appliable) on the member cluster side, and report any + differences. No actual apply ops would be executed, and resources will be left alone as they + are on the member clusters. + + + Use ComparisonOption setting to control how the difference is calculated. + + + For a comparison between the different strategies and usage examples, refer to the + Fleet documentation. enum: - ClientSideApply - ServerSideApply - ReportDiff type: string + whenToApply: + default: Always + description: |- + WhenToApply controls when Fleet would apply the manifests on the hub cluster to the member + clusters. + + + Available options are: + + + * Always: with this option, Fleet will periodically apply hub cluster manifests + on the member cluster side; this will effectively overwrite any change in the fields + managed by Fleet (i.e., specified in the hub cluster manifest). This is the default + option. + + + Note that this option would revert any ad-hoc changes made on the member cluster side in + the managed fields; if you would like to make temporary edits on the member cluster side + in the managed fields, switch to IfNotDrifted option. Note that changes in unmanaged + fields will be left alone; if you use the FullDiff compare option, such changes will + be reported as drifts. + + + * IfNotDrifted: with this option, Fleet will stop applying hub cluster manifests on + clusters that have drifted from the desired state; apply ops would still continue on + the rest of the clusters. Drifts are calculated using the ComparisonOption, + as explained in the corresponding field. + + + Use this option if you would like Fleet to detect drifts in your multi-cluster setup. + A drift occurs when an agent makes an ad-hoc change on the member cluster side that + makes affected resources deviate from its desired state as kept in the hub cluster; + and this option grants you an opportunity to view the drift details and take actions + accordingly. The drift details will be reported in the CRP status. + + + To fix a drift, you may: + + + * revert the changes manually on the member cluster side + * update the hub cluster manifest; this will trigger Fleet to apply the latest revision + of the manifests, which will overwrite the drifted fields + (if they are managed by Fleet) + * switch to the Always option; this will trigger Fleet to apply the current revision + of the manifests, which will overwrite the drifted fields (if they are managed by Fleet). + * if applicable and necessary, delete the drifted resources on the member cluster side; Fleet + will attempt to re-create them using the hub cluster manifests + enum: + - Always + - IfNotDrifted + type: string type: object conditions: description: |- @@ -225,13 +399,13 @@ spec: x-kubernetes-list-type: map deletionStageStatus: description: |- - DeletionStageStatus list the current status of the deletion stage. The deletion stage is - the stage that removes all the resources from the clusters that are not selected by the + DeletionStageStatus lists the current status of the deletion stage. The deletion stage + removes all the resources from the clusters that are not selected by the current policy after all the update stages are completed. properties: - 'afterStageTaskStatus ': + afterStageTaskStatus: description: |- - The status of the post update tasks that are associated with current stage. + The status of the post-update tasks associated with the current stage. Empty if the stage has not finished updating all the clusters. items: properties: @@ -242,7 +416,7 @@ spec: type: string conditions: description: |- - Conditions is an array of current observed conditions for the specific type of post update task. + Conditions is an array of current observed conditions for the specific type of post-update task. Known conditions are "ApprovalRequestCreated", "WaitTimeElapsed", and "ApprovalRequestApproved". items: description: "Condition contains details for one aspect @@ -319,7 +493,7 @@ spec: - type x-kubernetes-list-type: map type: - description: The type of the post update task. + description: The type of the post-update task. enum: - TimedWait - Approval @@ -351,7 +525,7 @@ spec: conditions: description: |- Conditions is an array of current observed conditions for clusters. Empty if the cluster has not started updating. - Known conditions are "Started,"Succeeded". + Known conditions are "Started", "Succeeded". items: description: "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis @@ -557,10 +731,10 @@ spec: type: string stagedUpdateStrategySnapshot: description: |- - StagedUpdateStrategySnapshot is the snapshot of the StagedUpdateStrategy that we are going to use for the update run. + StagedUpdateStrategySnapshot is the snapshot of the StagedUpdateStrategy used for the update run. The snapshot is immutable during the update run. - We will apply the strategy to the the list of clusters scheduled by the CRP according to the current policy. - The update run will fail to initialize if the strategy fails to produce a valid list of stages in which each selected + The strategy is applied to the list of clusters scheduled by the CRP according to the current policy. + The update run fails to initialize if the strategy fails to produce a valid list of stages where each selected cluster is included in exactly one stage. properties: stages: @@ -569,20 +743,20 @@ spec: items: description: |- StageConfig describes a single update stage. - The clusters in each stage are updated sequentially for now. - We will stop the update if any of the updates fail. + The clusters in each stage are updated sequentially. + The update stops if any of the updates fail. properties: afterStageTasks: description: |- The collection of tasks that each stage needs to complete successfully before moving to the next stage. - Each task is executed in parallel and there can not be more than one task of the same type. + Each task is executed in parallel and there cannot be more than one task of the same type. items: - description: AfterStageTask is the collection of post - stage tasks that ALL need to be completed before we - can move to the next stage. + description: AfterStageTask is the collection of post-stage + tasks that ALL need to be completed before moving to + the next stage. properties: type: - description: The type of the after stage task. + description: The type of the after-stage task. enum: - TimedWait - Approval @@ -591,7 +765,7 @@ spec: default: 1h description: The time to wait after all the clusters in the current stage complete the update before - we move to the next stage. + moving to the next stage. pattern: ^0|([0-9]+(\.[0-9]+)?(s|m|h))+$ type: string required: @@ -671,15 +845,15 @@ spec: type: object stagesStatus: description: |- - StagesStatus list the current updating status of each stage. + StagesStatus lists the current updating status of each stage. The list is empty if the update run is not started or failed to initialize. items: description: StageUpdatingStatus defines the status of the update run in a stage. properties: - 'afterStageTaskStatus ': + afterStageTaskStatus: description: |- - The status of the post update tasks that are associated with current stage. + The status of the post-update tasks associated with the current stage. Empty if the stage has not finished updating all the clusters. items: properties: @@ -690,7 +864,7 @@ spec: type: string conditions: description: |- - Conditions is an array of current observed conditions for the specific type of post update task. + Conditions is an array of current observed conditions for the specific type of post-update task. Known conditions are "ApprovalRequestCreated", "WaitTimeElapsed", and "ApprovalRequestApproved". items: description: "Condition contains details for one aspect @@ -767,7 +941,7 @@ spec: - type x-kubernetes-list-type: map type: - description: The type of the post update task. + description: The type of the post-update task. enum: - TimedWait - Approval @@ -799,7 +973,7 @@ spec: conditions: description: |- Conditions is an array of current observed conditions for clusters. Empty if the cluster has not started updating. - Known conditions are "Started,"Succeeded". + Known conditions are "Started", "Succeeded". items: description: "Condition contains details for one aspect of the current state of this API Resource.\n---\nThis diff --git a/config/crd/bases/placement.kubernetes-fleet.io_stagedupdatestrategies.yaml b/config/crd/bases/placement.kubernetes-fleet.io_stagedupdatestrategies.yaml index 80609e893..63c97c2b3 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_stagedupdatestrategies.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_stagedupdatestrategies.yaml @@ -49,20 +49,20 @@ spec: items: description: |- StageConfig describes a single update stage. - The clusters in each stage are updated sequentially for now. - We will stop the update if any of the updates fail. + The clusters in each stage are updated sequentially. + The update stops if any of the updates fail. properties: afterStageTasks: description: |- The collection of tasks that each stage needs to complete successfully before moving to the next stage. - Each task is executed in parallel and there can not be more than one task of the same type. + Each task is executed in parallel and there cannot be more than one task of the same type. items: - description: AfterStageTask is the collection of post stage - tasks that ALL need to be completed before we can move to - the next stage. + description: AfterStageTask is the collection of post-stage + tasks that ALL need to be completed before moving to the + next stage. properties: type: - description: The type of the after stage task. + description: The type of the after-stage task. enum: - TimedWait - Approval @@ -70,7 +70,7 @@ spec: waitTime: default: 1h description: The time to wait after all the clusters in - the current stage complete the update before we move + the current stage complete the update before moving to the next stage. pattern: ^0|([0-9]+(\.[0-9]+)?(s|m|h))+$ type: string diff --git a/config/crd/bases/placement.kubernetes-fleet.io_works.yaml b/config/crd/bases/placement.kubernetes-fleet.io_works.yaml index fd318bbed..b42126925 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_works.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_works.yaml @@ -772,6 +772,47 @@ spec: required: - ordinal type: object + observedDriftsOrDiffs: + description: |- + ObservedDriftsOrDifferences explains the details about the observed drifts or configuration + differences. Fleet might truncate the details as appropriate to control object size. + + + Each detail entry is a JSON patch that specifies how the live state (the state on the member + cluster side) compares against the desired state (the state kept in the hub cluster manifest). + + + An event about the details will be emitted as well. + items: + description: |- + ObservedDriftOrDiffDetail contains the details of observed drifts or configuration differences. + Each detail entry is a JSON patch that specifies how the live state (the state on the member + cluster side) compares against the desired state (the state kept in the hub cluster manifest). + properties: + op: + description: Op is the JSON patch operation. + enum: + - add + - remove + - replace + type: string + path: + description: The JSON path that points to a field that + has drifted or has configuration differences. + type: string + value: + description: |- + The value that the drift or configuration difference entails. + + + For the JSON patch operation Add and Replace, the value will be the added/replacement value; + for the JSON patch operation Remove, this field will be empty. + type: string + required: + - op + - path + type: object + type: array required: - conditions type: object From 70b4c1105dea6a7e16b9380bed5ffe33d159f107 Mon Sep 17 00:00:00 2001 From: michaelawyu Date: Wed, 9 Oct 2024 13:51:03 +0800 Subject: [PATCH 2/2] Added new fields for diffs --- apis/cluster/v1beta1/zz_generated.deepcopy.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 5 +- apis/placement/v1beta1/binding_types.go | 26 +++- .../v1beta1/clusterresourceplacement_types.go | 137 ++++++++++-------- apis/placement/v1beta1/work_types.go | 24 ++- .../v1beta1/zz_generated.deepcopy.go | 108 ++++++++++---- apis/v1alpha1/zz_generated.deepcopy.go | 2 +- 7 files changed, 204 insertions(+), 100 deletions(-) diff --git a/apis/cluster/v1beta1/zz_generated.deepcopy.go b/apis/cluster/v1beta1/zz_generated.deepcopy.go index 6d06cb15b..6c25f0189 100644 --- a/apis/cluster/v1beta1/zz_generated.deepcopy.go +++ b/apis/cluster/v1beta1/zz_generated.deepcopy.go @@ -10,7 +10,7 @@ Licensed under the MIT license. package v1beta1 import ( - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/apis/placement/v1alpha1/zz_generated.deepcopy.go b/apis/placement/v1alpha1/zz_generated.deepcopy.go index f5c9c8c2d..bd9b21f27 100644 --- a/apis/placement/v1alpha1/zz_generated.deepcopy.go +++ b/apis/placement/v1alpha1/zz_generated.deepcopy.go @@ -10,9 +10,10 @@ Licensed under the MIT license. package v1alpha1 import ( - "go.goms.io/fleet/apis/placement/v1beta1" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" + + "go.goms.io/fleet/apis/placement/v1beta1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/apis/placement/v1beta1/binding_types.go b/apis/placement/v1beta1/binding_types.go index 1693fe9f8..2887283f6 100644 --- a/apis/placement/v1beta1/binding_types.go +++ b/apis/placement/v1beta1/binding_types.go @@ -93,17 +93,29 @@ type ResourceBindingStatus struct { // +optional FailedPlacements []FailedResourcePlacement `json:"failedPlacements,omitempty"` - // DriftedOrDiffedPlacements is a list of all the resources that: - // * have drifted from the desired state as kept in the hub cluster, as detected - // by Fleet with the drift detection features enabled; or - // * have configuration differences from the desired state as kept in the hub cluster, as - // found by Fleet during the takeover process, or with the ReportDiff apply strategy. + // DriftedPlacements is a list of resources that have drifted from their desired states + // kept in the hub cluster, as found by Fleet using the drift detection mechanism. // - // To control the object size, only the first 100 drifted or diffed resources will be included. + // To control the object size, only the first 100 drifted resources will be included. // This field is only meaningful if the `ClusterName` is not empty. // +kubebuilder:validation:Optional // +kubebuilder:validation:MaxItems=100 - DriftedOrDiffedResourcePlacement []DriftedOrDiffedResourcePlacement `json:"driftedOrDiffedResourcePlacement,omitempty"` + DriftedPlacements []DriftedResourcePlacement `json:"driftedPlacements,omitempty"` + + // DiffedPlacements is a list of resources that have configuration differences from their + // corresponding hub cluster manifests. Fleet will report such differences when: + // + // * The CRP uses the ReportDiff apply strategy, which instructs Fleet to compare the hub + // cluster manifests against the live resources without actually performing any apply op; or + // * Fleet finds a pre-existing resource on the member cluster side that does not match its + // hub cluster counterpart, and the CRP has been configured to only take over a resource if + // no configuration differences are found. + // + // To control the object size, only the first 100 diffed resources will be included. + // This field is only meaningful if the `ClusterName` is not empty. + // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=100 + DiffedPlacements []DiffedResourcePlacement `json:"diffedPlacements,omitempty"` // +patchMergeKey=type // +patchStrategy=merge diff --git a/apis/placement/v1beta1/clusterresourceplacement_types.go b/apis/placement/v1beta1/clusterresourceplacement_types.go index 2e87ff479..3132dbfcf 100644 --- a/apis/placement/v1beta1/clusterresourceplacement_types.go +++ b/apis/placement/v1beta1/clusterresourceplacement_types.go @@ -865,17 +865,29 @@ type ResourcePlacementStatus struct { // +kubebuilder:validation:MaxItems=100 FailedPlacements []FailedResourcePlacement `json:"failedPlacements,omitempty"` - // DriftedOrDiffedPlacements is a list of all the resources that: - // * have drifted from the desired state as kept in the hub cluster, as detected - // by Fleet with the drift detection features enabled; or - // * have configuration differences from the desired state as kept in the hub cluster, as - // found by Fleet during the takeover process, or with the ReportDiff apply strategy. + // DriftedPlacements is a list of resources that have drifted from their desired states + // kept in the hub cluster, as found by Fleet using the drift detection mechanism. // - // To control the object size, only the first 100 drifted or diffed resources will be included. + // To control the object size, only the first 100 drifted resources will be included. // This field is only meaningful if the `ClusterName` is not empty. // +kubebuilder:validation:Optional // +kubebuilder:validation:MaxItems=100 - DriftedOrDiffedPlacements []DriftedOrDiffedResourcePlacement `json:"driftedPlacements,omitempty"` + DriftedPlacements []DriftedResourcePlacement `json:"driftedPlacements,omitempty"` + + // DiffedPlacements is a list of resources that have configuration differences from their + // corresponding hub cluster manifests. Fleet will report such differences when: + // + // * The CRP uses the ReportDiff apply strategy, which instructs Fleet to compare the hub + // cluster manifests against the live resources without actually performing any apply op; or + // * Fleet finds a pre-existing resource on the member cluster side that does not match its + // hub cluster counterpart, and the CRP has been configured to only take over a resource if + // no configuration differences are found. + // + // To control the object size, only the first 100 diffed resources will be included. + // This field is only meaningful if the `ClusterName` is not empty. + // +kubebuilder:validation:Optional + // +kubebuilder:validation:MaxItems=100 + DiffedPlacements []DiffedResourcePlacement `json:"diffedPlacements,omitempty"` // Conditions is an array of current observed conditions for ResourcePlacementStatus. // +kubebuilder:validation:Optional @@ -893,26 +905,6 @@ type FailedResourcePlacement struct { Condition metav1.Condition `json:"condition"` } -// DriftedOrDiffedResourceOwnership explains the ownership of a resource with drifts or -// configuration differences. In other words, it helps report whether the resource is under -// the management of Fleet. -// +enum -type DriftedOrDiffedResourceOwnership string - -const ( - // DriftedOrDiffedResourceOwnershipManagedByFleet means the resource is currently managed - // by Fleet. Fleet will attempt to apply manifest from the hub cluster to the resource ( - // if applicable); the resource will be deleted if its corresponding placement has been - // deleted. - DriftedOrDiffedResourceOwnershipManagedByFleet DriftedOrDiffedResourceOwnership = "ManagedByFleet" - - // DriftedOrDiffedResourceOwnershipStandalone means the resource is not managed by Fleet; - // it might be created manually before Fleet starts managing the cluster. Fleet will not - // attempt to apply manifest from the hub cluster to the resource; the resource will also be - // left alone even if its corresponding placement has been deleted. - DriftedOrDiffedResourceOwnershipStandalone DriftedOrDiffedResourceOwnership = "Standalone" -) - // JSONPatchOp is the operation of a JSON patch. Fleet uses JSON patches to describe drifts // and configuration differences found in the resources; in the case of Fleet, only // the Add, Remove, and Replace operations are used. @@ -930,10 +922,9 @@ const ( JSONPatchOpReplace JSONPatchOp = "replace" ) -// ObservedDriftOrDiffDetail contains the details of observed drifts or configuration differences. -// Each detail entry is a JSON patch that specifies how the live state (the state on the member -// cluster side) compares against the desired state (the state kept in the hub cluster manifest). -type ObservedDriftOrDiffDetail struct { +// JSONPatchDetail describes a JSON patch that explains an observed configuration drift or +// difference. +type JSONPatchDetail struct { // Op is the JSON patch operation. // +kubebuilder:validation:Required // +kubebuilder:validation:Enum=add;remove;replace @@ -943,60 +934,90 @@ type ObservedDriftOrDiffDetail struct { // +kubebuilder:validation:Required Path string `json:"path"` - // The value that the drift or configuration difference entails. + // The current value at the JSON path, i.e., the value before the JSON patch operation. // - // For the JSON patch operation Add and Replace, the value will be the added/replacement value; - // for the JSON patch operation Remove, this field will be empty. + // For the JSON patch operation Add, this field will be left empty. + // + // Note that this field is kept for informational purposes only; it is not a required part of the + // JSON patch; see RFC 6902 for more information. // +kubebuilder:validation:Optional - Value string `json:"value,omitempty"` + CurrentValue string `json:"value,omitempty"` + + // The value associated with the JSON path, i.e., the value after the JSON patch operation. + // + // For the JSON patch operation Remove, this field will be left empty. + // +kubebuilder:validation:Optional + Value string `json:"newValue,omitempty"` +} + +// DriftedResourcePlacement contains the details of a resource with configuration drifts. +type DriftedResourcePlacement struct { + // The resource that has drifted. + // +kubebuilder:validation:Required + ResourceIdentifier `json:",inline"` + + // ObservationTime is the time when we observe the configuration drifts for the resource. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Format=date-time + ObservationTime metav1.Time `json:"observationTime"` + + // TargetClusterObservedGeneration is the generation of the resource on the target cluster + // that contains the configuration drifts. + // +kubebuilder:validation:Required + TargetClusterObservedGeneration int64 `json:"targetClusterObservedGeneration"` + + // FirstDriftedObservedTime is the first time the resource on the target cluster is + // observed to have configuration drifts. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Format=date-time + FirstDriftedObservedTime metav1.Time `json:"firstDriftedObservedTime"` + + // ObservedDrifts are the details about the found configuration drifts. Note that + // Fleet might truncate the details as appropriate to control the object size. + // + // Each detail entry is a JSON patch that specifies how the live state (the state on the member + // cluster side) compares against the desired state (the state kept in the hub cluster manifest). + // + // An event about the details will be emitted as well. + // +kubebuilder:validation:Optional + ObservedDrifts []JSONPatchDetail `json:"observedDrifts,omitempty"` } -// DriftedOrDiffedResourcePlacement contains the details of resources with drifts or configuration -// differences. -type DriftedOrDiffedResourcePlacement struct { +// DiffedResourcePlacement contains the details of a resource with configuration differences. +type DiffedResourcePlacement struct { // The resource that has drifted. // +kubebuilder:validation:Required ResourceIdentifier `json:",inline"` - // ObservationTime is the time we observe the drifts or configuration differences that are - // described in the observedDifferences field. + // ObservationTime is the time when we observe the configuration differences for the resource. // +kubebuilder:validation:Required // +kubebuilder:validation:Type=string // +kubebuilder:validation:Format=date-time ObservationTime metav1.Time `json:"observationTime"` // TargetClusterObservedGeneration is the generation of the resource on the target cluster - // that contains the drifts or configuration differences. + // that contains the configuration differences. // +kubebuilder:validation:Required TargetClusterObservedGeneration int64 `json:"targetClusterObservedGeneration"` - // Ownership describes the ownership of the resource with drifts or configuration differences. - // Two options are available: - // * ManagedByFleet: the resource is currently managed by Fleet. Fleet will attempt to apply - // manifest from the hub cluster to the resource (if applicable); the resource will be deleted - // if its corresponding placement has been deleted. - // * Standalone: the resource is not managed by Fleet; it might be created manually before Fleet - // starts managing the cluster. Fleet will not attempt to apply manifest from the hub cluster to - // the resource; the resource will also be left alone even if its corresponding placement has been - // deleted. - Ownership DriftedOrDiffedResourceOwnership `json:"ownership"` - - // FirstDriftOrDiffObservedTime is the first time the resource on the target cluster is - // observed to have drifts or configuration differences. + // FirstDiffedObservedTime is the first time the resource on the target cluster is + // observed to have configuration differences. // +kubebuilder:validation:Required // +kubebuilder:validation:Type=string // +kubebuilder:validation:Format=date-time - FirstDriftOrDiffObservedTime metav1.Time `json:"firstDriftOrDiffObservedTime"` + FirstDiffedObservedTime metav1.Time `json:"firstDiffedObservedTime"` - // ObservedDriftsOrDifferences explains the details about the observed drifts or configuration - // differences. Fleet might truncate the details as appropriate to control object size. + // ObservedDiffs are the details about the found configuration differences. Note that + // Fleet might truncate the details as appropriate to control the object size. // // Each detail entry is a JSON patch that specifies how the live state (the state on the member // cluster side) compares against the desired state (the state kept in the hub cluster manifest). // // An event about the details will be emitted as well. // +kubebuilder:validation:Optional - ObservedDriftsOrDiffs []ObservedDriftOrDiffDetail `json:"observedDriftsOrDiffs,omitempty"` + ObservedDiffs []JSONPatchDetail `json:"observedDrifts,omitempty"` } // Toleration allows ClusterResourcePlacement to tolerate any taint that matches diff --git a/apis/placement/v1beta1/work_types.go b/apis/placement/v1beta1/work_types.go index 4fd8bd9b5..8c670f4a6 100644 --- a/apis/placement/v1beta1/work_types.go +++ b/apis/placement/v1beta1/work_types.go @@ -124,15 +124,31 @@ type ManifestCondition struct { // +required Conditions []metav1.Condition `json:"conditions"` - // ObservedDriftsOrDifferences explains the details about the observed drifts or configuration - // differences. Fleet might truncate the details as appropriate to control object size. + // ObservedDrifts explains the details about the observed configuration drifts. + // Fleet might truncate the details as appropriate to control object size. // // Each detail entry is a JSON patch that specifies how the live state (the state on the member // cluster side) compares against the desired state (the state kept in the hub cluster manifest). // - // An event about the details will be emitted as well. + // Note that configuration drifts can only occur on a resource if it is currently owned by + // Fleet and its corresponding placement is set to use the ClientSideApply or ServerSideApply + // apply strategy. In other words, ObservedDrifts and ObservedDiffs will not be populated + // at the same time. // +kubebuilder:validation:Optional - ObservedDriftsOrDiffs []ObservedDriftOrDiffDetail `json:"observedDriftsOrDiffs,omitempty"` + ObservedDrifts []JSONPatchDetail `json:"observedDriftsOrDiffs,omitempty"` + + // ObservedDiffs explains the details about the observed configuration differences. + // Fleet might truncate the details as appropriate to control object size. + // + // Each detail entry is a JSON patch that specifies how the live state (the state on the member + // cluster side) compares against the desired state (the state kept in the hub cluster manifest). + // + // Note that configuration differences can only occur on a resource if it is not currently owned + // by Fleet (i.e., it is a pre-existing resource that needs to be taken over), or if its + // corresponding placement is set to use the ReportDiff apply strategy. In other words, + // ObservedDiffs and ObservedDrifts will not be populated at the same time. + // +kubebuilder:validation:Optional + ObservedDiffs []JSONPatchDetail `json:"observedDiffs,omitempty"` } // +genclient diff --git a/apis/placement/v1beta1/zz_generated.deepcopy.go b/apis/placement/v1beta1/zz_generated.deepcopy.go index 40cdf08a6..0c7f34f28 100644 --- a/apis/placement/v1beta1/zz_generated.deepcopy.go +++ b/apis/placement/v1beta1/zz_generated.deepcopy.go @@ -10,7 +10,7 @@ Licensed under the MIT license. package v1beta1 import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" ) @@ -615,24 +615,47 @@ func (in *ClusterSelectorTerm) DeepCopy() *ClusterSelectorTerm { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DriftedOrDiffedResourcePlacement) DeepCopyInto(out *DriftedOrDiffedResourcePlacement) { +func (in *DiffedResourcePlacement) DeepCopyInto(out *DiffedResourcePlacement) { *out = *in in.ResourceIdentifier.DeepCopyInto(&out.ResourceIdentifier) in.ObservationTime.DeepCopyInto(&out.ObservationTime) - in.FirstDriftOrDiffObservedTime.DeepCopyInto(&out.FirstDriftOrDiffObservedTime) - if in.ObservedDriftsOrDiffs != nil { - in, out := &in.ObservedDriftsOrDiffs, &out.ObservedDriftsOrDiffs - *out = make([]ObservedDriftOrDiffDetail, len(*in)) + in.FirstDiffedObservedTime.DeepCopyInto(&out.FirstDiffedObservedTime) + if in.ObservedDiffs != nil { + in, out := &in.ObservedDiffs, &out.ObservedDiffs + *out = make([]JSONPatchDetail, len(*in)) copy(*out, *in) } } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DriftedOrDiffedResourcePlacement. -func (in *DriftedOrDiffedResourcePlacement) DeepCopy() *DriftedOrDiffedResourcePlacement { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiffedResourcePlacement. +func (in *DiffedResourcePlacement) DeepCopy() *DiffedResourcePlacement { if in == nil { return nil } - out := new(DriftedOrDiffedResourcePlacement) + out := new(DiffedResourcePlacement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DriftedResourcePlacement) DeepCopyInto(out *DriftedResourcePlacement) { + *out = *in + in.ResourceIdentifier.DeepCopyInto(&out.ResourceIdentifier) + in.ObservationTime.DeepCopyInto(&out.ObservationTime) + in.FirstDriftedObservedTime.DeepCopyInto(&out.FirstDriftedObservedTime) + if in.ObservedDrifts != nil { + in, out := &in.ObservedDrifts, &out.ObservedDrifts + *out = make([]JSONPatchDetail, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DriftedResourcePlacement. +func (in *DriftedResourcePlacement) DeepCopy() *DriftedResourcePlacement { + if in == nil { + return nil + } + out := new(DriftedResourcePlacement) in.DeepCopyInto(out) return out } @@ -669,6 +692,21 @@ func (in *FailedResourcePlacement) DeepCopy() *FailedResourcePlacement { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JSONPatchDetail) DeepCopyInto(out *JSONPatchDetail) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONPatchDetail. +func (in *JSONPatchDetail) DeepCopy() *JSONPatchDetail { + if in == nil { + return nil + } + out := new(JSONPatchDetail) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Manifest) DeepCopyInto(out *Manifest) { *out = *in @@ -696,6 +734,16 @@ func (in *ManifestCondition) DeepCopyInto(out *ManifestCondition) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.ObservedDrifts != nil { + in, out := &in.ObservedDrifts, &out.ObservedDrifts + *out = make([]JSONPatchDetail, len(*in)) + copy(*out, *in) + } + if in.ObservedDiffs != nil { + in, out := &in.ObservedDiffs, &out.ObservedDiffs + *out = make([]JSONPatchDetail, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManifestCondition. @@ -723,21 +771,6 @@ func (in *NamespacedName) DeepCopy() *NamespacedName { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ObservedDriftOrDiffDetail) DeepCopyInto(out *ObservedDriftOrDiffDetail) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObservedDriftOrDiffDetail. -func (in *ObservedDriftOrDiffDetail) DeepCopy() *ObservedDriftOrDiffDetail { - if in == nil { - return nil - } - out := new(ObservedDriftOrDiffDetail) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PlacementPolicy) DeepCopyInto(out *PlacementPolicy) { *out = *in @@ -894,6 +927,20 @@ func (in *ResourceBindingStatus) DeepCopyInto(out *ResourceBindingStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.DriftedPlacements != nil { + in, out := &in.DriftedPlacements, &out.DriftedPlacements + *out = make([]DriftedResourcePlacement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DiffedPlacements != nil { + in, out := &in.DiffedPlacements, &out.DiffedPlacements + *out = make([]DiffedResourcePlacement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]v1.Condition, len(*in)) @@ -969,9 +1016,16 @@ func (in *ResourcePlacementStatus) DeepCopyInto(out *ResourcePlacementStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - if in.DriftedOrDiffedPlacements != nil { - in, out := &in.DriftedOrDiffedPlacements, &out.DriftedOrDiffedPlacements - *out = make([]DriftedOrDiffedResourcePlacement, len(*in)) + if in.DriftedPlacements != nil { + in, out := &in.DriftedPlacements, &out.DriftedPlacements + *out = make([]DriftedResourcePlacement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DiffedPlacements != nil { + in, out := &in.DiffedPlacements, &out.DiffedPlacements + *out = make([]DiffedResourcePlacement, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index 0d4061551..ac4844274 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -11,7 +11,7 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" )