sigs.k8s.io/cluster-api@v1.7.1/exp/util/util.go (about) 1 /* 2 Copyright 2020 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 util implements utility functions. 18 package util 19 20 import ( 21 "context" 22 23 "github.com/go-logr/logr" 24 "github.com/pkg/errors" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/apimachinery/pkg/runtime/schema" 27 "k8s.io/klog/v2" 28 "sigs.k8s.io/controller-runtime/pkg/client" 29 "sigs.k8s.io/controller-runtime/pkg/handler" 30 "sigs.k8s.io/controller-runtime/pkg/reconcile" 31 32 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 33 expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" 34 "sigs.k8s.io/cluster-api/util/labels/format" 35 ) 36 37 // GetOwnerMachinePool returns the MachinePool objects owning the current resource. 38 func GetOwnerMachinePool(ctx context.Context, c client.Client, obj metav1.ObjectMeta) (*expv1.MachinePool, error) { 39 for _, ref := range obj.GetOwnerReferences() { 40 if ref.Kind != "MachinePool" { 41 continue 42 } 43 gv, err := schema.ParseGroupVersion(ref.APIVersion) 44 if err != nil { 45 return nil, errors.WithStack(err) 46 } 47 if gv.Group == expv1.GroupVersion.Group { 48 return GetMachinePoolByName(ctx, c, obj.Namespace, ref.Name) 49 } 50 } 51 return nil, nil 52 } 53 54 // GetMachinePoolByName finds and returns a MachinePool object using the specified params. 55 func GetMachinePoolByName(ctx context.Context, c client.Client, namespace, name string) (*expv1.MachinePool, error) { 56 m := &expv1.MachinePool{} 57 key := client.ObjectKey{Name: name, Namespace: namespace} 58 if err := c.Get(ctx, key, m); err != nil { 59 return nil, err 60 } 61 return m, nil 62 } 63 64 // GetMachinePoolByLabels finds and returns a MachinePool object using the value of clusterv1.MachinePoolNameLabel. 65 // This differs from GetMachinePoolByName as the label value can be a hash. 66 func GetMachinePoolByLabels(ctx context.Context, c client.Client, namespace string, labels map[string]string) (*expv1.MachinePool, error) { 67 selector := map[string]string{} 68 if clusterName, ok := labels[clusterv1.ClusterNameLabel]; ok { 69 selector = map[string]string{clusterv1.ClusterNameLabel: clusterName} 70 } 71 72 if poolNameHash, ok := labels[clusterv1.MachinePoolNameLabel]; ok { 73 machinePoolList := &expv1.MachinePoolList{} 74 if err := c.List(ctx, machinePoolList, client.InNamespace(namespace), client.MatchingLabels(selector)); err != nil { 75 return nil, errors.Wrapf(err, "failed to list MachinePools using labels %v", selector) 76 } 77 78 for _, mp := range machinePoolList.Items { 79 if format.MustFormatValue(mp.Name) == poolNameHash { 80 return &mp, nil 81 } 82 } 83 } else { 84 return nil, errors.Errorf("labels missing required key `%s`", clusterv1.MachinePoolNameLabel) 85 } 86 87 return nil, nil 88 } 89 90 // MachinePoolToInfrastructureMapFunc returns a handler.MapFunc that watches for 91 // MachinePool events and returns reconciliation requests for an infrastructure provider object. 92 func MachinePoolToInfrastructureMapFunc(gvk schema.GroupVersionKind, log logr.Logger) handler.MapFunc { 93 log = log.WithValues("machine-pool-to-infra-map-func", gvk.String()) 94 return func(_ context.Context, o client.Object) []reconcile.Request { 95 m, ok := o.(*expv1.MachinePool) 96 if !ok { 97 log.V(4).Info("Not a machine pool", "Object", klog.KObj(o)) 98 return nil 99 } 100 log := log.WithValues("MachinePool", klog.KObj(o)) 101 102 gk := gvk.GroupKind() 103 ref := m.Spec.Template.Spec.InfrastructureRef 104 // Return early if the GroupKind doesn't match what we expect. 105 infraGK := ref.GroupVersionKind().GroupKind() 106 if gk != infraGK { 107 log.V(4).Info("Infra kind doesn't match filter group kind", "infrastructureGroupKind", infraGK.String()) 108 return nil 109 } 110 111 log.V(4).Info("Projecting object") 112 return []reconcile.Request{ 113 { 114 NamespacedName: client.ObjectKey{ 115 Namespace: m.Namespace, 116 Name: ref.Name, 117 }, 118 }, 119 } 120 } 121 }