@@ -17,6 +17,7 @@ limitations under the License.
17
17
package controller
18
18
19
19
import (
20
+ "errors"
20
21
"fmt"
21
22
"reflect"
22
23
"strconv"
@@ -31,6 +32,8 @@ import (
31
32
"k8s.io/api/core/v1"
32
33
"k8s.io/apimachinery/pkg/api/resource"
33
34
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
35
+ "k8s.io/client-go/kubernetes"
36
+ fakeclientset "k8s.io/client-go/kubernetes/fake"
34
37
)
35
38
36
39
const (
@@ -647,3 +650,284 @@ func TestGetSecretReference(t *testing.T) {
647
650
})
648
651
}
649
652
}
653
+
654
+ func TestProvision (t * testing.T ) {
655
+ var requestedBytes int64 = 100
656
+
657
+ type pvSpec struct {
658
+ Name string
659
+ ReclaimPolicy v1.PersistentVolumeReclaimPolicy
660
+ AccessModes []v1.PersistentVolumeAccessMode
661
+ Capacity v1.ResourceList
662
+ CSIPVS * v1.CSIPersistentVolumeSource
663
+ }
664
+
665
+ testcases := map [string ]struct {
666
+ volOpts controller.VolumeOptions
667
+ notNilSelector bool
668
+ driverNotReady bool
669
+ makeVolumeNameErr bool
670
+ getSecretRefErr bool
671
+ getCredentialsErr bool
672
+ volWithLessCap bool
673
+ expectedPVSpec * pvSpec
674
+ withSecretRefs bool
675
+ expectErr bool
676
+ }{
677
+ "normal provision" : {
678
+ volOpts : controller.VolumeOptions {
679
+ PersistentVolumeReclaimPolicy : v1 .PersistentVolumeReclaimDelete ,
680
+ PVName : "test-name" ,
681
+ PVC : createFakePVC (requestedBytes ),
682
+ Parameters : map [string ]string {
683
+ "fstype" : "ext3" ,
684
+ },
685
+ },
686
+ expectedPVSpec : & pvSpec {
687
+ Name : "test-testi" ,
688
+ ReclaimPolicy : v1 .PersistentVolumeReclaimDelete ,
689
+ Capacity : v1.ResourceList {
690
+ v1 .ResourceName (v1 .ResourceStorage ): bytesToGiQuantity (requestedBytes ),
691
+ },
692
+ CSIPVS : & v1.CSIPersistentVolumeSource {
693
+ Driver : "test-driver" ,
694
+ VolumeHandle : "test-volume-id" ,
695
+ FSType : "ext3" ,
696
+ VolumeAttributes : map [string ]string {
697
+ "storage.kubernetes.io/csiProvisionerIdentity" : "test-provisioner" ,
698
+ },
699
+ },
700
+ },
701
+ },
702
+ "provision with access modes" : {
703
+ volOpts : controller.VolumeOptions {
704
+ PersistentVolumeReclaimPolicy : v1 .PersistentVolumeReclaimDelete ,
705
+ PVName : "test-name" ,
706
+ PVC : & v1.PersistentVolumeClaim {
707
+ ObjectMeta : metav1.ObjectMeta {
708
+ UID : "testid" ,
709
+ },
710
+ Spec : v1.PersistentVolumeClaimSpec {
711
+ Selector : nil ,
712
+ Resources : v1.ResourceRequirements {
713
+ Requests : v1.ResourceList {
714
+ v1 .ResourceName (v1 .ResourceStorage ): resource .MustParse (strconv .FormatInt (requestedBytes , 10 )),
715
+ },
716
+ },
717
+ AccessModes : []v1.PersistentVolumeAccessMode {v1 .ReadWriteOnce },
718
+ },
719
+ },
720
+ Parameters : map [string ]string {},
721
+ },
722
+ expectedPVSpec : & pvSpec {
723
+ Name : "test-testi" ,
724
+ ReclaimPolicy : v1 .PersistentVolumeReclaimDelete ,
725
+ AccessModes : []v1.PersistentVolumeAccessMode {v1 .ReadWriteOnce },
726
+ Capacity : v1.ResourceList {
727
+ v1 .ResourceName (v1 .ResourceStorage ): bytesToGiQuantity (requestedBytes ),
728
+ },
729
+ CSIPVS : & v1.CSIPersistentVolumeSource {
730
+ Driver : "test-driver" ,
731
+ VolumeHandle : "test-volume-id" ,
732
+ FSType : "ext4" ,
733
+ VolumeAttributes : map [string ]string {
734
+ "storage.kubernetes.io/csiProvisionerIdentity" : "test-provisioner" ,
735
+ },
736
+ },
737
+ },
738
+ },
739
+ "provision with secrets" : {
740
+ volOpts : controller.VolumeOptions {
741
+ PVName : "test-name" ,
742
+ PVC : createFakePVC (requestedBytes ),
743
+ Parameters : map [string ]string {},
744
+ },
745
+ withSecretRefs : true ,
746
+ expectedPVSpec : & pvSpec {
747
+ Name : "test-testi" ,
748
+ Capacity : v1.ResourceList {
749
+ v1 .ResourceName (v1 .ResourceStorage ): bytesToGiQuantity (requestedBytes ),
750
+ },
751
+ CSIPVS : & v1.CSIPersistentVolumeSource {
752
+ Driver : "test-driver" ,
753
+ VolumeHandle : "test-volume-id" ,
754
+ FSType : "ext4" ,
755
+ VolumeAttributes : map [string ]string {
756
+ "storage.kubernetes.io/csiProvisionerIdentity" : "test-provisioner" ,
757
+ },
758
+ ControllerPublishSecretRef : & v1.SecretReference {
759
+ Name : "ctrlpublishsecret" ,
760
+ Namespace : "default" ,
761
+ },
762
+ NodeStageSecretRef : & v1.SecretReference {
763
+ Name : "nodestagesecret" ,
764
+ Namespace : "default" ,
765
+ },
766
+ NodePublishSecretRef : & v1.SecretReference {
767
+ Name : "nodepublishsecret" ,
768
+ Namespace : "default" ,
769
+ },
770
+ },
771
+ },
772
+ },
773
+ "fail to get secret reference" : {
774
+ volOpts : controller.VolumeOptions {
775
+ PVName : "test-name" ,
776
+ PVC : createFakePVC (requestedBytes ),
777
+ Parameters : map [string ]string {},
778
+ },
779
+ getSecretRefErr : true ,
780
+ expectErr : true ,
781
+ },
782
+ "fail not nil selector" : {
783
+ volOpts : controller.VolumeOptions {
784
+ PVName : "test-name" ,
785
+ PVC : createFakePVC (requestedBytes ),
786
+ },
787
+ notNilSelector : true ,
788
+ expectErr : true ,
789
+ },
790
+ "fail driver not ready" : {
791
+ volOpts : controller.VolumeOptions {
792
+ PVName : "test-name" ,
793
+ PVC : createFakePVC (requestedBytes ),
794
+ },
795
+ driverNotReady : true ,
796
+ expectErr : true ,
797
+ },
798
+ "fail to make volume name" : {
799
+ volOpts : controller.VolumeOptions {
800
+ PVName : "test-name" ,
801
+ PVC : createFakePVC (requestedBytes ),
802
+ },
803
+ makeVolumeNameErr : true ,
804
+ expectErr : true ,
805
+ },
806
+ "fail to get credentials" : {
807
+ volOpts : controller.VolumeOptions {
808
+ PVName : "test-name" ,
809
+ PVC : createFakePVC (requestedBytes ),
810
+ Parameters : map [string ]string {},
811
+ },
812
+ getCredentialsErr : true ,
813
+ expectErr : true ,
814
+ },
815
+ "fail vol with less capacity" : {
816
+ volOpts : controller.VolumeOptions {
817
+ PVName : "test-name" ,
818
+ PVC : createFakePVC (requestedBytes ),
819
+ Parameters : map [string ]string {},
820
+ },
821
+ volWithLessCap : true ,
822
+ expectErr : true ,
823
+ },
824
+ }
825
+
826
+ mockController , driver , identityServer , controllerServer , csiConn , err := createMockServer (t )
827
+ if err != nil {
828
+ t .Fatal (err )
829
+ }
830
+ defer mockController .Finish ()
831
+ defer driver .Stop ()
832
+
833
+ for k , tc := range testcases {
834
+ var clientSet kubernetes.Interface
835
+
836
+ if tc .withSecretRefs {
837
+ clientSet = fakeclientset .NewSimpleClientset (& v1.Secret {
838
+ ObjectMeta : metav1.ObjectMeta {
839
+ Name : "ctrlpublishsecret" ,
840
+ Namespace : "default" ,
841
+ },
842
+ }, & v1.Secret {
843
+ ObjectMeta : metav1.ObjectMeta {
844
+ Name : "nodestagesecret" ,
845
+ Namespace : "default" ,
846
+ },
847
+ }, & v1.Secret {
848
+ ObjectMeta : metav1.ObjectMeta {
849
+ Name : "nodepublishsecret" ,
850
+ Namespace : "default" ,
851
+ },
852
+ })
853
+ } else {
854
+ clientSet = fakeclientset .NewSimpleClientset ()
855
+ }
856
+
857
+ csiProvisioner := NewCSIProvisioner (clientSet , driver .Address (), 5 * time .Second , "test-provisioner" , "test" , 5 , csiConn .conn )
858
+
859
+ out := & csi.CreateVolumeResponse {
860
+ Volume : & csi.Volume {
861
+ CapacityBytes : requestedBytes ,
862
+ Id : "test-volume-id" ,
863
+ },
864
+ }
865
+
866
+ if tc .withSecretRefs {
867
+ tc .volOpts .Parameters [controllerPublishSecretNameKey ] = "ctrlpublishsecret"
868
+ tc .volOpts .Parameters [controllerPublishSecretNamespaceKey ] = "default"
869
+ tc .volOpts .Parameters [nodeStageSecretNameKey ] = "nodestagesecret"
870
+ tc .volOpts .Parameters [nodeStageSecretNamespaceKey ] = "default"
871
+ tc .volOpts .Parameters [nodePublishSecretNameKey ] = "nodepublishsecret"
872
+ tc .volOpts .Parameters [nodePublishSecretNamespaceKey ] = "default"
873
+ }
874
+
875
+ if tc .notNilSelector {
876
+ tc .volOpts .PVC .Spec .Selector = & metav1.LabelSelector {}
877
+ } else if tc .driverNotReady {
878
+ identityServer .EXPECT ().GetPluginCapabilities (gomock .Any (), gomock .Any ()).Return (nil , errors .New ("driver not ready" )).Times (1 )
879
+ } else if tc .makeVolumeNameErr {
880
+ tc .volOpts .PVC .ObjectMeta .UID = ""
881
+ provisionMockServerSetupExpectations (identityServer , controllerServer )
882
+ } else if tc .getSecretRefErr {
883
+ tc .volOpts .Parameters [provisionerSecretNameKey ] = ""
884
+ provisionMockServerSetupExpectations (identityServer , controllerServer )
885
+ } else if tc .getCredentialsErr {
886
+ tc .volOpts .Parameters [provisionerSecretNameKey ] = "secretx"
887
+ tc .volOpts .Parameters [provisionerSecretNamespaceKey ] = "default"
888
+ provisionMockServerSetupExpectations (identityServer , controllerServer )
889
+ } else if tc .volWithLessCap {
890
+ out .Volume .CapacityBytes = int64 (80 )
891
+ provisionMockServerSetupExpectations (identityServer , controllerServer )
892
+ controllerServer .EXPECT ().CreateVolume (gomock .Any (), gomock .Any ()).Return (out , nil ).Times (1 )
893
+ controllerServer .EXPECT ().DeleteVolume (gomock .Any (), gomock .Any ()).Return (& csi.DeleteVolumeResponse {}, nil ).Times (1 )
894
+ } else {
895
+ // Setup regular mock call expectations.
896
+ provisionMockServerSetupExpectations (identityServer , controllerServer )
897
+ controllerServer .EXPECT ().CreateVolume (gomock .Any (), gomock .Any ()).Return (out , nil ).Times (1 )
898
+ }
899
+
900
+ pv , err := csiProvisioner .Provision (tc .volOpts )
901
+ if tc .expectErr && err == nil {
902
+ t .Errorf ("test %q: Expected error, got none" , k )
903
+ }
904
+ if ! tc .expectErr && err != nil {
905
+ t .Errorf ("test %q: got error: %v" , k , err )
906
+ }
907
+
908
+ if tc .expectedPVSpec != nil {
909
+ if pv .Name != tc .expectedPVSpec .Name {
910
+ t .Errorf ("test %q: expected PV name: %q, got: %q" , k , tc .expectedPVSpec .Name , pv .Name )
911
+ }
912
+
913
+ if pv .Spec .PersistentVolumeReclaimPolicy != tc .expectedPVSpec .ReclaimPolicy {
914
+ t .Errorf ("test %q: expected reclaim policy: %v, got: %v" , k , tc .expectedPVSpec .ReclaimPolicy , pv .Spec .PersistentVolumeReclaimPolicy )
915
+ }
916
+
917
+ if ! reflect .DeepEqual (pv .Spec .AccessModes , tc .expectedPVSpec .AccessModes ) {
918
+ t .Errorf ("test %q: expected access modes: %v, got: %v" , k , tc .expectedPVSpec .AccessModes , pv .Spec .AccessModes )
919
+ }
920
+
921
+ if ! reflect .DeepEqual (pv .Spec .Capacity , tc .expectedPVSpec .Capacity ) {
922
+ t .Errorf ("test %q: expected capacity: %v, got: %v" , k , tc .expectedPVSpec .Capacity , pv .Spec .Capacity )
923
+ }
924
+
925
+ if tc .expectedPVSpec .CSIPVS != nil {
926
+ if ! reflect .DeepEqual (pv .Spec .PersistentVolumeSource .CSI , tc .expectedPVSpec .CSIPVS ) {
927
+ t .Errorf ("test %q: expected PV: %v, got: %v" , k , tc .expectedPVSpec .CSIPVS , pv .Spec .PersistentVolumeSource .CSI )
928
+ }
929
+ }
930
+
931
+ }
932
+ }
933
+ }
0 commit comments