[RIC-297] Update GNB Request REST API - Validation

Change-Id: I6ed0e435af31dbc6aaeee67653277525ad930020
Signed-off-by: idanshal <idan.shalom@intl.att.com>
diff --git a/E2Manager/controllers/nodeb_controller.go b/E2Manager/controllers/nodeb_controller.go
index 7b8a86f..90b9311 100644
--- a/E2Manager/controllers/nodeb_controller.go
+++ b/E2Manager/controllers/nodeb_controller.go
@@ -17,7 +17,6 @@
 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
 //  platform project (RICP).
 
-
 package controllers
 
 import (
@@ -26,6 +25,9 @@
 	"e2mgr/models"
 	"e2mgr/providers/httpmsghandlerprovider"
 	"encoding/json"
+	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+	"github.com/golang/protobuf/jsonpb"
+	"github.com/golang/protobuf/proto"
 	"github.com/gorilla/mux"
 	"io"
 	"io/ioutil"
@@ -45,6 +47,7 @@
 	X2Setup(writer http.ResponseWriter, r *http.Request)
 	EndcSetup(writer http.ResponseWriter, r *http.Request)
 	GetNodeb(writer http.ResponseWriter, r *http.Request)
+	UpdateGnb(writer http.ResponseWriter, r *http.Request)
 	GetNodebIdList(writer http.ResponseWriter, r *http.Request)
 }
 
@@ -74,6 +77,24 @@
 	c.handleRequest(writer, &r.Header, httpmsghandlerprovider.GetNodebRequest, request, false)
 }
 
+func (c *NodebController) UpdateGnb(writer http.ResponseWriter, r *http.Request) {
+	c.logger.Infof("[Client -> E2 Manager] #NodebController.UpdateGnb - request: %v", c.prettifyRequest(r))
+	vars := mux.Vars(r)
+	ranName := vars[ParamRanName]
+
+	request := models.UpdateGnbRequest{}
+
+	gnb := entities.Gnb{}
+
+	if !c.extractRequestBodyToProto(r, &gnb, writer) {
+		return
+	}
+
+	request.Gnb = &gnb;
+	request.RanName = ranName
+	c.handleRequest(writer, &r.Header, httpmsghandlerprovider.UpdateGnbRequest, request, true)
+}
+
 func (c *NodebController) Shutdown(writer http.ResponseWriter, r *http.Request) {
 	c.logger.Infof("[Client -> E2 Manager] #NodebController.Shutdown - request: %v", c.prettifyRequest(r))
 	c.handleRequest(writer, &r.Header, httpmsghandlerprovider.ShutdownRequest, nil, false)
@@ -116,6 +137,20 @@
 	c.handleRequest(writer, &r.Header, httpmsghandlerprovider.EndcSetupRequest, request, true)
 }
 
+func (c *NodebController) extractRequestBodyToProto(r *http.Request, pb proto.Message , writer http.ResponseWriter) bool {
+	defer r.Body.Close()
+
+	err := jsonpb.Unmarshal(r.Body, pb)
+
+	if err != nil {
+		c.logger.Errorf("[Client -> E2 Manager] #NodebController.extractJsonBody - unable to extract json body - error: %s", err)
+		c.handleErrorResponse(e2managererrors.NewInvalidJsonError(), writer)
+		return false
+	}
+
+	return true
+}
+
 func (c *NodebController) extractJsonBody(r *http.Request, request models.Request, writer http.ResponseWriter) bool {
 	defer r.Body.Close()
 	body, err := ioutil.ReadAll(io.LimitReader(r.Body, LimitRequest))
@@ -136,9 +171,9 @@
 	return true
 }
 
