Modified BPA controller and fixed bugs
[icn.git] / cmd / bpa-operator / pkg / controller / provisioning / provisioning_controller_test.go
1 package provisioning
2
3 import (
4
5        "context"
6        "testing"
7        "io/ioutil"
8        "os"
9
10        bpav1alpha1 "github.com/bpa-operator/pkg/apis/bpa/v1alpha1"
11        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12        batchv1 "k8s.io/api/batch/v1"
13        logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
14        "k8s.io/apimachinery/pkg/runtime"
15        "k8s.io/apimachinery/pkg/types"
16        "k8s.io/client-go/kubernetes/scheme"
17        "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
18        "sigs.k8s.io/controller-runtime/pkg/client/fake"
19        "sigs.k8s.io/controller-runtime/pkg/reconcile"
20        fakedynamic "k8s.io/client-go/dynamic/fake"
21 )
22
23 func TestProvisioningController(t *testing.T) {
24
25      logf.SetLogger(logf.ZapLogger(true))
26      bpaName1 := "bpa-test-cr"
27      bpaName2 := "bpa-test-2"
28      bpaName3 := "bpa-test-3"
29      namespace := "default"
30      clusterName := "test-cluster"
31      clusterName2 :=  "test-cluster-2"
32      clusterName3 := "test-cluster-3"
33      macAddress1 := "08:00:27:00:ab:2c"
34      macAddress2 := "08:00:27:00:ab:3d"
35      macAddress3 := "08:00:27:00:ab:1c"
36
37      // Create Fake DHCP file
38      err := createFakeDHCP()
39      if err != nil {
40         t.Fatalf("Cannot create Fake DHCP file for testing\n")
41      }
42
43      // Create Fake baremetalhost
44      bmhList := newBMList()
45
46     // Create Fake Provisioning CR
47     provisioning := newBPA(bpaName1, namespace, clusterName, macAddress1)
48     provisioning2 := newBPA(bpaName2, namespace, clusterName2, macAddress2)
49     provisioning3 := newBPA(bpaName3, namespace, clusterName3, macAddress3)
50
51     // Objects to track in the fake Client
52     objs := []runtime.Object{provisioning, provisioning2, provisioning3}
53
54     // Register operator types with the runtime scheme
55     sc := scheme.Scheme
56
57     sc.AddKnownTypes(bpav1alpha1.SchemeGroupVersion, provisioning, provisioning2, provisioning3)
58
59     // Create Fake Clients
60     fakeClient := fake.NewFakeClient(objs...)
61     fakeDyn := fakedynamic.NewSimpleDynamicClient(sc, bmhList,)
62
63     r := &ReconcileProvisioning{client: fakeClient, scheme: sc, bmhClient: fakeDyn}
64
65     // Mock request to simulate Reconcile() being called on an event for a watched resource 
66     req := simulateRequest(provisioning)
67     _, err = r.Reconcile(req)
68     if err != nil {
69        t.Fatalf("reconcile: (%v)", err)
70     }
71
72    // Test 1: Check the job was created with the expected name
73     job := &batchv1.Job{}
74     err = r.client.Get(context.TODO(), types.NamespacedName{Name: "kud-test-cluster", Namespace: namespace}, job)
75     if err != nil {
76         t.Fatalf("Error occured while getting job: (%v)", err)
77     }
78
79    // Test 2: Check that cluster name metadata in job is the expected cluster name
80    jobClusterName := job.Labels["cluster"]
81    if jobClusterName != clusterName {
82       t.Fatalf("Job cluster Name is wrong")
83    }
84
85
86    // Test 3: Check that the right error is produced when host with MAC address does not exist
87    req = simulateRequest(provisioning2)
88     _, err = r.Reconcile(req)
89     expectedErr := "Host with MAC Address " + macAddress2 + " not found\n"
90     if err.Error() != expectedErr {
91        t.Fatalf("Failed, Unexpected error occured %v\n", err)
92     }
93
94    // Test 4: Check that the right error is produced when MAC address is not found in the DHCP lease file
95    req = simulateRequest(provisioning3)
96     _, err = r.Reconcile(req)
97     expectedErr = "IP address not found for host with MAC address " + macAddress3 + " \n"
98     if err.Error() != expectedErr {
99        t.Fatalf("Failed, Unexpected error occured %v\n", err)
100     }
101
102    // Delete Fake DHCP file and cluster directories
103    err = os.Remove("/var/lib/dhcp/dhcpd.leases")
104    if err != nil {
105       t.Logf("\nUnable to delete fake DHCP file\n")
106    }
107    err = os.RemoveAll("/multi-cluster/" + clusterName)
108    if err != nil {
109       t.Logf("\nUnable to delete cluster directory %s\n", clusterName)
110    }
111    err = os.RemoveAll("/multi-cluster/" + clusterName2)
112    if err != nil {
113       t.Logf("\nUnable to delete cluster directory %s\n", clusterName2)
114    }
115    err = os.RemoveAll("/multi-cluster/" + clusterName3)
116    if err != nil {
117       t.Logf("\nUnable to delete cluster directory %s\n", clusterName3)
118    }
119
120
121 }
122
123 func simulateRequest(bpaCR *bpav1alpha1.Provisioning) reconcile.Request {
124         namespacedName := types.NamespacedName{
125                 Name:      bpaCR.ObjectMeta.Name,
126                 Namespace: bpaCR.ObjectMeta.Namespace,
127         }
128         return reconcile.Request{NamespacedName: namespacedName}
129 }
130
131
132
133 func newBPA(name, namespace, clusterName, macAddress string) *bpav1alpha1.Provisioning {
134
135      provisioningCR := &bpav1alpha1.Provisioning{
136         ObjectMeta: metav1.ObjectMeta{
137             Name:      name,
138             Namespace: namespace,
139             Labels: map[string]string{
140                 "cluster": clusterName,
141             },
142         },
143         Spec: bpav1alpha1.ProvisioningSpec{
144                Masters: []map[string]bpav1alpha1.Master{
145                          map[string]bpav1alpha1.Master{
146                            "test-master" : bpav1alpha1.Master{
147                                  MACaddress: macAddress,
148                             },
149
150                },
151               },
152        },
153
154     }
155     return provisioningCR
156 }
157
158
159 func newBMList() *unstructured.UnstructuredList{
160
161         bmMap := map[string]interface{}{
162                            "apiVersion": "metal3.io/v1alpha1",
163                            "kind": "BareMetalHostList",
164                            "metaData": map[string]interface{}{
165                                "continue": "",
166                                    "resourceVersion": "11830058",
167                                    "selfLink": "/apis/metal3.io/v1alpha1/baremetalhosts",
168
169                  },
170                  }
171
172
173
174
175         metaData := map[string]interface{}{
176                          "creationTimestamp": "2019-10-24T04:51:15Z",
177                          "generation":"1",
178                          "name": "fake-test-bmh",
179                          "namespace": "default",
180                          "resourceVersion": "11829263",
181                          "selfLink": "/apis/metal3.io/v1alpha1/namespaces/default/baremetalhosts/bpa-test-bmh",
182                          "uid": "e92cb312-f619-11e9-90bc-00219ba0c77a",
183         }
184
185
186
187         nicMap1 := map[string]interface{}{
188                         "ip": "",
189                          "mac": "08:00:27:00:ab:2c",
190                          "model": "0x8086 0x1572",
191                          "name": "eth3",
192                          "pxe": "false",
193                          "speedGbps": "0",
194                          "vlanId": "0",
195         }
196
197        nicMap2 := map[string]interface{}{
198                         "ip": "",
199                          "mac": "08:00:27:00:ab:1c",
200                          "model": "0x8086 0x1572",
201                          "name": "eth4",
202                          "pxe": "false",
203                          "speedGbps": "0",
204                          "vlanId": "0",
205         }
206
207         specMap  := map[string]interface{}{
208                           "status" : map[string]interface{}{
209                                    "errorMessage": "",
210                                         "hardware": map[string]interface{}{
211                                            "nics": map[string]interface{}{
212                                                 "nic1" : nicMap1,
213                                                 "nic2" : nicMap2,
214                                             },
215                           },
216                           },
217
218
219         }
220
221         itemMap := map[string]interface{}{
222                            "apiVersion": "metal3.io/v1alpha1",
223                            "kind": "BareMetalHost",
224                            "metadata": metaData,
225                            "spec": specMap,
226                  }
227         itemU := unstructured.Unstructured{
228                          Object: itemMap,
229                    }
230
231         itemsList := []unstructured.Unstructured{itemU,}
232
233         bmhList := &unstructured.UnstructuredList{
234                                         Object: bmMap,
235                                         Items: itemsList,
236          }
237
238
239       return bmhList
240 }
241
242
243 // Create DHCP file for testing
244 func createFakeDHCP() error{
245
246
247      dhcpData := []byte(`lease 192.168.50.63 {
248   starts 4 2019/08/08 22:32:49;
249   ends 4 2019/08/08 23:52:49;
250   cltt 4 2019/08/08 22:32:49;
251   binding state active;
252   next binding state free;
253   rewind binding state free;
254   hardware ethernet 08:00:27:00:ab:2c;
255   client-hostname "fake-test-bmh"";
256 }`)
257      err := ioutil.WriteFile("/var/lib/dhcp/dhcpd.leases", dhcpData, 0777)
258
259      if (err != nil) {
260         return err
261      }
262
263     return nil
264 }