46e81f633fbba0d7876e7d9474f59600246ca037
[ric-plt/xapp-frame.git] / pkg / xapp / restapi.go
1 /*
2 ==================================================================================
3   Copyright (c) 2019 AT&T Intellectual Property.
4   Copyright (c) 2019 Nokia
5
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
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
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 ==================================================================================
18 */
19
20 package xapp
21
22 import (
23         "encoding/json"
24         "github.com/gorilla/mux"
25         "github.com/spf13/viper"
26         "io/ioutil"
27         "net/http"
28         "os"
29
30         "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
31 )
32
33 const (
34         ReadyURL     = "/ric/v1/health/ready"
35         AliveURL     = "/ric/v1/health/alive"
36         ConfigURL    = "/ric/v1/cm/{name}"
37         AppConfigURL = "/ric/v1/config"
38 )
39
40 type StatusCb func() bool
41
42 type Router struct {
43         router *mux.Router
44         cbMap  []StatusCb
45 }
46
47 func NewRouter() *Router {
48         r := &Router{
49                 router: mux.NewRouter().StrictSlash(true),
50                 cbMap:  make([]StatusCb, 0),
51         }
52
53         // Inject default routes for health probes
54         r.InjectRoute(ReadyURL, readyHandler, "GET")
55         r.InjectRoute(AliveURL, aliveHandler, "GET")
56         r.InjectRoute(ConfigURL, configHandler, "POST")
57         r.InjectRoute(AppConfigURL, appconfigHandler, "GET")
58
59         return r
60 }
61
62 func (r *Router) serviceChecker(inner http.HandlerFunc) http.HandlerFunc {
63         return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
64                 Logger.Info("restapi: method=%s url=%s", req.Method, req.URL.RequestURI())
65                 if req.URL.RequestURI() == AliveURL || r.CheckStatus() {
66                         inner.ServeHTTP(w, req)
67                 } else {
68                         respondWithJSON(w, http.StatusServiceUnavailable, nil)
69                 }
70         })
71 }
72
73 func (r *Router) InjectRoute(url string, handler http.HandlerFunc, method string) *mux.Route {
74         return r.router.Path(url).HandlerFunc(r.serviceChecker(handler)).Methods(method)
75 }
76
77 func (r *Router) InjectQueryRoute(url string, h http.HandlerFunc, m string, q ...string) *mux.Route {
78         return r.router.Path(url).HandlerFunc(r.serviceChecker(h)).Methods(m).Queries(q...)
79 }
80
81 func (r *Router) InjectRoutePrefix(prefix string, handler http.HandlerFunc) *mux.Route {
82         return r.router.PathPrefix(prefix).HandlerFunc(r.serviceChecker(handler))
83 }
84
85 func (r *Router) InjectStatusCb(f StatusCb) {
86         r.cbMap = append(r.cbMap, f)
87 }
88
89 func (r *Router) CheckStatus() (status bool) {
90         if len(r.cbMap) == 0 {
91                 return true
92         }
93
94         for _, f := range r.cbMap {
95                 status = f()
96         }
97         return
98 }
99
100 func readyHandler(w http.ResponseWriter, r *http.Request) {
101         respondWithJSON(w, http.StatusOK, nil)
102 }
103
104 func aliveHandler(w http.ResponseWriter, r *http.Request) {
105         respondWithJSON(w, http.StatusOK, nil)
106 }
107
108 func configHandler(w http.ResponseWriter, r *http.Request) {
109         xappName := mux.Vars(r)["name"]
110         if xappName == "" || r.Body == nil {
111                 respondWithJSON(w, http.StatusBadRequest, nil)
112                 return
113         }
114         defer r.Body.Close()
115
116         body, err := ioutil.ReadAll(r.Body)
117         if err != nil {
118                 Logger.Error("ioutil.ReadAll failed: %v", err)
119                 respondWithJSON(w, http.StatusInternalServerError, nil)
120                 return
121         }
122
123         if err := PublishConfigChange(xappName, string(body)); err != nil {
124                 respondWithJSON(w, http.StatusInternalServerError, nil)
125                 return
126         }
127
128         respondWithJSON(w, http.StatusOK, nil)
129 }
130
131 func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
132         w.Header().Set("Content-Type", "application/json")
133         w.WriteHeader(code)
134         if payload != nil {
135                 response, _ := json.Marshal(payload)
136                 w.Write(response)
137         }
138 }
139
140 func appconfigHandler(w http.ResponseWriter, r *http.Request) {
141
142         Logger.Info("Inside appconfigHandler")
143
144         var appconfig models.XappConfigList
145         var metadata models.ConfigMetadata
146         var xappconfig models.XAppConfig
147         name := viper.GetString("name")
148         configtype := "json"
149         metadata.XappName = &name
150         metadata.ConfigType = &configtype
151
152         configFile, err := os.Open("/opt/ric/config/config-file.json")
153         if err != nil {
154                 Logger.Error("Cannot open config file: %v", err)
155                 respondWithJSON(w, http.StatusInternalServerError, nil)
156                 // return nil,errors.New("Could Not parse the config file")
157         }
158
159         body, err := ioutil.ReadAll(configFile)
160
161         defer configFile.Close()
162
163         xappconfig.Metadata = &metadata
164         xappconfig.Config = string(body)
165
166         appconfig = append(appconfig, &xappconfig)
167
168         respondWithJSON(w, http.StatusOK, appconfig)
169
170         //return appconfig,nil
171 }