Skip to content

Commit 72e2cec

Browse files
authored
Return ygot strcut from app module processGet() functions (sonic-net#72)
* Return ygot strcut from app module processGet() functions * Updated the appInterface method processGet() to accept a TranslibFmtType argument indicating whether the response data should be returned as IETF json bytes or a ygot.GoStruct object. Translib subscription infra will use TranslibFmtType=ygot. The translib.Get() API will continue to use TranslibFmtType=ietf_json. * Modified processGet() method signature in all existing app modules. All of them will call the common generateGetResponse() utility func which builds the response data as per TranslibFmtType input. Removed all direct dumpIetfJson() calls from app modules. * GetResponse struct contains both []byte and ygot.GoStruct fields. One of them will be populated based on the TranslibFmtType input. * Added TranslibFmtType field to GetRequest also. This can be used in future to support protocol specific response encodings like protobuf encoding. Signed-off-by: Sachin Holla <[email protected]> * Minor code cleanup to address review comments --------- Signed-off-by: Sachin Holla <[email protected]>
1 parent 80df301 commit 72e2cec

13 files changed

+107
-134
lines changed

translib/acl_app.go

+2-7
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func (app *AclApp) processDelete(d *db.DB) (SetResponse, error) {
194194
return resp, err
195195
}
196196

197-
func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
197+
func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) {
198198
var err error
199199
var payload []byte
200200

@@ -204,12 +204,7 @@ func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
204204
return GetResponse{Payload: payload, ErrSrc: AppErr}, err
205205
}
206206

207-
payload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget)
208-
if err != nil {
209-
return GetResponse{Payload: payload, ErrSrc: AppErr}, err
210-
}
211-
212-
return GetResponse{Payload: payload}, err
207+
return generateGetResponse(app.pathInfo.Path, app.ygotRoot, fmtType)
213208
}
214209

215210
func (app *AclApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) {

translib/api_tests_app.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (app *apiTests) processDelete(d *db.DB) (SetResponse, error) {
126126
return app.processSet()
127127
}
128128

129-
func (app *apiTests) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
129+
func (app *apiTests) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) {
130130
var gr GetResponse
131131
err := app.getError()
132132
if err != nil {

translib/app_interface.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ type appInterface interface {
9090
processUpdate(d *db.DB) (SetResponse, error)
9191
processReplace(d *db.DB) (SetResponse, error)
9292
processDelete(d *db.DB) (SetResponse, error)
93-
processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error)
93+
processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error)
9494
processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error)
9595
processSubscribe(req processSubRequest) (processSubResponse, error)
9696
}

translib/app_utils.go

+21-13
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package translib
2222
import (
2323
"reflect"
2424
"strings"
25+
2526
"github.com/Azure/sonic-mgmt-common/translib/db"
2627
"github.com/Azure/sonic-mgmt-common/translib/ocbinds"
2728
"github.com/Azure/sonic-mgmt-common/translib/tlerr"
@@ -67,16 +68,19 @@ func getYangPathFromYgotStruct(s ygot.GoStruct, yangPathPrefix string, appModule
6768
return ""
6869
}
6970

70-
func generateGetResponsePayload(targetUri string, deviceObj *ocbinds.Device, ygotTarget *interface{}) ([]byte, error) {
71+
func generateGetResponse(targetUri string, root *ygot.GoStruct, fmtType TranslibFmtType) (GetResponse, error) {
7172
var err error
72-
var payload []byte
73+
var resp GetResponse
7374

75+
if root == nil {
76+
return resp, tlerr.InvalidArgs("ygotRoot not specified")
77+
}
7478
if len(targetUri) == 0 {
75-
return payload, tlerr.InvalidArgs("GetResponse failed as target Uri is not valid")
79+
return resp, tlerr.InvalidArgs("GetResponse failed as target Uri is not valid")
7680
}
77-
path, err := ygot.StringToPath(targetUri, ygot.StructuredPath, ygot.StringSlicePath)
81+
path, err := ygot.StringToPath(targetUri, ygot.StructuredPath)
7882
if err != nil {
79-
return payload, tlerr.InvalidArgs("URI to path conversion failed: %v", err)
83+
return resp, tlerr.InvalidArgs("URI to path conversion failed: %v", err)
8084
}
8185

8286
// Get current node (corresponds to ygotTarget) and its parent node
@@ -92,21 +96,21 @@ func generateGetResponsePayload(targetUri string, deviceObj *ocbinds.Device, ygo
9296
parentPath.Elem = append(parentPath.Elem, pathList[i])
9397
}
9498
}
95-
parentNodeList, err := ytypes.GetNode(ygSchema.RootSchema(), deviceObj, parentPath)
99+
parentNodeList, err := ytypes.GetNode(ygSchema.RootSchema(), *root, parentPath)
96100
if err != nil {
97-
return payload, err
101+
return resp, err
98102
}
99103
if len(parentNodeList) == 0 {
100-
return payload, tlerr.InvalidArgs("Invalid URI: %s", targetUri)
104+
return resp, tlerr.InvalidArgs("Invalid URI: %s", targetUri)
101105
}
102106
parentNode := parentNodeList[0].Data
103107

104-
currentNodeList, err := ytypes.GetNode(ygSchema.RootSchema(), deviceObj, path, &(ytypes.GetPartialKeyMatch{}))
108+
currentNodeList, err := ytypes.GetNode(ygSchema.RootSchema(), *root, path, &(ytypes.GetPartialKeyMatch{}))
105109
if err != nil {
106-
return payload, err
110+
return resp, err
107111
}
108112
if len(currentNodeList) == 0 {
109-
return payload, tlerr.NotFound("Resource not found")
113+
return resp, tlerr.NotFound("Resource not found")
110114
}
111115
//currentNode := currentNodeList[0].Data
112116
currentNodeYangName := currentNodeList[0].Schema.Name
@@ -137,9 +141,13 @@ func generateGetResponsePayload(targetUri string, deviceObj *ocbinds.Device, ygo
137141
}
138142
}
139143

140-
payload, err = dumpIetfJson(parentCloneObj, true)
144+
if fmtType == TRANSLIB_FMT_YGOT {
145+
resp.ValueTree = parentCloneObj
146+
} else {
147+
resp.Payload, err = dumpIetfJson(parentCloneObj, true)
148+
}
141149

142-
return payload, err
150+
return resp, err
143151
}
144152

