Correct Query API endpoint registration 65/118965/1
authorKonrad Bańka <k.banka@samsung.com>
Tue, 9 Mar 2021 14:57:37 +0000 (15:57 +0100)
committerKonrad Bańka <k.banka@samsung.com>
Tue, 9 Mar 2021 14:57:37 +0000 (15:57 +0100)
Apart from corrections, corrected handling of name-only query requests
as well as provided bunch of UTs.

Issue-ID: MULTICLOUD-1307
Signed-off-by: Konrad Bańka <k.banka@samsung.com>
Change-Id: Ida3d3e434525f323bd8c40ddc7ffd58df9c5e831

src/k8splugin/api/api.go
src/k8splugin/api/instancehandler_test.go
src/k8splugin/internal/app/instance.go

index 2c53a29..4a196ae 100644 (file)
@@ -47,9 +47,9 @@ func NewRouter(defClient rb.DefinitionManager,
                Queries("rb-name", "{rb-name}",
                        "rb-version", "{rb-version}",
                        "profile-name", "{profile-name}").Methods("GET")
-
        instRouter.HandleFunc("/instance/{instID}", instHandler.getHandler).Methods("GET")
        instRouter.HandleFunc("/instance/{instID}/status", instHandler.statusHandler).Methods("GET")
+       instRouter.HandleFunc("/instance/{instID}/query", instHandler.queryHandler).Methods("GET")
        instRouter.HandleFunc("/instance/{instID}/query", instHandler.queryHandler).
                Queries("ApiVersion", "{ApiVersion}",
                        "Kind", "{Kind}",
index 8e6c72f..e05bd2d 100644 (file)
@@ -20,10 +20,13 @@ import (
        "io/ioutil"
        "net/http"
        "net/http/httptest"
+       neturl "net/url"
        "reflect"
        "sort"
        "testing"
 
+       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+
        "github.com/onap/multicloud-k8s/src/k8splugin/internal/app"
        "github.com/onap/multicloud-k8s/src/k8splugin/internal/helm"
 
@@ -61,6 +64,14 @@ func (m *mockInstanceClient) Get(id string) (app.InstanceResponse, error) {
        return m.items[0], nil
 }
 
+func (m *mockInstanceClient) Query(id, apiVersion, kind, name, labels string) (app.InstanceStatus, error) {
+       if m.err != nil {
+               return app.InstanceStatus{}, m.err
+       }
+
+       return m.statusItem, nil
+}
+
 func (m *mockInstanceClient) Status(id string) (app.InstanceStatus, error) {
        if m.err != nil {
                return app.InstanceStatus{}, m.err
@@ -497,3 +508,262 @@ func TestDeleteHandler(t *testing.T) {
                })
        }
 }
+
+func TestInstanceQueryHandler(t *testing.T) {
+       testCases := []struct {
+               label            string
+               input            map[string]string
+               id               string
+               expectedCode     int
+               expectedResponse *app.InstanceStatus
+               instClient       *mockInstanceClient
+       }{
+               {
+                       label:        "Missing apiVersion mandatory parameter",
+                       id:           "HaKpys8e",
+                       input:        map[string]string{},
+                       expectedCode: http.StatusBadRequest,
+                       instClient: &mockInstanceClient{
+                               err: pkgerrors.New("Missing apiVersion mandatory parameter"),
+                       },
+               },
+               {
+                       label: "Missing kind mandatory parameter",
+                       id:    "HaKpys8e",
+                       input: map[string]string{
+                               "ApiVersion": "v1",
+                       },
+                       expectedCode: http.StatusBadRequest,
+                       instClient: &mockInstanceClient{
+                               err: pkgerrors.New("Missing kind mandatory parameter"),
+                       },
+               },
+               {
+                       label: "Missing name or label mandatory parameters",
+                       id:    "HaKpys8e",
+                       input: map[string]string{
+                               "ApiVersion": "v1",
+                               "Kind":       "Pod",
+                       },
+                       expectedCode: http.StatusBadRequest,
+                       instClient: &mockInstanceClient{
+                               err: pkgerrors.New("Name or Labels parameter must be provided"),
+                       },
+               },
+               {
+                       label: "Query instance by name",
+                       id:    "HaKpys8e",
+                       input: map[string]string{
+                               "ApiVersion": "v1",
+                               "Kind":       "Pod",
+                               "Name":       "Test",
+                       },
+                       expectedCode: http.StatusOK,
+                       expectedResponse: &app.InstanceStatus{
+                               Request: app.InstanceRequest{
+                                       RBName:      "test-rbdef",
+                                       RBVersion:   "v1",
+                                       ProfileName: "profile1",
+                                       CloudRegion: "region1",
+                               },
+                               Ready:         false,
+                               ResourceCount: int32(1),
+                               ResourcesStatus: []app.ResourceStatus{
+                                       {
+                                               Name: "Test",
+                                               GVK: schema.GroupVersionKind{
+                                                       Group:   "",
+                                                       Version: "v1",
+                                                       Kind:    "Pod",
+                                               },
+                                               Status: unstructured.Unstructured{
+                                                       Object: map[string]interface{}{
+                                                               "kind":       "Pod",
+                                                               "apiVersion": "v1",
+                                                               "metadata": map[string]interface{}{
+                                                                       "name": string("Test"),
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       instClient: &mockInstanceClient{
+                               statusItem: app.InstanceStatus{
+                                       Request: app.InstanceRequest{
+                                               RBName:      "test-rbdef",
+                                               RBVersion:   "v1",
+                                               ProfileName: "profile1",
+                                               CloudRegion: "region1",
+                                       },
+                                       Ready:         false,
+                                       ResourceCount: int32(1),
+                                       ResourcesStatus: []app.ResourceStatus{
+                                               {
+                                                       Name: "Test",
+                                                       GVK: schema.GroupVersionKind{
+                                                               Group:   "",
+                                                               Version: "v1",
+                                                               Kind:    "Pod",
+                                                       },
+                                                       Status: unstructured.Unstructured{
+                                                               Object: map[string]interface{}{
+                                                                       "kind":       "Pod",
+                                                                       "apiVersion": "v1",
+                                                                       "metadata": map[string]interface{}{
+                                                                               "name": string("Test"),
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+               },
+               {
+                       label: "Query instance by label",
+                       id:    "HaKpys8e",
+                       input: map[string]string{
+                               "ApiVersion": "v1",
+                               "Kind":       "Pod",
+                               "Labels":     "app=test",
+                       },
+                       expectedCode: http.StatusOK,
+                       expectedResponse: &app.InstanceStatus{
+                               Request: app.InstanceRequest{
+                                       RBName:      "test-rbdef",
+                                       RBVersion:   "v1",
+                                       ProfileName: "profile1",
+                                       CloudRegion: "region1",
+                               },
+                               Ready:         false,
+                               ResourceCount: int32(1),
+                               ResourcesStatus: []app.ResourceStatus{
+                                       {
+                                               Name: "Test-1",
+                                               GVK: schema.GroupVersionKind{
+                                                       Group:   "",
+                                                       Version: "v1",
+                                                       Kind:    "Pod",
+                                               },
+                                               Status: unstructured.Unstructured{
+                                                       Object: map[string]interface{}{
+                                                               "kind":       "Pod",
+                                                               "apiVersion": "v1",
+                                                               "metadata": map[string]interface{}{
+                                                                       "name": string("Test-1"),
+                                                                       "labels": map[string]interface{}{
+                                                                               "app": string("test"),
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                                       {
+                                               Name: "Test-2",
+                                               GVK: schema.GroupVersionKind{
+                                                       Group:   "",
+                                                       Version: "v1",
+                                                       Kind:    "Pod",
+                                               },
+                                               Status: unstructured.Unstructured{
+                                                       Object: map[string]interface{}{
+                                                               "kind":       "Pod",
+                                                               "apiVersion": "v1",
+                                                               "metadata": map[string]interface{}{
+                                                                       "name": string("Test-2"),
+                                                                       "labels": map[string]interface{}{
+                                                                               "app": string("test"),
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       instClient: &mockInstanceClient{
+                               statusItem: app.InstanceStatus{
+                                       Request: app.InstanceRequest{
+                                               RBName:      "test-rbdef",
+                                               RBVersion:   "v1",
+                                               ProfileName: "profile1",
+                                               CloudRegion: "region1",
+                                       },
+                                       Ready:         false,
+                                       ResourceCount: int32(1),
+                                       ResourcesStatus: []app.ResourceStatus{
+                                               {
+                                                       Name: "Test-1",
+                                                       GVK: schema.GroupVersionKind{
+                                                               Group:   "",
+                                                               Version: "v1",
+                                                               Kind:    "Pod",
+                                                       },
+                                                       Status: unstructured.Unstructured{
+                                                               Object: map[string]interface{}{
+                                                                       "kind":       "Pod",
+                                                                       "apiVersion": "v1",
+                                                                       "metadata": map[string]interface{}{
+                                                                               "name": string("Test-1"),
+                                                                               "labels": map[string]interface{}{
+                                                                                       "app": string("test"),
+                                                                               },
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                               {
+                                                       Name: "Test-2",
+                                                       GVK: schema.GroupVersionKind{
+                                                               Group:   "",
+                                                               Version: "v1",
+                                                               Kind:    "Pod",
+                                                       },
+                                                       Status: unstructured.Unstructured{
+                                                               Object: map[string]interface{}{
+                                                                       "kind":       "Pod",
+                                                                       "apiVersion": "v1",
+                                                                       "metadata": map[string]interface{}{
+                                                                               "name": string("Test-2"),
+                                                                               "labels": map[string]interface{}{
+                                                                                       "app": string("test"),
+                                                                               },
+                                                                       },
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+               },
+       }
+
+       for _, testCase := range testCases {
+               t.Run(testCase.label, func(t *testing.T) {
+                       params := neturl.Values{}
+                       for k, v := range testCase.input {
+                               params.Add(k, v)
+                       }
+                       url := "/v1/instance/" + testCase.id + "/query?" + params.Encode()
+                       request := httptest.NewRequest("GET", url, nil)
+                       resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil))
+
+                       if testCase.expectedCode != resp.StatusCode {
+                               body, _ := ioutil.ReadAll(resp.Body)
+                               t.Fatalf("Request method returned: %v and it was expected: %v\nReturned body: %s",
+                                       resp.StatusCode, testCase.expectedCode, body)
+                       }
+                       if resp.StatusCode == http.StatusOK {
+                               var response app.InstanceStatus
+                               err := json.NewDecoder(resp.Body).Decode(&response)
+                               if err != nil {
+                                       t.Fatalf("Parsing the returned response got an error (%s)", err)
+                               }
+                               if !reflect.DeepEqual(testCase.expectedResponse, &response) {
+                                       t.Fatalf("TestQueryHandler returned:\n result=%v\n expected=%v",
+                                               &response, testCase.expectedResponse)
+                               }
+                       }
+               })
+       }
+}
index 337ce68..b90a642 100644 (file)
@@ -22,6 +22,7 @@ import (
        "log"
        "strings"
 
+       "k8s.io/apimachinery/pkg/runtime/schema"
        protorelease "k8s.io/helm/pkg/proto/hapi/release"
 
        "github.com/onap/multicloud-k8s/src/k8splugin/internal/db"
@@ -259,7 +260,10 @@ func (v *InstanceClient) Query(id, apiVersion, kind, name, labels string) (Insta
                        resourcesStatus = resList
                }
        } else if name != "" {
-               resIdentifier := helm.KubernetesResource{}
+               resIdentifier := helm.KubernetesResource{
+                       Name: name,
+                       GVK:  schema.FromAPIVersionAndKind(apiVersion, kind),
+               }
                res, err := k8sClient.getResourceStatus(resIdentifier, resResp.Namespace)
                if err != nil {
                        return InstanceStatus{}, pkgerrors.Wrap(err, "Querying Resource")