From b00a7930a27afed7ba2576378aeecc75fb0759f3 Mon Sep 17 00:00:00 2001 From: Konrad Bańka Date: Tue, 9 Mar 2021 15:57:37 +0100 Subject: Correct Query API endpoint registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Change-Id: Ida3d3e434525f323bd8c40ddc7ffd58df9c5e831 --- src/k8splugin/api/api.go | 2 +- src/k8splugin/api/instancehandler_test.go | 270 ++++++++++++++++++++++++++++++ src/k8splugin/internal/app/instance.go | 6 +- 3 files changed, 276 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/k8splugin/api/api.go b/src/k8splugin/api/api.go index 2c53a297..4a196ae2 100644 --- a/src/k8splugin/api/api.go +++ b/src/k8splugin/api/api.go @@ -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}", diff --git a/src/k8splugin/api/instancehandler_test.go b/src/k8splugin/api/instancehandler_test.go index 8e6c72fc..e05bd2d7 100644 --- a/src/k8splugin/api/instancehandler_test.go +++ b/src/k8splugin/api/instancehandler_test.go @@ -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) + } + } + }) + } +} diff --git a/src/k8splugin/internal/app/instance.go b/src/k8splugin/internal/app/instance.go index 337ce687..b90a6428 100644 --- a/src/k8splugin/internal/app/instance.go +++ b/src/k8splugin/internal/app/instance.go @@ -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") -- cgit 1.2.3-korg