aboutsummaryrefslogtreecommitdiffstats
path: root/src/k8splugin/api
diff options
context:
space:
mode:
authorLukasz Rajewski <lukasz.rajewski@orange.com>2022-02-15 22:39:37 +0100
committerLukasz Rajewski <lukasz.rajewski@orange.com>2022-03-02 22:46:03 +0100
commit5b18db4fc784763402e0898bf5e996886279347e (patch)
tree984a315638e1ef87841144fbb6a7e56484ffd12c /src/k8splugin/api
parenta73b42b9c3877f1a34939d85941482f7f5c44db9 (diff)
Implementation of status notification mechanism0.10.0
- Subscription CRUD endpoints - Subscription notifu executor - Cleanup of subscriptions on instance delete - Sending notification to the specified callback Issue-ID: MULTICLOUD-1445 Signed-off-by: Lukasz Rajewski <lukasz.rajewski@orange.com> Change-Id: I5b867a348e916f6c2c471bcc5326c831d832f45e
Diffstat (limited to 'src/k8splugin/api')
-rw-r--r--src/k8splugin/api/api.go17
-rw-r--r--src/k8splugin/api/brokerhandler_test.go8
-rw-r--r--src/k8splugin/api/defhandler_test.go12
-rw-r--r--src/k8splugin/api/healthcheckhandler_test.go4
-rw-r--r--src/k8splugin/api/instancehandler.go2
-rw-r--r--src/k8splugin/api/instancehandler_test.go12
-rw-r--r--src/k8splugin/api/profilehandler_test.go10
-rw-r--r--src/k8splugin/api/statussubhandler.go229
8 files changed, 268 insertions, 26 deletions
diff --git a/src/k8splugin/api/api.go b/src/k8splugin/api/api.go
index 64c83e03..64959f5e 100644
--- a/src/k8splugin/api/api.go
+++ b/src/k8splugin/api/api.go
@@ -1,7 +1,7 @@
/*
Copyright 2018 Intel Corporation.
Copyright © 2021 Samsung Electronics
-Copyright © 2021 Orange
+Copyright © 2022 Orange
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@ func NewRouter(defClient rb.DefinitionManager,
configClient app.ConfigManager,
connectionClient connection.ConnectionManager,
templateClient rb.ConfigTemplateManager,
+ subscriptionClient app.InstanceStatusSubManager,
healthcheckClient healthcheck.InstanceHCManager) *mux.Router {
router := mux.NewRouter()
@@ -52,7 +53,6 @@ func NewRouter(defClient rb.DefinitionManager,
"profile-name", "{profile-name}").Methods("GET")
//Want to get full Data -> add query param: /install/{instID}?full=true
instRouter.HandleFunc("/instance/{instID}", instHandler.getHandler).Methods("GET")
- instRouter.HandleFunc("/instance/{instID}/status", instHandler.statusHandler).Methods("GET")
instRouter.HandleFunc("/instance/{instID}/upgrade", instHandler.upgradeHandler).Methods("POST")
instRouter.HandleFunc("/instance/{instID}/query", instHandler.queryHandler).Methods("GET")
instRouter.HandleFunc("/instance/{instID}/query", instHandler.queryHandler).
@@ -62,6 +62,19 @@ func NewRouter(defClient rb.DefinitionManager,
"Labels", "{Labels}").Methods("GET")
instRouter.HandleFunc("/instance/{instID}", instHandler.deleteHandler).Methods("DELETE")
+ // Status handler routes
+ if subscriptionClient == nil {
+ subscriptionClient = app.NewInstanceStatusSubClient()
+ subscriptionClient.RestoreWatchers()
+ }
+ instanceStatusSubHandler := instanceStatusSubHandler{client: subscriptionClient}
+ instRouter.HandleFunc("/instance/{instID}/status", instHandler.statusHandler).Methods("GET")
+ instRouter.HandleFunc("/instance/{instID}/status/subscription", instanceStatusSubHandler.listHandler).Methods("GET")
+ instRouter.HandleFunc("/instance/{instID}/status/subscription", instanceStatusSubHandler.createHandler).Methods("POST")
+ instRouter.HandleFunc("/instance/{instID}/status/subscription/{subID}", instanceStatusSubHandler.getHandler).Methods("GET")
+ instRouter.HandleFunc("/instance/{instID}/status/subscription/{subID}", instanceStatusSubHandler.updateHandler).Methods("PUT")
+ instRouter.HandleFunc("/instance/{instID}/status/subscription/{subID}", instanceStatusSubHandler.deleteHandler).Methods("DELETE")
+
// Query handler routes
if queryClient == nil {
queryClient = app.NewQueryClient()
diff --git a/src/k8splugin/api/brokerhandler_test.go b/src/k8splugin/api/brokerhandler_test.go
index 767cae1e..a08b8a9b 100644
--- a/src/k8splugin/api/brokerhandler_test.go
+++ b/src/k8splugin/api/brokerhandler_test.go
@@ -313,7 +313,7 @@ func TestBrokerCreateHandler(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/cloudowner/cloudregion/infra_workload", testCase.input)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
defer resp.Body.Close()
if testCase.expectedCode != resp.StatusCode {
@@ -409,7 +409,7 @@ func TestBrokerGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/cloudowner/cloudregion/infra_workload/"+testCase.input, nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
t.Fatalf("Request method returned: %v and it was expected: %v",
@@ -489,7 +489,7 @@ func TestBrokerFindHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/cloudowner/cloudregion/infra_workload?name="+testCase.input, nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
t.Fatalf("Request method returned: %v and it was expected: %v",
@@ -551,7 +551,7 @@ func TestBrokerDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/cloudowner/cloudregion/infra_workload/"+testCase.input, nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
t.Fatalf("Request method returned: %v and it was expected: %v", resp.StatusCode, testCase.expectedCode)
diff --git a/src/k8splugin/api/defhandler_test.go b/src/k8splugin/api/defhandler_test.go
index b626b6f3..22d45487 100644
--- a/src/k8splugin/api/defhandler_test.go
+++ b/src/k8splugin/api/defhandler_test.go
@@ -139,7 +139,7 @@ func TestRBDefCreateHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v1/rb/definition", testCase.reader)
- resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -208,7 +208,7 @@ func TestRBDefListVersionsHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v1/rb/definition/testresourcebundle", nil)
- resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -288,7 +288,7 @@ func TestRBDefListAllHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v1/rb/definition", nil)
- resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -368,7 +368,7 @@ func TestRBDefGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v1/rb/definition/"+testCase.name+"/"+testCase.version, nil)
- resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -419,7 +419,7 @@ func TestRBDefDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v1/rb/definition/"+testCase.name+"/"+testCase.version, nil)
- resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -476,7 +476,7 @@ func TestRBDefUploadHandler(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST",
"/v1/rb/definition/"+testCase.name+"/"+testCase.version+"/content", testCase.body)
- resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(testCase.rbDefClient, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
diff --git a/src/k8splugin/api/healthcheckhandler_test.go b/src/k8splugin/api/healthcheckhandler_test.go
index 3a03d902..c6c07c16 100644
--- a/src/k8splugin/api/healthcheckhandler_test.go
+++ b/src/k8splugin/api/healthcheckhandler_test.go
@@ -35,7 +35,7 @@ func TestHealthCheckHandler(t *testing.T) {
Err: nil,
}
request := httptest.NewRequest("GET", "/v1/healthcheck", nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != http.StatusOK {
@@ -48,7 +48,7 @@ func TestHealthCheckHandler(t *testing.T) {
Err: pkgerrors.New("Runtime Error in DB"),
}
request := httptest.NewRequest("GET", "/v1/healthcheck", nil)
- resp := executeRequest(request, NewRouter(nil, nil, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != http.StatusInternalServerError {
diff --git a/src/k8splugin/api/instancehandler.go b/src/k8splugin/api/instancehandler.go
index 6d1fd7b3..dd5fd0dd 100644
--- a/src/k8splugin/api/instancehandler.go
+++ b/src/k8splugin/api/instancehandler.go
@@ -211,7 +211,7 @@ func (i instanceHandler) statusHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["instID"]
- resp, err := i.client.Status(id)
+ resp, err := i.client.Status(id, true)
if err != nil {
log.Error("Error getting Status", log.Fields{
"error": err,
diff --git a/src/k8splugin/api/instancehandler_test.go b/src/k8splugin/api/instancehandler_test.go
index 444b6695..f06af446 100644
--- a/src/k8splugin/api/instancehandler_test.go
+++ b/src/k8splugin/api/instancehandler_test.go
@@ -72,7 +72,7 @@ func (m *mockInstanceClient) Query(id, apiVersion, kind, name, labels string) (a
return m.statusItem, nil
}
-func (m *mockInstanceClient) Status(id string) (app.InstanceStatus, error) {
+func (m *mockInstanceClient) Status(id string, checkReady bool) (app.InstanceStatus, error) {
if m.err != nil {
return app.InstanceStatus{}, m.err
}
@@ -205,7 +205,7 @@ func TestInstanceCreateHandler(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v1/instance", testCase.input)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
body, _ := ioutil.ReadAll(resp.Body)
@@ -306,7 +306,7 @@ func TestInstanceGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v1/instance/"+testCase.input, nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
t.Fatalf("Request method returned: %v and it was expected: %v",
@@ -441,7 +441,7 @@ func TestInstanceListHandler(t *testing.T) {
}
request.URL.RawQuery = q.Encode()
}
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
t.Fatalf("Request method returned: %v and it was expected: %v",
@@ -500,7 +500,7 @@ func TestDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v1/instance/"+testCase.input, nil)
- resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
t.Fatalf("Request method returned: %v and it was expected: %v", resp.StatusCode, testCase.expectedCode)
@@ -734,7 +734,7 @@ func TestInstanceQueryHandler(t *testing.T) {
}
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, nil))
+ resp := executeRequest(request, NewRouter(nil, nil, testCase.instClient, nil, nil, nil, nil, nil, nil))
if testCase.expectedCode != resp.StatusCode {
body, _ := ioutil.ReadAll(resp.Body)
diff --git a/src/k8splugin/api/profilehandler_test.go b/src/k8splugin/api/profilehandler_test.go
index 181b775b..57040668 100644
--- a/src/k8splugin/api/profilehandler_test.go
+++ b/src/k8splugin/api/profilehandler_test.go
@@ -127,7 +127,7 @@ func TestRBProfileCreateHandler(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST", "/v1/rb/definition/test-rbdef/v1/profile",
testCase.reader)
- resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -207,7 +207,7 @@ func TestRBProfileGetHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v1/rb/definition/test-rbdef/v1/profile/"+testCase.prname, nil)
- resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -288,7 +288,7 @@ func TestRBProfileListHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("GET", "/v1/rb/definition/"+testCase.def+"/"+testCase.version+"/profile", nil)
- resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -347,7 +347,7 @@ func TestRBProfileDeleteHandler(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("DELETE", "/v1/rb/definition/test-rbdef/v1/profile/"+testCase.prname, nil)
- resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
@@ -400,7 +400,7 @@ func TestRBProfileUploadHandler(t *testing.T) {
t.Run(testCase.label, func(t *testing.T) {
request := httptest.NewRequest("POST",
"/v1/rb/definition/test-rbdef/v1/profile/"+testCase.prname+"/content", testCase.body)
- resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil))
+ resp := executeRequest(request, NewRouter(nil, testCase.rbProClient, nil, nil, nil, nil, nil, nil, nil))
//Check returned code
if resp.StatusCode != testCase.expectedCode {
diff --git a/src/k8splugin/api/statussubhandler.go b/src/k8splugin/api/statussubhandler.go
new file mode 100644
index 00000000..c5c8de23
--- /dev/null
+++ b/src/k8splugin/api/statussubhandler.go
@@ -0,0 +1,229 @@
+/*
+Copyright © 2022 Orange
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package api
+
+import (
+ "encoding/json"
+ "io"
+ "net/http"
+
+ "github.com/onap/multicloud-k8s/src/k8splugin/internal/app"
+ log "github.com/onap/multicloud-k8s/src/k8splugin/internal/logutils"
+
+ "github.com/gorilla/mux"
+)
+
+// Used to store the backend implementation objects
+// Also simplifies the mocking needed for unit testing
+type instanceStatusSubHandler struct {
+ // Interface that implements Status Subscription operations
+ client app.InstanceStatusSubManager
+}
+
+func (iss instanceStatusSubHandler) createHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ id := vars["instID"]
+
+ var subRequest app.SubscriptionRequest
+
+ err := json.NewDecoder(r.Body).Decode(&subRequest)
+ switch {
+ case err == io.EOF:
+ log.Error("Body Empty", log.Fields{
+ "error": io.EOF,
+ })
+ http.Error(w, "Body empty", http.StatusBadRequest)
+ return
+ case err != nil:
+ log.Error("Error unmarshaling Body", log.Fields{
+ "error": err,
+ })
+ http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+ return
+ }
+
+ // Name is required.
+ if subRequest.Name == "" {
+ http.Error(w, "Missing name in POST request", http.StatusBadRequest)
+ return
+ }
+
+ // MinNotifyInterval cannot be less than 0
+ if subRequest.MinNotifyInterval < 0 {
+ http.Error(w, "Min Notify Interval has invalid value", http.StatusBadRequest)
+ return
+ }
+
+ // CallbackUrl is required
+ if subRequest.CallbackUrl == "" {
+ http.Error(w, "CallbackUrl has invalid value", http.StatusBadRequest)
+ return
+ }
+
+ resp, err := iss.client.Create(id, subRequest)
+ if err != nil {
+ log.Error("Error creating subscription", log.Fields{
+ "error": err,
+ "instance": id,
+ "response": resp,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusCreated)
+ err = json.NewEncoder(w).Encode(resp)
+ if err != nil {
+ log.Error("Error Marshaling Response", log.Fields{
+ "error": err,
+ "response": resp,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+func (iss instanceStatusSubHandler) getHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ instanceId := vars["instID"]
+ subId := vars["subID"]
+
+ resp, err := iss.client.Get(instanceId, subId)
+ if err != nil {
+ log.Error("Error getting instance's Status Subscription", log.Fields{
+ "error": err,
+ "instanceID": instanceId,
+ "subscriptionID": subId,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ err = json.NewEncoder(w).Encode(resp)
+ if err != nil {
+ log.Error("Error Marshaling Response", log.Fields{
+ "error": err,
+ "response": resp,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+func (iss instanceStatusSubHandler) updateHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ instanceId := vars["instID"]
+ subId := vars["subID"]
+
+ var subRequest app.SubscriptionRequest
+
+ err := json.NewDecoder(r.Body).Decode(&subRequest)
+ switch {
+ case err == io.EOF:
+ log.Error("Body Empty", log.Fields{
+ "error": io.EOF,
+ })
+ http.Error(w, "Body empty", http.StatusBadRequest)
+ return
+ case err != nil:
+ log.Error("Error unmarshaling Body", log.Fields{
+ "error": err,
+ })
+ http.Error(w, err.Error(), http.StatusUnprocessableEntity)
+ return
+ }
+
+ // MinNotifyInterval cannot be less than 0
+ if subRequest.MinNotifyInterval < 0 {
+ http.Error(w, "Min Notify Interval has invalid value", http.StatusBadRequest)
+ return
+ }
+
+ // CallbackUrl is required
+ if subRequest.CallbackUrl == "" {
+ http.Error(w, "CallbackUrl has invalid value", http.StatusBadRequest)
+ return
+ }
+
+ resp, err := iss.client.Update(instanceId, subId, subRequest)
+ if err != nil {
+ log.Error("Error updating instance's Status Subscription", log.Fields{
+ "error": err,
+ "instanceID": instanceId,
+ "subscriptionID": subId,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ err = json.NewEncoder(w).Encode(resp)
+ if err != nil {
+ log.Error("Error Marshaling Response", log.Fields{
+ "error": err,
+ "response": resp,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}
+
+func (iss instanceStatusSubHandler) deleteHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ instanceId := vars["instID"]
+ subId := vars["subID"]
+
+ err := iss.client.Delete(instanceId, subId)
+ if err != nil {
+ log.Error("Error deleting instance's Status Subscription", log.Fields{
+ "error": err,
+ "instanceID": instanceId,
+ "subscriptionID": subId,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ w.WriteHeader(http.StatusAccepted)
+}
+
+func (iss instanceStatusSubHandler) listHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ id := vars["instID"]
+
+ resp, err := iss.client.List(id)
+ if err != nil {
+ log.Error("Error listing instance Status Subscriptions", log.Fields{
+ "error": err,
+ "instance-id": id,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ err = json.NewEncoder(w).Encode(resp)
+ if err != nil {
+ log.Error("Error Marshaling Response", log.Fields{
+ "error": err,
+ "response": resp,
+ })
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+}