blob: 46e81f633fbba0d7876e7d9474f59600246ca037 [file] [log] [blame]
Mohamed Abukar2e78e422019-06-02 11:45:52 +03001/*
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
20package xapp
21
22import (
23 "encoding/json"
24 "github.com/gorilla/mux"
wahidw413abf52020-12-15 12:17:09 +000025 "github.com/spf13/viper"
Mohamed Abukarf4668932020-09-15 09:40:07 +030026 "io/ioutil"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030027 "net/http"
wahidw413abf52020-12-15 12:17:09 +000028 "os"
29
30 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030031)
32
33const (
wahidw413abf52020-12-15 12:17:09 +000034 ReadyURL = "/ric/v1/health/ready"
35 AliveURL = "/ric/v1/health/alive"
36 ConfigURL = "/ric/v1/cm/{name}"
37 AppConfigURL = "/ric/v1/config"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030038)
39
40type StatusCb func() bool
41
42type Router struct {
43 router *mux.Router
44 cbMap []StatusCb
45}
46
47func 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")
Mohamed Abukarf4668932020-09-15 09:40:07 +030056 r.InjectRoute(ConfigURL, configHandler, "POST")
wahidw413abf52020-12-15 12:17:09 +000057 r.InjectRoute(AppConfigURL, appconfigHandler, "GET")
Mohamed Abukar2e78e422019-06-02 11:45:52 +030058
59 return r
60}
61
62func (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())
Mohamed Abukar9cfde092020-04-28 17:11:33 +030065 if req.URL.RequestURI() == AliveURL || r.CheckStatus() {
Mohamed Abukar2e78e422019-06-02 11:45:52 +030066 inner.ServeHTTP(w, req)
67 } else {
68 respondWithJSON(w, http.StatusServiceUnavailable, nil)
69 }
70 })
71}
72
73func (r *Router) InjectRoute(url string, handler http.HandlerFunc, method string) *mux.Route {
Juha Hyttinen5bd72732020-08-14 11:38:06 +030074 return r.router.Path(url).HandlerFunc(r.serviceChecker(handler)).Methods(method)
Mohamed Abukar2e78e422019-06-02 11:45:52 +030075}
76
77func (r *Router) InjectQueryRoute(url string, h http.HandlerFunc, m string, q ...string) *mux.Route {
Juha Hyttinen5bd72732020-08-14 11:38:06 +030078 return r.router.Path(url).HandlerFunc(r.serviceChecker(h)).Methods(m).Queries(q...)
79}
80
81func (r *Router) InjectRoutePrefix(prefix string, handler http.HandlerFunc) *mux.Route {
82 return r.router.PathPrefix(prefix).HandlerFunc(r.serviceChecker(handler))
Mohamed Abukar2e78e422019-06-02 11:45:52 +030083}
84
85func (r *Router) InjectStatusCb(f StatusCb) {
86 r.cbMap = append(r.cbMap, f)
87}
88
89func (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
100func readyHandler(w http.ResponseWriter, r *http.Request) {
101 respondWithJSON(w, http.StatusOK, nil)
102}
103
104func aliveHandler(w http.ResponseWriter, r *http.Request) {
105 respondWithJSON(w, http.StatusOK, nil)
106}
107
Mohamed Abukarf4668932020-09-15 09:40:07 +0300108func 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
Mohamed Abukar2e78e422019-06-02 11:45:52 +0300131func 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}
wahidw413abf52020-12-15 12:17:09 +0000139
140func 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}