diff --git a/pkg/apis/core/v1alpha1/extensions_federatedobject.go b/pkg/apis/core/v1alpha1/extensions_federatedobject.go index af48d8f5..d62ab2f1 100644 --- a/pkg/apis/core/v1alpha1/extensions_federatedobject.go +++ b/pkg/apis/core/v1alpha1/extensions_federatedobject.go @@ -17,17 +17,19 @@ limitations under the License. package v1alpha1 import ( + "encoding/json" "reflect" "sort" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" ) // Placement extensions -// GetPlacementUnion returns the union of all clusters listed under the Placement field of the FederatedObject. -func (o *FederatedObject) GetPlacementUnion() sets.Set[string] { +// GetPlacementUnion returns the union of all clusters listed under the Placement field of the GenericFederatedObject. +func (o *GenericFederatedObject) GetPlacementUnion() sets.Set[string] { set := sets.New[string]() for _, placement := range o.Spec.Placements { for _, cluster := range placement.Placement { @@ -39,7 +41,7 @@ func (o *FederatedObject) GetPlacementUnion() sets.Set[string] { // GetControllerPlacement returns the slice containing all the ClusterPlacements from a given controller. Returns nil if // the controller is not present. -func (o *FederatedObject) GetControllerPlacement(controller string) []ClusterReference { +func (o *GenericFederatedObject) GetControllerPlacement(controller string) []ClusterReference { for _, placement := range o.Spec.Placements { if placement.Controller == controller { return placement.Placement @@ -49,8 +51,8 @@ func (o *FederatedObject) GetControllerPlacement(controller string) []ClusterRef } // SetControllerPlacement sets the ClusterPlacements for a given controller. If clusterNames is nil or empty, the previous -// placement for the given controller will be deleted. Returns a bool indicating if the FederatedObject has changed. -func (o *FederatedObject) SetControllerPlacement(controller string, clusterNames []string) bool { +// placement for the given controller will be deleted. Returns a bool indicating if the GenericFederatedObject has changed. +func (o *GenericFederatedObject) SetControllerPlacement(controller string, clusterNames []string) bool { if len(clusterNames) == 0 { return o.DeleteControllerPlacement(controller) } @@ -88,9 +90,9 @@ func (o *FederatedObject) SetControllerPlacement(controller string, clusterNames return false } -// DeleteClusterPlacement deletes a controller's placement, returning a bool to indicate if the FederatedObject has +// DeleteClusterPlacement deletes a controller's placement, returning a bool to indicate if the GenericFederatedObject has // changed. -func (o *FederatedObject) DeleteControllerPlacement(controller string) bool { +func (o *GenericFederatedObject) DeleteControllerPlacement(controller string) bool { oldPlacementIdx := -1 for i := range o.Spec.Placements { if o.Spec.Placements[i].Controller == controller { @@ -107,6 +109,17 @@ func (o *FederatedObject) DeleteControllerPlacement(controller string) bool { return true } +func (o *GenericFederatedObject) GetTemplateGVK() (schema.GroupVersionKind, error) { + type partialTypeMetadata struct { + metav1.TypeMeta `json:",inline"` + } + metadata := &partialTypeMetadata{} + if err := json.Unmarshal(o.Spec.Template.Raw, metadata); err != nil { + return schema.GroupVersionKind{}, nil + } + return metadata.GroupVersionKind(), nil +} + // Follower extensions func (l *LeaderReference) GroupKind() schema.GroupKind { diff --git a/pkg/apis/core/v1alpha1/types_federatedobject.go b/pkg/apis/core/v1alpha1/types_federatedobject.go index 60078f16..62fa2a58 100644 --- a/pkg/apis/core/v1alpha1/types_federatedobject.go +++ b/pkg/apis/core/v1alpha1/types_federatedobject.go @@ -22,6 +22,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Schema shared by both FederatedObject and ClusterFederatedObject. type GenericFederatedObject struct { metav1.TypeMeta `json:",inline"` diff --git a/pkg/apis/core/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/core/v1alpha1/zz_generated.deepcopy.go index 2f09791b..250629be 100644 --- a/pkg/apis/core/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/core/v1alpha1/zz_generated.deepcopy.go @@ -935,6 +935,14 @@ func (in *GenericFederatedObject) DeepCopy() *GenericFederatedObject { return out } +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GenericFederatedObject) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GenericFederatedObjectCondition) DeepCopyInto(out *GenericFederatedObjectCondition) { *out = *in diff --git a/pkg/util/fedobjectadapters/adapters.go b/pkg/util/fedobjectadapters/adapters.go new file mode 100644 index 00000000..583dce3e --- /dev/null +++ b/pkg/util/fedobjectadapters/adapters.go @@ -0,0 +1,97 @@ +package fedobjectadapters + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + fedcorev1a1 "github.com/kubewharf/kubeadmiral/pkg/apis/core/v1alpha1" + fedcorev1a1client "github.com/kubewharf/kubeadmiral/pkg/client/clientset/versioned/typed/core/v1alpha1" + fedcorev1a1listers "github.com/kubewharf/kubeadmiral/pkg/client/listers/core/v1alpha1" +) + +func convertToGeneric[Type *fedcorev1a1.ClusterFederatedObject | *fedcorev1a1.FederatedObject]( + obj Type, err error, +) (*fedcorev1a1.GenericFederatedObject, error) { + return (*fedcorev1a1.GenericFederatedObject)(obj), err +} + +func GetFromLister( + fedObjectLister fedcorev1a1listers.FederatedObjectLister, + clusterFedObjectLister fedcorev1a1listers.ClusterFederatedObjectLister, + namespace, name string, +) (*fedcorev1a1.GenericFederatedObject, error) { + if namespace == "" { + return convertToGeneric(clusterFedObjectLister.Get(name)) + } else { + return convertToGeneric(fedObjectLister.FederatedObjects(namespace).Get(name)) + } +} + +func Create( + ctx context.Context, + fedObjectClient fedcorev1a1client.FederatedObjectsGetter, + clusterFedObjectClient fedcorev1a1client.ClusterFederatedObjectsGetter, + obj *fedcorev1a1.GenericFederatedObject, + opts metav1.CreateOptions, +) (*fedcorev1a1.GenericFederatedObject, error) { + if obj.GetNamespace() == "" { + return convertToGeneric( + clusterFedObjectClient.ClusterFederatedObjects().Create(ctx, (*fedcorev1a1.ClusterFederatedObject)(obj), opts), + ) + } else { + return convertToGeneric( + fedObjectClient.FederatedObjects(obj.GetNamespace()).Create(ctx, (*fedcorev1a1.FederatedObject)(obj), opts), + ) + } +} + +func Update( + ctx context.Context, + fedObjectClient fedcorev1a1client.FederatedObjectsGetter, + clusterFedObjectClient fedcorev1a1client.ClusterFederatedObjectsGetter, + obj *fedcorev1a1.GenericFederatedObject, + opts metav1.UpdateOptions, +) (*fedcorev1a1.GenericFederatedObject, error) { + if obj.GetNamespace() == "" { + return convertToGeneric( + clusterFedObjectClient.ClusterFederatedObjects().Update(ctx, (*fedcorev1a1.ClusterFederatedObject)(obj), opts), + ) + } else { + return convertToGeneric( + fedObjectClient.FederatedObjects(obj.GetNamespace()).Update(ctx, (*fedcorev1a1.FederatedObject)(obj), opts), + ) + } +} + +func UpdateStatus( + ctx context.Context, + fedObjectClient fedcorev1a1client.FederatedObjectsGetter, + clusterFedObjectClient fedcorev1a1client.ClusterFederatedObjectsGetter, + obj *fedcorev1a1.GenericFederatedObject, + opts metav1.UpdateOptions, +) (*fedcorev1a1.GenericFederatedObject, error) { + if obj.GetNamespace() == "" { + return convertToGeneric( + clusterFedObjectClient.ClusterFederatedObjects().UpdateStatus(ctx, (*fedcorev1a1.ClusterFederatedObject)(obj), opts), + ) + } else { + return convertToGeneric( + fedObjectClient.FederatedObjects(obj.GetNamespace()).UpdateStatus(ctx, (*fedcorev1a1.FederatedObject)(obj), opts), + ) + } +} + +func Delete( + ctx context.Context, + fedObjectClient fedcorev1a1client.FederatedObjectsGetter, + clusterFedObjectClient fedcorev1a1client.ClusterFederatedObjectsGetter, + namespace, name string, + opts metav1.DeleteOptions, +) error { + if namespace == "" { + return clusterFedObjectClient.ClusterFederatedObjects().Delete(ctx, name, opts) + } else { + return fedObjectClient.FederatedObjects(namespace).Delete(ctx, name, opts) + } +}