diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang index ced7029938..263cf9274d 100644 --- a/models/yang/common/sonic-extensions.yang +++ b/models/yang/common/sonic-extensions.yang @@ -71,7 +71,7 @@ module sonic-extensions { description "Validation callpoint used to validate a YANG node during data translation back to YANG as a response to GET."; } - extension redis-db-name { + extension db-name { argument "db-name"; description "DB name that will indicate where data is stored. Eg: Config DB, App DB etc"; } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index e48c71cdcc..7571bb025c 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package translib import ( diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index c69ecabda6..05eb21a292 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -30,8 +48,8 @@ func reportIfError(errs []error) { } } -func getOcModelsList () ([] string) { - var fileList [] string +func getOcModelsList () ([]string) { + var fileList []string file, err := os.Open(YangPath + "models_list") if err != nil { return fileList @@ -51,7 +69,7 @@ func getOcModelsList () ([] string) { return fileList } -func getDefaultModelsList () ([] string) { +func getDefaultModelsList () ([]string) { var files []string fileInfo, err := ioutil.ReadDir(YangPath) if err != nil { diff --git a/src/translib/transformer/xconst.go b/src/translib/transformer/xconst.go index bcc2d0ffb3..a1fb5f9f46 100644 --- a/src/translib/transformer/xconst.go +++ b/src/translib/transformer/xconst.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer const ( @@ -7,7 +25,7 @@ const ( YANG_LEAF = "leaf" YANG_LEAF_LIST = "leaflist" - YANG_ANNOT_DB_NAME = "redis-db-name" + YANG_ANNOT_DB_NAME = "db-name" YANG_ANNOT_TABLE_NAME = "table-name" YANG_ANNOT_FIELD_NAME = "field-name" YANG_ANNOT_KEY_DELIM = "key-delimiter" diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 3f07baa4a0..fd8b694366 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index f9c8c6d3a3..35e17ed004 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 3c675c63c9..692353e675 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -331,7 +349,7 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m } } } else { - xpath, _ := RemoveXPATHPredicates(uri) + xpath, _ := XfmrRemoveXPATHPredicates(uri) if _, ok := xYangSpecMap[xpath]; ok { cdb = xYangSpecMap[xpath].dbIndex } diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 78e6b19bca..09b79b8a25 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -20,7 +38,7 @@ type typeMapOfInterface map[string]interface{} func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { result := make(map[string]interface{}) - xpath, _ := RemoveXPATHPredicates(inParams.uri) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) log.Infof("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xYangSpecMap[xpath].xfmrFunc, xpath) _, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { @@ -60,10 +78,7 @@ func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { } func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { - xpath, _ := RemoveXPATHPredicates(inParams.uri) - if strings.Count(xpath, ":") > 1 { - xpath = stripAugmentedModuleNames(xpath) - } + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) ret, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil, err @@ -77,7 +92,7 @@ func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { } func validateHandlerFunc(inParams XfmrParams) (bool) { - xpath, _ := RemoveXPATHPredicates(inParams.uri) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) ret, err := XlateFuncCall(xYangSpecMap[xpath].validateFunc, inParams) if err != nil { return false @@ -159,7 +174,8 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { const INTBASE = 10 yngTerminalNdDtType := xDbSpecMap[fieldXpath].dbEntry.Type.Kind switch yngTerminalNdDtType { - case yang.Yenum, yang.Ystring, yang.Yunion: + case yang.Yenum, yang.Ystring, yang.Yunion, yang.Yleafref: + // TODO handle leaf-ref base type log.Info("DB leaf-list and Yang leaf-list are of same data-type") for _, fldVal := range valLst { resLst = append(resLst, fldVal) @@ -196,7 +212,7 @@ func sonicDbToYangTerminalNodeFill(tblName string, field string, value string, r } yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) - if yangType == "leaf-list" { + if yangType == YANG_LEAF_LIST { /* this should never happen but just adding for safetty */ if !strings.HasSuffix(field, "@") { log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) @@ -249,7 +265,11 @@ func sonicDbToYangDataFill(uri string, xpath string, dbIdx db.DBNum, table strin if chldYangType == YANG_LEAF || chldYangType == YANG_LEAF_LIST { log.Infof("tbl(%v), k(%v), yc(%v)", table, key, yangChldName) - sonicDbToYangTerminalNodeFill(table, yangChldName, (*dbDataMap)[dbIdx][table][key].Field[yangChldName], resultMap) + fldName := yangChldName + if chldYangType == YANG_LEAF_LIST { + fldName = fldName + "@" + } + sonicDbToYangTerminalNodeFill(table, fldName, (*dbDataMap)[dbIdx][table][key].Field[fldName], resultMap) } else if chldYangType == YANG_CONTAINER { curMap := make(map[string]interface{}) curUri := xpath + "/" + yangChldName @@ -266,7 +286,12 @@ func sonicDbToYangDataFill(uri string, xpath string, dbIdx db.DBNum, table strin var mapSlice []typeMapOfInterface curUri := xpath + "/" + yangChldName mapSlice = sonicDbToYangListFill(curUri, curUri, dbIdx, table, key, dbDataMap) - if len(mapSlice) > 0 { + if len(key) > 0 && len(mapSlice) == 1 {// Single instance query. Don't return array of maps + for k, val := range mapSlice[0] { + resultMap[k] = val + } + + } else if len(mapSlice) > 0 { resultMap[yangChldName] = mapSlice } else { log.Infof("Empty list for xpath(%v)", curUri) @@ -291,7 +316,7 @@ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map fieldName := tokens[len(tokens)-1] dbSpecField := table + "/" + fieldName _, ok := xDbSpecMap[dbSpecField] - if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { + if ok && (xDbSpecMap[dbSpecField].fieldType == YANG_LEAF || xDbSpecMap[dbSpecField].fieldType == YANG_LEAF_LIST) { dbNode = xDbSpecMap[dbSpecField] xpath = dbSpecField } else { @@ -311,6 +336,9 @@ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map if yangType == YANG_LEAF || yangType == YANG_LEAF_LIST { fldName := xDbSpecMap[xpath].dbEntry.Name + if yangType == YANG_LEAF_LIST { + fldName = fldName + "@" + } sonicDbToYangTerminalNodeFill(table, fldName, (*dbDataMap)[cdb][table][key].Field[fldName], resultMap) } else if yangType == YANG_CONTAINER { if len(table) > 0 { @@ -319,7 +347,12 @@ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map sonicDbToYangDataFill(uri, xpath, cdb, table, key, dbDataMap, resultMap) } else if yangType == YANG_LIST { mapSlice := sonicDbToYangListFill(uri, xpath, cdb, table, key, dbDataMap) - if len(mapSlice) > 0 { + if len(key) > 0 && len(mapSlice) == 1 {// Single instance query. Don't return array of maps + for k, val := range mapSlice[0] { + resultMap[k] = val + } + + } else if len(mapSlice) > 0 { pathl := strings.Split(xpath, "/") lname := pathl[len(pathl) - 1] resultMap[lname] = mapSlice @@ -353,10 +386,9 @@ func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string dbFormat := KeySpec{} dbFormat.Ts.Name = tblName dbFormat.dbNum = cdb - /* TODO - handle key if tblKey != "" { dbFormat.Key.Comp = append(dbFormat.Key.Comp, tblKey) - } */ + } err = TraverseDb(dbs, dbFormat, &dbresult, nil) if err != nil { log.Errorf("TraverseDb() failure for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) @@ -373,8 +405,8 @@ func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string // Assumption: All tables are from the same DB func dbDataFromTblXfmrGet(tbl string, inParams XfmrParams, dbDataMap *map[db.DBNum]map[string]map[string]db.Value) error { - xpath, _ := RemoveXPATHPredicates(inParams.uri) - curDbDataMap, err := fillDbDataMapForTbl(inParams.uri, xpath, tbl, "", inParams.curDb, inParams.dbs) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) + curDbDataMap, err := fillDbDataMapForTbl(inParams.uri, xpath, tbl, inParams.key, inParams.curDb, inParams.dbs) if err == nil { mapCopy((*dbDataMap)[inParams.curDb], curDbDataMap[inParams.curDb]) } @@ -389,7 +421,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x xfmrTblFunc := *xYangSpecMap[xpath].xfmrTbl if len(xfmrTblFunc) > 0 { tblXfmr = true - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, tblKey, dbDataMap, nil) tblList = xfmrTblHandlerFunc(xfmrTblFunc, inParams) if len(tblList) != 0 { for _, curTbl := range tblList { @@ -423,7 +455,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x for k, kv := range curKeyMap { curMap[k] = kv } - curXpath, _ := RemoveXPATHPredicates(curUri) + curXpath, _ := XfmrRemoveXPATHPredicates(curUri) yangDataFill(dbs, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey, cdb, validate) mapSlice = append(mapSlice, curMap) } @@ -471,7 +503,7 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ if len(dbFldName) > 0 && !xYangSpecMap[xpath].isKey { yangType := yangTypeGet(xYangSpecMap[xpath].yangEntry) - if yangType == "leaf-list" { + if yangType == YANG_LEAF_LIST { dbFldName += "@" val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] if ok { @@ -518,7 +550,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } chldYangType := yangTypeGet(xYangSpecMap[chldXpath].yangEntry) - if chldYangType == "leaf" || chldYangType == "leaf-list" { + if chldYangType == YANG_LEAF || chldYangType == YANG_LEAF_LIST { fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) if err != nil { log.Infof("Failed to get data(\"%v\").", chldUri) @@ -526,12 +558,13 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath for lf, val := range fldValMap { resultMap[lf] = val } - } else if chldYangType == "container" { + } else if chldYangType == YANG_CONTAINER { cname := xYangSpecMap[chldXpath].yangEntry.Name if xYangSpecMap[chldXpath].xfmrTbl != nil { xfmrTblFunc := *xYangSpecMap[chldXpath].xfmrTbl if len(xfmrTblFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + //inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, tblKey, dbDataMap, nil) tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) if len(tblList) > 1 { log.Warningf("Table transformer returned more than one table for container %v", chldXpath) @@ -561,7 +594,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath log.Infof("Empty container(\"%v\").\r\n", chldUri) } } - } else if chldYangType == "list" { + } else if chldYangType == YANG_LIST { cdb = xYangSpecMap[chldXpath].dbIndex if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) @@ -600,71 +633,113 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db yangNode, ok := xYangSpecMap[reqXpath] if ok { yangType := yangTypeGet(yangNode.yangEntry) - if yangType == "leaf" || yangType == "leaf-list" { - //fldName := xYangSpecMap[reqXpath].fieldName + validateHandlerFlag := false + tableXfmrFlag := false + IsValidate := false + if len(xYangSpecMap[reqXpath].validateFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, keyName, dbDataMap, nil) + res := validateHandlerFunc(inParams) + if !res { + validateHandlerFlag = true + /* cannot immediately return from her since reXpath yangtype decides the return type */ + } else { + IsValidate = res + } + } + isList := false + switch yangType { + case YANG_LIST: + isList = true + case YANG_LEAF, YANG_LEAF_LIST, YANG_CONTAINER: + isList = false + default: + log.Infof("Unknown yang object type for path %v", reqXpath) + isList = true //do not want non-list processing to happen + } + /*If yangtype is a list separate code path is to be taken in case of table transformer + since that code path already handles the calling of table transformer and subsequent processing + */ + if (!validateHandlerFlag) && (!isList) { + if xYangSpecMap[reqXpath].xfmrTbl != nil { + xfmrTblFunc := *xYangSpecMap[reqXpath].xfmrTbl + if len(xfmrTblFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, keyName, dbDataMap, nil) + tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) + if len(tblList) > 1 { + log.Warningf("Table transformer returned more than one table for container %v", reqXpath) + tableXfmrFlag = true + } + if len(tblList) == 0 { + log.Warningf("Table transformer returned no table for conatiner %v", reqXpath) + tableXfmrFlag = true + } + if !tableXfmrFlag { + dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) + } + } else { + log.Warningf("empty table transformer function name for xpath - %v", reqXpath) + tableXfmrFlag = true + } + } + } + for { + if yangType == YANG_LEAF || yangType == YANG_LEAF_LIST { yangName := xYangSpecMap[reqXpath].yangEntry.Name + if validateHandlerFlag || tableXfmrFlag { + resultMap[yangName] = "" + break + } tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) - validateHandlerFlag := false - if len(xYangSpecMap[reqXpath].validateFunc) > 0 { - // TODO - handle non CONFIG-DB - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) - res := validateHandlerFunc(inParams) - if !res { - validateHandlerFlag = true - resultMap[yangName] = "" - } - } - if !validateHandlerFlag { - fldValMap, err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) - //err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) - if err != nil { - log.Infof("Empty terminal node (\"%v\").", uri) - } - resultMap = fldValMap - } - } else if yangType == "container" { + fldValMap, err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) + if err != nil { + log.Infof("Empty terminal node (\"%v\").", uri) + } + resultMap = fldValMap + break + + } else if yangType == YANG_CONTAINER { cname := xYangSpecMap[reqXpath].yangEntry.Name cmap := make(map[string]interface{}) - IsYangDataFill := true + if validateHandlerFlag || tableXfmrFlag { + resultMap[cname] = cmap + break + } if len(xYangSpecMap[reqXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) cmap, _ = xfmrHandlerFunc(inParams) if cmap != nil && len(cmap) > 0 { resultMap[cname] = cmap - IsYangDataFill = false - } - } else if xYangSpecMap[reqXpath].xfmrTbl != nil { - xfmrTblFunc := *xYangSpecMap[reqXpath].xfmrTbl - if len(xfmrTblFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) - tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) - if len(tblList) > 1 { - log.Warningf("Table transformer returned more than one table for container %v", reqXpath) - IsYangDataFill = false - } - if len(tblList) != 0 { - dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - if err != nil { - log.Infof("Empty container(\"%v\").\r\n", uri) - } - - } - - } else { - log.Warningf("empty table transformer function name for xpath - %v", reqXpath) - IsYangDataFill = false + break } } - if IsYangDataFill { - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - if err != nil { - log.Infof("Empty container(\"%v\").\r\n", uri) - } + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, IsValidate) + if err != nil { + log.Infof("Empty container(\"%v\").\r\n", uri) + } + break + } else if yangType == YANG_LIST { + var err error + var logStr string + if xYangSpecMap[reqXpath].xfmrTbl != nil { + /* pass empty table string since in case of list table transformer can have multiple tables returned, + which are already being fetched and handled in yangListDataFill + */ + err = yangListDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, "", keyName, cdb, IsValidate) + logStr = fmt.Sprintf("yangListDataFill failed for list case(\"%v\").\r\n", uri) + } else { + err = yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, IsValidate) + logStr = fmt.Sprintf("yangDataFill failed for list(\"%v\").\r\n", uri) + } + if err != nil { + log.Infof("%v", logStr) + } + break } else { - yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) + log.Warningf("Unknown yang object type for path %v", reqXpath) + break } + } //end of for } } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index b6fe747d84..9ca32132bc 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -18,7 +36,7 @@ import ( /* Invoke the post tansformer */ func postXfmrHandlerFunc(inParams XfmrParams) (map[string]map[string]db.Value, error) { - xpath, _ := RemoveXPATHPredicates(inParams.uri) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) ret, err := XlateFuncCall(xYangSpecMap[xpath].xfmrPost, inParams) if err != nil { return nil, err @@ -314,11 +332,20 @@ func sonicYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName str fieldName := tokens[len(tokens)-1] dbSpecField := tableName + "/" + fieldName _, ok := xDbSpecMap[dbSpecField] - if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { - // Specific leaf case - dbVal.Field = make(map[string]string) - dbVal.Field[fieldName] = "" - } + if ok { + yangType := xDbSpecMap[dbSpecField].fieldType + // terminal node case + if yangType == YANG_LEAF_LIST { + fieldName = fieldName + "@" + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = "" + } + if yangType == YANG_LEAF { + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = "" + } + + } } result[tableName][keyName] = dbVal } else { @@ -522,7 +549,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, func sonicXpathKeyExtract(path string) (string, string, string) { xpath, keyStr, tableName := "", "", "" var err error - xpath, err = RemoveXPATHPredicates(path) + xpath, err = XfmrRemoveXPATHPredicates(path) if err != nil { return xpath, keyStr, tableName } @@ -561,10 +588,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st cdb := db.ConfigDB var dbs [db.MaxDB]*db.DB - pfxPath, _ = RemoveXPATHPredicates(path) - if strings.Count(path, ":") > 1 { - pfxPath = stripAugmentedModuleNames(pfxPath) - } + pfxPath, _ = XfmrRemoveXPATHPredicates(path) xpathInfo, ok := xYangSpecMap[pfxPath] if !ok { log.Errorf("No entry found in xYangSpecMap for xpath %v.", pfxPath) @@ -583,7 +607,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st if len(keyStr) > 0 { keyStr += keySeparator } - yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) + yangXpath, _ := XfmrRemoveXPATHPredicates(curPathWithKey) _, ok := xYangSpecMap[yangXpath] if ok { if len(xYangSpecMap[yangXpath].xfmrKey) > 0 { diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 6afbeeaa74..05d2bc1715 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -431,3 +449,31 @@ func stripAugmentedModuleNames(xpath string) string { return path } +func XfmrRemoveXPATHPredicates(xpath string) (string, error) { + pathList := strings.Split(xpath, "/") + pathList = pathList[1:] + for i, pvar := range pathList { + if strings.Contains(pvar, "[") && strings.Contains(pvar, "]") { + si, ei := strings.Index(pvar, "["), strings.Index(pvar, "]") + // substring contains [] entries + if (si < ei) { + pvar = strings.Split(pvar, "[")[0] + pathList[i] = pvar + + } else { + // This substring contained a ] before a [. + return "", fmt.Errorf("Incorrect ordering of [] within substring %s of %s, [ pos: %d, ] pos: %d", pvar, xpath, si, ei) + } + } else if strings.Contains(pvar, "[") || strings.Contains(pvar, "]") { + // This substring contained a mismatched pair of []s. + return "", fmt.Errorf("Mismatched brackets within substring %s of %s", pvar, xpath) + } + if (i > 0) && strings.Contains(pvar, ":") { + pvar = strings.Split(pvar,":")[1] + pathList[i] = pvar + } + } + path := "/" + strings.Join(pathList, "/") + return path,nil +} + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 11198a645f..85cff79cd3 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// 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. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -261,7 +279,6 @@ func dbMapBuild(entries []*yang.Entry) { } moduleNm := e.Name log.Infof("Module name(%v)", moduleNm) - xDbSpecOrdTblMap[moduleNm] = []string{} trkTpCnt := true dbMapFill("", "", moduleNm, trkTpCnt, xDbSpecMap, e) } @@ -335,7 +352,7 @@ func annotEntryFill(xYangSpecMap map[string]*yangXpathInfo, xpath string, entry xpathData.validateFunc = ext.NName() case "use-self-key" : xpathData.keyXpath = nil - case "redis-db-name" : + case "db-name" : if ext.NName() == "APPL_DB" { xpathData.dbIndex = db.ApplDB } else if ext.NName() == "ASIC_DB" { @@ -562,7 +579,6 @@ func updateSchemaOrderedMap(module string, entry *yang.Entry) { } } } - xDbSpecOrdTblMap[module] = children } func updateChildTable(keyspec []KeySpec, chlist *[]string) ([]string) {