diff --git a/pkg/controllers/multiclusterservice/mcs_controller_test.go b/pkg/controllers/multiclusterservice/mcs_controller_test.go index 738022942574..0008277a0559 100644 --- a/pkg/controllers/multiclusterservice/mcs_controller_test.go +++ b/pkg/controllers/multiclusterservice/mcs_controller_test.go @@ -265,6 +265,10 @@ func TestPropagateMultiClusterService(t *testing.T) { { name: "Propagate to one ready cluster", mcs: &networkingv1alpha1.MultiClusterService{ + TypeMeta: metav1.TypeMeta{ + Kind: "MultiClusterService", + APIVersion: networkingv1alpha1.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-mcs", Namespace: "default", @@ -353,6 +357,10 @@ func TestPropagateMultiClusterService(t *testing.T) { { name: "Propagate to multiple ready clusters", mcs: &networkingv1alpha1.MultiClusterService{ + TypeMeta: metav1.TypeMeta{ + Kind: "MultiClusterService", + APIVersion: networkingv1alpha1.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-mcs", Namespace: "default", @@ -401,6 +409,10 @@ func TestPropagateMultiClusterService(t *testing.T) { { name: "Mixed cluster readiness and API support", mcs: &networkingv1alpha1.MultiClusterService{ + TypeMeta: metav1.TypeMeta{ + Kind: "MultiClusterService", + APIVersion: networkingv1alpha1.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-mcs", Namespace: "default", diff --git a/pkg/controllers/namespace/namespace_sync_controller_test.go b/pkg/controllers/namespace/namespace_sync_controller_test.go index 409d5fb56854..48f04bec6265 100644 --- a/pkg/controllers/namespace/namespace_sync_controller_test.go +++ b/pkg/controllers/namespace/namespace_sync_controller_test.go @@ -102,6 +102,10 @@ func TestController_Reconcile(t *testing.T) { { name: "Namespace should be synced", namespace: &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-namespace", }, @@ -120,6 +124,10 @@ func TestController_Reconcile(t *testing.T) { { name: "Namespace should not be synced", namespace: &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "kube-system", }, @@ -144,6 +152,10 @@ func TestController_Reconcile(t *testing.T) { { name: "Namespace should not be synced - kube-public", namespace: &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "kube-public", }, @@ -247,8 +259,15 @@ func TestController_buildWorks(t *testing.T) { _ = policyv1alpha1.Install(scheme) namespace := &corev1.Namespace{ + TypeMeta: metav1.TypeMeta{ + Kind: "Namespace", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-namespace", + Labels: map[string]string{ + "overridden": "false", + }, }, } @@ -272,7 +291,7 @@ func TestController_buildWorks(t *testing.T) { Spec: policyv1alpha1.OverrideSpec{ ResourceSelectors: []policyv1alpha1.ResourceSelector{ { - APIVersion: "v1", + APIVersion: corev1.SchemeGroupVersion.String(), Kind: "Namespace", Name: "test-namespace", }, diff --git a/pkg/detector/detector_test.go b/pkg/detector/detector_test.go index 10f77fa06343..aa5c328ace99 100644 --- a/pkg/detector/detector_test.go +++ b/pkg/detector/detector_test.go @@ -532,6 +532,10 @@ func TestOnUpdate(t *testing.T) { { name: "core v1 object", oldObj: &corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pod", Namespace: "default", @@ -541,6 +545,10 @@ func TestOnUpdate(t *testing.T) { }, }, newObj: &corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pod", Namespace: "default", @@ -1023,7 +1031,7 @@ func TestApplyClusterPolicy(t *testing.T) { } } -//Helper Functions +// Helper Functions // setupTestScheme creates a runtime scheme with necessary types for testing func setupTestScheme() *runtime.Scheme { diff --git a/pkg/resourceinterpreter/customized/declarative/luavm/lua_test.go b/pkg/resourceinterpreter/customized/declarative/luavm/lua_test.go index 76fb64f5cb58..e17e955ce42c 100644 --- a/pkg/resourceinterpreter/customized/declarative/luavm/lua_test.go +++ b/pkg/resourceinterpreter/customized/declarative/luavm/lua_test.go @@ -286,13 +286,17 @@ func TestAggregateDeploymentStatus(t *testing.T) { oldDeploy := &appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ Kind: "Deployment", - APIVersion: "apps/v1", + APIVersion: appsv1.SchemeGroupVersion.String(), }, + Status: appsv1.DeploymentStatus{Replicas: 0, ReadyReplicas: 1, UpdatedReplicas: 0, AvailableReplicas: 0, UnavailableReplicas: 0}, } - oldDeploy.Status = appsv1.DeploymentStatus{ - Replicas: 0, ReadyReplicas: 1, UpdatedReplicas: 0, AvailableReplicas: 0, UnavailableReplicas: 0} - newDeploy := &appsv1.Deployment{Status: appsv1.DeploymentStatus{Replicas: 0, ReadyReplicas: 3, UpdatedReplicas: 0, AvailableReplicas: 0, UnavailableReplicas: 0}} + newDeploy := &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + Status: appsv1.DeploymentStatus{Replicas: 0, ReadyReplicas: 3, UpdatedReplicas: 0, AvailableReplicas: 0, UnavailableReplicas: 0}} oldObj, _ := helper.ToUnstructured(oldDeploy) newObj, _ := helper.ToUnstructured(newDeploy) @@ -339,10 +343,13 @@ func TestAggregateDeploymentStatus(t *testing.T) { func TestHealthDeploymentStatus(t *testing.T) { var cnt int32 = 2 newDeploy := &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, Spec: appsv1.DeploymentSpec{ Replicas: &cnt, }, - ObjectMeta: metav1.ObjectMeta{ Generation: 1, }, diff --git a/pkg/resourceinterpreter/customized/webhook/configmanager/manager_test.go b/pkg/resourceinterpreter/customized/webhook/configmanager/manager_test.go index 5ff52d90cf0b..36c8ffd616e7 100644 --- a/pkg/resourceinterpreter/customized/webhook/configmanager/manager_test.go +++ b/pkg/resourceinterpreter/customized/webhook/configmanager/manager_test.go @@ -194,6 +194,10 @@ func TestUpdateConfiguration(t *testing.T) { name: "valid configurations", configs: []runtime.Object{ &configv1alpha1.ResourceInterpreterWebhookConfiguration{ + TypeMeta: metav1.TypeMeta{ + Kind: "ResourceInterpreterWebhookConfiguration", + APIVersion: configv1alpha1.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{Name: "config1"}, Webhooks: []configv1alpha1.ResourceInterpreterWebhook{ {Name: "webhook1"}, diff --git a/pkg/resourceinterpreter/default/native/aggregatestatus_test.go b/pkg/resourceinterpreter/default/native/aggregatestatus_test.go index e4bb77d65e7c..41f6f2e84c26 100644 --- a/pkg/resourceinterpreter/default/native/aggregatestatus_test.go +++ b/pkg/resourceinterpreter/default/native/aggregatestatus_test.go @@ -49,8 +49,19 @@ func TestAggregateDeploymentStatus(t *testing.T) { {ClusterName: "member2", Status: raw, Applied: true}, } - oldDeploy := &appsv1.Deployment{} - newDeploy := &appsv1.Deployment{Status: appsv1.DeploymentStatus{Replicas: 2, ReadyReplicas: 2, UpdatedReplicas: 2, AvailableReplicas: 2, UnavailableReplicas: 0}} + oldDeploy := &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + } + newDeploy := &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, + Status: appsv1.DeploymentStatus{Replicas: 2, ReadyReplicas: 2, UpdatedReplicas: 2, AvailableReplicas: 2, UnavailableReplicas: 0}, + } oldObj, _ := helper.ToUnstructured(oldDeploy) newObj, _ := helper.ToUnstructured(newDeploy) @@ -95,15 +106,31 @@ func TestAggregateServiceStatus(t *testing.T) { {ClusterName: "member1", Status: rawLB, Applied: true}, } - serviceClusterIP := &corev1.Service{Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeClusterIP}} - serviceNodePort := &corev1.Service{Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeNodePort}} - serviceExternalName := &corev1.Service{Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeExternalName}} + serviceClusterIP := &corev1.Service{ + TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: corev1.SchemeGroupVersion.String()}, + Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeClusterIP}, + } + serviceNodePort := &corev1.Service{ + TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: corev1.SchemeGroupVersion.String()}, + Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeNodePort}, + } + serviceExternalName := &corev1.Service{ + TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: corev1.SchemeGroupVersion.String()}, + Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeExternalName}, + } objServiceClusterIP, _ := helper.ToUnstructured(serviceClusterIP) objServiceNodePort, _ := helper.ToUnstructured(serviceNodePort) objServiceExternalName, _ := helper.ToUnstructured(serviceExternalName) - oldServiceLoadBalancer := &corev1.Service{Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeLoadBalancer}} - newServiceLoadBalancer := &corev1.Service{Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeLoadBalancer}, Status: corev1.ServiceStatus{LoadBalancer: corev1.LoadBalancerStatus{Ingress: []corev1.LoadBalancerIngress{{IP: "8.8.8.8", Hostname: "member1"}}}}} + oldServiceLoadBalancer := &corev1.Service{ + TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: corev1.SchemeGroupVersion.String()}, + Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeLoadBalancer}, + } + newServiceLoadBalancer := &corev1.Service{ + TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: corev1.SchemeGroupVersion.String()}, + Spec: corev1.ServiceSpec{Type: corev1.ServiceTypeLoadBalancer}, + Status: corev1.ServiceStatus{LoadBalancer: corev1.LoadBalancerStatus{Ingress: []corev1.LoadBalancerIngress{{IP: "8.8.8.8", Hostname: "member1"}}}}, + } oldObjServiceLoadBalancer, _ := helper.ToUnstructured(oldServiceLoadBalancer) newObjServiceLoadBalancer, _ := helper.ToUnstructured(newServiceLoadBalancer) @@ -160,8 +187,13 @@ func TestAggregateIngressStatus(t *testing.T) { {ClusterName: "member1", Status: raw, Applied: true}, } - oldIngress := &networkingv1.Ingress{} - newIngress := &networkingv1.Ingress{Status: networkingv1.IngressStatus{LoadBalancer: networkingv1.IngressLoadBalancerStatus{Ingress: []networkingv1.IngressLoadBalancerIngress{{IP: "8.8.8.8", Hostname: "member1"}}}}} + oldIngress := &networkingv1.Ingress{ + TypeMeta: metav1.TypeMeta{Kind: "Ingress", APIVersion: networkingv1.SchemeGroupVersion.String()}, + } + newIngress := &networkingv1.Ingress{ + TypeMeta: metav1.TypeMeta{Kind: "Ingress", APIVersion: networkingv1.SchemeGroupVersion.String()}, + Status: networkingv1.IngressStatus{LoadBalancer: networkingv1.IngressLoadBalancerStatus{Ingress: []networkingv1.IngressLoadBalancerIngress{{IP: "8.8.8.8", Hostname: "member1"}}}}, + } oldObj, _ := helper.ToUnstructured(oldIngress) newObj, _ := helper.ToUnstructured(newIngress) @@ -222,12 +254,20 @@ func TestAggregateJobStatus(t *testing.T) { {ClusterName: "member2", Status: rawWithJobFailed, Applied: true}, } - oldJob := &batchv1.Job{} - newJob := &batchv1.Job{Status: batchv1.JobStatus{Active: 0, Succeeded: 2, Failed: 0, StartTime: &startTime, CompletionTime: &completionTime, Conditions: []batchv1.JobCondition{{Type: batchv1.JobComplete, Status: corev1.ConditionTrue, Reason: "Completed", Message: "Job completed"}}}} + oldJob := &batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + } + newJob := &batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: batchv1.JobStatus{Active: 0, Succeeded: 2, Failed: 0, StartTime: &startTime, CompletionTime: &completionTime, Conditions: []batchv1.JobCondition{{Type: batchv1.JobComplete, Status: corev1.ConditionTrue, Reason: "Completed", Message: "Job completed"}}}, + } oldObj, _ := helper.ToUnstructured(oldJob) newObj, _ := helper.ToUnstructured(newJob) - newJobWithJobFailed := &batchv1.Job{Status: batchv1.JobStatus{Active: 0, Succeeded: 1, Failed: 1, StartTime: &startTime, CompletionTime: &completionTime, Conditions: []batchv1.JobCondition{{Type: batchv1.JobFailed, Status: corev1.ConditionTrue, Reason: "JobFailed", Message: "Job executed failed in member clusters member2"}}}} + newJobWithJobFailed := &batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: batchv1.JobStatus{Active: 0, Succeeded: 1, Failed: 1, StartTime: &startTime, CompletionTime: &completionTime, Conditions: []batchv1.JobCondition{{Type: batchv1.JobFailed, Status: corev1.ConditionTrue, Reason: "JobFailed", Message: "Job executed failed in member clusters member2"}}}, + } newObjWithJobFailed, _ := helper.ToUnstructured(newJobWithJobFailed) tests := []struct { @@ -280,8 +320,13 @@ func TestAggregateDaemonSetStatus(t *testing.T) { {ClusterName: "member2", Status: raw, Applied: true}, } - oldDaemonSet := &appsv1.DaemonSet{} - newDaemonSet := &appsv1.DaemonSet{Status: appsv1.DaemonSetStatus{CurrentNumberScheduled: 2, NumberMisscheduled: 0, DesiredNumberScheduled: 2, NumberReady: 2, UpdatedNumberScheduled: 2, NumberAvailable: 2, NumberUnavailable: 0}} + oldDaemonSet := &appsv1.DaemonSet{ + TypeMeta: metav1.TypeMeta{Kind: "DaemonSet", APIVersion: appsv1.SchemeGroupVersion.String()}, + } + newDaemonSet := &appsv1.DaemonSet{ + TypeMeta: metav1.TypeMeta{Kind: "DaemonSet", APIVersion: appsv1.SchemeGroupVersion.String()}, + Status: appsv1.DaemonSetStatus{CurrentNumberScheduled: 2, NumberMisscheduled: 0, DesiredNumberScheduled: 2, NumberReady: 2, UpdatedNumberScheduled: 2, NumberAvailable: 2, NumberUnavailable: 0}, + } oldObj, _ := helper.ToUnstructured(oldDaemonSet) newObj, _ := helper.ToUnstructured(newDaemonSet) @@ -325,8 +370,13 @@ func TestAggregateStatefulSetStatus(t *testing.T) { {ClusterName: "member2", Status: raw, Applied: true}, } - oldStatefulSet := &appsv1.StatefulSet{} - newStatefulSet := &appsv1.StatefulSet{Status: appsv1.StatefulSetStatus{Replicas: 2, ReadyReplicas: 2, UpdatedReplicas: 2, AvailableReplicas: 2, CurrentReplicas: 2}} + oldStatefulSet := &appsv1.StatefulSet{ + TypeMeta: metav1.TypeMeta{Kind: "StatefulSet", APIVersion: appsv1.SchemeGroupVersion.String()}, + } + newStatefulSet := &appsv1.StatefulSet{ + TypeMeta: metav1.TypeMeta{Kind: "StatefulSet", APIVersion: appsv1.SchemeGroupVersion.String()}, + Status: appsv1.StatefulSetStatus{Replicas: 2, ReadyReplicas: 2, UpdatedReplicas: 2, AvailableReplicas: 2, CurrentReplicas: 2}, + } oldObj, _ := helper.ToUnstructured(oldStatefulSet) newObj, _ := helper.ToUnstructured(newStatefulSet) @@ -447,10 +497,15 @@ func TestAggregatePodStatus(t *testing.T) { }, }, } - newInitContainerObj, _ := helper.ToUnstructured(&corev1.Pod{Status: corev1.PodStatus{ - InitContainerStatuses: newInitContainerStatuses1, - Phase: corev1.PodPending, - }}) + newInitContainerObj, _ := helper.ToUnstructured(&corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + Status: corev1.PodStatus{ + InitContainerStatuses: newInitContainerStatuses1, + Phase: corev1.PodPending, + }}) initContainerStatusMap1 := map[string]interface{}{ "initContainerStatuses": []corev1.ContainerStatus{newInitContainerStatuses1[0], newInitContainerStatuses1[1]}, "phase": corev1.PodPending, @@ -460,11 +515,21 @@ func TestAggregatePodStatus(t *testing.T) { {ClusterName: "member1", Status: initContainerRaw1, Applied: true}, } - curObj, _ := helper.ToUnstructured(&corev1.Pod{}) - newObj, _ := helper.ToUnstructured(&corev1.Pod{Status: corev1.PodStatus{ - ContainerStatuses: newContainerStatuses1, - Phase: corev1.PodRunning, - }}) + curObj, _ := helper.ToUnstructured(&corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + }) + newObj, _ := helper.ToUnstructured(&corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + Status: corev1.PodStatus{ + ContainerStatuses: newContainerStatuses1, + Phase: corev1.PodRunning, + }}) statusMap1 := map[string]interface{}{ "containerStatuses": []corev1.ContainerStatus{containerStatuses1[0]}, @@ -554,10 +619,15 @@ func TestAggregatePodStatus(t *testing.T) { }, } - newPodFailed := &corev1.Pod{Status: corev1.PodStatus{ - ContainerStatuses: newContainerStatuses2, - Phase: corev1.PodPending, - }} + newPodFailed := &corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + Status: corev1.PodStatus{ + ContainerStatuses: newContainerStatuses2, + Phase: corev1.PodPending, + }} newObjFailed, _ := helper.ToUnstructured(newPodFailed) containerStatusesRunning := []corev1.ContainerStatus{ @@ -604,10 +674,15 @@ func TestAggregatePodStatus(t *testing.T) { {ClusterName: "member2", Status: nil, Applied: true}, } - failObj, _ := helper.ToUnstructured(&corev1.Pod{Status: corev1.PodStatus{ - ContainerStatuses: []corev1.ContainerStatus{containerStatusesRunning[0], newContainerStatusesFail[0]}, - Phase: corev1.PodFailed, - }}) + failObj, _ := helper.ToUnstructured(&corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + Status: corev1.PodStatus{ + ContainerStatuses: []corev1.ContainerStatus{containerStatusesRunning[0], newContainerStatusesFail[0]}, + Phase: corev1.PodFailed, + }}) // test succeeded rawSucceeded, _ := helper.BuildStatusRawExtension(statusMapSucceeded) @@ -616,15 +691,25 @@ func TestAggregatePodStatus(t *testing.T) { {ClusterName: "member2", Status: rawSucceeded, Applied: true}, } - succeededObj, _ := helper.ToUnstructured(&corev1.Pod{Status: corev1.PodStatus{ - ContainerStatuses: []corev1.ContainerStatus{containerStatusesRunning[0], newContainerStatusesSucceeded[0]}, - Phase: corev1.PodRunning, - }}) - - pendingObj, _ := helper.ToUnstructured(&corev1.Pod{Status: corev1.PodStatus{ - ContainerStatuses: []corev1.ContainerStatus{containerStatusesRunning[0]}, - Phase: corev1.PodPending, - }}) + succeededObj, _ := helper.ToUnstructured(&corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + Status: corev1.PodStatus{ + ContainerStatuses: []corev1.ContainerStatus{containerStatusesRunning[0], newContainerStatusesSucceeded[0]}, + Phase: corev1.PodRunning, + }}) + + pendingObj, _ := helper.ToUnstructured(&corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + Status: corev1.PodStatus{ + ContainerStatuses: []corev1.ContainerStatus{containerStatusesRunning[0]}, + Phase: corev1.PodPending, + }}) tests := []struct { name string @@ -721,16 +806,27 @@ func TestAggregatePVCStatus(t *testing.T) { } // test aggregatePersistentVolumeClaimStatus function - oldPVC := &corev1.PersistentVolumeClaim{} + oldPVC := &corev1.PersistentVolumeClaim{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolumeClaim", APIVersion: corev1.SchemeGroupVersion.String()}, + } oldObj, _ := helper.ToUnstructured(oldPVC) - boundNewPVC := &corev1.PersistentVolumeClaim{Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimBound}} + boundNewPVC := &corev1.PersistentVolumeClaim{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolumeClaim", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimBound}, + } newBoundPVCObj, _ := helper.ToUnstructured(boundNewPVC) - lostNewPVC := &corev1.PersistentVolumeClaim{Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimLost}} + lostNewPVC := &corev1.PersistentVolumeClaim{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolumeClaim", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimLost}, + } newLostPVCObj, _ := helper.ToUnstructured(lostNewPVC) - pendingNewPVC := &corev1.PersistentVolumeClaim{Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimPending}} + pendingNewPVC := &corev1.PersistentVolumeClaim{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolumeClaim", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimPending}, + } newPendingPVCObj, _ := helper.ToUnstructured(pendingNewPVC) tests := []struct { @@ -832,22 +928,39 @@ func TestAggregatePVStatus(t *testing.T) { } // test aggregatePersistentVolumeStatus function - oldPVC := &corev1.PersistentVolume{} + oldPVC := &corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolume", APIVersion: corev1.SchemeGroupVersion.String()}, + } oldObj, _ := helper.ToUnstructured(oldPVC) - availableNewPv := &corev1.PersistentVolume{Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeAvailable}} + availableNewPv := &corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolume", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeAvailable}, + } newAvailablePvObj, _ := helper.ToUnstructured(availableNewPv) - boundNewPV := &corev1.PersistentVolume{Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeBound}} + boundNewPV := &corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolume", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeBound}, + } newBoundPVObj, _ := helper.ToUnstructured(boundNewPV) - releaseNewPV := &corev1.PersistentVolume{Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeReleased}} + releaseNewPV := &corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolume", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeReleased}, + } newReleasePVObj, _ := helper.ToUnstructured(releaseNewPV) - failedNewPV := &corev1.PersistentVolume{Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeFailed}} + failedNewPV := &corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolume", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumeFailed}, + } newFailedPVObj, _ := helper.ToUnstructured(failedNewPV) - pendingNewPV := &corev1.PersistentVolume{Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumePending}} + pendingNewPV := &corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{Kind: "PersistentVolume", APIVersion: corev1.SchemeGroupVersion.String()}, + Status: corev1.PersistentVolumeStatus{Phase: corev1.VolumePending}, + } newPendingPVObj, _ := helper.ToUnstructured(pendingNewPV) tests := []struct { @@ -901,6 +1014,10 @@ func TestAggregatePVStatus(t *testing.T) { func TestAggregatedPodDisruptionBudgetStatus(t *testing.T) { currPdbObj, _ := helper.ToUnstructured(&policyv1.PodDisruptionBudget{ + TypeMeta: metav1.TypeMeta{ + Kind: "PodDisruptionBudget", + APIVersion: policyv1.SchemeGroupVersion.String(), + }, Status: policyv1.PodDisruptionBudgetStatus{ CurrentHealthy: 1, DesiredHealthy: 1, @@ -910,6 +1027,10 @@ func TestAggregatedPodDisruptionBudgetStatus(t *testing.T) { }) expectedPdbObj, _ := helper.ToUnstructured(&policyv1.PodDisruptionBudget{ + TypeMeta: metav1.TypeMeta{ + Kind: "PodDisruptionBudget", + APIVersion: policyv1.SchemeGroupVersion.String(), + }, Status: policyv1.PodDisruptionBudgetStatus{ CurrentHealthy: 2, DesiredHealthy: 2, @@ -938,6 +1059,10 @@ func TestAggregatedPodDisruptionBudgetStatus(t *testing.T) { }) expectedUnhealthyPdbObj, _ := helper.ToUnstructured(&policyv1.PodDisruptionBudget{ + TypeMeta: metav1.TypeMeta{ + Kind: "PodDisruptionBudget", + APIVersion: policyv1.SchemeGroupVersion.String(), + }, Status: policyv1.PodDisruptionBudgetStatus{ CurrentHealthy: 0, DesiredHealthy: 2, @@ -994,6 +1119,10 @@ func TestAggregatedPodDisruptionBudgetStatus(t *testing.T) { func Test_aggregateCronJobStatus(t *testing.T) { currCronJobObj, _ := helper.ToUnstructured(&batchv1.CronJob{ + TypeMeta: metav1.TypeMeta{ + Kind: "CronJob", + APIVersion: batchv1.SchemeGroupVersion.String(), + }, Status: batchv1.CronJobStatus{ Active: []corev1.ObjectReference{}, LastScheduleTime: nil, @@ -1032,6 +1161,10 @@ func Test_aggregateCronJobStatus(t *testing.T) { parse, _ := time.Parse("2006-01-02 15:04:05", "2023-02-08 07:17:00") successfulTime := metav1.NewTime(parse) expectedCronJobObj, _ := helper.ToUnstructured(&batchv1.CronJob{ + TypeMeta: metav1.TypeMeta{ + Kind: "CronJob", + APIVersion: batchv1.SchemeGroupVersion.String(), + }, Status: batchv1.CronJobStatus{ Active: []corev1.ObjectReference{ { @@ -1082,6 +1215,10 @@ func Test_aggregateCronJobStatus(t *testing.T) { func Test_aggregateHorizontalPodAutoscalerStatus(t *testing.T) { curHPA, _ := helper.ToUnstructured(&autoscalingv2.HorizontalPodAutoscaler{ + TypeMeta: metav1.TypeMeta{ + Kind: "HorizontalPodAutoscaler", + APIVersion: autoscalingv2.SchemeGroupVersion.String(), + }, Status: autoscalingv2.HorizontalPodAutoscalerStatus{ CurrentReplicas: 0, DesiredReplicas: 0, @@ -1096,6 +1233,10 @@ func Test_aggregateHorizontalPodAutoscalerStatus(t *testing.T) { "desiredReplicas": 4, }) expectHPA, _ := helper.ToUnstructured(&autoscalingv2.HorizontalPodAutoscaler{ + TypeMeta: metav1.TypeMeta{ + Kind: "HorizontalPodAutoscaler", + APIVersion: autoscalingv2.SchemeGroupVersion.String(), + }, Status: autoscalingv2.HorizontalPodAutoscalerStatus{ CurrentReplicas: 6, DesiredReplicas: 6, diff --git a/pkg/resourceinterpreter/default/native/reflectstatus_test.go b/pkg/resourceinterpreter/default/native/reflectstatus_test.go index 78a392f9fc58..2d719e3c98b4 100644 --- a/pkg/resourceinterpreter/default/native/reflectstatus_test.go +++ b/pkg/resourceinterpreter/default/native/reflectstatus_test.go @@ -48,6 +48,10 @@ func Test_reflectPodDisruptionBudgetStatus(t *testing.T) { name: "PDB with valid status", object: func() *unstructured.Unstructured { pdb := &policyv1.PodDisruptionBudget{ + TypeMeta: metav1.TypeMeta{ + Kind: "PodDisruptionBudget", + APIVersion: policyv1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-pdb", Namespace: "test-ns", @@ -142,6 +146,10 @@ func Test_reflectHorizontalPodAutoscalerStatus(t *testing.T) { name: "HPA with valid status", object: func() *unstructured.Unstructured { hpa := &autoscalingv2.HorizontalPodAutoscaler{ + TypeMeta: metav1.TypeMeta{ + Kind: "HorizontalPodAutoscaler", + APIVersion: autoscalingv2.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-hpa", Namespace: "test-ns", @@ -357,6 +365,10 @@ func Test_getAllDefaultReflectStatusInterpreter(t *testing.T) { func Test_reflectDeploymentStatus(t *testing.T) { validDeployment := &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + Kind: "Deployment", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-deployment", Namespace: "test-ns", @@ -564,7 +576,10 @@ func Test_reflectIngressStatus(t *testing.T) { }, } - ingressStatusMap, _ := helper.ToUnstructured(&networkingv1.Ingress{Status: testIngress}) + ingressStatusMap, _ := helper.ToUnstructured(&networkingv1.Ingress{ + TypeMeta: metav1.TypeMeta{Kind: "Ingress", APIVersion: networkingv1.SchemeGroupVersion.String()}, + Status: testIngress, + }) wantRawExtension, _ := helper.BuildStatusRawExtension(testIngress) tests := []struct { @@ -641,7 +656,10 @@ func Test_reflectJobStatus(t *testing.T) { { name: "job with all status fields", object: func() *unstructured.Unstructured { - obj, _ := helper.ToUnstructured(&batchv1.Job{Status: jobStatus}) + obj, _ := helper.ToUnstructured(&batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: jobStatus, + }) return obj }(), want: func() *runtime.RawExtension { @@ -675,7 +693,10 @@ func Test_reflectJobStatus(t *testing.T) { object: func() *unstructured.Unstructured { status := jobStatus.DeepCopy() status.Conditions = []batchv1.JobCondition{} - obj, _ := helper.ToUnstructured(&batchv1.Job{Status: *status}) + obj, _ := helper.ToUnstructured(&batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: *status, + }) return obj }(), want: func() *runtime.RawExtension { @@ -701,7 +722,10 @@ func Test_reflectJobStatus(t *testing.T) { Message: "Job failed due to error", }, } - obj, _ := helper.ToUnstructured(&batchv1.Job{Status: *status}) + obj, _ := helper.ToUnstructured(&batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: *status, + }) return obj }(), want: func() *runtime.RawExtension { @@ -731,7 +755,10 @@ func Test_reflectJobStatus(t *testing.T) { status.Active = 1 status.CompletionTime = nil status.Conditions = []batchv1.JobCondition{} - obj, _ := helper.ToUnstructured(&batchv1.Job{Status: *status}) + obj, _ := helper.ToUnstructured(&batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: *status, + }) return obj }(), want: func() *runtime.RawExtension { @@ -761,7 +788,10 @@ func Test_reflectJobStatus(t *testing.T) { object: func() *unstructured.Unstructured { status := jobStatus.DeepCopy() status.CompletionTime = nil - obj, _ := helper.ToUnstructured(&batchv1.Job{Status: *status}) + obj, _ := helper.ToUnstructured(&batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: *status, + }) return obj }(), want: func() *runtime.RawExtension { @@ -777,7 +807,10 @@ func Test_reflectJobStatus(t *testing.T) { object: func() *unstructured.Unstructured { status := jobStatus.DeepCopy() status.StartTime = nil - obj, _ := helper.ToUnstructured(&batchv1.Job{Status: *status}) + obj, _ := helper.ToUnstructured(&batchv1.Job{ + TypeMeta: metav1.TypeMeta{Kind: "Job", APIVersion: batchv1.SchemeGroupVersion.String()}, + Status: *status, + }) return obj }(), want: func() *runtime.RawExtension { @@ -819,6 +852,10 @@ func Test_reflectDaemonSetStatus(t *testing.T) { name: "daemonset with valid status and generation annotation", object: func() *unstructured.Unstructured { ds := &appsv1.DaemonSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "DaemonSet", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-daemonset", Namespace: "test-ns", @@ -984,6 +1021,10 @@ func Test_reflectStatefulSetStatus(t *testing.T) { name: "statefulset with valid status and generation annotation", object: func() *unstructured.Unstructured { sts := &appsv1.StatefulSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "StatefulSet", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-statefulset", Namespace: "test-ns", @@ -1069,6 +1110,10 @@ func Test_reflectStatefulSetStatus(t *testing.T) { name: "statefulset with partial status fields", object: func() *unstructured.Unstructured { sts := &appsv1.StatefulSet{ + TypeMeta: metav1.TypeMeta{ + Kind: "StatefulSet", + APIVersion: appsv1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "test-statefulset", Namespace: "test-ns", diff --git a/pkg/resourceinterpreter/default/native/retain_test.go b/pkg/resourceinterpreter/default/native/retain_test.go index e15b4cf74c28..8069a0eb70a4 100644 --- a/pkg/resourceinterpreter/default/native/retain_test.go +++ b/pkg/resourceinterpreter/default/native/retain_test.go @@ -169,6 +169,10 @@ func Test_retainK8sWorkloadReplicas(t *testing.T) { func Test_retainSecretServiceAccountToken(t *testing.T) { createSecret := func(secretType corev1.SecretType, dataKey, dataValue string) *unstructured.Unstructured { ret, _ := helper.ToUnstructured(&corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{}, Data: map[string][]byte{dataKey: []byte(dataValue)}, Type: secretType, @@ -238,6 +242,10 @@ func Test_retainSecretServiceAccountToken(t *testing.T) { func Test_retainPersistentVolumeFields(t *testing.T) { createPV := func(claimRef *corev1.ObjectReference) *unstructured.Unstructured { ret, _ := helper.ToUnstructured(&corev1.PersistentVolume{ + TypeMeta: metav1.TypeMeta{ + Kind: "PersistentVolume", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "pv", }, @@ -277,6 +285,10 @@ func Test_retainPersistentVolumeFields(t *testing.T) { func Test_retainPersistentVolumeClaimFields(t *testing.T) { createPVC := func(volumeName string) *unstructured.Unstructured { ret, _ := helper.ToUnstructured(&corev1.PersistentVolumeClaim{ + TypeMeta: metav1.TypeMeta{ + Kind: "PersistentVolumeClaim", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: "pvc", }, diff --git a/pkg/scheduler/event_handler.go b/pkg/scheduler/event_handler.go index a37af1f029be..b619ff4b4c3f 100644 --- a/pkg/scheduler/event_handler.go +++ b/pkg/scheduler/event_handler.go @@ -37,7 +37,6 @@ import ( "github.com/karmada-io/karmada/pkg/util" "github.com/karmada-io/karmada/pkg/util/fedinformer" "github.com/karmada-io/karmada/pkg/util/gclient" - "github.com/karmada-io/karmada/pkg/util/helper" ) // addAllEventHandlers is a helper function used in Scheduler @@ -130,20 +129,26 @@ func (s *Scheduler) onResourceBindingAdd(obj interface{}) { } func (s *Scheduler) onResourceBindingUpdate(old, cur interface{}) { - unstructuredOldObj, err := helper.ToUnstructured(old) + t, err := meta.TypeAccessor(old) if err != nil { - klog.Errorf("Failed to transform oldObj, error: %v", err) + klog.Errorf("Failed to transform oldObj as meta.Type, error: %v", err) return } - unstructuredNewObj, err := helper.ToUnstructured(cur) + oldMeta, err := meta.Accessor(old) if err != nil { - klog.Errorf("Failed to transform newObj, error: %v", err) + klog.Errorf("Failed to transform oldObj as metav1.Object, error: %v", err) return } - if unstructuredOldObj.GetGeneration() == unstructuredNewObj.GetGeneration() { - klog.V(4).Infof("Ignore update event of object (kind=%s, %s/%s) as specification no change", unstructuredOldObj.GetKind(), unstructuredOldObj.GetNamespace(), unstructuredOldObj.GetName()) + newMeta, err := meta.Accessor(cur) + if err != nil { + klog.Errorf("Failed to transform newObj as metav1.Object, error: %v", err) + return + } + + if oldMeta.GetGeneration() == newMeta.GetGeneration() { + klog.V(4).Infof("Ignore update event of object (kind=%s, %s/%s) as specification no change", t.GetKind(), oldMeta.GetNamespace(), oldMeta.GetName()) return } diff --git a/pkg/scheduler/scheduler_metrics_test.go b/pkg/scheduler/scheduler_metrics_test.go index 97364fd58a1e..c3e14488c056 100644 --- a/pkg/scheduler/scheduler_metrics_test.go +++ b/pkg/scheduler/scheduler_metrics_test.go @@ -42,6 +42,10 @@ var ( } updateBinding = func(scheduler *Scheduler, obj interface{}) { oldRB := &workv1alpha2.ResourceBinding{ + TypeMeta: metav1.TypeMeta{ + Kind: "ResourceBinding", + APIVersion: workv1alpha2.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Generation: 1, }, @@ -86,6 +90,10 @@ func TestIncomingBindingMetrics(t *testing.T) { var crbInfos = make([]*workv1alpha2.ClusterResourceBinding, 0, 3) for i := 1; i <= 3; i++ { rb := &workv1alpha2.ResourceBinding{ + TypeMeta: metav1.TypeMeta{ + Kind: "ResourceBinding", + APIVersion: workv1alpha2.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("test-rb-%d", i), Namespace: "bar", @@ -97,6 +105,10 @@ func TestIncomingBindingMetrics(t *testing.T) { for i := 1; i <= 3; i++ { crb := &workv1alpha2.ClusterResourceBinding{ + TypeMeta: metav1.TypeMeta{ + Kind: "ClusterResourceBinding", + APIVersion: workv1alpha2.GroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("test-rb-%d", i), Generation: 2, diff --git a/pkg/util/eventfilter/eventfilter_test.go b/pkg/util/eventfilter/eventfilter_test.go index 8ed99cfd54e6..53da8a3ad8d1 100644 --- a/pkg/util/eventfilter/eventfilter_test.go +++ b/pkg/util/eventfilter/eventfilter_test.go @@ -329,6 +329,10 @@ func TestResourceChangeByKarmada(t *testing.T) { { name: "Change by Karmada", oldObj: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ ResourceVersion: "123456", Labels: map[string]string{"app.karmada.io/managed": "true"}, @@ -336,6 +340,10 @@ func TestResourceChangeByKarmada(t *testing.T) { Data: map[string]string{"key": "value"}, }, newObj: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ ResourceVersion: "123457", Labels: map[string]string{"app.karmada.io/managed": "false"}, @@ -347,6 +355,10 @@ func TestResourceChangeByKarmada(t *testing.T) { { name: "Change not by Karmada", oldObj: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ ResourceVersion: "123456", Labels: map[string]string{"app": "v1"}, @@ -354,6 +366,10 @@ func TestResourceChangeByKarmada(t *testing.T) { Data: map[string]string{"key": "value"}, }, newObj: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ ResourceVersion: "123457", Labels: map[string]string{"app": "v2"}, @@ -365,6 +381,10 @@ func TestResourceChangeByKarmada(t *testing.T) { { name: "Change in Karmada annotations", oldObj: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ ResourceVersion: "123456", Annotations: map[string]string{"note.karmada.io/managed": "true"}, @@ -372,6 +392,10 @@ func TestResourceChangeByKarmada(t *testing.T) { Data: map[string]string{"key": "value"}, }, newObj: &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: corev1.SchemeGroupVersion.String(), + }, ObjectMeta: metav1.ObjectMeta{ ResourceVersion: "123457", Annotations: map[string]string{"note.karmada.io/managed": "false"}, diff --git a/pkg/util/helper/unstructured.go b/pkg/util/helper/unstructured.go index 5dbd03ebea28..39a71266c63b 100644 --- a/pkg/util/helper/unstructured.go +++ b/pkg/util/helper/unstructured.go @@ -21,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" "github.com/karmada-io/karmada/pkg/util" ) @@ -62,5 +63,12 @@ func ToUnstructured(obj interface{}) (*unstructured.Unstructured, error) { if err != nil { return nil, err } - return &unstructured.Unstructured{Object: uncastObj}, nil + unstructuredObj := &unstructured.Unstructured{Object: uncastObj} + if unstructuredObj.GetKind() == "" { + return nil, runtime.NewMissingKindErr(klog.KObj(unstructuredObj).String()) + } + if unstructuredObj.GetAPIVersion() == "" { + return nil, runtime.NewMissingVersionErr(klog.KObj(unstructuredObj).String()) + } + return unstructuredObj, nil } diff --git a/pkg/util/helper/unstructured_test.go b/pkg/util/helper/unstructured_test.go index d8bad0d3c02a..2d94afa1fe26 100644 --- a/pkg/util/helper/unstructured_test.go +++ b/pkg/util/helper/unstructured_test.go @@ -20,6 +20,7 @@ import ( "testing" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -170,6 +171,8 @@ func TestToUnstructured(t *testing.T) { name: "convert unstructured object", object: &unstructured.Unstructured{ Object: map[string]interface{}{ + "apiVersion": "apps/v1", + "kind": "Deployment", "spec": map[string]interface{}{ "replicas": int64(1), }, @@ -180,6 +183,10 @@ func TestToUnstructured(t *testing.T) { { name: "convert typed object", object: &corev1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: corev1.SchemeGroupVersion.String(), + }, Spec: corev1.PodSpec{ NodeName: "some-node", },