Add suport for query api on root level
[multicloud/k8s.git] / src / k8splugin / api / instancehandler_test.go
1 /*
2 Copyright 2018 Intel Corporation.
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6     http://www.apache.org/licenses/LICENSE-2.0
7 Unless required by applicable law or agreed to in writing, software
8 distributed under the License is distributed on an "AS IS" BASIS,
9 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 See the License for the specific language governing permissions and
11 limitations under the License.
12 */
13
14 package api
15
16 import (
17         "bytes"
18         "encoding/json"
19         "io"
20         "io/ioutil"
21         "net/http"
22         "net/http/httptest"
23         neturl "net/url"
24         "reflect"
25         "sort"
26         "testing"
27
28         "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29
30         "github.com/onap/multicloud-k8s/src/k8splugin/internal/app"
31         "github.com/onap/multicloud-k8s/src/k8splugin/internal/helm"
32
33         "github.com/gorilla/mux"
34         pkgerrors "github.com/pkg/errors"
35         "k8s.io/apimachinery/pkg/runtime/schema"
36 )
37
38 //Creating an embedded interface via anonymous variable
39 //This allows us to make mockDB satisfy the DatabaseConnection
40 //interface even if we are not implementing all the methods in it
41 type mockInstanceClient struct {
42         app.InstanceManager
43         // Items and err will be used to customize each test
44         // via a localized instantiation of mockInstanceClient
45         items      []app.InstanceResponse
46         miniitems  []app.InstanceMiniResponse
47         statusItem app.InstanceStatus
48         err        error
49 }
50
51 func (m *mockInstanceClient) Create(inp app.InstanceRequest) (app.InstanceResponse, error) {
52         if m.err != nil {
53                 return app.InstanceResponse{}, m.err
54         }
55
56         return m.items[0], nil
57 }
58
59 func (m *mockInstanceClient) Get(id string) (app.InstanceResponse, error) {
60         if m.err != nil {
61                 return app.InstanceResponse{}, m.err
62         }
63
64         return m.items[0], nil
65 }
66
67 func (m *mockInstanceClient) Query(id, apiVersion, kind, name, labels string) (app.InstanceStatus, error) {
68         if m.err != nil {
69                 return app.InstanceStatus{}, m.err
70         }
71
72         return m.statusItem, nil
73 }
74
75 func (m *mockInstanceClient) Status(id string) (app.InstanceStatus, error) {
76         if m.err != nil {
77                 return app.InstanceStatus{}, m.err
78         }
79
80         return m.statusItem, nil
81 }
82
83 func (m *mockInstanceClient) List(rbname, rbversion, profilename string) ([]app.InstanceMiniResponse, error) {
84         if m.err != nil {
85                 return []app.InstanceMiniResponse{}, m.err
86         }
87
88         return m.miniitems, nil
89 }
90
91 func (m *mockInstanceClient) Find(rbName string, ver string, profile string, labelKeys map[string]string) ([]app.InstanceMiniResponse, error) {
92         if m.err != nil {
93                 return nil, m.err
94         }
95
96         return m.miniitems, nil
97 }
98
99 func (m *mockInstanceClient) Delete(id string) error {
100         return m.err
101 }
102
103 func executeRequest(request *http.Request, router *mux.Router) *http.Response {
104         recorder := httptest.NewRecorder()
105         router.ServeHTTP(recorder, request)
106         resp := recorder.Result()
107         return resp
108 }
109
110 func TestInstanceCreateHandler(t *testing.T) {
111         testCases := []struct {
112                 label        string
113                 input        io.Reader
114                 expected     app.InstanceResponse
115                 expectedCode int
116                 instClient   *mockInstanceClient
117         }{
118                 {
119                         label:        "Missing body failure",
120                         expectedCode: http.StatusBadRequest,
121                 },
122                 {
123                         label:        "Invalid JSON request format",
124                         input:        bytes.NewBuffer([]byte("invalid")),
125                         expectedCode: http.StatusUnprocessableEntity,
126                 },
127                 {
128                         label: "Missing parameter failure",
129                         input: bytes.NewBuffer([]byte(`{
130                                 "rb-name": "test-rbdef",
131                                 "profile-name": "profile1",
132                                 "cloud-region": "kud"
133                         }`)),
134                         expectedCode: http.StatusUnprocessableEntity,
135                 },
136                 {
137                         label: "Succesfully create an Instance",
138                         input: bytes.NewBuffer([]byte(`{
139                                 "cloud-region": "region1",
140                                 "rb-name": "test-rbdef",
141                                 "rb-version": "v1",
142                                 "profile-name": "profile1"
143                         }`)),
144                         expected: app.InstanceResponse{
145                                 ID: "HaKpys8e",
146                                 Request: app.InstanceRequest{
147                                         RBName:      "test-rbdef",
148                                         RBVersion:   "v1",
149                                         ProfileName: "profile1",
150                                         CloudRegion: "region1",
151                                 },
152                                 Namespace: "testnamespace",
153                                 Resources: []helm.KubernetesResource{
154                                         {
155                                                 GVK: schema.GroupVersionKind{
156                                                         Group:   "apps",
157                                                         Version: "v1",
158                                                         Kind:    "Deployment"},
159                                                 Name: "test-deployment",
160                                         },
161                                         {
162                                                 GVK: schema.GroupVersionKind{
163                                                         Group:   "",
164                                                         Version: "v1",
165                                                         Kind:    "Service"},
166                                                 Name: "test-service",
167                                         },
168                                 },
169                         },
170                         expectedCode: http.StatusCreated,
171                         instClient: &mockInstanceClient{
172                                 items: []app.InstanceResponse{
173                                         {
174                                                 ID: "HaKpys8e",
175                                                 Request: app.InstanceRequest{
176                                                         RBName:      "test-rbdef",
177                                                         RBVersion:   "v1",
178                                                         ProfileName: "profile1",
179                                                         CloudRegion: "region1",
180                                                 },
181                                                 Namespace: "testnamespace",
182                                                 Resources: []helm.KubernetesResource{
183                                                         {
184                                                                 GVK: schema.GroupVersionKind{
185                                                                         Group:   "apps",
186                                                                         Version: "v1",
187                                                                         Kind:    "Deployment"},
188                                                                 Name: "test-deployment",
189                                                         },
190                                                         {
191                                                                 GVK: schema.GroupVersionKind{
192                                                                         Group:   "",
193                                                                         Version: "v1",
194                                                                         Kind:    "Service"},
195                                                                 Name: "test-service",
196                                                         },
197                                                 },
198                                         },
199                                 },
200                         },
201                 },
202         }
203
204         for _, testCase := range testCases {
205                 t.Run(testCase.label, func(t *testing.T) {
206
207                         request := httptest.NewRequest("POST", "/v1/instance", testCase.input)
208                         resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
209
210                         if testCase.expectedCode != resp.StatusCode {
211                                 body, _ := ioutil.ReadAll(resp.Body)
212                                 t.Log(string(body))
213                                 t.Fatalf("Request method returned: \n%v\n and it was expected: \n%v", resp.StatusCode, testCase.expectedCode)
214                         }
215
216                         if resp.StatusCode == http.StatusCreated {
217                                 var response app.InstanceResponse
218                                 err := json.NewDecoder(resp.Body).Decode(&response)
219                                 if err != nil {
220                                         t.Fatalf("Parsing the returned response got an error (%s)", err)
221                                 }
222                         }
223                 })
224         }
225 }
226
227 func TestInstanceGetHandler(t *testing.T) {
228         testCases := []struct {
229                 label            string
230                 input            string
231                 expectedCode     int
232                 expectedResponse *app.InstanceResponse
233                 instClient       *mockInstanceClient
234         }{
235                 {
236                         label:        "Fail to retrieve Instance",
237                         input:        "HaKpys8e",
238                         expectedCode: http.StatusInternalServerError,
239                         instClient: &mockInstanceClient{
240                                 err: pkgerrors.New("Internal error"),
241                         },
242                 },
243                 {
244                         label:        "Succesful get an Instance",
245                         input:        "HaKpys8e",
246                         expectedCode: http.StatusOK,
247                         expectedResponse: &app.InstanceResponse{
248                                 ID: "HaKpys8e",
249                                 Request: app.InstanceRequest{
250                                         RBName:      "test-rbdef",
251                                         RBVersion:   "v1",
252                                         ProfileName: "profile1",
253                                         CloudRegion: "region1",
254                                 },
255                                 Namespace: "testnamespace",
256                                 Resources: []helm.KubernetesResource{
257                                         {
258                                                 GVK: schema.GroupVersionKind{
259                                                         Group:   "apps",
260                                                         Version: "v1",
261                                                         Kind:    "Deployment"},
262                                                 Name: "test-deployment",
263                                         },
264                                         {
265                                                 GVK: schema.GroupVersionKind{
266                                                         Group:   "",
267                                                         Version: "v1",
268                                                         Kind:    "Service"},
269                                                 Name: "test-service",
270                                         },
271                                 },
272                         },
273                         instClient: &mockInstanceClient{
274                                 items: []app.InstanceResponse{
275                                         {
276                                                 ID: "HaKpys8e",
277                                                 Request: app.InstanceRequest{
278                                                         RBName:      "test-rbdef",
279                                                         RBVersion:   "v1",
280                                                         ProfileName: "profile1",
281                                                         CloudRegion: "region1",
282                                                 },
283                                                 Namespace: "testnamespace",
284                                                 Resources: []helm.KubernetesResource{
285                                                         {
286                                                                 GVK: schema.GroupVersionKind{
287                                                                         Group:   "apps",
288                                                                         Version: "v1",
289                                                                         Kind:    "Deployment"},
290                                                                 Name: "test-deployment",
291                                                         },
292                                                         {
293                                                                 GVK: schema.GroupVersionKind{
294                                                                         Group:   "",
295                                                                         Version: "v1",
296                                                                         Kind:    "Service"},
297                                                                 Name: "test-service",
298                                                         },
299                                                 },
300                                         },
301                                 },
302                         },
303                 },
304         }
305
306         for _, testCase := range testCases {
307                 t.Run(testCase.label, func(t *testing.T) {
308                         request := httptest.NewRequest("GET", "/v1/instance/"+testCase.input, nil)
309                         resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
310
311                         if testCase.expectedCode != resp.StatusCode {
312                                 t.Fatalf("Request method returned: %v and it was expected: %v",
313                                         resp.StatusCode, testCase.expectedCode)
314                         }
315                         if resp.StatusCode == http.StatusOK {
316                                 var response app.InstanceResponse
317                                 err := json.NewDecoder(resp.Body).Decode(&response)
318                                 if err != nil {
319                                         t.Fatalf("Parsing the returned response got an error (%s)", err)
320                                 }
321                                 if !reflect.DeepEqual(testCase.expectedResponse, &response) {
322                                         t.Fatalf("TestGetHandler returned:\n result=%v\n expected=%v",
323                                                 &response, testCase.expectedResponse)
324                                 }
325                         }
326                 })
327         }
328 }
329
330 func TestInstanceListHandler(t *testing.T) {
331         testCases := []struct {
332                 label            string
333                 input            string
334                 expectedCode     int
335                 queryParams      bool
336                 queryParamsMap   map[string]string
337                 expectedResponse []app.InstanceMiniResponse
338                 instClient       *mockInstanceClient
339         }{
340                 {
341                         label:        "Fail to List Instance",
342                         input:        "HaKpys8e",
343                         expectedCode: http.StatusInternalServerError,
344                         instClient: &mockInstanceClient{
345                                 err: pkgerrors.New("Internal error"),
346                         },
347                 },
348                 {
349                         label:        "Succesful List Instances",
350                         expectedCode: http.StatusOK,
351                         expectedResponse: []app.InstanceMiniResponse{
352                                 {
353                                         ID: "HaKpys8e",
354                                         Request: app.InstanceRequest{
355                                                 RBName:      "test-rbdef",
356                                                 RBVersion:   "v1",
357                                                 ProfileName: "profile1",
358                                                 CloudRegion: "region1",
359                                         },
360                                         Namespace: "testnamespace",
361                                 },
362                                 {
363                                         ID: "HaKpys8f",
364                                         Request: app.InstanceRequest{
365                                                 RBName:      "test-rbdef-two",
366                                                 RBVersion:   "versionsomething",
367                                                 ProfileName: "profile3",
368                                                 CloudRegion: "region1",
369                                         },
370                                         Namespace: "testnamespace-two",
371                                 },
372                         },
373                         instClient: &mockInstanceClient{
374                                 miniitems: []app.InstanceMiniResponse{
375                                         {
376                                                 ID: "HaKpys8e",
377                                                 Request: app.InstanceRequest{
378                                                         RBName:      "test-rbdef",
379                                                         RBVersion:   "v1",
380                                                         ProfileName: "profile1",
381                                                         CloudRegion: "region1",
382                                                 },
383                                                 Namespace: "testnamespace",
384                                         },
385                                         {
386                                                 ID: "HaKpys8f",
387                                                 Request: app.InstanceRequest{
388                                                         RBName:      "test-rbdef-two",
389                                                         RBVersion:   "versionsomething",
390                                                         ProfileName: "profile3",
391                                                         CloudRegion: "region1",
392                                                 },
393                                                 Namespace: "testnamespace-two",
394                                         },
395                                 },
396                         },
397                 },
398                 {
399                         label:       "List Instances Based on Query Parameters",
400                         queryParams: true,
401                         queryParamsMap: map[string]string{
402                                 "rb-name": "test-rbdef1",
403                         },
404                         expectedCode: http.StatusOK,
405                         expectedResponse: []app.InstanceMiniResponse{
406                                 {
407                                         ID: "HaKpys8e",
408                                         Request: app.InstanceRequest{
409                                                 RBName:      "test-rbdef",
410                                                 RBVersion:   "v1",
411                                                 ProfileName: "profile1",
412                                                 CloudRegion: "region1",
413                                         },
414                                         Namespace: "testnamespace",
415                                 },
416                         },
417                         instClient: &mockInstanceClient{
418                                 miniitems: []app.InstanceMiniResponse{
419                                         {
420                                                 ID: "HaKpys8e",
421                                                 Request: app.InstanceRequest{
422                                                         RBName:      "test-rbdef",
423                                                         RBVersion:   "v1",
424                                                         ProfileName: "profile1",
425                                                         CloudRegion: "region1",
426                                                 },
427                                                 Namespace: "testnamespace",
428                                         },
429                                 },
430                         },
431                 },
432         }
433
434         for _, testCase := range testCases {
435                 t.Run(testCase.label, func(t *testing.T) {
436                         request := httptest.NewRequest("GET", "/v1/instance", nil)
437                         if testCase.queryParams {
438                                 q := request.URL.Query()
439                                 for k, v := range testCase.queryParamsMap {
440                                         q.Add(k, v)
441                                 }
442                                 request.URL.RawQuery = q.Encode()
443                         }
444                         resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
445
446                         if testCase.expectedCode != resp.StatusCode {
447                                 t.Fatalf("Request method returned: %v and it was expected: %v",
448                                         resp.StatusCode, testCase.expectedCode)
449                         }
450                         if resp.StatusCode == http.StatusOK {
451                                 var response []app.InstanceMiniResponse
452                                 err := json.NewDecoder(resp.Body).Decode(&response)
453                                 if err != nil {
454                                         t.Fatalf("Parsing the returned response got an error (%s)", err)
455                                 }
456
457                                 // Since the order of returned slice is not guaranteed
458                                 // Sort them first and then do deepequal
459                                 // Check both and return error if both don't match
460                                 sort.Slice(response, func(i, j int) bool {
461                                         return response[i].ID < response[j].ID
462                                 })
463
464                                 sort.Slice(testCase.expectedResponse, func(i, j int) bool {
465                                         return testCase.expectedResponse[i].ID < testCase.expectedResponse[j].ID
466                                 })
467
468                                 if reflect.DeepEqual(testCase.expectedResponse, response) == false {
469                                         t.Fatalf("TestGetHandler returned:\n result=%v\n expected=%v",
470                                                 &response, testCase.expectedResponse)
471                                 }
472                         }
473                 })
474         }
475 }
476
477 func TestDeleteHandler(t *testing.T) {
478         testCases := []struct {
479                 label        string
480                 input        string
481                 expectedCode int
482                 instClient   *mockInstanceClient
483         }{
484                 {
485                         label:        "Fail to destroy VNF",
486                         input:        "HaKpys8e",
487                         expectedCode: http.StatusInternalServerError,
488                         instClient: &mockInstanceClient{
489                                 err: pkgerrors.New("Internal error"),
490                         },
491                 },
492                 {
493                         label:        "Succesful delete a VNF",
494                         input:        "HaKpys8e",
495                         expectedCode: http.StatusAccepted,
496                         instClient:   &mockInstanceClient{},
497                 },
498         }
499
500         for _, testCase := range testCases {
501                 t.Run(testCase.label, func(t *testing.T) {
502                         request := httptest.NewRequest("DELETE", "/v1/instance/"+testCase.input, nil)
503                         resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
504
505                         if testCase.expectedCode != resp.StatusCode {
506                                 t.Fatalf("Request method returned: %v and it was expected: %v", resp.StatusCode, testCase.expectedCode)
507                         }
508                 })
509         }
510 }
511
512 func TestInstanceQueryHandler(t *testing.T) {
513         testCases := []struct {
514                 label            string
515                 input            map[string]string
516                 id               string
517                 expectedCode     int
518                 expectedResponse *app.InstanceStatus
519                 instClient       *mockInstanceClient
520         }{
521                 {
522                         label:        "Missing apiVersion mandatory parameter",
523                         id:           "HaKpys8e",
524                         input:        map[string]string{},
525                         expectedCode: http.StatusBadRequest,
526                         instClient: &mockInstanceClient{
527                                 err: pkgerrors.New("Missing apiVersion mandatory parameter"),
528                         },
529                 },
530                 {
531                         label: "Missing kind mandatory parameter",
532                         id:    "HaKpys8e",
533                         input: map[string]string{
534                                 "ApiVersion": "v1",
535                         },
536                         expectedCode: http.StatusBadRequest,
537                         instClient: &mockInstanceClient{
538                                 err: pkgerrors.New("Missing kind mandatory parameter"),
539                         },
540                 },
541                 {
542                         label: "Query instance by name",
543                         id:    "HaKpys8e",
544                         input: map[string]string{
545                                 "ApiVersion": "v1",
546                                 "Kind":       "Pod",
547                                 "Name":       "Test",
548                         },
549                         expectedCode: http.StatusOK,
550                         expectedResponse: &app.InstanceStatus{
551                                 Request: app.InstanceRequest{
552                                         RBName:      "test-rbdef",
553                                         RBVersion:   "v1",
554                                         ProfileName: "profile1",
555                                         CloudRegion: "region1",
556                                 },
557                                 Ready:         false,
558                                 ResourceCount: int32(1),
559                                 ResourcesStatus: []app.ResourceStatus{
560                                         {
561                                                 Name: "Test",
562                                                 GVK: schema.GroupVersionKind{
563                                                         Group:   "",
564                                                         Version: "v1",
565                                                         Kind:    "Pod",
566                                                 },
567                                                 Status: unstructured.Unstructured{
568                                                         Object: map[string]interface{}{
569                                                                 "kind":       "Pod",
570                                                                 "apiVersion": "v1",
571                                                                 "metadata": map[string]interface{}{
572                                                                         "name": string("Test"),
573                                                                 },
574                                                         },
575                                                 },
576                                         },
577                                 },
578                         },
579                         instClient: &mockInstanceClient{
580                                 statusItem: app.InstanceStatus{
581                                         Request: app.InstanceRequest{
582                                                 RBName:      "test-rbdef",
583                                                 RBVersion:   "v1",
584                                                 ProfileName: "profile1",
585                                                 CloudRegion: "region1",
586                                         },
587                                         Ready:         false,
588                                         ResourceCount: int32(1),
589                                         ResourcesStatus: []app.ResourceStatus{
590                                                 {
591                                                         Name: "Test",
592                                                         GVK: schema.GroupVersionKind{
593                                                                 Group:   "",
594                                                                 Version: "v1",
595                                                                 Kind:    "Pod",
596                                                         },
597                                                         Status: unstructured.Unstructured{
598                                                                 Object: map[string]interface{}{
599                                                                         "kind":       "Pod",
600                                                                         "apiVersion": "v1",
601                                                                         "metadata": map[string]interface{}{
602                                                                                 "name": string("Test"),
603                                                                         },
604                                                                 },
605                                                         },
606                                                 },
607                                         },
608                                 },
609                         },
610                 },
611                 {
612                         label: "Query instance by label",
613                         id:    "HaKpys8e",
614                         input: map[string]string{
615                                 "ApiVersion": "v1",
616                                 "Kind":       "Pod",
617                                 "Labels":     "app=test",
618                         },
619                         expectedCode: http.StatusOK,
620                         expectedResponse: &app.InstanceStatus{
621                                 Request: app.InstanceRequest{
622                                         RBName:      "test-rbdef",
623                                         RBVersion:   "v1",
624                                         ProfileName: "profile1",
625                                         CloudRegion: "region1",
626                                 },
627                                 Ready:         false,
628                                 ResourceCount: int32(1),
629                                 ResourcesStatus: []app.ResourceStatus{
630                                         {
631                                                 Name: "Test-1",
632                                                 GVK: schema.GroupVersionKind{
633                                                         Group:   "",
634                                                         Version: "v1",
635                                                         Kind:    "Pod",
636                                                 },
637                                                 Status: unstructured.Unstructured{
638                                                         Object: map[string]interface{}{
639                                                                 "kind":       "Pod",
640                                                                 "apiVersion": "v1",
641                                                                 "metadata": map[string]interface{}{
642                                                                         "name": string("Test-1"),
643                                                                         "labels": map[string]interface{}{
644                                                                                 "app": string("test"),
645                                                                         },
646                                                                 },
647                                                         },
648                                                 },
649                                         },
650                                         {
651                                                 Name: "Test-2",
652                                                 GVK: schema.GroupVersionKind{
653                                                         Group:   "",
654                                                         Version: "v1",
655                                                         Kind:    "Pod",
656                                                 },
657                                                 Status: unstructured.Unstructured{
658                                                         Object: map[string]interface{}{
659                                                                 "kind":       "Pod",
660                                                                 "apiVersion": "v1",
661                                                                 "metadata": map[string]interface{}{
662                                                                         "name": string("Test-2"),
663                                                                         "labels": map[string]interface{}{
664                                                                                 "app": string("test"),
665                                                                         },
666                                                                 },
667                                                         },
668                                                 },
669                                         },
670                                 },
671                         },
672                         instClient: &mockInstanceClient{
673                                 statusItem: app.InstanceStatus{
674                                         Request: app.InstanceRequest{
675                                                 RBName:      "test-rbdef",
676                                                 RBVersion:   "v1",
677                                                 ProfileName: "profile1",
678                                                 CloudRegion: "region1",
679                                         },
680                                         Ready:         false,
681                                         ResourceCount: int32(1),
682                                         ResourcesStatus: []app.ResourceStatus{
683                                                 {
684                                                         Name: "Test-1",
685                                                         GVK: schema.GroupVersionKind{
686                                                                 Group:   "",
687                                                                 Version: "v1",
688                                                                 Kind:    "Pod",
689                                                         },
690                                                         Status: unstructured.Unstructured{
691                                                                 Object: map[string]interface{}{
692                                                                         "kind":       "Pod",
693                                                                         "apiVersion": "v1",
694                                                                         "metadata": map[string]interface{}{
695                                                                                 "name": string("Test-1"),
696                                                                                 "labels": map[string]interface{}{
697                                                                                         "app": string("test"),
698                                                                                 },
699                                                                         },
700                                                                 },
701                                                         },
702                                                 },
703                                                 {
704                                                         Name: "Test-2",
705                                                         GVK: schema.GroupVersionKind{
706                                                                 Group:   "",
707                                                                 Version: "v1",
708                                                                 Kind:    "Pod",
709                                                         },
710                                                         Status: unstructured.Unstructured{
711                                                                 Object: map[string]interface{}{
712                                                                         "kind":       "Pod",
713                                                                         "apiVersion": "v1",
714                                                                         "metadata": map[string]interface{}{
715                                                                                 "name": string("Test-2"),
716                                                                                 "labels": map[string]interface{}{
717                                                                                         "app": string("test"),
718                                                                                 },
719                                                                         },
720                                                                 },
721                                                         },
722                                                 },
723                                         },
724                                 },
725                         },
726                 },
727         }
728
729         for _, testCase := range testCases {
730                 t.Run(testCase.label, func(t *testing.T) {
731                         params := neturl.Values{}
732                         for k, v := range testCase.input {
733                                 params.Add(k, v)
734                         }
735                         url := "/v1/instance/" + testCase.id + "/query?" + params.Encode()
736                         request := httptest.NewRequest("GET", url, nil)
737                         resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
738
739                         if testCase.expectedCode != resp.StatusCode {
740                                 body, _ := ioutil.ReadAll(resp.Body)
741                                 t.Fatalf("Request method returned: %v and it was expected: %v\nReturned body: %s",
742                                         resp.StatusCode, testCase.expectedCode, body)
743                         }
744                         if resp.StatusCode == http.StatusOK {
745                                 var response app.InstanceStatus
746                                 err := json.NewDecoder(resp.Body).Decode(&response)
747                                 if err != nil {
748                                         t.Fatalf("Parsing the returned response got an error (%s)", err)
749                                 }
750                                 if !reflect.DeepEqual(testCase.expectedResponse, &response) {
751                                         t.Fatalf("TestQueryHandler returned:\n result=%v\n expected=%v",
752                                                 &response, testCase.expectedResponse)
753                                 }
754                         }
755                 })
756         }
757 }