sync status of pvc

Signed-off-by: chaunceyjiang <chaunceyjiang@gmail.com>
This commit is contained in:
chaunceyjiang 2022-06-28 10:55:21 +08:00
parent 05bf0d2426
commit 6ffe6f0967
4 changed files with 136 additions and 0 deletions

View File

@ -98,6 +98,7 @@ Supported resources:
- DaemonSet(apps/v1)
- StatefulSet(apps/v1)
- Pod(v1)
- PersistentVolumeClaim(v1)
### InterpretStatus

View File

@ -28,6 +28,7 @@ func getAllDefaultAggregateStatusInterpreter() map[schema.GroupVersionKind]aggre
s[appsv1.SchemeGroupVersion.WithKind(util.DaemonSetKind)] = aggregateDaemonSetStatus
s[appsv1.SchemeGroupVersion.WithKind(util.StatefulSetKind)] = aggregateStatefulSetStatus
s[corev1.SchemeGroupVersion.WithKind(util.PodKind)] = aggregatePodStatus
s[corev1.SchemeGroupVersion.WithKind(util.PersistentVolumeClaimKind)] = aggregatePersistentVolumeClaimStatus
return s
}
@ -320,3 +321,40 @@ func aggregatePodStatus(object *unstructured.Unstructured, aggregatedStatusItems
pod.Status = *newStatus
return helper.ToUnstructured(pod)
}
func aggregatePersistentVolumeClaimStatus(object *unstructured.Unstructured, aggregatedStatusItems []workv1alpha2.AggregatedStatusItem) (*unstructured.Unstructured, error) {
pvc, err := helper.ConvertToPersistentVolumeClaim(object)
if err != nil {
return nil, err
}
newStatus := &corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimBound}
for _, item := range aggregatedStatusItems {
if item.Status == nil {
continue
}
temp := &corev1.PersistentVolumeClaimStatus{}
if err = json.Unmarshal(item.Status.Raw, temp); err != nil {
return nil, err
}
klog.V(3).Infof("Grab pvc(%s/%s) status from cluster(%s), phase: %s", pvc.Namespace,
pvc.Name, item.ClusterName, temp.Phase)
if temp.Phase == corev1.ClaimLost {
newStatus.Phase = corev1.ClaimLost
break
}
if temp.Phase != corev1.ClaimBound {
newStatus.Phase = temp.Phase
}
}
if reflect.DeepEqual(pvc.Status, *newStatus) {
klog.V(3).Infof("ignore update pvc(%s/%s) status as up to date", pvc.Namespace, pvc.Name)
return object, nil
}
pvc.Status = *newStatus
return helper.ToUnstructured(pvc)
}

View File

@ -541,3 +541,90 @@ func TestAggregatePodStatus(t *testing.T) {
assert.Equal(t, tt.expectedObj, actualObj)
}
}
func TestAggregatePVCStatus(t *testing.T) {
statusBoundMap := map[string]interface{}{
"phase": corev1.ClaimBound,
}
// Bound status
boundRaw1, _ := helper.BuildStatusRawExtension(statusBoundMap)
boundRaw2, _ := helper.BuildStatusRawExtension(statusBoundMap)
aggregatedStatusItems1 := []workv1alpha2.AggregatedStatusItem{
{ClusterName: "member1", Status: boundRaw1, Applied: true},
{ClusterName: "member2", Status: boundRaw2, Applied: true},
}
// Lost status
statusLostMap := map[string]interface{}{
"phase": corev1.ClaimLost,
}
lostRaw1, _ := helper.BuildStatusRawExtension(statusBoundMap)
lostRaw2, _ := helper.BuildStatusRawExtension(statusLostMap)
aggregatedStatusItems2 := []workv1alpha2.AggregatedStatusItem{
{ClusterName: "member1", Status: lostRaw1, Applied: true},
{ClusterName: "member2", Status: lostRaw2, Applied: true},
}
// Pending status
statusPendingMap := map[string]interface{}{
"phase": corev1.ClaimPending,
}
pendingRaw1, _ := helper.BuildStatusRawExtension(statusBoundMap)
pendingRaw2, _ := helper.BuildStatusRawExtension(statusPendingMap)
aggregatedStatusItems3 := []workv1alpha2.AggregatedStatusItem{
{ClusterName: "member1", Status: pendingRaw1, Applied: true},
{ClusterName: "member2", Status: pendingRaw2, Applied: true},
}
// test aggregatePersistentVolumeClaimStatus function
oldPVC := &corev1.PersistentVolumeClaim{}
oldObj, _ := helper.ToUnstructured(oldPVC)
boundNewPVC := &corev1.PersistentVolumeClaim{Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimBound}}
newBoundPVCObj, _ := helper.ToUnstructured(boundNewPVC)
lostNewPVC := &corev1.PersistentVolumeClaim{Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimLost}}
newLostPVCObj, _ := helper.ToUnstructured(lostNewPVC)
pendingNewPVC := &corev1.PersistentVolumeClaim{Status: corev1.PersistentVolumeClaimStatus{Phase: corev1.ClaimPending}}
newPendingPVCObj, _ := helper.ToUnstructured(pendingNewPVC)
tests := []struct {
name string
curObj *unstructured.Unstructured
aggregatedStatusItems []workv1alpha2.AggregatedStatusItem
expectedObj *unstructured.Unstructured
}{
{
name: "update pvc status",
curObj: oldObj,
aggregatedStatusItems: aggregatedStatusItems1,
expectedObj: newBoundPVCObj,
},
{
name: "update pvc status",
curObj: oldObj,
aggregatedStatusItems: aggregatedStatusItems2,
expectedObj: newLostPVCObj,
},
{
name: "update pvc status",
curObj: oldObj,
aggregatedStatusItems: aggregatedStatusItems3,
expectedObj: newPendingPVCObj,
},
{
name: "ignore update pvc status as up to date",
curObj: newBoundPVCObj,
aggregatedStatusItems: aggregatedStatusItems1,
expectedObj: newBoundPVCObj,
},
}
for _, tt := range tests {
actualObj, _ := aggregatePersistentVolumeClaimStatus(tt.curObj, tt.aggregatedStatusItems)
assert.Equal(t, tt.expectedObj, actualObj)
}
}

View File

@ -55,6 +55,16 @@ func ConvertToPod(obj *unstructured.Unstructured) (*corev1.Pod, error) {
return typedObj, nil
}
// ConvertToPersistentVolumeClaim converts a pvc object from unstructured to typed.
func ConvertToPersistentVolumeClaim(obj *unstructured.Unstructured) (*corev1.PersistentVolumeClaim, error) {
typedObj := &corev1.PersistentVolumeClaim{}
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), typedObj); err != nil {
return nil, err
}
return typedObj, nil
}
// ConvertToNode converts a Node object from unstructured to typed.
func ConvertToNode(obj *unstructured.Unstructured) (*corev1.Node, error) {
typedObj := &corev1.Node{}