Skip to content

Commit

Permalink
Merge pull request #91 from darkowlzz/provision-test
Browse files Browse the repository at this point in the history
Add controller provision tests
  • Loading branch information
lpabon committed May 31, 2018
2 parents e8dcc7f + 23529d8 commit b1def1c
Showing 1 changed file with 284 additions and 0 deletions.
284 changes: 284 additions & 0 deletions pkg/controller/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package controller

import (
"errors"
"fmt"
"reflect"
"strconv"
Expand All @@ -31,6 +32,8 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
fakeclientset "k8s.io/client-go/kubernetes/fake"
)

const (
Expand Down Expand Up @@ -647,3 +650,284 @@ func TestGetSecretReference(t *testing.T) {
})
}
}

func TestProvision(t *testing.T) {
var requestedBytes int64 = 100

type pvSpec struct {
Name string
ReclaimPolicy v1.PersistentVolumeReclaimPolicy
AccessModes []v1.PersistentVolumeAccessMode
Capacity v1.ResourceList
CSIPVS *v1.CSIPersistentVolumeSource
}

testcases := map[string]struct {
volOpts controller.VolumeOptions
notNilSelector bool
driverNotReady bool
makeVolumeNameErr bool
getSecretRefErr bool
getCredentialsErr bool
volWithLessCap bool
expectedPVSpec *pvSpec
withSecretRefs bool
expectErr bool
}{
"normal provision": {
volOpts: controller.VolumeOptions{
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
Parameters: map[string]string{
"fstype": "ext3",
},
},
expectedPVSpec: &pvSpec{
Name: "test-testi",
ReclaimPolicy: v1.PersistentVolumeReclaimDelete,
Capacity: v1.ResourceList{
v1.ResourceName(v1.ResourceStorage): bytesToGiQuantity(requestedBytes),
},
CSIPVS: &v1.CSIPersistentVolumeSource{
Driver: "test-driver",
VolumeHandle: "test-volume-id",
FSType: "ext3",
VolumeAttributes: map[string]string{
"storage.kubernetes.io/csiProvisionerIdentity": "test-provisioner",
},
},
},
},
"provision with access modes": {
volOpts: controller.VolumeOptions{
PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete,
PVName: "test-name",
PVC: &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
UID: "testid",
},
Spec: v1.PersistentVolumeClaimSpec{
Selector: nil,
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceName(v1.ResourceStorage): resource.MustParse(strconv.FormatInt(requestedBytes, 10)),
},
},
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
},
},
Parameters: map[string]string{},
},
expectedPVSpec: &pvSpec{
Name: "test-testi",
ReclaimPolicy: v1.PersistentVolumeReclaimDelete,
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
Capacity: v1.ResourceList{
v1.ResourceName(v1.ResourceStorage): bytesToGiQuantity(requestedBytes),
},
CSIPVS: &v1.CSIPersistentVolumeSource{
Driver: "test-driver",
VolumeHandle: "test-volume-id",
FSType: "ext4",
VolumeAttributes: map[string]string{
"storage.kubernetes.io/csiProvisionerIdentity": "test-provisioner",
},
},
},
},
"provision with secrets": {
volOpts: controller.VolumeOptions{
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
Parameters: map[string]string{},
},
withSecretRefs: true,
expectedPVSpec: &pvSpec{
Name: "test-testi",
Capacity: v1.ResourceList{
v1.ResourceName(v1.ResourceStorage): bytesToGiQuantity(requestedBytes),
},
CSIPVS: &v1.CSIPersistentVolumeSource{
Driver: "test-driver",
VolumeHandle: "test-volume-id",
FSType: "ext4",
VolumeAttributes: map[string]string{
"storage.kubernetes.io/csiProvisionerIdentity": "test-provisioner",
},
ControllerPublishSecretRef: &v1.SecretReference{
Name: "ctrlpublishsecret",
Namespace: "default",
},
NodeStageSecretRef: &v1.SecretReference{
Name: "nodestagesecret",
Namespace: "default",
},
NodePublishSecretRef: &v1.SecretReference{
Name: "nodepublishsecret",
Namespace: "default",
},
},
},
},
"fail to get secret reference": {
volOpts: controller.VolumeOptions{
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
Parameters: map[string]string{},
},
getSecretRefErr: true,
expectErr: true,
},
"fail not nil selector": {
volOpts: controller.VolumeOptions{
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
},
notNilSelector: true,
expectErr: true,
},
"fail driver not ready": {
volOpts: controller.VolumeOptions{
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
},
driverNotReady: true,
expectErr: true,
},
"fail to make volume name": {
volOpts: controller.VolumeOptions{
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
},
makeVolumeNameErr: true,
expectErr: true,
},
"fail to get credentials": {
volOpts: controller.VolumeOptions{
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
Parameters: map[string]string{},
},
getCredentialsErr: true,
expectErr: true,
},
"fail vol with less capacity": {
volOpts: controller.VolumeOptions{
PVName: "test-name",
PVC: createFakePVC(requestedBytes),
Parameters: map[string]string{},
},
volWithLessCap: true,
expectErr: true,
},
}

