From b102d4ab1a47809f514213eb1f997d4f60893c9f Mon Sep 17 00:00:00 2001 From: Larry Sachs Date: Mon, 20 Jul 2020 22:46:49 -0700 Subject: Adds PUT api to v2/projects Add functionality to support the PUT api for v2/projects/{project-name} Also add unit tests for the PUT api Issue-ID: MULTICLOUD-1130 Change-Id: Ia271569c5f0dec3152952e64171fd5a182aaa333 Signed-off-by: Larry Sachs --- src/orchestrator/api/api.go | 1 + src/orchestrator/api/projecthandler.go | 46 +++++++++++++- src/orchestrator/api/projecthandler_test.go | 95 ++++++++++++++++++++++++++++- 3 files changed, 140 insertions(+), 2 deletions(-) (limited to 'src/orchestrator/api') diff --git a/src/orchestrator/api/api.go b/src/orchestrator/api/api.go index 097b9ab3..03afee28 100644 --- a/src/orchestrator/api/api.go +++ b/src/orchestrator/api/api.go @@ -56,6 +56,7 @@ func NewRouter(projectClient moduleLib.ProjectManager, client: ControllerClient, } router.HandleFunc("/projects", projHandler.createHandler).Methods("POST") + router.HandleFunc("/projects/{project-name}", projHandler.updateHandler).Methods("PUT") router.HandleFunc("/projects/{project-name}", projHandler.getHandler).Methods("GET") router.HandleFunc("/projects", projHandler.getHandler).Methods("GET") router.HandleFunc("/projects/{project-name}", projHandler.deleteHandler).Methods("DELETE") diff --git a/src/orchestrator/api/projecthandler.go b/src/orchestrator/api/projecthandler.go index 09b24096..83211b64 100644 --- a/src/orchestrator/api/projecthandler.go +++ b/src/orchestrator/api/projecthandler.go @@ -54,7 +54,7 @@ func (h projectHandler) createHandler(w http.ResponseWriter, r *http.Request) { return } - ret, err := h.client.CreateProject(p) + ret, err := h.client.CreateProject(p, false) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -69,6 +69,50 @@ func (h projectHandler) createHandler(w http.ResponseWriter, r *http.Request) { } } +// Update handles updating the Project entry in the database +func (h projectHandler) updateHandler(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name := vars["project-name"] + + var p moduleLib.Project + + err := json.NewDecoder(r.Body).Decode(&p) + switch { + case err == io.EOF: + http.Error(w, "Empty body", http.StatusBadRequest) + return + case err != nil: + http.Error(w, err.Error(), http.StatusUnprocessableEntity) + return + } + + // Name is required. + if p.MetaData.Name == "" { + http.Error(w, "Missing name in PUT request", http.StatusBadRequest) + return + } + + // Name in URL should match name in body + if p.MetaData.Name != name { + http.Error(w, "Mismatched name in PUT request", http.StatusBadRequest) + return + } + + ret, err := h.client.CreateProject(p, true) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + err = json.NewEncoder(w).Encode(ret) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + // Get handles GET operations on a particular Project Name // Returns a Project func (h projectHandler) getHandler(w http.ResponseWriter, r *http.Request) { diff --git a/src/orchestrator/api/projecthandler_test.go b/src/orchestrator/api/projecthandler_test.go index dae87e2b..6810099f 100644 --- a/src/orchestrator/api/projecthandler_test.go +++ b/src/orchestrator/api/projecthandler_test.go @@ -40,7 +40,7 @@ type mockProjectManager struct { Err error } -func (m *mockProjectManager) CreateProject(inp moduleLib.Project) (moduleLib.Project, error) { +func (m *mockProjectManager) CreateProject(inp moduleLib.Project, exists bool) (moduleLib.Project, error) { if m.Err != nil { return moduleLib.Project{}, m.Err } @@ -144,6 +144,99 @@ func TestProjectCreateHandler(t *testing.T) { } } +func TestProjectUpdateHandler(t *testing.T) { + testCases := []struct { + label, name string + reader io.Reader + expected moduleLib.Project + expectedCode int + projectClient *mockProjectManager + }{ + { + label: "Missing Project Name in Request Body", + name: "testProject", + reader: bytes.NewBuffer([]byte(`{ + "description":"test description" + }`)), + expectedCode: http.StatusBadRequest, + projectClient: &mockProjectManager{}, + }, + { + label: "Missing Body Failure", + name: "testProject", + expectedCode: http.StatusBadRequest, + projectClient: &mockProjectManager{}, + }, + { + label: "Mismatched Name Failure", + name: "testProject", + expectedCode: http.StatusBadRequest, + reader: bytes.NewBuffer([]byte(`{ + "metadata" : { + "name": "testProjectNameMismatch", + "description": "Test Project used for unit testing" + } + }`)), + projectClient: &mockProjectManager{}, + }, + { + label: "Update Project", + name: "testProject", + expectedCode: http.StatusOK, + reader: bytes.NewBuffer([]byte(`{ + "metadata" : { + "name": "testProject", + "description": "Test Project used for unit testing" + } + }`)), + expected: moduleLib.Project{ + MetaData: moduleLib.ProjectMetaData{ + Name: "testProject", + Description: "Test Project used for unit testing", + UserData1: "update data1", + UserData2: "update data2", + }, + }, + projectClient: &mockProjectManager{ + //Items that will be returned by the mocked Client + Items: []moduleLib.Project{ + { + MetaData: moduleLib.ProjectMetaData{ + Name: "testProject", + Description: "Test Project used for unit testing", + UserData1: "update data1", + UserData2: "update data2", + }, + }, + }, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.label, func(t *testing.T) { + request := httptest.NewRequest("PUT", "/v2/projects/"+testCase.name, testCase.reader) + resp := executeRequest(request, NewRouter(testCase.projectClient, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)) + + //Check returned code + if resp.StatusCode != testCase.expectedCode { + t.Fatalf("Expected %d; Got: %d", testCase.expectedCode, resp.StatusCode) + } + + //Check returned body only if statusOK + if resp.StatusCode == http.StatusOK { + got := moduleLib.Project{} + json.NewDecoder(resp.Body).Decode(&got) + + if reflect.DeepEqual(testCase.expected, got) == false { + t.Errorf("updateHandler returned unexpected body: got %v;"+ + " expected %v", got, testCase.expected) + } + } + }) + } +} + func TestProjectGetHandler(t *testing.T) { testCases := []struct { -- cgit 1.2.3-korg