From f555f883d8b2beacae2bb21226562eb1e1079d25 Mon Sep 17 00:00:00 2001
From: kmova <kiran.mova@mayadata.io>
Date: Sun, 5 Apr 2020 05:49:35 +0000
Subject: [PATCH 1/4] feat(localpv-device): allow local pv device on select
 devices

Ref: https://github.com/openebs/openebs/issues/2916

This PR makes use of the Label Selector capability
added in the BDC. More details: https://github.com/openebs/openebs/issues/2921

The BDC Label Selector feature makes it possible for
administrators to group a set of block devices and use
them for creating Local PV (device).

To use the Label Selector feature with Local PV (Devices)
the administrator is expected to group(or pool) a set of
block devices by assigning them the label:
 openebs.io/block-device-pool=< pool-name >.

The `<pool-name>` can be passed to Local PV storage class
via cas annotations. If the value is present, then Local PV
device provisioner will set the following additional selector
on the BDC:
 `openebs.io/block-device-pool=< pool-name >`

Signed-off-by: kmova <kiran.mova@mayadata.io>
---
 cmd/provisioner-localpv/app/config.go         | 47 +++++++++++++++++++
 .../app/helper_blockdevice.go                 | 16 +++++--
 .../app/provisioner_blockdevice.go            |  1 +
 pkg/blockdeviceclaim/v1alpha1/build.go        | 30 ++++++++++++
 4 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/cmd/provisioner-localpv/app/config.go b/cmd/provisioner-localpv/app/config.go
