2 ==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
24 "github.com/gorilla/mux"
25 "github.com/spf13/viper"
32 func (m *XappManager) Initialize(h Helmer) *mux.Router {
33 m.sd = SubscriptionDispatcher{}
36 m.router = mux.NewRouter().StrictSlash(true)
38 resources := []Resource{
39 Resource{"GET", "/ric/v1/health", m.getHealthStatus},
41 Resource{"GET", "/ric/v1/xapps", m.getAllXapps},
42 Resource{"GET", "/ric/v1/xapps/{name}", m.getXappByName},
43 Resource{"GET", "/ric/v1/xapps/{name}/instances/{id}", m.getXappInstanceByName},
44 Resource{"POST", "/ric/v1/xapps", m.deployXapp},
45 Resource{"DELETE", "/ric/v1/xapps/{name}", m.undeployXapp},
47 Resource{"GET", "/ric/v1/subscriptions", m.getSubscriptions},
48 Resource{"POST", "/ric/v1/subscriptions", m.addSubscription},
49 Resource{"GET", "/ric/v1/subscriptions/{id}", m.getSubscription},
50 Resource{"DELETE", "/ric/v1/subscriptions/{id}", m.deleteSubscription},
51 Resource{"PUT", "/ric/v1/subscriptions/{id}", m.updateSubscription},
54 for _, resource := range resources {
55 handler := Logger(resource.HandlerFunc)
56 m.router.Methods(resource.Method).Path(resource.Url).Handler(handler)
63 func (m *XappManager) getHealthStatus(w http.ResponseWriter, r *http.Request) {
64 respondWithJSON(w, http.StatusOK, nil)
68 func (m *XappManager) Run() {
69 host := viper.GetString("local.host")
73 log.Printf("Xapp manager started ... serving on %s\n", host)
75 log.Fatal(http.ListenAndServe(host, m.router))
78 func (m *XappManager) getXappByName(w http.ResponseWriter, r *http.Request) {
79 xappName, ok := getResourceId(r, w, "name")
84 if xapp, err := m.helm.Status(xappName); err == nil {
85 respondWithJSON(w, http.StatusOK, xapp)
87 respondWithError(w, http.StatusNotFound, err.Error())
91 func (m *XappManager) getXappInstanceByName(w http.ResponseWriter, r *http.Request) {
92 xappName, ok := getResourceId(r, w, "name")
97 xapp, err := m.helm.Status(xappName)
99 respondWithError(w, http.StatusNotFound, err.Error())
103 xappInstanceName, ok := getResourceId(r, w, "id")
108 for _, v := range xapp.Instances {
109 if v.Name == xappInstanceName {
110 respondWithJSON(w, http.StatusOK, v)
114 mdclog(Mdclog_err, "Xapp instance not found - url=" + r.URL.RequestURI())
116 respondWithError(w, http.StatusNotFound, "Xapp instance not found")
119 func (m *XappManager) getAllXapps(w http.ResponseWriter, r *http.Request) {
120 xapps, err := m.helm.StatusAll()
122 respondWithError(w, http.StatusInternalServerError, err.Error())
126 respondWithJSON(w, http.StatusOK, xapps)
129 func (m *XappManager) deployXapp(w http.ResponseWriter, r *http.Request) {
131 mdclog(Mdclog_err, "No xapp data found in request body - url=" + r.URL.RequestURI())
132 respondWithError(w, http.StatusMethodNotAllowed, "No xapp data!")
137 if err := json.NewDecoder(r.Body).Decode(&xapp); err != nil {
138 mdclog(Mdclog_err, "Invalid xapp data in request body - url=" + r.URL.RequestURI())
139 respondWithError(w, http.StatusMethodNotAllowed, "Invalid xapp data!")
144 xapp, err := m.helm.Install(xapp.Name)
146 respondWithError(w, http.StatusInternalServerError, err.Error())
150 respondWithJSON(w, http.StatusCreated, xapp)
152 m.sd.Publish(xapp, EventType("created"))
155 func (m *XappManager) undeployXapp(w http.ResponseWriter, r *http.Request) {
156 xappName, ok := getResourceId(r, w, "name")
161 xapp, err := m.helm.Delete(xappName)
163 respondWithError(w, http.StatusInternalServerError, err.Error())
167 respondWithJSON(w, http.StatusNoContent, nil)
169 m.sd.Publish(xapp, EventType("deleted"))
172 // API: resthook handlers
173 func (m *XappManager) getSubscriptions(w http.ResponseWriter, r *http.Request) {
174 respondWithJSON(w, http.StatusOK, m.sd.GetAll())
177 func (m *XappManager) getSubscription(w http.ResponseWriter, r *http.Request) {
178 if id, ok := getResourceId(r, w, "id"); ok == true {
179 if s, ok := m.sd.Get(id); ok {
180 respondWithJSON(w, http.StatusOK, s)
182 mdclog(Mdclog_err, "Subscription not found - url=" + r.URL.RequestURI())
183 respondWithError(w, http.StatusNotFound, "Subscription not found")
188 func (m *XappManager) deleteSubscription(w http.ResponseWriter, r *http.Request) {
189 if id, ok := getResourceId(r, w, "id"); ok == true {
190 if _, ok := m.sd.Delete(id); ok {
191 respondWithJSON(w, http.StatusNoContent, nil)
193 mdclog(Mdclog_err, "Subscription not found - url=" + r.URL.RequestURI())
194 respondWithError(w, http.StatusNotFound, "Subscription not found")
199 func (m *XappManager) addSubscription(w http.ResponseWriter, r *http.Request) {
200 var req SubscriptionReq
201 if r.Body == nil || json.NewDecoder(r.Body).Decode(&req) != nil {
202 mdclog(Mdclog_err, "Invalid request payload - url=" + r.URL.RequestURI())
203 respondWithError(w, http.StatusMethodNotAllowed, "Invalid request payload")
208 respondWithJSON(w, http.StatusCreated, m.sd.Add(req))
211 func (m *XappManager) updateSubscription(w http.ResponseWriter, r *http.Request) {
212 if id, ok := getResourceId(r, w, "id"); ok == true {
213 var req SubscriptionReq
214 if r.Body == nil || json.NewDecoder(r.Body).Decode(&req) != nil {
215 mdclog(Mdclog_err, "Invalid request payload - url=" + r.URL.RequestURI())
216 respondWithError(w, http.StatusMethodNotAllowed, "Invalid request payload")
221 if s, ok := m.sd.Update(id, req); ok {
222 respondWithJSON(w, http.StatusOK, s)
224 mdclog(Mdclog_err, "Subscription not found - url=" + r.URL.RequestURI())
225 respondWithError(w, http.StatusNotFound, "Subscription not found")
231 func respondWithError(w http.ResponseWriter, code int, message string) {
232 respondWithJSON(w, code, map[string]string{"error": message})
235 func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
236 w.Header().Set("Content-Type", "application/json")
239 response, _ := json.Marshal(payload)
244 func getResourceId(r *http.Request, w http.ResponseWriter, pattern string) (id string, ok bool) {
245 if id, ok = mux.Vars(r)[pattern]; ok != true {
246 mdclog(Mdclog_err, "Couldn't resolve name/id from the request URL")
247 respondWithError(w, http.StatusMethodNotAllowed, "Couldn't resolve name/id from the request URL")