X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=cmd%2Fappmgr%2Fapi.go;h=7acb7c790d8bbf7ed93209141ad405e16059857f;hb=refs%2Fchanges%2F93%2F1893%2F1;hp=0d3fef9dc6edd713d9ea29be329909ea0ce2e145;hpb=193caf9d7e08b84a0b9c1f0352924a7efd77e77c;p=ric-plt%2Fappmgr.git diff --git a/cmd/appmgr/api.go b/cmd/appmgr/api.go index 0d3fef9..7acb7c7 100755 --- a/cmd/appmgr/api.go +++ b/cmd/appmgr/api.go @@ -21,21 +21,21 @@ package main import ( "encoding/json" + "errors" "github.com/gorilla/mux" "github.com/spf13/viper" "log" "net/http" + "time" ) // API functions -func (m *XappManager) Initialize(h Helmer) { - /* - m.sd = SubscriptionDispatcher{} - m.sd.Initialize() - m.helm = h - m.helm.Initialize() - */ +func (m *XappManager) Initialize(h Helmer, cm ConfigMapper) { + m.cm = cm + m.helm = h + m.helm.SetCM(cm) + m.router = mux.NewRouter().StrictSlash(true) resources := []Resource{ @@ -43,6 +43,7 @@ func (m *XappManager) Initialize(h Helmer) { {"GET", "/ric/v1/health/ready", m.getHealthStatus}, {"GET", "/ric/v1/xapps", m.getAllXapps}, + {"GET", "/ric/v1/xapps/search", m.searchAllXapps}, {"GET", "/ric/v1/xapps/{name}", m.getXappByName}, {"GET", "/ric/v1/xapps/{name}/instances/{id}", m.getXappInstanceByName}, {"POST", "/ric/v1/xapps", m.deployXapp}, @@ -53,10 +54,16 @@ func (m *XappManager) Initialize(h Helmer) { {"GET", "/ric/v1/subscriptions/{id}", m.getSubscription}, {"DELETE", "/ric/v1/subscriptions/{id}", m.deleteSubscription}, {"PUT", "/ric/v1/subscriptions/{id}", m.updateSubscription}, + + {"GET", "/ric/v1/config", m.getConfig}, + {"POST", "/ric/v1/config", m.createConfig}, + {"PUT", "/ric/v1/config", m.updateConfig}, + {"DELETE", "/ric/v1/config", m.deleteConfig}, + {"DELETE", "/ric/v1/config/{name}", m.deleteSingleConfig}, } for _, resource := range resources { - handler := Logger(resource.HandlerFunc) + handler := LogRestRequests(resource.HandlerFunc) //handler = m.serviceChecker(handler) m.router.Methods(resource.Method).Path(resource.Url).Handler(handler) } @@ -68,7 +75,6 @@ func (m *XappManager) finalize(h Helmer) { m.sd = SubscriptionDispatcher{} m.sd.Initialize() - m.helm = h m.helm.Initialize() m.notifyClients() @@ -136,7 +142,7 @@ func (m *XappManager) getXappInstanceByName(w http.ResponseWriter, r *http.Reque return } } - mdclog(MdclogErr, "Xapp instance not found - url="+r.URL.RequestURI()) + Logger.Error("Xapp instance not found - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusNotFound, "Xapp instance not found") } @@ -151,27 +157,38 @@ func (m *XappManager) getAllXapps(w http.ResponseWriter, r *http.Request) { respondWithJSON(w, http.StatusOK, xapps) } +func (m *XappManager) searchAllXapps(w http.ResponseWriter, r *http.Request) { + respondWithJSON(w, http.StatusOK, m.helm.SearchAll()) +} + func (m *XappManager) deployXapp(w http.ResponseWriter, r *http.Request) { if r.Body == nil { - mdclog(MdclogErr, "No xapp data found in request body - url="+r.URL.RequestURI()) + Logger.Error("No xapp data found in request body - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusMethodNotAllowed, "No xapp data!") return } - var xapp Xapp - if err := json.NewDecoder(r.Body).Decode(&xapp); err != nil { - mdclog(MdclogErr, "Invalid xapp data in request body - url="+r.URL.RequestURI()) + var cm XappDeploy + if err := json.NewDecoder(r.Body).Decode(&cm); err != nil { + Logger.Error("Invalid xapp data in request body - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusMethodNotAllowed, "Invalid xapp data!") return } defer r.Body.Close() - xapp, err := m.helm.Install(xapp.Name) + xapp, err := m.helm.Install(cm) if err != nil { respondWithError(w, http.StatusInternalServerError, err.Error()) return } + for i := 0; i < 3; i++ { + if xapp, err = m.helm.Status(xapp.Name); xapp.Instances != nil { + break + } + time.Sleep(time.Duration(5) * time.Second) + } + respondWithJSON(w, http.StatusCreated, xapp) m.sd.Publish(xapp, EventType("created")) @@ -204,7 +221,7 @@ func (m *XappManager) getSubscription(w http.ResponseWriter, r *http.Request) { if s, ok := m.sd.Get(id); ok { respondWithJSON(w, http.StatusOK, s) } else { - mdclog(MdclogErr, "Subscription not found - url="+r.URL.RequestURI()) + Logger.Error("Subscription not found - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusNotFound, "Subscription not found") } } @@ -215,7 +232,7 @@ func (m *XappManager) deleteSubscription(w http.ResponseWriter, r *http.Request) if _, ok := m.sd.Delete(id); ok { respondWithJSON(w, http.StatusNoContent, nil) } else { - mdclog(MdclogErr, "Subscription not found - url="+r.URL.RequestURI()) + Logger.Error("Subscription not found - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusNotFound, "Subscription not found") } } @@ -224,7 +241,7 @@ func (m *XappManager) deleteSubscription(w http.ResponseWriter, r *http.Request) func (m *XappManager) addSubscription(w http.ResponseWriter, r *http.Request) { var req SubscriptionReq if r.Body == nil || json.NewDecoder(r.Body).Decode(&req) != nil { - mdclog(MdclogErr, "Invalid request payload - url="+r.URL.RequestURI()) + Logger.Error("Invalid request payload - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusMethodNotAllowed, "Invalid request payload") return } @@ -237,7 +254,7 @@ func (m *XappManager) updateSubscription(w http.ResponseWriter, r *http.Request) if id, ok := getResourceId(r, w, "id"); ok == true { var req SubscriptionReq if r.Body == nil || json.NewDecoder(r.Body).Decode(&req) != nil { - mdclog(MdclogErr, "Invalid request payload - url="+r.URL.RequestURI()) + Logger.Error("Invalid request payload - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusMethodNotAllowed, "Invalid request payload") return } @@ -246,7 +263,7 @@ func (m *XappManager) updateSubscription(w http.ResponseWriter, r *http.Request) if s, ok := m.sd.Update(id, req); ok { respondWithJSON(w, http.StatusOK, s) } else { - mdclog(MdclogErr, "Subscription not found - url="+r.URL.RequestURI()) + Logger.Error("Subscription not found - url=%s", r.URL.RequestURI()) respondWithError(w, http.StatusNotFound, "Subscription not found") } } @@ -255,13 +272,79 @@ func (m *XappManager) updateSubscription(w http.ResponseWriter, r *http.Request) func (m *XappManager) notifyClients() { xapps, err := m.helm.StatusAll() if err != nil { - mdclog(MdclogInfo, "Couldn't fetch xapps status information"+err.Error()) + Logger.Info("Couldn't fetch xapps status information: %v", err.Error()) return } m.sd.notifyClients(xapps, "updated") } +func (m *XappManager) getConfig(w http.ResponseWriter, r *http.Request) { + cfg := m.cm.UploadConfig() + respondWithJSON(w, http.StatusOK, cfg) +} + +func (m *XappManager) createConfig(w http.ResponseWriter, r *http.Request) { + var c XAppConfig + if parseConfig(w, r, &c) != nil { + return + } + + if errList, err := m.cm.CreateConfigMap(c); err != nil { + if err.Error() != "Validation failed!" { + respondWithError(w, http.StatusInternalServerError, err.Error()) + } else { + respondWithJSON(w, http.StatusUnprocessableEntity, errList) + } + return + } + respondWithJSON(w, http.StatusCreated, c.Metadata) +} + +func (m *XappManager) updateConfig(w http.ResponseWriter, r *http.Request) { + var c XAppConfig + if parseConfig(w, r, &c) != nil { + return + } + + if errList, err := m.cm.UpdateConfigMap(c); err != nil { + if err.Error() != "Validation failed!" { + respondWithError(w, http.StatusInternalServerError, err.Error()) + } else { + respondWithJSON(w, http.StatusInternalServerError, errList) + } + return + } + respondWithJSON(w, http.StatusOK, c.Metadata) +} + +func (m *XappManager) deleteSingleConfig(w http.ResponseWriter, r *http.Request) { + xappName, ok := getResourceId(r, w, "name") + if ok != true { + return + } + + md := ConfigMetadata{Name: xappName, Namespace: m.cm.GetNamespace(""), ConfigName: xappName + "-appconfig"} + m.delConfig(w, XAppConfig{Metadata: md}) +} + +func (m *XappManager) deleteConfig(w http.ResponseWriter, r *http.Request) { + var c XAppConfig + if parseConfig(w, r, &c) != nil { + return + } + + m.delConfig(w, c) +} + +func (m *XappManager) delConfig(w http.ResponseWriter, c XAppConfig) { + if _, err := m.cm.DeleteConfigMap(c); err != nil { + respondWithError(w, http.StatusInternalServerError, err.Error()) + return + } + respondWithJSON(w, http.StatusNoContent, nil) +} + // Helper functions func respondWithError(w http.ResponseWriter, code int, message string) { respondWithJSON(w, code, map[string]string{"error": message}) @@ -278,9 +361,20 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { func getResourceId(r *http.Request, w http.ResponseWriter, pattern string) (id string, ok bool) { if id, ok = mux.Vars(r)[pattern]; ok != true { - mdclog(MdclogErr, "Couldn't resolve name/id from the request URL") + Logger.Error("Couldn't resolve name/id from the request URL") respondWithError(w, http.StatusMethodNotAllowed, "Couldn't resolve name/id from the request URL") return } return } + +func parseConfig(w http.ResponseWriter, r *http.Request, req *XAppConfig) error { + if r.Body == nil || json.NewDecoder(r.Body).Decode(&req) != nil { + Logger.Error("Invalid request payload - url=%s", r.URL.RequestURI()) + respondWithError(w, http.StatusMethodNotAllowed, "Invalid request payload") + return errors.New("Invalid payload") + } + defer r.Body.Close() + + return nil +}