-func (c *NodebController) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest, request models.Request, validateHeader bool) {
+func (c *NodebController) handleRequest(writer http.ResponseWriter, header *http.Header, requestName httpmsghandlerprovider.IncomingRequest, request models.Request, validateRequestHeaders bool) {
 
-	if validateHeader {
+	if validateRequestHeaders {
 
 		err := c.validateRequestHeader(header)
 		if err != nil {
diff --git a/E2Manager/controllers/nodeb_controller_test.go b/E2Manager/controllers/nodeb_controller_test.go
index 88983f4..47b4bc8 100644
--- a/E2Manager/controllers/nodeb_controller_test.go
+++ b/E2Manager/controllers/nodeb_controller_test.go
@@ -17,7 +17,6 @@
 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
 //  platform project (RICP).
 
-
 package controllers
 
 import (
@@ -51,6 +50,19 @@
 	"testing"
 )
 
+const (
+	RanName                      = "test"
+	AssociatedE2TInstanceAddress = "10.0.2.15:38000"
+	ValidationFailureJson        = "{\"errorCode\":402,\"errorMessage\":\"Validation error\"}"
+	ResourceNotFoundJson         = "{\"errorCode\":404,\"errorMessage\":\"Resource not found\"}"
+	RnibErrorJson                = "{\"errorCode\":500,\"errorMessage\":\"RNIB error\"}"
+)
+
+var (
+	ServedNrCellInformationRequiredFields = []string{"cellId", "choiceNrMode", "nrMode", "nrPci", "servedPlmns"}
+	NrNeighbourInformationRequiredFields  = []string{"nrCgi", "choiceNrMode", "nrMode", "nrPci"}
+)
+
 type controllerGetNodebTestContext struct {
 	ranName              string
 	nodebInfo            *entities.NodebInfo
@@ -66,7 +78,56 @@
 	expectedJsonResponse string
 }
 
-func  setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock) {
+type getNodebInfoResult struct {
+	nodebInfo *entities.NodebInfo
+	rnibError error
+}
+
+type controllerUpdateGnbTestContext struct {
+	getNodebInfoResult   *getNodebInfoResult
+	requestBody          map[string]interface{}
+	expectedStatusCode   int
+	expectedJsonResponse string
+}
+
+func buildNrNeighbourInformation(propToOmit string) map[string]interface{} {
+	ret := map[string]interface{}{
+		"nrCgi": "whatever",
+		"choiceNrMode": map[string]interface{}{
+			"tdd": map[string]interface{}{},
+		},
+		"nrMode": 1,
+		"nrPci":  1,
+	}
+
+	if len(propToOmit) != 0 {
+		delete(ret, propToOmit)
+	}
+
+	return ret
+}
+
+func buildServedNrCellInformation(propToOmit string) map[string]interface{} {
+	ret := map[string]interface{}{
+		"cellId": "whatever",
+		"choiceNrMode": map[string]interface{}{
+			"fdd": map[string]interface{}{},
+		},
+		"nrMode": 1,
+		"nrPci":  1,
+		"servedPlmns": []interface{}{
+			"whatever",
+		},
+	}
+
+	if len(propToOmit) != 0 {
+		delete(ret, propToOmit)
+	}
+
+	return ret
+}
+
+func setupControllerTest(t *testing.T) (*NodebController, *mocks.RnibReaderMock, *mocks.RnibWriterMock, *mocks.RmrMessengerMock, *mocks.E2TInstancesManagerMock) {
 	log := initLog(t)
 	config := configuration.ParseConfiguration()
 
@@ -110,13 +171,13 @@
 	controller, readerMock, writerMock, rmrMessengerMock, _ := setupControllerTest(t)
 
 	ranName := "test"
-	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress: "10.0.2.15:8989"}
 	readerMock.On("GetNodeb", ranName).Return(nb, nil)
 	var nbUpdated = *nb
 	nbUpdated.ConnectionAttempts = 0
 	writerMock.On("UpdateNodebInfo", &nbUpdated).Return(nil)
 
-	var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+	var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress: "10.0.2.15:8989"}
 	writerMock.On("UpdateNodebInfo", nbUpdated2).Return(nil)
 
 	payload := e2pdus.PackedX2setupRequest
@@ -141,17 +202,17 @@
 	controller, readerMock, writerMock, rmrMessengerMock, _ := setupControllerTest(t)
 
 	ranName := "test"
-	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+	nb := &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_DISCONNECTED, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, AssociatedE2TInstanceAddress: "10.0.2.15:8989"}
 	readerMock.On("GetNodeb", ranName).Return(nb, nil)
 	var nbUpdated = *nb
 	nbUpdated.ConnectionAttempts = 0
 	writerMock.On("UpdateNodebInfo", &nbUpdated).Return(nil)
 
-	var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress:"10.0.2.15:8989"}
+	var nbUpdated2 = &entities.NodebInfo{RanName: ranName, ConnectionStatus: entities.ConnectionStatus_CONNECTING, E2ApplicationProtocol: entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, ConnectionAttempts: 1, AssociatedE2TInstanceAddress: "10.0.2.15:8989"}
 	writerMock.On("UpdateNodebInfo", nbUpdated2).Return(nil)
 
 	payload := e2pdus.PackedEndcX2setupRequest
-	var xAction[]byte
+	var xAction []byte
 	msg := rmrCgo.NewMBuf(rmrCgo.RIC_ENDC_X2_SETUP_REQ, len(payload), ranName, &payload, &xAction)
 
 	rmrMessengerMock.On("SendMsg", mock.Anything, true).Return(msg, nil)
@@ -168,7 +229,7 @@
 }
 
 func TestShutdownHandlerRnibError(t *testing.T) {
-	controller, _, _, _, e2tInstancesManagerMock:= setupControllerTest(t)
+	controller, _, _, _, e2tInstancesManagerMock := setupControllerTest(t)
 	e2tInstancesManagerMock.On("GetE2TAddresses").Return([]string{}, e2managererrors.NewRnibDbError())
 
 	writer := httptest.NewRecorder()
@@ -185,7 +246,7 @@
 	controller, readerMock, _, _, _ := setupControllerTest(t)
 	writer := httptest.NewRecorder()
 	readerMock.On("GetNodeb", context.ranName).Return(context.nodebInfo, context.rnibError)
-	req, _ := http.NewRequest("GET", "/nodeb", nil)
+	req, _ := http.NewRequest(http.MethodGet, "/nodeb", nil)
 	req = mux.SetURLVars(req, map[string]string{"ranName": context.ranName})
 	controller.GetNodeb(writer, req)
 	assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode)
@@ -197,13 +258,220 @@
 	controller, readerMock, _, _, _ := setupControllerTest(t)
 	writer := httptest.NewRecorder()
 	readerMock.On("GetListNodebIds").Return(context.nodebIdList, context.rnibError)
-	req, _ := http.NewRequest("GET", "/nodeb/ids", nil)
+	req, _ := http.NewRequest(http.MethodGet, "/nodeb/ids", nil)
 	controller.GetNodebIdList(writer, req)
 	assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode)
 	bodyBytes, _ := ioutil.ReadAll(writer.Body)
 	assert.Equal(t, context.expectedJsonResponse, string(bodyBytes))
 }
 