index 129d90a8b8..52253915e3 100644
--- a/cmd/provisioner-localpv/app/config.go
+++ b/cmd/provisioner-localpv/app/config.go
@@ -37,12 +37,45 @@ const (
 	//KeyPVStorageType defines if the PV should be backed
 	// a hostpath ( sub directory or a storage device)
 	KeyPVStorageType = "StorageType"
+
 	//KeyPVBasePath defines base directory for hostpath volumes
 	// can be configured via the StorageClass annotations.
 	KeyPVBasePath = "BasePath"
+
 	//KeyPVFSType defines filesystem type to be used with devices
 	// and can be configured via the StorageClass annotations.
 	KeyPVFSType = "FSType"
+
+	//KeyBDPoolName defines the value for the Block Device Pool
+	//label selector configured via the StorageClass annotations.
+	//User can group block devices across nodes to form a block
+	//device pool, by setting the label on block devices as:
+	//  openebs.io/block-device-pool=<pool-name>
+	//
+	//The <pool-name> used above can be passsed to the
+	//Local PV device provisioner via the StorageClass
+	//CAS annotations.
+	//
+	//Example: Local PV device StorageClass for picking devices
+	//labeled as: openebs.io/block-device-pool=pool-x
+	//will be as follows
+	//
+	// kind: StorageClass
+	// metadata:
+	//   name: openebs-device-pool-x
+	//   annotations:
+	//     openebs.io/cas-type: local
+	//     cas.openebs.io/config: |
+	//       - name: StorageType
+	//         value: "device"
+	//       - name: BlockDevicePoolName
+	//         value: "pool-x"
+	// provisioner: openebs.io/local
+	// volumeBindingMode: WaitForFirstConsumer
+	// reclaimPolicy: Delete
+	//
+	KeyBDPoolName = "BlockDevicePoolName"
+
 	//KeyPVRelativePath defines the alternate folder name under the BasePath
 	// By default, the pv name will be used as the folder name.
 	// KeyPVBasePath can be useful for providing the same underlying folder
@@ -139,6 +172,20 @@ func (c *VolumeConfig) GetFSType() string {
 	return fsType
 }
 
+//GetBDPoolName returns the block device pool label
+//value configured in StorageClass.
+//
+//Default is "", no device pool will be set and all
+//the available block devices can be used for creating
+//Local PV.
+func (c *VolumeConfig) GetBDPoolName() string {
+	bdPoolName := c.getValue(KeyBDPoolName)
+	if len(strings.TrimSpace(bdPoolName)) == 0 {
+		return ""
+	}
+	return bdPoolName
+}
+
 //GetPath returns a valid PV path based on the configuration
 // or an error. The Path is constructed using the following rules:
 // If AbsolutePath is specified return it. (Future)
diff --git a/cmd/provisioner-localpv/app/helper_blockdevice.go b/cmd/provisioner-localpv/app/helper_blockdevice.go
index f2c3238278..71ad96eb5c 100644
--- a/cmd/provisioner-localpv/app/helper_blockdevice.go
+++ b/cmd/provisioner-localpv/app/helper_blockdevice.go
@@ -65,6 +65,10 @@ type HelperBlockDeviceOptions struct {
 	bdcName string
 	//  volumeMode of PVC
 	volumeMode corev1.PersistentVolumeMode
+
+	//bdPoolName is the value passed for
+	// BlockDevicePoolName via StorageClass config
+	bdPoolName string
 }
 
 // validate checks that the required fields to create BDC
@@ -120,14 +124,20 @@ func (p *Provisioner) createBlockDeviceClaim(blkDevOpts *HelperBlockDeviceOption
 		return nil
 	}
 
-	bdcObj, err := blockdeviceclaim.NewBuilder().
+	bdcObjBuilder := blockdeviceclaim.NewBuilder().
 		WithNamespace(p.namespace).
 		WithName(bdcName).
 		WithHostName(blkDevOpts.nodeHostname).
 		WithCapacity(blkDevOpts.capacity).
 		WithFinalizer(LocalPVFinalizer).
-		WithBlockVolumeMode(blkDevOpts.volumeMode).
-		Build()
+		WithBlockVolumeMode(blkDevOpts.volumeMode)
+
+	// If bdPoolName is configure, set it on the BDC
+	if len(blkDevOpts.bdPoolName) > 0 {
+		bdcObjBuilder.WithBlockDevicePoolName(blkDevOpts.bdPoolName)
+	}
+
+	bdcObj, err := bdcObjBuilder.Build()
 
 	if err != nil {
 		//TODO : Need to relook at this error
diff --git a/cmd/provisioner-localpv/app/provisioner_blockdevice.go b/cmd/provisioner-localpv/app/provisioner_blockdevice.go
index 18bec2649e..4ad61468a7 100644
--- a/cmd/provisioner-localpv/app/provisioner_blockdevice.go
+++ b/cmd/provisioner-localpv/app/provisioner_blockdevice.go
@@ -45,6 +45,7 @@ func (p *Provisioner) ProvisionBlockDevice(opts pvController.VolumeOptions, volu
 		name:         name,
 		capacity:     capacity.String(),
 		volumeMode:   *opts.PVC.Spec.VolumeMode,
+		bdPoolName:   volumeConfig.GetBDPoolName(),
 	}
 
 	path, blkPath, err := p.getBlockDevicePath(blkDevOpts)
diff --git a/pkg/blockdeviceclaim/v1alpha1/build.go b/pkg/blockdeviceclaim/v1alpha1/build.go
index eb896413ef..25b559f0f9 100644
--- a/pkg/blockdeviceclaim/v1alpha1/build.go
+++ b/pkg/blockdeviceclaim/v1alpha1/build.go
@@ -31,8 +31,13 @@ const (
 
 	// StoragePoolKindCSPC holds the value of CStorPoolCluster
 	StoragePoolKindCSPC = "CStorPoolCluster"
+
 	// APIVersion holds the value of OpenEBS version
 	APIVersion = "openebs.io/v1alpha1"
+
+	// bdPoolKey defines the label selector key
+	// used for grouping block devices on a given node
+	bdPoolKey = "openebs.io/block-device-pool"
 )
 
 // Builder is the builder object for BlockDeviceClaim
@@ -323,3 +328,28 @@ func (b *Builder) WithBlockVolumeMode(mode corev1.PersistentVolumeMode) *Builder
 
 	return b
 }
+
+// WithBlockDevicePoolName appends (or creates) the BDC Label Selector
+// by setting the provided value to the fixed key
+// openebs.io/block-device-pool
+// This will enable the NDM to pick only devices that
+// match the node (hostname) and block device pool label.
+func (b *Builder) WithBlockDevicePoolName(bdPoolName string) *Builder {
+	if len(bdPoolName) == 0 {
+		b.errs = append(
+			b.errs,
+			errors.New("failed to build BDC object: missing block device pool name"),
+		)
+		return b
+	}
+
+	if b.BDC.Object.Spec.Selector == nil {
+		newmatchlabels := map[string]string{}
+		b.BDC.Object.Spec.Selector = &metav1.LabelSelector{
+			MatchLabels: newmatchlabels,
+		}
+	}
+
+	b.BDC.Object.Spec.Selector.MatchLabels[bdPoolKey] = bdPoolName
+	return b
+}

From 2f1d26386e2b47bcaa83a32d6abcaaa95d2fbc7a Mon Sep 17 00:00:00 2001
From: kmova <kiran.mova@mayadata.io>
Date: Mon, 6 Apr 2020 06:01:27 +0000
Subject: [PATCH 2/4] ut(blockdeviceclaim): for method WithBlockDevicePoolName

Signed-off-by: kmova <kiran.mova@mayadata.io>
---
 pkg/blockdeviceclaim/v1alpha1/build.go      |  8 +--
 pkg/blockdeviceclaim/v1alpha1/build_test.go | 63 ++++++++++++++++++++-
 2 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/pkg/blockdeviceclaim/v1alpha1/build.go b/pkg/blockdeviceclaim/v1alpha1/build.go
index 25b559f0f9..6d967bd293 100644
--- a/pkg/blockdeviceclaim/v1alpha1/build.go
+++ b/pkg/blockdeviceclaim/v1alpha1/build.go
@@ -344,10 +344,10 @@ func (b *Builder) WithBlockDevicePoolName(bdPoolName string) *Builder {
 	}
 
 	if b.BDC.Object.Spec.Selector == nil {
-		newmatchlabels := map[string]string{}
-		b.BDC.Object.Spec.Selector = &metav1.LabelSelector{
-			MatchLabels: newmatchlabels,
-		}
+		b.BDC.Object.Spec.Selector = &metav1.LabelSelector{}
+	}
+	if b.BDC.Object.Spec.Selector.MatchLabels == nil {
+		b.BDC.Object.Spec.Selector.MatchLabels = map[string]string{}
 	}
 
 	b.BDC.Object.Spec.Selector.MatchLabels[bdPoolKey] = bdPoolName
diff --git a/pkg/blockdeviceclaim/v1alpha1/build_test.go b/pkg/blockdeviceclaim/v1alpha1/build_test.go
index da1245747a..669a226b82 100644
--- a/pkg/blockdeviceclaim/v1alpha1/build_test.go
+++ b/pkg/blockdeviceclaim/v1alpha1/build_test.go
@@ -206,16 +206,46 @@ func TestBuildWithCapacity(t *testing.T) {
 	}
 }
 
