github.com/openebs/node-disk-manager@v1.9.1-0.20230225014141-4531f06ffa1e/db/kubernetes/client.go (about) 1 /* 2 Copyright 2019 The OpenEBS 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 kubernetes 18 19 import ( 20 "context" 21 "fmt" 22 23 apis "github.com/openebs/node-disk-manager/api/v1alpha1" 24 "github.com/openebs/node-disk-manager/blockdevice" 25 26 "os" 27 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 "k8s.io/client-go/rest" 30 "k8s.io/klog/v2" 31 "sigs.k8s.io/controller-runtime/pkg/client" 32 "sigs.k8s.io/controller-runtime/pkg/client/config" 33 "sigs.k8s.io/controller-runtime/pkg/manager" 34 ) 35 36 const ( 37 // NamespaceENV is the name of environment variable to get the namespace 38 NamespaceENV = "NAMESPACE" 39 ) 40 41 const ( 42 // kubernetesLabelPrefix is the label prefix for kubernetes 43 kubernetesLabelPrefix = "kubernetes.io/" 44 45 // openebsLabelPrefix is the label prefix for openebs labels 46 openebsLabelPrefix = "openebs.io/" 47 48 // blockDeviceTag is the label suffix used to tag a blockdevice 49 blockDeviceTag = "block-device-tag" 50 51 // KubernetesHostNameLabel is the kubernetes hostname label 52 KubernetesHostNameLabel = kubernetesLabelPrefix + blockdevice.HostName 53 54 // BlockDeviceTagLabel is the label used to tag a blockdevice for 55 // a particular use case. 56 // BlockDevices having this label can only be claimed by BDCs which 57 // have a matching label selector. 58 BlockDeviceTagLabel = openebsLabelPrefix + blockDeviceTag 59 ) 60 61 // Client is the wrapper over the k8s client that will be used by 62 // NDM to interface with etcd 63 type Client struct { 64 // cfg is configuration used to generate the client 65 cfg *rest.Config 66 67 // client is the controller-runtime client used to interface with etcd 68 client client.Client 69 70 // namespace in which this client is operating 71 namespace string 72 } 73 74 // New creates a new client object using the default config 75 func New() (Client, error) { 76 77 c := Client{} 78 79 // get the kube cfg 80 cfg, err := config.GetConfig() 81 if err != nil { 82 klog.Errorf("error getting cfg. %v", err) 83 return c, err 84 } 85 86 c.cfg = cfg 87 88 klog.V(2).Info("Client config created.") 89 90 err = c.setNamespace() 91 if err != nil { 92 klog.Errorf("error setting namespace for client. %v", err) 93 return c, err 94 } 95 96 klog.V(2).Infof("Namespace \"%s\" set for the client", c.namespace) 97 98 err = c.InitClient() 99 return c, err 100 } 101 102 // InitClient sets the client using the config 103 func (cl *Client) InitClient() error { 104 c, err := client.New(cl.cfg, client.Options{}) 105 if err != nil { 106 return err 107 } 108 cl.client = c 109 return nil 110 } 111 112 // SetClient sets the given client 113 func (cl *Client) SetClient(client2 client.Client) { 114 cl.client = client2 115 } 116 117 // RegisterAPI registers the API scheme in the client using the manager. 118 // This function needs to be called only once a client object 119 func (cl *Client) RegisterAPI() error { 120 mgr, err := manager.New(cl.cfg, manager.Options{Namespace: cl.namespace}) 121 if err != nil { 122 return err 123 } 124 125 // Setup Scheme for all resources 126 if err := apis.AddToScheme(mgr.GetScheme()); err != nil { 127 return err 128 } 129 return nil 130 } 131 132 // setNamespace sets the namespace in which NDM is running 133 func (cl *Client) setNamespace() error { 134 ns, ok := os.LookupEnv(NamespaceENV) 135 if !ok { 136 return fmt.Errorf("error getting namespace from ENV variable") 137 } 138 139 cl.namespace = ns 140 141 return nil 142 } 143 144 // ListBlockDevice lists the block device from etcd based on 145 // the filters used 146 func (cl *Client) ListBlockDevice(filters ...interface{}) ([]blockdevice.BlockDevice, error) { 147 bdList := &apis.BlockDeviceList{ 148 TypeMeta: metav1.TypeMeta{ 149 Kind: "BlockDevice", 150 APIVersion: "openebs.io/v1alpha1", 151 }, 152 } 153 154 // list only from this namespace 155 listOpts := []client.ListOption{ 156 client.InNamespace(cl.namespace), 157 } 158 159 for _, filter := range filters { 160 // convert the filter interface to relevant list option 161 opts := filter.(client.ListOption) 162 listOpts = append(listOpts, opts) 163 } 164 165 err := cl.client.List(context.TODO(), bdList, listOpts...) 166 if err != nil { 167 klog.Error("error in listing BDs. ", err) 168 return nil, err 169 } 170 171 blockDeviceList := make([]blockdevice.BlockDevice, 0) 172 err = convertBlockDeviceAPIListToBlockDeviceList(bdList, &blockDeviceList) 173 if err != nil { 174 return blockDeviceList, err 175 } 176 177 klog.V(4).Infof("no of blockdevices listed : %d", len(blockDeviceList)) 178 179 return blockDeviceList, nil 180 }