1
16
17 package systemnamespaces
18
19 import (
20 "testing"
21
22 v1 "k8s.io/api/core/v1"
23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 "k8s.io/apimachinery/pkg/labels"
25 "k8s.io/apimachinery/pkg/runtime"
26 "k8s.io/client-go/informers"
27 "k8s.io/client-go/kubernetes/fake"
28 k8stesting "k8s.io/client-go/testing"
29 )
30
31
32 func Test_Controller(t *testing.T) {
33 systemNamespaces := []string{metav1.NamespaceSystem, metav1.NamespacePublic, v1.NamespaceNodeLease}
34
35 tests := []struct {
36 name string
37 namespaces []string
38 actions [][]string
39 }{
40 {
41 name: "no system namespaces",
42 actions: [][]string{
43 {"create", "namespaces"},
44 {"create", "namespaces"},
45 {"create", "namespaces"},
46 {"create", "namespaces"},
47 },
48 },
49 {
50 name: "no system namespaces but others",
51 namespaces: []string{"foo", "bar"},
52 actions: [][]string{
53 {"create", "namespaces"},
54 {"create", "namespaces"},
55 {"create", "namespaces"},
56 {"create", "namespaces"},
57 },
58 },
59 {
60 name: "one system namespace",
61 namespaces: []string{metav1.NamespaceSystem},
62 actions: [][]string{
63 {"create", "namespaces"},
64 {"create", "namespaces"},
65 {"create", "namespaces"},
66 },
67 },
68 {
69 name: "two system namespaces",
70 namespaces: []string{metav1.NamespaceSystem, metav1.NamespacePublic},
71 actions: [][]string{
72 {"create", "namespaces"},
73 {"create", "namespaces"},
74 },
75 },
76 {
77 name: "three namespaces",
78 namespaces: []string{metav1.NamespaceSystem, metav1.NamespacePublic, v1.NamespaceNodeLease},
79 actions: [][]string{
80 {"create", "namespaces"},
81 },
82 },
83
84 {
85 name: "the four namespaces",
86 namespaces: []string{metav1.NamespaceSystem, metav1.NamespacePublic, v1.NamespaceNodeLease, v1.NamespaceDefault},
87 },
88 }
89
90 for _, test := range tests {
91 t.Run(test.name, func(t *testing.T) {
92 objs := []runtime.Object{}
93 for _, ns := range test.namespaces {
94 objs = append(objs,
95 &v1.Namespace{
96 ObjectMeta: metav1.ObjectMeta{
97 Name: ns,
98 Namespace: "",
99 },
100 },
101 )
102 }
103 clientset := fake.NewSimpleClientset(objs...)
104 informerFactory := informers.NewSharedInformerFactory(clientset, 0)
105 namespaceInformer := informerFactory.Core().V1().Namespaces()
106 for _, obj := range objs {
107 namespaceInformer.Informer().GetIndexer().Add(obj)
108 }
109
110 controller := NewController(clientset, namespaceInformer)
111
112 clientset.PrependReactor("create", "namespaces", func(action k8stesting.Action) (bool, runtime.Object, error) {
113 create := action.(k8stesting.CreateAction)
114 namespaceInformer.Informer().GetIndexer().Add(create.GetObject())
115 return true, create.GetObject(), nil
116 })
117
118 controller.sync()
119
120 expectAction(t, clientset.Actions(), test.actions)
121 namespaces, err := controller.namespaceLister.List(labels.Everything())
122 if err != nil {
123 t.Errorf("unexpected error: %v", err)
124 }
125
126 got := map[string]bool{}
127 for _, ns := range namespaces {
128 got[ns.Name] = true
129 }
130
131 for _, ns := range systemNamespaces {
132 if !got[ns] {
133 t.Errorf("unexpected namespaces: %v", namespaces)
134 break
135 }
136 }
137 })
138 }
139 }
140
141 func expectAction(t *testing.T, actions []k8stesting.Action, expected [][]string) {
142 t.Helper()
143 if len(actions) != len(expected) {
144 t.Fatalf("Expected at least %d actions, got %d", len(expected), len(actions))
145 }
146
147 for i, action := range actions {
148 verb := expected[i][0]
149 if action.GetVerb() != verb {
150 t.Errorf("Expected action %d verb to be %s, got %s", i, verb, action.GetVerb())
151 }
152 resource := expected[i][1]
153 if action.GetResource().Resource != resource {
154 t.Errorf("Expected action %d resource to be %s, got %s", i, resource, action.GetResource().Resource)
155 }
156 }
157 }
158
View as plain text