sigs.k8s.io/kueue@v0.6.2/pkg/util/admissioncheck/admissioncheck.go (about) 1 /* 2 Copyright 2023 The Kubernetes 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 admissioncheck 18 19 import ( 20 "context" 21 "errors" 22 "fmt" 23 24 "k8s.io/apimachinery/pkg/runtime/schema" 25 "k8s.io/apimachinery/pkg/types" 26 "sigs.k8s.io/controller-runtime/pkg/client" 27 "sigs.k8s.io/controller-runtime/pkg/client/apiutil" 28 29 kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1" 30 ) 31 32 var ( 33 ErrNilParametersRef = errors.New("missing parameters reference") 34 ErrBadParametersRef = errors.New("bad parameters reference") 35 ) 36 37 type objAsPtr[T any] interface { 38 client.Object 39 *T 40 } 41 42 type ConfigHelper[PtrT objAsPtr[T], T any] struct { 43 gk schema.GroupKind 44 client client.Client 45 } 46 47 func NewConfigHelper[PtrT objAsPtr[T], T any](c client.Client) (*ConfigHelper[PtrT, T], error) { 48 helper := ConfigHelper[PtrT, T]{ 49 client: c, 50 } 51 52 gvk, err := apiutil.GVKForObject(helper.newConfigPtr(), c.Scheme()) 53 if err != nil { 54 return nil, err 55 } 56 57 helper.gk = gvk.GroupKind() 58 return &helper, nil 59 } 60 61 func (ch *ConfigHelper[PtrT, T]) newConfigPtr() PtrT { 62 return PtrT(new(T)) 63 } 64 65 // isValidConfigReference - checks if the provided reference is addressing an object specific to this helper. 66 func (ch *ConfigHelper[PtrT, T]) isValidConfigReference(ref *kueue.AdmissionCheckParametersReference) (bool, error) { 67 return refValidForGK(ref, ch.gk) 68 } 69 70 // ConfigByName - get the config identified by its name 71 func (ch *ConfigHelper[PtrT, T]) ConfigByName(ctx context.Context, name string) (PtrT, error) { 72 configPtr := ch.newConfigPtr() 73 if err := ch.client.Get(ctx, types.NamespacedName{Name: name}, configPtr); err != nil { 74 return nil, err 75 } 76 return configPtr, nil 77 } 78 79 // ConfigFromRef - get the config identified by ref if valid. 80 func (ch *ConfigHelper[PtrT, T]) ConfigFromRef(ctx context.Context, ref *kueue.AdmissionCheckParametersReference) (PtrT, error) { 81 if isValid, err := ch.isValidConfigReference(ref); !isValid { 82 return nil, err 83 } 84 return ch.ConfigByName(ctx, ref.Name) 85 } 86 87 // ConfigForAdmissionCheck - get the configuration of the admission check identified by its name if it uses the 88 // helpers configuration type. 89 func (ch *ConfigHelper[PtrT, T]) ConfigForAdmissionCheck(ctx context.Context, checkName string) (PtrT, error) { 90 ac := &kueue.AdmissionCheck{} 91 if err := ch.client.Get(ctx, types.NamespacedName{Name: checkName}, ac); err != nil { 92 return nil, err 93 } 94 95 return ch.ConfigFromRef(ctx, ac.Spec.Parameters) 96 } 97 98 func refValidForGK(ref *kueue.AdmissionCheckParametersReference, gk schema.GroupKind) (bool, error) { 99 if ref == nil { 100 return false, ErrNilParametersRef 101 } 102 103 if len(ref.Name) == 0 { 104 return false, fmt.Errorf("empty name: %w", ErrBadParametersRef) 105 } 106 if gk.Group != ref.APIGroup { 107 return false, fmt.Errorf("wrong group %q, expecting %q: %w", ref.APIGroup, gk.Group, ErrBadParametersRef) 108 } 109 110 if gk.Kind != ref.Kind { 111 return false, fmt.Errorf("wrong kind %q, expecting %q: %w", ref.Kind, gk.Kind, ErrBadParametersRef) 112 } 113 return true, nil 114 } 115 116 func IndexerByConfigFunction(ControllerName string, gvk schema.GroupVersionKind) client.IndexerFunc { 117 gk := gvk.GroupKind() 118 return func(obj client.Object) []string { 119 ac, isAc := obj.(*kueue.AdmissionCheck) 120 if !isAc || ac == nil || ac.Spec.ControllerName != ControllerName { 121 return nil 122 } 123 if isvalid, _ := refValidForGK(ac.Spec.Parameters, gk); !isvalid { 124 return nil 125 } 126 return []string{ac.Spec.Parameters.Name} 127 } 128 } 129 130 // FilterForController - returns a list of check names controlled by ControllerName. 131 func FilterForController(ctx context.Context, c client.Client, states []kueue.AdmissionCheckState, ControllerName string) ([]string, error) { 132 var retActive []string 133 for _, state := range states { 134 ac := &kueue.AdmissionCheck{} 135 136 if err := c.Get(ctx, types.NamespacedName{Name: state.Name}, ac); client.IgnoreNotFound(err) != nil { 137 return nil, err 138 } else if err == nil && ac.Spec.ControllerName == ControllerName { 139 retActive = append(retActive, ac.Name) 140 } 141 } 142 return retActive, nil 143 }