+func controllerUpdateGnbTestExecuter(t *testing.T, context *controllerUpdateGnbTestContext) {
+	controller, readerMock, _, _, _ := setupControllerTest(t)
+	writer := httptest.NewRecorder()
+
+	if context.getNodebInfoResult != nil {
+		readerMock.On("GetNodeb", RanName).Return(context.getNodebInfoResult.nodebInfo, context.getNodebInfoResult.rnibError)
+	}
+
+	updateGnbUrl := fmt.Sprintf("/nodeb/%s/update", RanName)
+	requestBody := getJsonRequestAsBuffer(context.requestBody)
+	req, _ := http.NewRequest(http.MethodGet, updateGnbUrl, requestBody)
+	req.Header.Set("Content-Type", "application/json")
+	req = mux.SetURLVars(req, map[string]string{"ranName": RanName})
+	controller.UpdateGnb(writer, req)
+	assert.Equal(t, context.expectedStatusCode, writer.Result().StatusCode)
+	bodyBytes, _ := ioutil.ReadAll(writer.Body)
+	assert.Equal(t, context.expectedJsonResponse, string(bodyBytes))
+}
+
+func TestControllerUpdateGnbEmptyServedNrCells(t *testing.T) {
+	context := controllerUpdateGnbTestContext{
+		getNodebInfoResult: nil,
+		requestBody: map[string]interface{}{
+			"servedNrCells": []interface{}{
+			},
+		},
+		expectedStatusCode:   http.StatusBadRequest,
+		expectedJsonResponse: ValidationFailureJson,
+	}
+
+	controllerUpdateGnbTestExecuter(t, &context)
+}
+
+func TestControllerUpdateGnbMissingServedNrCellInformation(t *testing.T) {
+	context := controllerUpdateGnbTestContext{
+		getNodebInfoResult: nil,
+		requestBody: map[string]interface{}{
+			"servedNrCells": []interface{}{
+				map[string]interface{}{
+					"servedNrCellInformation": nil,
+				},
+			},
+		},
+		expectedStatusCode:   http.StatusBadRequest,
+		expectedJsonResponse: ValidationFailureJson,
+	}
+
+	controllerUpdateGnbTestExecuter(t, &context)
+}
+
+func TestControllerUpdateGnbMissingServedNrCellRequiredProp(t *testing.T) {
+
+	for _, v := range ServedNrCellInformationRequiredFields {
+		context := controllerUpdateGnbTestContext{
+			getNodebInfoResult: nil,
+			requestBody: map[string]interface{}{
+				"servedNrCells": []interface{}{
+					map[string]interface{}{
+						"servedNrCellInformation": buildServedNrCellInformation(v),
+					},
+				},
+			},
+			expectedStatusCode:   http.StatusBadRequest,
+			expectedJsonResponse: ValidationFailureJson,
+		}
+
+		controllerUpdateGnbTestExecuter(t, &context)
+	}
+}
+
+func TestControllerUpdateGnbMissingServedNrCellFddOrTdd(t *testing.T) {
+
+	servedNrCellInformation := buildServedNrCellInformation("")
+	servedNrCellInformation["choiceNrMode"] = map[string]interface{}{}
+
+	context := controllerUpdateGnbTestContext{
+		getNodebInfoResult: nil,
+		requestBody: map[string]interface{}{
+			"servedNrCells": []interface{}{
+				map[string]interface{}{
+					"servedNrCellInformation": servedNrCellInformation,
+				},
+			},
+		},
+		expectedStatusCode:   http.StatusBadRequest,
+		expectedJsonResponse: ValidationFailureJson,
+	}
+
+	controllerUpdateGnbTestExecuter(t, &context)
+}
+
+func TestControllerUpdateGnbMissingNeighbourInfoFddOrTdd(t *testing.T) {
+
+	nrNeighbourInfo := buildNrNeighbourInformation("")
+	nrNeighbourInfo["choiceNrMode"] = map[string]interface{}{}
+
+	context := controllerUpdateGnbTestContext{
+		getNodebInfoResult: nil,
+		requestBody: map[string]interface{}{
+			"servedNrCells": []interface{}{
+				map[string]interface{}{
+					"servedNrCellInformation": buildServedNrCellInformation(""),
+					"nrNeighbourInfos":        []interface{}{
+						nrNeighbourInfo,
+					},
+				},
+			},
+		},
+		expectedStatusCode:   http.StatusBadRequest,
+		expectedJsonResponse: ValidationFailureJson,
+	}
+
+	controllerUpdateGnbTestExecuter(t, &context)
+}
+
+func TestControllerUpdateGnbMissingNrNeighbourInformationRequiredProp(t *testing.T) {
+
+	for _, v := range NrNeighbourInformationRequiredFields {
+		context := controllerUpdateGnbTestContext{
+			getNodebInfoResult: nil,
+			requestBody: map[string]interface{}{
+				"servedNrCells": []interface{}{
+					map[string]interface{}{
+						"servedNrCellInformation": buildServedNrCellInformation(""),
+						"nrNeighbourInfos":        []interface{}{
+							buildNrNeighbourInformation(v),
+						},
+					},
+				},
+			},
+			expectedStatusCode:   http.StatusBadRequest,
+			expectedJsonResponse: ValidationFailureJson,
+		}
+
+		controllerUpdateGnbTestExecuter(t, &context)
+	}
+}
+
+func TestControllerUpdateGnbValidServedNrCellInformationAndNrNeighbourInfoGetNodebSuccess(t *testing.T) {
+	context := controllerUpdateGnbTestContext{
+		getNodebInfoResult: &getNodebInfoResult{
+			nodebInfo: &entities.NodebInfo{RanName: RanName, ConnectionStatus: entities.ConnectionStatus_CONNECTED, AssociatedE2TInstanceAddress: AssociatedE2TInstanceAddress},
+			rnibError: nil,
+		},
+		requestBody: map[string]interface{}{
+			"servedNrCells": []interface{}{
+				map[string]interface{}{
+					"servedNrCellInformation": buildServedNrCellInformation(""),
+					"nrNeighbourInfos":        []interface{}{
+						buildNrNeighbourInformation(""),
+					},
+				},
+			},
+		},
+		expectedStatusCode:   http.StatusOK,
+		expectedJsonResponse: "{\"ranName\":\"test\",\"connectionStatus\":\"CONNECTED\",\"associatedE2tInstanceAddress\":\"10.0.2.15:38000\"}",
+	}
+
+	controllerUpdateGnbTestExecuter(t, &context)
+}
+
+func TestControllerUpdateGnbValidServedNrCellInformationGetNodebNotFound(t *testing.T) {
+	context := controllerUpdateGnbTestContext{
+		getNodebInfoResult: &getNodebInfoResult{
+			nodebInfo: nil,
+			rnibError: common.NewResourceNotFoundError("#reader.GetNodeb - Not found Error"),
+		},
+		requestBody: map[string]interface{}{
+			"servedNrCells": []interface{}{
+				map[string]interface{}{
+					"servedNrCellInformation": buildServedNrCellInformation(""),
+				},
+			},
+		},
+		expectedStatusCode:   http.StatusNotFound,
+		expectedJsonResponse: ResourceNotFoundJson,
+	}
+
+	controllerUpdateGnbTestExecuter(t, &context)
+}
+
+func TestControllerUpdateGnbValidServedNrCellInformationGetNodebInternalError(t *testing.T) {
+	context := controllerUpdateGnbTestContext{
+		getNodebInfoResult: &getNodebInfoResult{
+			nodebInfo: nil,
+			rnibError: common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")),
+		},
+		requestBody: map[string]interface{}{
+			"servedNrCells": []interface{}{
+				map[string]interface{}{
+					"servedNrCellInformation": buildServedNrCellInformation(""),
+				},
+			},
+		},
+		expectedStatusCode:   http.StatusInternalServerError,
+		expectedJsonResponse: RnibErrorJson,
+	}
+
+	controllerUpdateGnbTestExecuter(t, &context)
+}
+
+func getJsonRequestAsBuffer(requestJson map[string]interface{}) *bytes.Buffer {
+	b := new(bytes.Buffer)
+	_ = json.NewEncoder(b).Encode(requestJson)
+	return b;
+}
+
 func TestControllerGetNodebSuccess(t *testing.T) {
 	ranName := "test"
 	var rnibError error
@@ -227,7 +495,7 @@
 		nodebInfo:            nodebInfo,
 		rnibError:            common.NewResourceNotFoundError("#reader.GetNodeb - Not found Error"),
 		expectedStatusCode:   http.StatusNotFound,
-		expectedJsonResponse: "{\"errorCode\":404,\"errorMessage\":\"Resource not found\"}",
+		expectedJsonResponse: ResourceNotFoundJson,
 	}
 
 	controllerGetNodebTestExecuter(t, &context)
