diff --git a/pkg/util/helper/unstructured.go b/pkg/util/helper/unstructured.go index 50d684f5b..4c5a1dac6 100644 --- a/pkg/util/helper/unstructured.go +++ b/pkg/util/helper/unstructured.go @@ -1,6 +1,9 @@ package helper import ( + appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -37,3 +40,63 @@ func ConvertToResourceBinding(obj *unstructured.Unstructured) (*workv1alpha1.Res return typedObj, nil } + +// ConvertToPod converts a Pod object from unstructured to typed. +func ConvertToPod(obj *unstructured.Unstructured) (*corev1.Pod, error) { + typedObj := &corev1.Pod{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil { + return nil, err + } + + return typedObj, nil +} + +// ConvertToReplicaSet converts a ReplicaSet object from unstructured to typed. +func ConvertToReplicaSet(obj *unstructured.Unstructured) (*appsv1.ReplicaSet, error) { + typedObj := &appsv1.ReplicaSet{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil { + return nil, err + } + + return typedObj, nil +} + +// ConvertToDeployment converts a Deployment object from unstructured to typed. +func ConvertToDeployment(obj *unstructured.Unstructured) (*appsv1.Deployment, error) { + typedObj := &appsv1.Deployment{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil { + return nil, err + } + + return typedObj, nil +} + +// ConvertToDaemonSet converts a DaemonSet object from unstructured to typed. +func ConvertToDaemonSet(obj *unstructured.Unstructured) (*appsv1.DaemonSet, error) { + typedObj := &appsv1.DaemonSet{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil { + return nil, err + } + + return typedObj, nil +} + +// ConvertToStatefulSet converts a StatefulSet object from unstructured to typed. +func ConvertToStatefulSet(obj *unstructured.Unstructured) (*appsv1.StatefulSet, error) { + typedObj := &appsv1.StatefulSet{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil { + return nil, err + } + + return typedObj, nil +} + +// ConvertToJob converts a Job object from unstructured to typed. +func ConvertToJob(obj *unstructured.Unstructured) (*batchv1.Job, error) { + typedObj := &batchv1.Job{} + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil { + return nil, err + } + + return typedObj, nil +} diff --git a/pkg/util/objectwatcher/retain.go b/pkg/util/objectwatcher/retain.go index 4cb4fba17..ee2f85c7e 100644 --- a/pkg/util/objectwatcher/retain.go +++ b/pkg/util/objectwatcher/retain.go @@ -4,8 +4,10 @@ import ( "fmt" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" "github.com/karmada-io/karmada/pkg/util" + "github.com/karmada-io/karmada/pkg/util/helper" ) /* @@ -50,16 +52,35 @@ func RetainClusterFields(desiredObj, clusterObj *unstructured.Unstructured) erro } func retainPodFields(desiredObj, clusterObj *unstructured.Unstructured) error { - nodeName, ok, err := unstructured.NestedString(clusterObj.Object, "spec", "nodeName") + desiredPod, err := helper.ConvertToPod(desiredObj) if err != nil { - return fmt.Errorf("error retrieving nodeName from cluster pod: %w", err) + return fmt.Errorf("failed to convert desiredPod from unstructured object: %v", err) } - if ok && nodeName != "" { - err := unstructured.SetNestedField(desiredObj.Object, nodeName, "spec", "nodeName") - if err != nil { - return fmt.Errorf("error setting nodeName for pod: %w", err) + + clusterPod, err := helper.ConvertToPod(clusterObj) + if err != nil { + return fmt.Errorf("failed to convert clusterPod from unstructured object: %v", err) + } + + desiredPod.Spec.NodeName = clusterPod.Spec.NodeName + desiredPod.Spec.ServiceAccountName = clusterPod.Spec.ServiceAccountName + desiredPod.Spec.Volumes = clusterPod.Spec.Volumes + // retain volumeMounts in each container + for _, clusterContainer := range clusterPod.Spec.Containers { + for desiredIndex, desiredContainer := range desiredPod.Spec.Containers { + if desiredContainer.Name == clusterContainer.Name { + desiredPod.Spec.Containers[desiredIndex].VolumeMounts = clusterContainer.VolumeMounts + break + } } } + + unCastObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(desiredPod) + if err != nil { + return fmt.Errorf("failed to transform Pod: %v", err) + } + + desiredObj.Object = unCastObj return nil }