Skip to content

Commit

Permalink
Add logic for openebs namespace determination from cli code (#21)
Browse files Browse the repository at this point in the history
Signed-off-by: Abhinandan-Purkait <abhinandan.purkait@mayadata.io>
  • Loading branch information
Abhinandan-Purkait authored Jun 2, 2021
1 parent c616588 commit 1d0d034
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 17 deletions.
31 changes: 20 additions & 11 deletions client/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -130,6 +131,14 @@ 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 {
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) {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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")
}
Expand All @@ -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")
}
Expand All @@ -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")
}
Expand All @@ -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)
}
Expand Down
19 changes: 14 additions & 5 deletions kubectl-openebs/cli/command/describe/pvc_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,33 +80,36 @@ 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"},
Short: "Displays PersistentVolumeClaim information",
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
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")
}
// TODO: Make K8sClient to be able to determine openebs namespace by itself.
// 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")
}
Expand All @@ -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{}
Expand Down
15 changes: 15 additions & 0 deletions kubectl-openebs/cli/util/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,18 @@ const (
// 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",
}
)
6 changes: 5 additions & 1 deletion kubectl-openebs/cli/util/k8s_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -70,6 +71,9 @@ func GetCasTypeFromSC(v1SC *v1.StorageClass) string {
return v1SC.Parameters[OpenEBSCasTypeKeySc]
}
}
if v, ok := ProvsionerAndCasTypeMap[v1SC.Provisioner]; ok {
return v
}
return Unknown
}

Expand Down

0 comments on commit 1d0d034

Please sign in to comment.