mockController, driver, identityServer, controllerServer, csiConn, err := createMockServer(t)
if err != nil {
t.Fatal(err)
}
defer mockController.Finish()
defer driver.Stop()

for k, tc := range testcases {
var clientSet kubernetes.Interface

if tc.withSecretRefs {
clientSet = fakeclientset.NewSimpleClientset(&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "ctrlpublishsecret",
Namespace: "default",
},
}, &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "nodestagesecret",
Namespace: "default",
},
}, &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "nodepublishsecret",
Namespace: "default",
},
})
} else {
clientSet = fakeclientset.NewSimpleClientset()
}

csiProvisioner := NewCSIProvisioner(clientSet, driver.Address(), 5*time.Second, "test-provisioner", "test", 5, csiConn.conn)

out := &csi.CreateVolumeResponse{
Volume: &csi.Volume{
CapacityBytes: requestedBytes,
Id: "test-volume-id",
},
}

if tc.withSecretRefs {
tc.volOpts.Parameters[controllerPublishSecretNameKey] = "ctrlpublishsecret"
tc.volOpts.Parameters[controllerPublishSecretNamespaceKey] = "default"
tc.volOpts.Parameters[nodeStageSecretNameKey] = "nodestagesecret"
tc.volOpts.Parameters[nodeStageSecretNamespaceKey] = "default"
tc.volOpts.Parameters[nodePublishSecretNameKey] = "nodepublishsecret"
tc.volOpts.Parameters[nodePublishSecretNamespaceKey] = "default"
}

if tc.notNilSelector {
tc.volOpts.PVC.Spec.Selector = &metav1.LabelSelector{}
} else if tc.driverNotReady {
identityServer.EXPECT().GetPluginCapabilities(gomock.Any(), gomock.Any()).Return(nil, errors.New("driver not ready")).Times(1)
} else if tc.makeVolumeNameErr {
tc.volOpts.PVC.ObjectMeta.UID = ""
provisionMockServerSetupExpectations(identityServer, controllerServer)
} else if tc.getSecretRefErr {
tc.volOpts.Parameters[provisionerSecretNameKey] = ""
provisionMockServerSetupExpectations(identityServer, controllerServer)
} else if tc.getCredentialsErr {
tc.volOpts.Parameters[provisionerSecretNameKey] = "secretx"
tc.volOpts.Parameters[provisionerSecretNamespaceKey] = "default"
provisionMockServerSetupExpectations(identityServer, controllerServer)
} else if tc.volWithLessCap {
out.Volume.CapacityBytes = int64(80)
provisionMockServerSetupExpectations(identityServer, controllerServer)
controllerServer.EXPECT().CreateVolume(gomock.Any(), gomock.Any()).Return(out, nil).Times(1)
controllerServer.EXPECT().DeleteVolume(gomock.Any(), gomock.Any()).Return(&csi.DeleteVolumeResponse{}, nil).Times(1)
} else {
// Setup regular mock call expectations.
provisionMockServerSetupExpectations(identityServer, controllerServer)
controllerServer.EXPECT().CreateVolume(gomock.Any(), gomock.Any()).Return(out, nil).Times(1)
}

pv, err := csiProvisioner.Provision(tc.volOpts)
if tc.expectErr && err == nil {
t.Errorf("test %q: Expected error, got none", k)
}
if !tc.expectErr && err != nil {
t.Errorf("test %q: got error: %v", k, err)
}

if tc.expectedPVSpec != nil {
if pv.Name != tc.expectedPVSpec.Name {
t.Errorf("test %q: expected PV name: %q, got: %q", k, tc.expectedPVSpec.Name, pv.Name)
}

if pv.Spec.PersistentVolumeReclaimPolicy != tc.expectedPVSpec.ReclaimPolicy {
t.Errorf("test %q: expected reclaim policy: %v, got: %v", k, tc.expectedPVSpec.ReclaimPolicy, pv.Spec.PersistentVolumeReclaimPolicy)
}

if !reflect.DeepEqual(pv.Spec.AccessModes, tc.expectedPVSpec.AccessModes) {
t.Errorf("test %q: expected access modes: %v, got: %v", k, tc.expectedPVSpec.AccessModes, pv.Spec.AccessModes)
}

if !reflect.DeepEqual(pv.Spec.Capacity, tc.expectedPVSpec.Capacity) {
t.Errorf("test %q: expected capacity: %v, got: %v", k, tc.expectedPVSpec.Capacity, pv.Spec.Capacity)
}

if tc.expectedPVSpec.CSIPVS != nil {
if !reflect.DeepEqual(pv.Spec.PersistentVolumeSource.CSI, tc.expectedPVSpec.CSIPVS) {
t.Errorf("test %q: expected PV: %v, got: %v", k, tc.expectedPVSpec.CSIPVS, pv.Spec.PersistentVolumeSource.CSI)
}
}

}
}
}

0 comments on commit b1def1c

Please sign in to comment.