@@ -241,7 +509,7 @@
 		nodebInfo:            nodebInfo,
 		rnibError:            common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")),
 		expectedStatusCode:   http.StatusInternalServerError,
-		expectedJsonResponse: "{\"errorCode\":500,\"errorMessage\":\"RNIB error\"}",
+		expectedJsonResponse: RnibErrorJson,
 	}
 
 	controllerGetNodebTestExecuter(t, &context)
@@ -284,7 +552,7 @@
 		nodebIdList:          nodebIdList,
 		rnibError:            common.NewInternalError(errors.New("#reader.GetNodeb - Internal Error")),
 		expectedStatusCode:   http.StatusInternalServerError,
-		expectedJsonResponse: "{\"errorCode\":500,\"errorMessage\":\"RNIB error\"}",
+		expectedJsonResponse: RnibErrorJson,
 	}
 
 	controllerGetNodebIdListTestExecuter(t, &context)
@@ -453,7 +721,7 @@
 }
 
 func TestX2ResetHandleFailureInvalidBody(t *testing.T) {
-	controller, _, _, _ , _:= setupControllerTest(t)
+	controller, _, _, _, _ := setupControllerTest(t)
 
 	ranName := "test1"
 
@@ -470,7 +738,7 @@
 }
 
 func TestHandleErrorResponse(t *testing.T) {
-	controller, _, _, _ , _:= setupControllerTest(t)
+	controller, _, _, _, _ := setupControllerTest(t)
 
 	writer := httptest.NewRecorder()
 	controller.handleErrorResponse(e2managererrors.NewRnibDbError(), writer)
diff --git a/E2Manager/go.mod b/E2Manager/go.mod
index 02a35a1..52ed763 100644
--- a/E2Manager/go.mod
+++ b/E2Manager/go.mod
@@ -9,7 +9,6 @@
 	github.com/go-ozzo/ozzo-validation v3.5.0+incompatible
 	github.com/golang/protobuf v1.3.4
 	github.com/gorilla/mux v1.7.0
-	github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
 	github.com/imdario/mergo v0.3.9 // indirect
 	github.com/magiconair/properties v1.8.1
 	github.com/pelletier/go-toml v1.5.0 // indirect
diff --git a/E2Manager/go.sum b/E2Manager/go.sum
index d72ec0e..fbd6e77 100644
--- a/E2Manager/go.sum
+++ b/E2Manager/go.sum
@@ -1,18 +1,10 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.32/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.33 h1:QqWDNf3E8OpevC8swnZFxd56oW/7+5kVa9Ps4LWAZy8=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.33/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.34 h1:d53dCN59dZftx847pzyo/zIKk0XJjOqMAx4VwxJHO10=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common v1.0.34/go.mod h1:QJ1uPPZosGbhxUWpUpeM5fLqFHdnWTrVnvW2DgyOCes=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.32/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.33 h1:VwfmU5yww6nejkRK2qYD/+VYy6+RBHWHihInHwgK1EE=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.33/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.34 h1:7jxKtb+VPgwHKxQuWne1mG09rsi330erwb1u4OsWEaA=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities v1.0.34/go.mod h1:G+4sUBMbLfQ+RrGS65U15tKmbnP+/1b5oLTPmMfyfT4=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.33 h1:dUTtIlG3F1+qyDZ1OIVsVFwygAioLNUkjiMzxTaHV9o=
-gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.33/go.mod h1:oPHTwdTeaOEuvqVRAog9WoCTW7O6ynE6rOyFB/sp9C0=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.34 h1:niBDUlmhq+8dhXt7z8KW+ZBq/0XlnM4FzvrLYlub1co=
 gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/reader v1.0.34/go.mod h1:tcc2L3Fb7hTvxK+QVTCbWjBX//078qOgPMwA9ZyCxY4=
 gerrit.o-ran-sc.org/r/ric-plt/sdlgo.git v0.5.2 h1:UK7awyRKIkVdokWvvkYvazlg3EWIfMnIqCcJxTnLlDA=
@@ -54,7 +46,6 @@
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
 github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
-github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
 github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
 github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -80,8 +71,6 @@
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
 github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
-github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
-github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -98,28 +87,22 @@
 github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
 github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
-github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
 github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
-github.com/googleapis/gnostic v0.1.0 h1:rVsPeBmXbYv4If/cumu1AzZPwV58q433hvONV1UEZoI=
-github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
-github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
 github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
 github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
 github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
-github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
-github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
@@ -134,7 +117,6 @@
 github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 github.com/json-iterator/go v1.1.8 h1:QiWkFLKq0T7mpzwOTu6BzNDbfTE8OLrYhVKYMLF46Ok=
 github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
@@ -173,11 +155,12 @@
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
 github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
 github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
 github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
 github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
 github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
@@ -298,8 +281,6 @@
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
 golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7 h1:HmbHVPwrPEKPGLAcHSrMe6+hqSUlvZU0rab6x5EXfGU=
-golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -320,6 +301,7 @@
 google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -350,23 +332,12 @@
 gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.0.0-20190111032252-67edc246be36 h1:XrFGq/4TDgOxYOxtNROTyp2ASjHjBIITdk/+aJD+zyY=
-k8s.io/api v0.0.0-20190111032252-67edc246be36/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
 k8s.io/api v0.17.0 h1:H9d/lw+VkZKEVIUc8F3wgiQ+FUXTTr21M87jXLU7yqM=
 k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
-k8s.io/api v0.18.0 h1:lwYk8Vt7rsVTwjRU6pzEsa9YNhThbmbocQlKvNBB4EQ=
-k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
 k8s.io/apimachinery v0.17.0 h1:xRBnuie9rXcPxUkDizUsGvPf1cnlZCFu210op7J7LJo=
 k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
-k8s.io/apimachinery v0.18.0 h1:fuPfYpk3cs1Okp/515pAf0dNhL66+8zk8RLbSX+EgAE=
-k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
 k8s.io/client-go v0.17.0 h1:8QOGvUGdqDMFrm9sD6IUFl256BcffynGoe80sxgTEDg=
 k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
-k8s.io/client-go v4.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
-k8s.io/client-go v10.0.0+incompatible h1:F1IqCqw7oMBzDkqlcBymRq1450wD0eNqLE9jzUrIi34=
-k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
-k8s.io/client-go v11.0.0+incompatible h1:LBbX2+lOwY9flffWlJM7f1Ct8V2SRNiMRDFeiwnJo9o=
-k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
 k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
 k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
@@ -374,16 +345,8 @@
 k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
 k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
-k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
 k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
 k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
-k8s.io/utils v0.0.0-20200327001022-6496210b90e8 h1:6JFbaLjRyBz8K2Jvt+pcT+N3vvwMZfg8MfVENwe9aag=
-k8s.io/utils v0.0.0-20200327001022-6496210b90e8/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
-sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
-sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
-sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
 sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
 sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
-sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
-sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/E2Manager/handlers/httpmsghandlers/request_handler.go b/E2Manager/handlers/httpmsghandlers/request_handler.go
index 5d1f6cf..e37adb7 100644
--- a/E2Manager/handlers/httpmsghandlers/request_handler.go
+++ b/E2Manager/handlers/httpmsghandlers/request_handler.go
@@ -17,7 +17,6 @@
 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
 //  platform project (RICP).
 
-
 package httpmsghandlers
 
 import (
diff --git a/E2Manager/handlers/httpmsghandlers/update_gnb_request_handler.go b/E2Manager/handlers/httpmsghandlers/update_gnb_request_handler.go
new file mode 100644
index 0000000..1d12a53
--- /dev/null
+++ b/E2Manager/handlers/httpmsghandlers/update_gnb_request_handler.go
@@ -0,0 +1,211 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package httpmsghandlers
+
+import (
+	"e2mgr/e2managererrors"
+	"e2mgr/logger"
+	"e2mgr/models"
+	"e2mgr/services"
+	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
+	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+	"github.com/pkg/errors"
+)
+
+const VALIDATION_FAILURE_MESSAGE = "#UpdateGnbRequestHandler.Handle - validation failure: %s is a mandatory field"
+
+type UpdateGnbRequestHandler struct {
+	logger          *logger.Logger
+	rNibDataService services.RNibDataService
+}
+
+func NewUpdateGnbRequestHandler(logger *logger.Logger, rNibDataService services.RNibDataService) *UpdateGnbRequestHandler {
+	return &UpdateGnbRequestHandler{
+		logger:          logger,
+		rNibDataService: rNibDataService,
+	}
+}
+
+func (h *UpdateGnbRequestHandler) Handle(request models.Request) (models.IResponse, error) {
+
+	updateGnbRequest := request.(models.UpdateGnbRequest)
+
+	h.logger.Infof("#UpdateGnbRequestHandler.Handle - Ran name: %s", updateGnbRequest.RanName)
+
+	err := h.validateRequestBody(updateGnbRequest)
+
+	if err != nil {
+		return nil, err
+	}
+
+	nodebInfo, err := h.rNibDataService.GetNodeb(updateGnbRequest.RanName)
+
+	if err != nil {
+		_, ok := err.(*common.ResourceNotFoundError)
+		if !ok {
+			h.logger.Errorf("#UpdateGnbRequestHandler.Handle - RAN name: %s - failed to get nodeb entity from RNIB. Error: %s", updateGnbRequest.RanName, err)
+			return nil, e2managererrors.NewRnibDbError()
+		}
+
+		h.logger.Errorf("#UpdateGnbRequestHandler.Handle - RAN name: %s - RAN not found on RNIB. Error: %s", updateGnbRequest.RanName, err)
+		return nil, e2managererrors.NewResourceNotFoundError()
+	}
+
+	//gnb := nodebInfo.GetGnb()
+	//
+	//if gnb == nil {
+	//	// TODO: log and return appropriate error
+	//	return nil, e2managererrors.NewRnibDbError()
+	//}
+	//
+	//gnb.ServedNrCells = updateGnbRequest.ServedNrCells
+	//
+	//err = h.rNibDataService.UpdateGnbCells(nodebInfo, updateGnbRequest.ServedNrCells)
+	//
+	//if err != nil {
+	//	// TODO: handle error
+	//	return nil, err
+	//}
+
+	return models.NewUpdateGnbResponse(nodebInfo), nil
+}
+
+func (h *UpdateGnbRequestHandler) validateRequestBody(updateGnbRequest models.UpdateGnbRequest) (error) {
+
+	if len(updateGnbRequest.ServedNrCells) == 0 {
+		h.logger.Errorf(VALIDATION_FAILURE_MESSAGE+" and cannot be empty", "servedCells")
+		return e2managererrors.NewRequestValidationError()
+	}
+
+	for _, servedNrCell := range updateGnbRequest.ServedNrCells {
+		if servedNrCell.ServedNrCellInformation == nil {
+			h.logger.Errorf(VALIDATION_FAILURE_MESSAGE+" and cannot be empty", "servedNrCellInformation")
+			return e2managererrors.NewRequestValidationError()
+		}
+
+		err := isServedNrCellInformationValid(servedNrCell.ServedNrCellInformation)
+
+		if err != nil {
+			h.logger.Errorf(VALIDATION_FAILURE_MESSAGE, err)
+			return e2managererrors.NewRequestValidationError()
+		}
+
+		if len(servedNrCell.NrNeighbourInfos) == 0 {
+			continue
+		}
+
+		for _, nrNeighbourInformation := range servedNrCell.NrNeighbourInfos {
+
+			err := isNrNeighbourInformationValid(nrNeighbourInformation)
+
+			if err != nil {
+				h.logger.Errorf(VALIDATION_FAILURE_MESSAGE, err)
+				return e2managererrors.NewRequestValidationError()
+			}
+
+		}
+	}
+
+	return nil
+}
+
+func isServedNrCellInformationValid(servedNrCellInformation *entities.ServedNRCellInformation) error {
+	if servedNrCellInformation.CellId == "" {
+		return errors.New("cellId");
+	}
+
+	if servedNrCellInformation.ChoiceNrMode == nil {
+		return errors.New("choiceNrMode");
+	}
+
+	if servedNrCellInformation.NrMode == entities.Nr_UNKNOWN {
+		return errors.New("nrMode");
+	}
+
+	if servedNrCellInformation.NrPci == 0 {
+		return errors.New("nrPci");
+	}
+
+	if len(servedNrCellInformation.ServedPlmns) == 0 {
+		return errors.New("servedPlmns");
+	}
+
+	return isServedNrCellInfoChoiceNrModeValid(servedNrCellInformation.ChoiceNrMode)
+}
+
+func isServedNrCellInfoChoiceNrModeValid(choiceNrMode *entities.ServedNRCellInformation_ChoiceNRMode) error {
+	if choiceNrMode.Fdd != nil {
+		return isServedNrCellInfoFddValid(choiceNrMode.Fdd)
+	}
+
+	if choiceNrMode.Tdd != nil {
+		return isServedNrCellInfoTddValid(choiceNrMode.Tdd)
+	}
+
+	return errors.New("served nr cell fdd / tdd")
+}
+
+func isServedNrCellInfoTddValid(tdd *entities.ServedNRCellInformation_ChoiceNRMode_TddInfo) error {
+	return nil
+}
+
+func isServedNrCellInfoFddValid(fdd *entities.ServedNRCellInformation_ChoiceNRMode_FddInfo) error {
+	return nil
+}
+
+func isNrNeighbourInformationValid(nrNeighbourInformation *entities.NrNeighbourInformation) error {
+	if nrNeighbourInformation.NrCgi == "" {
+		return errors.New("nrCgi")
+	}
+
+	if nrNeighbourInformation.ChoiceNrMode == nil {
+		return errors.New("choiceNrMode")
+	}
+
+	if nrNeighbourInformation.NrMode == entities.Nr_UNKNOWN {
+		return errors.New("nrMode")
+	}
+
+	if nrNeighbourInformation.NrPci == 0 {
+		return errors.New("nrPci")
+	}
+
+	return isNrNeighbourInfoChoiceNrModeValid(nrNeighbourInformation.ChoiceNrMode)
+}
+
+func isNrNeighbourInfoChoiceNrModeValid(choiceNrMode *entities.NrNeighbourInformation_ChoiceNRMode) error {
+	if choiceNrMode.Fdd != nil {
+		return isNrNeighbourInfoFddValid(choiceNrMode.Fdd)
+	}
+
+	if choiceNrMode.Tdd != nil {
+		return isNrNeighbourInfoTddValid(choiceNrMode.Tdd)
+	}
+
+	return errors.New("nr neighbour fdd / tdd")
+}
+
+func isNrNeighbourInfoTddValid(tdd *entities.NrNeighbourInformation_ChoiceNRMode_TddInfo) error {
+	return nil
+}
+
+func isNrNeighbourInfoFddValid(fdd *entities.NrNeighbourInformation_ChoiceNRMode_FddInfo) error {
+	return nil
+}
diff --git a/E2Manager/httpserver/http_server.go b/E2Manager/httpserver/http_server.go
index 608110f..2c140eb 100644
--- a/E2Manager/httpserver/http_server.go
+++ b/E2Manager/httpserver/http_server.go
@@ -17,7 +17,6 @@
 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
 //  platform project (RICP).
 
-
 package httpserver
 
 import (
@@ -43,16 +42,16 @@
 
 func initializeRoutes(router *mux.Router, rootController controllers.IRootController, nodebController controllers.INodebController, e2tController controllers.IE2TController) {
 	r := router.PathPrefix("/v1").Subrouter()
-	r.HandleFunc("/health", rootController.HandleHealthCheckRequest).Methods("GET")
+	r.HandleFunc("/health", rootController.HandleHealthCheckRequest).Methods(http.MethodGet)
 
 	rr := r.PathPrefix("/nodeb").Subrouter()
-	rr.HandleFunc("/ids", nodebController.GetNodebIdList).Methods("GET")
-	rr.HandleFunc("/{ranName}", nodebController.GetNodeb).Methods("GET")
-	rr.HandleFunc("/shutdown", nodebController.Shutdown).Methods("PUT")
-	rr.HandleFunc("/{ranName}/reset", nodebController.X2Reset).Methods("PUT")
-	rr.HandleFunc("/x2-setup", nodebController.X2Setup).Methods("POST")
-	rr.HandleFunc("/endc-setup", nodebController.EndcSetup).Methods("POST")
-
+	rr.HandleFunc("/ids", nodebController.GetNodebIdList).Methods(http.MethodGet)
+	rr.HandleFunc("/{ranName}", nodebController.GetNodeb).Methods(http.MethodGet)
+	rr.HandleFunc("/{ranName}/update", nodebController.UpdateGnb).Methods(http.MethodPut)
+	rr.HandleFunc("/shutdown", nodebController.Shutdown).Methods(http.MethodPut)
+	rr.HandleFunc("/{ranName}/reset", nodebController.X2Reset).Methods(http.MethodPut)
+	rr.HandleFunc("/x2-setup", nodebController.X2Setup).Methods(http.MethodPost)
+	rr.HandleFunc("/endc-setup", nodebController.EndcSetup).Methods(http.MethodPost)
 	rrr := r.PathPrefix("/e2t").Subrouter()
-	rrr.HandleFunc("/list", e2tController.GetE2TInstances).Methods("GET")
+	rrr.HandleFunc("/list", e2tController.GetE2TInstances).Methods(http.MethodGet)
 }
diff --git a/E2Manager/mocks/nodeb_controller_mock.go b/E2Manager/mocks/nodeb_controller_mock.go
index c729323..a164383 100644
--- a/E2Manager/mocks/nodeb_controller_mock.go
+++ b/E2Manager/mocks/nodeb_controller_mock.go
@@ -74,3 +74,10 @@
 
 	c.Called()
 }
+
+func (c *NodebControllerMock) UpdateGnb(writer http.ResponseWriter, r *http.Request) {
+	writer.Header().Set("Content-Type", "application/json")
+	writer.WriteHeader(http.StatusOK)
+
+	c.Called()
+}
diff --git a/E2Manager/models/update_gnb_request.go b/E2Manager/models/update_gnb_request.go
new file mode 100644
index 0000000..7c039d6
--- /dev/null
+++ b/E2Manager/models/update_gnb_request.go
@@ -0,0 +1,27 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package models
+
+import "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+
+type UpdateGnbRequest struct {
+	RanName string
+	*entities.Gnb
+}
diff --git a/E2Manager/models/update_gnb_response.go b/E2Manager/models/update_gnb_response.go
new file mode 100644
index 0000000..59131e5
--- /dev/null
+++ b/E2Manager/models/update_gnb_response.go
@@ -0,0 +1,48 @@
+//
+// Copyright 2019 AT&T Intellectual Property
+// Copyright 2019 Nokia
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//  This source code is part of the near-RT RIC (RAN Intelligent Controller)
+//  platform project (RICP).
+
+package models
+
+import (
+	"e2mgr/e2managererrors"
+	"gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
+	"github.com/golang/protobuf/jsonpb"
+)
+
+type UpdateGnbResponse struct {
+	nodebInfo *entities.NodebInfo
+}
+
+func NewUpdateGnbResponse(nodebInfo *entities.NodebInfo) *UpdateGnbResponse {
+	return &UpdateGnbResponse{
+		nodebInfo: nodebInfo,
+	}
+}
+
+func (response *UpdateGnbResponse) Marshal() ([]byte, error) {
+	m := jsonpb.Marshaler{}
+	result, err := m.MarshalToString(response.nodebInfo)
+
+	if err != nil {
+		return nil, e2managererrors.NewInternalError()
+	}
+
+	return []byte(result), nil
+
+}
diff --git a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go
index cfbda44..f5572cd 100644
--- a/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go
+++ b/E2Manager/providers/httpmsghandlerprovider/incoming_request_handler_provider.go
@@ -41,6 +41,7 @@
 	GetNodebRequest        IncomingRequest = "GetNodebRequest"
 	GetNodebIdListRequest  IncomingRequest = "GetNodebIdListRequest"
 	GetE2TInstancesRequest IncomingRequest = "GetE2TInstancesRequest"
+	UpdateGnbRequest       IncomingRequest = "UpdateGnbRequest"
 )
 
 type IncomingRequestHandlerProvider struct {
@@ -59,13 +60,14 @@
 func initRequestHandlerMap(logger *logger.Logger, rmrSender *rmrsender.RmrSender, config *configuration.Configuration, rNibDataService services.RNibDataService, ranSetupManager *managers.RanSetupManager, e2tInstancesManager managers.IE2TInstancesManager, e2tAssociationManager *managers.E2TAssociationManager, rmClient clients.IRoutingManagerClient) map[IncomingRequest]httpmsghandlers.RequestHandler {
 
 	return map[IncomingRequest]httpmsghandlers.RequestHandler{
-		ShutdownRequest:  httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient),
-		ResetRequest:     httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService),
-		X2SetupRequest:   httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
-		EndcSetupRequest: httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
-		GetNodebRequest:  httpmsghandlers.NewGetNodebRequestHandler(logger, rNibDataService),
-		GetNodebIdListRequest: httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService),
+		ShutdownRequest:        httpmsghandlers.NewDeleteAllRequestHandler(logger, rmrSender, config, rNibDataService, e2tInstancesManager, rmClient),
+		ResetRequest:           httpmsghandlers.NewX2ResetRequestHandler(logger, rmrSender, rNibDataService),
+		X2SetupRequest:         httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
+		EndcSetupRequest:       httpmsghandlers.NewSetupRequestHandler(logger, rNibDataService, ranSetupManager, entities.E2ApplicationProtocol_ENDC_X2_SETUP_REQUEST, e2tInstancesManager, e2tAssociationManager),
+		GetNodebRequest:        httpmsghandlers.NewGetNodebRequestHandler(logger, rNibDataService),
+		GetNodebIdListRequest:  httpmsghandlers.NewGetNodebIdListRequestHandler(logger, rNibDataService),
 		GetE2TInstancesRequest: httpmsghandlers.NewGetE2TInstancesRequestHandler(logger, e2tInstancesManager),
+		UpdateGnbRequest:       httpmsghandlers.NewUpdateGnbRequestHandler(logger, rNibDataService),
 	}
 }
 
