volcano.sh/volcano@v1.9.0/pkg/webhooks/admission/podgroups/mutate/mutate_podgroup.go (about) 1 /* 2 Copyright 2021 The Volcano 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 mutate 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 24 admissionv1 "k8s.io/api/admission/v1" 25 whv1 "k8s.io/api/admissionregistration/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/klog/v2" 28 29 schedulingv1beta1 "volcano.sh/apis/pkg/apis/scheduling/v1beta1" 30 "volcano.sh/volcano/pkg/webhooks/router" 31 "volcano.sh/volcano/pkg/webhooks/schema" 32 "volcano.sh/volcano/pkg/webhooks/util" 33 ) 34 35 func init() { 36 router.RegisterAdmission(service) 37 } 38 39 var service = &router.AdmissionService{ 40 Path: "/podgroups/mutate", 41 Func: PodGroups, 42 Config: config, 43 MutatingConfig: &whv1.MutatingWebhookConfiguration{ 44 Webhooks: []whv1.MutatingWebhook{{ 45 Name: "mutatepodgroup.volcano.sh", 46 Rules: []whv1.RuleWithOperations{ 47 { 48 Operations: []whv1.OperationType{whv1.Create}, 49 Rule: whv1.Rule{ 50 APIGroups: []string{schedulingv1beta1.SchemeGroupVersion.Group}, 51 APIVersions: []string{schedulingv1beta1.SchemeGroupVersion.Version}, 52 Resources: []string{"podgroups"}, 53 }, 54 }, 55 }, 56 }}, 57 }, 58 } 59 60 var config = &router.AdmissionServiceConfig{} 61 62 type patchOperation struct { 63 Op string `json:"op"` 64 Path string `json:"path"` 65 Value interface{} `json:"value,omitempty"` 66 } 67 68 // PodGroups mutate podgroups. 69 func PodGroups(ar admissionv1.AdmissionReview) *admissionv1.AdmissionResponse { 70 klog.V(3).Infof("Mutating %s podgroup %s.", ar.Request.Operation, ar.Request.Name) 71 72 podgroup, err := schema.DecodePodGroup(ar.Request.Object, ar.Request.Resource) 73 if err != nil { 74 return util.ToAdmissionResponse(err) 75 } 76 77 var patchBytes []byte 78 switch ar.Request.Operation { 79 case admissionv1.Create: 80 patchBytes, err = createPodGroupPatch(podgroup) 81 default: 82 return util.ToAdmissionResponse(fmt.Errorf("invalid operation `%s`, "+ 83 "expect operation to be `CREATE`", ar.Request.Operation)) 84 } 85 86 if err != nil { 87 return &admissionv1.AdmissionResponse{ 88 Allowed: false, 89 Result: &metav1.Status{Message: err.Error()}, 90 } 91 } 92 93 reviewResponse := admissionv1.AdmissionResponse{ 94 Allowed: true, 95 Patch: patchBytes, 96 } 97 if len(patchBytes) > 0 { 98 pt := admissionv1.PatchTypeJSONPatch 99 reviewResponse.PatchType = &pt 100 } 101 return &reviewResponse 102 } 103 104 func createPodGroupPatch(podgroup *schedulingv1beta1.PodGroup) ([]byte, error) { 105 var patch []patchOperation 106 if len(podgroup.Spec.Queue) == 0 { 107 queueName := schedulingv1beta1.DefaultQueue 108 ns, err := config.KubeClient.CoreV1().Namespaces().Get(context.TODO(), podgroup.Namespace, metav1.GetOptions{}) 109 if err == nil { 110 if val, ok := ns.GetAnnotations()[schedulingv1beta1.QueueNameAnnotationKey]; ok { 111 queueName = val 112 } 113 } 114 patch = append(patch, patchOperation{ 115 Op: "add", 116 Path: "/spec/queue", 117 Value: queueName, 118 }) 119 } 120 121 return json.Marshal(patch) 122 }