145153
func getTargetNodeYangSchema(targetUri string, deviceObj *ocbinds.Device) (*yang.Entry, error) {

translib/app_utils_test.go

+29-7
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,37 @@ func TestMain(m *testing.M) {
7272

7373
func processGetRequest(url string, expectedRespJson string, errorCase bool) func(*testing.T) {
7474
return func(t *testing.T) {
75-
response, err := Get(GetRequest{Path: url})
76-
if err != nil && !errorCase {
77-
t.Fatalf("Error %v received for Url: %s", err, url)
78-
}
75+
t.Run("ietf_json", func(t *testing.T) {
76+
verifyGet(t, GetRequest{Path: url}, expectedRespJson, errorCase)
77+
})
78+
t.Run("ygot", func(t *testing.T) {
79+
verifyGet(t, GetRequest{Path: url, FmtType: TRANSLIB_FMT_YGOT}, expectedRespJson, errorCase)
80+
})
81+
}
82+
}
7983

80-
respJson := response.Payload
81-
if string(respJson) != expectedRespJson {
82-
t.Fatalf("Response for Url: %s received is not expected:\n%s", url, string(respJson))
84+
func verifyGet(t *testing.T, req GetRequest, expJson string, expError bool) {
85+
t.Helper()
86+
response, err := Get(req)
87+
if expError {
88+
if err == nil {
89+
t.Fatalf("GET %s did not return an error", req.Path)
8390
}
91+
return
92+
}
93+
var respJson []byte
94+
if req.FmtType == TRANSLIB_FMT_YGOT && response.ValueTree != nil {
95+
respJson, err = dumpIetfJson(response.ValueTree, true)
96+
if err != nil {
97+
t.Fatalf("GET %s returned invalid YGOT. error=%v", req.Path, err)
98+
}
99+
} else if req.FmtType == TRANSLIB_FMT_IETF_JSON {
100+
respJson = response.Payload
101+
}
102+
if j := string(respJson); j != expJson {
103+
t.Errorf("GET %s returned invalid response", req.Path)
104+
t.Errorf("Expected: %s", expJson)
105+
t.Fatalf("Received: %s", j)
84106
}
85107
}
86108

translib/common_app.go

+2-6
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) {
195195
return resp, err
196196
}
197197

198-
func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
198+
func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) {
199199
var err error
200200
var payload []byte
201201
var resPayload []byte
@@ -277,11 +277,7 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
277277
}
278278
}
279279
if resYgot != nil {
280-
resPayload, err = generateGetResponsePayload(app.pathInfo.Path, resYgot.(*ocbinds.Device), app.ygotTarget)
281-
if err != nil {
282-
log.Warning("generateGetResponsePayload() couldn't generate payload.")
283-
resPayload = payload
284-
}
280+
return generateGetResponse(app.pathInfo.Path, &resYgot, fmtType)
285281
} else {
286282
resPayload = payload
287283
}

translib/intf_app.go

+9-39
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ func (app *IntfApp) processDelete(d *db.DB) (SetResponse, error) {
303303
}
304304

305305
/* Note : Registration already happened, followed by filling the internal DS and filling the JSON */
306-
func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
306+
func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) {
307307

308308
var err error
309309
var payload []byte
@@ -339,12 +339,8 @@ func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
339339
return GetResponse{Payload: payload, ErrSrc: AppErr}, e
340340
}
341341

342-
payload, err = dumpIetfJson(oc_val, false)
343-
if err == nil {
344-
return GetResponse{Payload: payload}, err
345-
} else {
346-
return GetResponse{Payload: payload, ErrSrc: AppErr}, err
347-
}
342+
ifInfo.State = oc_val
343+
continue
348344
}
349345

