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