From: subhash kumar singh Date: Wed, 16 Nov 2022 18:02:21 +0000 (+0000) Subject: Implement health check for xApp X-Git-Tag: 2.0.0~4 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=c1e4374fb522f55e9263dd2deca3d244e709ebdf;p=ric-plt%2Fricdms.git Implement health check for xApp Implement API to query the health status of xApp. Signed-off-by: subhash kumar singh Change-Id: Ie0b922fa72af9d174766e8cf947cebfc4aa3ec76 --- diff --git a/config/config-test.yaml b/config/config-test.yaml index b2b2461..4b41e89 100644 --- a/config/config-test.yaml +++ b/config/config-test.yaml @@ -18,4 +18,5 @@ mock-server: "127.0.0.1:9191" getCharts-url: "http://127.0.0.1:9191" download-charts-url-format: "http://127.0.0.1:9191/helmrepo/charts/%s-%s.tgz" getCharts-by-name-url: "http://127.0.0.1:9191/helmrepo/api/charts/%s" -getCharts-by-name-and-version-url: "http://127.0.0.1:9191/helmrepo/api/charts/%s/%s" \ No newline at end of file +getCharts-by-name-and-version-url: "http://127.0.0.1:9191/helmrepo/api/charts/%s/%s" +getXappHealth-url: "http://127.0.0.1:9191/ric/v1/health/alive/%s/%s" \ No newline at end of file diff --git a/config/config.yaml b/config/config.yaml index 861912d..36604be 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -17,4 +17,5 @@ onborder-url: "http://service-ricplt-xapp-onboarder-http.ricplt:8888/api/v1/onbo getCharts-url: "http://service-ricplt-xapp-onboarder-http.ricplt:8080/api/charts" download-charts-url-format: "http://service-ricplt-xapp-onboarder-http.ricplt:8080/charts/%s-%s.tgz" getCharts-by-name-url: "http://172.17.0.1:9100/helmrepo/api/charts/%s" -getCharts-by-name-and-version-url: "http://172.17.0.1:9100/helmrepo/api/charts/%s/%s" \ No newline at end of file +getCharts-by-name-and-version-url: "http://172.17.0.1:9100/helmrepo/api/charts/%s/%s" +getXappHealth-url: "http://service-ricxqapp-%s-http.%s:8080/ric/v1/health/alive" \ No newline at end of file diff --git a/pkg/config/conf.go b/pkg/config/conf.go index c24500f..6c54b2b 100644 --- a/pkg/config/conf.go +++ b/pkg/config/conf.go @@ -35,6 +35,7 @@ type Conf struct { GetChartsByNameAndVersionURL string `yaml:"getCharts-by-name-and-version-url"` DownloadChartURLFormat string `yaml:"download-charts-url-format"` MockServer string `yaml:"mock-server"` + GETxAPPHealthURL string `yaml:"getXappHealth-url"` } func ReadConfiguration(configFile string) (c *Conf, err error) { diff --git a/pkg/health/health.go b/pkg/health/health.go index d007da4..3046559 100644 --- a/pkg/health/health.go +++ b/pkg/health/health.go @@ -20,7 +20,13 @@ package health -import "gerrit.o-ran-sc.org/r/ric-plt/ricdms/pkg/models" +import ( + "fmt" + "net/http" + + "gerrit.o-ran-sc.org/r/ric-plt/ricdms/pkg/models" + "gerrit.o-ran-sc.org/r/ric-plt/ricdms/pkg/ricdms" +) var ( HEALTHY = "Service is running healthy" @@ -28,6 +34,7 @@ var ( type IHealthChecker interface { GetStatus() *models.Status + GetxAppStatus(appName, namespace string) *models.Status } type HealthChecker struct { @@ -41,3 +48,20 @@ func (h *HealthChecker) GetStatus() *models.Status { Status: &HEALTHY, } } + +func (h *HealthChecker) GetxAppStatus(appName, namespace string) *models.Status { + resp, err := http.Get(fmt.Sprintf(ricdms.Config.GETxAPPHealthURL, appName, namespace)) + if err != nil { + ricdms.Logger.Error("Received error while fetching health info: %v", err) + return nil + } + + if resp.StatusCode != http.StatusOK { + ricdms.Logger.Error("xApp is not healthy (http status=%s)", resp.Status) + return nil + } + + return &models.Status{ + Status: &HEALTHY, + } +} diff --git a/pkg/restful/restful.go b/pkg/restful/restful.go index 46a4387..b17c7ad 100644 --- a/pkg/restful/restful.go +++ b/pkg/restful/restful.go @@ -70,6 +70,12 @@ func (r *Restful) setupHandler() { return resp }) + api.HealthGetHealthcheckXAppXAppNameNamespaceNamespaceHandler = health.GetHealthcheckXAppXAppNameNamespaceNamespaceHandlerFunc(func(param health.GetHealthcheckXAppXAppNameNamespaceNamespaceParams) middleware.Responder { + ricdms.Logger.Debug("==> Healthcheck for xApp is invoked") + resp := r.rh.GetxAppHealth(param.XAppName, param.Namespace) + return resp + }) + api.OnboardPostOnboardxAppsHandler = onboard.PostOnboardxAppsHandlerFunc(func(poap onboard.PostOnboardxAppsParams) middleware.Responder { ricdms.Logger.Debug("==> onboard API invoked.") resp := r.rh.OnBoard(poap.Body) diff --git a/pkg/resthooks/resthooks.go b/pkg/resthooks/resthooks.go index 7cc8efe..e0d7df2 100644 --- a/pkg/resthooks/resthooks.go +++ b/pkg/resthooks/resthooks.go @@ -47,6 +47,15 @@ func (rh *Resthook) GetDMSHealth() (resp middleware.Responder) { return health.NewGetHealthCheckOK().WithPayload(rh.HealthChecker.GetStatus()) } +func (rh *Resthook) GetxAppHealth(appname, namespace string) (resp middleware.Responder) { + ricdms.Logger.Debug("Healthchecker: xApp health check is initiated") + status := rh.HealthChecker.GetxAppStatus(appname, namespace) + if status == nil { + return health.NewGetHealthCheckInternalServerError() + } + return health.NewGetHealthCheckOK().WithPayload(status) +} + func (rh *Resthook) OnBoard(params *models.Descriptor) (resp middleware.Responder) { ricdms.Logger.Debug("onboarder: invoked") return rh.Onboarder.Onboard(params) diff --git a/pkg/resthooks/resthooks_test.go b/pkg/resthooks/resthooks_test.go index 7b65f15..40b32ac 100644 --- a/pkg/resthooks/resthooks_test.go +++ b/pkg/resthooks/resthooks_test.go @@ -42,7 +42,6 @@ import ( h "gerrit.o-ran-sc.org/r/ric-plt/ricdms/pkg/restapi/operations/health" "gerrit.o-ran-sc.org/r/ric-plt/ricdms/pkg/ricdms" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" ) var rh *Resthook @@ -55,7 +54,7 @@ func TestMain(m *testing.M) { } ricdms.Init() rh = &Resthook{ - HealthChecker: HealthCheckerMock{}, + HealthChecker: health.NewHealthChecker(), Onboarder: onboard.NewOnboarder(), ChartMgr: ch.NewChartmgr(), DeployMgr: deploy.NewDeploymentManager(), @@ -78,6 +77,54 @@ func TestHealth(t *testing.T) { } } +func TestHealthxAppFail(t *testing.T) { + svr := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(501) + })) + + svr.Listener.Close() + svr.Listener, _ = net.Listen("tcp", ricdms.Config.MockServer) + + svr.Start() + defer svr.Close() + + resp := rh.GetxAppHealth("test", "test") + switch resp.(type) { + case *h.GetHealthCheckOK: + assert.Fail(t, "Health check should not be okay: %v", resp) + + case *h.GetHealthCheckInternalServerError: + break + + default: + assert.Fail(t, "Unknown type of resp : %v", resp) + } +} + +func TestHealthxApp(t *testing.T) { + svr := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + + svr.Listener.Close() + svr.Listener, _ = net.Listen("tcp", ricdms.Config.MockServer) + + svr.Start() + defer svr.Close() + + resp := rh.GetxAppHealth("test", "test") + switch resp.(type) { + case *h.GetHealthCheckOK: + assert.Equal(t, successStatus, resp.(*h.GetHealthCheckOK).Payload) + + case *h.GetHealthCheckInternalServerError: + assert.Fail(t, "Internal Server generated: %v", resp) + + default: + assert.Fail(t, "Unknown type of resp : %v", resp) + } +} + func TestOnboard(t *testing.T) { xApp := &models.Descriptor{ Config: "SAMPLE_CONFIGURATION", @@ -219,11 +266,3 @@ func TestUninstallxApp(t *testing.T) { assert.Fail(t, "response type did not match actual: %T", response) } } - -type HealthCheckerMock struct { - mock.Mock -} - -func (h HealthCheckerMock) GetStatus() *models.Status { - return successStatus -}