cache_based_manager_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. Copyright 2018 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 manager
  14. import (
  15. "fmt"
  16. "reflect"
  17. "strings"
  18. "sync"
  19. "testing"
  20. "time"
  21. v1 "k8s.io/api/core/v1"
  22. apierrors "k8s.io/apimachinery/pkg/api/errors"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "k8s.io/apimachinery/pkg/runtime"
  25. "k8s.io/apimachinery/pkg/util/clock"
  26. "k8s.io/apimachinery/pkg/util/sets"
  27. clientset "k8s.io/client-go/kubernetes"
  28. "k8s.io/client-go/kubernetes/fake"
  29. core "k8s.io/client-go/testing"
  30. podutil "k8s.io/kubernetes/pkg/api/v1/pod"
  31. "github.com/stretchr/testify/assert"
  32. )
  33. func checkObject(t *testing.T, store *objectStore, ns, name string, shouldExist bool) {
  34. _, err := store.Get(ns, name)
  35. if shouldExist && err != nil {
  36. t.Errorf("unexpected actions: %#v", err)
  37. }
  38. if !shouldExist && (err == nil || !strings.Contains(err.Error(), fmt.Sprintf("object %q/%q not registered", ns, name))) {
  39. t.Errorf("unexpected actions: %#v", err)
  40. }
  41. }
  42. func noObjectTTL() (time.Duration, bool) {
  43. return time.Duration(0), false
  44. }
  45. func getSecret(fakeClient clientset.Interface) GetObjectFunc {
  46. return func(namespace, name string, opts metav1.GetOptions) (runtime.Object, error) {
  47. return fakeClient.CoreV1().Secrets(namespace).Get(name, opts)
  48. }
  49. }
  50. func newSecretStore(fakeClient clientset.Interface, clock clock.Clock, getTTL GetObjectTTLFunc, ttl time.Duration) *objectStore {
  51. return &objectStore{
  52. getObject: getSecret(fakeClient),
  53. clock: clock,
  54. items: make(map[objectKey]*objectStoreItem),
  55. defaultTTL: ttl,
  56. getTTL: getTTL,
  57. }
  58. }
  59. func getSecretNames(pod *v1.Pod) sets.String {
  60. result := sets.NewString()
  61. podutil.VisitPodSecretNames(pod, func(name string) bool {
  62. result.Insert(name)
  63. return true
  64. })
  65. return result
  66. }
  67. func newCacheBasedSecretManager(store Store) Manager {
  68. return NewCacheBasedManager(store, getSecretNames)
  69. }
  70. func TestSecretStore(t *testing.T) {
  71. fakeClient := &fake.Clientset{}
  72. store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0)
  73. store.AddReference("ns1", "name1")
  74. store.AddReference("ns2", "name2")
  75. store.AddReference("ns1", "name1")
  76. store.AddReference("ns1", "name1")
  77. store.DeleteReference("ns1", "name1")
  78. store.DeleteReference("ns2", "name2")
  79. store.AddReference("ns3", "name3")
  80. // Adds don't issue Get requests.
  81. actions := fakeClient.Actions()
  82. assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions)
  83. // Should issue Get request
  84. store.Get("ns1", "name1")
  85. // Shouldn't issue Get request, as secret is not registered
  86. store.Get("ns2", "name2")
  87. // Should issue Get request
  88. store.Get("ns3", "name3")
  89. actions = fakeClient.Actions()
  90. assert.Equal(t, 2, len(actions), "unexpected actions: %#v", actions)
  91. for _, a := range actions {
  92. assert.True(t, a.Matches("get", "secrets"), "unexpected actions: %#v", a)
  93. }
  94. checkObject(t, store, "ns1", "name1", true)
  95. checkObject(t, store, "ns2", "name2", false)
  96. checkObject(t, store, "ns3", "name3", true)
  97. checkObject(t, store, "ns4", "name4", false)
  98. }
  99. func TestSecretStoreDeletingSecret(t *testing.T) {
  100. fakeClient := &fake.Clientset{}
  101. store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0)
  102. store.AddReference("ns", "name")
  103. result := &v1.Secret{ObjectMeta: metav1.ObjectMeta{Namespace: "ns", Name: "name", ResourceVersion: "10"}}
  104. fakeClient.AddReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
  105. return true, result, nil
  106. })
  107. secret, err := store.Get("ns", "name")
  108. if err != nil {
  109. t.Errorf("Unexpected error: %v", err)
  110. }
  111. if !reflect.DeepEqual(secret, result) {
  112. t.Errorf("Unexpected secret: %v", secret)
  113. }
  114. fakeClient.PrependReactor("get", "secrets", func(action core.Action) (bool, runtime.Object, error) {
  115. return true, &v1.Secret{}, apierrors.NewNotFound(v1.Resource("secret"), "name")
  116. })
  117. secret, err = store.Get("ns", "name")
  118. if err == nil || !apierrors.IsNotFound(err) {
  119. t.Errorf("Unexpected error: %v", err)
  120. }
  121. if !reflect.DeepEqual(secret, &v1.Secret{}) {
  122. t.Errorf("Unexpected secret: %v", secret)
  123. }
  124. }
  125. func TestSecretStoreGetAlwaysRefresh(t *testing.T) {
  126. fakeClient := &fake.Clientset{}
  127. fakeClock := clock.NewFakeClock(time.Now())
  128. store := newSecretStore(fakeClient, fakeClock, noObjectTTL, 0)
  129. for i := 0; i < 10; i++ {
  130. store.AddReference(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i))
  131. }
  132. fakeClient.ClearActions()
  133. wg := sync.WaitGroup{}
  134. wg.Add(100)
  135. for i := 0; i < 100; i++ {
  136. go func(i int) {
  137. store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10))
  138. wg.Done()
  139. }(i)
  140. }
  141. wg.Wait()
  142. actions := fakeClient.Actions()
  143. assert.Equal(t, 100, len(actions), "unexpected actions: %#v", actions)
  144. for _, a := range actions {
  145. assert.True(t, a.Matches("get", "secrets"), "unexpected actions: %#v", a)
  146. }
  147. }
  148. func TestSecretStoreGetNeverRefresh(t *testing.T) {
  149. fakeClient := &fake.Clientset{}
  150. fakeClock := clock.NewFakeClock(time.Now())
  151. store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute)
  152. for i := 0; i < 10; i++ {
  153. store.AddReference(fmt.Sprintf("ns-%d", i), fmt.Sprintf("name-%d", i))
  154. }
  155. fakeClient.ClearActions()
  156. wg := sync.WaitGroup{}
  157. wg.Add(100)
  158. for i := 0; i < 100; i++ {
  159. go func(i int) {
  160. store.Get(fmt.Sprintf("ns-%d", i%10), fmt.Sprintf("name-%d", i%10))
  161. wg.Done()
  162. }(i)
  163. }
  164. wg.Wait()
  165. actions := fakeClient.Actions()
  166. // Only first Get, should forward the Get request.
  167. assert.Equal(t, 10, len(actions), "unexpected actions: %#v", actions)
  168. }
  169. func TestCustomTTL(t *testing.T) {
  170. ttl := time.Duration(0)
  171. ttlExists := false
  172. customTTL := func() (time.Duration, bool) {
  173. return ttl, ttlExists
  174. }
  175. fakeClient := &fake.Clientset{}
  176. fakeClock := clock.NewFakeClock(time.Time{})
  177. store := newSecretStore(fakeClient, fakeClock, customTTL, time.Minute)
  178. store.AddReference("ns", "name")
  179. store.Get("ns", "name")
  180. fakeClient.ClearActions()
  181. // Set 0-ttl and see if that works.
  182. ttl = time.Duration(0)
  183. ttlExists = true
  184. store.Get("ns", "name")
  185. actions := fakeClient.Actions()
  186. assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions)
  187. fakeClient.ClearActions()
  188. // Set 5-minute ttl and see if this works.
  189. ttl = time.Duration(5) * time.Minute
  190. store.Get("ns", "name")
  191. actions = fakeClient.Actions()
  192. assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions)
  193. // Still no effect after 4 minutes.
  194. fakeClock.Step(4 * time.Minute)
  195. store.Get("ns", "name")
  196. actions = fakeClient.Actions()
  197. assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions)
  198. // Now it should have an effect.
  199. fakeClock.Step(time.Minute)
  200. store.Get("ns", "name")
  201. actions = fakeClient.Actions()
  202. assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions)
  203. fakeClient.ClearActions()
  204. // Now remove the custom ttl and see if that works.
  205. ttlExists = false
  206. fakeClock.Step(55 * time.Second)
  207. store.Get("ns", "name")
  208. actions = fakeClient.Actions()
  209. assert.Equal(t, 0, len(actions), "unexpected actions: %#v", actions)
  210. // Pass the minute and it should be triggered now.
  211. fakeClock.Step(5 * time.Second)
  212. store.Get("ns", "name")
  213. actions = fakeClient.Actions()
  214. assert.Equal(t, 1, len(actions), "unexpected actions: %#v", actions)
  215. }
  216. func TestParseNodeAnnotation(t *testing.T) {
  217. testCases := []struct {
  218. node *v1.Node
  219. err error
  220. exists bool
  221. ttl time.Duration
  222. }{
  223. {
  224. node: nil,
  225. err: fmt.Errorf("error"),
  226. exists: false,
  227. },
  228. {
  229. node: &v1.Node{
  230. ObjectMeta: metav1.ObjectMeta{
  231. Name: "node",
  232. },
  233. },
  234. exists: false,
  235. },
  236. {
  237. node: &v1.Node{
  238. ObjectMeta: metav1.ObjectMeta{
  239. Name: "node",
  240. Annotations: map[string]string{},
  241. },
  242. },
  243. exists: false,
  244. },
  245. {
  246. node: &v1.Node{
  247. ObjectMeta: metav1.ObjectMeta{
  248. Name: "node",
  249. Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "bad"},
  250. },
  251. },
  252. exists: false,
  253. },
  254. {
  255. node: &v1.Node{
  256. ObjectMeta: metav1.ObjectMeta{
  257. Name: "node",
  258. Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "0"},
  259. },
  260. },
  261. exists: true,
  262. ttl: time.Duration(0),
  263. },
  264. {
  265. node: &v1.Node{
  266. ObjectMeta: metav1.ObjectMeta{
  267. Name: "node",
  268. Annotations: map[string]string{v1.ObjectTTLAnnotationKey: "60"},
  269. },
  270. },
  271. exists: true,
  272. ttl: time.Minute,
  273. },
  274. }
  275. for i, testCase := range testCases {
  276. getNode := func() (*v1.Node, error) { return testCase.node, testCase.err }
  277. ttl, exists := GetObjectTTLFromNodeFunc(getNode)()
  278. if exists != testCase.exists {
  279. t.Errorf("%d: incorrect parsing: %t", i, exists)
  280. continue
  281. }
  282. if exists && ttl != testCase.ttl {
  283. t.Errorf("%d: incorrect ttl: %v", i, ttl)
  284. }
  285. }
  286. }
  287. type envSecrets struct {
  288. envVarNames []string
  289. envFromNames []string
  290. }
  291. type secretsToAttach struct {
  292. imagePullSecretNames []string
  293. containerEnvSecrets []envSecrets
  294. }
  295. func podWithSecrets(ns, podName string, toAttach secretsToAttach) *v1.Pod {
  296. pod := &v1.Pod{
  297. ObjectMeta: metav1.ObjectMeta{
  298. Namespace: ns,
  299. Name: podName,
  300. },
  301. Spec: v1.PodSpec{},
  302. }
  303. for _, name := range toAttach.imagePullSecretNames {
  304. pod.Spec.ImagePullSecrets = append(
  305. pod.Spec.ImagePullSecrets, v1.LocalObjectReference{Name: name})
  306. }
  307. for i, secrets := range toAttach.containerEnvSecrets {
  308. container := v1.Container{
  309. Name: fmt.Sprintf("container-%d", i),
  310. }
  311. for _, name := range secrets.envFromNames {
  312. envFrom := v1.EnvFromSource{
  313. SecretRef: &v1.SecretEnvSource{
  314. LocalObjectReference: v1.LocalObjectReference{
  315. Name: name,
  316. },
  317. },
  318. }
  319. container.EnvFrom = append(container.EnvFrom, envFrom)
  320. }
  321. for _, name := range secrets.envVarNames {
  322. envSource := &v1.EnvVarSource{
  323. SecretKeyRef: &v1.SecretKeySelector{
  324. LocalObjectReference: v1.LocalObjectReference{
  325. Name: name,
  326. },
  327. },
  328. }
  329. container.Env = append(container.Env, v1.EnvVar{ValueFrom: envSource})
  330. }
  331. pod.Spec.Containers = append(pod.Spec.Containers, container)
  332. }
  333. return pod
  334. }
  335. func TestCacheInvalidation(t *testing.T) {
  336. fakeClient := &fake.Clientset{}
  337. fakeClock := clock.NewFakeClock(time.Now())
  338. store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute)
  339. manager := newCacheBasedSecretManager(store)
  340. // Create a pod with some secrets.
  341. s1 := secretsToAttach{
  342. imagePullSecretNames: []string{"s1"},
  343. containerEnvSecrets: []envSecrets{
  344. {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}},
  345. {envVarNames: []string{"s2"}},
  346. },
  347. }
  348. manager.RegisterPod(podWithSecrets("ns1", "name1", s1))
  349. // Fetch both secrets - this should triggger get operations.
  350. store.Get("ns1", "s1")
  351. store.Get("ns1", "s10")
  352. store.Get("ns1", "s2")
  353. actions := fakeClient.Actions()
  354. assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions)
  355. fakeClient.ClearActions()
  356. // Update a pod with a new secret.
  357. s2 := secretsToAttach{
  358. imagePullSecretNames: []string{"s1"},
  359. containerEnvSecrets: []envSecrets{
  360. {envVarNames: []string{"s1"}},
  361. {envVarNames: []string{"s2"}, envFromNames: []string{"s20"}},
  362. {envVarNames: []string{"s3"}},
  363. },
  364. }
  365. manager.RegisterPod(podWithSecrets("ns1", "name1", s2))
  366. // All secrets should be invalidated - this should trigger get operations.
  367. store.Get("ns1", "s1")
  368. store.Get("ns1", "s2")
  369. store.Get("ns1", "s20")
  370. store.Get("ns1", "s3")
  371. actions = fakeClient.Actions()
  372. assert.Equal(t, 4, len(actions), "unexpected actions: %#v", actions)
  373. fakeClient.ClearActions()
  374. // Create a new pod that is refencing the first three secrets - those should
  375. // be invalidated.
  376. manager.RegisterPod(podWithSecrets("ns1", "name2", s1))
  377. store.Get("ns1", "s1")
  378. store.Get("ns1", "s10")
  379. store.Get("ns1", "s2")
  380. store.Get("ns1", "s20")
  381. store.Get("ns1", "s3")
  382. actions = fakeClient.Actions()
  383. assert.Equal(t, 3, len(actions), "unexpected actions: %#v", actions)
  384. fakeClient.ClearActions()
  385. }
  386. func TestRegisterIdempotence(t *testing.T) {
  387. fakeClient := &fake.Clientset{}
  388. fakeClock := clock.NewFakeClock(time.Now())
  389. store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute)
  390. manager := newCacheBasedSecretManager(store)
  391. s1 := secretsToAttach{
  392. imagePullSecretNames: []string{"s1"},
  393. }
  394. refs := func(ns, name string) int {
  395. store.lock.Lock()
  396. defer store.lock.Unlock()
  397. item, ok := store.items[objectKey{ns, name}]
  398. if !ok {
  399. return 0
  400. }
  401. return item.refCount
  402. }
  403. manager.RegisterPod(podWithSecrets("ns1", "name1", s1))
  404. assert.Equal(t, 1, refs("ns1", "s1"))
  405. manager.RegisterPod(podWithSecrets("ns1", "name1", s1))
  406. assert.Equal(t, 1, refs("ns1", "s1"))
  407. manager.RegisterPod(podWithSecrets("ns1", "name2", s1))
  408. assert.Equal(t, 2, refs("ns1", "s1"))
  409. manager.UnregisterPod(podWithSecrets("ns1", "name1", s1))
  410. assert.Equal(t, 1, refs("ns1", "s1"))
  411. manager.UnregisterPod(podWithSecrets("ns1", "name1", s1))
  412. assert.Equal(t, 1, refs("ns1", "s1"))
  413. manager.UnregisterPod(podWithSecrets("ns1", "name2", s1))
  414. assert.Equal(t, 0, refs("ns1", "s1"))
  415. }
  416. func TestCacheRefcounts(t *testing.T) {
  417. fakeClient := &fake.Clientset{}
  418. fakeClock := clock.NewFakeClock(time.Now())
  419. store := newSecretStore(fakeClient, fakeClock, noObjectTTL, time.Minute)
  420. manager := newCacheBasedSecretManager(store)
  421. s1 := secretsToAttach{
  422. imagePullSecretNames: []string{"s1"},
  423. containerEnvSecrets: []envSecrets{
  424. {envVarNames: []string{"s1"}, envFromNames: []string{"s10"}},
  425. {envVarNames: []string{"s2"}},
  426. {envVarNames: []string{"s3"}},
  427. },
  428. }
  429. manager.RegisterPod(podWithSecrets("ns1", "name1", s1))
  430. manager.RegisterPod(podWithSecrets("ns1", "name2", s1))
  431. s2 := secretsToAttach{
  432. imagePullSecretNames: []string{"s2"},
  433. containerEnvSecrets: []envSecrets{
  434. {envVarNames: []string{"s4"}},
  435. {envVarNames: []string{"s5"}, envFromNames: []string{"s50"}},
  436. },
  437. }
  438. manager.RegisterPod(podWithSecrets("ns1", "name2", s2))
  439. manager.RegisterPod(podWithSecrets("ns1", "name3", s2))
  440. manager.RegisterPod(podWithSecrets("ns1", "name4", s2))
  441. manager.UnregisterPod(podWithSecrets("ns1", "name3", s2))
  442. s3 := secretsToAttach{
  443. imagePullSecretNames: []string{"s1"},
  444. containerEnvSecrets: []envSecrets{
  445. {envVarNames: []string{"s3"}, envFromNames: []string{"s30"}},
  446. {envVarNames: []string{"s5"}},
  447. },
  448. }
  449. manager.RegisterPod(podWithSecrets("ns1", "name5", s3))
  450. manager.RegisterPod(podWithSecrets("ns1", "name6", s3))
  451. s4 := secretsToAttach{
  452. imagePullSecretNames: []string{"s3"},
  453. containerEnvSecrets: []envSecrets{
  454. {envVarNames: []string{"s6"}},
  455. {envFromNames: []string{"s60"}},
  456. },
  457. }
  458. manager.RegisterPod(podWithSecrets("ns1", "name7", s4))
  459. manager.UnregisterPod(podWithSecrets("ns1", "name7", s4))
  460. // Also check the Add + Update + Remove scenario.
  461. manager.RegisterPod(podWithSecrets("ns1", "other-name", s1))
  462. manager.RegisterPod(podWithSecrets("ns1", "other-name", s2))
  463. manager.UnregisterPod(podWithSecrets("ns1", "other-name", s2))
  464. s5 := secretsToAttach{
  465. containerEnvSecrets: []envSecrets{
  466. {envVarNames: []string{"s7"}},
  467. {envFromNames: []string{"s70"}},
  468. },
  469. }
  470. // Check the no-op update scenario
  471. manager.RegisterPod(podWithSecrets("ns1", "noop-pod", s5))
  472. manager.RegisterPod(podWithSecrets("ns1", "noop-pod", s5))
  473. // Now we have: 3 pods with s1, 2 pods with s2 and 2 pods with s3, 0 pods with s4.
  474. refs := func(ns, name string) int {
  475. store.lock.Lock()
  476. defer store.lock.Unlock()
  477. item, ok := store.items[objectKey{ns, name}]
  478. if !ok {
  479. return 0
  480. }
  481. return item.refCount
  482. }
  483. assert.Equal(t, 3, refs("ns1", "s1"))
  484. assert.Equal(t, 1, refs("ns1", "s10"))
  485. assert.Equal(t, 3, refs("ns1", "s2"))
  486. assert.Equal(t, 3, refs("ns1", "s3"))
  487. assert.Equal(t, 2, refs("ns1", "s30"))
  488. assert.Equal(t, 2, refs("ns1", "s4"))
  489. assert.Equal(t, 4, refs("ns1", "s5"))
  490. assert.Equal(t, 2, refs("ns1", "s50"))
  491. assert.Equal(t, 0, refs("ns1", "s6"))
  492. assert.Equal(t, 0, refs("ns1", "s60"))
  493. assert.Equal(t, 1, refs("ns1", "s7"))
  494. assert.Equal(t, 1, refs("ns1", "s70"))
  495. }
  496. func TestCacheBasedSecretManager(t *testing.T) {
  497. fakeClient := &fake.Clientset{}
  498. store := newSecretStore(fakeClient, clock.RealClock{}, noObjectTTL, 0)
  499. manager := newCacheBasedSecretManager(store)
  500. // Create a pod with some secrets.
  501. s1 := secretsToAttach{
  502. imagePullSecretNames: []string{"s1"},
  503. containerEnvSecrets: []envSecrets{
  504. {envVarNames: []string{"s1"}},
  505. {envVarNames: []string{"s2"}},
  506. {envFromNames: []string{"s20"}},
  507. },
  508. }
  509. manager.RegisterPod(podWithSecrets("ns1", "name1", s1))
  510. // Update the pod with a different secrets.
  511. s2 := secretsToAttach{
  512. imagePullSecretNames: []string{"s1"},
  513. containerEnvSecrets: []envSecrets{
  514. {envVarNames: []string{"s3"}},
  515. {envVarNames: []string{"s4"}},
  516. {envFromNames: []string{"s40"}},
  517. },
  518. }
  519. manager.RegisterPod(podWithSecrets("ns1", "name1", s2))
  520. // Create another pod, but with same secrets in different namespace.
  521. manager.RegisterPod(podWithSecrets("ns2", "name2", s2))
  522. // Create and delete a pod with some other secrets.
  523. s3 := secretsToAttach{
  524. imagePullSecretNames: []string{"s5"},
  525. containerEnvSecrets: []envSecrets{
  526. {envVarNames: []string{"s6"}},
  527. {envFromNames: []string{"s60"}},
  528. },
  529. }
  530. manager.RegisterPod(podWithSecrets("ns3", "name", s3))
  531. manager.UnregisterPod(podWithSecrets("ns3", "name", s3))
  532. // We should have only: s1, s3 and s4 secrets in namespaces: ns1 and ns2.
  533. for _, ns := range []string{"ns1", "ns2", "ns3"} {
  534. for _, secret := range []string{"s1", "s2", "s3", "s4", "s5", "s6", "s20", "s40", "s50"} {
  535. shouldExist :=
  536. (secret == "s1" || secret == "s3" || secret == "s4" || secret == "s40") && (ns == "ns1" || ns == "ns2")
  537. checkObject(t, store, ns, secret, shouldExist)
  538. }
  539. }
  540. }