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.
26 "github.com/onap/multicloud-k8s/src/k8splugin/internal/app"
27 "github.com/onap/multicloud-k8s/src/k8splugin/internal/helm"
29 "github.com/gorilla/mux"
30 pkgerrors "github.com/pkg/errors"
31 "k8s.io/apimachinery/pkg/runtime/schema"
34 //Creating an embedded interface via anonymous variable
35 //This allows us to make mockDB satisfy the DatabaseConnection
36 //interface even if we are not implementing all the methods in it
37 type mockInstanceClient struct {
39 // Items and err will be used to customize each test
40 // via a localized instantiation of mockInstanceClient
41 items []app.InstanceResponse
45 func (m *mockInstanceClient) Create(inp app.InstanceRequest) (app.InstanceResponse, error) {
47 return app.InstanceResponse{}, m.err
50 return m.items[0], nil
53 func (m *mockInstanceClient) Get(id string) (app.InstanceResponse, error) {
55 return app.InstanceResponse{}, m.err
58 return m.items[0], nil
61 func (m *mockInstanceClient) Find(rbName string, ver string, profile string, labelKeys map[string]string) ([]app.InstanceResponse, error) {
69 func (m *mockInstanceClient) Delete(id string) error {
73 func executeRequest(request *http.Request, router *mux.Router) *http.Response {
74 recorder := httptest.NewRecorder()
75 router.ServeHTTP(recorder, request)
76 resp := recorder.Result()
80 func TestInstanceCreateHandler(t *testing.T) {
81 testCases := []struct {
84 expected app.InstanceResponse
86 instClient *mockInstanceClient
89 label: "Missing body failure",
90 expectedCode: http.StatusBadRequest,
93 label: "Invalid JSON request format",
94 input: bytes.NewBuffer([]byte("invalid")),
95 expectedCode: http.StatusUnprocessableEntity,
98 label: "Missing parameter failure",
99 input: bytes.NewBuffer([]byte(`{
100 "rb-name": "test-rbdef",
101 "profile-name": "profile1",
102 "cloud-region": "kud"
104 expectedCode: http.StatusUnprocessableEntity,
107 label: "Succesfully create an Instance",
108 input: bytes.NewBuffer([]byte(`{
109 "cloud-region": "region1",
110 "rb-name": "test-rbdef",
112 "profile-name": "profile1"
114 expected: app.InstanceResponse{
116 Request: app.InstanceRequest{
117 RBName: "test-rbdef",
119 ProfileName: "profile1",
120 CloudRegion: "region1",
122 Namespace: "testnamespace",
123 Resources: []helm.KubernetesResource{
125 GVK: schema.GroupVersionKind{
129 Name: "test-deployment",
132 GVK: schema.GroupVersionKind{
136 Name: "test-service",
140 expectedCode: http.StatusCreated,
141 instClient: &mockInstanceClient{
142 items: []app.InstanceResponse{
145 Request: app.InstanceRequest{
146 RBName: "test-rbdef",
148 ProfileName: "profile1",
149 CloudRegion: "region1",
151 Namespace: "testnamespace",
152 Resources: []helm.KubernetesResource{
154 GVK: schema.GroupVersionKind{
158 Name: "test-deployment",
161 GVK: schema.GroupVersionKind{
165 Name: "test-service",
174 for _, testCase := range testCases {
175 t.Run(testCase.label, func(t *testing.T) {
177 request := httptest.NewRequest("POST", "/v1/instance", testCase.input)
178 resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil))
180 if testCase.expectedCode != resp.StatusCode {
181 body, _ := ioutil.ReadAll(resp.Body)
183 t.Fatalf("Request method returned: \n%v\n and it was expected: \n%v", resp.StatusCode, testCase.expectedCode)
186 if resp.StatusCode == http.StatusCreated {
187 var response app.InstanceResponse
188 err := json.NewDecoder(resp.Body).Decode(&response)
190 t.Fatalf("Parsing the returned response got an error (%s)", err)
197 func TestInstanceGetHandler(t *testing.T) {
198 testCases := []struct {
202 expectedResponse *app.InstanceResponse
203 instClient *mockInstanceClient
206 label: "Fail to retrieve Instance",
208 expectedCode: http.StatusInternalServerError,
209 instClient: &mockInstanceClient{
210 err: pkgerrors.New("Internal error"),
214 label: "Succesful get an Instance",
216 expectedCode: http.StatusOK,
217 expectedResponse: &app.InstanceResponse{
219 Request: app.InstanceRequest{
220 RBName: "test-rbdef",
222 ProfileName: "profile1",
223 CloudRegion: "region1",
225 Namespace: "testnamespace",
226 Resources: []helm.KubernetesResource{
228 GVK: schema.GroupVersionKind{
232 Name: "test-deployment",
235 GVK: schema.GroupVersionKind{
239 Name: "test-service",
243 instClient: &mockInstanceClient{
244 items: []app.InstanceResponse{
247 Request: app.InstanceRequest{
248 RBName: "test-rbdef",
250 ProfileName: "profile1",
251 CloudRegion: "region1",
253 Namespace: "testnamespace",
254 Resources: []helm.KubernetesResource{
256 GVK: schema.GroupVersionKind{
260 Name: "test-deployment",
263 GVK: schema.GroupVersionKind{
267 Name: "test-service",
276 for _, testCase := range testCases {
277 t.Run(testCase.label, func(t *testing.T) {
278 request := httptest.NewRequest("GET", "/v1/instance/"+testCase.input, nil)
279 resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil))
281 if testCase.expectedCode != resp.StatusCode {
282 t.Fatalf("Request method returned: %v and it was expected: %v",
283 resp.StatusCode, testCase.expectedCode)
285 if resp.StatusCode == http.StatusOK {
286 var response app.InstanceResponse
287 err := json.NewDecoder(resp.Body).Decode(&response)
289 t.Fatalf("Parsing the returned response got an error (%s)", err)
291 if !reflect.DeepEqual(testCase.expectedResponse, &response) {
292 t.Fatalf("TestGetHandler returned:\n result=%v\n expected=%v",
293 &response, testCase.expectedResponse)
300 func TestDeleteHandler(t *testing.T) {
301 testCases := []struct {
305 instClient *mockInstanceClient
308 label: "Fail to destroy VNF",
310 expectedCode: http.StatusInternalServerError,
311 instClient: &mockInstanceClient{
312 err: pkgerrors.New("Internal error"),
316 label: "Succesful delete a VNF",
318 expectedCode: http.StatusAccepted,
319 instClient: &mockInstanceClient{},
323 for _, testCase := range testCases {
324 t.Run(testCase.label, func(t *testing.T) {
325 request := httptest.NewRequest("DELETE", "/v1/instance/"+testCase.input, nil)
326 resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil))
328 if testCase.expectedCode != resp.StatusCode {
329 t.Fatalf("Request method returned: %v and it was expected: %v", resp.StatusCode, testCase.expectedCode)
335 // TODO: Update this test when the UpdateVNF endpoint is fixed.
337 func TestVNFInstanceUpdate(t *testing.T) {
338 t.Run("Succesful update a VNF", func(t *testing.T) {
340 "cloud_region_id": "region1",
347 "network_parameters": {
349 "connection_point": "string",
350 "ip_address": "string",
351 "workload_name": "string"
355 expected := &UpdateVnfResponse{
359 var result UpdateVnfResponse
361 req := httptest.NewRequest("PUT", "/v1/vnf_instances/1", bytes.NewBuffer(payload))
363 GetVNFClient = func(configPath string) (krd.VNFInstanceClientInterface, error) {
365 update: func() error {
370 utils.ReadCSARFromFileSystem = func(csarID string) (*krd.KubernetesData, error) {
371 kubeData := &krd.KubernetesData{
372 Deployment: &appsV1.Deployment{},
373 Service: &coreV1.Service{},
378 response := executeRequest(req)
379 checkResponseCode(t, http.StatusCreated, response.Code)
381 err := json.NewDecoder(response.Body).Decode(&result)
383 t.Fatalf("TestVNFInstanceUpdate returned:\n result=%v\n expected=%v", err, expected.DeploymentID)
386 if resp.DeploymentID != expected.DeploymentID {
387 t.Fatalf("TestVNFInstanceUpdate returned:\n result=%v\n expected=%v", resp.DeploymentID, expected.DeploymentID)