123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920 |
- package validation
- import (
- "fmt"
- "strings"
- "testing"
- "k8s.io/apimachinery/pkg/api/resource"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- utilfeature "k8s.io/apiserver/pkg/util/feature"
- featuregatetesting "k8s.io/component-base/featuregate/testing"
- api "k8s.io/kubernetes/pkg/apis/core"
- "k8s.io/kubernetes/pkg/apis/storage"
- "k8s.io/kubernetes/pkg/features"
- utilpointer "k8s.io/utils/pointer"
- )
- var (
- deleteReclaimPolicy = api.PersistentVolumeReclaimDelete
- immediateMode1 = storage.VolumeBindingImmediate
- immediateMode2 = storage.VolumeBindingImmediate
- waitingMode = storage.VolumeBindingWaitForFirstConsumer
- invalidMode = storage.VolumeBindingMode("foo")
- inlineSpec = api.PersistentVolumeSpec{
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
- PersistentVolumeSource: api.PersistentVolumeSource{
- CSI: &api.CSIPersistentVolumeSource{
- Driver: "com.test.foo",
- VolumeHandle: "foobar",
- },
- },
- }
- )
- func TestValidateStorageClass(t *testing.T) {
- deleteReclaimPolicy := api.PersistentVolumeReclaimPolicy("Delete")
- retainReclaimPolicy := api.PersistentVolumeReclaimPolicy("Retain")
- recycleReclaimPolicy := api.PersistentVolumeReclaimPolicy("Recycle")
- successCases := []storage.StorageClass{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/foo-provisioner",
- Parameters: map[string]string{},
- ReclaimPolicy: &deleteReclaimPolicy,
- VolumeBindingMode: &immediateMode1,
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/foo-provisioner",
- ReclaimPolicy: &deleteReclaimPolicy,
- VolumeBindingMode: &immediateMode1,
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/foo-provisioner",
- Parameters: map[string]string{
- "kubernetes.io/foo-parameter": "free/form/string",
- "foo-parameter": "free-form-string",
- "foo-parameter2": "{\"embedded\": \"json\", \"with\": {\"structures\":\"inside\"}}",
- },
- ReclaimPolicy: &deleteReclaimPolicy,
- VolumeBindingMode: &immediateMode1,
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/foo-provisioner",
- ReclaimPolicy: &retainReclaimPolicy,
- VolumeBindingMode: &immediateMode1,
- },
- }
-
- for k, v := range successCases {
- if errs := ValidateStorageClass(&v); len(errs) != 0 {
- t.Errorf("Expected success for %d, got %v", k, errs)
- }
- }
-
- longParameters := make(map[string]string)
- totalSize := 0
- for totalSize < maxProvisionerParameterSize {
- k := fmt.Sprintf("param/%d", totalSize)
- v := fmt.Sprintf("value-%d", totalSize)
- longParameters[k] = v
- totalSize = totalSize + len(k) + len(v)
- }
- errorCases := map[string]storage.StorageClass{
- "namespace is present": {
- ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"},
- Provisioner: "kubernetes.io/foo-provisioner",
- ReclaimPolicy: &deleteReclaimPolicy,
- },
- "invalid provisioner": {
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/invalid/provisioner",
- ReclaimPolicy: &deleteReclaimPolicy,
- },
- "invalid empty parameter name": {
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/foo",
- Parameters: map[string]string{
- "": "value",
- },
- ReclaimPolicy: &deleteReclaimPolicy,
- },
- "provisioner: Required value": {
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "",
- ReclaimPolicy: &deleteReclaimPolicy,
- },
- "too long parameters": {
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/foo",
- Parameters: longParameters,
- ReclaimPolicy: &deleteReclaimPolicy,
- },
- "invalid reclaimpolicy": {
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Provisioner: "kubernetes.io/foo",
- ReclaimPolicy: &recycleReclaimPolicy,
- },
- }
-
- for testName, storageClass := range errorCases {
- if errs := ValidateStorageClass(&storageClass); len(errs) == 0 {
- t.Errorf("Expected failure for test: %s", testName)
- }
- }
- }
- func TestVolumeAttachmentValidation(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigration, true)()
- volumeName := "pv-name"
- empty := ""
- migrationEnabledSuccessCases := []storage.VolumeAttachment{
- {
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- NodeName: "mynode",
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: "foo-with-inlinespec"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- InlineVolumeSpec: &inlineSpec,
- },
- NodeName: "mynode",
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: "foo-with-status"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- NodeName: "mynode",
- },
- Status: storage.VolumeAttachmentStatus{
- Attached: true,
- AttachmentMetadata: map[string]string{
- "foo": "bar",
- },
- AttachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- DetachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: "foo-with-inlinespec-and-status"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- InlineVolumeSpec: &inlineSpec,
- },
- NodeName: "mynode",
- },
- Status: storage.VolumeAttachmentStatus{
- Attached: true,
- AttachmentMetadata: map[string]string{
- "foo": "bar",
- },
- AttachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- DetachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- },
- },
- }
- for _, volumeAttachment := range migrationEnabledSuccessCases {
- if errs := ValidateVolumeAttachment(&volumeAttachment); len(errs) != 0 {
- t.Errorf("expected success: %v %v", volumeAttachment, errs)
- }
- }
- migrationEnabledErrorCases := []storage.VolumeAttachment{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "",
- NodeName: "mynode",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: nil,
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &empty,
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- },
- Status: storage.VolumeAttachmentStatus{
- Attached: true,
- AttachmentMetadata: map[string]string{
- "foo": "bar",
- },
- AttachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- DetachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: strings.Repeat("a", maxVolumeErrorMessageSize+1),
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- },
- Status: storage.VolumeAttachmentStatus{
- Attached: true,
- AttachmentMetadata: map[string]string{
- "foo": strings.Repeat("a", maxAttachedVolumeMetadataSize),
- },
- AttachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- DetachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{},
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- InlineVolumeSpec: &inlineSpec,
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- InlineVolumeSpec: &api.PersistentVolumeSpec{
- Capacity: api.ResourceList{
- api.ResourceName(api.ResourceStorage): resource.MustParse("10G"),
- },
- AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
- PersistentVolumeSource: api.PersistentVolumeSource{
- FlexVolume: &api.FlexPersistentVolumeSource{
- Driver: "kubernetes.io/blue",
- FSType: "ext4",
- },
- },
- StorageClassName: "test-storage-class",
- },
- },
- },
- },
- }
- for _, volumeAttachment := range migrationEnabledErrorCases {
- if errs := ValidateVolumeAttachment(&volumeAttachment); len(errs) == 0 {
- t.Errorf("expected failure for test: %v", volumeAttachment)
- }
- }
-
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigration, false)()
- migrationDisabledSuccessCases := []storage.VolumeAttachment{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "node",
- Source: storage.VolumeAttachmentSource{
- InlineVolumeSpec: &inlineSpec,
- },
- },
- },
- }
- for _, volumeAttachment := range migrationDisabledSuccessCases {
- if errs := ValidateVolumeAttachment(&volumeAttachment); len(errs) != 0 {
- t.Errorf("expected success: %v %v", volumeAttachment, errs)
- }
- }
- }
- func TestVolumeAttachmentUpdateValidation(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIMigration, true)()
- volumeName := "foo"
- newVolumeName := "bar"
- old := storage.VolumeAttachment{
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{},
- NodeName: "mynode",
- },
- }
- successCases := []storage.VolumeAttachment{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{},
- NodeName: "mynode",
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{},
- NodeName: "mynode",
- },
- Status: storage.VolumeAttachmentStatus{
- Attached: true,
- AttachmentMetadata: map[string]string{
- "foo": "bar",
- },
- AttachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- DetachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- },
- },
- }
- for _, volumeAttachment := range successCases {
- volumeAttachment.Spec.Source = storage.VolumeAttachmentSource{}
- old.Spec.Source = storage.VolumeAttachmentSource{}
-
- volumeAttachment.Spec.Source.PersistentVolumeName = &volumeName
- old.Spec.Source.PersistentVolumeName = &volumeName
- if errs := ValidateVolumeAttachmentUpdate(&volumeAttachment, &old); len(errs) != 0 {
- t.Errorf("expected success: %+v", errs)
- }
- volumeAttachment.Spec.Source = storage.VolumeAttachmentSource{}
- old.Spec.Source = storage.VolumeAttachmentSource{}
-
- volumeAttachment.Spec.Source.InlineVolumeSpec = &inlineSpec
- old.Spec.Source.InlineVolumeSpec = &inlineSpec
- if errs := ValidateVolumeAttachmentUpdate(&volumeAttachment, &old); len(errs) != 0 {
- t.Errorf("expected success: %+v", errs)
- }
- }
-
- old.Spec.Source = storage.VolumeAttachmentSource{}
- old.Spec.Source.PersistentVolumeName = &volumeName
- errorCases := []storage.VolumeAttachment{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "another-attacher",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- NodeName: "mynode",
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &newVolumeName,
- },
- NodeName: "mynode",
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- NodeName: "anothernode",
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- InlineVolumeSpec: &inlineSpec,
- },
- NodeName: "mynode",
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- NodeName: "mynode",
- },
- Status: storage.VolumeAttachmentStatus{
- Attached: true,
- AttachmentMetadata: map[string]string{
- "foo": "bar",
- },
- AttachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: strings.Repeat("a", maxAttachedVolumeMetadataSize),
- },
- DetachError: &storage.VolumeError{
- Time: metav1.Time{},
- Message: "hello world",
- },
- },
- },
- }
- for _, volumeAttachment := range errorCases {
- if errs := ValidateVolumeAttachmentUpdate(&volumeAttachment, &old); len(errs) == 0 {
- t.Errorf("Expected failure for test: %+v", volumeAttachment)
- }
- }
- }
- func TestVolumeAttachmentValidationV1(t *testing.T) {
- volumeName := "pv-name"
- invalidVolumeName := "-invalid-@#$%^&*()-"
- successCases := []storage.VolumeAttachment{
- {
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- NodeName: "mynode",
- },
- },
- }
- for _, volumeAttachment := range successCases {
- if errs := ValidateVolumeAttachmentV1(&volumeAttachment); len(errs) != 0 {
- t.Errorf("expected success: %+v", errs)
- }
- }
- errorCases := []storage.VolumeAttachment{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "invalid-@#$%^&*()",
- NodeName: "mynode",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &volumeName,
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo"},
- Spec: storage.VolumeAttachmentSpec{
- Attacher: "myattacher",
- NodeName: "mynode",
- Source: storage.VolumeAttachmentSource{
- PersistentVolumeName: &invalidVolumeName,
- },
- },
- },
- }
- for _, volumeAttachment := range errorCases {
- if errs := ValidateVolumeAttachmentV1(&volumeAttachment); len(errs) == 0 {
- t.Errorf("Expected failure for test: %+v", volumeAttachment)
- }
- }
- }
- func makeClass(mode *storage.VolumeBindingMode, topologies []api.TopologySelectorTerm) *storage.StorageClass {
- return &storage.StorageClass{
- ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "foo"},
- Provisioner: "kubernetes.io/foo-provisioner",
- ReclaimPolicy: &deleteReclaimPolicy,
- VolumeBindingMode: mode,
- AllowedTopologies: topologies,
- }
- }
- type bindingTest struct {
- class *storage.StorageClass
- shouldSucceed bool
- }
- func TestValidateVolumeBindingMode(t *testing.T) {
- cases := map[string]bindingTest{
- "no mode": {
- class: makeClass(nil, nil),
- shouldSucceed: false,
- },
- "immediate mode": {
- class: makeClass(&immediateMode1, nil),
- shouldSucceed: true,
- },
- "waiting mode": {
- class: makeClass(&waitingMode, nil),
- shouldSucceed: true,
- },
- "invalid mode": {
- class: makeClass(&invalidMode, nil),
- shouldSucceed: false,
- },
- }
- for testName, testCase := range cases {
- errs := ValidateStorageClass(testCase.class)
- if testCase.shouldSucceed && len(errs) != 0 {
- t.Errorf("Expected success for test %q, got %v", testName, errs)
- }
- if !testCase.shouldSucceed && len(errs) == 0 {
- t.Errorf("Expected failure for test %q, got success", testName)
- }
- }
- }
- type updateTest struct {
- oldClass *storage.StorageClass
- newClass *storage.StorageClass
- shouldSucceed bool
- }
- func TestValidateUpdateVolumeBindingMode(t *testing.T) {
- noBinding := makeClass(nil, nil)
- immediateBinding1 := makeClass(&immediateMode1, nil)
- immediateBinding2 := makeClass(&immediateMode2, nil)
- waitBinding := makeClass(&waitingMode, nil)
- cases := map[string]updateTest{
- "old and new no mode": {
- oldClass: noBinding,
- newClass: noBinding,
- shouldSucceed: true,
- },
- "old and new same mode ptr": {
- oldClass: immediateBinding1,
- newClass: immediateBinding1,
- shouldSucceed: true,
- },
- "old and new same mode value": {
- oldClass: immediateBinding1,
- newClass: immediateBinding2,
- shouldSucceed: true,
- },
- "old no mode, new mode": {
- oldClass: noBinding,
- newClass: waitBinding,
- shouldSucceed: false,
- },
- "old mode, new no mode": {
- oldClass: waitBinding,
- newClass: noBinding,
- shouldSucceed: false,
- },
- "old and new different modes": {
- oldClass: waitBinding,
- newClass: immediateBinding1,
- shouldSucceed: false,
- },
- }
- for testName, testCase := range cases {
- errs := ValidateStorageClassUpdate(testCase.newClass, testCase.oldClass)
- if testCase.shouldSucceed && len(errs) != 0 {
- t.Errorf("Expected success for %v, got %v", testName, errs)
- }
- if !testCase.shouldSucceed && len(errs) == 0 {
- t.Errorf("Expected failure for %v, got success", testName)
- }
- }
- }
- func TestValidateAllowedTopologies(t *testing.T) {
- validTopology := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- },
- },
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone2"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node2"},
- },
- },
- },
- }
- topologyInvalidKey := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "/invalidkey",
- Values: []string{"zone1"},
- },
- },
- },
- }
- topologyLackOfValues := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{},
- },
- },
- },
- }
- topologyDupValues := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1", "node1"},
- },
- },
- },
- }
- topologyMultiValues := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1", "node2"},
- },
- },
- },
- }
- topologyEmptyMatchLabelExpressions := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: nil,
- },
- }
- topologyDupKeys := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node2"},
- },
- },
- },
- }
- topologyMultiTerm := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- },
- },
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node2"},
- },
- },
- },
- }
- topologyDupTermsIdentical := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- },
- },
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- },
- },
- }
- topologyExprsOneSameOneDiff := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- },
- },
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node2"},
- },
- },
- },
- }
- topologyValuesOneSameOneDiff := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1", "node2"},
- },
- },
- },
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1", "node3"},
- },
- },
- },
- }
- topologyDupTermsDiffExprOrder := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1"},
- },
- },
- },
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1"},
- },
- {
- Key: "kubernetes.io/hostname",
- Values: []string{"node1"},
- },
- },
- },
- }
- topologyDupTermsDiffValueOrder := []api.TopologySelectorTerm{
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone1", "zone2"},
- },
- },
- },
- {
- MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
- {
- Key: "failure-domain.beta.kubernetes.io/zone",
- Values: []string{"zone2", "zone1"},
- },
- },
- },
- }
- cases := map[string]bindingTest{
- "no topology": {
- class: makeClass(&waitingMode, nil),
- shouldSucceed: true,
- },
- "valid topology": {
- class: makeClass(&waitingMode, validTopology),
- shouldSucceed: true,
- },
- "topology invalid key": {
- class: makeClass(&waitingMode, topologyInvalidKey),
- shouldSucceed: false,
- },
- "topology lack of values": {
- class: makeClass(&waitingMode, topologyLackOfValues),
- shouldSucceed: false,
- },
- "duplicate TopologySelectorRequirement values": {
- class: makeClass(&waitingMode, topologyDupValues),
- shouldSucceed: false,
- },
- "multiple TopologySelectorRequirement values": {
- class: makeClass(&waitingMode, topologyMultiValues),
- shouldSucceed: true,
- },
- "empty MatchLabelExpressions": {
- class: makeClass(&waitingMode, topologyEmptyMatchLabelExpressions),
- shouldSucceed: false,
- },
- "duplicate MatchLabelExpression keys": {
- class: makeClass(&waitingMode, topologyDupKeys),
- shouldSucceed: false,
- },
- "duplicate MatchLabelExpression keys but across separate terms": {
- class: makeClass(&waitingMode, topologyMultiTerm),
- shouldSucceed: true,
- },
- "duplicate AllowedTopologies terms - identical": {
- class: makeClass(&waitingMode, topologyDupTermsIdentical),
- shouldSucceed: false,
- },
- "two AllowedTopologies terms, with a pair of the same MatchLabelExpressions and a pair of different ones": {
- class: makeClass(&waitingMode, topologyExprsOneSameOneDiff),
- shouldSucceed: true,
- },
- "two AllowedTopologies terms, with a pair of the same Values and a pair of different ones": {
- class: makeClass(&waitingMode, topologyValuesOneSameOneDiff),
- shouldSucceed: true,
- },
- "duplicate AllowedTopologies terms - different MatchLabelExpressions order": {
- class: makeClass(&waitingMode, topologyDupTermsDiffExprOrder),
- shouldSucceed: false,
- },
- "duplicate AllowedTopologies terms - different TopologySelectorRequirement values order": {
- class: makeClass(&waitingMode, topologyDupTermsDiffValueOrder),
- shouldSucceed: false,
- },
- }
- for testName, testCase := range cases {
- errs := ValidateStorageClass(testCase.class)
- if testCase.shouldSucceed && len(errs) != 0 {
- t.Errorf("Expected success for test %q, got %v", testName, errs)
- }
- if !testCase.shouldSucceed && len(errs) == 0 {
- t.Errorf("Expected failure for test %q, got success", testName)
- }
- }
- }
- func TestCSINodeValidation(t *testing.T) {
- driverName := "driver-name"
- driverName2 := "1io.kubernetes-storage-2-csi-driver3"
- longName := "my-a-b-c-d-c-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-ABCDEFGHIJKLMNOPQRSTUVWXYZ-driver"
- nodeID := "nodeA"
- successCases := []storage.CSINode{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io-kubernetes-storage-csi-driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo3"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "1io-kubernetes-storage-2-csi-driver3",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo4"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage-csi-driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo5"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: driverName2,
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo2"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "a",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo6"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "driver1",
- NodeID: "node1",
- TopologyKeys: []string{"key1", "key2"},
- },
- {
- Name: "driverB",
- NodeID: "nodeA",
- TopologyKeys: []string{"keyA", "keyB"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo7"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "driver1",
- NodeID: "node1",
- TopologyKeys: []string{"key1"},
- },
- {
- Name: "driver2",
- NodeID: "node1",
- TopologyKeys: []string{"key1"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo11"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(0)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo11"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(1)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo8"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "driver1",
- NodeID: "node1",
- TopologyKeys: []string{"zone_1", "zone.2"},
- },
- {
- Name: "driver2",
- NodeID: "node1",
- TopologyKeys: []string{"zone-3", "zone.4"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo9"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "driver1",
- NodeID: "node1",
- TopologyKeys: []string{"company-com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo10"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: driverName,
- NodeID: nodeID,
- },
- },
- },
- },
- }
- for _, csiNode := range successCases {
- if errs := ValidateCSINode(&csiNode); len(errs) != 0 {
- t.Errorf("expected success: %v", errs)
- }
- }
- errorCases := []storage.CSINode{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo3"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "_io.kubernetes.storage.csi.driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo4"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver/",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo5"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io/kubernetes/storage/csi~driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo6"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io_kubernetes_storage_csi_driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo7"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: longName,
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo8"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo9"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: driverName,
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", ""},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo10"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "driver1",
- NodeID: "node1",
- TopologyKeys: []string{"key1", "key2"},
- },
- {
- Name: "driver1",
- NodeID: "nodeX",
- TopologyKeys: []string{"keyA", "keyB"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo11"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "driver1",
- NodeID: "node1",
- TopologyKeys: []string{"key1", "key1"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo12"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "driver1",
- NodeID: "node1",
- TopologyKeys: []string{"key1"},
- },
- {
- Name: "driver2",
- NodeID: "nodeX",
- TopologyKeys: []string{"keyA", "keyA"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo13"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: driverName,
- NodeID: "",
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo11"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(-1)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo14"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: driverName,
- NodeID: "node1",
- TopologyKeys: []string{"Company.Com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- }
- for _, csiNode := range errorCases {
- if errs := ValidateCSINode(&csiNode); len(errs) == 0 {
- t.Errorf("Expected failure for test: %v", csiNode)
- }
- }
- }
- func TestCSINodeUpdateValidation(t *testing.T) {
-
-
-
- nodeID := "nodeA"
- old := storage.CSINode{
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(20)},
- },
- },
- },
- }
- successCases := []storage.CSINode{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(20)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(20)},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-3",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(30)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.new-driver",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(30)},
- },
- },
- },
- },
- }
- for _, csiNode := range successCases {
- if errs := ValidateCSINodeUpdate(&csiNode, &old); len(errs) != 0 {
- t.Errorf("expected success: %+v", errs)
- }
- }
- errorCases := []storage.CSINode{
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: "nodeB",
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(20)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(20)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(10)},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(20)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: utilpointer.Int32Ptr(21)},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- Allocatable: &storage.VolumeNodeResources{Count: nil},
- },
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "foo1"},
- Spec: storage.CSINodeSpec{
- Drivers: []storage.CSINodeDriver{
- {
- Name: "io.kubernetes.storage.csi.driver-1",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- {
- Name: "io.kubernetes.storage.csi.driver-2",
- NodeID: nodeID,
- TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
- },
- },
- },
- },
- }
- for _, csiNode := range errorCases {
- if errs := ValidateCSINodeUpdate(&csiNode, &old); len(errs) == 0 {
- t.Errorf("Expected failure for test: %+v", csiNode)
- }
- }
- }
- func TestCSIDriverValidation(t *testing.T) {
- driverName := "test-driver"
- longName := "my-a-b-c-d-c-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-ABCDEFGHIJKLMNOPQRSTUVWXYZ-driver"
- invalidName := "-invalid-@#$%^&*()-"
- attachRequired := true
- attachNotRequired := false
- podInfoOnMount := true
- notPodInfoOnMount := false
- successCases := []storage.CSIDriver{
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "io.kubernetes.storage.csi.driver"},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "io-kubernetes-storage-csi-driver"},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "1csi2driver3"},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: "io.kubernetes.storage.csi-driver"},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- storage.VolumeLifecyclePersistent,
- },
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- storage.VolumeLifecycleEphemeral,
- },
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- storage.VolumeLifecycleEphemeral,
- storage.VolumeLifecyclePersistent,
- },
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- storage.VolumeLifecycleEphemeral,
- storage.VolumeLifecyclePersistent,
- storage.VolumeLifecycleEphemeral,
- },
- },
- },
- }
- for _, csiDriver := range successCases {
- if errs := ValidateCSIDriver(&csiDriver); len(errs) != 0 {
- t.Errorf("expected success: %v", errs)
- }
- }
- errorCases := []storage.CSIDriver{
- {
- ObjectMeta: metav1.ObjectMeta{Name: invalidName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: longName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: nil,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: nil,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- "no-such-mode",
- },
- },
- },
- }
- for _, csiDriver := range errorCases {
- if errs := ValidateCSIDriver(&csiDriver); len(errs) == 0 {
- t.Errorf("Expected failure for test: %v", csiDriver)
- }
- }
- }
- func TestCSIDriverValidationUpdate(t *testing.T) {
- driverName := "test-driver"
- longName := "my-a-b-c-d-c-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-ABCDEFGHIJKLMNOPQRSTUVWXYZ-driver"
- invalidName := "-invalid-@#$%^&*()-"
- attachRequired := true
- attachNotRequired := false
- podInfoOnMount := true
- notPodInfoOnMount := false
- old := storage.CSIDriver{
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- storage.VolumeLifecycleEphemeral,
- storage.VolumeLifecyclePersistent,
- },
- },
- }
-
-
- successCases := []storage.CSIDriver{old}
- for _, csiDriver := range successCases {
- if errs := ValidateCSIDriverUpdate(&csiDriver, &old); len(errs) != 0 {
- t.Errorf("expected success for %+v: %v", csiDriver, errs)
- }
- }
- errorCases := []storage.CSIDriver{
- {
- ObjectMeta: metav1.ObjectMeta{Name: invalidName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachRequired,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
- ObjectMeta: metav1.ObjectMeta{Name: longName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: nil,
- PodInfoOnMount: &podInfoOnMount,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: nil,
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- "no-such-mode",
- },
- },
- },
- {
-
- ObjectMeta: metav1.ObjectMeta{Name: driverName},
- Spec: storage.CSIDriverSpec{
- AttachRequired: &attachNotRequired,
- PodInfoOnMount: ¬PodInfoOnMount,
- VolumeLifecycleModes: []storage.VolumeLifecycleMode{
- storage.VolumeLifecycleEphemeral,
- },
- },
- },
- }
- for _, csiDriver := range errorCases {
- if errs := ValidateCSIDriverUpdate(&csiDriver, &old); len(errs) == 0 {
- t.Errorf("Expected failure for test: %v", csiDriver)
- }
- }
- }
|