350346
/* Filling the counter Info to internal DS */
@@ -365,12 +361,8 @@ func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
365361
return GetResponse{Payload: payload, ErrSrc: AppErr}, e
366362
}
367363

368-
payload, err = dumpIetfJson(counter_val, false)
369-
if err == nil {
370-
return GetResponse{Payload: payload}, err
371-
} else {
372-
return GetResponse{Payload: payload, ErrSrc: AppErr}, err
373-
}
364+
ifInfo.State = &ocbinds.OpenconfigInterfaces_Interfaces_Interface_State{Counters: counter_val}
365+
continue
374366
}
375367

376368
/* Filling Interface IP info to internal DS */
@@ -385,28 +377,10 @@ func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
385377
ygot.BuildEmptyTree(ifInfo.State)
386378
}
387379
app.convertInternalToOCIntfInfo(&ifKey, ifInfo)
388-
if *app.ygotTarget == ifInfo {
389-
payload, err = dumpIetfJson(intfObj, false)
390-
} else {
391-
dummyifInfo := &ocbinds.OpenconfigInterfaces_Interfaces_Interface{}
392-
counter_all_val := &ocbinds.OpenconfigInterfaces_Interfaces_Interface_State{}
393-
if *app.ygotTarget == ifInfo.Config {
394-
dummyifInfo.Config = ifInfo.Config
395-
payload, err = dumpIetfJson(dummyifInfo, false)
396-
} else if *app.ygotTarget == ifInfo.State {
397-
dummyifInfo.State = ifInfo.State
398-
payload, err = dumpIetfJson(dummyifInfo, false)
399-
} else if *app.ygotTarget == ifInfo.State.Counters {
400-
counter_all_val.Counters = ifInfo.State.Counters
401-
payload, err = dumpIetfJson(counter_all_val, false)
402-
} else {
403-
log.Info("Not supported get type!")
404-
err = errors.New("Requested get-type not supported!")
405-
}
406-
}
407380
}
408381
}
409-
return GetResponse{Payload: payload}, err
382+
383+
return generateGetResponse(pathInfo.Path, app.ygotRoot, fmtType)
410384
}
411385

412386
/* Get all Interfaces */
@@ -442,13 +416,9 @@ func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
442416
ygot.BuildEmptyTree(ifInfo)
443417
app.convertInternalToOCIntfInfo(&ifKey, ifInfo)
444418
}
445-
if *app.ygotTarget == intfObj {
446-
payload, err = dumpIetfJson((*app.ygotRoot).(*ocbinds.Device), true)
447-
} else {
448-
log.Error("Wrong request!")
449-
}
450419
}
451-
return GetResponse{Payload: payload}, err
420+
421+
return generateGetResponse(pathInfo.Path, app.ygotRoot, fmtType)
452422
}
453423

454424
func (app *IntfApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) {

translib/lldp_app.go

+6-18
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,18 @@ func (app *lldpApp) processDelete(d *db.DB) (SetResponse, error) {
180180
return resp, err
181181
}
182182

183-
func (app *lldpApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
183+
func (app *lldpApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) {
184184
var err error
185185
var payload []byte
186186

187187
app.appDb = dbs[db.ApplDB]
188188
lldpIntfObj := app.getAppRootObject()
189189

190190
targetUriPath, err := getYangPathFromUri(app.path.Path)
191+
if err != nil {
192+
return GetResponse{}, err
193+
}
194+
191195
log.Info("lldp processGet")
192196
log.Info("targetUriPath: ", targetUriPath)
193197

@@ -205,12 +209,6 @@ func (app *lldpApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
205209
}
206210
ygot.BuildEmptyTree(oneIfInfo)
207211
app.getLldpNeighInfoFromInternalMap(&ifname, oneIfInfo)
208-
if *app.ygotTarget == lldpIntfObj.Interfaces {
209-
payload, err = dumpIetfJson(lldpIntfObj, true)
210-
} else {
211-
log.Info("Wrong request!")
212-
}
213-
214212
}
215213
} else if targetUriPath == "/openconfig-lldp:lldp/interfaces/interface" {
216214
intfObj := lldpIntfObj.Interfaces
@@ -222,23 +220,13 @@ func (app *lldpApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) {
222220
ifInfo := intfObj.Interface[ifname]
223221
ygot.BuildEmptyTree(ifInfo)
224222
app.getLldpNeighInfoFromInternalMap(&ifname, ifInfo)
225-
226-
if *app.ygotTarget == intfObj.Interface[ifname] {
227-
payload, err = dumpIetfJson(intfObj, true)
228-
if err != nil {
229-
log.Info("Creation of subinterface subtree failed!")
230-
return GetResponse{Payload: payload, ErrSrc: AppErr}, err
231-
}
232-
} else {
233-
log.Info("Wrong request!")
234-
}
235223
}
236224
} else {
237225
log.Info("No data")
238226
}
239227
}
240228

241-
return GetResponse{Payload:payload}, err
229+
return generateGetResponse(app.path.Path, app.ygotRoot, fmtType)
242230
}
243231

244232
func (app *lldpApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) {

0 commit comments

Comments
 (0)