sync status of pod

Signed-off-by: bruce <zhangyongxi_yewu@cmss.chinamobile.com>
This commit is contained in:
bruce 2022-06-13 15:15:56 +08:00
parent 1ae36f7e16
commit 738352611e
3 changed files with 247 additions and 0 deletions

View File

@ -97,6 +97,7 @@ Supported resources:
- Job(batch/v1)
- DaemonSet(apps/v1)
- StatefulSet(apps/v1)
- Pod(v1)
### InterpretStatus

View File

@ -27,6 +27,7 @@ func getAllDefaultAggregateStatusInterpreter() map[schema.GroupVersionKind]aggre
s[batchv1.SchemeGroupVersion.WithKind(util.JobKind)] = aggregateJobStatus
s[appsv1.SchemeGroupVersion.WithKind(util.DaemonSetKind)] = aggregateDaemonSetStatus
s[appsv1.SchemeGroupVersion.WithKind(util.StatefulSetKind)] = aggregateStatefulSetStatus
s[corev1.SchemeGroupVersion.WithKind(util.PodKind)] = aggregatePodStatus
return s
}
@ -269,3 +270,53 @@ func aggregateStatefulSetStatus(object *unstructured.Unstructured, aggregatedSta
return helper.ToUnstructured(statefulSet)
}
func aggregatePodStatus(object *unstructured.Unstructured, aggregatedStatusItems []workv1alpha2.AggregatedStatusItem) (*unstructured.Unstructured, error) {
pod, err := helper.ConvertToPod(object)
if err != nil {
return nil, err
}
newStatus := &corev1.PodStatus{}
newStatus.ContainerStatuses = make([]corev1.ContainerStatus, 0)
runningFlag := true
for _, item := range aggregatedStatusItems {
if item.Status == nil {
runningFlag = false
continue
}
temp := &corev1.PodStatus{}
if err = json.Unmarshal(item.Status.Raw, temp); err != nil {
return nil, err
}
if temp.Phase != corev1.PodRunning {
runningFlag = false
}
for _, containerStatus := range temp.ContainerStatuses {
tempStatus := corev1.ContainerStatus{
Ready: containerStatus.Ready,
State: containerStatus.State,
}
newStatus.ContainerStatuses = append(newStatus.ContainerStatuses, tempStatus)
}
klog.V(3).Infof("Grab pod(%s/%s) status from cluster(%s), phase: %s", pod.Namespace,
pod.Name, item.ClusterName, temp.Phase)
}
if runningFlag {
newStatus.Phase = corev1.PodRunning
} else {
newStatus.Phase = corev1.PodPending
}
if reflect.DeepEqual(pod.Status, *newStatus) {
klog.V(3).Infof("ignore update pod(%s/%s) status as up to date", pod.Namespace, pod.Name)
return object, nil
}
pod.Status = *newStatus
return helper.ToUnstructured(pod)
}

View File

@ -2,6 +2,7 @@ package defaultinterpreter
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
@ -346,3 +347,197 @@ func cleanUnstructuredJobConditionTime(object *unstructured.Unstructured) *unstr
ret, _ := helper.ToUnstructured(job)
return ret
}
func TestAggregatePodStatus(t *testing.T) {
startedTrue := true
timeNow := time.Now()
containerStatuses1 := []corev1.ContainerStatus{
{
ContainerID: "containerd://6cee0afa333472f672341352e0d",
Image: "nginx:latest",
ImageID: "docker.io/library/import-2022-06-05@sha256:dfb593",
Name: "busybox-2",
Ready: true,
RestartCount: 0,
Started: &startedTrue,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
{
ContainerID: "containerd://b373fb05ebf57020573cdf4a4518a3b2a8",
Image: "nginx:latest",
ImageID: "docker.io/library/import-2022-06-05@sha256:a29d07a75",
Name: "busybox-2",
Ready: true,
RestartCount: 0,
Started: &startedTrue,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
}
newContainerStatuses1 := []corev1.ContainerStatus{
{
Ready: true,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
{
Ready: true,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
}
curObj, _ := helper.ToUnstructured(&corev1.Pod{})
newObj, _ := helper.ToUnstructured(&corev1.Pod{Status: corev1.PodStatus{
ContainerStatuses: newContainerStatuses1,
Phase: corev1.PodRunning,
}})
statusMap1 := map[string]interface{}{
"containerStatuses": []corev1.ContainerStatus{containerStatuses1[0]},
"phase": corev1.PodRunning,
}
raw1, _ := helper.BuildStatusRawExtension(statusMap1)
statusMap2 := map[string]interface{}{
"containerStatuses": []corev1.ContainerStatus{containerStatuses1[1]},
"phase": corev1.PodRunning,
}
raw2, _ := helper.BuildStatusRawExtension(statusMap2)
aggregatedStatusItems1 := []workv1alpha2.AggregatedStatusItem{
{ClusterName: "member1", Status: raw1, Applied: true},
{ClusterName: "member2", Status: raw2, Applied: true},
}
containerStatuses2 := []corev1.ContainerStatus{
{
ContainerID: "containerd://6cee0afa333472f672341352e0d",
Image: "nginx:latest",
ImageID: "docker.io/library/import-2022-06-05@sha256:dfb593",
Name: "busybox-2",
Ready: true,
RestartCount: 0,
Started: &startedTrue,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
{
ContainerID: "containerd://b373fb05ebf57020573cdf4a4518a3b2a8",
Image: "nginx:latest",
ImageID: "docker.io/library/import-2022-06-05@sha256:a29d07a75",
Name: "busybox-2",
Ready: false,
RestartCount: 0,
Started: &startedTrue,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
}
statusMap3 := map[string]interface{}{
"containerStatuses": []corev1.ContainerStatus{containerStatuses2[0]},
"phase": corev1.PodRunning,
}
raw3, _ := helper.BuildStatusRawExtension(statusMap3)
statusMap4 := map[string]interface{}{
"containerStatuses": []corev1.ContainerStatus{containerStatuses2[1]},
"phase": corev1.PodPending,
}
raw4, _ := helper.BuildStatusRawExtension(statusMap4)
aggregatedStatusItems2 := []workv1alpha2.AggregatedStatusItem{
{ClusterName: "member1", Status: raw3, Applied: true},
{ClusterName: "member2", Status: raw4, Applied: true},
}
newContainerStatuses2 := []corev1.ContainerStatus{
{
Ready: true,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
{
Ready: false,
State: corev1.ContainerState{
Running: &corev1.ContainerStateRunning{
StartedAt: metav1.Time{
Time: timeNow,
},
},
},
},
}
newPodFailed := &corev1.Pod{Status: corev1.PodStatus{
ContainerStatuses: newContainerStatuses2,
Phase: corev1.PodPending,
}}
newObjFailed, _ := helper.ToUnstructured(newPodFailed)
tests := []struct {
name string
curObj *unstructured.Unstructured
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
expectedObj *unstructured.Unstructured
}{
{
name: "update pod status",
curObj: curObj,
aggregatedStatusItems: aggregatedStatusItems1,
expectedObj: newObj,
},
{
name: "ignore update pod status as up to date",
curObj: newObj,
aggregatedStatusItems: aggregatedStatusItems1,
expectedObj: newObj,
},
{
name: "update pod status as one Pod failed",
curObj: newObj,
aggregatedStatusItems: aggregatedStatusItems2,
expectedObj: newObjFailed,
},
}
for _, tt := range tests {
actualObj, _ := aggregatePodStatus(tt.curObj, tt.aggregatedStatusItems)
assert.Equal(t, tt.expectedObj, actualObj)
}
}