github.com/kubeflow/training-operator@v1.7.0/pkg/common/util/reconciler_generic.go (about) 1 // Copyright 2021 The Kubeflow Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License 14 15 package util 16 17 import ( 18 "fmt" 19 "reflect" 20 "strings" 21 22 log "github.com/sirupsen/logrus" 23 24 kubeflowv1 "github.com/kubeflow/training-operator/pkg/apis/kubeflow.org/v1" 25 "github.com/kubeflow/training-operator/pkg/controller.v1/common" 26 "github.com/kubeflow/training-operator/pkg/controller.v1/expectation" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 "sigs.k8s.io/controller-runtime/pkg/event" 29 ) 30 31 // GenExpectationGenericKey generates an expectation key for {Kind} of a job 32 func GenExpectationGenericKey(jobKey string, replicaType string, pl string) string { 33 return jobKey + "/" + strings.ToLower(replicaType) + "/" + pl 34 } 35 36 // LoggerForGenericKind generates log entry for generic Kubernetes resource Kind 37 func LoggerForGenericKind(obj metav1.Object, kind string) *log.Entry { 38 job := "" 39 if controllerRef := metav1.GetControllerOf(obj); controllerRef != nil { 40 if controllerRef.Kind == kind { 41 job = obj.GetNamespace() + "." + controllerRef.Name 42 } 43 } 44 return log.WithFields(log.Fields{ 45 // We use job to match the key used in controller.go 46 // In controller.go we log the key used with the workqueue. 47 "job": job, 48 kind: obj.GetNamespace() + "." + obj.GetName(), 49 "uid": obj.GetUID(), 50 }) 51 } 52 53 // OnDependentCreateFuncGeneric modify expectations when dependent (pod/service) creation observed. 54 func OnDependentCreateFuncGeneric(exp expectation.ControllerExpectationsInterface) func(event.CreateEvent) bool { 55 return func(e event.CreateEvent) bool { 56 rtype := e.Object.GetLabels()[kubeflowv1.ReplicaTypeLabel] 57 if len(rtype) == 0 { 58 return false 59 } 60 61 if controllerRef := metav1.GetControllerOf(e.Object); controllerRef != nil { 62 jobKey := fmt.Sprintf("%s/%s", e.Object.GetNamespace(), controllerRef.Name) 63 var expectKey string 64 pl := strings.ToLower(e.Object.GetObjectKind().GroupVersionKind().Kind) + "s" 65 expectKey = GenExpectationGenericKey(jobKey, rtype, pl) 66 exp.CreationObserved(expectKey) 67 return true 68 } 69 70 return true 71 } 72 } 73 74 // OnDependentUpdateFuncGeneric modify expectations when dependent (pod/service) update observed. 75 func OnDependentUpdateFuncGeneric(jc *common.JobController) func(updateEvent event.UpdateEvent) bool { 76 return func(e event.UpdateEvent) bool { 77 newObj := e.ObjectNew 78 oldObj := e.ObjectOld 79 if newObj.GetResourceVersion() == oldObj.GetResourceVersion() { 80 // Periodic resync will send update events for all known pods. 81 // Two different versions of the same pod will always have different RVs. 82 return false 83 } 84 85 kind := jc.Controller.GetAPIGroupVersionKind().Kind 86 var logger = LoggerForGenericKind(newObj, kind) 87 88 newControllerRef := metav1.GetControllerOf(newObj) 89 oldControllerRef := metav1.GetControllerOf(oldObj) 90 controllerRefChanged := !reflect.DeepEqual(newControllerRef, oldControllerRef) 91 92 if controllerRefChanged && oldControllerRef != nil { 93 // The ControllerRef was changed. Sync the old controller, if any. 94 if job := resolveControllerRef(jc, oldObj.GetNamespace(), oldControllerRef); job != nil { 95 logger.Infof("%s controller ref updated: %v, %v", kind, newObj, oldObj) 96 return true 97 } 98 } 99 100 // If it has a controller ref, that's all that matters. 101 if newControllerRef != nil { 102 job := resolveControllerRef(jc, newObj.GetNamespace(), newControllerRef) 103 if job == nil { 104 return false 105 } 106 logger.Debugf("%s has a controller ref: %v, %v", kind, newObj, oldObj) 107 return true 108 } 109 return false 110 } 111 } 112 113 // OnDependentDeleteFuncGeneric modify expectations when dependent (pod/service) deletion observed. 114 func OnDependentDeleteFuncGeneric(exp expectation.ControllerExpectationsInterface) func(event.DeleteEvent) bool { 115 return func(e event.DeleteEvent) bool { 116 117 rtype := e.Object.GetLabels()[kubeflowv1.ReplicaTypeLabel] 118 if len(rtype) == 0 { 119 return false 120 } 121 122 if controllerRef := metav1.GetControllerOf(e.Object); controllerRef != nil { 123 jobKey := fmt.Sprintf("%s/%s", e.Object.GetNamespace(), controllerRef.Name) 124 pl := strings.ToLower(e.Object.GetObjectKind().GroupVersionKind().Kind) + "s" 125 var expectKey = GenExpectationGenericKey(jobKey, rtype, pl) 126 127 exp.DeletionObserved(expectKey) 128 return true 129 } 130 131 return true 132 } 133 }