glusterfs_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package glusterfs
  14. import (
  15. "fmt"
  16. "os"
  17. "reflect"
  18. "testing"
  19. gapi "github.com/heketi/heketi/pkg/glusterfs/api"
  20. "k8s.io/api/core/v1"
  21. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  22. "k8s.io/apimachinery/pkg/runtime"
  23. "k8s.io/apimachinery/pkg/types"
  24. "k8s.io/client-go/kubernetes/fake"
  25. core "k8s.io/client-go/testing"
  26. utiltesting "k8s.io/client-go/util/testing"
  27. "k8s.io/kubernetes/pkg/util/mount"
  28. "k8s.io/kubernetes/pkg/volume"
  29. volumetest "k8s.io/kubernetes/pkg/volume/testing"
  30. )
  31. func TestCanSupport(t *testing.T) {
  32. tmpDir, err := utiltesting.MkTmpdir("glusterfs_test")
  33. if err != nil {
  34. t.Fatalf("error creating temp dir: %v", err)
  35. }
  36. defer os.RemoveAll(tmpDir)
  37. plugMgr := volume.VolumePluginMgr{}
  38. plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
  39. plug, err := plugMgr.FindPluginByName("kubernetes.io/glusterfs")
  40. if err != nil {
  41. t.Errorf("Can't find the plugin by name")
  42. }
  43. if plug.GetPluginName() != "kubernetes.io/glusterfs" {
  44. t.Errorf("Wrong name: %s", plug.GetPluginName())
  45. }
  46. if plug.CanSupport(&volume.Spec{}) {
  47. t.Errorf("Expected false")
  48. }
  49. if plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{}}}) {
  50. t.Errorf("Expected false")
  51. }
  52. if !plug.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{Glusterfs: &v1.GlusterfsVolumeSource{}}}}) {
  53. t.Errorf("Expected true")
  54. }
  55. if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{}}}) {
  56. t.Errorf("Expected false")
  57. }
  58. if plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{}}}}) {
  59. t.Errorf("Expected false")
  60. }
  61. if !plug.CanSupport(&volume.Spec{PersistentVolume: &v1.PersistentVolume{Spec: v1.PersistentVolumeSpec{PersistentVolumeSource: v1.PersistentVolumeSource{Glusterfs: &v1.GlusterfsPersistentVolumeSource{}}}}}) {
  62. t.Errorf("Expected true")
  63. }
  64. }
  65. func TestGetAccessModes(t *testing.T) {
  66. tmpDir, err := utiltesting.MkTmpdir("glusterfs_test")
  67. if err != nil {
  68. t.Fatalf("error creating temp dir: %v", err)
  69. }
  70. defer os.RemoveAll(tmpDir)
  71. plugMgr := volume.VolumePluginMgr{}
  72. plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
  73. plug, err := plugMgr.FindPersistentPluginByName("kubernetes.io/glusterfs")
  74. if err != nil {
  75. t.Errorf("Can't find the plugin by name")
  76. }
  77. if !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteOnce) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadOnlyMany) || !volumetest.ContainsAccessMode(plug.GetAccessModes(), v1.ReadWriteMany) {
  78. t.Errorf("Expected three AccessModeTypes: %s, %s, and %s", v1.ReadWriteOnce, v1.ReadOnlyMany, v1.ReadWriteMany)
  79. }
  80. }
  81. func doTestPlugin(t *testing.T, spec *volume.Spec) {
  82. tmpDir, err := utiltesting.MkTmpdir("glusterfs_test")
  83. if err != nil {
  84. t.Fatalf("error creating temp dir: %v", err)
  85. }
  86. defer os.RemoveAll(tmpDir)
  87. plugMgr := volume.VolumePluginMgr{}
  88. plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, nil, nil))
  89. plug, err := plugMgr.FindPluginByName("kubernetes.io/glusterfs")
  90. if err != nil {
  91. t.Errorf("Can't find the plugin by name")
  92. }
  93. ep := &v1.Endpoints{ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Subsets: []v1.EndpointSubset{{
  94. Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}}}}}
  95. pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{UID: types.UID("poduid")}}
  96. mounter, err := plug.(*glusterfsPlugin).newMounterInternal(spec, ep, pod, &mount.FakeMounter{})
  97. volumePath := mounter.GetPath()
  98. if err != nil {
  99. t.Errorf("Failed to make a new Mounter: %v", err)
  100. }
  101. if mounter == nil {
  102. t.Error("Got a nil Mounter")
  103. }
  104. expectedPath := fmt.Sprintf("%s/pods/poduid/volumes/kubernetes.io~glusterfs/vol1", tmpDir)
  105. if volumePath != expectedPath {
  106. t.Errorf("Unexpected path, expected %q, got: %q", expectedPath, volumePath)
  107. }
  108. if err := mounter.SetUp(volume.MounterArgs{}); err != nil {
  109. t.Errorf("Expected success, got: %v", err)
  110. }
  111. if _, err := os.Stat(volumePath); err != nil {
  112. if os.IsNotExist(err) {
  113. t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
  114. } else {
  115. t.Errorf("SetUp() failed: %v", err)
  116. }
  117. }
  118. unmounter, err := plug.(*glusterfsPlugin).newUnmounterInternal("vol1", types.UID("poduid"), &mount.FakeMounter{})
  119. if err != nil {
  120. t.Errorf("Failed to make a new Unmounter: %v", err)
  121. }
  122. if unmounter == nil {
  123. t.Error("Got a nil Unmounter")
  124. }
  125. if err := unmounter.TearDown(); err != nil {
  126. t.Errorf("Expected success, got: %v", err)
  127. }
  128. if _, err := os.Stat(volumePath); err == nil {
  129. t.Errorf("TearDown() failed, volume path still exists: %s", volumePath)
  130. } else if !os.IsNotExist(err) {
  131. t.Errorf("TearDown() failed: %v", err)
  132. }
  133. }
  134. func TestPluginVolume(t *testing.T) {
  135. vol := &v1.Volume{
  136. Name: "vol1",
  137. VolumeSource: v1.VolumeSource{Glusterfs: &v1.GlusterfsVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false}},
  138. }
  139. doTestPlugin(t, volume.NewSpecFromVolume(vol))
  140. }
  141. func TestPluginPersistentVolume(t *testing.T) {
  142. vol := &v1.PersistentVolume{
  143. ObjectMeta: metav1.ObjectMeta{
  144. Name: "vol1",
  145. },
  146. Spec: v1.PersistentVolumeSpec{
  147. PersistentVolumeSource: v1.PersistentVolumeSource{
  148. Glusterfs: &v1.GlusterfsPersistentVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
  149. },
  150. },
  151. }
  152. doTestPlugin(t, volume.NewSpecFromPersistentVolume(vol, false))
  153. }
  154. func TestPersistentClaimReadOnlyFlag(t *testing.T) {
  155. tmpDir, err := utiltesting.MkTmpdir("glusterfs_test")
  156. if err != nil {
  157. t.Fatalf("error creating temp dir: %v", err)
  158. }
  159. defer os.RemoveAll(tmpDir)
  160. pv := &v1.PersistentVolume{
  161. ObjectMeta: metav1.ObjectMeta{
  162. Name: "pvA",
  163. },
  164. Spec: v1.PersistentVolumeSpec{
  165. PersistentVolumeSource: v1.PersistentVolumeSource{
  166. Glusterfs: &v1.GlusterfsPersistentVolumeSource{EndpointsName: "ep", Path: "vol", ReadOnly: false},
  167. },
  168. ClaimRef: &v1.ObjectReference{
  169. Name: "claimA",
  170. },
  171. },
  172. }
  173. claim := &v1.PersistentVolumeClaim{
  174. ObjectMeta: metav1.ObjectMeta{
  175. Name: "claimA",
  176. Namespace: "nsA",
  177. },
  178. Spec: v1.PersistentVolumeClaimSpec{
  179. VolumeName: "pvA",
  180. },
  181. Status: v1.PersistentVolumeClaimStatus{
  182. Phase: v1.ClaimBound,
  183. },
  184. }
  185. ep := &v1.Endpoints{
  186. ObjectMeta: metav1.ObjectMeta{
  187. Namespace: "nsA",
  188. Name: "ep",
  189. },
  190. Subsets: []v1.EndpointSubset{{
  191. Addresses: []v1.EndpointAddress{{IP: "127.0.0.1"}},
  192. Ports: []v1.EndpointPort{{Name: "foo", Port: 80, Protocol: v1.ProtocolTCP}},
  193. }},
  194. }
  195. client := fake.NewSimpleClientset(pv, claim, ep)
  196. plugMgr := volume.VolumePluginMgr{}
  197. plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(tmpDir, client, nil))
  198. plug, _ := plugMgr.FindPluginByName(glusterfsPluginName)
  199. // readOnly bool is supplied by persistent-claim volume source when its mounter creates other volumes
  200. spec := volume.NewSpecFromPersistentVolume(pv, true)
  201. pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "nsA", UID: types.UID("poduid")}}
  202. mounter, _ := plug.NewMounter(spec, pod, volume.VolumeOptions{})
  203. if !mounter.GetAttributes().ReadOnly {
  204. t.Errorf("Expected true for mounter.IsReadOnly")
  205. }
  206. }
  207. func TestParseClassParameters(t *testing.T) {
  208. secret := v1.Secret{
  209. Type: "kubernetes.io/glusterfs",
  210. Data: map[string][]byte{
  211. "data": []byte("mypassword"),
  212. },
  213. }
  214. tests := []struct {
  215. name string
  216. parameters map[string]string
  217. secret *v1.Secret
  218. expectError bool
  219. expectConfig *provisionerConfig
  220. }{
  221. {
  222. "password",
  223. map[string]string{
  224. "resturl": "https://localhost:8080",
  225. "restuser": "admin",
  226. "restuserkey": "password",
  227. },
  228. nil, // secret
  229. false, // expect error
  230. &provisionerConfig{
  231. url: "https://localhost:8080",
  232. user: "admin",
  233. userKey: "password",
  234. secretValue: "password",
  235. gidMin: 2000,
  236. gidMax: 2147483647,
  237. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  238. thinPoolSnapFactor: float32(1.0),
  239. customEpNamePrefix: "glusterfs-dynamic",
  240. },
  241. },
  242. {
  243. "secret",
  244. map[string]string{
  245. "resturl": "https://localhost:8080",
  246. "restuser": "admin",
  247. "secretname": "mysecret",
  248. "secretnamespace": "default",
  249. },
  250. &secret,
  251. false, // expect error
  252. &provisionerConfig{
  253. url: "https://localhost:8080",
  254. user: "admin",
  255. secretName: "mysecret",
  256. secretNamespace: "default",
  257. secretValue: "mypassword",
  258. gidMin: 2000,
  259. gidMax: 2147483647,
  260. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  261. thinPoolSnapFactor: float32(1.0),
  262. customEpNamePrefix: "glusterfs-dynamic",
  263. },
  264. },
  265. {
  266. "no authentication",
  267. map[string]string{
  268. "resturl": "https://localhost:8080",
  269. "restauthenabled": "false",
  270. },
  271. &secret,
  272. false, // expect error
  273. &provisionerConfig{
  274. url: "https://localhost:8080",
  275. gidMin: 2000,
  276. gidMax: 2147483647,
  277. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  278. thinPoolSnapFactor: float32(1.0),
  279. customEpNamePrefix: "glusterfs-dynamic",
  280. },
  281. },
  282. {
  283. "missing secret",
  284. map[string]string{
  285. "resturl": "https://localhost:8080",
  286. "secretname": "mysecret",
  287. "secretnamespace": "default",
  288. },
  289. nil, // secret
  290. true, // expect error
  291. nil,
  292. },
  293. {
  294. "secret with no namespace",
  295. map[string]string{
  296. "resturl": "https://localhost:8080",
  297. "secretname": "mysecret",
  298. },
  299. &secret,
  300. true, // expect error
  301. nil,
  302. },
  303. {
  304. "missing url",
  305. map[string]string{
  306. "restuser": "admin",
  307. "restuserkey": "password",
  308. },
  309. nil, // secret
  310. true, // expect error
  311. nil,
  312. },
  313. {
  314. "unknown parameter",
  315. map[string]string{
  316. "unknown": "yes",
  317. "resturl": "https://localhost:8080",
  318. "restuser": "admin",
  319. "restuserkey": "password",
  320. },
  321. nil, // secret
  322. true, // expect error
  323. nil,
  324. },
  325. {
  326. "invalid gidMin #1",
  327. map[string]string{
  328. "resturl": "https://localhost:8080",
  329. "restauthenabled": "false",
  330. "gidMin": "0",
  331. },
  332. &secret,
  333. true, // expect error
  334. nil,
  335. },
  336. {
  337. "invalid gidMin #2",
  338. map[string]string{
  339. "resturl": "https://localhost:8080",
  340. "restauthenabled": "false",
  341. "gidMin": "1999",
  342. },
  343. &secret,
  344. true, // expect error
  345. nil,
  346. },
  347. {
  348. "invalid gidMin #3",
  349. map[string]string{
  350. "resturl": "https://localhost:8080",
  351. "restauthenabled": "false",
  352. "gidMin": "1999",
  353. },
  354. &secret,
  355. true, // expect error
  356. nil,
  357. },
  358. {
  359. "invalid gidMax #1",
  360. map[string]string{
  361. "resturl": "https://localhost:8080",
  362. "restauthenabled": "false",
  363. "gidMax": "0",
  364. },
  365. &secret,
  366. true, // expect error
  367. nil,
  368. },
  369. {
  370. "invalid gidMax #2",
  371. map[string]string{
  372. "resturl": "https://localhost:8080",
  373. "restauthenabled": "false",
  374. "gidMax": "1999",
  375. },
  376. &secret,
  377. true, // expect error
  378. nil,
  379. },
  380. {
  381. "invalid gidMax #3",
  382. map[string]string{
  383. "resturl": "https://localhost:8080",
  384. "restauthenabled": "false",
  385. "gidMax": "1999",
  386. },
  387. &secret,
  388. true, // expect error
  389. nil,
  390. },
  391. {
  392. "invalid gidMin:gidMax",
  393. map[string]string{
  394. "resturl": "https://localhost:8080",
  395. "restauthenabled": "false",
  396. "gidMin": "5001",
  397. "gidMax": "5000",
  398. },
  399. &secret,
  400. true, // expect error
  401. nil,
  402. },
  403. {
  404. "valid gidMin",
  405. map[string]string{
  406. "resturl": "https://localhost:8080",
  407. "restauthenabled": "false",
  408. "gidMin": "4000",
  409. },
  410. &secret,
  411. false, // expect error
  412. &provisionerConfig{
  413. url: "https://localhost:8080",
  414. gidMin: 4000,
  415. gidMax: 2147483647,
  416. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  417. thinPoolSnapFactor: float32(1.0),
  418. customEpNamePrefix: "glusterfs-dynamic",
  419. },
  420. },
  421. {
  422. "valid gidMax",
  423. map[string]string{
  424. "resturl": "https://localhost:8080",
  425. "restauthenabled": "false",
  426. "gidMax": "5000",
  427. },
  428. &secret,
  429. false, // expect error
  430. &provisionerConfig{
  431. url: "https://localhost:8080",
  432. gidMin: 2000,
  433. gidMax: 5000,
  434. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  435. thinPoolSnapFactor: float32(1.0),
  436. customEpNamePrefix: "glusterfs-dynamic",
  437. },
  438. },
  439. {
  440. "valid gidMin:gidMax",
  441. map[string]string{
  442. "resturl": "https://localhost:8080",
  443. "restauthenabled": "false",
  444. "gidMin": "4000",
  445. "gidMax": "5000",
  446. },
  447. &secret,
  448. false, // expect error
  449. &provisionerConfig{
  450. url: "https://localhost:8080",
  451. gidMin: 4000,
  452. gidMax: 5000,
  453. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 3}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  454. thinPoolSnapFactor: float32(1.0),
  455. customEpNamePrefix: "glusterfs-dynamic",
  456. },
  457. },
  458. {
  459. "valid volumetype: replicate",
  460. map[string]string{
  461. "resturl": "https://localhost:8080",
  462. "restauthenabled": "false",
  463. "gidMin": "4000",
  464. "gidMax": "5000",
  465. "volumetype": "replicate:4",
  466. },
  467. &secret,
  468. false, // expect error
  469. &provisionerConfig{
  470. url: "https://localhost:8080",
  471. gidMin: 4000,
  472. gidMax: 5000,
  473. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  474. thinPoolSnapFactor: float32(1.0),
  475. customEpNamePrefix: "glusterfs-dynamic",
  476. },
  477. },
  478. {
  479. "valid volumetype: disperse",
  480. map[string]string{
  481. "resturl": "https://localhost:8080",
  482. "restauthenabled": "false",
  483. "gidMin": "4000",
  484. "gidMax": "5000",
  485. "volumetype": "disperse:4:2",
  486. },
  487. &secret,
  488. false, // expect error
  489. &provisionerConfig{
  490. url: "https://localhost:8080",
  491. gidMin: 4000,
  492. gidMax: 5000,
  493. volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}},
  494. thinPoolSnapFactor: float32(1.0),
  495. customEpNamePrefix: "glusterfs-dynamic",
  496. },
  497. },
  498. {
  499. "valid snapfactor: 50",
  500. map[string]string{
  501. "resturl": "https://localhost:8080",
  502. "restauthenabled": "false",
  503. "gidMin": "4000",
  504. "gidMax": "5000",
  505. "volumetype": "disperse:4:2",
  506. "snapfactor": "50",
  507. },
  508. &secret,
  509. false, // expect error
  510. &provisionerConfig{
  511. url: "https://localhost:8080",
  512. gidMin: 4000,
  513. gidMax: 5000,
  514. volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}},
  515. thinPoolSnapFactor: float32(50),
  516. customEpNamePrefix: "glusterfs-dynamic",
  517. },
  518. },
  519. {
  520. "valid volumenameprefix: dept-dev",
  521. map[string]string{
  522. "resturl": "https://localhost:8080",
  523. "restauthenabled": "false",
  524. "gidMin": "4000",
  525. "gidMax": "5000",
  526. "volumetype": "disperse:4:2",
  527. "snapfactor": "50",
  528. "volumenameprefix": "dept-dev",
  529. },
  530. &secret,
  531. false, // expect error
  532. &provisionerConfig{
  533. url: "https://localhost:8080",
  534. gidMin: 4000,
  535. gidMax: 5000,
  536. volumeType: gapi.VolumeDurabilityInfo{Type: "disperse", Replicate: gapi.ReplicaDurability{Replica: 0}, Disperse: gapi.DisperseDurability{Data: 4, Redundancy: 2}},
  537. thinPoolSnapFactor: float32(50),
  538. volumeNamePrefix: "dept-dev",
  539. customEpNamePrefix: "glusterfs-dynamic",
  540. },
  541. },
  542. {
  543. "invalid volumetype (disperse) parameter",
  544. map[string]string{
  545. "resturl": "https://localhost:8080",
  546. "restauthenabled": "false",
  547. "volumetype": "disperse:4:asd",
  548. },
  549. &secret,
  550. true, // expect error
  551. nil,
  552. },
  553. {
  554. "invalid volumetype (replicate) parameter",
  555. map[string]string{
  556. "resturl": "https://localhost:8080",
  557. "restauthenabled": "false",
  558. "volumetype": "replicate:asd",
  559. },
  560. &secret,
  561. true, // expect error
  562. nil,
  563. },
  564. {
  565. "invalid volumetype: unknown volumetype",
  566. map[string]string{
  567. "resturl": "https://localhost:8080",
  568. "restauthenabled": "false",
  569. "volumetype": "dispersereplicate:4:2",
  570. },
  571. &secret,
  572. true, // expect error
  573. nil,
  574. },
  575. {
  576. "invalid volumetype : negative value",
  577. map[string]string{
  578. "resturl": "https://localhost:8080",
  579. "restauthenabled": "false",
  580. "volumetype": "replicate:-1000",
  581. },
  582. &secret,
  583. true, // expect error
  584. nil,
  585. },
  586. {
  587. "invalid thinPoolSnapFactor: value out of range",
  588. map[string]string{
  589. "resturl": "https://localhost:8080",
  590. "restauthenabled": "false",
  591. "snapfactor": "0.5",
  592. },
  593. &secret,
  594. true, // expect error
  595. nil,
  596. },
  597. {
  598. "invalid volumenameprefix: string starting with '_'",
  599. map[string]string{
  600. "resturl": "https://localhost:8080",
  601. "restauthenabled": "false",
  602. "volumenameprefix": "_",
  603. },
  604. &secret,
  605. true, // expect error
  606. nil,
  607. },
  608. {
  609. "invalid volumenameprefix: string with '_'",
  610. map[string]string{
  611. "resturl": "https://localhost:8080",
  612. "restauthenabled": "false",
  613. "volumenameprefix": "qe_dept",
  614. },
  615. &secret,
  616. true, // expect error
  617. nil,
  618. },
  619. {
  620. "invalid thinPoolSnapFactor: value out of range",
  621. map[string]string{
  622. "resturl": "https://localhost:8080",
  623. "restauthenabled": "false",
  624. "snapfactor": "120",
  625. },
  626. &secret,
  627. true, // expect error
  628. nil,
  629. },
  630. {
  631. "enable custom ep/svc name: customEpNamePrefix: myprefix",
  632. map[string]string{
  633. "resturl": "https://localhost:8080",
  634. "restauthenabled": "false",
  635. "gidMin": "4000",
  636. "gidMax": "5000",
  637. "volumetype": "replicate:4",
  638. "customEpNamePrefix": "myprefix",
  639. },
  640. &secret,
  641. false, // expect error
  642. &provisionerConfig{
  643. url: "https://localhost:8080",
  644. gidMin: 4000,
  645. gidMax: 5000,
  646. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  647. thinPoolSnapFactor: float32(1.0),
  648. customEpNamePrefix: "myprefix",
  649. },
  650. },
  651. {
  652. "empty custom ep/svc name: customEpNamePrefix:''",
  653. map[string]string{
  654. "resturl": "https://localhost:8080",
  655. "restauthenabled": "false",
  656. "gidMin": "4000",
  657. "gidMax": "5000",
  658. "volumetype": "replicate:4",
  659. "customEpNamePrefix": "",
  660. },
  661. &secret,
  662. false, // expect error
  663. &provisionerConfig{
  664. url: "https://localhost:8080",
  665. gidMin: 4000,
  666. gidMax: 5000,
  667. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  668. thinPoolSnapFactor: float32(1.0),
  669. customEpNamePrefix: "",
  670. },
  671. },
  672. {
  673. "custom ep/svc name with 26 chars: customEpNamePrefix:'charstringhastwentysixchar'",
  674. map[string]string{
  675. "resturl": "https://localhost:8080",
  676. "restauthenabled": "false",
  677. "gidMin": "4000",
  678. "gidMax": "5000",
  679. "volumetype": "replicate:4",
  680. "customEpNamePrefix": "charstringhastwentysixchar",
  681. },
  682. &secret,
  683. false, // expect error
  684. &provisionerConfig{
  685. url: "https://localhost:8080",
  686. gidMin: 4000,
  687. gidMax: 5000,
  688. volumeType: gapi.VolumeDurabilityInfo{Type: "replicate", Replicate: gapi.ReplicaDurability{Replica: 4}, Disperse: gapi.DisperseDurability{Data: 0, Redundancy: 0}},
  689. thinPoolSnapFactor: float32(1.0),
  690. customEpNamePrefix: "charstringhastwentysixchar",
  691. },
  692. },
  693. {
  694. "invalid customepnameprefix ( ie >26 chars) parameter",
  695. map[string]string{
  696. "resturl": "https://localhost:8080",
  697. "restauthenabled": "false",
  698. "gidMin": "4000",
  699. "gidMax": "5000",
  700. "volumetype": "replicate:4",
  701. "customEpNamePrefix": "myprefixhasmorethan26characters",
  702. },
  703. &secret,
  704. true, // expect error
  705. nil,
  706. },
  707. }
  708. for _, test := range tests {
  709. client := &fake.Clientset{}
  710. client.AddReactor("get", "secrets", func(action core.Action) (handled bool, ret runtime.Object, err error) {
  711. if test.secret != nil {
  712. return true, test.secret, nil
  713. }
  714. return true, nil, fmt.Errorf("Test %s did not set a secret", test.name)
  715. })
  716. cfg, err := parseClassParameters(test.parameters, client)
  717. if err != nil && !test.expectError {
  718. t.Errorf("Test %s got unexpected error %v", test.name, err)
  719. }
  720. if err == nil && test.expectError {
  721. t.Errorf("test %s expected error and got none", test.name)
  722. }
  723. if test.expectConfig != nil {
  724. if !reflect.DeepEqual(cfg, test.expectConfig) {
  725. t.Errorf("Test %s returned unexpected data, expected: %+v, got: %+v", test.name, test.expectConfig, cfg)
  726. }
  727. }
  728. }
  729. }