/pkg/backup/operator/operator_test.go

https://github.com/arangodb/kube-arangodb · Go · 371 lines · 265 code · 70 blank · 36 comment · 13 complexity · e293626292f13e0a2e638144c06080b9 MD5 · raw file

  1. //
  2. // DISCLAIMER
  3. //
  4. // Copyright 2016-2021 ArangoDB GmbH, Cologne, Germany
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License");
  7. // you may not use this file except in compliance with the License.
  8. // You may obtain a copy of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17. //
  18. // Copyright holder is ArangoDB GmbH, Cologne, Germany
  19. //
  20. // Author Adam Janikowski
  21. //
  22. package operator
  23. import (
  24. "context"
  25. "time"
  26. "github.com/rs/zerolog/log"
  27. "github.com/arangodb/kube-arangodb/pkg/backup/operator/operation"
  28. "github.com/stretchr/testify/assert"
  29. "testing"
  30. "github.com/stretchr/testify/require"
  31. core "k8s.io/api/core/v1"
  32. meta "k8s.io/apimachinery/pkg/apis/meta/v1"
  33. "k8s.io/apimachinery/pkg/util/uuid"
  34. "k8s.io/client-go/informers"
  35. "k8s.io/client-go/kubernetes/fake"
  36. )
  37. func Test_Operator_InformerProcessing(t *testing.T) {
  38. // Arrange
  39. name := string(uuid.NewUUID())
  40. o := NewOperator(log.Logger, name, name)
  41. size := 64
  42. objects := make([]string, size)
  43. for id := range objects {
  44. objects[id] = randomString(10)
  45. }
  46. m, i := mockSimpleObject(name, true)
  47. require.NoError(t, o.RegisterHandler(m))
  48. client := fake.NewSimpleClientset()
  49. informer := informers.NewSharedInformerFactory(client, 0)
  50. require.NoError(t, o.RegisterInformer(informer.Core().V1().Pods().Informer(), "", "v1", "pods"))
  51. require.NoError(t, o.RegisterStarter(informer))
  52. stopCh := make(chan struct{})
  53. // Act
  54. require.NoError(t, o.Start(4, stopCh))
  55. for _, name := range objects {
  56. _, err := client.CoreV1().Pods("test").Create(context.Background(), &core.Pod{
  57. TypeMeta: meta.TypeMeta{
  58. APIVersion: "v1",
  59. Kind: "Pod",
  60. },
  61. ObjectMeta: meta.ObjectMeta{
  62. Name: name,
  63. },
  64. }, meta.CreateOptions{})
  65. require.NoError(t, err)
  66. }
  67. // Assert
  68. res := waitForItems(t, i, size)
  69. assert.Len(t, res, size)
  70. time.Sleep(50 * time.Millisecond)
  71. assert.Len(t, i, 0)
  72. close(stopCh)
  73. close(i)
  74. }
  75. func Test_Operator_MultipleInformers(t *testing.T) {
  76. // Arrange
  77. name := string(uuid.NewUUID())
  78. o := NewOperator(log.Logger, name, name)
  79. size := 16
  80. objects := make([]string, size)
  81. for id := range objects {
  82. objects[id] = randomString(10)
  83. }
  84. m, i := mockSimpleObject(name, true)
  85. require.NoError(t, o.RegisterHandler(m))
  86. client := fake.NewSimpleClientset()
  87. informer := informers.NewSharedInformerFactory(client, 0)
  88. require.NoError(t, o.RegisterInformer(informer.Core().V1().Pods().Informer(), "", "v1", "pods"))
  89. require.NoError(t, o.RegisterInformer(informer.Core().V1().Nodes().Informer(), "", "v1", "nodes"))
  90. require.NoError(t, o.RegisterStarter(informer))
  91. stopCh := make(chan struct{})
  92. // Act
  93. require.NoError(t, o.Start(4, stopCh))
  94. for _, name := range objects {
  95. _, err := client.CoreV1().Pods("test").Create(context.Background(), &core.Pod{
  96. TypeMeta: meta.TypeMeta{
  97. APIVersion: "v1",
  98. Kind: "Pod",
  99. },
  100. ObjectMeta: meta.ObjectMeta{
  101. Name: name,
  102. },
  103. }, meta.CreateOptions{})
  104. require.NoError(t, err)
  105. _, err = client.CoreV1().Nodes().Create(context.Background(), &core.Node{
  106. TypeMeta: meta.TypeMeta{
  107. APIVersion: "v1",
  108. Kind: "Node",
  109. },
  110. ObjectMeta: meta.ObjectMeta{
  111. Name: name,
  112. },
  113. }, meta.CreateOptions{})
  114. require.NoError(t, err)
  115. }
  116. // Assert
  117. res := waitForItems(t, i, size*2)
  118. assert.Len(t, res, size*2)
  119. time.Sleep(50 * time.Millisecond)
  120. assert.Len(t, i, 0)
  121. close(stopCh)
  122. close(i)
  123. }
  124. func Test_Operator_MultipleInformers_IgnoredTypes(t *testing.T) {
  125. // Arrange
  126. name := string(uuid.NewUUID())
  127. o := NewOperator(log.Logger, name, name)
  128. size := 16
  129. objects := make([]string, size)
  130. for id := range objects {
  131. objects[id] = randomString(10)
  132. }
  133. m, i := mockSimpleObject(name, true)
  134. require.NoError(t, o.RegisterHandler(m))
  135. client := fake.NewSimpleClientset()
  136. informer := informers.NewSharedInformerFactory(client, 0)
  137. require.NoError(t, o.RegisterInformer(informer.Core().V1().Pods().Informer(), "", "v1", "pods"))
  138. require.NoError(t, o.RegisterStarter(informer))
  139. stopCh := make(chan struct{})
  140. // Act
  141. require.NoError(t, o.Start(4, stopCh))
  142. for _, name := range objects {
  143. _, err := client.CoreV1().Pods("test").Create(context.Background(), &core.Pod{
  144. TypeMeta: meta.TypeMeta{
  145. APIVersion: "v1",
  146. Kind: "Pod",
  147. },
  148. ObjectMeta: meta.ObjectMeta{
  149. Name: name,
  150. },
  151. }, meta.CreateOptions{})
  152. require.NoError(t, err)
  153. _, err = client.CoreV1().Nodes().Create(context.Background(), &core.Node{
  154. TypeMeta: meta.TypeMeta{
  155. APIVersion: "v1",
  156. Kind: "Node",
  157. },
  158. ObjectMeta: meta.ObjectMeta{
  159. Name: name,
  160. },
  161. }, meta.CreateOptions{})
  162. require.NoError(t, err)
  163. }
  164. // Assert
  165. res := waitForItems(t, i, size)
  166. assert.Len(t, res, size)
  167. time.Sleep(50 * time.Millisecond)
  168. assert.Len(t, i, 0)
  169. close(stopCh)
  170. close(i)
  171. }
  172. func Test_Operator_MultipleInformers_MultipleHandlers(t *testing.T) {
  173. // Arrange
  174. name := string(uuid.NewUUID())
  175. o := NewOperator(log.Logger, name, name)
  176. size := 16
  177. objects := make([]string, size)
  178. for id := range objects {
  179. objects[id] = randomString(10)
  180. }
  181. mp, ip := mockSimpleObjectFunc(name, func(item operation.Item) bool {
  182. return item.Kind == "pods"
  183. })
  184. require.NoError(t, o.RegisterHandler(mp))
  185. mn, in := mockSimpleObjectFunc(name, func(item operation.Item) bool {
  186. return item.Kind == "nodes"
  187. })
  188. require.NoError(t, o.RegisterHandler(mn))
  189. ms, is := mockSimpleObjectFunc(name, func(item operation.Item) bool {
  190. return item.Kind == "services"
  191. })
  192. require.NoError(t, o.RegisterHandler(ms))
  193. md, id := mockSimpleObject(name, true)
  194. require.NoError(t, o.RegisterHandler(md))
  195. client := fake.NewSimpleClientset()
  196. informer := informers.NewSharedInformerFactory(client, 0)
  197. require.NoError(t, o.RegisterInformer(informer.Core().V1().Pods().Informer(), "", "v1", "pods"))
  198. require.NoError(t, o.RegisterInformer(informer.Core().V1().Nodes().Informer(), "", "v1", "nodes"))
  199. require.NoError(t, o.RegisterInformer(informer.Core().V1().Services().Informer(), "", "v1", "services"))
  200. require.NoError(t, o.RegisterInformer(informer.Core().V1().ServiceAccounts().Informer(), "", "v1", "sa"))
  201. require.NoError(t, o.RegisterStarter(informer))
  202. stopCh := make(chan struct{})
  203. // Act
  204. require.NoError(t, o.Start(4, stopCh))
  205. for _, name := range objects {
  206. _, err := client.CoreV1().Pods("test").Create(context.Background(), &core.Pod{
  207. TypeMeta: meta.TypeMeta{
  208. APIVersion: "v1",
  209. Kind: "Pod",
  210. },
  211. ObjectMeta: meta.ObjectMeta{
  212. Name: name,
  213. },
  214. }, meta.CreateOptions{})
  215. require.NoError(t, err)
  216. _, err = client.CoreV1().Nodes().Create(context.Background(), &core.Node{
  217. TypeMeta: meta.TypeMeta{
  218. APIVersion: "v1",
  219. Kind: "Node",
  220. },
  221. ObjectMeta: meta.ObjectMeta{
  222. Name: name,
  223. },
  224. }, meta.CreateOptions{})
  225. require.NoError(t, err)
  226. _, err = client.CoreV1().Services("test").Create(context.Background(), &core.Service{
  227. TypeMeta: meta.TypeMeta{
  228. APIVersion: "v1",
  229. Kind: "Service",
  230. },
  231. ObjectMeta: meta.ObjectMeta{
  232. Name: name,
  233. },
  234. }, meta.CreateOptions{})
  235. require.NoError(t, err)
  236. _, err = client.CoreV1().ServiceAccounts("test").Create(context.Background(), &core.ServiceAccount{
  237. TypeMeta: meta.TypeMeta{
  238. APIVersion: "v1",
  239. Kind: "ServiceAccount",
  240. },
  241. ObjectMeta: meta.ObjectMeta{
  242. Name: name,
  243. },
  244. }, meta.CreateOptions{})
  245. require.NoError(t, err)
  246. }
  247. // Assert
  248. assert.Len(t, waitForItems(t, ip, size), size)
  249. assert.Len(t, waitForItems(t, in, size), size)
  250. assert.Len(t, waitForItems(t, is, size), size)
  251. assert.Len(t, waitForItems(t, id, size), size)
  252. time.Sleep(50 * time.Millisecond)
  253. assert.Len(t, ip, 0)
  254. assert.Len(t, in, 0)
  255. assert.Len(t, is, 0)
  256. assert.Len(t, id, 0)
  257. close(stopCh)
  258. close(ip)
  259. close(in)
  260. close(is)
  261. close(id)
  262. }
  263. func Test_Operator_InformerProcessing_Namespaced(t *testing.T) {
  264. // Arrange
  265. name := string(uuid.NewUUID())
  266. o := NewOperator(log.Logger, name, name)
  267. size := 16
  268. objects := make([]string, size)
  269. for id := range objects {
  270. objects[id] = randomString(10)
  271. }
  272. m, i := mockSimpleObject(name, true)
  273. require.NoError(t, o.RegisterHandler(m))
  274. client := fake.NewSimpleClientset()
  275. informer := informers.NewSharedInformerFactoryWithOptions(client, 0, informers.WithNamespace(objects[0]))
  276. require.NoError(t, o.RegisterInformer(informer.Core().V1().Pods().Informer(), "", "v1", "pods"))
  277. require.NoError(t, o.RegisterStarter(informer))
  278. stopCh := make(chan struct{})
  279. // Act
  280. require.NoError(t, o.Start(4, stopCh))
  281. for _, name := range objects {
  282. _, err := client.CoreV1().Pods(name).Create(context.Background(), &core.Pod{
  283. TypeMeta: meta.TypeMeta{
  284. APIVersion: "v1",
  285. Kind: "Pod",
  286. },
  287. ObjectMeta: meta.ObjectMeta{
  288. Name: name,
  289. Namespace: name,
  290. },
  291. }, meta.CreateOptions{})
  292. require.NoError(t, err)
  293. }
  294. // Assert
  295. res := waitForItems(t, i, 1)
  296. assert.Len(t, res, 1)
  297. time.Sleep(50 * time.Millisecond)
  298. assert.Len(t, i, 0)
  299. close(stopCh)
  300. close(i)
  301. }