Some code refactoring, etc. 85/5385/2 v0.7.1
authorMohamed Abukar <abukar.mohamed@nokia.com>
Wed, 30 Dec 2020 15:48:12 +0000 (17:48 +0200)
committerMohamed Abukar <abukar.mohamed@nokia.com>
Thu, 31 Dec 2020 07:14:00 +0000 (09:14 +0200)
Change-Id: I4d3e4a38fcdeab11fa846c3b7ec16d998fe29180
Signed-off-by: Mohamed Abukar <abukar.mohamed@nokia.com>
pkg/xapp/restapi.go
pkg/xapp/types.go
pkg/xapp/xapp.go
pkg/xapp/xapp_test.go

index 46e81f6..e335c08 100755 (executable)
@@ -37,6 +37,10 @@ const (
        AppConfigURL = "/ric/v1/config"
 )
 
+var (
+       healthReady bool
+)
+
 type StatusCb func() bool
 
 type Router struct {
@@ -97,7 +101,12 @@ func (r *Router) CheckStatus() (status bool) {
        return
 }
 
+func IsHealthProbeReady() bool {
+       return healthReady
+}
+
 func readyHandler(w http.ResponseWriter, r *http.Request) {
+       healthReady = true
        respondWithJSON(w, http.StatusOK, nil)
 }
 
index b6fc49b..c9fe1ec 100755 (executable)
@@ -81,3 +81,14 @@ type PortData struct {
        Policies          []int
        MaxRetryOnFailure int
 }
+
+// @todo: read these from config or somewhere else
+const (
+       SERVICE_HTTP    = "SERVICE_%s_%s_HTTP_PORT"
+       SERVICE_RMR     = "SERVICE_%s_%s_RMR_PORT"
+       CONFIG_PATH     = "/ric/v1/config"
+       REGISTER_PATH   = "http://service-%s-appmgr-http.%s:8080/ric/v1/register"
+       DEREGISTER_PATH = "http://service-%s-appmgr-http.%s:8080/ric/v1/deregister"
+       DEFAULT_PLT_NS  = "ricplt"
+       DEFAULT_XAPP_NS = "ricxapp"
+)
index 2bf7799..1f02285 100755 (executable)
@@ -24,7 +24,6 @@ import (
        "encoding/json"
        "fmt"
        "github.com/spf13/viper"
-       "io/ioutil"
        "net/http"
        "os"
        "os/signal"
@@ -71,112 +70,109 @@ func XappReadyCb(params interface{}) {
        }
 }
 
-func xappShutdownCb() {
-       SendDeregistermsg()
-       Logger.Info("Wait for xapp to get unregistered")
-       time.Sleep(10 * time.Second)
+func SetShutdownCB(cb ShutdownCB) {
+       shutdownCb = cb
 }
 
-func registerxapp() {
-       var (
-               retries int = 10
-       )
-       for retries > 0 {
-               name, _ := os.Hostname()
-               httpservicename := "SERVICE_RICXAPP_" + strings.ToUpper(name) + "_HTTP_PORT"
-               httpendpoint := os.Getenv(strings.Replace(httpservicename, "-", "_", -1))
-               urlString := strings.Split(httpendpoint, "//")
-               // Added this check to make UT pass
-               if urlString[0] == "" {
-                       return
-               }
-               resp, err := http.Get(fmt.Sprintf("http://%s/ric/v1/health/ready", urlString[1]))
-               retries -= 1
+func XappShutdownCb() {
+       if err := doDeregister(); err != nil {
+               Logger.Info("xApp deregistration failed: %v, terminating ungracefully!", err)
+       } else {
+               Logger.Info("xApp deregistration successfull!")
+       }
+
+       if shutdownCb != nil {
+               shutdownCb()
+       }
+}
+
+func registerXapp() {
+       for {
                time.Sleep(5 * time.Second)
-               if err != nil {
-                       Logger.Error("Error in health check: %v", err)
+               if !IsHealthProbeReady() {
+                       Logger.Info("xApp is not ready yet, waiting ...")
+                       continue
                }
-               if err == nil {
-                       retries -= 10
-                       Logger.Info("Health Probe Success with resp.StatusCode is %v", resp.StatusCode)
-                       if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
-                               go SendRegistermsg()
-                       }
-               } else {
-                       Logger.Info("Health Probe failed, retrying...")
+
+               Logger.Info("xApp is now up and ready, continue with registration ...")
+               if err := doRegister(); err == nil {
+                       Logger.Info("xApp registration done, proceeding with startup ...")
+                       break
                }
        }
 }
 
-func SendRegistermsg() {
-       name, _ := os.Hostname()
-       xappname := viper.GetString("name")
-       xappversion := viper.GetString("version")
+func getService(host, service string) string {
        appnamespace := os.Getenv("APP_NAMESPACE")
        if appnamespace == "" {
-               appnamespace = "ricxapp"
+               appnamespace = DEFAULT_XAPP_NS
        }
-       httpservicename := "SERVICE_" + strings.ToUpper(appnamespace) + "_" + strings.ToUpper(name) + "_HTTP_PORT"
-       rmrservicename := "SERVICE_" + strings.ToUpper(appnamespace) + "_" + strings.ToUpper(name) + "_RMR_PORT"
-       httpendpointstr := os.Getenv(strings.Replace(httpservicename, "-", "_", -1))
-       rmrendpointstr := os.Getenv(strings.Replace(rmrservicename, "-", "_", -1))
-       httpendpoint := strings.Split(httpendpointstr, "//")
-       rmrendpoint := strings.Split(rmrendpointstr, "//")
-       if httpendpoint[0] == "" || rmrendpoint[0] == "" {
-               return
+
+       svc := fmt.Sprintf(service, strings.ToUpper(appnamespace), strings.ToUpper(host))
+       url := strings.Split(os.Getenv(strings.Replace(svc, "-", "_", -1)), "//")
+       if len(url) > 1 {
+               return url[1]
        }
+       return ""
+}
 
+func getPltNamespace(envName, defVal string) string {
        pltnamespace := os.Getenv("PLT_NAMESPACE")
        if pltnamespace == "" {
-               pltnamespace = "ricplt"
+               pltnamespace = defVal
        }
 
-       configpath := "/ric/v1/config"
+       return pltnamespace
+}
+
+func doPost(pltNs, url string, msg []byte, status int) error {
+       resp, err := http.Post(fmt.Sprintf(url, pltNs, pltNs), "application/json", bytes.NewBuffer(msg))
+       if err != nil || resp == nil || resp.StatusCode != status {
+               Logger.Info("http.Post to '%s' failed with error: %v", fmt.Sprintf(url, pltNs, pltNs), err)
+               return err
+       }
+       Logger.Info("Post to '%s' done, status:%v", fmt.Sprintf(url, pltNs, pltNs), resp.Status)
+
+       return err
+}
+
+func doRegister() error {
+       host, _ := os.Hostname()
+       xappname := viper.GetString("name")
+       xappversion := viper.GetString("version")
+       pltNs := getPltNamespace("PLT_NAMESPACE", DEFAULT_PLT_NS)
+
+       httpEp, rmrEp := getService(host, SERVICE_HTTP), getService(host, SERVICE_RMR)
+       if httpEp == "" || rmrEp == "" {
+               Logger.Warn("Couldn't resolve service endpoints: httpEp=%s rmrEp=%s", httpEp, rmrEp)
+               return nil
+       }
 
        requestBody, err := json.Marshal(map[string]string{
-               "appName":         name,
-               "httpEndpoint":    httpendpoint[1],
-               "rmrEndpoint":     rmrendpoint[1],
+               "appName":         host,
+               "httpEndpoint":    httpEp,
+               "rmrEndpoint":     rmrEp,
                "appInstanceName": xappname,
                "appVersion":      xappversion,
-               "configPath":      configpath,
+               "configPath":      CONFIG_PATH,
        })
 
        if err != nil {
-               Logger.Info("Error while compiling request to appmgr: %v", err)
-       } else {
-               url := fmt.Sprintf("http://service-%v-appmgr-http.%v:8080/ric/v1/register", pltnamespace, pltnamespace)
-               resp, err := http.Post(url, "application/json", bytes.NewBuffer(requestBody))
-               Logger.Info(" Resp is %v", resp)
-               if err != nil {
-                       Logger.Info("Error  compiling request to appmgr: %v", err)
-               }
-               Logger.Info("Registering request sent. Response received is :%v", resp)
-
-               if resp != nil {
-                       body, err := ioutil.ReadAll(resp.Body)
-                       Logger.Info("Post body is %v", resp.Body)
-                       if err != nil {
-                               Logger.Info("rsp: Error  compiling request to appmgr: %v", string(body))
-                       }
-                       defer resp.Body.Close()
-               }
+               Logger.Error("json.Marshal failed with error: %v", err)
+               return err
        }
+
+       return doPost(pltNs, REGISTER_PATH, requestBody, http.StatusCreated)
 }
 
-func SendDeregistermsg() {
+func doDeregister() error {
+       if !IsHealthProbeReady() {
+               return nil
+       }
 
        name, _ := os.Hostname()
        xappname := viper.GetString("name")
-
-       appnamespace := os.Getenv("APP_NAMESPACE")
-       if appnamespace == "" {
-               appnamespace = "ricxapp"
-       }
-       pltnamespace := os.Getenv("PLT_NAMESPACE")
-       if pltnamespace == "" {
-               pltnamespace = "ricplt"
-       }
+       pltNs := getPltNamespace("PLT_NAMESPACE", DEFAULT_PLT_NS)
 
        requestBody, err := json.Marshal(map[string]string{
                "appName":         name,
@@ -184,29 +180,11 @@ func SendDeregistermsg() {
        })
 
        if err != nil {
-               Logger.Info("Error while compiling request to appmgr: %v", err)
-       } else {
-               url := fmt.Sprintf("http://service-%v-appmgr-http.%v:8080/ric/v1/deregister", pltnamespace, pltnamespace)
-               resp, err := http.Post(url, "application/json", bytes.NewBuffer(requestBody))
-               Logger.Info(" Resp is %v", resp)
-               if err != nil {
-                       Logger.Info("Error  compiling request to appmgr: %v", err)
-               }
-               Logger.Info("Deregistering request sent. Response received is :%v", resp)
-
-               if resp != nil {
-                       body, err := ioutil.ReadAll(resp.Body)
-                       Logger.Info("Post body is %v", resp.Body)
-                       if err != nil {
-                               Logger.Info("rsp: Error  compiling request to appmgr: %v", string(body))
-                       }
-                       defer resp.Body.Close()
-               }
+               Logger.Error("json.Marshal failed with error: %v", err)
+               return err
        }
-}
 
-func SetShutdownCB(cb ShutdownCB) {
-       shutdownCb = cb
+       return doPost(pltNs, DEREGISTER_PATH, requestBody, http.StatusNoContent)
 }
 
 func InstallSignalHandler() {
@@ -230,9 +208,7 @@ func InstallSignalHandler() {
 
                                        // close callback
                                        go func() {
-                                               if shutdownCb != nil {
-                                                       shutdownCb()
-                                               }
+                                               XappShutdownCb()
                                                sentry <- struct{}{}
                                        }()
                                        select {
@@ -280,15 +256,18 @@ func init() {
 
 func RunWithParams(c MessageConsumer, sdlcheck bool) {
        Rmr = NewRMRClient()
+
        Rmr.SetReadyCB(XappReadyCb, nil)
-       SetShutdownCB(xappShutdownCb)
+
        host := fmt.Sprintf(":%d", GetPortData("http").Port)
        go http.ListenAndServe(host, Resource.router)
        Logger.Info(fmt.Sprintf("Xapp started, listening on: %s", host))
+
        if sdlcheck {
                Sdl.TestConnection()
        }
-       go registerxapp()
+       go registerXapp()
+
        Rmr.Start(c)
 }
 
index 173b57f..388d079 100755 (executable)
@@ -430,14 +430,14 @@ func TestappconfigHandler(t *testing.T) {
        executeRequest(req, handleFunc)
 }
 
-func TestSendRegistermsg(t *testing.T) {
-       Logger.Error("CASE: TestSendRegistermsg")
-       SendRegistermsg()
+func TestRegisterXapp(t *testing.T) {
+       Logger.Error("CASE: TestRegisterXapp")
+       doRegister()
 }
 
-func TestSendDeregistermsg(t *testing.T) {
-       Logger.Error("CASE: TestSendDeregistermsg")
-       SendDeregistermsg()
+func TestDeregisterXapp(t *testing.T) {
+       Logger.Error("CASE: TestDeregisterXapp")
+       doDeregister()
 }
 
 func TestMisc(t *testing.T) {