+func TestBuilderWithBlockDevicePoolName(t *testing.T) {
+	tests := map[string]struct {
+		name      string
+		expectErr bool
+	}{
+		"Test Builder with pool name": {
+			name:      "test",
+			expectErr: false,
+		},
+		"Test Builder without pool name": {
+			name:      "",
+			expectErr: true,
+		},
+	}
+	for name, mock := range tests {
+		name, mock := name, mock
+		t.Run(name, func(t *testing.T) {
+			b := NewBuilder().WithBlockDevicePoolName(mock.name)
+			if mock.expectErr && len(b.errs) == 0 {
+				t.Fatalf("Test %q failed: expected error not to be nil", name)
+			}
+			if !mock.expectErr && len(b.errs) > 0 {
+				t.Fatalf("Test %q failed: expected error to be nil", name)
+			}
+		})
+	}
+}
+
 func TestBuild(t *testing.T) {
 	tests := map[string]struct {
 		name        string
 		capacity    string
+		poolName    string
 		expectedBDC *apis.BlockDeviceClaim
 		expectedErr bool
 	}{
 		"BDC with correct details": {
 			name:     "BDC1",
 			capacity: "10Ti",
+			poolName: "",
 			expectedBDC: &apis.BlockDeviceClaim{
 				ObjectMeta: metav1.ObjectMeta{Name: "BDC1"},
 				Spec: apis.DeviceClaimSpec{
@@ -228,9 +258,31 @@ func TestBuild(t *testing.T) {
 			},
 			expectedErr: false,
 		},
+		"BDC with correct details, including device pool": {
+			name:     "BDC1",
+			capacity: "10Ti",
+			poolName: "test",
+			expectedBDC: &apis.BlockDeviceClaim{
+				ObjectMeta: metav1.ObjectMeta{Name: "BDC1"},
+				Spec: apis.DeviceClaimSpec{
+					Resources: apis.DeviceClaimResources{
+						Requests: corev1.ResourceList{
+							corev1.ResourceName(ndm.ResourceStorage): fakeCapacity("10Ti"),
+						},
+					},
+					Selector: &metav1.LabelSelector{
+						MatchLabels: map[string]string{
+							bdPoolKey: "test",
+						},
+					},
+				},
+			},
+			expectedErr: false,
+		},
 		"BDC with error": {
 			name:        "",
 			capacity:    "500Gi",
+			poolName:    "test",
 			expectedBDC: nil,
 			expectedErr: true,
 		},
@@ -238,7 +290,16 @@ func TestBuild(t *testing.T) {
 	for name, mock := range tests {
 		name, mock := name, mock
 		t.Run(name, func(t *testing.T) {
-			bdcObj, err := NewBuilder().WithName(mock.name).WithCapacity(mock.capacity).Build()
+			bdcObjBuilder := NewBuilder().
+				WithName(mock.name).
+				WithCapacity(mock.capacity)
+
+			if len(mock.poolName) > 0 {
+				bdcObjBuilder.WithBlockDevicePoolName(mock.poolName)
+			}
+
+			bdcObj, err := bdcObjBuilder.Build()
+
 			if mock.expectedErr && err == nil {
 				t.Fatalf("Test %q failed: expected error not to be nil", name)
 			}

From 41a4a8b6d5b344b2fec0f6f63e625ab00eb18fbc Mon Sep 17 00:00:00 2001
From: kmova <kiran.mova@mayadata.io>
Date: Mon, 6 Apr 2020 17:48:12 +0000
Subject: [PATCH 3/4] feat(localpv-device): rename Block Device Pool to Tag

Signed-off-by: kmova <kiran.mova@mayadata.io>
---
 cmd/provisioner-localpv/app/config.go         | 40 ++++++++++---------
 .../app/helper_blockdevice.go                 | 12 +++---
 .../app/provisioner_blockdevice.go            |  2 +-
 pkg/blockdeviceclaim/v1alpha1/build.go        | 20 +++++-----
 pkg/blockdeviceclaim/v1alpha1/build_test.go   | 28 ++++++-------
 5 files changed, 52 insertions(+), 50 deletions(-)

diff --git a/cmd/provisioner-localpv/app/config.go b/cmd/provisioner-localpv/app/config.go
index 52253915e3..eac37cb518 100644
--- a/cmd/provisioner-localpv/app/config.go
+++ b/cmd/provisioner-localpv/app/config.go
@@ -46,35 +46,37 @@ const (
 	// and can be configured via the StorageClass annotations.
 	KeyPVFSType = "FSType"
 
-	//KeyBDPoolName defines the value for the Block Device Pool
+	//KeyBDTag defines the value for the Block Device Tag
 	//label selector configured via the StorageClass annotations.
-	//User can group block devices across nodes to form a block
-	//device pool, by setting the label on block devices as:
-	//  openebs.io/block-device-pool=<pool-name>
+	//User can group block devices across nodes by setting the
+	//label on block devices as:
+	//  openebs.io/block-device-tag=<tag-value>
 	//
-	//The <pool-name> used above can be passsed to the
+	//The <tag-value> used above can be passsed to the
 	//Local PV device provisioner via the StorageClass
-	//CAS annotations.
+	//CAS annotations, to specify that Local PV (device)
+	//should only make use of those block devices that
+	//tagged with the given <tag-value>.
 	//
 	//Example: Local PV device StorageClass for picking devices
-	//labeled as: openebs.io/block-device-pool=pool-x
+	//labeled as: openebs.io/block-device-tag=tag-x
 	//will be as follows
 	//
 	// kind: StorageClass
 	// metadata:
-	//   name: openebs-device-pool-x
+	//   name: openebs-device-tag-x
 	//   annotations:
 	//     openebs.io/cas-type: local
 	//     cas.openebs.io/config: |
 	//       - name: StorageType
 	//         value: "device"
-	//       - name: BlockDevicePoolName
-	//         value: "pool-x"
+	//       - name: BlockDeviceTag
+	//         value: "tag-x"
 	// provisioner: openebs.io/local
 	// volumeBindingMode: WaitForFirstConsumer
 	// reclaimPolicy: Delete
 	//
-	KeyBDPoolName = "BlockDevicePoolName"
+	KeyBDTag = "BlockDeviceTag"
 
 	//KeyPVRelativePath defines the alternate folder name under the BasePath
 	// By default, the pv name will be used as the folder name.
@@ -172,18 +174,18 @@ func (c *VolumeConfig) GetFSType() string {
 	return fsType
 }
 
-//GetBDPoolName returns the block device pool label
+//GetBDTagValue returns the block device tag
 //value configured in StorageClass.
 //
-//Default is "", no device pool will be set and all
-//the available block devices can be used for creating
-//Local PV.
-func (c *VolumeConfig) GetBDPoolName() string {
-	bdPoolName := c.getValue(KeyBDPoolName)
-	if len(strings.TrimSpace(bdPoolName)) == 0 {
+//Default is "", no device tag will be set and any
+//available block device (without labelled with tag)
+//can be used for creating Local PV(device).
+func (c *VolumeConfig) GetBDTagValue() string {
+	bdTagValue := c.getValue(KeyBDTag)
+	if len(strings.TrimSpace(bdTagValue)) == 0 {
 		return ""
 	}
-	return bdPoolName
+	return bdTagValue
 }
 
 //GetPath returns a valid PV path based on the configuration
diff --git a/cmd/provisioner-localpv/app/helper_blockdevice.go b/cmd/provisioner-localpv/app/helper_blockdevice.go
index 71ad96eb5c..1237a28d8f 100644
--- a/cmd/provisioner-localpv/app/helper_blockdevice.go
+++ b/cmd/provisioner-localpv/app/helper_blockdevice.go
@@ -66,9 +66,9 @@ type HelperBlockDeviceOptions struct {
 	//  volumeMode of PVC
 	volumeMode corev1.PersistentVolumeMode
 
-	//bdPoolName is the value passed for
-	// BlockDevicePoolName via StorageClass config
-	bdPoolName string
+	//bdTagValue is the value passed for
+	// BlockDeviceTag via StorageClass config
+	bdTagValue string
 }
 
 // validate checks that the required fields to create BDC
@@ -132,9 +132,9 @@ func (p *Provisioner) createBlockDeviceClaim(blkDevOpts *HelperBlockDeviceOption
 		WithFinalizer(LocalPVFinalizer).
 		WithBlockVolumeMode(blkDevOpts.volumeMode)
 
-	// If bdPoolName is configure, set it on the BDC
-	if len(blkDevOpts.bdPoolName) > 0 {
-		bdcObjBuilder.WithBlockDevicePoolName(blkDevOpts.bdPoolName)
+	// If bdTagValue is configure, set it on the BDC
+	if len(blkDevOpts.bdTagValue) > 0 {
+		bdcObjBuilder.WithBlockDeviceTag(blkDevOpts.bdTagValue)
 	}
 
 	bdcObj, err := bdcObjBuilder.Build()
diff --git a/cmd/provisioner-localpv/app/provisioner_blockdevice.go b/cmd/provisioner-localpv/app/provisioner_blockdevice.go
index 4ad61468a7..0c97088d90 100644
--- a/cmd/provisioner-localpv/app/provisioner_blockdevice.go
+++ b/cmd/provisioner-localpv/app/provisioner_blockdevice.go
@@ -45,7 +45,7 @@ func (p *Provisioner) ProvisionBlockDevice(opts pvController.VolumeOptions, volu
 		name:         name,
 		capacity:     capacity.String(),
 		volumeMode:   *opts.PVC.Spec.VolumeMode,
-		bdPoolName:   volumeConfig.GetBDPoolName(),
+		bdTagValue:   volumeConfig.GetBDTagValue(),
 	}
 
 	path, blkPath, err := p.getBlockDevicePath(blkDevOpts)
diff --git a/pkg/blockdeviceclaim/v1alpha1/build.go b/pkg/blockdeviceclaim/v1alpha1/build.go
index 6d967bd293..27b806d6d5 100644
--- a/pkg/blockdeviceclaim/v1alpha1/build.go
+++ b/pkg/blockdeviceclaim/v1alpha1/build.go
@@ -35,9 +35,9 @@ const (
 	// APIVersion holds the value of OpenEBS version
 	APIVersion = "openebs.io/v1alpha1"
 
-	// bdPoolKey defines the label selector key
-	// used for grouping block devices on a given node
-	bdPoolKey = "openebs.io/block-device-pool"
+	// bdTagKey defines the label selector key
+	// used for grouping block devices using a tag.
+	bdTagKey = "openebs.io/block-device-tag"
 )
 
 // Builder is the builder object for BlockDeviceClaim
@@ -329,16 +329,16 @@ func (b *Builder) WithBlockVolumeMode(mode corev1.PersistentVolumeMode) *Builder
 	return b
 }
 
-// WithBlockDevicePoolName appends (or creates) the BDC Label Selector
+// WithBlockDeviceTag appends (or creates) the BDC Label Selector
 // by setting the provided value to the fixed key
-// openebs.io/block-device-pool
+// openebs.io/block-device-tag
 // This will enable the NDM to pick only devices that
-// match the node (hostname) and block device pool label.
-func (b *Builder) WithBlockDevicePoolName(bdPoolName string) *Builder {
-	if len(bdPoolName) == 0 {
+// match the node (hostname) and block device tag value.
+func (b *Builder) WithBlockDeviceTag(bdTagValue string) *Builder {
+	if len(bdTagValue) == 0 {
 		b.errs = append(
 			b.errs,
-			errors.New("failed to build BDC object: missing block device pool name"),
+			errors.New("failed to build BDC object: missing block device tag value"),
 		)
 		return b
 	}
@@ -350,6 +350,6 @@ func (b *Builder) WithBlockDevicePoolName(bdPoolName string) *Builder {
 		b.BDC.Object.Spec.Selector.MatchLabels = map[string]string{}
 	}
 
-	b.BDC.Object.Spec.Selector.MatchLabels[bdPoolKey] = bdPoolName
+	b.BDC.Object.Spec.Selector.MatchLabels[bdTagKey] = bdTagValue
 	return b
 }
diff --git a/pkg/blockdeviceclaim/v1alpha1/build_test.go b/pkg/blockdeviceclaim/v1alpha1/build_test.go
index 669a226b82..916ede042d 100644
--- a/pkg/blockdeviceclaim/v1alpha1/build_test.go
+++ b/pkg/blockdeviceclaim/v1alpha1/build_test.go
@@ -206,24 +206,24 @@ func TestBuildWithCapacity(t *testing.T) {
 	}
 }
 
-func TestBuilderWithBlockDevicePoolName(t *testing.T) {
+func TestBuilderWithBlockDeviceTag(t *testing.T) {
 	tests := map[string]struct {
-		name      string
+		tag       string
 		expectErr bool
 	}{
-		"Test Builder with pool name": {
-			name:      "test",
+		"Test Builder with tag": {
+			tag:       "test",
 			expectErr: false,
 		},
-		"Test Builder without pool name": {
-			name:      "",
+		"Test Builder without tag": {
+			tag:       "",
 			expectErr: true,
 		},
 	}
 	for name, mock := range tests {
 		name, mock := name, mock
 		t.Run(name, func(t *testing.T) {
-			b := NewBuilder().WithBlockDevicePoolName(mock.name)
+			b := NewBuilder().WithBlockDeviceTag(mock.tag)
 			if mock.expectErr && len(b.errs) == 0 {
 				t.Fatalf("Test %q failed: expected error not to be nil", name)
 			}
@@ -238,14 +238,14 @@ func TestBuild(t *testing.T) {
 	tests := map[string]struct {
 		name        string
 		capacity    string
-		poolName    string
+		tagValue    string
 		expectedBDC *apis.BlockDeviceClaim
 		expectedErr bool
 	}{
 		"BDC with correct details": {
 			name:     "BDC1",
 			capacity: "10Ti",
-			poolName: "",
+			tagValue: "",
 			expectedBDC: &apis.BlockDeviceClaim{
 				ObjectMeta: metav1.ObjectMeta{Name: "BDC1"},
 				Spec: apis.DeviceClaimSpec{
@@ -261,7 +261,7 @@ func TestBuild(t *testing.T) {
 		"BDC with correct details, including device pool": {
 			name:     "BDC1",
 			capacity: "10Ti",
-			poolName: "test",
+			tagValue: "test",
 			expectedBDC: &apis.BlockDeviceClaim{
 				ObjectMeta: metav1.ObjectMeta{Name: "BDC1"},
 				Spec: apis.DeviceClaimSpec{
@@ -272,7 +272,7 @@ func TestBuild(t *testing.T) {
 					},
 					Selector: &metav1.LabelSelector{
 						MatchLabels: map[string]string{
-							bdPoolKey: "test",
+							bdTagKey: "test",
 						},
 					},
 				},
@@ -282,7 +282,7 @@ func TestBuild(t *testing.T) {
 		"BDC with error": {
 			name:        "",
 			capacity:    "500Gi",
-			poolName:    "test",
+			tagValue:    "test",
 			expectedBDC: nil,
 			expectedErr: true,
 		},
@@ -294,8 +294,8 @@ func TestBuild(t *testing.T) {
 				WithName(mock.name).
 				WithCapacity(mock.capacity)
 
-			if len(mock.poolName) > 0 {
-				bdcObjBuilder.WithBlockDevicePoolName(mock.poolName)
+			if len(mock.tagValue) > 0 {
+				bdcObjBuilder.WithBlockDeviceTag(mock.tagValue)
 			}
 
 			bdcObj, err := bdcObjBuilder.Build()

From 9da0aa72554f05ec66fb93ae2a6bc2570d38fec9 Mon Sep 17 00:00:00 2001
From: kmova <kiran.mova@mayadata.io>
Date: Tue, 7 Apr 2020 15:42:58 +0000
Subject: [PATCH 4/4] docs(localpv): update instruction on running bdd

Signed-off-by: kmova <kiran.mova@mayadata.io>
---
 tests/localpv/README.md     | 40 +++++++++++++++++++++++++++++++++++++
 tests/localpv/suite_test.go |  3 ++-
 2 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 tests/localpv/README.md

diff --git a/tests/localpv/README.md b/tests/localpv/README.md
new file mode 100644
index 0000000000..e4e0c99e7c
--- /dev/null
+++ b/tests/localpv/README.md
@@ -0,0 +1,40 @@
+# Local PV Provisioner BDD
+
+Local PV Provisioner BDD tests are developed using ginkgo & gomega libraries.
+
+## How to run the tests?
+
+### Pre-requisites
+
+- Install Ginkgo and Gomega on your development machine. 
+  ```
+  $ go get github.com/onsi/ginkgo/ginkgo
+  $ go get github.com/onsi/gomega/...
+  ```
+- Get your Kubernetes Cluster ready and make sure you can run 
+  kubectl from your development machine. 
+  Note down the path to the `kubeconfig` file used by kubectl 
+  to access your cluster.  Example: /home/<user>/.kube/config
+
+- (Optional) Set the KUBECONFIG environment variable on your 
+  development machine to point to the kubeconfig file. 
+  Example: KUBECONFIG=/home/<user>/.kube/config
+
+  If you do not set this ENV, you will have to pass the file 
+  to the ginkgo CLI
+
+- Some of the tests require block devices (that are not mounted)
+  to be available in the cluster.
+
+- Install required OpenEBS components. 
+  Example: `kubectl apply -f openebs-operator.yaml`
+
+### Run tests
+
+- Run the tests by being in the localpv tests folder. 
+  `$ cd $GOPATH/src/github.com/openebs/maya/tests/localpv/`
+  `$ ginkgo -v --`
+ 
+  In case the KUBECONFIG env is not configured, you can run:
+  `$ ginkgo -v -- -kubeconfig=/path/to/kubeconfig`
+
diff --git a/tests/localpv/suite_test.go b/tests/localpv/suite_test.go
index 9c89cf38cf..fed54a348d 100644
--- a/tests/localpv/suite_test.go
+++ b/tests/localpv/suite_test.go
@@ -16,6 +16,7 @@ package localpv
 import (
 	"flag"
 
+	"os"
 	"testing"
 
 	. "github.com/onsi/ginkgo"
@@ -45,7 +46,7 @@ func TestSource(t *testing.T) {
 }
 
 func init() {
-	flag.StringVar(&kubeConfigPath, "kubeconfig", "", "path to kubeconfig to invoke kubernetes API calls")
+	flag.StringVar(&kubeConfigPath, "kubeconfig", os.Getenv("KUBECONFIG"), "path to kubeconfig to invoke kubernetes API calls")
 }
 
 var ops *tests.Operations