1
16
17 package pod
18
19 import (
20 "bytes"
21 "context"
22 "encoding/json"
23 "fmt"
24
25 v1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/types"
28 "k8s.io/apimachinery/pkg/util/strategicpatch"
29 clientset "k8s.io/client-go/kubernetes"
30 podutil "k8s.io/kubernetes/pkg/api/v1/pod"
31 )
32
33
34 func PatchPodStatus(ctx context.Context, c clientset.Interface, namespace, name string, uid types.UID, oldPodStatus, newPodStatus v1.PodStatus) (*v1.Pod, []byte, bool, error) {
35 patchBytes, unchanged, err := preparePatchBytesForPodStatus(namespace, name, uid, oldPodStatus, newPodStatus)
36 if err != nil {
37 return nil, nil, false, err
38 }
39 if unchanged {
40 return nil, patchBytes, true, nil
41 }
42
43 updatedPod, err := c.CoreV1().Pods(namespace).Patch(ctx, name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}, "status")
44 if err != nil {
45 return nil, nil, false, fmt.Errorf("failed to patch status %q for pod %q/%q: %v", patchBytes, namespace, name, err)
46 }
47 return updatedPod, patchBytes, false, nil
48 }
49
50 func preparePatchBytesForPodStatus(namespace, name string, uid types.UID, oldPodStatus, newPodStatus v1.PodStatus) ([]byte, bool, error) {
51 oldData, err := json.Marshal(v1.Pod{
52 Status: oldPodStatus,
53 })
54 if err != nil {
55 return nil, false, fmt.Errorf("failed to Marshal oldData for pod %q/%q: %v", namespace, name, err)
56 }
57
58 newData, err := json.Marshal(v1.Pod{
59 ObjectMeta: metav1.ObjectMeta{UID: uid},
60 Status: newPodStatus,
61 })
62 if err != nil {
63 return nil, false, fmt.Errorf("failed to Marshal newData for pod %q/%q: %v", namespace, name, err)
64 }
65
66 patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Pod{})
67 if err != nil {
68 return nil, false, fmt.Errorf("failed to CreateTwoWayMergePatch for pod %q/%q: %v", namespace, name, err)
69 }
70 return patchBytes, bytes.Equal(patchBytes, []byte(fmt.Sprintf(`{"metadata":{"uid":%q}}`, uid))), nil
71 }
72
73
74 func ReplaceOrAppendPodCondition(conditions []v1.PodCondition, condition *v1.PodCondition) []v1.PodCondition {
75 if i, _ := podutil.GetPodConditionFromList(conditions, condition.Type); i >= 0 {
76 conditions[i] = *condition
77 } else {
78 conditions = append(conditions, *condition)
79 }
80 return conditions
81 }
82
View as plain text