4 Copyright 2018 Intel Corporation.
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
27 pkgerrors "github.com/pkg/errors"
28 "k8s.io/client-go/kubernetes"
30 helper "k8splugin/internal/app"
31 "k8splugin/internal/db"
34 type mockCSAR struct {
36 resourceYAMLNameMap map[string][]string
40 func (c *mockCSAR) CreateVNF(id, r, n string,
41 kubeclient *kubernetes.Clientset) (string, map[string][]string, error) {
42 return c.externalVNFID, c.resourceYAMLNameMap, c.err
45 func (c *mockCSAR) DestroyVNF(data map[string][]string, namespace string,
46 kubeclient *kubernetes.Clientset) error {
50 func executeRequest(req *http.Request) *http.Response {
51 router := NewRouter("", nil, nil)
52 recorder := httptest.NewRecorder()
53 router.ServeHTTP(recorder, req)
55 return recorder.Result()
58 func checkResponseCode(t *testing.T, expected, actual int) {
59 if expected != actual {
60 t.Errorf("Expected response code %d. Got %d\n", expected, actual)
64 func TestCreateHandler(t *testing.T) {
65 testCases := []struct {
69 mockGetVNFClientErr error
70 mockCreateVNF *mockCSAR
74 label: "Missing body failure",
75 expectedCode: http.StatusBadRequest,
78 label: "Invalid JSON request format",
79 input: bytes.NewBuffer([]byte("invalid")),
80 expectedCode: http.StatusUnprocessableEntity,
83 label: "Missing parameter failure",
84 input: bytes.NewBuffer([]byte(`{
92 "vnf_instance_name": "test",
93 "vnf_instance_description": "vRouter_test_description"
95 expectedCode: http.StatusUnprocessableEntity,
98 label: "Fail to get the VNF client",
99 input: bytes.NewBuffer([]byte(`{
100 "cloud_region_id": "region1",
101 "rb_profile_id": "123e4567-e89b-12d3-a456-426655440000",
104 expectedCode: http.StatusInternalServerError,
105 mockGetVNFClientErr: pkgerrors.New("Get VNF client error"),
108 label: "Fail to create the VNF instance",
109 input: bytes.NewBuffer([]byte(`{
110 "cloud_region_id": "region1",
111 "rb_profile_id": "123e4567-e89b-12d3-a456-426655440000",
114 expectedCode: http.StatusInternalServerError,
115 mockCreateVNF: &mockCSAR{
116 err: pkgerrors.New("Internal error"),
120 label: "Fail to create a VNF DB record",
121 input: bytes.NewBuffer([]byte(`{
122 "cloud_region_id": "region1",
123 "rb_profile_id": "123e4567-e89b-12d3-a456-426655440000",
126 expectedCode: http.StatusInternalServerError,
127 mockCreateVNF: &mockCSAR{
128 resourceYAMLNameMap: map[string][]string{},
130 mockStore: &db.MockDB{
131 Err: pkgerrors.New("Internal error"),
135 label: "Succesful create a VNF",
136 input: bytes.NewBuffer([]byte(`{
137 "cloud_region_id": "region1",
138 "rb_profile_id": "123e4567-e89b-12d3-a456-426655440000",
141 expectedCode: http.StatusCreated,
142 mockCreateVNF: &mockCSAR{
143 resourceYAMLNameMap: map[string][]string{
144 "deployment": []string{"cloud1-default-uuid-sisedeploy"},
145 "service": []string{"cloud1-default-uuid-sisesvc"},
148 mockStore: &db.MockDB{},
152 for _, testCase := range testCases {
153 t.Run(testCase.label, func(t *testing.T) {
154 GetVNFClient = func(configPath string) (kubernetes.Clientset, error) {
155 return kubernetes.Clientset{}, testCase.mockGetVNFClientErr
157 if testCase.mockCreateVNF != nil {
158 helper.CreateVNF = testCase.mockCreateVNF.CreateVNF
160 if testCase.mockStore != nil {
161 db.DBconn = testCase.mockStore
164 request := httptest.NewRequest("POST", "/v1/vnf_instances/", testCase.input)
165 result := executeRequest(request)
167 if testCase.expectedCode != result.StatusCode {
168 t.Fatalf("Request method returned: \n%v\n and it was expected: \n%v", result.StatusCode, testCase.expectedCode)
170 if result.StatusCode == http.StatusCreated {
171 var response CreateVnfResponse
172 err := json.NewDecoder(result.Body).Decode(&response)
174 t.Fatalf("Parsing the returned response got an error (%s)", err)
181 func TestListHandler(t *testing.T) {
182 testCases := []struct {
185 expectedResponse []string
189 label: "Fail to retrieve DB records",
190 expectedCode: http.StatusInternalServerError,
191 mockStore: &db.MockDB{
192 Err: pkgerrors.New("Internal error"),
196 label: "Get empty list",
197 expectedCode: http.StatusOK,
198 expectedResponse: []string{""},
199 mockStore: &db.MockDB{},
202 label: "Succesful get a list of VNF",
203 expectedCode: http.StatusOK,
204 expectedResponse: []string{"uid1"},
205 mockStore: &db.MockDB{
206 Items: map[string]map[string][]byte{
208 "data": []byte("{}"),
215 for _, testCase := range testCases {
216 t.Run(testCase.label, func(t *testing.T) {
217 if testCase.mockStore != nil {
218 db.DBconn = testCase.mockStore
221 request := httptest.NewRequest("GET", "/v1/vnf_instances/cloud1/default", nil)
222 result := executeRequest(request)
224 if testCase.expectedCode != result.StatusCode {
225 t.Fatalf("Request method returned: \n%v\n and it was expected: \n%v",
226 result.StatusCode, testCase.expectedCode)
228 if result.StatusCode == http.StatusOK {
229 var response ListVnfsResponse
230 err := json.NewDecoder(result.Body).Decode(&response)
232 t.Fatalf("Parsing the returned response got an error (%s)", err)
234 if !reflect.DeepEqual(testCase.expectedResponse, response.VNFs) {
235 t.Fatalf("TestListHandler returned:\n result=%v\n expected=%v",
236 response.VNFs, testCase.expectedResponse)
243 func TestDeleteHandler(t *testing.T) {
244 testCases := []struct {
247 mockGetVNFClientErr error
248 mockDeleteVNF *mockCSAR
252 label: "Fail to read a VNF DB record",
253 expectedCode: http.StatusInternalServerError,
254 mockStore: &db.MockDB{
255 Err: pkgerrors.New("Internal error"),
259 label: "Fail to find VNF record be deleted",
260 expectedCode: http.StatusInternalServerError,
261 mockStore: &db.MockDB{
262 Items: map[string]map[string][]byte{},
266 label: "Fail to unmarshal the DB record",
267 expectedCode: http.StatusInternalServerError,
268 mockStore: &db.MockDB{
269 Items: map[string]map[string][]byte{
270 "cloudregion1-testnamespace-uuid1": {
271 "data": []byte("{invalid format}"),
277 label: "Fail to get the VNF client",
278 expectedCode: http.StatusInternalServerError,
279 mockGetVNFClientErr: pkgerrors.New("Get VNF client error"),
280 mockStore: &db.MockDB{
281 Items: map[string]map[string][]byte{
282 "cloudregion1-testnamespace-uuid1": {
284 "{\"deployment\": [\"deploy1\", \"deploy2\"]," +
285 "\"service\": [\"svc1\", \"svc2\"]}"),
291 label: "Fail to destroy VNF",
292 expectedCode: http.StatusInternalServerError,
293 mockStore: &db.MockDB{
294 Items: map[string]map[string][]byte{
295 "cloudregion1-testnamespace-uuid1": {
297 "{\"deployment\": [\"deploy1\", \"deploy2\"]," +
298 "\"service\": [\"svc1\", \"svc2\"]}"),
302 mockDeleteVNF: &mockCSAR{
303 err: pkgerrors.New("Internal error"),
307 label: "Succesful delete a VNF",
308 expectedCode: http.StatusAccepted,
309 mockStore: &db.MockDB{
310 Items: map[string]map[string][]byte{
311 "cloudregion1-testnamespace-uuid1": {
313 "{\"deployment\": [\"deploy1\", \"deploy2\"]," +
314 "\"service\": [\"svc1\", \"svc2\"]}"),
318 mockDeleteVNF: &mockCSAR{},
322 for _, testCase := range testCases {
323 t.Run(testCase.label, func(t *testing.T) {
324 GetVNFClient = func(configPath string) (kubernetes.Clientset, error) {
325 return kubernetes.Clientset{}, testCase.mockGetVNFClientErr
327 if testCase.mockStore != nil {
328 db.DBconn = testCase.mockStore
330 if testCase.mockDeleteVNF != nil {
331 helper.DestroyVNF = testCase.mockDeleteVNF.DestroyVNF
334 request := httptest.NewRequest("DELETE", "/v1/vnf_instances/cloudregion1/testnamespace/uuid1", nil)
335 result := executeRequest(request)
337 if testCase.expectedCode != result.StatusCode {
338 t.Fatalf("Request method returned: %v and it was expected: %v", result.StatusCode, testCase.expectedCode)
344 // TODO: Update this test when the UpdateVNF endpoint is fixed.
346 func TestVNFInstanceUpdate(t *testing.T) {
347 t.Run("Succesful update a VNF", func(t *testing.T) {
349 "cloud_region_id": "region1",
356 "network_parameters": {
358 "connection_point": "string",
359 "ip_address": "string",
360 "workload_name": "string"
364 expected := &UpdateVnfResponse{
368 var result UpdateVnfResponse
370 req := httptest.NewRequest("PUT", "/v1/vnf_instances/1", bytes.NewBuffer(payload))
372 GetVNFClient = func(configPath string) (krd.VNFInstanceClientInterface, error) {
374 update: func() error {
379 utils.ReadCSARFromFileSystem = func(csarID string) (*krd.KubernetesData, error) {
380 kubeData := &krd.KubernetesData{
381 Deployment: &appsV1.Deployment{},
382 Service: &coreV1.Service{},
387 response := executeRequest(req)
388 checkResponseCode(t, http.StatusCreated, response.Code)
390 err := json.NewDecoder(response.Body).Decode(&result)
392 t.Fatalf("TestVNFInstanceUpdate returned:\n result=%v\n expected=%v", err, expected.DeploymentID)
395 if result.DeploymentID != expected.DeploymentID {
396 t.Fatalf("TestVNFInstanceUpdate returned:\n result=%v\n expected=%v", result.DeploymentID, expected.DeploymentID)
402 func TestGetHandler(t *testing.T) {
403 testCases := []struct {
406 expectedResponse *GetVnfResponse
410 label: "Fail to retrieve DB record",
411 expectedCode: http.StatusInternalServerError,
412 mockStore: &db.MockDB{
413 Err: pkgerrors.New("Internal error"),
417 label: "Not found DB record",
418 expectedCode: http.StatusInternalServerError,
419 mockStore: &db.MockDB{},
422 label: "Fail to unmarshal the DB record",
423 expectedCode: http.StatusInternalServerError,
424 mockStore: &db.MockDB{
425 Items: map[string]map[string][]byte{
426 "cloud1-default-1": {
427 "data": []byte("{invalid-format}"),
433 label: "Succesful get a list of VNF",
434 expectedCode: http.StatusOK,
435 expectedResponse: &GetVnfResponse{
437 CloudRegionID: "cloud1",
438 Namespace: "default",
439 VNFComponents: map[string][]string{
440 "deployment": []string{"deploy1", "deploy2"},
441 "service": []string{"svc1", "svc2"},
444 mockStore: &db.MockDB{
445 Items: map[string]map[string][]byte{
446 "cloud1-default-1": {
448 "{\"deployment\": [\"deploy1\", \"deploy2\"]," +
449 "\"service\": [\"svc1\", \"svc2\"]}"),
450 "cloud1-default-2": []byte("{}"),
457 for _, testCase := range testCases {
458 t.Run(testCase.label, func(t *testing.T) {
459 db.DBconn = testCase.mockStore
460 request := httptest.NewRequest("GET", "/v1/vnf_instances/cloud1/default/1", nil)
461 result := executeRequest(request)
463 if testCase.expectedCode != result.StatusCode {
464 t.Fatalf("Request method returned: %v and it was expected: %v",
465 result.StatusCode, testCase.expectedCode)
467 if result.StatusCode == http.StatusOK {
468 var response GetVnfResponse
469 err := json.NewDecoder(result.Body).Decode(&response)
471 t.Fatalf("Parsing the returned response got an error (%s)", err)
473 if !reflect.DeepEqual(testCase.expectedResponse, &response) {
474 t.Fatalf("TestGetHandler returned:\n result=%v\n expected=%v",
475 &response, testCase.expectedResponse)