diff --git a/E2Manager/tests/dataProvider.go b/E2Manager/tests/dataProvider.go
index 8095663..dfa637e 100644
--- a/E2Manager/tests/dataProvider.go
+++ b/E2Manager/tests/dataProvider.go
@@ -17,16 +17,13 @@
 //  This source code is part of the near-RT RIC (RAN Intelligent Controller)
 //  platform project (RICP).
 
-
 package tests
 
 import (
 	"bytes"
 	"encoding/json"
-	"fmt"
 	"net/http"
 	"strconv"
-	"testing"
 )
 
 const (
@@ -49,38 +46,13 @@
 }
 
 func GetHttpRequest() *http.Request {
-	data := map[string]interface{}{"ranIp": RanIp,
-		"ranPort": RanPort, "ranName": RanName}
-	b := new(bytes.Buffer)
-	_ = json.NewEncoder(b).Encode(data)
-	req, _ := http.NewRequest("POST", "https://localhost:3800/request", b)
-	return req
-}
-
-func GetInvalidRequestDetails() *http.Request {
-	data := map[string]interface{}{"ranIp": "256.0.0.0",
-		"ranPort": RanPort, "ranName": RanName}
-	b := new(bytes.Buffer)
-	_ = json.NewEncoder(b).Encode(data)
-	req, _ := http.NewRequest("POST", "https://localhost:3800/request", b)
-	return req
-}
-
-func GetInvalidMessageType() *http.Request {
-	data := map[string]interface{}{"ranIp": "1.2.3.4",
-		"ranPort": RanPort, "ranName": RanName}
-	b := new(bytes.Buffer)
-	_ = json.NewEncoder(b).Encode(data)
-	req, _ := http.NewRequest("POST", "https://localhost:3800/request", b)
-	return req
-}
-
-func GetPackedPayload(t *testing.T) []byte {
-	inputPayloadAsStr := "2006002a000002001500080002f82900007a8000140017000000630002f8290007ab50102002f829000001000133"
-	payload := make([]byte, len(inputPayloadAsStr)/2)
-	_, err := fmt.Sscanf(inputPayloadAsStr, "%x", &payload)
-	if err != nil {
-		t.Errorf("convert inputPayloadAsStr to payloadAsByte. Error: %v\n", err)
+	data := map[string]interface{}{
+		"ranIp":   RanIp,
+		"ranPort": RanPort,
+		"ranName": RanName,
 	}
-	return payload
+	b := new(bytes.Buffer)
+	_ = json.NewEncoder(b).Encode(data)
+	req, _ := http.NewRequest("POST", "https://localhost:3800/request", b)
+	return req
 }