diff --git a/apis/cluster/v1beta1/zz_generated.deepcopy.go b/apis/cluster/v1beta1/zz_generated.deepcopy.go index 5ce0e1367..d0e850ca0 100644 --- a/apis/cluster/v1beta1/zz_generated.deepcopy.go +++ b/apis/cluster/v1beta1/zz_generated.deepcopy.go @@ -21,7 +21,7 @@ limitations under the License. package v1beta1 import ( - v1 "k8s.io/api/core/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 df9f5e6d7..6d1656d18 100644 --- a/apis/placement/v1alpha1/zz_generated.deepcopy.go +++ b/apis/placement/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ package v1alpha1 import ( "github.com/kubefleet-dev/kubefleet/apis/placement/v1beta1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" ) diff --git a/apis/placement/v1beta1/clusterresourceplacement_types.go b/apis/placement/v1beta1/clusterresourceplacement_types.go index 5a6678d19..f33254773 100644 --- a/apis/placement/v1beta1/clusterresourceplacement_types.go +++ b/apis/placement/v1beta1/clusterresourceplacement_types.go @@ -539,6 +539,11 @@ type RolloutStrategy struct { // DeleteStrategy configures the deletion behavior when the ClusterResourcePlacement is deleted. // +kubebuilder:validation:Optional DeleteStrategy *DeleteStrategy `json:"deleteStrategy,omitempty"` + + // ReportBackStrategy describes how to report back the status of applied resources on the member cluster. + // +kubebuilder:validation:Optional + // +kubebuilder:validation:XValidation:rule="(self == null) || (self.type == 'Mirror' ? size(self.destination) != 0 : true)",message="when reportBackStrategy.type is 'Mirror', a destination must be specified" + ReportBackStrategy *ReportBackStrategy `json:"reportBackStrategy,omitempty"` } // ApplyStrategy describes when and how to apply the selected resource to the target cluster. @@ -1480,6 +1485,66 @@ const ( DeletePropagationPolicyDelete DeletePropagationPolicy = "Delete" ) +type ReportBackStrategyType string + +const ( + // ReportBackStrategyTypeDisabled disables status back-reporting from the member clusters. + ReportBackStrategyTypeDisabled ReportBackStrategyType = "Disabled" + + // ReportBackStrategyTypeMirror enables status back-reporting by + // copying the status fields verbatim to some destination on the hub cluster side. + ReportBackStrategyTypeMirror ReportBackStrategyType = "Mirror" +) + +type ReportBackDestination string + +const ( + // ReportBackDestinationOriginalResource implies the status fields will be copied verbatim to the + // the original resource on the hub cluster side. This is only performed when the placement object has a + // scheduling policy that selects exactly one member cluster (i.e., a pickFixed scheduling policy with + // exactly one cluster name, or a pickN scheduling policy with the numberOfClusters field set to 1). + ReportBackDestinationOriginalResource ReportBackDestination = "OriginalResource" + + // ReportBackDestinationWorkAPI implies the status fields will be copied verbatim via the Work API + // on the hub cluster side. Users may look up the status of a specific resource applied to a specific + // member cluster by inspecting the corresponding Work object on the hub cluster side. + ReportBackDestinationWorkAPI ReportBackDestination = "WorkAPI" +) + +// ReportBackStrategy describes how to report back the resource status from member clusters. +type ReportBackStrategy struct { + // Type dictates the type of the report back strategy to use. + // + // Available options include: + // + // * Disabled: status back-reporting is disabled. This is the default behavior. + // + // * Mirror: status back-reporting is enabled by copying the status fields verbatim to + // a destination on the hub cluster side; see the Destination field for more information. + // + // +kubebuilder:default=Disabled + // +kubebuilder:validation:Enum=Disabled;Mirror + // +kubebuilder:validation:Required + Type ReportBackStrategyType `json:"type"` + + // Destination dictates where to copy the status fields to when the report back strategy type is Mirror. + // + // Available options include: + // + // * OriginalResource: the status fields will be copied verbatim to the original resource on the hub cluster side. + // This is only performed when the placement object has a scheduling policy that selects exactly one member cluster + // (i.e., a pickFixed scheduling policy with exactly one cluster name, or a pickN scheduling policy with the numberOfClusters + // field set to 1). + // + // * WorkAPI: the status fields will be copied verbatim via the Work API on the hub cluster side. Users may look up + // the status of a specific resource applied to a specific member cluster by inspecting the corresponding Work object + // on the hub cluster side. This is the default behavior. + // + // +kubebuilder:validation:Enum=OriginalResource;WorkAPI + // +kubebuilder:validation:Optional + Destination *ReportBackDestination `json:"destination,omitempty"` +} + // ClusterResourcePlacementList contains a list of ClusterResourcePlacement. // +kubebuilder:resource:scope="Cluster" // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/apis/placement/v1beta1/work_types.go b/apis/placement/v1beta1/work_types.go index 4781e72ff..f4592f3d7 100644 --- a/apis/placement/v1beta1/work_types.go +++ b/apis/placement/v1beta1/work_types.go @@ -68,6 +68,10 @@ type WorkSpec struct { // and is owned by other appliers. // +optional ApplyStrategy *ApplyStrategy `json:"applyStrategy,omitempty"` + + // ReportBackStrategy describes how to report back the status of applied resources on the member cluster. + // +optional + ReportBackStrategy *ReportBackStrategy `json:"reportBackStrategy,omitempty"` } // WorkloadTemplate represents the manifest workload to be deployed on spoke cluster @@ -142,7 +146,7 @@ type DriftDetails struct { // +kubebuilder:validation:Required ObservedInMemberClusterGeneration int64 `json:"observedInMemberClusterGeneration"` - // FirsftDriftedObservedTime is the timestamp when the drift was first detected. + // FirstDriftedObservedTime is the timestamp when the drift was first detected. // // +kubebuilder:validation:Required // +kubebuilder:validation:Type=string @@ -176,7 +180,7 @@ type DiffDetails struct { // +kubebuilder:validation:Optional ObservedInMemberClusterGeneration *int64 `json:"observedInMemberClusterGeneration"` - // FirsftDiffedObservedTime is the timestamp when the configuration difference + // FirstDiffedObservedTime is the timestamp when the configuration difference // was first detected. // // +kubebuilder:validation:Required @@ -196,6 +200,19 @@ type DiffDetails struct { ObservedDiffs []PatchDetail `json:"observedDiffs,omitempty"` } +type BackReportedStatus struct { + // +kubebuilder:validation:EmbeddedResource + // +kubebuilder:pruning:PreserveUnknownFields + ObservedStatus runtime.RawExtension `json:"observedStatus,omitempty"` + + // ObservationTime is the timestamp when the status was last back reported. + // + // +kubebuilder:validation:Required + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Format=date-time + ObservationTime metav1.Time `json:"observationTime"` +} + // ManifestCondition represents the conditions of the resources deployed on // spoke cluster. type ManifestCondition struct { @@ -228,6 +245,11 @@ type ManifestCondition struct { // // +kubebuilder:validation:Optional DiffDetails *DiffDetails `json:"diffDetails,omitempty"` + + // BackReportedStatus is the status reported back from the member cluster (if applicable). + // + // +kubebuilder:validation:Optional + BackReportedStatus *BackReportedStatus `json:"backReportedStatus,omitempty"` } // +genclient diff --git a/apis/placement/v1beta1/zz_generated.deepcopy.go b/apis/placement/v1beta1/zz_generated.deepcopy.go index 792a0e81a..873227f17 100644 --- a/apis/placement/v1beta1/zz_generated.deepcopy.go +++ b/apis/placement/v1beta1/zz_generated.deepcopy.go @@ -21,7 +21,7 @@ limitations under the License. package v1beta1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" ) @@ -314,6 +314,23 @@ func (in *ApprovalRequestStatus) DeepCopy() *ApprovalRequestStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BackReportedStatus) DeepCopyInto(out *BackReportedStatus) { + *out = *in + in.ObservedStatus.DeepCopyInto(&out.ObservedStatus) + in.ObservationTime.DeepCopyInto(&out.ObservationTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackReportedStatus. +func (in *BackReportedStatus) DeepCopy() *BackReportedStatus { + if in == nil { + return nil + } + out := new(BackReportedStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterAffinity) DeepCopyInto(out *ClusterAffinity) { *out = *in @@ -1491,6 +1508,11 @@ func (in *ManifestCondition) DeepCopyInto(out *ManifestCondition) { *out = new(DiffDetails) (*in).DeepCopyInto(*out) } + if in.BackReportedStatus != nil { + in, out := &in.BackReportedStatus, &out.BackReportedStatus + *out = new(BackReportedStatus) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManifestCondition. @@ -1896,6 +1918,26 @@ func (in *PropertySorter) DeepCopy() *PropertySorter { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReportBackStrategy) DeepCopyInto(out *ReportBackStrategy) { + *out = *in + if in.Destination != nil { + in, out := &in.Destination, &out.Destination + *out = new(ReportBackDestination) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportBackStrategy. +func (in *ReportBackStrategy) DeepCopy() *ReportBackStrategy { + if in == nil { + return nil + } + out := new(ReportBackStrategy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ResourceBinding) DeepCopyInto(out *ResourceBinding) { *out = *in @@ -2541,6 +2583,11 @@ func (in *RolloutStrategy) DeepCopyInto(out *RolloutStrategy) { *out = new(DeleteStrategy) **out = **in } + if in.ReportBackStrategy != nil { + in, out := &in.ReportBackStrategy, &out.ReportBackStrategy + *out = new(ReportBackStrategy) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStrategy. @@ -3073,6 +3120,11 @@ func (in *WorkSpec) DeepCopyInto(out *WorkSpec) { *out = new(ApplyStrategy) (*in).DeepCopyInto(*out) } + if in.ReportBackStrategy != nil { + in, out := &in.ReportBackStrategy, &out.ReportBackStrategy + *out = new(ReportBackStrategy) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkSpec. diff --git a/apis/v1alpha1/zz_generated.deepcopy.go b/apis/v1alpha1/zz_generated.deepcopy.go index 85550ca19..27a862c43 100644 --- a/apis/v1alpha1/zz_generated.deepcopy.go +++ b/apis/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ package v1alpha1 import ( corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml index 186898038..ec0caf947 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_clusterresourceplacements.yaml @@ -1947,6 +1947,51 @@ spec: - Delete type: string type: object + reportBackStrategy: + description: ReportBackStrategy describes how to report back the + status of applied resources on the member cluster. + properties: + destination: + description: |- + Destination dictates where to copy the status fields to when the report back strategy type is Mirror. + + Available options include: + + * OriginalResource: the status fields will be copied verbatim to the original resource on the hub cluster side. + This is only performed when the placement object has a scheduling policy that selects exactly one member cluster + (i.e., a pickFixed scheduling policy with exactly one cluster name, or a pickN scheduling policy with the numberOfClusters + field set to 1). + + * WorkAPI: the status fields will be copied verbatim via the Work API on the hub cluster side. Users may look up + the status of a specific resource applied to a specific member cluster by inspecting the corresponding Work object + on the hub cluster side. This is the default behavior. + enum: + - OriginalResource + - WorkAPI + type: string + type: + default: Disabled + description: |- + Type dictates the type of the report back strategy to use. + + Available options include: + + * Disabled: status back-reporting is disabled. This is the default behavior. + + * Mirror: status back-reporting is enabled by copying the status fields verbatim to + a destination on the hub cluster side; see the Destination field for more information. + enum: + - Disabled + - Mirror + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: when reportBackStrategy.type is 'Mirror', a destination + must be specified + rule: '(self == null) || (self.type == ''Mirror'' ? size(self.destination) + != 0 : true)' rollingUpdate: description: Rolling update config params. Present only if RolloutStrategyType = RollingUpdate. diff --git a/config/crd/bases/placement.kubernetes-fleet.io_resourceplacements.yaml b/config/crd/bases/placement.kubernetes-fleet.io_resourceplacements.yaml index 743ad2355..92488b409 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_resourceplacements.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_resourceplacements.yaml @@ -882,6 +882,51 @@ spec: - Delete type: string type: object + reportBackStrategy: + description: ReportBackStrategy describes how to report back the + status of applied resources on the member cluster. + properties: + destination: + description: |- + Destination dictates where to copy the status fields to when the report back strategy type is Mirror. + + Available options include: + + * OriginalResource: the status fields will be copied verbatim to the original resource on the hub cluster side. + This is only performed when the placement object has a scheduling policy that selects exactly one member cluster + (i.e., a pickFixed scheduling policy with exactly one cluster name, or a pickN scheduling policy with the numberOfClusters + field set to 1). + + * WorkAPI: the status fields will be copied verbatim via the Work API on the hub cluster side. Users may look up + the status of a specific resource applied to a specific member cluster by inspecting the corresponding Work object + on the hub cluster side. This is the default behavior. + enum: + - OriginalResource + - WorkAPI + type: string + type: + default: Disabled + description: |- + Type dictates the type of the report back strategy to use. + + Available options include: + + * Disabled: status back-reporting is disabled. This is the default behavior. + + * Mirror: status back-reporting is enabled by copying the status fields verbatim to + a destination on the hub cluster side; see the Destination field for more information. + enum: + - Disabled + - Mirror + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: when reportBackStrategy.type is 'Mirror', a destination + must be specified + rule: '(self == null) || (self.type == ''Mirror'' ? size(self.destination) + != 0 : true)' rollingUpdate: description: Rolling update config params. Present only if RolloutStrategyType = RollingUpdate. diff --git a/config/crd/bases/placement.kubernetes-fleet.io_works.yaml b/config/crd/bases/placement.kubernetes-fleet.io_works.yaml index 66cec7ac2..e2220df73 100644 --- a/config/crd/bases/placement.kubernetes-fleet.io_works.yaml +++ b/config/crd/bases/placement.kubernetes-fleet.io_works.yaml @@ -531,6 +531,46 @@ spec: - Never type: string type: object + reportBackStrategy: + description: ReportBackStrategy describes how to report back the status + of applied resources on the member cluster. + properties: + destination: + description: |- + Destination dictates where to copy the status fields to when the report back strategy type is Mirror. + + Available options include: + + * OriginalResource: the status fields will be copied verbatim to the original resource on the hub cluster side. + This is only performed when the placement object has a scheduling policy that selects exactly one member cluster + (i.e., a pickFixed scheduling policy with exactly one cluster name, or a pickN scheduling policy with the numberOfClusters + field set to 1). + + * WorkAPI: the status fields will be copied verbatim via the Work API on the hub cluster side. Users may look up + the status of a specific resource applied to a specific member cluster by inspecting the corresponding Work object + on the hub cluster side. This is the default behavior. + enum: + - OriginalResource + - WorkAPI + type: string + type: + default: Disabled + description: |- + Type dictates the type of the report back strategy to use. + + Available options include: + + * Disabled: status back-reporting is disabled. This is the default behavior. + + * Mirror: status back-reporting is enabled by copying the status fields verbatim to + a destination on the hub cluster side; see the Destination field for more information. + enum: + - Disabled + - Mirror + type: string + required: + - type + type: object workload: description: Workload represents the manifest workload to be deployed on spoke cluster @@ -624,6 +664,22 @@ spec: ManifestCondition represents the conditions of the resources deployed on spoke cluster. properties: + backReportedStatus: + description: BackReportedStatus is the status reported back + from the member cluster (if applicable). + properties: + observationTime: + description: ObservationTime is the timestamp when the status + was last back reported. + format: date-time + type: string + observedStatus: + type: object + x-kubernetes-embedded-resource: true + x-kubernetes-preserve-unknown-fields: true + required: + - observationTime + type: object conditions: description: Conditions represents the conditions of this resource on spoke cluster @@ -695,7 +751,7 @@ spec: properties: firstDiffedObservedTime: description: |- - FirsftDiffedObservedTime is the timestamp when the configuration difference + FirstDiffedObservedTime is the timestamp when the configuration difference was first detected. format: date-time type: string @@ -765,8 +821,8 @@ spec: at the same time. properties: firstDriftedObservedTime: - description: FirsftDriftedObservedTime is the timestamp - when the drift was first detected. + description: FirstDriftedObservedTime is the timestamp when + the drift was first detected. format: date-time type: string observationTime: diff --git a/test/apis/v1alpha1/zz_generated.deepcopy.go b/test/apis/v1alpha1/zz_generated.deepcopy.go index 143bdee7b..081bec913 100644 --- a/test/apis/v1alpha1/zz_generated.deepcopy.go +++ b/test/apis/v1alpha1/zz_generated.deepcopy.go @@ -21,7 +21,7 @@ limitations under the License. package v1alpha1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" )