csi_metrics_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. Copyright 2019 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 csi
  14. import (
  15. "io"
  16. "testing"
  17. csipbv1 "github.com/container-storage-interface/spec/lib/go/csi"
  18. "k8s.io/apimachinery/pkg/api/resource"
  19. "k8s.io/kubernetes/pkg/volume"
  20. "k8s.io/kubernetes/pkg/volume/csi/fake"
  21. )
  22. func TestGetMetrics(t *testing.T) {
  23. tests := []struct {
  24. name string
  25. volumeID string
  26. targetPath string
  27. expectSuccess bool
  28. }{
  29. {
  30. name: "with valid name and volume id",
  31. expectSuccess: true,
  32. volumeID: "foobar",
  33. targetPath: "/mnt/foo",
  34. },
  35. }
  36. for _, tc := range tests {
  37. metricsGetter := &metricsCsi{volumeID: tc.volumeID, targetPath: tc.targetPath}
  38. metricsGetter.csiClient = &csiDriverClient{
  39. driverName: "com.google.gcepd",
  40. nodeV1ClientCreator: func(addr csiAddr) (csipbv1.NodeClient, io.Closer, error) {
  41. nodeClient := fake.NewNodeClientWithVolumeStats(true /* VolumeStatsCapable */)
  42. fakeCloser := fake.NewCloser(t)
  43. nodeClient.SetNodeVolumeStatsResp(getRawVolumeInfo())
  44. return nodeClient, fakeCloser, nil
  45. },
  46. }
  47. metrics, err := metricsGetter.GetMetrics()
  48. if err != nil {
  49. t.Fatalf("for %s: unexpected error : %v", tc.name, err)
  50. }
  51. if metrics == nil {
  52. t.Fatalf("unexpected nil metrics")
  53. }
  54. expectedMetrics := getRawVolumeInfo()
  55. for _, usage := range expectedMetrics.Usage {
  56. if usage.Unit == csipbv1.VolumeUsage_BYTES {
  57. availableBytes := resource.NewQuantity(usage.Available, resource.BinarySI)
  58. totalBytes := resource.NewQuantity(usage.Total, resource.BinarySI)
  59. usedBytes := resource.NewQuantity(usage.Used, resource.BinarySI)
  60. if metrics.Available.Cmp(*availableBytes) != 0 {
  61. t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *availableBytes, *(metrics.Available))
  62. }
  63. if metrics.Capacity.Cmp(*totalBytes) != 0 {
  64. t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *totalBytes, *(metrics.Capacity))
  65. }
  66. if metrics.Used.Cmp(*usedBytes) != 0 {
  67. t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *usedBytes, *(metrics.Used))
  68. }
  69. }
  70. if usage.Unit == csipbv1.VolumeUsage_INODES {
  71. freeInodes := resource.NewQuantity(usage.Available, resource.BinarySI)
  72. inodes := resource.NewQuantity(usage.Total, resource.BinarySI)
  73. usedInodes := resource.NewQuantity(usage.Used, resource.BinarySI)
  74. if metrics.InodesFree.Cmp(*freeInodes) != 0 {
  75. t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *freeInodes, *(metrics.InodesFree))
  76. }
  77. if metrics.Inodes.Cmp(*inodes) != 0 {
  78. t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *inodes, *(metrics.Inodes))
  79. }
  80. if metrics.InodesUsed.Cmp(*usedInodes) != 0 {
  81. t.Fatalf("for %s: error: expected :%v , got: %v", tc.name, *usedInodes, *(metrics.InodesUsed))
  82. }
  83. }
  84. }
  85. }
  86. }
  87. // test GetMetrics with a volume that does not support stats
  88. func TestGetMetricsDriverNotSupportStats(t *testing.T) {
  89. tests := []struct {
  90. name string
  91. volumeID string
  92. targetPath string
  93. expectSuccess bool
  94. }{
  95. {
  96. name: "volume created by simple driver",
  97. expectSuccess: true,
  98. volumeID: "foobar",
  99. targetPath: "/mnt/foo",
  100. },
  101. }
  102. for _, tc := range tests {
  103. metricsGetter := &metricsCsi{volumeID: tc.volumeID, targetPath: tc.targetPath}
  104. metricsGetter.csiClient = &csiDriverClient{
  105. driverName: "com.simple.SimpleDriver",
  106. nodeV1ClientCreator: func(addr csiAddr) (csipbv1.NodeClient, io.Closer, error) {
  107. nodeClient := fake.NewNodeClientWithVolumeStats(false /* VolumeStatsCapable */)
  108. fakeCloser := fake.NewCloser(t)
  109. nodeClient.SetNodeVolumeStatsResp(getRawVolumeInfo())
  110. return nodeClient, fakeCloser, nil
  111. },
  112. }
  113. metrics, err := metricsGetter.GetMetrics()
  114. if err == nil {
  115. t.Fatalf("for %s: expected error, but got nil error", tc.name)
  116. }
  117. if !volume.IsNotSupported(err) {
  118. t.Fatalf("for %s, expected not supported error but got: %v", tc.name, err)
  119. }
  120. if metrics != nil {
  121. t.Fatalf("for %s, expected nil metrics, but got: %v", tc.name, metrics)
  122. }
  123. }
  124. }
  125. func getRawVolumeInfo() *csipbv1.NodeGetVolumeStatsResponse {
  126. return &csipbv1.NodeGetVolumeStatsResponse{
  127. Usage: []*csipbv1.VolumeUsage{
  128. {
  129. Available: int64(10),
  130. Total: int64(10),
  131. Used: int64(2),
  132. Unit: csipbv1.VolumeUsage_BYTES,
  133. },
  134. {
  135. Available: int64(100),
  136. Total: int64(100),
  137. Used: int64(20),
  138. Unit: csipbv1.VolumeUsage_INODES,
  139. },
  140. },
  141. }
  142. }