1 package edgeinjector
2
3 import (
4 "context"
5 "fmt"
6
7 "reflect"
8 "testing"
9 "time"
10
11 dsapi "edge-infra.dev/pkg/edge/datasync/apis/v1alpha1"
12 "edge-infra.dev/pkg/edge/datasync/couchdb"
13 "edge-infra.dev/pkg/edge/k8objectsutils/ownerref"
14 "edge-infra.dev/pkg/k8s/runtime/controller"
15 "edge-infra.dev/pkg/lib/fog"
16 v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
17 nodemeta "edge-infra.dev/pkg/sds/ien/node"
18 "edge-infra.dev/test/framework/k8s/envtest"
19
20 "github.com/google/uuid"
21 "github.com/stretchr/testify/assert"
22 "github.com/stretchr/testify/require"
23
24 appsv1 "k8s.io/api/apps/v1"
25 corev1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/types"
28 ctrl "sigs.k8s.io/controller-runtime"
29 "sigs.k8s.io/controller-runtime/pkg/client"
30 )
31
32 var (
33 namespace = "default"
34 timeout = 5 * time.Second
35 interval = time.Second
36 log = fog.New()
37 testEnv *envtest.Environment
38 cfg = &Config{
39 EnableWebhook: false,
40 ReconcileConcurrency: 1,
41 PollingInterval: timeout,
42 RequeueTime: interval,
43 }
44 mgr ctrl.Manager
45 )
46
47 func TestMain(m *testing.M) {
48 testEnv = envtest.Setup()
49 defer func() {
50 err := testEnv.Stop()
51 if err != nil {
52 panic(fmt.Errorf("failed to stop test environment, %w", err))
53 }
54 }()
55 var err error
56 mgr, err = create(log, cfg, controller.WithCfg(testEnv.Config))
57 if err != nil {
58 panic(fmt.Errorf("failed to create manager, %w", err))
59 }
60 go func() {
61 err = mgr.Start(ctrl.SetupSignalHandler())
62 if err != nil {
63 panic(fmt.Errorf("failed to start manager, %w", err))
64 }
65 }()
66 m.Run()
67 }
68
69 func TestCouchDBUserSecret(t *testing.T) {
70 ctx := context.Background()
71 uid := uuid.New().String()
72
73 cl := mgr.GetClient()
74
75 nodeName := fmt.Sprintf("node-%s", uid)
76 node := &corev1.Node{
77 TypeMeta: metav1.TypeMeta{
78 APIVersion: "v1",
79 Kind: "Node",
80 },
81 ObjectMeta: metav1.ObjectMeta{
82 UID: types.UID(uid),
83 Name: nodeName,
84 Labels: map[string]string{
85 nodemeta.RoleLabel: string(v1ien.ControlPlane),
86 nodemeta.ClassLabel: string(v1ien.Server),
87 },
88 },
89 }
90 require.NoError(t, cl.Create(ctx, node), "fail to create node")
91
92 deployment := basicDeployment(namespace, fmt.Sprintf("deploy-%s", uid))
93 require.NoError(t, cl.Create(ctx, deployment), "fail to create deployment")
94
95 pod := basicPod(namespace, deployment.Name, nodeName, ownerReference(deployment))
96 require.NoError(t, cl.Create(ctx, pod), "fail to create pod")
97
98 require.Eventually(t, func() bool {
99 err := cl.Get(ctx, client.ObjectKeyFromObject(pod), pod)
100 return err == nil
101 }, timeout, interval, "pod does not exist")
102
103 if len(pod.Labels) == 0 {
104 pod.Labels = map[string]string{}
105 }
106
107 secretName := fmt.Sprintf("%s-%s", CouchDBSecret, uid)
108 pod.Labels[SecretLabel(CouchDBSecret)] = secretName
109 require.NoError(t, cl.Update(ctx, pod), "fail to update pod")
110
111 require.Eventually(t, func() bool {
112 err := cl.Get(ctx, client.ObjectKeyFromObject(pod), pod)
113 return err == nil && pod.Labels[SecretLabel(CouchDBSecret)] == secretName
114 }, timeout, interval, "pod does not contain secret label")
115
116 ref := metav1.OwnerReference{Name: fmt.Sprintf("deploy-%s", uid)}
117 username := ownerref.ResourceName(fmt.Sprintf("%s-%s", couchdb.CouchDBName, node.UID), ref, namespace, nodeName, false)
118
119 user := &dsapi.CouchDBUser{
120 TypeMeta: metav1.TypeMeta{
121 APIVersion: dsapi.GroupVersion.String(),
122 Kind: "CouchDBUser",
123 },
124 ObjectMeta: metav1.ObjectMeta{
125 Name: username,
126 Namespace: namespace,
127 },
128 }
129
130
131 require.Eventually(t, func() bool {
132 err := cl.Get(ctx, client.ObjectKeyFromObject(user), user)
133 return err == nil
134 }, timeout, interval, "CouchDBUser does not exist: %s", user.Name)
135
136 assert.Equal(t, user.Spec.Type, dsapi.UserCredentials)
137 assert.Equal(t, user.Spec.User.Name, "")
138 assert.Equal(t, user.Spec.User.Secret.Namespace, namespace)
139 assert.Equal(t, user.Spec.User.Secret.Name, secretName)
140 assert.Equal(t, ref.Name, user.OwnerReferences[0].Name)
141 }
142
143 func TestNodeSecret(t *testing.T) {
144 ctx := context.Background()
145 uid := uuid.New().String()
146 cl := mgr.GetClient()
147
148 nodeName := fmt.Sprintf("node-%s", uid)
149 node := &corev1.Node{
150 TypeMeta: metav1.TypeMeta{
151 APIVersion: "v1",
152 Kind: "Node",
153 },
154 ObjectMeta: metav1.ObjectMeta{
155 Name: nodeName,
156 Labels: map[string]string{
157 nodemeta.HostnameLabel: "localhost",
158 nodemeta.LaneLabel: "1",
159 nodemeta.ClassLabel: "server",
160 nodemeta.RoleLabel: "controlplane",
161 },
162 },
163 }
164 require.NoError(t, cl.Create(ctx, node), "fail to create node")
165 deployment := basicDeployment(namespace, fmt.Sprintf("deploy-%s", uid))
166 require.NoError(t, cl.Create(ctx, deployment), "fail to create deployment")
167
168 pod := basicPod(namespace, deployment.Name, nodeName, ownerReference(deployment))
169 require.NoError(t, cl.Create(ctx, pod), "fail to create pod")
170
171 require.Eventually(t, func() bool {
172 err := cl.Get(ctx, client.ObjectKeyFromObject(pod), pod)
173 return err == nil
174 }, timeout, interval, "pod does not exist")
175
176 if len(pod.Labels) == 0 {
177 pod.Labels = map[string]string{}
178 }
179 secretName := fmt.Sprintf("%s-%s", NodeSecret, uid)
180 pod.Labels[SecretLabel(NodeSecret)] = secretName
181
182 require.NoError(t, cl.Update(ctx, pod), "fail to update pod")
183
184 ref := metav1.OwnerReference{Name: deployment.Name}
185 secret := &corev1.Secret{
186 TypeMeta: metav1.TypeMeta{
187 APIVersion: "v1",
188 Kind: "Secret",
189 },
190 ObjectMeta: metav1.ObjectMeta{
191 Name: secretName,
192 Namespace: namespace,
193 },
194 }
195
196 require.Eventually(t, func() bool {
197 err := cl.Get(ctx, client.ObjectKeyFromObject(secret), secret)
198 return err == nil
199 }, timeout, interval, "Secret does not exist: %s", secret.Name)
200
201 assert.Equal(t, string(secret.Data[string(Hostname)]), "localhost")
202 assert.Equal(t, string(secret.Data[string(Lane)]), "1")
203 assert.Equal(t, string(secret.Data[string(Role)]), string(v1ien.ControlPlane))
204 assert.Equal(t, string(secret.Data[string(Class)]), string(v1ien.Server))
205 assert.Equal(t, ref.Name, secret.OwnerReferences[0].Name)
206 }
207 func basicPod(namespace, name, nodeName string, reference []metav1.OwnerReference) *corev1.Pod {
208 pod := &corev1.Pod{
209 TypeMeta: metav1.TypeMeta{
210 APIVersion: "v1",
211 Kind: "Pod",
212 },
213 ObjectMeta: metav1.ObjectMeta{
214 Namespace: namespace,
215 Name: name,
216 Labels: map[string]string{},
217 OwnerReferences: reference,
218 },
219 Spec: corev1.PodSpec{
220 Containers: []corev1.Container{
221 {
222 Name: "podinfo",
223 Image: "podinfo:10.4",
224 },
225 },
226 NodeName: nodeName,
227 },
228 }
229
230 return pod
231 }
232
233 func basicDeployment(namespace, name string) *appsv1.Deployment {
234 label := "hola"
235 replica := int32(1)
236 return &appsv1.Deployment{
237 TypeMeta: metav1.TypeMeta{
238 Kind: "Deployment",
239 APIVersion: "apps/v1",
240 },
241 ObjectMeta: metav1.ObjectMeta{
242 Namespace: namespace,
243 Name: name,
244 },
245 Spec: appsv1.DeploymentSpec{
246 Replicas: &replica,
247 Selector: &metav1.LabelSelector{
248 MatchLabels: map[string]string{
249 "app": label,
250 },
251 },
252 Template: corev1.PodTemplateSpec{
253 ObjectMeta: metav1.ObjectMeta{
254 Labels: map[string]string{
255 "app": label,
256 },
257 },
258 Spec: corev1.PodSpec{
259 Containers: []corev1.Container{
260 {
261 Name: "nginx",
262 Image: "nginx",
263 },
264 },
265 },
266 },
267 },
268 }
269 }
270
271 func ownerReference(obj *appsv1.Deployment) []metav1.OwnerReference {
272 return []metav1.OwnerReference{
273 *metav1.NewControllerRef(obj,
274 appsv1.SchemeGroupVersion.WithKind(reflect.TypeOf(appsv1.Deployment{}).Name())),
275 }
276 }
277
View as plain text