1 package nodeagent
2
3 import (
4 "context"
5 "os"
6 "testing"
7 "time"
8
9 "github.com/stretchr/testify/require"
10 "gotest.tools/v3/assert/cmp"
11 corev1 "k8s.io/api/core/v1"
12 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13 ctrl "sigs.k8s.io/controller-runtime"
14 "sigs.k8s.io/controller-runtime/pkg/client"
15
16 "edge-infra.dev/pkg/k8s/runtime/conditions"
17 "edge-infra.dev/pkg/k8s/runtime/events"
18 "edge-infra.dev/pkg/k8s/testing/kmp"
19 "edge-infra.dev/pkg/lib/fog"
20 v1ien "edge-infra.dev/pkg/sds/ien/k8s/apis/v1"
21 "edge-infra.dev/pkg/sds/ien/k8s/controllers/nodeagent/config"
22 "edge-infra.dev/test/f2"
23 "edge-infra.dev/test/f2/x/ktest"
24 )
25
26 var f f2.Framework
27
28 var (
29 ienodeName = "edge-worker"
30 )
31
32 var sdsNamespaceTest = corev1.Namespace{
33 ObjectMeta: metav1.ObjectMeta{
34 Name: "sds",
35 },
36 }
37
38 var (
39 flagsTest = config.Flags{
40 WatchAllNamespaces: &watchAllNamespaces,
41 PluginsConfigMap: &pluginsConfigMapNamespacedName,
42 ThinclientConfigMap: &thinclientConfigMapNotSet,
43 Pprof: nil,
44 NodeRootPath: &nodeRootPath,
45 }
46
47 watchAllNamespaces = false
48 pluginsConfigMapNamespacedName = "nodeagent-plugins"
49 thinclientConfigMapNotSet = ""
50 nodeRootPath = "/"
51
52 nodeAgentConfigMapTest = corev1.ConfigMap{
53 ObjectMeta: metav1.ObjectMeta{
54 Name: "nodeagent-plugins",
55 Namespace: "sds",
56 },
57 Data: map[string]string{
58 "suspendAll": "false",
59 "exampleIENode": "true",
60 "exampleSecret": "false",
61 "exampleConfigMap": "true",
62 "exampleNodeFirewall": "true",
63 },
64 }
65 nodeInfo = corev1.Node{
66 ObjectMeta: metav1.ObjectMeta{
67 Name: "edge-worker",
68 },
69 }
70 )
71
72 var secretTest = corev1.Secret{ObjectMeta: metav1.ObjectMeta{Namespace: "sds", Name: "example-secret"}}
73
74 var (
75 clusterFirewall = v1ien.NewClusterFirewall("testClusterFirewall", []v1ien.ClusterRule{})
76 ownerRef = *metav1.NewControllerRef(clusterFirewall, v1ien.ClusterFirewallGVK)
77 nodefirewallTest = v1ien.NewNodeFirewall("edge-worker-example-nodefirewall", []v1ien.NodeRule{}, ownerRef)
78 )
79
80 func TestMain(m *testing.M) {
81 ctrl.SetLogger(fog.New())
82 os.Setenv("HOSTNAME", ienodeName)
83
84 f = f2.New(
85 context.Background(),
86 f2.WithExtensions(
87 ktest.New(
88 ktest.WithCtrlManager(createControllerManager),
89 ),
90 )).
91 Setup(func(ctx f2.Context) (f2.Context, error) {
92 k, err := ktest.FromContext(ctx)
93 if err != nil {
94 return ctx, err
95 }
96
97
98 if !*k.Env.UseExistingCluster {
99 k.Timeout = 5 * time.Second
100 k.Tick = 10 * time.Millisecond
101 }
102
103 return ctx, nil
104 })
105
106 os.Exit(f.Run(m))
107 }
108
109 func TestControllerEntersReadyState(t *testing.T) {
110 status := f2.NewFeature("Reconciles its Status").
111 Setup("Register Controllers", func(ctx f2.Context, t *testing.T) f2.Context {
112 k := ktest.FromContextT(ctx, t)
113
114 eventRecorder := events.NewRecorder(k.Manager, ctrl.Log, "nodeagent")
115 _, err := registerControllers(flagsTest, k.Manager, eventRecorder)
116 require.NoError(t, err)
117
118 ns := sdsNamespaceTest.DeepCopy()
119 require.NoError(t, k.Client.Create(ctx, ns))
120
121 node := nodeInfo.DeepCopy()
122 require.NoError(t, k.Client.Create(ctx, node))
123
124 cm := nodeAgentConfigMapTest.DeepCopy()
125 require.NoError(t, k.Client.Create(ctx, cm))
126
127 secret := secretTest.DeepCopy()
128 require.NoError(t, k.Client.Create(ctx, secret))
129
130 nodefirewall := nodefirewallTest.DeepCopy()
131 require.NoError(t, k.Client.Create(ctx, nodefirewall))
132
133 return ctx
134 }).
135 Test("Check IEN becomes ready after reconciling", func(ctx f2.Context, t *testing.T) f2.Context {
136 k := ktest.FromContextT(ctx, t)
137
138 ienode := IENodeMock()
139 require.NoError(t, k.Client.Create(ctx, ienode))
140
141 k.WaitOn(t, k.Check(ienode, kmp.IsReady()))
142
143 return ctx
144 }).
145 Test("Check ConfigMap plugin is ready", func(ctx f2.Context, t *testing.T) f2.Context {
146 k := ktest.FromContextT(ctx, t)
147 ienode := IENodeMock()
148
149 k.WaitOn(t, k.Check(ienode, func(o client.Object) cmp.Result {
150 ienode, _ := o.(*v1ien.IENode)
151 if conditions.IsTrue(ienode, "exampleConfigMap") {
152 return cmp.ResultSuccess
153 }
154 return cmp.ResultFailure("exampleConfigMap conditions not true")
155 }))
156 return ctx
157 }).
158 Test("Check Secrets plugin is ready", func(ctx f2.Context, t *testing.T) f2.Context {
159 k := ktest.FromContextT(ctx, t)
160 ienode := IENodeMock()
161
162 k.WaitOn(t, k.Check(ienode, func(o client.Object) cmp.Result {
163 ienode, _ := o.(*v1ien.IENode)
164 if conditions.IsTrue(ienode, "exampleSecret") {
165 return cmp.ResultSuccess
166 }
167 return cmp.ResultFailure("exampleSecret conditions not true")
168 }))
169
170 return ctx
171 }).
172 Test("Check NodeFirewall plugin is ready", func(ctx f2.Context, t *testing.T) f2.Context {
173 k := ktest.FromContextT(ctx, t)
174 ienode := IENodeMock()
175
176 k.WaitOn(t, k.Check(ienode, func(o client.Object) cmp.Result {
177 ienode, _ := o.(*v1ien.IENode)
178 if conditions.IsTrue(ienode, "exampleNodeFirewall") {
179 return cmp.ResultSuccess
180 }
181 return cmp.ResultFailure("exampleNodeFirewall conditions not true")
182 }))
183
184 return ctx
185 }).
186 Feature()
187
188 f.Test(t, status)
189 }
190
191 func IENodeMock() *v1ien.IENode {
192 return &v1ien.IENode{
193 ObjectMeta: metav1.ObjectMeta{
194 Name: ienodeName,
195 },
196 Spec: v1ien.IENodeSpec{
197 Role: "worker",
198 Lane: "1",
199 Network: []v1ien.Network{
200 {
201 MacAddress: "90:74:c2:0f:d8:77",
202 Addresses: make([]string, 0),
203 Gateway4: "192.168.1.1",
204 DHCP4: false,
205 DHCP6: false,
206 },
207 },
208 PrimaryInterface: &v1ien.PrimaryInterface{
209 InterfaceID: "9647e74f-aba3-447f-b327-31ecce7f8d4c",
210 MacAddresses: []string{"90:74:c2:0f:d8:77"},
211 },
212 },
213 }
214 }
215
View as plain text