github.com/kubewharf/katalyst-core@v0.5.3/pkg/client/control/pod.go (about) 1 /* 2 Copyright 2022 The Katalyst Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package control 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 24 core "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/types" 27 "k8s.io/apimachinery/pkg/util/strategicpatch" 28 "k8s.io/client-go/kubernetes" 29 statusutil "k8s.io/kubernetes/pkg/util/pod" 30 31 "github.com/kubewharf/katalyst-core/pkg/util/general" 32 ) 33 34 // PodUpdater is used to update Pod 35 type PodUpdater interface { 36 UpdatePod(ctx context.Context, pod *core.Pod, opts metav1.UpdateOptions) (*core.Pod, error) 37 UpdatePodStatus(ctx context.Context, pod *core.Pod, opts metav1.UpdateOptions) (*core.Pod, error) 38 PatchPod(ctx context.Context, oldPod, newPod *core.Pod) error 39 PatchPodStatus(ctx context.Context, oldPod, newPod *core.Pod) error 40 } 41 42 type DummyPodUpdater struct{} 43 44 func (d *DummyPodUpdater) UpdatePod(_ context.Context, _ *core.Pod, _ metav1.UpdateOptions) (*core.Pod, error) { 45 return nil, nil 46 } 47 48 func (d *DummyPodUpdater) PatchPod(_ context.Context, _, _ *core.Pod) error { 49 return nil 50 } 51 52 func (d *DummyPodUpdater) UpdatePodStatus(_ context.Context, _ *core.Pod, _ metav1.UpdateOptions) (*core.Pod, error) { 53 return nil, nil 54 } 55 56 func (d *DummyPodUpdater) PatchPodStatus(_ context.Context, _, _ *core.Pod) error { 57 return nil 58 } 59 60 type RealPodUpdater struct { 61 client kubernetes.Interface 62 } 63 64 func NewRealPodUpdater(client kubernetes.Interface) *RealPodUpdater { 65 return &RealPodUpdater{ 66 client: client, 67 } 68 } 69 70 func (r *RealPodUpdater) UpdatePod(ctx context.Context, pod *core.Pod, opts metav1.UpdateOptions) (*core.Pod, error) { 71 if pod == nil { 72 return nil, fmt.Errorf("can't update a nil Pod") 73 } 74 75 return r.client.CoreV1().Pods(pod.Namespace).Update(ctx, pod, opts) 76 } 77 78 func (r *RealPodUpdater) PatchPod(ctx context.Context, oldPod, newPod *core.Pod) error { 79 if oldPod == nil || newPod == nil { 80 return fmt.Errorf("can't update a nil Pod") 81 } 82 83 oldData, err := json.Marshal(oldPod) 84 if err != nil { 85 return err 86 } 87 88 newData, err := json.Marshal(newPod) 89 if err != nil { 90 return err 91 } 92 93 patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, &core.Pod{}) 94 if err != nil { 95 return fmt.Errorf("failed to create merge patch for pod %q/%q: %v", oldPod.Namespace, oldPod.Name, err) 96 } else if general.JsonPathEmpty(patchBytes) { 97 return nil 98 } 99 100 _, err = r.client.CoreV1().Pods(oldPod.Namespace).Patch(ctx, oldPod.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{}) 101 return err 102 } 103 104 func (r *RealPodUpdater) UpdatePodStatus(ctx context.Context, pod *core.Pod, opts metav1.UpdateOptions) (*core.Pod, error) { 105 if pod == nil { 106 return nil, fmt.Errorf("can't update a nil Pod's status") 107 } 108 109 return r.client.CoreV1().Pods(pod.Namespace).UpdateStatus(ctx, pod, opts) 110 } 111 112 func (r *RealPodUpdater) PatchPodStatus(_ context.Context, oldPod, newPod *core.Pod) error { 113 _, _, _, err := statusutil.PatchPodStatus(r.client, oldPod.Namespace, oldPod.Name, oldPod.UID, oldPod.Status, newPod.Status) 114 return err 115 } 116 117 // RealPodUpdaterWithMetric todo: implement with emitting metrics on updating 118 type RealPodUpdaterWithMetric struct { 119 client kubernetes.Interface 120 RealPodUpdater 121 }