aliyunprovider_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. package cloud
  2. import (
  3. "fmt"
  4. "testing"
  5. "github.com/aliyun/alibaba-cloud-sdk-go/sdk"
  6. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials"
  7. "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/signers"
  8. v1 "k8s.io/api/core/v1"
  9. resource "k8s.io/apimachinery/pkg/api/resource"
  10. )
  11. func TestCreateDescribePriceACSRequest(t *testing.T) {
  12. node := &SlimK8sNode{
  13. InstanceType: "ecs.g6.large",
  14. RegionID: "cn-hangzhou",
  15. PriceUnit: "Hour",
  16. MemorySizeInKiB: "16KiB",
  17. IsIoOptimized: true,
  18. OSType: "Linux",
  19. ProviderID: "Ali-XXX-node-01",
  20. InstanceTypeFamily: "g6",
  21. }
  22. disk := &SlimK8sDisk{
  23. DiskType: "data",
  24. RegionID: "cn-hangzhou",
  25. PriceUnit: "Hour",
  26. SizeInGiB: "20",
  27. DiskCategory: "diskCategory",
  28. PerformanceLevel: "cloud_essd",
  29. ProviderID: "d-Ali-XXX-01",
  30. StorageClass: "testStorageClass",
  31. }
  32. cases := []struct {
  33. name string
  34. testStruct interface{}
  35. expectedError error
  36. }{
  37. {
  38. name: "test CreateDescribePriceACSRequest with SlimK8sNode struct Object",
  39. testStruct: node,
  40. expectedError: nil,
  41. },
  42. {
  43. name: "test CreateDescribePriceACSRequest with SlimK8sDisk struct Object",
  44. testStruct: disk,
  45. expectedError: nil,
  46. },
  47. }
  48. for _, c := range cases {
  49. t.Run(c.name, func(t *testing.T) {
  50. _, err := createDescribePriceACSRequest(c.testStruct)
  51. if err != nil && c.expectedError == nil {
  52. t.Fatalf("Case name %s: Error converting to Alibaba cloud request", c.name)
  53. }
  54. })
  55. }
  56. }
  57. func TestProcessDescribePriceAndCreateAlibabaPricing(t *testing.T) {
  58. // Skipping this test case since it exposes secret but a good test case to verify when
  59. // supporting a new family of instances, steps to perform are
  60. // STEP 1: Comment the t.Skip() line and then replace XXX_KEY_ID with the alibaba key id of your account and XXX_SECRET_ID with alibaba cloud secret of your account.
  61. // STEP 2: Once you verify describePrice is working and no change needed in processDescribePriceAndCreateAlibabaPricing, you can go ahead and revert the step 1 changes.
  62. // This test case was use to test all general puprose instances
  63. t.Skip()
  64. client, err := sdk.NewClientWithAccessKey("cn-hangzhou", "XXX_KEY_ID", "XXX_SECRET_ID")
  65. if err != nil {
  66. t.Errorf("Error connecting to the Alibaba cloud")
  67. }
  68. aak := credentials.NewAccessKeyCredential("XXX_KEY_ID", "XXX_SECRET_ID")
  69. signer := signers.NewAccessKeySigner(aak)
  70. cases := []struct {
  71. name string
  72. teststruct interface{}
  73. expectedError error
  74. }{
  75. {
  76. name: "test Enhanced General Purpose Type g6e instance family",
  77. teststruct: &SlimK8sNode{
  78. InstanceType: "ecs.g6e.xlarge",
  79. RegionID: "cn-hangzhou",
  80. PriceUnit: "Hour",
  81. MemorySizeInKiB: "16777216KiB",
  82. IsIoOptimized: true,
  83. OSType: "Linux",
  84. ProviderID: "cn-hangzhou.i-test-01",
  85. InstanceTypeFamily: "g6e",
  86. },
  87. expectedError: nil,
  88. },
  89. {
  90. name: "test General Purpose Type g6 instance family",
  91. teststruct: &SlimK8sNode{
  92. InstanceType: "ecs.g6.3xlarge",
  93. RegionID: "cn-hangzhou",
  94. PriceUnit: "Hour",
  95. MemorySizeInKiB: "50331648KiB",
  96. IsIoOptimized: true,
  97. OSType: "Linux",
  98. ProviderID: "cn-hangzhou.i-test-02",
  99. InstanceTypeFamily: "g6",
  100. },
  101. expectedError: nil,
  102. },
  103. {
  104. name: "test General Purpose Type g5 instance family",
  105. teststruct: &SlimK8sNode{
  106. InstanceType: "ecs.g5.2xlarge",
  107. RegionID: "cn-hangzhou",
  108. PriceUnit: "Hour",
  109. MemorySizeInKiB: "33554432KiB",
  110. IsIoOptimized: true,
  111. OSType: "Linux",
  112. ProviderID: "cn-hangzhou.i-test-03",
  113. InstanceTypeFamily: "g5",
  114. },
  115. expectedError: nil,
  116. },
  117. {
  118. name: "test General Purpose Type sn2 instance family",
  119. teststruct: &SlimK8sNode{
  120. InstanceType: "ecs.sn2.large",
  121. RegionID: "cn-hangzhou",
  122. PriceUnit: "Hour",
  123. MemorySizeInKiB: "16777216KiB",
  124. IsIoOptimized: true,
  125. OSType: "Linux",
  126. ProviderID: "cn-hangzhou.i-test-04",
  127. InstanceTypeFamily: "sn2",
  128. },
  129. expectedError: nil,
  130. },
  131. {
  132. name: "test General Purpose Type with Enhanced Network Performance sn2ne instance family",
  133. teststruct: &SlimK8sNode{
  134. InstanceType: "ecs.sn2ne.2xlarge",
  135. RegionID: "cn-hangzhou",
  136. PriceUnit: "Hour",
  137. MemorySizeInKiB: "33554432KiB",
  138. IsIoOptimized: true,
  139. OSType: "Linux",
  140. ProviderID: "cn-hangzhou.i-test-05",
  141. InstanceTypeFamily: "sn2ne",
  142. },
  143. expectedError: nil,
  144. },
  145. {
  146. name: "test for a nil information",
  147. teststruct: nil,
  148. expectedError: fmt.Errorf("unsupported ECS pricing component at this time"),
  149. },
  150. {
  151. name: "test Cloud Disk with Category cloud representing basic disk",
  152. teststruct: &SlimK8sDisk{
  153. DiskType: "data",
  154. RegionID: "cn-hangzhou",
  155. PriceUnit: "Hour",
  156. SizeInGiB: "20",
  157. DiskCategory: "cloud",
  158. ProviderID: "d-Ali-cloud-XXX-01",
  159. StorageClass: "temp",
  160. },
  161. expectedError: nil,
  162. },
  163. {
  164. name: "test Cloud Disk with Category cloud_efficiency representing ultra disk",
  165. teststruct: &SlimK8sDisk{
  166. DiskType: "data",
  167. RegionID: "cn-hangzhou",
  168. PriceUnit: "Hour",
  169. SizeInGiB: "40",
  170. DiskCategory: "cloud_efficiency",
  171. ProviderID: "d-Ali-cloud-XXX-02",
  172. StorageClass: "temp",
  173. },
  174. expectedError: nil,
  175. },
  176. {
  177. name: "test Cloud Disk with Category cloud_ssd representing standard SSD",
  178. teststruct: &SlimK8sDisk{
  179. DiskType: "data",
  180. RegionID: "cn-hangzhou",
  181. PriceUnit: "Hour",
  182. SizeInGiB: "40",
  183. DiskCategory: "cloud_efficiency",
  184. ProviderID: "d-Ali-cloud-XXX-02",
  185. StorageClass: "temp",
  186. },
  187. expectedError: nil,
  188. },
  189. {
  190. name: "test Cloud Disk with Category cloud_essd representing Enhanced SSD with PL2 performance level",
  191. teststruct: &SlimK8sDisk{
  192. DiskType: "data",
  193. RegionID: "cn-hangzhou",
  194. PriceUnit: "Hour",
  195. SizeInGiB: "80",
  196. DiskCategory: "cloud_ssd",
  197. PerformanceLevel: "PL2",
  198. ProviderID: "d-Ali-cloud-XXX-04",
  199. StorageClass: "temp",
  200. },
  201. expectedError: nil,
  202. },
  203. }
  204. custom := &CustomPricing{}
  205. for _, c := range cases {
  206. t.Run(c.name, func(t *testing.T) {
  207. pricingObj, err := processDescribePriceAndCreateAlibabaPricing(client, c.teststruct, signer, custom)
  208. if err != nil && c.expectedError == nil {
  209. t.Fatalf("Case name %s: got an error %s", c.name, err)
  210. }
  211. if c.teststruct != nil {
  212. if pricingObj == nil {
  213. t.Fatalf("Case name %s: got a nil pricing object", c.name)
  214. }
  215. t.Logf("Case name %s: Pricing Information gathered for instanceType is %v", c.name, pricingObj.PricingTerms.PricingDetails.TradePrice)
  216. }
  217. })
  218. }
  219. }
  220. func TestGetInstanceFamilyFromType(t *testing.T) {
  221. cases := []struct {
  222. name string
  223. instanceType string
  224. expectedInstanceFamily string
  225. }{
  226. {
  227. name: "test if ecs.[instance-family].[different-type] work",
  228. instanceType: "ecs.sn2ne.2xlarge",
  229. expectedInstanceFamily: "sn2ne",
  230. },
  231. {
  232. name: "test if random word gives you ALIBABA_UNKNOWN_INSTANCE_FAMILY_TYPE value ",
  233. instanceType: "random.value",
  234. expectedInstanceFamily: ALIBABA_UNKNOWN_INSTANCE_FAMILY_TYPE,
  235. },
  236. {
  237. name: "test if random instance family gives you ALIBABA_NOT_SUPPORTED_INSTANCE_FAMILY_TYPE value ",
  238. instanceType: "ecs.g7e.2xlarge",
  239. expectedInstanceFamily: ALIBABA_NOT_SUPPORTED_INSTANCE_FAMILY_TYPE,
  240. },
  241. }
  242. for _, c := range cases {
  243. t.Run(c.name, func(t *testing.T) {
  244. returnValue := getInstanceFamilyFromType(c.instanceType)
  245. if returnValue != c.expectedInstanceFamily {
  246. t.Fatalf("Case name %s: expected instance family of type %s but got %s", c.name, c.expectedInstanceFamily, returnValue)
  247. }
  248. })
  249. }
  250. }
  251. func TestDetermineKeyForPricing(t *testing.T) {
  252. type randomK8sStruct struct {
  253. name string
  254. }
  255. cases := []struct {
  256. name string
  257. testVar interface{}
  258. expectedKey string
  259. expectedError error
  260. }{
  261. {
  262. name: "test when all RegionID, InstanceType, OSType & ALIBABA_OPTIMIZE_KEYWORD words are used in Node key",
  263. testVar: &SlimK8sNode{
  264. InstanceType: "ecs.sn2.large",
  265. RegionID: "cn-hangzhou",
  266. PriceUnit: "Hour",
  267. MemorySizeInKiB: "16777216KiB",
  268. IsIoOptimized: true,
  269. OSType: "linux",
  270. ProviderID: "cn-hangzhou.i-test-04",
  271. InstanceTypeFamily: "sn2",
  272. },
  273. expectedKey: "cn-hangzhou::ecs.sn2.large::linux::optimize",
  274. expectedError: nil,
  275. },
  276. {
  277. name: "test missing InstanceType to create Node key",
  278. testVar: &SlimK8sNode{
  279. RegionID: "cn-hangzhou",
  280. PriceUnit: "Hour",
  281. MemorySizeInKiB: "16777216KiB",
  282. IsIoOptimized: true,
  283. OSType: "linux",
  284. ProviderID: "cn-hangzhou.i-test-04",
  285. },
  286. expectedKey: "cn-hangzhou::linux::optimize",
  287. expectedError: nil,
  288. },
  289. {
  290. name: "test when node has a systemDisk Information with missing Performance level",
  291. testVar: &SlimK8sNode{
  292. InstanceType: "ecs.sn2.large",
  293. RegionID: "cn-hangzhou",
  294. PriceUnit: "Hour",
  295. MemorySizeInKiB: "16777216KiB",
  296. IsIoOptimized: true,
  297. OSType: "linux",
  298. ProviderID: "cn-hangzhou.i-test-04",
  299. InstanceTypeFamily: "sn2",
  300. SystemDisk: &SlimK8sDisk{
  301. DiskType: "system",
  302. RegionID: "cn-hangzhou",
  303. PriceUnit: "Hour",
  304. SizeInGiB: "40",
  305. DiskCategory: "cloud_efficiency",
  306. ProviderID: "d-Ali-cloud-XXX-i1",
  307. StorageClass: "",
  308. },
  309. },
  310. expectedKey: "cn-hangzhou::ecs.sn2.large::linux::optimize::cloud_efficiency::40",
  311. expectedError: nil,
  312. },
  313. {
  314. name: "test when node has a systemDisk Information with all information",
  315. testVar: &SlimK8sNode{
  316. InstanceType: "ecs.sn2.large",
  317. RegionID: "cn-hangzhou",
  318. PriceUnit: "Hour",
  319. MemorySizeInKiB: "16777216KiB",
  320. IsIoOptimized: true,
  321. OSType: "linux",
  322. ProviderID: "cn-hangzhou.i-test-04",
  323. InstanceTypeFamily: "sn2",
  324. SystemDisk: &SlimK8sDisk{
  325. DiskType: "data",
  326. RegionID: "cn-hangzhou",
  327. PriceUnit: "Hour",
  328. SizeInGiB: "80",
  329. DiskCategory: "cloud_ssd",
  330. PerformanceLevel: "PL2",
  331. ProviderID: "d-Ali-cloud-XXX-04",
  332. StorageClass: "",
  333. },
  334. },
  335. expectedKey: "cn-hangzhou::ecs.sn2.large::linux::optimize::cloud_ssd::80::PL2",
  336. expectedError: nil,
  337. },
  338. {
  339. name: "test random k8s struct should return unsupported error",
  340. testVar: &randomK8sStruct{
  341. name: "test struct",
  342. },
  343. expectedKey: "",
  344. expectedError: fmt.Errorf("unsupported ECS type randomK8sStruct for DescribePrice at this time"),
  345. },
  346. {
  347. name: "test for nil check",
  348. testVar: nil,
  349. expectedKey: "",
  350. expectedError: fmt.Errorf("unsupported ECS type randomK8sStruct for DescribePrice at this time"),
  351. },
  352. {
  353. name: "test when all RegionID, InstanceType, OSType & ALIBABA_OPTIMIZE_KEYWORD words are used to key",
  354. testVar: &SlimK8sDisk{
  355. DiskType: "data",
  356. RegionID: "cn-hangzhou",
  357. PriceUnit: "Hour",
  358. SizeInGiB: "40",
  359. DiskCategory: "cloud_efficiency",
  360. ProviderID: "d-Ali-cloud-XXX-02",
  361. StorageClass: "temp",
  362. },
  363. expectedKey: "cn-hangzhou::data::cloud_efficiency::40",
  364. expectedError: nil,
  365. },
  366. {
  367. name: "test missing InstanceType to create key",
  368. testVar: &SlimK8sDisk{
  369. DiskType: "data",
  370. RegionID: "cn-hangzhou",
  371. PriceUnit: "Hour",
  372. SizeInGiB: "80",
  373. DiskCategory: "cloud_ssd",
  374. PerformanceLevel: "PL2",
  375. ProviderID: "d-Ali-cloud-XXX-04",
  376. StorageClass: "temp",
  377. },
  378. expectedKey: "cn-hangzhou::data::cloud_ssd::PL2::80",
  379. expectedError: nil,
  380. },
  381. }
  382. for _, c := range cases {
  383. t.Run(c.name, func(t *testing.T) {
  384. returnString, returnErr := determineKeyForPricing(c.testVar)
  385. if c.expectedError == nil && returnErr != nil {
  386. t.Fatalf("Case name %s: expected error was nil but recieved error %v", c.name, returnErr)
  387. }
  388. if returnString != c.expectedKey {
  389. t.Fatalf("Case name %s: determineKeyForPricing recieved %s but expected %s", c.name, returnString, c.expectedKey)
  390. }
  391. })
  392. }
  393. }
  394. func TestGenerateSlimK8sNodeFromV1Node(t *testing.T) {
  395. testv1Node := &v1.Node{}
  396. testv1Node.Labels = make(map[string]string)
  397. testv1Node.Labels["topology.kubernetes.io/region"] = "us-east-1"
  398. testv1Node.Labels["beta.kubernetes.io/os"] = "linux"
  399. testv1Node.Labels["node.kubernetes.io/instance-type"] = "ecs.sn2ne.2xlarge"
  400. testv1Node.Status.Capacity = v1.ResourceList{
  401. v1.ResourceMemory: *resource.NewQuantity(16, resource.BinarySI),
  402. }
  403. cases := []struct {
  404. name string
  405. testNode *v1.Node
  406. expectedSlimNode *SlimK8sNode
  407. }{
  408. {
  409. name: "test a generic *v1.Node to *SlimK8sNode Conversion",
  410. testNode: testv1Node,
  411. expectedSlimNode: &SlimK8sNode{
  412. InstanceType: "ecs.sn2ne.2xlarge",
  413. RegionID: "us-east-1",
  414. PriceUnit: ALIBABA_HOUR_PRICE_UNIT,
  415. MemorySizeInKiB: "16",
  416. IsIoOptimized: true,
  417. OSType: "linux",
  418. InstanceTypeFamily: "sn2ne",
  419. },
  420. },
  421. }
  422. for _, c := range cases {
  423. t.Run(c.name, func(t *testing.T) {
  424. returnSlimK8sNode := generateSlimK8sNodeFromV1Node(c.testNode)
  425. if returnSlimK8sNode.InstanceType != c.expectedSlimNode.InstanceType {
  426. t.Fatalf("unexpected conversion in function generateSlimK8sNodeFromV1Node expected InstanceType: %s , recieved InstanceType: %s", c.expectedSlimNode.InstanceType, returnSlimK8sNode.InstanceType)
  427. }
  428. if returnSlimK8sNode.RegionID != c.expectedSlimNode.RegionID {
  429. t.Fatalf("unexpected conversion in function generateSlimK8sNodeFromV1Node expected RegionID: %s , recieved RegionID: %s", c.expectedSlimNode.RegionID, returnSlimK8sNode.RegionID)
  430. }
  431. if returnSlimK8sNode.PriceUnit != c.expectedSlimNode.PriceUnit {
  432. t.Fatalf("unexpected conversion in function generateSlimK8sNodeFromV1Node expected PriceUnit: %s , recieved PriceUnit: %s", c.expectedSlimNode.PriceUnit, returnSlimK8sNode.PriceUnit)
  433. }
  434. if returnSlimK8sNode.MemorySizeInKiB != c.expectedSlimNode.MemorySizeInKiB {
  435. t.Fatalf("unexpected conversion in function generateSlimK8sNodeFromV1Node expected MemorySizeInKiB: %s , recieved MemorySizeInKiB: %s", c.expectedSlimNode.MemorySizeInKiB, returnSlimK8sNode.MemorySizeInKiB)
  436. }
  437. if returnSlimK8sNode.OSType != c.expectedSlimNode.OSType {
  438. t.Fatalf("unexpected conversion in function generateSlimK8sNodeFromV1Node expected OSType: %s , recieved OSType: %s", c.expectedSlimNode.OSType, returnSlimK8sNode.OSType)
  439. }
  440. if returnSlimK8sNode.InstanceTypeFamily != c.expectedSlimNode.InstanceTypeFamily {
  441. t.Fatalf("unexpected conversion in function generateSlimK8sNodeFromV1Node expected InstanceTypeFamily: %s , recieved InstanceTypeFamily: %s", c.expectedSlimNode.InstanceTypeFamily, returnSlimK8sNode.InstanceTypeFamily)
  442. }
  443. })
  444. }
  445. }
  446. func TestGenerateSlimK8sDiskFromV1PV(t *testing.T) {
  447. testv1PV := &v1.PersistentVolume{}
  448. testv1PV.Spec.Capacity = v1.ResourceList{
  449. v1.ResourceStorage: *resource.NewQuantity(16*1024*1024*1024, resource.BinarySI),
  450. }
  451. testv1PV.Spec.CSI = &v1.CSIPersistentVolumeSource{}
  452. testv1PV.Spec.CSI.VolumeHandle = "testPV"
  453. testv1PV.Spec.CSI.VolumeAttributes = map[string]string{
  454. "performanceLevel": "PL2",
  455. "type": "cloud_essd",
  456. }
  457. testv1PV.Spec.CSI.VolumeHandle = "testPV"
  458. testv1PV.Spec.StorageClassName = "testStorageClass"
  459. cases := []struct {
  460. name string
  461. testPV *v1.PersistentVolume
  462. expectedSlimDisk *SlimK8sDisk
  463. inpRegionID string
  464. }{
  465. {
  466. name: "test a generic *v1.Node to *SlimK8sNode Conversion",
  467. testPV: testv1PV,
  468. expectedSlimDisk: &SlimK8sDisk{
  469. DiskType: ALIBABA_DATA_DISK_CATEGORY,
  470. RegionID: "us-east-1",
  471. PriceUnit: ALIBABA_HOUR_PRICE_UNIT,
  472. SizeInGiB: "16",
  473. DiskCategory: "cloud_essd",
  474. PerformanceLevel: "PL2",
  475. ProviderID: "testPV",
  476. StorageClass: "testStorageClass",
  477. },
  478. inpRegionID: "us-east-1",
  479. },
  480. }
  481. for _, c := range cases {
  482. t.Run(c.name, func(t *testing.T) {
  483. returnSlimK8sDisk := generateSlimK8sDiskFromV1PV(c.testPV, c.inpRegionID)
  484. if returnSlimK8sDisk.DiskType != c.expectedSlimDisk.DiskType {
  485. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected DiskType: %s , recieved DiskType: %s", c.expectedSlimDisk.DiskType, returnSlimK8sDisk.DiskType)
  486. }
  487. if returnSlimK8sDisk.RegionID != c.expectedSlimDisk.RegionID {
  488. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected RegionID: %s , recieved RegionID Type: %s", c.expectedSlimDisk.RegionID, returnSlimK8sDisk.RegionID)
  489. }
  490. if returnSlimK8sDisk.PriceUnit != c.expectedSlimDisk.PriceUnit {
  491. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected PriceUnit: %s , recieved PriceUnit Type: %s", c.expectedSlimDisk.PriceUnit, returnSlimK8sDisk.PriceUnit)
  492. }
  493. if returnSlimK8sDisk.SizeInGiB != c.expectedSlimDisk.SizeInGiB {
  494. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected SizeInGiB: %s , recieved SizeInGiB Type: %s", c.expectedSlimDisk.SizeInGiB, returnSlimK8sDisk.SizeInGiB)
  495. }
  496. if returnSlimK8sDisk.DiskCategory != c.expectedSlimDisk.DiskCategory {
  497. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected DiskCategory: %s , recieved DiskCategory Type: %s", c.expectedSlimDisk.DiskCategory, returnSlimK8sDisk.DiskCategory)
  498. }
  499. if returnSlimK8sDisk.PerformanceLevel != c.expectedSlimDisk.PerformanceLevel {
  500. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected PerformanceLevel: %s , recieved PerformanceLevel Type: %s", c.expectedSlimDisk.PerformanceLevel, returnSlimK8sDisk.PerformanceLevel)
  501. }
  502. if returnSlimK8sDisk.ProviderID != c.expectedSlimDisk.ProviderID {
  503. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected ProviderID: %s , recieved ProviderID Type: %s", c.expectedSlimDisk.ProviderID, returnSlimK8sDisk.ProviderID)
  504. }
  505. if returnSlimK8sDisk.StorageClass != c.expectedSlimDisk.StorageClass {
  506. t.Fatalf("unexpected conversion in function generateSlimK8sDiskFromV1PV expected StorageClass: %s , recieved StorageClass Type: %s", c.expectedSlimDisk.StorageClass, returnSlimK8sDisk.StorageClass)
  507. }
  508. })
  509. }
  510. }
  511. func TestGetNumericalValueFromResourceQuantity(t *testing.T) {
  512. cases := []struct {
  513. name string
  514. inputResourceQuanity string
  515. expectedValue string
  516. }{
  517. {
  518. name: "positive scenario: when inputResourceQuantity is 10Gi",
  519. inputResourceQuanity: "10Gi",
  520. expectedValue: "10",
  521. },
  522. {
  523. name: "negative scenario: when inputResourceQuantity is Gi",
  524. inputResourceQuanity: "Gi",
  525. expectedValue: ALIBABA_DEFAULT_DATADISK_SIZE,
  526. },
  527. {
  528. name: "negative scenario: when inputResourceQuantity is 10",
  529. inputResourceQuanity: "10",
  530. expectedValue: ALIBABA_DEFAULT_DATADISK_SIZE,
  531. },
  532. {
  533. name: "negative scenario: when inputResourceQuantity is empty string",
  534. inputResourceQuanity: "",
  535. expectedValue: ALIBABA_DEFAULT_DATADISK_SIZE,
  536. },
  537. }
  538. for _, c := range cases {
  539. t.Run(c.name, func(t *testing.T) {
  540. returnValue := getNumericalValueFromResourceQuantity(c.inputResourceQuanity)
  541. if c.expectedValue != returnValue {
  542. t.Fatalf("Case name %s: getNumericalValueFromResourceQuantity recieved %s but expected %s", c.name, returnValue, c.expectedValue)
  543. }
  544. })
  545. }
  546. }
  547. func TestDeterminePVRegion(t *testing.T) {
  548. genericNodeAffinityTestStruct := v1.NodeSelectorTerm{
  549. MatchExpressions: []v1.NodeSelectorRequirement{
  550. {
  551. Key: "topology.diskplugin.csi.alibabacloud.com/zone",
  552. Operator: v1.NodeSelectorOpIn,
  553. Values: []string{"us-east-1a"},
  554. },
  555. },
  556. MatchFields: []v1.NodeSelectorRequirement{},
  557. }
  558. // testPV1 contains the Label with region information as well as node affinity in spec
  559. testPV1 := &v1.PersistentVolume{}
  560. testPV1.Name = "testPV1"
  561. testPV1.Labels = make(map[string]string)
  562. testPV1.Labels[ALIBABA_DISK_TOPOLOGY_REGION_LABEL] = "us-east-1"
  563. testPV1.Spec.NodeAffinity = &v1.VolumeNodeAffinity{
  564. Required: &v1.NodeSelector{
  565. NodeSelectorTerms: []v1.NodeSelectorTerm{genericNodeAffinityTestStruct},
  566. },
  567. }
  568. // testPV2 contains the only zone label
  569. testPV2 := &v1.PersistentVolume{}
  570. testPV2.Name = "testPV2"
  571. testPV2.Labels = make(map[string]string)
  572. testPV2.Labels[ALIBABA_DISK_TOPOLOGY_ZONE_LABEL] = "us-east-1a"
  573. // testPV3 contains only node affinity in spec
  574. testPV3 := &v1.PersistentVolume{}
  575. testPV3.Name = "testPV3"
  576. testPV3.Spec.NodeAffinity = &v1.VolumeNodeAffinity{
  577. Required: &v1.NodeSelector{
  578. NodeSelectorTerms: []v1.NodeSelectorTerm{genericNodeAffinityTestStruct},
  579. },
  580. }
  581. // testPV4 contains no label/annotation or any node affinity
  582. testPV4 := &v1.PersistentVolume{}
  583. testPV4.Name = "testPV4"
  584. cases := []struct {
  585. name string
  586. inputPV *v1.PersistentVolume
  587. expectedRegion string
  588. }{
  589. {
  590. name: "When Region label topology.diskplugin.csi.alibabacloud.com/region is present along with node affinity details",
  591. inputPV: testPV1,
  592. expectedRegion: "us-east-1",
  593. },
  594. {
  595. name: "When zone label topology.diskplugin.csi.alibabacloud.com/zone is present function has to determine region",
  596. inputPV: testPV2,
  597. expectedRegion: "us-east-1",
  598. },
  599. {
  600. name: "When only node affinity detail is present function has to determine the region",
  601. inputPV: testPV3,
  602. expectedRegion: "us-east-1",
  603. },
  604. {
  605. name: "When no region/zone information is present function returns empty to default to cluster region",
  606. inputPV: testPV4,
  607. expectedRegion: "",
  608. },
  609. }
  610. for _, c := range cases {
  611. t.Run(c.name, func(t *testing.T) {
  612. returnRegion := determinePVRegion(c.inputPV)
  613. if c.expectedRegion != returnRegion {
  614. t.Fatalf("Case name %s: determinePVRegion recieved region :%s but expected region: %s", c.name, returnRegion, c.expectedRegion)
  615. }
  616. })
  617. }
  618. }