From 85949065e083bf293d5ebf8d83369f5546658f9b Mon Sep 17 00:00:00 2001 From: Abhinandan-Purkait Date: Wed, 2 Jun 2021 19:41:15 +0530 Subject: [PATCH 1/4] Add logic for openebs namespace determination from cli code Signed-off-by: Abhinandan-Purkait --- client/k8s.go | 31 ++++++++++++------- .../cli/command/describe/describe.go | 1 - .../cli/command/describe/pvc_info.go | 19 +++++++++--- kubectl-openebs/cli/util/constant.go | 17 ++++++++++ kubectl-openebs/cli/util/k8s_utils.go | 6 +++- 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/client/k8s.go b/client/k8s.go index ceeb248a..77513fde 100644 --- a/client/k8s.go +++ b/client/k8s.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "path/filepath" + "strings" cstorv1 "github.com/openebs/api/v2/pkg/apis/cstor/v1" "github.com/openebs/api/v2/pkg/apis/openebs.io/v1alpha1" @@ -47,9 +48,9 @@ type K8sAPIVersion string // K8sClient provides the necessary utility to operate over // various K8s Kind objects type K8sClient struct { - // ns refers to K8s namespace where the operation + // Ns refers to K8s namespace where the operation // will be performed - ns string + Ns string // K8sCS refers to the Clientset capable of communicating // with the K8s cluster K8sCS kubernetes.Interface @@ -59,7 +60,7 @@ type K8sClient struct { } // NewK8sClient creates a new K8sClient -// TODO: improve K8sClientset instantiation. for example remove the ns from +// TODO: improve K8sClientset instantiation. for example remove the Ns from // K8sClient struct func NewK8sClient(ns string) (*K8sClient, error) { // get the appropriate clientsets & set the kubeconfig accordingly @@ -75,7 +76,7 @@ func NewK8sClient(ns string) (*K8sClient, error) { return nil, errors.Wrap(err, "failed to build OpenEBS clientset") } return &K8sClient{ - ns: ns, + Ns: ns, K8sCS: k8sCS, OpenebsCS: openebsCS, }, nil @@ -131,6 +132,14 @@ func homeDir() string { return os.Getenv("KUBECONFIG") } +func (k K8sClient) GetOpenEBSNamespace(casType string) (string, error) { + pods, err := k.K8sCS.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{LabelSelector: fmt.Sprintf("openebs.io/component-name=%s", util.CasTypeAndComponentNameMap[strings.ToLower(casType)])}) + if err != nil || len(pods.Items) == 0 { + return "", errors.New("unable to determine openebs namespace") + } + return pods.Items[0].Namespace, nil +} + // GetStorageClass using the K8sClient's storage class client func (k K8sClient) GetStorageClass(driver string) (*v1.StorageClass, error) { scs, err := k.K8sCS.StorageV1().StorageClasses().Get(context.TODO(), driver, metav1.GetOptions{}) @@ -160,7 +169,7 @@ func (k K8sClient) GetcStorVolumes() (*cstorv1.CStorVolumeList, error) { // GetcStorVolume fetches the volume object of the given name in the given namespace func (k K8sClient) GetcStorVolume(volName string) (*cstorv1.CStorVolume, error) { - volInfo, err := k.OpenebsCS.CstorV1().CStorVolumes(k.ns).Get(context.TODO(), volName, metav1.GetOptions{}) + volInfo, err := k.OpenebsCS.CstorV1().CStorVolumes(k.Ns).Get(context.TODO(), volName, metav1.GetOptions{}) if err != nil { return nil, errors.Wrapf(err, "error while while getting volume %s", volName) } @@ -210,9 +219,9 @@ func (k K8sClient) GetPV(name string) (*corev1.PersistentVolume, error) { // GetCVC used to get cStor Volume Config information for cStor a given volume using a cStorClient func (k K8sClient) GetCVC(name string) (*cstorv1.CStorVolumeConfig, error) { - cStorVolumeConfig, err := k.OpenebsCS.CstorV1().CStorVolumeConfigs(k.ns).Get(context.TODO(), name, metav1.GetOptions{}) + cStorVolumeConfig, err := k.OpenebsCS.CstorV1().CStorVolumeConfigs(k.Ns).Get(context.TODO(), name, metav1.GetOptions{}) if err != nil { - return nil, errors.Wrapf(err, "error while getting cStor Volume Config for %s in %s", name, k.ns) + return nil, errors.Wrapf(err, "error while getting cStor Volume Config for %s in %s", name, k.Ns) } return cStorVolumeConfig, nil } @@ -283,7 +292,7 @@ func (k K8sClient) GetCVA(volumeName string) (*cstorv1.CStorVolumeAttachment, er // GetCstorVolumeTargetPod for the passed volume to show details func (k K8sClient) GetCstorVolumeTargetPod(volumeClaim string, volumeName string) (*corev1.Pod, error) { - pods, err := k.K8sCS.CoreV1().Pods(k.ns).List(context.TODO(), metav1.ListOptions{LabelSelector: fmt.Sprintf("openebs.io/persistent-volume-claim=%s,openebs.io/persistent-volume=%s,openebs.io/target=cstor-target", volumeClaim, volumeName)}) + pods, err := k.K8sCS.CoreV1().Pods(k.Ns).List(context.TODO(), metav1.ListOptions{LabelSelector: fmt.Sprintf("openebs.io/persistent-volume-claim=%s,openebs.io/persistent-volume=%s,openebs.io/target=cstor-target", volumeClaim, volumeName)}) if err != nil || len(pods.Items) == 0 { return nil, errors.New("The target pod for the volume was not found") } @@ -292,7 +301,7 @@ func (k K8sClient) GetCstorVolumeTargetPod(volumeClaim string, volumeName string // GetcStorPool using the OpenEBS's Client func (k K8sClient) GetcStorPool(poolName string) (*cstorv1.CStorPoolInstance, error) { - cStorPool, err := k.OpenebsCS.CstorV1().CStorPoolInstances(k.ns).Get(context.TODO(), poolName, metav1.GetOptions{}) + cStorPool, err := k.OpenebsCS.CstorV1().CStorPoolInstances(k.Ns).Get(context.TODO(), poolName, metav1.GetOptions{}) if err != nil { return nil, errors.Wrapf(err, "Error while while getting cspi") } @@ -301,7 +310,7 @@ func (k K8sClient) GetcStorPool(poolName string) (*cstorv1.CStorPoolInstance, er // GetBlockDevice using the OpenEBS's Client func (k K8sClient) GetBlockDevice(bd string) (*v1alpha1.BlockDevice, error) { - blockDevice, err := k.OpenebsCS.OpenebsV1alpha1().BlockDevices(k.ns).Get(context.TODO(), bd, metav1.GetOptions{}) + blockDevice, err := k.OpenebsCS.OpenebsV1alpha1().BlockDevices(k.Ns).Get(context.TODO(), bd, metav1.GetOptions{}) if err != nil { return nil, errors.Wrapf(err, "Error while while getting block device") } @@ -311,7 +320,7 @@ func (k K8sClient) GetBlockDevice(bd string) (*v1alpha1.BlockDevice, error) { // GetCVRByPoolName using the OpenEBS's Client func (k K8sClient) GetCVRByPoolName(poolName string) (*cstorv1.CStorVolumeReplicaList, error) { label := "cstorpoolinstance.openebs.io/name" + "=" + poolName - CVRs, err := k.OpenebsCS.CstorV1().CStorVolumeReplicas(k.ns).List(context.TODO(), metav1.ListOptions{LabelSelector: label}) + CVRs, err := k.OpenebsCS.CstorV1().CStorVolumeReplicas(k.Ns).List(context.TODO(), metav1.ListOptions{LabelSelector: label}) if err != nil { return nil, errors.Wrapf(err, "error while getting cStor Volume Replica for pool %s", poolName) } diff --git a/kubectl-openebs/cli/command/describe/describe.go b/kubectl-openebs/cli/command/describe/describe.go index 46848a36..80c1274e 100644 --- a/kubectl-openebs/cli/command/describe/describe.go +++ b/kubectl-openebs/cli/command/describe/describe.go @@ -47,7 +47,6 @@ func NewCmdDescribe(rootCmd *cobra.Command) *cobra.Command { fmt.Println(volumeCommandHelpText) }, } - cmd.AddCommand( NewCmdDescribeVolume(), NewCmdDescribePVC(), diff --git a/kubectl-openebs/cli/command/describe/pvc_info.go b/kubectl-openebs/cli/command/describe/pvc_info.go index b05e1201..03d3ca3e 100644 --- a/kubectl-openebs/cli/command/describe/pvc_info.go +++ b/kubectl-openebs/cli/command/describe/pvc_info.go @@ -80,6 +80,7 @@ PV Status : {{.PVStatus}} // NewCmdDescribePVC Displays the pvc describe details func NewCmdDescribePVC() *cobra.Command { + var openebsNs string cmd := &cobra.Command{ Use: "pvc", Aliases: []string{"pvcs", "persistentvolumeclaims", "persistentvolumeclaim"}, @@ -87,18 +88,20 @@ func NewCmdDescribePVC() *cobra.Command { Long: pvcInfoCommandHelpText, Example: `kubectl openebs describe pvc cstor-vol-1 cstor-vol-2 -n storage`, Run: func(cmd *cobra.Command, args []string) { - var pvNs string // This namespace belongs to the PVC entered + var pvNs, openebsNamespace string // This namespace belongs to the PVC entered if pvNs, _ = cmd.Flags().GetString("namespace"); pvNs == "" { pvNs = "default" } - util.CheckErr(RunPVCInfo(cmd, args, pvNs), util.Fatal) + openebsNamespace, _ = cmd.Flags().GetString("openebs-namespace") + util.CheckErr(RunPVCInfo(cmd, args, pvNs, openebsNamespace), util.Fatal) }, } + cmd.Flags().StringVarP(&openebsNs, "openebs-namespace", "", "", "to read the openebs namespace from user.\nIf not provided it is determined from components.") return cmd } // RunPVCInfo runs info command and make call to display the results -func RunPVCInfo(cmd *cobra.Command, pvcs []string, ns string) error { +func RunPVCInfo(cmd *cobra.Command, pvcs []string, ns string, openebsNs string) error { if len(pvcs) == 0 { return errors.New("Please give at least one pvc name to describe") } @@ -106,7 +109,7 @@ func RunPVCInfo(cmd *cobra.Command, pvcs []string, ns string) error { // Below is currently hardcoded to support only if resources are in openebs ns // because the -n flag is used to take the pvc namespace and same cannot be used to // take the openebs namespace - clientset, err := client.NewK8sClient("openebs") + clientset, err := client.NewK8sClient(openebsNs) if err != nil { return errors.Wrap(err, "Failed to execute describe pvc command") } @@ -130,7 +133,13 @@ func RunPVCInfo(cmd *cobra.Command, pvcs []string, ns string) error { // Get the casType from the storage class and branch on basic of CSTOR and NON-CSTOR PVCs. casType := util.GetCasTypeFromSC(sc) if casType == util.CstorCasType { - + if openebsNs == "" { + nsFromCli, err := clientset.GetOpenEBSNamespace(util.CstorCasType) + if err != nil { + return errors.Wrap(err, "Error determining the openebs namespace, please specify using \"--openebs-namespace\" flag") + } + clientset.Ns = nsFromCli + } // Create Empty template objects and fill gradually when underlying sub CRs are identified. pvcInfo := util.CstorPVCInfo{} cvcInfo := util.CVCInfo{} diff --git a/kubectl-openebs/cli/util/constant.go b/kubectl-openebs/cli/util/constant.go index 24c74c7b..ad384866 100644 --- a/kubectl-openebs/cli/util/constant.go +++ b/kubectl-openebs/cli/util/constant.go @@ -39,8 +39,25 @@ const ( OpenEBSCasTypeKeySc = "cas-type" // CstorCasType cas type name CstorCasType = "cstor" + // CstorCasType cas type name + JivaCasType = "jiva" // Healthy cstor volume status Healthy = "Healthy" // StorageKey key present in pvc status.capacity StorageKey = "storage" ) + +var ( + // CasTypeAndComponentNameMap stores the component name of the corresponding cas type + CasTypeAndComponentNameMap = map[string]string{ + "cstor": "openebs-cstor-csi-controller", + } + // ProvsionerAndCasTypeMap stores the cas type name of the corresponding provisioner + ProvsionerAndCasTypeMap = map[string]string{ + "cstor.csi.openebs.io": "cstor", + "openebs.io/provisioner-iscsi": "jiva", + "openebs.io/local": "local", + "local.csi.openebs.io ": "localpv-lvm", + "zfs.csi.openebs.io": "localpv-zfs", + } +) diff --git a/kubectl-openebs/cli/util/k8s_utils.go b/kubectl-openebs/cli/util/k8s_utils.go index 23126e17..f7e8941f 100644 --- a/kubectl-openebs/cli/util/k8s_utils.go +++ b/kubectl-openebs/cli/util/k8s_utils.go @@ -17,10 +17,11 @@ limitations under the License. package util import ( + "strconv" + cstorv1 "github.com/openebs/api/v2/pkg/apis/cstor/v1" corev1 "k8s.io/api/core/v1" v1 "k8s.io/api/storage/v1" - "strconv" ) // GetUsedCapacityFromCVR as the healthy replicas would have the correct used capacity details @@ -70,6 +71,9 @@ func GetCasTypeFromSC(v1SC *v1.StorageClass) string { return v1SC.Parameters[OpenEBSCasTypeKeySc] } } + if _, ok := ProvsionerAndCasTypeMap[v1SC.Provisioner]; ok { + return ProvsionerAndCasTypeMap[v1SC.Provisioner] + } return Unknown } From 28955bb499208dfd46d25e8fa1ba2b04da92d7ac Mon Sep 17 00:00:00 2001 From: Abhinandan-Purkait Date: Wed, 2 Jun 2021 19:59:39 +0530 Subject: [PATCH 2/4] golint caught fixes Signed-off-by: Abhinandan-Purkait --- client/k8s.go | 2 +- kubectl-openebs/cli/util/constant.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/k8s.go b/client/k8s.go index 77513fde..1c6627bc 100644 --- a/client/k8s.go +++ b/client/k8s.go @@ -131,7 +131,7 @@ func homeDir() string { } return os.Getenv("KUBECONFIG") } - +// GetOpenEBSNamespace from the specific engine component based on cas-type func (k K8sClient) GetOpenEBSNamespace(casType string) (string, error) { pods, err := k.K8sCS.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{LabelSelector: fmt.Sprintf("openebs.io/component-name=%s", util.CasTypeAndComponentNameMap[strings.ToLower(casType)])}) if err != nil || len(pods.Items) == 0 { diff --git a/kubectl-openebs/cli/util/constant.go b/kubectl-openebs/cli/util/constant.go index ad384866..dc61f01d 100644 --- a/kubectl-openebs/cli/util/constant.go +++ b/kubectl-openebs/cli/util/constant.go @@ -39,8 +39,6 @@ const ( OpenEBSCasTypeKeySc = "cas-type" // CstorCasType cas type name CstorCasType = "cstor" - // CstorCasType cas type name - JivaCasType = "jiva" // Healthy cstor volume status Healthy = "Healthy" // StorageKey key present in pvc status.capacity From 28276bded7fb1a638b04c6759cc8279b3b07f9eb Mon Sep 17 00:00:00 2001 From: Abhinandan-Purkait Date: Wed, 2 Jun 2021 20:02:27 +0530 Subject: [PATCH 3/4] remove changes in describe.go Signed-off-by: Abhinandan-Purkait --- kubectl-openebs/cli/command/describe/describe.go | 1 + 1 file changed, 1 insertion(+) diff --git a/kubectl-openebs/cli/command/describe/describe.go b/kubectl-openebs/cli/command/describe/describe.go index 80c1274e..46848a36 100644 --- a/kubectl-openebs/cli/command/describe/describe.go +++ b/kubectl-openebs/cli/command/describe/describe.go @@ -47,6 +47,7 @@ func NewCmdDescribe(rootCmd *cobra.Command) *cobra.Command { fmt.Println(volumeCommandHelpText) }, } + cmd.AddCommand( NewCmdDescribeVolume(), NewCmdDescribePVC(), From 5c60f6c7086aba7202f3a60d2e4c97871aa135f6 Mon Sep 17 00:00:00 2001 From: Harsh Vardhan Date: Wed, 2 Jun 2021 20:56:59 +0530 Subject: [PATCH 4/4] Simplify code & fix comments --- kubectl-openebs/cli/command/describe/pvc_info.go | 2 +- kubectl-openebs/cli/util/k8s_utils.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kubectl-openebs/cli/command/describe/pvc_info.go b/kubectl-openebs/cli/command/describe/pvc_info.go index 03d3ca3e..3470b1ea 100644 --- a/kubectl-openebs/cli/command/describe/pvc_info.go +++ b/kubectl-openebs/cli/command/describe/pvc_info.go @@ -88,7 +88,7 @@ func NewCmdDescribePVC() *cobra.Command { Long: pvcInfoCommandHelpText, Example: `kubectl openebs describe pvc cstor-vol-1 cstor-vol-2 -n storage`, Run: func(cmd *cobra.Command, args []string) { - var pvNs, openebsNamespace string // This namespace belongs to the PVC entered + var pvNs, openebsNamespace string if pvNs, _ = cmd.Flags().GetString("namespace"); pvNs == "" { pvNs = "default" } diff --git a/kubectl-openebs/cli/util/k8s_utils.go b/kubectl-openebs/cli/util/k8s_utils.go index f7e8941f..0009a82c 100644 --- a/kubectl-openebs/cli/util/k8s_utils.go +++ b/kubectl-openebs/cli/util/k8s_utils.go @@ -71,8 +71,8 @@ func GetCasTypeFromSC(v1SC *v1.StorageClass) string { return v1SC.Parameters[OpenEBSCasTypeKeySc] } } - if _, ok := ProvsionerAndCasTypeMap[v1SC.Provisioner]; ok { - return ProvsionerAndCasTypeMap[v1SC.Provisioner] + if v, ok := ProvsionerAndCasTypeMap[v1SC.Provisioner]; ok { + return v } return Unknown }