commit
9083d06b7c
|
@ -190,14 +190,15 @@ func aggregateDaemonSetStatus(object *unstructured.Unstructured, aggregatedStatu
|
|||
if err = json.Unmarshal(item.Status.Raw, temp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klog.V(3).Infof("Grab daemonSet(%s/%s) status from cluster(%s), currentNumberScheduled: %d, desiredNumberScheduled: %d, numberAvailable: %d, numberMisscheduled: %d, numberReady: %d, updatedNumberScheduled: %d",
|
||||
daemonSet.Namespace, daemonSet.Name, item.ClusterName, temp.CurrentNumberScheduled, temp.DesiredNumberScheduled, temp.NumberAvailable, temp.NumberMisscheduled, temp.NumberReady, temp.UpdatedNumberScheduled)
|
||||
klog.V(3).Infof("Grab daemonSet(%s/%s) status from cluster(%s), currentNumberScheduled: %d, desiredNumberScheduled: %d, numberAvailable: %d, numberMisscheduled: %d, numberReady: %d, updatedNumberScheduled: %d, numberUnavailable: %d",
|
||||
daemonSet.Namespace, daemonSet.Name, item.ClusterName, temp.CurrentNumberScheduled, temp.DesiredNumberScheduled, temp.NumberAvailable, temp.NumberMisscheduled, temp.NumberReady, temp.UpdatedNumberScheduled, temp.NumberUnavailable)
|
||||
newStatus.CurrentNumberScheduled += temp.CurrentNumberScheduled
|
||||
newStatus.DesiredNumberScheduled += temp.DesiredNumberScheduled
|
||||
newStatus.NumberAvailable += temp.NumberAvailable
|
||||
newStatus.NumberMisscheduled += temp.NumberMisscheduled
|
||||
newStatus.NumberReady += temp.NumberReady
|
||||
newStatus.UpdatedNumberScheduled += temp.UpdatedNumberScheduled
|
||||
newStatus.NumberUnavailable += temp.NumberUnavailable
|
||||
}
|
||||
|
||||
if oldStatus.CurrentNumberScheduled == newStatus.CurrentNumberScheduled &&
|
||||
|
@ -205,7 +206,8 @@ func aggregateDaemonSetStatus(object *unstructured.Unstructured, aggregatedStatu
|
|||
oldStatus.NumberAvailable == newStatus.NumberAvailable &&
|
||||
oldStatus.NumberMisscheduled == newStatus.NumberMisscheduled &&
|
||||
oldStatus.NumberReady == newStatus.NumberReady &&
|
||||
oldStatus.UpdatedNumberScheduled == newStatus.UpdatedNumberScheduled {
|
||||
oldStatus.UpdatedNumberScheduled == newStatus.UpdatedNumberScheduled &&
|
||||
oldStatus.NumberUnavailable == newStatus.NumberUnavailable {
|
||||
klog.V(3).Infof("ignore update daemonSet(%s/%s) status as up to date", daemonSet.Namespace, daemonSet.Name)
|
||||
return object, nil
|
||||
}
|
||||
|
@ -216,6 +218,7 @@ func aggregateDaemonSetStatus(object *unstructured.Unstructured, aggregatedStatu
|
|||
oldStatus.NumberMisscheduled = newStatus.NumberMisscheduled
|
||||
oldStatus.NumberReady = newStatus.NumberReady
|
||||
oldStatus.UpdatedNumberScheduled = newStatus.UpdatedNumberScheduled
|
||||
oldStatus.NumberUnavailable = newStatus.NumberUnavailable
|
||||
|
||||
return helper.ToUnstructured(daemonSet)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,335 @@
|
|||
package defaultinterpreter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
|
||||
"github.com/karmada-io/karmada/pkg/util/helper"
|
||||
)
|
||||
|
||||
func TestAggregateDeploymentStatus(t *testing.T) {
|
||||
statusMap := map[string]interface{}{
|
||||
"replicas": 1,
|
||||
"readyReplicas": 1,
|
||||
"updatedReplicas": 1,
|
||||
"availableReplicas": 1,
|
||||
"unavailableReplicas": 0,
|
||||
}
|
||||
raw, _ := helper.BuildStatusRawExtension(statusMap)
|
||||
aggregatedStatusItems := []workv1alpha2.AggregatedStatusItem{
|
||||
{ClusterName: "member1", Status: raw, Applied: true},
|
||||
{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}}
|
||||
oldObj, _ := helper.ToUnstructured(oldDeploy)
|
||||
newObj, _ := helper.ToUnstructured(newDeploy)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
|
||||
expectedObj *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
name: "update deployment status",
|
||||
curObj: oldObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
{
|
||||
name: "ignore update deployment status as up to date",
|
||||
curObj: newObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
actualObj, _ := aggregateDeploymentStatus(tt.curObj, tt.aggregatedStatusItems)
|
||||
assert.Equal(t, tt.expectedObj, actualObj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAggregateServiceStatus(t *testing.T) {
|
||||
statusMapNotLB := map[string]interface{}{}
|
||||
rawNotLB, _ := helper.BuildStatusRawExtension(statusMapNotLB)
|
||||
aggregatedStatusItemsNotLB := []workv1alpha2.AggregatedStatusItem{
|
||||
{ClusterName: "member1", Status: rawNotLB, Applied: true},
|
||||
}
|
||||
|
||||
statusMapLB := map[string]interface{}{
|
||||
"loadBalancer": corev1.LoadBalancerStatus{Ingress: []corev1.LoadBalancerIngress{{IP: "8.8.8.8"}}},
|
||||
}
|
||||
rawLB, _ := helper.BuildStatusRawExtension(statusMapLB)
|
||||
aggregatedStatusItemsLB := []workv1alpha2.AggregatedStatusItem{
|
||||
{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}}
|
||||
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"}}}}}
|
||||
oldObjServiceLoadBalancer, _ := helper.ToUnstructured(oldServiceLoadBalancer)
|
||||
newObjServiceLoadBalancer, _ := helper.ToUnstructured(newServiceLoadBalancer)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
|
||||
expectedObj *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
name: "ignore update service status when type is ClusterIP",
|
||||
curObj: objServiceClusterIP,
|
||||
aggregatedStatusItems: aggregatedStatusItemsNotLB,
|
||||
expectedObj: objServiceClusterIP,
|
||||
},
|
||||
{
|
||||
name: "ignore update service status when type is NodePort",
|
||||
curObj: objServiceNodePort,
|
||||
aggregatedStatusItems: aggregatedStatusItemsNotLB,
|
||||
expectedObj: objServiceNodePort,
|
||||
},
|
||||
{
|
||||
name: "ignore update service status when type is ExternalName",
|
||||
curObj: objServiceExternalName,
|
||||
aggregatedStatusItems: aggregatedStatusItemsNotLB,
|
||||
expectedObj: objServiceExternalName,
|
||||
},
|
||||
{
|
||||
name: "update service status when type is LoadBalancer",
|
||||
curObj: oldObjServiceLoadBalancer,
|
||||
aggregatedStatusItems: aggregatedStatusItemsLB,
|
||||
expectedObj: newObjServiceLoadBalancer,
|
||||
},
|
||||
{
|
||||
name: "ignore update service status as up to date when type is LoadBalancer",
|
||||
curObj: newObjServiceLoadBalancer,
|
||||
aggregatedStatusItems: aggregatedStatusItemsLB,
|
||||
expectedObj: newObjServiceLoadBalancer,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
actualObj, _ := aggregateServiceStatus(tt.curObj, tt.aggregatedStatusItems)
|
||||
assert.Equal(t, tt.expectedObj, actualObj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAggregateIngressStatus(t *testing.T) {
|
||||
statusMap := map[string]interface{}{
|
||||
"loadBalancer": corev1.LoadBalancerStatus{Ingress: []corev1.LoadBalancerIngress{{IP: "8.8.8.8"}}},
|
||||
}
|
||||
raw, _ := helper.BuildStatusRawExtension(statusMap)
|
||||
aggregatedStatusItems := []workv1alpha2.AggregatedStatusItem{
|
||||
{ClusterName: "member1", Status: raw, Applied: true},
|
||||
}
|
||||
|
||||
oldIngress := &extensionsv1beta1.Ingress{}
|
||||
newIngress := &extensionsv1beta1.Ingress{Status: extensionsv1beta1.IngressStatus{LoadBalancer: corev1.LoadBalancerStatus{Ingress: []corev1.LoadBalancerIngress{{IP: "8.8.8.8", Hostname: "member1"}}}}}
|
||||
oldObj, _ := helper.ToUnstructured(oldIngress)
|
||||
newObj, _ := helper.ToUnstructured(newIngress)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
|
||||
expectedObj *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
name: "update ingress status",
|
||||
curObj: oldObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
{
|
||||
name: "ignore update ingress status as up to date",
|
||||
curObj: newObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
actualObj, _ := aggregateIngressStatus(tt.curObj, tt.aggregatedStatusItems)
|
||||
assert.Equal(t, tt.expectedObj, actualObj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAggregateJobStatus(t *testing.T) {
|
||||
startTime := metav1.Now()
|
||||
completionTime := startTime
|
||||
statusMap := map[string]interface{}{
|
||||
"active": 0,
|
||||
"succeeded": 1,
|
||||
"failed": 0,
|
||||
"startTime": startTime,
|
||||
"completionTime": completionTime,
|
||||
"conditions": []batchv1.JobCondition{{Type: batchv1.JobComplete, Status: corev1.ConditionTrue}},
|
||||
}
|
||||
raw, _ := helper.BuildStatusRawExtension(statusMap)
|
||||
aggregatedStatusItems := []workv1alpha2.AggregatedStatusItem{
|
||||
{ClusterName: "member1", Status: raw, Applied: true},
|
||||
{ClusterName: "member2", Status: raw, Applied: true},
|
||||
}
|
||||
|
||||
statusMapWithJobfailed := map[string]interface{}{
|
||||
"active": 0,
|
||||
"succeeded": 0,
|
||||
"failed": 1,
|
||||
"startTime": startTime,
|
||||
"completionTime": completionTime,
|
||||
"conditions": []batchv1.JobCondition{{Type: batchv1.JobFailed, Status: corev1.ConditionTrue}},
|
||||
}
|
||||
rawWithJobFailed, _ := helper.BuildStatusRawExtension(statusMapWithJobfailed)
|
||||
aggregatedStatusItemsWithJobFailed := []workv1alpha2.AggregatedStatusItem{
|
||||
{ClusterName: "member1", Status: raw, Applied: true},
|
||||
{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, LastProbeTime: metav1.Now(), LastTransitionTime: metav1.Now(), 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, LastProbeTime: metav1.Now(), LastTransitionTime: metav1.Now(), Reason: "JobFailed", Message: "Job executed failed in member clusters member2"}}}}
|
||||
newObjWithJobFailed, _ := helper.ToUnstructured(newJobWithJobFailed)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
|
||||
expectedObj *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
name: "update job status without job failed",
|
||||
curObj: oldObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
{
|
||||
name: "update job status with job failed",
|
||||
curObj: oldObj,
|
||||
aggregatedStatusItems: aggregatedStatusItemsWithJobFailed,
|
||||
expectedObj: newObjWithJobFailed,
|
||||
},
|
||||
{
|
||||
name: "ignore update job status as up to date",
|
||||
curObj: newObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
actualObj, _ := aggregateJobStatus(tt.curObj, tt.aggregatedStatusItems)
|
||||
assert.Equal(t, tt.expectedObj, actualObj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAggregateDaemonSetStatus(t *testing.T) {
|
||||
statusMap := map[string]interface{}{
|
||||
"currentNumberScheduled": 1,
|
||||
"numberMisscheduled": 0,
|
||||
"desiredNumberScheduled": 1,
|
||||
"numberReady": 1,
|
||||
"updatedNumberScheduled": 1,
|
||||
"numberAvailable": 1,
|
||||
"numberUnavailable": 0,
|
||||
}
|
||||
raw, _ := helper.BuildStatusRawExtension(statusMap)
|
||||
aggregatedStatusItems := []workv1alpha2.AggregatedStatusItem{
|
||||
{ClusterName: "member1", Status: raw, Applied: true},
|
||||
{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}}
|
||||
oldObj, _ := helper.ToUnstructured(oldDaemonSet)
|
||||
newObj, _ := helper.ToUnstructured(newDaemonSet)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
|
||||
expectedObj *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
name: "update daemonSet status",
|
||||
curObj: oldObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
{
|
||||
name: "ignore update daemonSet status as up to date",
|
||||
curObj: newObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
actualObj, _ := aggregateDaemonSetStatus(tt.curObj, tt.aggregatedStatusItems)
|
||||
assert.Equal(t, tt.expectedObj, actualObj)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAggregateStatefulSetStatus(t *testing.T) {
|
||||
statusMap := map[string]interface{}{
|
||||
"replicas": 1,
|
||||
"readyReplicas": 1,
|
||||
"currentReplicas": 1,
|
||||
"updatedReplicas": 1,
|
||||
"availableReplicas": 1,
|
||||
}
|
||||
raw, _ := helper.BuildStatusRawExtension(statusMap)
|
||||
aggregatedStatusItems := []workv1alpha2.AggregatedStatusItem{
|
||||
{ClusterName: "member1", Status: raw, Applied: true},
|
||||
{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}}
|
||||
oldObj, _ := helper.ToUnstructured(oldStatefulSet)
|
||||
newObj, _ := helper.ToUnstructured(newStatefulSet)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
curObj *unstructured.Unstructured
|
||||
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
|
||||
expectedObj *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
name: "update statefulSet status",
|
||||
curObj: oldObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
{
|
||||
name: "ignore update statefulSet status as up to date",
|
||||
curObj: newObj,
|
||||
aggregatedStatusItems: aggregatedStatusItems,
|
||||
expectedObj: newObj,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
actualObj, _ := aggregateStatefulSetStatus(tt.curObj, tt.aggregatedStatusItems)
|
||||
assert.Equal(t, tt.expectedObj, actualObj)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue