kubemodel_test.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. package kubemodel
  2. import (
  3. "errors"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/require"
  7. )
  8. func TestKubeModel(t *testing.T) {
  9. start := time.Now().UTC().Truncate(time.Hour)
  10. end := start.Add(time.Hour)
  11. t.Run("RegisterError", func(t *testing.T) {
  12. kms := NewKubeModelSet(start, end)
  13. require.NotNil(t, kms.Metadata)
  14. require.Len(t, kms.GetErrors(), 0)
  15. kms.Error(errors.New("test error"))
  16. require.Len(t, kms.GetErrors(), 1)
  17. require.Equal(t, "test error", kms.GetErrors()[0].Message)
  18. kms.Error(errors.New("test error 2"))
  19. require.Len(t, kms.GetErrors(), 2)
  20. require.Equal(t, "test error 2", kms.GetErrors()[1].Message)
  21. })
  22. t.Run("RegisterCluster", func(t *testing.T) {
  23. t.Run("empty cluster UID", func(t *testing.T) {
  24. var err error
  25. kms := NewKubeModelSet(start, end)
  26. err = kms.RegisterCluster("")
  27. require.NotNil(t, err)
  28. require.Len(t, kms.GetErrors(), 1)
  29. require.Equal(t, "RegisterCluster: uid is nil", kms.GetErrors()[0].Message)
  30. require.Nil(t, kms.Cluster)
  31. })
  32. t.Run("new cluster UID", func(t *testing.T) {
  33. var err error
  34. var clusterUID = "cluster-uid"
  35. kms := NewKubeModelSet(start, end)
  36. err = kms.RegisterCluster(clusterUID)
  37. require.Nil(t, err)
  38. require.Len(t, kms.GetErrors(), 0)
  39. require.NotNil(t, kms.Cluster)
  40. require.Equal(t, clusterUID, kms.Cluster.UID)
  41. })
  42. t.Run("multiple Register calls", func(t *testing.T) {
  43. var err error
  44. var clusterUID = "cluster-uid"
  45. kms := NewKubeModelSet(start, end)
  46. err = kms.RegisterCluster(clusterUID)
  47. require.Nil(t, err)
  48. require.Len(t, kms.GetErrors(), 0)
  49. require.NotNil(t, kms.Cluster)
  50. require.Equal(t, clusterUID, kms.Cluster.UID)
  51. // Register cluster with same UID, expect no-op on second try
  52. err = kms.RegisterCluster(clusterUID)
  53. require.Nil(t, err)
  54. require.Len(t, kms.GetErrors(), 0)
  55. require.NotNil(t, kms.Cluster)
  56. require.Equal(t, clusterUID, kms.Cluster.UID)
  57. // Register cluster with another UID (should not happen), expect no-op
  58. err = kms.RegisterCluster("another-uid")
  59. require.Nil(t, err)
  60. require.Len(t, kms.GetWarnings(), 1)
  61. require.Equal(t, "RegisterCluster(another-uid): attempting to change cluster UID from cluster-uid to another-uid", kms.GetWarnings()[0].Message)
  62. require.NotNil(t, kms.Cluster)
  63. require.Equal(t, clusterUID, kms.Cluster.UID) // original kms.Cluster is not modified
  64. })
  65. })
  66. t.Run("RegisterNamespace", func(t *testing.T) {
  67. t.Run("empty namespace UID", func(t *testing.T) {
  68. var err error
  69. kms := NewKubeModelSet(start, end)
  70. err = kms.RegisterNamespace("", "")
  71. require.NotNil(t, err)
  72. require.Len(t, kms.GetErrors(), 1)
  73. require.Equal(t, "UID is nil for Namespace ''", kms.GetErrors()[0].Message)
  74. require.Len(t, kms.Namespaces, 0)
  75. })
  76. t.Run("register namespace on KMS w/o cluster", func(t *testing.T) {
  77. var err error
  78. kms := NewKubeModelSet(start, end)
  79. testUID := "uid"
  80. testName := "name"
  81. err = kms.RegisterNamespace(testUID, testName)
  82. require.Nil(t, err)
  83. require.Len(t, kms.GetWarnings(), 1)
  84. require.Equal(t, "RegisterNamespace(uid, name): Cluster is nil", kms.GetWarnings()[0].Message)
  85. testNamespace := &Namespace{UID: testUID, ClusterUID: "", Name: testName}
  86. require.NotNil(t, kms.Namespaces[testUID])
  87. require.Equal(t, testNamespace, kms.Namespaces[testUID])
  88. require.NotNil(t, kms.idx.namespaceByName[testName])
  89. require.Equal(t, testNamespace, kms.idx.namespaceByName[testName])
  90. require.Equal(t, 1, kms.Metadata.ObjectCount)
  91. })
  92. t.Run("register namespace on KMS w/ cluster", func(t *testing.T) {
  93. var err error
  94. kms := NewKubeModelSet(start, end)
  95. err = kms.RegisterCluster("cluster-uid")
  96. require.Nil(t, err)
  97. // At this point we have a KMS with a cluster registered
  98. testUID := "uid"
  99. testName := "name"
  100. err = kms.RegisterNamespace(testUID, testName)
  101. require.Nil(t, err)
  102. require.Len(t, kms.GetErrors(), 0)
  103. require.NotNil(t, kms.Namespaces[testUID])
  104. testNamespace := &Namespace{UID: testUID, ClusterUID: "cluster-uid", Name: testName}
  105. require.Equal(t, testNamespace, kms.Namespaces[testUID])
  106. require.Equal(t, testNamespace, kms.idx.namespaceByName[testName])
  107. require.Equal(t, 1, kms.Metadata.ObjectCount)
  108. // Register same namespace again, expect no-op on second try
  109. err = kms.RegisterNamespace(testUID, testName)
  110. require.Nil(t, err)
  111. require.Len(t, kms.GetErrors(), 0)
  112. require.NotNil(t, kms.Namespaces[testUID])
  113. require.Equal(t, testNamespace, kms.Namespaces[testUID])
  114. require.Equal(t, testNamespace, kms.idx.namespaceByName[testName])
  115. require.Equal(t, 1, kms.Metadata.ObjectCount) // remains 1
  116. })
  117. })
  118. t.Run("RegisterResourceQuota", func(t *testing.T) {
  119. t.Run("empty resourceQuota UID", func(t *testing.T) {
  120. var err error
  121. kms := NewKubeModelSet(start, end)
  122. err = kms.RegisterResourceQuota("", "test", "")
  123. require.NotNil(t, err)
  124. require.Len(t, kms.GetErrors(), 1)
  125. require.Equal(t, "UID is nil for ResourceQuota 'test'", kms.GetErrors()[0].Message)
  126. require.Len(t, kms.ResourceQuotas, 0)
  127. })
  128. t.Run("register resource quota on KMS w/o namespace", func(t *testing.T) {
  129. var err error
  130. kms := NewKubeModelSet(start, end)
  131. testUID := "uid"
  132. testName := "name"
  133. err = kms.RegisterResourceQuota(testUID, testName, "unregistered-namespace")
  134. require.Nil(t, err)
  135. require.Len(t, kms.GetWarnings(), 1)
  136. require.Equal(t, "RegisterResourceQuota(uid, name, unregistered-namespace): missing namespace", kms.GetWarnings()[0].Message)
  137. testRQ := &ResourceQuota{
  138. UID: "uid",
  139. NamespaceUID: "",
  140. Name: "name",
  141. Spec: &ResourceQuotaSpec{Hard: &ResourceQuotaSpecHard{}},
  142. Status: &ResourceQuotaStatus{Used: &ResourceQuotaStatusUsed{}},
  143. }
  144. require.NotNil(t, kms.ResourceQuotas[testUID])
  145. require.Equal(t, testRQ, kms.ResourceQuotas[testUID])
  146. require.Equal(t, 1, kms.Metadata.ObjectCount)
  147. })
  148. t.Run("register resource quota on KMS w/ namespace", func(t *testing.T) {
  149. kms := NewKubeModelSet(start, end)
  150. kms.RegisterCluster("cluster-uid")
  151. kms.RegisterNamespace("namespace-uid", "namespace")
  152. // At this point we have a KMS with a cluster and namespace registered
  153. testUID := "uid"
  154. testName := "name"
  155. testNamespace := "namespace" // Register RQ in namespace that was already registered
  156. kms.RegisterResourceQuota(testUID, testName, testNamespace)
  157. testRQ := &ResourceQuota{
  158. UID: "uid",
  159. NamespaceUID: "namespace-uid",
  160. Name: "name",
  161. Spec: &ResourceQuotaSpec{Hard: &ResourceQuotaSpecHard{}},
  162. Status: &ResourceQuotaStatus{Used: &ResourceQuotaStatusUsed{}},
  163. }
  164. require.Len(t, kms.GetErrors(), 0)
  165. require.NotNil(t, kms.ResourceQuotas[testUID])
  166. require.Equal(t, testRQ, kms.ResourceQuotas[testUID])
  167. require.Equal(t, 2, kms.Metadata.ObjectCount) // 1 namespace and 1 RQ
  168. // Register same RQ again, expect no-op on second try
  169. kms.RegisterResourceQuota(testUID, testName, testNamespace)
  170. require.Len(t, kms.GetErrors(), 0)
  171. require.NotNil(t, kms.ResourceQuotas[testUID])
  172. require.Equal(t, testRQ, kms.ResourceQuotas[testUID])
  173. require.Equal(t, 2, kms.Metadata.ObjectCount) // 1 namespace and 1 RQ
  174. })
  175. t.Run("register multiple RQs in multiple namespaces", func(t *testing.T) {
  176. kms := NewKubeModelSet(start, end)
  177. kms.RegisterCluster("cluster-uid")
  178. kms.RegisterNamespace("namespace-1-uid", "namespace-1")
  179. kms.RegisterNamespace("namespace-2-uid", "namespace-2")
  180. kms.RegisterResourceQuota("uid-1", "name-1", "namespace-1")
  181. kms.RegisterResourceQuota("uid-2", "name-2", "namespace-2")
  182. require.Len(t, kms.GetErrors(), 0)
  183. require.NotNil(t, kms.ResourceQuotas)
  184. require.Len(t, kms.ResourceQuotas, 2)
  185. testRQ1 := &ResourceQuota{
  186. UID: "uid-1",
  187. NamespaceUID: "namespace-1-uid",
  188. Name: "name-1",
  189. Spec: &ResourceQuotaSpec{Hard: &ResourceQuotaSpecHard{}},
  190. Status: &ResourceQuotaStatus{Used: &ResourceQuotaStatusUsed{}},
  191. }
  192. testRQ2 := &ResourceQuota{
  193. UID: "uid-2",
  194. NamespaceUID: "namespace-2-uid",
  195. Name: "name-2",
  196. Spec: &ResourceQuotaSpec{Hard: &ResourceQuotaSpecHard{}},
  197. Status: &ResourceQuotaStatus{Used: &ResourceQuotaStatusUsed{}},
  198. }
  199. require.Equal(t, testRQ1, kms.ResourceQuotas["uid-1"])
  200. require.Equal(t, testRQ2, kms.ResourceQuotas["uid-2"])
  201. require.Equal(t, 4, kms.Metadata.ObjectCount) // 2 namespaces and 2 RQs
  202. // Register a third RQ with an invalid namespace
  203. kms.RegisterResourceQuota("uid-3", "name-3", "namespace-3")
  204. require.Len(t, kms.GetWarnings(), 1)
  205. require.Equal(t, "RegisterResourceQuota(uid-3, name-3, namespace-3): missing namespace", kms.GetWarnings()[0].Message)
  206. testRQ3 := &ResourceQuota{
  207. UID: "uid-3",
  208. NamespaceUID: "",
  209. Name: "name-3",
  210. Spec: &ResourceQuotaSpec{Hard: &ResourceQuotaSpecHard{}},
  211. Status: &ResourceQuotaStatus{Used: &ResourceQuotaStatusUsed{}},
  212. }
  213. require.Len(t, kms.ResourceQuotas, 3)
  214. require.NotNil(t, kms.ResourceQuotas["uid-3"])
  215. require.Equal(t, testRQ3, kms.ResourceQuotas["uid-3"])
  216. require.Equal(t, 5, kms.Metadata.ObjectCount) // 2 namespaces and 3 RQs
  217. })
  218. })
  219. }