2014-11-23 15:47:25 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
2014-11-23 15:47:25 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
2018-09-05 04:51:25 +00:00
package gcepd
2014-11-23 15:47:25 +00:00
import (
2015-12-14 14:50:13 +00:00
"fmt"
2014-11-23 15:47:25 +00:00
"os"
2015-10-12 12:28:03 +00:00
"path"
2018-08-24 21:38:25 +00:00
"reflect"
"sort"
2014-11-23 15:47:25 +00:00
"testing"
2017-06-22 18:24:23 +00:00
"k8s.io/api/core/v1"
2017-01-17 03:38:19 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2017-01-11 14:09:48 +00:00
"k8s.io/apimachinery/pkg/types"
2017-06-23 20:56:37 +00:00
"k8s.io/client-go/kubernetes/fake"
2017-01-23 18:37:22 +00:00
utiltesting "k8s.io/client-go/util/testing"
2018-08-24 21:38:25 +00:00
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume"
2016-02-29 21:31:42 +00:00
volumetest "k8s.io/kubernetes/pkg/volume/testing"
2018-02-06 08:38:41 +00:00
"k8s.io/kubernetes/pkg/volume/util"
2018-08-24 21:38:25 +00:00
volumeutil "k8s.io/kubernetes/pkg/volume/util"
2014-11-23 15:47:25 +00:00
)
func TestCanSupport ( t * testing . T ) {
2016-01-25 21:57:42 +00:00
tmpDir , err := utiltesting . MkTmpdir ( "gcepdTest" )
2015-10-12 12:28:03 +00:00
if err != nil {
t . Fatalf ( "can't make a temp dir: %v" , err )
}
defer os . RemoveAll ( tmpDir )
2015-03-19 05:18:31 +00:00
plugMgr := volume . VolumePluginMgr { }
2017-07-26 00:48:26 +00:00
plugMgr . InitPlugins ( ProbeVolumePlugins ( ) , nil /* prober */ , volumetest . NewFakeVolumeHost ( tmpDir , nil , nil ) )
2014-11-23 15:47:25 +00:00
plug , err := plugMgr . FindPluginByName ( "kubernetes.io/gce-pd" )
if err != nil {
t . Errorf ( "Can't find the plugin by name" )
}
2016-05-30 02:22:22 +00:00
if plug . GetPluginName ( ) != "kubernetes.io/gce-pd" {
t . Errorf ( "Wrong name: %s" , plug . GetPluginName ( ) )
2014-11-23 15:47:25 +00:00
}
2016-11-18 20:58:56 +00:00
if ! plug . CanSupport ( & volume . Spec { Volume : & v1 . Volume { VolumeSource : v1 . VolumeSource { GCEPersistentDisk : & v1 . GCEPersistentDiskVolumeSource { } } } } ) {
2014-11-23 15:47:25 +00:00
t . Errorf ( "Expected true" )
}
2016-11-18 20:58:56 +00:00
if ! plug . CanSupport ( & volume . Spec { PersistentVolume : & v1 . PersistentVolume { Spec : v1 . PersistentVolumeSpec { PersistentVolumeSource : v1 . PersistentVolumeSource { GCEPersistentDisk : & v1 . GCEPersistentDiskVolumeSource { } } } } } ) {
2015-05-23 13:53:33 +00:00
t . Errorf ( "Expected true" )
}
2014-11-23 15:47:25 +00:00
}
2015-03-12 19:37:02 +00:00
func TestGetAccessModes ( t * testing . T ) {
2016-01-25 21:57:42 +00:00
tmpDir , err := utiltesting . MkTmpdir ( "gcepdTest" )
2015-10-12 12:28:03 +00:00
if err != nil {
t . Fatalf ( "can't make a temp dir: %v" , err )
}
defer os . RemoveAll ( tmpDir )
2015-03-12 19:37:02 +00:00
plugMgr := volume . VolumePluginMgr { }
2017-07-26 00:48:26 +00:00
plugMgr . InitPlugins ( ProbeVolumePlugins ( ) , nil /* prober */ , volumetest . NewFakeVolumeHost ( tmpDir , nil , nil ) )
2015-03-12 19:37:02 +00:00
plug , err := plugMgr . FindPersistentPluginByName ( "kubernetes.io/gce-pd" )
if err != nil {
t . Errorf ( "Can't find the plugin by name" )
}
2017-10-20 16:35:47 +00:00
if ! volumetest . ContainsAccessMode ( plug . GetAccessModes ( ) , v1 . ReadWriteOnce ) || ! volumetest . ContainsAccessMode ( plug . GetAccessModes ( ) , v1 . ReadOnlyMany ) {
2016-11-18 20:58:56 +00:00
t . Errorf ( "Expected two AccessModeTypes: %s and %s" , v1 . ReadWriteOnce , v1 . ReadOnlyMany )
2015-03-12 19:37:02 +00:00
}
}
2015-04-10 20:41:20 +00:00
type fakePDManager struct {
2014-11-23 15:47:25 +00:00
}
2018-08-24 21:38:25 +00:00
func ( fake * fakePDManager ) CreateVolume ( c * gcePersistentDiskProvisioner , node * v1 . Node , allowedTopologies [ ] v1 . TopologySelectorTerm ) ( volumeID string , volumeSizeGB int , labels map [ string ] string , fstype string , err error ) {
2016-03-05 23:11:17 +00:00
labels = make ( map [ string ] string )
labels [ "fakepdmanager" ] = "yes"
2018-08-24 21:38:25 +00:00
labels [ kubeletapis . LabelZoneFailureDomain ] = "zone1__zone2"
2017-02-01 14:23:10 +00:00
return "test-gce-volume-name" , 100 , labels , "" , nil
2015-12-14 14:50:13 +00:00
}
func ( fake * fakePDManager ) DeleteVolume ( cd * gcePersistentDiskDeleter ) error {
if cd . pdName != "test-gce-volume-name" {
return fmt . Errorf ( "Deleter got unexpected volume name: %s" , cd . pdName )
}
return nil
}
2018-08-24 21:38:25 +00:00
func getNodeSelectorRequirementWithKey ( key string , term v1 . NodeSelectorTerm ) ( * v1 . NodeSelectorRequirement , error ) {
for _ , r := range term . MatchExpressions {
if r . Key == key {
return & r , nil
}
}
return nil , fmt . Errorf ( "key %s not found" , key )
}
2014-11-23 15:47:25 +00:00
func TestPlugin ( t * testing . T ) {
2016-01-25 21:57:42 +00:00
tmpDir , err := utiltesting . MkTmpdir ( "gcepdTest" )
2015-10-12 12:28:03 +00:00
if err != nil {
t . Fatalf ( "can't make a temp dir: %v" , err )
}
defer os . RemoveAll ( tmpDir )
2015-03-19 05:18:31 +00:00
plugMgr := volume . VolumePluginMgr { }
2017-07-26 00:48:26 +00:00
plugMgr . InitPlugins ( ProbeVolumePlugins ( ) , nil /* prober */ , volumetest . NewFakeVolumeHost ( tmpDir , nil , nil ) )
2014-11-23 15:47:25 +00:00
plug , err := plugMgr . FindPluginByName ( "kubernetes.io/gce-pd" )
if err != nil {
t . Errorf ( "Can't find the plugin by name" )
}
2016-11-18 20:58:56 +00:00
spec := & v1 . Volume {
2014-11-23 15:47:25 +00:00
Name : "vol1" ,
2016-11-18 20:58:56 +00:00
VolumeSource : v1 . VolumeSource {
GCEPersistentDisk : & v1 . GCEPersistentDiskVolumeSource {
2014-11-23 15:47:25 +00:00
PDName : "pd" ,
FSType : "ext4" ,
} ,
} ,
}
2015-04-10 20:41:20 +00:00
fakeManager := & fakePDManager { }
fakeMounter := & mount . FakeMounter { }
2016-03-23 05:12:21 +00:00
mounter , err := plug . ( * gcePersistentDiskPlugin ) . newMounterInternal ( volume . NewSpecFromVolume ( spec ) , types . UID ( "poduid" ) , fakeManager , fakeMounter )
2014-11-23 15:47:25 +00:00
if err != nil {
2016-03-23 05:12:21 +00:00
t . Errorf ( "Failed to make a new Mounter: %v" , err )
2014-11-23 15:47:25 +00:00
}
2016-03-23 05:12:21 +00:00
if mounter == nil {
t . Errorf ( "Got a nil Mounter" )
2014-11-23 15:47:25 +00:00
}
2015-10-12 12:28:03 +00:00
volPath := path . Join ( tmpDir , "pods/poduid/volumes/kubernetes.io~gce-pd/vol1" )
2016-03-23 05:12:21 +00:00
path := mounter . GetPath ( )
2015-10-12 12:28:03 +00:00
if path != volPath {
2014-11-23 15:47:25 +00:00
t . Errorf ( "Got unexpected path: %s" , path )
}
2016-03-23 05:12:21 +00:00
if err := mounter . SetUp ( nil ) ; err != nil {
2014-11-23 15:47:25 +00:00
t . Errorf ( "Expected success, got: %v" , err )
}
if _ , err := os . Stat ( path ) ; err != nil {
if os . IsNotExist ( err ) {
t . Errorf ( "SetUp() failed, volume path not created: %s" , path )
} else {
t . Errorf ( "SetUp() failed: %v" , err )
}
}
2015-04-10 20:41:20 +00:00
fakeManager = & fakePDManager { }
2016-03-23 05:12:21 +00:00
unmounter , err := plug . ( * gcePersistentDiskPlugin ) . newUnmounterInternal ( "vol1" , types . UID ( "poduid" ) , fakeManager , fakeMounter )
2014-11-23 15:47:25 +00:00
if err != nil {
2016-03-23 05:12:21 +00:00
t . Errorf ( "Failed to make a new Unmounter: %v" , err )
2014-11-23 15:47:25 +00:00
}
2016-03-23 05:12:21 +00:00
if unmounter == nil {
t . Errorf ( "Got a nil Unmounter" )
2014-11-23 15:47:25 +00:00
}
2016-03-23 05:12:21 +00:00
if err := unmounter . TearDown ( ) ; err != nil {
2014-11-23 15:47:25 +00:00
t . Errorf ( "Expected success, got: %v" , err )
}
if _ , err := os . Stat ( path ) ; err == nil {
t . Errorf ( "TearDown() failed, volume path still exists: %s" , path )
} else if ! os . IsNotExist ( err ) {
2017-10-25 17:30:33 +00:00
t . Errorf ( "TearDown() failed: %v" , err )
2014-11-23 15:47:25 +00:00
}
2015-12-14 14:50:13 +00:00
// Test Provisioner
options := volume . VolumeOptions {
2018-10-05 19:59:38 +00:00
PVC : volumetest . CreateTestPVC ( "100Mi" , [ ] v1 . PersistentVolumeAccessMode { v1 . ReadWriteOnce } ) ,
2016-11-18 20:58:56 +00:00
PersistentVolumeReclaimPolicy : v1 . PersistentVolumeReclaimDelete ,
2015-12-14 14:50:13 +00:00
}
provisioner , err := plug . ( * gcePersistentDiskPlugin ) . newProvisionerInternal ( options , & fakePDManager { } )
2017-08-26 04:16:34 +00:00
if err != nil {
t . Errorf ( "Error creating new provisioner:%v" , err )
}
2018-05-23 08:12:20 +00:00
persistentSpec , err := provisioner . Provision ( nil , nil )
2015-12-14 14:50:13 +00:00
if err != nil {
t . Errorf ( "Provision() failed: %v" , err )
}
if persistentSpec . Spec . PersistentVolumeSource . GCEPersistentDisk . PDName != "test-gce-volume-name" {
t . Errorf ( "Provision() returned unexpected volume ID: %s" , persistentSpec . Spec . PersistentVolumeSource . GCEPersistentDisk . PDName )
}
2016-11-18 20:58:56 +00:00
cap := persistentSpec . Spec . Capacity [ v1 . ResourceStorage ]
2015-12-14 14:50:13 +00:00
size := cap . Value ( )
2018-07-13 18:33:35 +00:00
if size != 100 * util . GIB {
2015-12-14 14:50:13 +00:00
t . Errorf ( "Provision() returned unexpected volume size: %v" , size )
}
2016-03-05 23:11:17 +00:00
if persistentSpec . Labels [ "fakepdmanager" ] != "yes" {
2018-08-24 21:38:25 +00:00
t . Errorf ( "Provision() returned unexpected value for fakepdmanager: %v" , persistentSpec . Labels [ "fakepdmanager" ] )
}
if persistentSpec . Labels [ kubeletapis . LabelZoneFailureDomain ] != "zone1__zone2" {
t . Errorf ( "Provision() returned unexpected value for %s: %v" , kubeletapis . LabelZoneFailureDomain , persistentSpec . Labels [ kubeletapis . LabelZoneFailureDomain ] )
}
if persistentSpec . Spec . NodeAffinity == nil {
t . Errorf ( "Unexpected nil NodeAffinity found" )
}
if len ( persistentSpec . Spec . NodeAffinity . Required . NodeSelectorTerms ) != 1 {
t . Errorf ( "Unexpected number of NodeSelectorTerms" )
}
term := persistentSpec . Spec . NodeAffinity . Required . NodeSelectorTerms [ 0 ]
if len ( term . MatchExpressions ) != 2 {
t . Errorf ( "Unexpected number of NodeSelectorRequirements in volume NodeAffinity: %d" , len ( term . MatchExpressions ) )
}
r , _ := getNodeSelectorRequirementWithKey ( "fakepdmanager" , term )
if r == nil || r . Values [ 0 ] != "yes" || r . Operator != v1 . NodeSelectorOpIn {
t . Errorf ( "NodeSelectorRequirement fakepdmanager-in-yes not found in volume NodeAffinity" )
}
zones , _ := volumeutil . ZonesToSet ( "zone1,zone2" )
r , _ = getNodeSelectorRequirementWithKey ( kubeletapis . LabelZoneFailureDomain , term )
if r == nil {
t . Errorf ( "NodeSelectorRequirement %s-in-%v not found in volume NodeAffinity" , kubeletapis . LabelZoneFailureDomain , zones )
}
sort . Strings ( r . Values )
if ! reflect . DeepEqual ( r . Values , zones . List ( ) ) {
t . Errorf ( "ZoneFailureDomain elements %v does not match zone labels %v" , r . Values , zones )
2016-03-05 23:11:17 +00:00
}
2015-12-14 14:50:13 +00:00
// Test Deleter
volSpec := & volume . Spec {
PersistentVolume : persistentSpec ,
}
deleter , err := plug . ( * gcePersistentDiskPlugin ) . newDeleterInternal ( volSpec , & fakePDManager { } )
2017-08-26 04:16:34 +00:00
if err != nil {
t . Errorf ( "Error creating new deleter:%v" , err )
}
2015-12-14 14:50:13 +00:00
err = deleter . Delete ( )
if err != nil {
t . Errorf ( "Deleter() failed: %v" , err )
}
2014-11-23 15:47:25 +00:00
}
2015-07-01 14:50:39 +00:00
2018-09-21 16:17:10 +00:00
func TestMountOptions ( t * testing . T ) {
tmpDir , err := utiltesting . MkTmpdir ( "gcepdTest" )
if err != nil {
t . Fatalf ( "can't make a temp dir: %v" , err )
}
defer os . RemoveAll ( tmpDir )
plugMgr := volume . VolumePluginMgr { }
plugMgr . InitPlugins ( ProbeVolumePlugins ( ) , nil /* prober */ , volumetest . NewFakeVolumeHost ( tmpDir , nil , nil ) )
plug , err := plugMgr . FindPluginByName ( "kubernetes.io/gce-pd" )
if err != nil {
t . Errorf ( "Can't find the plugin by name" )
}
pv := & v1 . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta {
Name : "pvA" ,
} ,
Spec : v1 . PersistentVolumeSpec {
PersistentVolumeSource : v1 . PersistentVolumeSource {
GCEPersistentDisk : & v1 . GCEPersistentDiskVolumeSource { } ,
} ,
ClaimRef : & v1 . ObjectReference {
Name : "claimA" ,
} ,
MountOptions : [ ] string { "_netdev" } ,
} ,
}
fakeManager := & fakePDManager { }
fakeMounter := & mount . FakeMounter { }
mounter , err := plug . ( * gcePersistentDiskPlugin ) . newMounterInternal ( volume . NewSpecFromPersistentVolume ( pv , false ) , types . UID ( "poduid" ) , fakeManager , fakeMounter )
if err != nil {
t . Errorf ( "Failed to make a new Mounter: %v" , err )
}
if mounter == nil {
t . Errorf ( "Got a nil Mounter" )
}
if err := mounter . SetUp ( nil ) ; err != nil {
t . Errorf ( "Expected success, got: %v" , err )
}
mountOptions := fakeMounter . MountPoints [ 0 ] . Opts
expectedMountOptions := [ ] string { "_netdev" , "bind" }
if ! reflect . DeepEqual ( mountOptions , expectedMountOptions ) {
t . Errorf ( "Expected mount options to be %v got %v" , expectedMountOptions , mountOptions )
}
}
2015-07-01 14:50:39 +00:00
func TestPersistentClaimReadOnlyFlag ( t * testing . T ) {
2016-11-18 20:58:56 +00:00
pv := & v1 . PersistentVolume {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2015-07-01 14:50:39 +00:00
Name : "pvA" ,
} ,
2016-11-18 20:58:56 +00:00
Spec : v1 . PersistentVolumeSpec {
PersistentVolumeSource : v1 . PersistentVolumeSource {
GCEPersistentDisk : & v1 . GCEPersistentDiskVolumeSource { } ,
2015-07-01 14:50:39 +00:00
} ,
2016-11-18 20:58:56 +00:00
ClaimRef : & v1 . ObjectReference {
2015-07-01 14:50:39 +00:00
Name : "claimA" ,
} ,
} ,
}
2016-11-18 20:58:56 +00:00
claim := & v1 . PersistentVolumeClaim {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2015-07-01 14:50:39 +00:00
Name : "claimA" ,
Namespace : "nsA" ,
} ,
2016-11-18 20:58:56 +00:00
Spec : v1 . PersistentVolumeClaimSpec {
2015-07-01 14:50:39 +00:00
VolumeName : "pvA" ,
} ,
2016-11-18 20:58:56 +00:00
Status : v1 . PersistentVolumeClaimStatus {
Phase : v1 . ClaimBound ,
2015-07-01 14:50:39 +00:00
} ,
}
2016-01-15 05:00:58 +00:00
client := fake . NewSimpleClientset ( pv , claim )
2015-07-01 14:50:39 +00:00
2016-01-25 21:57:42 +00:00
tmpDir , err := utiltesting . MkTmpdir ( "gcepdTest" )
2015-10-12 12:28:03 +00:00
if err != nil {
t . Fatalf ( "can't make a temp dir: %v" , err )
}
defer os . RemoveAll ( tmpDir )
2015-07-01 14:50:39 +00:00
plugMgr := volume . VolumePluginMgr { }
2017-07-26 00:48:26 +00:00
plugMgr . InitPlugins ( ProbeVolumePlugins ( ) , nil /* prober */ , volumetest . NewFakeVolumeHost ( tmpDir , client , nil ) )
2015-07-01 14:50:39 +00:00
plug , _ := plugMgr . FindPluginByName ( gcePersistentDiskPluginName )
2016-03-23 05:12:21 +00:00
// readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes
2015-07-01 14:50:39 +00:00
spec := volume . NewSpecFromPersistentVolume ( pv , true )
2017-01-17 03:38:19 +00:00
pod := & v1 . Pod { ObjectMeta : metav1 . ObjectMeta { UID : types . UID ( "poduid" ) } }
2016-03-23 05:12:21 +00:00
mounter , _ := plug . NewMounter ( spec , pod , volume . VolumeOptions { } )
2016-12-19 07:42:14 +00:00
if mounter == nil {
t . Fatalf ( "Got a nil Mounter" )
}
2015-07-01 14:50:39 +00:00
2016-03-23 05:12:21 +00:00
if ! mounter . GetAttributes ( ) . ReadOnly {
t . Errorf ( "Expected true for mounter.IsReadOnly" )
2015-07-01 14:50:39 +00:00
}
}