diff --git a/cvl/custom_validation/common.go b/cvl/custom_validation/common.go index 9a61ab2da..6128a7ccb 100644 --- a/cvl/custom_validation/common.go +++ b/cvl/custom_validation/common.go @@ -81,10 +81,10 @@ const ( // CVLEditConfigData Strcture for key and data in API type CVLEditConfigData struct { - VType CVLValidateType //Validation type - VOp CVLOperation //Operation type - Key string //Key format : "PORT|Ethernet4" - Data map[string]string //Value : {"alias": "40GE0/28", "mtu" : 9100, "admin_status": down} + VType CVLValidateType //Validation type + VOp CVLOperation //Operation type + Key string //Key format : "PORT|Ethernet4" + Data map[string]string //Value : {"alias": "40GE0/28", "mtu" : 9100, "admin_status": down} } // CVLErrorInfo CVL Error Structure diff --git a/cvl/cvl.go b/cvl/cvl.go index e2fc558e2..42c75b604 100644 --- a/cvl/cvl.go +++ b/cvl/cvl.go @@ -18,27 +18,28 @@ //////////////////////////////////////////////////////////////////////////////// package cvl + import ( "fmt" + "github.com/Azure/sonic-mgmt-common/cvl/internal/yparser" + "github.com/antchfx/jsonquery" + "github.com/antchfx/xmlquery" + "github.com/antchfx/xpath" + "github.com/go-redis/redis/v7" "os" - "strings" "regexp" + "strings" "time" - "github.com/go-redis/redis/v7" - "github.com/antchfx/xmlquery" - "github.com/antchfx/xpath" - "github.com/antchfx/jsonquery" - "github.com/Azure/sonic-mgmt-common/cvl/internal/yparser" //lint:ignore ST1001 This is safe to dot import for util package + custv "github.com/Azure/sonic-mgmt-common/cvl/custom_validation" . "github.com/Azure/sonic-mgmt-common/cvl/internal/util" - "sync" "io/ioutil" "path/filepath" - custv "github.com/Azure/sonic-mgmt-common/cvl/custom_validation" + "sync" "unsafe" ) -//DB number +// DB number const ( APPL_DB uint8 = 0 + iota ASIC_DB @@ -61,123 +62,122 @@ var reHashRef *regexp.Regexp = nil var cvlInitialized bool var dbNameToDbNum map[string]uint8 -//map of lua script loaded +// map of lua script loaded var luaScripts map[string]*redis.Script type tblFieldPair struct { tableName string - field string + field string } type mustInfo struct { - expr string //must expression + expr string //must expression exprTree *xpath.Expr //compiled expression tree - errCode string //err-app-tag - errStr string //error message + errCode string //err-app-tag + errStr string //error message } type leafRefInfo struct { - path string //leafref path - exprTree *xpath.Expr //compiled expression tree - yangListNames []string //all yang list in path - targetNodeName string //target node name + path string //leafref path + exprTree *xpath.Expr //compiled expression tree + yangListNames []string //all yang list in path + targetNodeName string //target node name } type whenInfo struct { - expr string //when expression - exprTree *xpath.Expr //compiled expression tree - nodeNames []string //list of nodes under when condition - yangListNames []string //all yang list in expression + expr string //when expression + exprTree *xpath.Expr //compiled expression tree + nodeNames []string //list of nodes under when condition + yangListNames []string //all yang list in expression } -//Important schema information to be loaded at bootup time +// Important schema information to be loaded at bootup time type modelTableInfo struct { - dbNum uint8 - modelName string - redisTableName string //To which Redis table it belongs to, used for 1 Redis to N Yang List - module *yparser.YParserModule - keys []string - redisKeyDelim string + dbNum uint8 + modelName string + redisTableName string //To which Redis table it belongs to, used for 1 Redis to N Yang List + module *yparser.YParserModule + keys []string + redisKeyDelim string redisKeyPattern string - redisTableSize int - mapLeaf []string //for 'mapping list' - leafRef map[string][]*leafRefInfo //for storing all leafrefs for a leaf in a table, - //multiple leafref possible for union - mustExpr map[string][]*mustInfo - whenExpr map[string][]*whenInfo + redisTableSize int + mapLeaf []string //for 'mapping list' + leafRef map[string][]*leafRefInfo //for storing all leafrefs for a leaf in a table, + //multiple leafref possible for union + mustExpr map[string][]*mustInfo + whenExpr map[string][]*whenInfo tablesForMustExp map[string]CVLOperation - refFromTables []tblFieldPair //list of table or table/field referring to this table - custValidation map[string]string // Map for custom validation node and function name - dfltLeafVal map[string]string //map of leaf names and default value - mandatoryNodes map[string]bool //map of leaf names and mandatory flag + refFromTables []tblFieldPair //list of table or table/field referring to this table + custValidation map[string]string // Map for custom validation node and function name + dfltLeafVal map[string]string //map of leaf names and default value + mandatoryNodes map[string]bool //map of leaf names and mandatory flag } - // CVLErrorInfo Struct for CVL Error Info type CVLErrorInfo struct { - TableName string /* Table having error */ - ErrCode CVLRetCode /* CVL Error return Code. */ - CVLErrDetails string /* CVL Error Message details. */ - Keys []string /* Keys of the Table having error. */ - Value string /* Field Value throwing error */ - Field string /* Field Name throwing error . */ - Msg string /* Detailed error message. */ - ConstraintErrMsg string /* Constraint error message. */ - ErrAppTag string + TableName string /* Table having error */ + ErrCode CVLRetCode /* CVL Error return Code. */ + CVLErrDetails string /* CVL Error Message details. */ + Keys []string /* Keys of the Table having error. */ + Value string /* Field Value throwing error */ + Field string /* Field Name throwing error . */ + Msg string /* Detailed error message. */ + ConstraintErrMsg string /* Constraint error message. */ + ErrAppTag string } // Struct for request data and YANG data type requestCacheType struct { - reqData CVLEditConfigData + reqData CVLEditConfigData yangData *xmlquery.Node } -// CVL Struct for CVL session +// CVL Struct for CVL session type CVL struct { //redisClient *redis.Client - yp *yparser.YParser - tmpDbCache map[string]interface{} //map of table storing map of key-value pair - requestCache map[string]map[string][]*requestCacheType//Cache of validated data, - //per table, per key. Can be used as dependent data in next request - maxTableElem map[string]int //max element count per table - batchLeaf []*yparser.YParserLeafValue //field name and value - yv *YValidator //Custom YANG validator for validating external dependencies - custvCache custv.CustValidationCache //Custom validation cache per session + yp *yparser.YParser + tmpDbCache map[string]interface{} //map of table storing map of key-value pair + requestCache map[string]map[string][]*requestCacheType //Cache of validated data, + //per table, per key. Can be used as dependent data in next request + maxTableElem map[string]int //max element count per table + batchLeaf []*yparser.YParserLeafValue //field name and value + yv *YValidator //Custom YANG validator for validating external dependencies + custvCache custv.CustValidationCache //Custom validation cache per session } // Struct for model namepsace and prefix type modelNamespace struct { prefix string - ns string + ns string } // Struct for storing all YANG list schema info type modelDataInfo struct { - modelNs map[string]*modelNamespace //model namespace - tableInfo map[string]*modelTableInfo //redis table to model name and keys - redisTableToYangList map[string][]string //Redis table to all YANG lists when it is not 1:1 mapping - allKeyDelims map[string]bool + modelNs map[string]*modelNamespace //model namespace + tableInfo map[string]*modelTableInfo //redis table to model name and keys + redisTableToYangList map[string][]string //Redis table to all YANG lists when it is not 1:1 mapping + allKeyDelims map[string]bool } -//Global data cache for redis table +// Global data cache for redis table type cvlGlobalSessionType struct { stopChan chan int //stop channel to stop notification listener - cv *CVL - mutex *sync.Mutex + cv *CVL + mutex *sync.Mutex } // Struct for storing key and value pair type keyValuePairStruct struct { - key string + key string values []string } var cvg cvlGlobalSessionType -//Single redis client for validation +// Single redis client for validation var redisClient *redis.Client -//Stores important model info +// Stores important model info var modelInfo modelDataInfo func TRACE_LOG(tracelevel CVLTraceLevel, fmtStr string, args ...interface{}) { @@ -188,13 +188,13 @@ func CVL_LOG(level CVLLogLevel, fmtStr string, args ...interface{}) { CVL_LEVEL_LOG(level, fmtStr, args...) } -//package init function +// package init function func init() { - if (os.Getenv("CVL_SCHEMA_PATH") != "") { + if os.Getenv("CVL_SCHEMA_PATH") != "" { CVL_SCHEMA = os.Getenv("CVL_SCHEMA_PATH") + "/" } - if (os.Getenv("CVL_DEBUG") != "") { + if os.Getenv("CVL_DEBUG") != "" { SetTrace(true) } @@ -206,13 +206,12 @@ func init() { return nil }) - ConfigFileSyncHandler() cvlCfgMap := ReadConfFile() - if (cvlCfgMap != nil) { - CVL_LOG(INFO ,"Current Values of CVL Configuration File %v", cvlCfgMap) + if cvlCfgMap != nil { + CVL_LOG(INFO, "Current Values of CVL Configuration File %v", cvlCfgMap) } //regular expression for leafref and hashref finding @@ -235,7 +234,7 @@ func init() { _, err := redisClient.ConfigSet("notify-keyspace-events", "AKE").Result() if err != nil { - CVL_LOG(WARNING ,"Could not enable notification error %s", err) + CVL_LOG(WARNING, "Could not enable notification error %s", err) } xpath.SetLogCallback(func(fmt string, args ...interface{}) { @@ -243,7 +242,7 @@ func init() { return } - TRACE_LOG(TRACE_SEMANTIC, "XPATH: " + fmt, args...) + TRACE_LOG(TRACE_SEMANTIC, "XPATH: "+fmt, args...) }) } @@ -264,16 +263,16 @@ func getNodeName(node *xmlquery.Node) string { return node.Data } -// Load all YIN schema files, apply deviation files +// Load all YIN schema files, apply deviation files func loadSchemaFiles() CVLRetCode { platformName := "" // Wait to check if CONFIG_DB is populated with DEVICE_METADATA. // This is needed to apply deviation file retryCnt := 0 - for ; (retryCnt < MAX_DEVICE_METADATA_FETCH_RETRY); retryCnt++ { + for ; retryCnt < MAX_DEVICE_METADATA_FETCH_RETRY; retryCnt++ { deviceMetaDataKey, err := redisClient.Keys("DEVICE_METADATA|localhost").Result() - if (err != nil) || (len(deviceMetaDataKey) == 0) { + if (err != nil) || (len(deviceMetaDataKey) == 0) { //Retry for 1 min time.Sleep(100 * time.Millisecond) //sleep for 1 sec and then retry continue @@ -284,7 +283,7 @@ func loadSchemaFiles() CVLRetCode { } //Now try to fetch the platform details - if (retryCnt < MAX_DEVICE_METADATA_FETCH_RETRY) { + if retryCnt < MAX_DEVICE_METADATA_FETCH_RETRY { deviceMetaData, err := redisClient.HGetAll("DEVICE_METADATA|localhost").Result() var exists bool platformName, exists = deviceMetaData["platform"] @@ -296,7 +295,7 @@ func loadSchemaFiles() CVLRetCode { //Scan schema directory to get all schema files modelFiles, err := filepath.Glob(CVL_SCHEMA + "/*.yin") if err != nil { - CVL_LOG(FATAL ,"Could not read schema files %v", err) + CVL_LOG(FATAL, "Could not read schema files %v", err) } moduleMap := map[string]*yparser.YParserModule{} @@ -305,33 +304,33 @@ func loadSchemaFiles() CVLRetCode { _, modelFile := filepath.Split(modelFilePath) TRACE_LOG(TRACE_LIBYANG, "Parsing schema file %s ...", - modelFilePath) + modelFilePath) - // Now parse each schema file + // Now parse each schema file var module *yparser.YParserModule if module, _ = yparser.ParseSchemaFile(modelFilePath); module == nil { - CVL_LOG(FATAL,fmt.Sprintf("Unable to parse schema file %s", modelFile)) + CVL_LOG(FATAL, fmt.Sprintf("Unable to parse schema file %s", modelFile)) return CVL_ERROR } moduleMap[modelFile] = module } - // Load all platform specific schema files based on platform details + // Load all platform specific schema files based on platform details // present in DEVICE_METADATA for { - if (platformName == "") { - CVL_LOG(INFO, "Skipping parsing of any platform specific YIN schema " + - "files as platform name can't be determined") + if platformName == "" { + CVL_LOG(INFO, "Skipping parsing of any platform specific YIN schema "+ + "files as platform name can't be determined") break } // Read directory under 'platform' directory allDirs, errDir := ioutil.ReadDir(CVL_SCHEMA + "/" + PLATFORM_SCHEMA_PATH) if (errDir != nil) || (len(allDirs) == 0) { - CVL_LOG(INFO, "Could not read platform schema location or no platform " + - "specific schema exists. %v", err) + CVL_LOG(INFO, "Could not read platform schema location or no platform "+ + "specific schema exists. %v", err) break } @@ -346,18 +345,17 @@ func loadSchemaFiles() CVLRetCode { //Get all platform specific YIN schema file names modelFiles, err := filepath.Glob(CVL_SCHEMA + "/" + - PLATFORM_SCHEMA_PATH + "/" + sDirName + "/*.yin") + PLATFORM_SCHEMA_PATH + "/" + sDirName + "/*.yin") if err != nil { - CVL_LOG(WARNING,"Could not read platform schema directory %v", err) + CVL_LOG(WARNING, "Could not read platform schema directory %v", err) break } - //Now parse platform schema files for _, modelFilePath := range modelFiles { _, modelFile := filepath.Split(modelFilePath) - TRACE_LOG(TRACE_YPARSER, "Parsing platform specific schema" + "file %s ...\n", modelFilePath) + TRACE_LOG(TRACE_YPARSER, "Parsing platform specific schema"+"file %s ...\n", modelFilePath) var module *yparser.YParserModule if module, _ = yparser.ParseSchemaFile(modelFilePath); module == nil { @@ -384,7 +382,7 @@ func loadSchemaFiles() CVLRetCode { return CVL_SUCCESS } -//Get list of YANG list names used in xpath expression +// Get list of YANG list names used in xpath expression func getYangListNamesInExpr(expr string) []string { tbl := []string{} @@ -393,7 +391,7 @@ func getYangListNamesInExpr(expr string) []string { //Match 1 - Prefix is used in path //Match 2 - Prefix is not used in path, it is in same YANG model - if strings.Contains(expr, ":" + tblName + "_LIST") || strings.Contains(expr, "/" + tblName + "_LIST") { + if strings.Contains(expr, ":"+tblName+"_LIST") || strings.Contains(expr, "/"+tblName+"_LIST") { tbl = append(tbl, tblName) } } @@ -401,9 +399,9 @@ func getYangListNamesInExpr(expr string) []string { return tbl } -//Get all YANG lists referred and the target node for leafref -//Ex: leafref { path "../../../ACL_TABLE/ACL_TABLE_LIST[aclname=current()]/aclname";} -//will return [ACL_TABLE] and aclname +// Get all YANG lists referred and the target node for leafref +// Ex: leafref { path "../../../ACL_TABLE/ACL_TABLE_LIST[aclname=current()]/aclname";} +// will return [ACL_TABLE] and aclname func getLeafRefTargetInfo(path string) ([]string, string) { target := "" @@ -414,7 +412,7 @@ func getLeafRefTargetInfo(path string) ([]string, string) { idx := strings.LastIndex(path, ":") //check with prefix first if idx > 0 { target = path[idx+1:] - } else if idx = strings.LastIndex(path, "/"); idx > 0{ //no prefix there + } else if idx = strings.LastIndex(path, "/"); idx > 0 { //no prefix there target = path[idx+1:] } @@ -428,19 +426,18 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //Store namespace and prefix ns, prefix := yparser.GetModelNs(module) - modelInfo.modelNs[modelName] = &modelNamespace{ns:ns, prefix:prefix} + modelInfo.modelNs[modelName] = &modelNamespace{ns: ns, prefix: prefix} list := yparser.GetModelListInfo(module) - if (list == nil) { + if list == nil { CVL_LOG(WARNING, "Unable to get schema details for %s", modelFile) return } - for _, lInfo := range list { TRACE_LOG(TRACE_YPARSER, - "Storing schema details for list %s", lInfo.ListName) + "Storing schema details for list %s", lInfo.ListName) tInfo := modelTableInfo{modelName: modelName} @@ -462,7 +459,7 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { } //Store leafref details - tInfo.leafRef = make(map[string][]*leafRefInfo, len(lInfo.LeafRef)) + tInfo.leafRef = make(map[string][]*leafRefInfo, len(lInfo.LeafRef)) for nodeName, lpathArr := range lInfo.LeafRef { //for each leaf or leaf-list leafRefInfoArr := []*leafRefInfo{} for _, lpath := range lpathArr { @@ -478,11 +475,11 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { for nodeName, xprArr := range lInfo.XpathExpr { for _, xpr := range xprArr { tInfo.mustExpr[nodeName] = append(tInfo.mustExpr[nodeName], - &mustInfo{ - expr: xpr.Expr, - errCode: xpr.ErrCode, - errStr: xpr.ErrStr, - }) + &mustInfo{ + expr: xpr.Expr, + errCode: xpr.ErrCode, + errStr: xpr.ErrStr, + }) } } @@ -491,10 +488,10 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { for nodeName, whenExprArr := range lInfo.WhenExpr { for _, whenExpr := range whenExprArr { tInfo.whenExpr[nodeName] = append(tInfo.whenExpr[nodeName], - &whenInfo { - expr: whenExpr.Expr, - nodeNames: whenExpr.NodeNames, - }) + &whenInfo{ + expr: whenExpr.Expr, + nodeNames: whenExpr.NodeNames, + }) } } @@ -510,8 +507,8 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { // Get YANG list to Redis table name func getYangListToRedisTbl(yangListName string) string { - if (strings.HasSuffix(yangListName, "_LIST")) { - yangListName = yangListName[0:len(yangListName) - len("_LIST")] + if strings.HasSuffix(yangListName, "_LIST") { + yangListName = yangListName[0 : len(yangListName)-len("_LIST")] } tInfo, exists := modelInfo.tableInfo[yangListName] @@ -522,27 +519,27 @@ func getYangListToRedisTbl(yangListName string) string { return yangListName } -//This functions build info of dependent table/fields -//which uses a particular table through leafref +// This functions build info of dependent table/fields +// which uses a particular table through leafref func buildRefTableInfo() { CVL_LOG(INFO_API, "Building reverse reference info from leafref") for tblName, tblInfo := range modelInfo.tableInfo { - if (len(tblInfo.leafRef) == 0) { + if len(tblInfo.leafRef) == 0 { continue } //For each leafref update the table used through leafref - for fieldName, leafRefs := range tblInfo.leafRef { + for fieldName, leafRefs := range tblInfo.leafRef { for _, leafRef := range leafRefs { for _, yangListName := range leafRef.yangListNames { - refTblInfo := modelInfo.tableInfo[yangListName] + refTblInfo := modelInfo.tableInfo[yangListName] refFromTables := &refTblInfo.refFromTables - *refFromTables = append(*refFromTables, tblFieldPair{tblName, fieldName}) - modelInfo.tableInfo[yangListName] = refTblInfo + *refFromTables = append(*refFromTables, tblFieldPair{tblName, fieldName}) + modelInfo.tableInfo[yangListName] = refTblInfo } } @@ -550,30 +547,30 @@ func buildRefTableInfo() { } - //Now sort list 'refFromTables' under each table based on dependency among them + //Now sort list 'refFromTables' under each table based on dependency among them for tblName, tblInfo := range modelInfo.tableInfo { - if (len(tblInfo.refFromTables) == 0) { + if len(tblInfo.refFromTables) == 0 { continue } depTableList := []string{} - for i:=0; i < len(tblInfo.refFromTables); i++ { + for i := 0; i < len(tblInfo.refFromTables); i++ { depTableList = append(depTableList, tblInfo.refFromTables[i].tableName) } sortedTableList, _ := cvg.cv.SortDepTables(depTableList) - if (len(sortedTableList) == 0) { + if len(sortedTableList) == 0 { continue } newRefFromTables := []tblFieldPair{} - for i:=0; i < len(sortedTableList); i++ { + for i := 0; i < len(sortedTableList); i++ { //Find fieldName fieldName := "" - for j :=0; j < len(tblInfo.refFromTables); j++ { - if (sortedTableList[i] == tblInfo.refFromTables[j].tableName) { - fieldName = tblInfo.refFromTables[j].field + for j := 0; j < len(tblInfo.refFromTables); j++ { + if sortedTableList[i] == tblInfo.refFromTables[j].tableName { + fieldName = tblInfo.refFromTables[j].field newRefFromTables = append(newRefFromTables, tblFieldPair{sortedTableList[i], fieldName}) } } @@ -585,12 +582,12 @@ func buildRefTableInfo() { } -//Find the tables names in must expression, these tables data need to be fetched -//during semantic validation +// Find the tables names in must expression, these tables data need to be fetched +// during semantic validation func addTableNamesForMustExp() { - for tblName, tblInfo := range modelInfo.tableInfo { - if (len(tblInfo.mustExpr) == 0) { + for tblName, tblInfo := range modelInfo.tableInfo { + if len(tblInfo.mustExpr) == 0 { continue } @@ -613,15 +610,15 @@ func addTableNamesForMustExp() { //store the current table if aggregate function like count() is used //check which table name is present in the must expression for tblNameSrch := range modelInfo.tableInfo { - if (tblNameSrch == tblName) { + if tblNameSrch == tblName { continue } //Table name should appear like "../VLAN_MEMBER_LIST/tagging_mode' or ' // "/prt:PORT/prt:ifname" re := regexp.MustCompile(fmt.Sprintf(".*[/]([-_a-zA-Z]*:)?%s_LIST[\\[/]?", tblNameSrch)) matches := re.FindStringSubmatch(mustExp.expr) - if (len(matches) > 0) { - //stores the table name + if len(matches) > 0 { + //stores the table name tblInfo.tablesForMustExp[tblNameSrch] = op } } @@ -633,23 +630,23 @@ func addTableNamesForMustExp() { } } -//Split key into table prefix and key +// Split key into table prefix and key func splitRedisKey(key string) (string, string) { var foundIdx int = -1 //Check with all key delim for keyDelim := range modelInfo.allKeyDelims { foundIdx = strings.Index(key, keyDelim) - if (foundIdx >= 0) { + if foundIdx >= 0 { //Matched with key delim break } } - if (foundIdx < 0) { + if foundIdx < 0 { //No matches CVL_LOG(WARNING, "Could not find any of key delimeter %v in key '%s'", - modelInfo.allKeyDelims, key) + modelInfo.allKeyDelims, key) return "", "" } @@ -663,9 +660,8 @@ func splitRedisKey(key string) (string, string) { prefixLen := foundIdx + 1 - TRACE_LOG(TRACE_SYNTAX, "Split Redis Key %s into (%s, %s)", - key, tblName, key[prefixLen:]) + key, tblName, key[prefixLen:]) return tblName, key[prefixLen:] } @@ -677,17 +673,17 @@ func splitKeyComponents(table, keyComps string) []string { return nil } -//Get the YANG list name from Redis key and table name -//This just returns same YANG list name as Redis table name -//when 1:1 mapping is there. For one Redis table to -//multiple YANG list, it returns appropriate YANG list name -//INTERFACE:Ethernet12 returns ==> INTERFACE -//INTERFACE:Ethernet12:1.1.1.0/32 ==> INTERFACE_IPADDR +// Get the YANG list name from Redis key and table name +// This just returns same YANG list name as Redis table name +// when 1:1 mapping is there. For one Redis table to +// multiple YANG list, it returns appropriate YANG list name +// INTERFACE:Ethernet12 returns ==> INTERFACE +// INTERFACE:Ethernet12:1.1.1.0/32 ==> INTERFACE_IPADDR func getRedisTblToYangList(tableName, key string) (yangList string) { defer func() { pYangList := &yangList - TRACE_LOG(TRACE_SYNTAX, "Got YANG list '%s' " + - "from Redis Table '%s', Key '%s'", *pYangList, tableName, key) + TRACE_LOG(TRACE_SYNTAX, "Got YANG list '%s' "+ + "from Redis Table '%s', Key '%s'", *pYangList, tableName, key) }() mapArr, exists := modelInfo.redisTableToYangList[tableName] @@ -702,7 +698,7 @@ func getRedisTblToYangList(tableName, key string) (yangList string) { numOfKeys := 1 //Assume only one key initially for keyDelim := range modelInfo.allKeyDelims { foundIdx = strings.Index(key, keyDelim) - if (foundIdx >= 0) { + if foundIdx >= 0 { //Matched with key delim keyComps := strings.Split(key, keyDelim) numOfKeys = len(keyComps) @@ -710,11 +706,11 @@ func getRedisTblToYangList(tableName, key string) (yangList string) { } } - //Check which list has number of keys as 'numOfKeys' + //Check which list has number of keys as 'numOfKeys' for i := 0; i < len(mapArr); i++ { tblInfo, exists := modelInfo.tableInfo[mapArr[i]] if exists { - if (len(tblInfo.keys) == numOfKeys) { + if len(tblInfo.keys) == numOfKeys { //Found the YANG list matching the number of keys return mapArr[i] } @@ -725,63 +721,63 @@ func getRedisTblToYangList(tableName, key string) (yangList string) { return tableName } -//Convert Redis key to Yang keys, if multiple key components are there, -//they are separated based on Yang schema -func getRedisToYangKeys(tableName string, redisKey string)[]keyValuePairStruct{ +// Convert Redis key to Yang keys, if multiple key components are there, +// they are separated based on Yang schema +func getRedisToYangKeys(tableName string, redisKey string) []keyValuePairStruct { keyNames := modelInfo.tableInfo[tableName].keys //First split all the keys components keyVals := strings.Split(redisKey, modelInfo.tableInfo[tableName].redisKeyDelim) //split by DB separator //Store patterns for each key components by splitting using key delim keyPatterns := strings.Split(modelInfo.tableInfo[tableName].redisKeyPattern, - modelInfo.tableInfo[tableName].redisKeyDelim) //split by DB separator + modelInfo.tableInfo[tableName].redisKeyDelim) //split by DB separator /* TBD. Workaround for optional keys in INTERFACE Table. Code will be removed once model is finalized. */ - if ((tableName == "INTERFACE") && (len(keyNames) != len(keyVals))) { + if (tableName == "INTERFACE") && (len(keyNames) != len(keyVals)) { keyVals = append(keyVals, "0.0.0.0/0") - } else if (len(keyNames) != len(keyVals)) { + } else if len(keyNames) != len(keyVals) { return nil //number key names and values does not match } mkeys := []keyValuePairStruct{} //For each key check the pattern and store key/value pair accordingly - for idx, keyName := range keyNames { + for idx, keyName := range keyNames { //check if key-pattern contains specific key pattern - if (keyPatterns[idx+1] == ("{" + keyName + "}")) { //no specific key pattern - just "{key}" - //Store key/value mapping - mkeys = append(mkeys, keyValuePairStruct{keyName, []string{keyVals[idx]}}) - } else if (keyPatterns[idx+1] == ("({" + keyName + "},)*")) { // key pattern is "({key},)*" i.e. repeating keys seperated by ',' + if keyPatterns[idx+1] == ("{" + keyName + "}") { //no specific key pattern - just "{key}" + //Store key/value mapping + mkeys = append(mkeys, keyValuePairStruct{keyName, []string{keyVals[idx]}}) + } else if keyPatterns[idx+1] == ("({" + keyName + "},)*") { // key pattern is "({key},)*" i.e. repeating keys seperated by ',' repeatedKeys := strings.Split(keyVals[idx], ",") mkeys = append(mkeys, keyValuePairStruct{keyName, repeatedKeys}) } } - TRACE_LOG(TRACE_SYNTAX, "getRedisToYangKeys() returns %v " + - "from Redis Table '%s', Key '%s'", mkeys, tableName, redisKey) + TRACE_LOG(TRACE_SYNTAX, "getRedisToYangKeys() returns %v "+ + "from Redis Table '%s', Key '%s'", mkeys, tableName, redisKey) return mkeys } -//Checks field map values and removes "NULL" entry, create array for leaf-list +// Checks field map values and removes "NULL" entry, create array for leaf-list func (c *CVL) checkFieldMap(fieldMap *map[string]string) map[string]interface{} { fieldMapNew := map[string]interface{}{} for field, value := range *fieldMap { - if (field == "NULL") { + if field == "NULL" { continue - } else if (field[len(field)-1:] == "@") { + } else if field[len(field)-1:] == "@" { //last char @ means it is a leaf-list/array of fields field = field[:len(field)-1] //strip @ //split the values seprated using ',' strArr := strings.Split(value, ",") //fieldMapNew[field] = strings.Split(value, ",") - arrMap := make([]interface{}, 0)//len(strArr)) + arrMap := make([]interface{}, 0) //len(strArr)) for _, strArrItem := range strArr { arrMap = append(arrMap, strArrItem) } - fieldMapNew[field] = arrMap//make([]interface{}, len(strArr)) + fieldMapNew[field] = arrMap //make([]interface{}, len(strArr)) } else { fieldMapNew[field] = value } @@ -790,10 +786,10 @@ func (c *CVL) checkFieldMap(fieldMap *map[string]string) map[string]interface{} return fieldMapNew } -//Merge 'src' map to 'dest' map of map[string]string type +// Merge 'src' map to 'dest' map of map[string]string type func mergeMap(dest map[string]string, src map[string]string) { TRACE_LOG(TRACE_SEMANTIC, - "Merging map %v into %v", src, dest) + "Merging map %v into %v", src, dest) for key, data := range src { dest[key] = data @@ -802,39 +798,39 @@ func mergeMap(dest map[string]string, src map[string]string) { func (c *CVL) translateToYang(jsonMap *map[string]interface{}) (*yparser.YParserNode, CVLErrorInfo) { - var cvlErrObj CVLErrorInfo + var cvlErrObj CVLErrorInfo //Parse the map data to json tree data, _ := jsonquery.ParseJsonMap(jsonMap) var root *yparser.YParserNode root = nil var errObj yparser.YParserError - for jsonNode := data.FirstChild; jsonNode != nil; jsonNode=jsonNode.NextSibling { + for jsonNode := data.FirstChild; jsonNode != nil; jsonNode = jsonNode.NextSibling { TRACE_LOG(TRACE_LIBYANG, "Translating, Top Node=%v\n", jsonNode.Data) //Visit each top level list in a loop for creating table data - topNode, cvlErrObj := c.generateTableData(true, jsonNode) + topNode, cvlErrObj := c.generateTableData(true, jsonNode) //Generate YANG data for Yang Validator topYangNode, cvlYErrObj := c.generateYangListData(jsonNode, true) - if topNode == nil { + if topNode == nil { cvlErrObj.ErrCode = CVL_SYNTAX_ERROR CVL_LOG(WARNING, "Unable to translate request data to YANG format") return nil, cvlErrObj } - if topYangNode == nil { + if topYangNode == nil { cvlYErrObj.ErrCode = CVL_SYNTAX_ERROR CVL_LOG(WARNING, "Unable to translate request data to YANG format") return nil, cvlYErrObj } - if (root == nil) { + if root == nil { root = topNode } else { if root, errObj = c.yp.MergeSubtree(root, topNode); errObj.ErrCode != yparser.YP_SUCCESS { - CVL_LOG(WARNING, "Unable to merge translated YANG data(libyang) " + - "while translating from request data to YANG format") + CVL_LOG(WARNING, "Unable to merge translated YANG data(libyang) "+ + "while translating from request data to YANG format") return nil, cvlErrObj } } @@ -845,29 +841,29 @@ func (c *CVL) translateToYang(jsonMap *map[string]interface{}) (*yparser.YParser doc.LastChild = topYangNode topYangNode.Parent = doc - if (IsTraceLevelSet(TRACE_CACHE)) { + if IsTraceLevelSet(TRACE_CACHE) { TRACE_LOG(TRACE_CACHE, "Before merge, YANG data tree = %s, source = %s", - c.yv.root.OutputXML(false), - doc.OutputXML(false)) + c.yv.root.OutputXML(false), + doc.OutputXML(false)) } if c.mergeYangData(c.yv.root, doc) != CVL_SUCCESS { - CVL_LOG(WARNING, "Unable to merge translated YANG data while " + - "translating from request data to YANG format") + CVL_LOG(WARNING, "Unable to merge translated YANG data while "+ + "translating from request data to YANG format") cvlYErrObj.ErrCode = CVL_SYNTAX_ERROR return nil, cvlErrObj } - if (IsTraceLevelSet(TRACE_CACHE)) { + if IsTraceLevelSet(TRACE_CACHE) { TRACE_LOG(TRACE_CACHE, "After merge, YANG data tree = %s", - c.yv.root.OutputXML(false)) + c.yv.root.OutputXML(false)) } } return root, cvlErrObj } -//Validate config - syntax and semantics -func (c *CVL) validate (data *yparser.YParserNode) CVLRetCode { +// Validate config - syntax and semantics +func (c *CVL) validate(data *yparser.YParserNode) CVLRetCode { depData := c.fetchDataToTmpCache() @@ -885,7 +881,7 @@ func (c *CVL) validate (data *yparser.YParserNode) CVLRetCode { return CVL_SUCCESS } -func createCVLErrObj(errObj yparser.YParserError, srcNode *jsonquery.Node) CVLErrorInfo { +func createCVLErrObj(errObj yparser.YParserError, srcNode *jsonquery.Node) CVLErrorInfo { errCode := CVLRetCode(errObj.ErrCode) if errObj.ErrCode == yparser.YP_INTERNAL_UNKNOWN { errCode = CVL_INTERNAL_UNKNOWN @@ -902,24 +898,23 @@ func createCVLErrObj(errObj yparser.YParserError, srcNode *jsonquery.Node) CVLE } } - cvlErrObj := CVLErrorInfo { - TableName : errObj.TableName, - ErrCode : errCode, - CVLErrDetails : cvlErrorMap[errCode], - Keys : errObj.Keys, - Value : errObj.Value, - Field : errObj.Field, - Msg : errObj.Msg, - ConstraintErrMsg : errObj.ErrTxt, - ErrAppTag : errObj.ErrAppTag, + cvlErrObj := CVLErrorInfo{ + TableName: errObj.TableName, + ErrCode: errCode, + CVLErrDetails: cvlErrorMap[errCode], + Keys: errObj.Keys, + Value: errObj.Value, + Field: errObj.Field, + Msg: errObj.Msg, + ConstraintErrMsg: errObj.ErrTxt, + ErrAppTag: errObj.ErrAppTag, } - return cvlErrObj } -//Perform syntax checks +// Perform syntax checks func (c *CVL) validateSyntax(data *yparser.YParserNode) (CVLErrorInfo, CVLRetCode) { var cvlErrObj CVLErrorInfo TRACE_LOG(TRACE_YPARSER, "Validating syntax ....") @@ -927,50 +922,50 @@ func (c *CVL) validateSyntax(data *yparser.YParserNode) (CVLErrorInfo, CVLRetCod //Get dependent data from Redis depData := c.fetchDataToTmpCache() //fetch data to temp cache for temporary validation - if errObj := c.yp.ValidateSyntax(data, depData); errObj.ErrCode != yparser.YP_SUCCESS { + if errObj := c.yp.ValidateSyntax(data, depData); errObj.ErrCode != yparser.YP_SUCCESS { retCode := CVLRetCode(errObj.ErrCode) - cvlErrObj = CVLErrorInfo { - TableName : errObj.TableName, - ErrCode : CVLRetCode(errObj.ErrCode), - CVLErrDetails : cvlErrorMap[retCode], - Keys : errObj.Keys, - Value : errObj.Value, - Field : errObj.Field, - Msg : errObj.Msg, - ConstraintErrMsg : errObj.ErrTxt, - ErrAppTag : errObj.ErrAppTag, - } + cvlErrObj = CVLErrorInfo{ + TableName: errObj.TableName, + ErrCode: CVLRetCode(errObj.ErrCode), + CVLErrDetails: cvlErrorMap[retCode], + Keys: errObj.Keys, + Value: errObj.Value, + Field: errObj.Field, + Msg: errObj.Msg, + ConstraintErrMsg: errObj.ErrTxt, + ErrAppTag: errObj.ErrAppTag, + } - CVL_LOG(WARNING,"Syntax validation failed. Error - %v", cvlErrObj) + CVL_LOG(WARNING, "Syntax validation failed. Error - %v", cvlErrObj) - return cvlErrObj, retCode + return cvlErrObj, retCode } return cvlErrObj, CVL_SUCCESS } -//Add config data item to accumulate per table +// Add config data item to accumulate per table func (c *CVL) addCfgDataItem(configData *map[string]interface{}, - cfgDataItem CVLEditConfigData) (string, string){ + cfgDataItem CVLEditConfigData) (string, string) { var cfgData map[string]interface{} = *configData tblName, key := splitRedisKey(cfgDataItem.Key) - if (tblName == "" || key == "") { + if tblName == "" || key == "" { //Bad redis key return "", "" } if _, existing := cfgData[tblName]; existing { fieldsMap := cfgData[tblName].(map[string]interface{}) - if (cfgDataItem.VOp == OP_DELETE) { + if cfgDataItem.VOp == OP_DELETE { return tblName, key } fieldsMap[key] = c.checkFieldMap(&cfgDataItem.Data) } else { fieldsMap := make(map[string]interface{}) - if (cfgDataItem.VOp == OP_DELETE) { + if cfgDataItem.VOp == OP_DELETE { fieldsMap[key] = nil } else { fieldsMap[key] = c.checkFieldMap(&cfgDataItem.Data) @@ -981,13 +976,13 @@ func (c *CVL) addCfgDataItem(configData *map[string]interface{}, return tblName, key } -//Perform user defined custom validation +// Perform user defined custom validation func (c *CVL) doCustomValidation(node *xmlquery.Node, custvCfg []custv.CVLEditConfigData, curCustvCfg *custv.CVLEditConfigData, yangListName, tbl, key string) CVLErrorInfo { - cvlErrObj := CVLErrorInfo{ErrCode : CVL_SUCCESS} + cvlErrObj := CVLErrorInfo{ErrCode: CVL_SUCCESS} // yangListName provides the correct table name defined in sonic-yang // For ex. VLAN_INTERFACE_LIST and VLAN_INTERFACE_IPADDR_LIST are in same container @@ -996,14 +991,13 @@ func (c *CVL) doCustomValidation(node *xmlquery.Node, //node value is empty for custom validation function at list level nodeVal := "" if !strings.HasSuffix(nodeName, "_LIST") { - for nodeLeaf := node.FirstChild; nodeLeaf != nil; - nodeLeaf = nodeLeaf.NextSibling { - if (nodeName != nodeLeaf.Data) { + for nodeLeaf := node.FirstChild; nodeLeaf != nil; nodeLeaf = nodeLeaf.NextSibling { + if nodeName != nodeLeaf.Data { continue } if (len(nodeLeaf.Attr) > 0) && - (nodeLeaf.Attr[0].Name.Local == "leaf-list") { + (nodeLeaf.Attr[0].Name.Local == "leaf-list") { nodeVal = curCustvCfg.Data[nodeName] } else { nodeVal = nodeLeaf.FirstChild.Data @@ -1015,20 +1009,20 @@ func (c *CVL) doCustomValidation(node *xmlquery.Node, //Call custom validation functions CVL_LOG(INFO_TRACE, "Calling custom validation function %s", custFunc) pCustv := &custv.CustValidationCtxt{ - ReqData: custvCfg, - CurCfg: curCustvCfg, + ReqData: custvCfg, + CurCfg: curCustvCfg, YNodeName: nodeName, - YNodeVal: nodeVal, - YCur: node, + YNodeVal: nodeVal, + YCur: node, SessCache: &(c.custvCache), - RClient: redisClient} + RClient: redisClient} errObj := custv.InvokeCustomValidation(&custv.CustomValidation{}, - custFunc, pCustv) + custFunc, pCustv) cvlErrObj = *(*CVLErrorInfo)(unsafe.Pointer(&errObj)) - if (cvlErrObj.ErrCode != CVL_SUCCESS) { + if cvlErrObj.ErrCode != CVL_SUCCESS { CVL_LOG(WARNING, "Custom validation failed, Error = %v", cvlErrObj) return cvlErrObj } @@ -1041,7 +1035,7 @@ func (c *CVL) doCustomValidation(node *xmlquery.Node, // target table name and leaf node name where leafRef is present func getLeafRefInfo(tblName, fldName, targetTblName string) *leafRefInfo { for _, refTblLeafRef := range modelInfo.tableInfo[tblName].leafRef[fldName] { - if (refTblLeafRef.path == "non-leafref") { + if refTblLeafRef.path == "non-leafref" { continue } @@ -1060,4 +1054,4 @@ func isMandatoryTrueNode(tblName, field string) bool { } return false -} \ No newline at end of file +} diff --git a/cvl/cvl_api.go b/cvl/cvl_api.go index 16f240a48..74da0f575 100644 --- a/cvl/cvl_api.go +++ b/cvl/cvl_api.go @@ -20,121 +20,124 @@ package cvl import ( - "fmt" - "reflect" "encoding/json" + "fmt" + "github.com/Azure/sonic-mgmt-common/cvl/internal/yparser" "github.com/go-redis/redis/v7" toposort "github.com/philopon/go-toposort" - "github.com/Azure/sonic-mgmt-common/cvl/internal/yparser" + "reflect" //lint:ignore ST1001 This is safe to dot import for util package + custv "github.com/Azure/sonic-mgmt-common/cvl/custom_validation" . "github.com/Azure/sonic-mgmt-common/cvl/internal/util" - "strings" "github.com/antchfx/xmlquery" - "unsafe" "runtime" - custv "github.com/Azure/sonic-mgmt-common/cvl/custom_validation" - "time" + "strings" "sync" + "time" + "unsafe" ) type CVLValidateType uint + const ( - VALIDATE_NONE CVLValidateType = iota //Data is used as dependent data - VALIDATE_SYNTAX //Syntax is checked and data is used as dependent data - VALIDATE_SEMANTICS //Semantics is checked - VALIDATE_ALL //Syntax and Semantics are checked + VALIDATE_NONE CVLValidateType = iota //Data is used as dependent data + VALIDATE_SYNTAX //Syntax is checked and data is used as dependent data + VALIDATE_SEMANTICS //Semantics is checked + VALIDATE_ALL //Syntax and Semantics are checked ) type CVLOperation uint + const ( - OP_NONE CVLOperation = 0 //Used to just validate the config without any operation - OP_CREATE = 1 << 0//For Create operation - OP_UPDATE = 1 << 1//For Update operation - OP_DELETE = 1 << 2//For Delete operation + OP_NONE CVLOperation = 0 //Used to just validate the config without any operation + OP_CREATE = 1 << 0 //For Create operation + OP_UPDATE = 1 << 1 //For Update operation + OP_DELETE = 1 << 2 //For Delete operation ) -var cvlErrorMap = map[CVLRetCode]string { - CVL_SUCCESS : "Config Validation Success", - CVL_SYNTAX_ERROR : "Config Validation Syntax Error", - CVL_SEMANTIC_ERROR : "Config Validation Semantic Error", - CVL_SYNTAX_MISSING_FIELD : "Required Field is Missing", - CVL_SYNTAX_INVALID_FIELD : "Invalid Field Received", - CVL_SYNTAX_INVALID_INPUT_DATA : "Invalid Input Data Received", - CVL_SYNTAX_MULTIPLE_INSTANCE : "Multiple Field Instances Received", - CVL_SYNTAX_DUPLICATE : "Duplicate Instances Received", - CVL_SYNTAX_ENUM_INVALID : "Invalid Enum Value Received", - CVL_SYNTAX_ENUM_INVALID_NAME : "Invalid Enum Value Received", - CVL_SYNTAX_ENUM_WHITESPACE : "Enum name with leading/trailing whitespaces Received", - CVL_SYNTAX_OUT_OF_RANGE : "Value out of range/length/pattern (data)", - CVL_SYNTAX_MINIMUM_INVALID : "min-elements constraint not honored", - CVL_SYNTAX_MAXIMUM_INVALID : "max-elements constraint not honored", - CVL_SEMANTIC_DEPENDENT_DATA_MISSING : "Dependent Data is missing", - CVL_SEMANTIC_MANDATORY_DATA_MISSING : "Mandatory Data is missing", - CVL_SEMANTIC_KEY_ALREADY_EXIST : "Key already existing.", - CVL_SEMANTIC_KEY_NOT_EXIST : "Key is missing.", - CVL_SEMANTIC_KEY_DUPLICATE : "Duplicate key received", - CVL_SEMANTIC_KEY_INVALID : "Invalid Key Received", - CVL_INTERNAL_UNKNOWN : "Internal Unknown Error", - CVL_ERROR : "Generic Error", - CVL_NOT_IMPLEMENTED : "Error Not Implemented", - CVL_FAILURE : "Generic Failure", +var cvlErrorMap = map[CVLRetCode]string{ + CVL_SUCCESS: "Config Validation Success", + CVL_SYNTAX_ERROR: "Config Validation Syntax Error", + CVL_SEMANTIC_ERROR: "Config Validation Semantic Error", + CVL_SYNTAX_MISSING_FIELD: "Required Field is Missing", + CVL_SYNTAX_INVALID_FIELD: "Invalid Field Received", + CVL_SYNTAX_INVALID_INPUT_DATA: "Invalid Input Data Received", + CVL_SYNTAX_MULTIPLE_INSTANCE: "Multiple Field Instances Received", + CVL_SYNTAX_DUPLICATE: "Duplicate Instances Received", + CVL_SYNTAX_ENUM_INVALID: "Invalid Enum Value Received", + CVL_SYNTAX_ENUM_INVALID_NAME: "Invalid Enum Value Received", + CVL_SYNTAX_ENUM_WHITESPACE: "Enum name with leading/trailing whitespaces Received", + CVL_SYNTAX_OUT_OF_RANGE: "Value out of range/length/pattern (data)", + CVL_SYNTAX_MINIMUM_INVALID: "min-elements constraint not honored", + CVL_SYNTAX_MAXIMUM_INVALID: "max-elements constraint not honored", + CVL_SEMANTIC_DEPENDENT_DATA_MISSING: "Dependent Data is missing", + CVL_SEMANTIC_MANDATORY_DATA_MISSING: "Mandatory Data is missing", + CVL_SEMANTIC_KEY_ALREADY_EXIST: "Key already existing.", + CVL_SEMANTIC_KEY_NOT_EXIST: "Key is missing.", + CVL_SEMANTIC_KEY_DUPLICATE: "Duplicate key received", + CVL_SEMANTIC_KEY_INVALID: "Invalid Key Received", + CVL_INTERNAL_UNKNOWN: "Internal Unknown Error", + CVL_ERROR: "Generic Error", + CVL_NOT_IMPLEMENTED: "Error Not Implemented", + CVL_FAILURE: "Generic Failure", } // CVLRetCode CVL Error codes type CVLRetCode int + const ( CVL_SUCCESS CVLRetCode = iota CVL_ERROR CVL_NOT_IMPLEMENTED CVL_INTERNAL_UNKNOWN CVL_FAILURE - CVL_SYNTAX_ERROR = CVLRetCode(yparser.YP_SYNTAX_ERROR) - CVL_SEMANTIC_ERROR = CVLRetCode(yparser.YP_SEMANTIC_ERROR) - CVL_SYNTAX_MISSING_FIELD = CVLRetCode(yparser.YP_SYNTAX_MISSING_FIELD) - CVL_SYNTAX_INVALID_FIELD = CVLRetCode(yparser.YP_SYNTAX_INVALID_FIELD) /* Invalid Field */ - CVL_SYNTAX_INVALID_INPUT_DATA = CVLRetCode(yparser.YP_SYNTAX_INVALID_INPUT_DATA) /*Invalid Input Data */ - CVL_SYNTAX_MULTIPLE_INSTANCE = CVLRetCode(yparser.YP_SYNTAX_MULTIPLE_INSTANCE) /* Multiple Field Instances */ - CVL_SYNTAX_DUPLICATE = CVLRetCode(yparser.YP_SYNTAX_DUPLICATE) /* Duplicate Fields */ - CVL_SYNTAX_ENUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_ENUM_INVALID) /* Invalid enum value */ - CVL_SYNTAX_ENUM_INVALID_NAME = CVLRetCode(yparser.YP_SYNTAX_ENUM_INVALID_NAME) /* Invalid enum name */ - CVL_SYNTAX_ENUM_WHITESPACE = CVLRetCode(yparser.YP_SYNTAX_ENUM_WHITESPACE) /* Enum name with leading/trailing whitespaces */ - CVL_SYNTAX_OUT_OF_RANGE = CVLRetCode(yparser.YP_SYNTAX_OUT_OF_RANGE) /* Value out of range/length/pattern (data) */ - CVL_SYNTAX_MINIMUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_MINIMUM_INVALID) /* min-elements constraint not honored */ - CVL_SYNTAX_MAXIMUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_MAXIMUM_INVALID) /* max-elements constraint not honored */ - CVL_SEMANTIC_DEPENDENT_DATA_MISSING = CVLRetCode(yparser.YP_SEMANTIC_DEPENDENT_DATA_MISSING) /* Dependent Data is missing */ + CVL_SYNTAX_ERROR = CVLRetCode(yparser.YP_SYNTAX_ERROR) + CVL_SEMANTIC_ERROR = CVLRetCode(yparser.YP_SEMANTIC_ERROR) + CVL_SYNTAX_MISSING_FIELD = CVLRetCode(yparser.YP_SYNTAX_MISSING_FIELD) + CVL_SYNTAX_INVALID_FIELD = CVLRetCode(yparser.YP_SYNTAX_INVALID_FIELD) /* Invalid Field */ + CVL_SYNTAX_INVALID_INPUT_DATA = CVLRetCode(yparser.YP_SYNTAX_INVALID_INPUT_DATA) /*Invalid Input Data */ + CVL_SYNTAX_MULTIPLE_INSTANCE = CVLRetCode(yparser.YP_SYNTAX_MULTIPLE_INSTANCE) /* Multiple Field Instances */ + CVL_SYNTAX_DUPLICATE = CVLRetCode(yparser.YP_SYNTAX_DUPLICATE) /* Duplicate Fields */ + CVL_SYNTAX_ENUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_ENUM_INVALID) /* Invalid enum value */ + CVL_SYNTAX_ENUM_INVALID_NAME = CVLRetCode(yparser.YP_SYNTAX_ENUM_INVALID_NAME) /* Invalid enum name */ + CVL_SYNTAX_ENUM_WHITESPACE = CVLRetCode(yparser.YP_SYNTAX_ENUM_WHITESPACE) /* Enum name with leading/trailing whitespaces */ + CVL_SYNTAX_OUT_OF_RANGE = CVLRetCode(yparser.YP_SYNTAX_OUT_OF_RANGE) /* Value out of range/length/pattern (data) */ + CVL_SYNTAX_MINIMUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_MINIMUM_INVALID) /* min-elements constraint not honored */ + CVL_SYNTAX_MAXIMUM_INVALID = CVLRetCode(yparser.YP_SYNTAX_MAXIMUM_INVALID) /* max-elements constraint not honored */ + CVL_SEMANTIC_DEPENDENT_DATA_MISSING = CVLRetCode(yparser.YP_SEMANTIC_DEPENDENT_DATA_MISSING) /* Dependent Data is missing */ CVL_SEMANTIC_MANDATORY_DATA_MISSING = CVLRetCode(yparser.YP_SEMANTIC_MANDATORY_DATA_MISSING) /* Mandatory Data is missing */ - CVL_SEMANTIC_KEY_ALREADY_EXIST = CVLRetCode(yparser.YP_SEMANTIC_KEY_ALREADY_EXIST) /* Key already existing. */ - CVL_SEMANTIC_KEY_NOT_EXIST = CVLRetCode(yparser.YP_SEMANTIC_KEY_NOT_EXIST) /* Key is missing. */ - CVL_SEMANTIC_KEY_DUPLICATE = CVLRetCode(yparser.YP_SEMANTIC_KEY_DUPLICATE) /* Duplicate key. */ - CVL_SEMANTIC_KEY_INVALID = CVLRetCode(yparser.YP_SEMANTIC_KEY_INVALID) + CVL_SEMANTIC_KEY_ALREADY_EXIST = CVLRetCode(yparser.YP_SEMANTIC_KEY_ALREADY_EXIST) /* Key already existing. */ + CVL_SEMANTIC_KEY_NOT_EXIST = CVLRetCode(yparser.YP_SEMANTIC_KEY_NOT_EXIST) /* Key is missing. */ + CVL_SEMANTIC_KEY_DUPLICATE = CVLRetCode(yparser.YP_SEMANTIC_KEY_DUPLICATE) /* Duplicate key. */ + CVL_SEMANTIC_KEY_INVALID = CVLRetCode(yparser.YP_SEMANTIC_KEY_INVALID) ) // CVLEditConfigData Strcture for key and data in API type CVLEditConfigData struct { - VType CVLValidateType //Validation type - VOp CVLOperation //Operation type - Key string //Key format : "PORT|Ethernet4" - Data map[string]string //Value : {"alias": "40GE0/28", "mtu" : 9100, "admin_status": down} + VType CVLValidateType //Validation type + VOp CVLOperation //Operation type + Key string //Key format : "PORT|Ethernet4" + Data map[string]string //Value : {"alias": "40GE0/28", "mtu" : 9100, "admin_status": down} } -// ValidationTimeStats CVL validations stats -//Maintain time stats for call to ValidateEditConfig(). -//Hits : Total number of times ValidateEditConfig() called -//Time : Total time spent in ValidateEditConfig() -//Peak : Highest time spent in ValidateEditConfig() +// ValidationTimeStats CVL validations stats +// Maintain time stats for call to ValidateEditConfig(). +// Hits : Total number of times ValidateEditConfig() called +// Time : Total time spent in ValidateEditConfig() +// Peak : Highest time spent in ValidateEditConfig() type ValidationTimeStats struct { Hits uint Time time.Duration Peak time.Duration } -//CVLDepDataForDelete Structure for dependent entry to be deleted +// CVLDepDataForDelete Structure for dependent entry to be deleted type CVLDepDataForDelete struct { - RefKey string //Ref Key which is getting deleted + RefKey string //Ref Key which is getting deleted Entry map[string]map[string]string //Entry or field which should be deleted as a result } -//Global data structure for maintaining validation stats +// Global data structure for maintaining validation stats var cfgValidationStats ValidationTimeStats var statsMutex *sync.Mutex @@ -144,10 +147,10 @@ func Initialize() CVLRetCode { return CVL_SUCCESS } - //Initialize redis Client + //Initialize redis Client redisClient = NewDbClient("CONFIG_DB") - if (redisClient == nil) { + if redisClient == nil { CVL_LOG(FATAL, "Unable to connect to Redis Config DB Server") return CVL_ERROR } @@ -158,9 +161,9 @@ func Initialize() CVLRetCode { yparser.Initialize() - modelInfo.modelNs = make(map[string]*modelNamespace) //redis table to model name - modelInfo.tableInfo = make(map[string]*modelTableInfo) //model namespace - modelInfo.allKeyDelims = make(map[string]bool) //all key delimiter + modelInfo.modelNs = make(map[string]*modelNamespace) //redis table to model name + modelInfo.tableInfo = make(map[string]*modelTableInfo) //model namespace + modelInfo.allKeyDelims = make(map[string]bool) //all key delimiter modelInfo.redisTableToYangList = make(map[string][]string) //Redis table to Yang list map dbNameToDbNum = map[string]uint8{"APPL_DB": APPL_DB, "CONFIG_DB": CONFIG_DB} @@ -194,7 +197,7 @@ func Finish() { } func ValidationSessOpen() (*CVL, CVLRetCode) { - cvl := &CVL{} + cvl := &CVL{} cvl.tmpDbCache = make(map[string]interface{}) cvl.requestCache = make(map[string]map[string][]*requestCacheType) cvl.maxTableElem = make(map[string]int) @@ -202,7 +205,7 @@ func ValidationSessOpen() (*CVL, CVLRetCode) { cvl.yv = &YValidator{} cvl.yv.root = &xmlquery.Node{Type: xmlquery.DocumentNode} - if (cvl == nil || cvl.yp == nil) { + if cvl == nil || cvl.yp == nil { return nil, CVL_FAILURE } @@ -222,14 +225,15 @@ func (c *CVL) ValidateStartupConfig(jsonData string) CVLRetCode { return CVL_NOT_IMPLEMENTED } -//ValidateIncrementalConfig Steps: +// ValidateIncrementalConfig Steps: +// // Check config data syntax // Fetch the depedent data // Merge config and dependent data // Finally validate func (c *CVL) ValidateIncrementalConfig(jsonData string) CVLRetCode { c.clearTmpDbCache() - var v interface{} + var v interface{} b := []byte(jsonData) if err := json.Unmarshal(b, &v); err != nil { @@ -260,9 +264,8 @@ func (c *CVL) ValidateIncrementalConfig(jsonData string) CVLRetCode { existingData := c.fetchDataToTmpCache() //Merge existing data for update syntax or checking duplicate entries - if (existingData != nil) { - if _, errObj = c.yp.MergeSubtree(root, existingData); - errObj.ErrCode != yparser.YP_SUCCESS { + if existingData != nil { + if _, errObj = c.yp.MergeSubtree(root, existingData); errObj.ErrCode != yparser.YP_SUCCESS { return CVL_ERROR } } @@ -278,10 +281,10 @@ func (c *CVL) ValidateIncrementalConfig(jsonData string) CVLRetCode { return CVL_SUCCESS } -//ValidateConfig Validate data for operation +// ValidateConfig Validate data for operation func (c *CVL) ValidateConfig(jsonData string) CVLRetCode { c.clearTmpDbCache() - var v interface{} + var v interface{} b := []byte(jsonData) if err := json.Unmarshal(b, &v); err == nil { @@ -294,7 +297,7 @@ func (c *CVL) ValidateConfig(jsonData string) CVLRetCode { } - if (c.validate(root) != CVL_SUCCESS) { + if c.validate(root) != CVL_SUCCESS { return CVL_FAILURE } @@ -303,13 +306,13 @@ func (c *CVL) ValidateConfig(jsonData string) CVLRetCode { return CVL_SUCCESS } -//ValidateEditConfig Validate config data based on edit operation +// ValidateEditConfig Validate config data based on edit operation func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorInfo, ret CVLRetCode) { ts := time.Now() defer func() { - if (cvlErr.ErrCode != CVL_SUCCESS) { + if cvlErr.ErrCode != CVL_SUCCESS { CVL_LOG(WARNING, "ValidateEditConfig() failed: %+v", cvlErr) } //Update validation time stats @@ -319,7 +322,7 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn var cvlErrObj CVLErrorInfo caller := "" - if (IsTraceSet()) { + if IsTraceSet() { pc := make([]uintptr, 10) runtime.Callers(2, pc) f := runtime.FuncForPC(pc[0]) @@ -341,19 +344,18 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn //c.yv.root.FirstChild = nil //c.yv.root.LastChild = nil - //Step 1: Get requested data first //add all dependent data to be fetched from Redis requestedData := make(map[string]interface{}) cfgDataLen := len(cfgData) for i := 0; i < cfgDataLen; i++ { - if (VALIDATE_ALL != cfgData[i].VType) { + if VALIDATE_ALL != cfgData[i].VType { continue } //Add config data item to be validated - tbl,key := c.addCfgDataItem(&requestedData, cfgData[i]) + tbl, key := c.addCfgDataItem(&requestedData, cfgData[i]) //Add to request cache reqTbl, exists := c.requestCache[tbl] @@ -366,7 +368,7 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn reqTbl[key] = cfgDataItemArr c.requestCache[tbl] = reqTbl - //Invalid table name or invalid key separator + //Invalid table name or invalid key separator if key == "" { cvlErrObj.ErrCode = CVL_SYNTAX_ERROR cvlErrObj.Msg = "Invalid table or key for " + cfgData[i].Key @@ -376,7 +378,7 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn switch cfgData[i].VOp { case OP_CREATE: - //Check max-element constraint + //Check max-element constraint if ret := c.checkMaxElemConstraint(OP_CREATE, tbl); ret != CVL_SUCCESS { cvlErrObj.ErrCode = CVL_SYNTAX_ERROR cvlErrObj.TableName = tbl @@ -385,21 +387,21 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn cvlErrObj.Msg = "Max elements limit reached" cvlErrObj.CVLErrDetails = cvlErrorMap[cvlErrObj.ErrCode] cvlErrObj.ConstraintErrMsg = fmt.Sprintf("Max elements limit %v reached", - modelInfo.tableInfo[tbl].redisTableSize) + modelInfo.tableInfo[tbl].redisTableSize) return cvlErrObj, CVL_SYNTAX_ERROR } case OP_UPDATE: - //Get the existing data from Redis to cache, so that final + //Get the existing data from Redis to cache, so that final //validation can be done after merging this dependent data c.addTableEntryToCache(tbl, key) case OP_DELETE: - if (len(cfgData[i].Data) > 0) { + if len(cfgData[i].Data) > 0 { //Check constraints for deleting field(s) for field := range cfgData[i].Data { - if (c.checkDeleteConstraint(cfgData, tbl, key, field) != CVL_SUCCESS) { + if c.checkDeleteConstraint(cfgData, tbl, key, field) != CVL_SUCCESS { cvlErrObj.ErrCode = CVL_SEMANTIC_ERROR cvlErrObj.TableName = tbl cvlErrObj.Keys = splitKeyComponents(tbl, key) @@ -431,7 +433,7 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn c.checkMaxElemConstraint(OP_DELETE, tbl) //Now check delete constraints - if (c.checkDeleteConstraint(cfgData, tbl, key, "") != CVL_SUCCESS) { + if c.checkDeleteConstraint(cfgData, tbl, key, "") != CVL_SUCCESS { cvlErrObj.ErrCode = CVL_SEMANTIC_ERROR cvlErrObj.TableName = tbl cvlErrObj.Keys = splitKeyComponents(tbl, key) @@ -447,12 +449,12 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn } } - if (IsTraceSet()) { + if IsTraceSet() { //Only for tracing jsonData := "" jsonDataBytes, err := json.Marshal(requestedData) - if (err == nil) { + if err == nil { jsonData = string(jsonDataBytes) } else { cvlErrObj.ErrCode = CVL_SYNTAX_ERROR @@ -467,18 +469,18 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn yang, errN := c.translateToYang(&requestedData) defer c.yp.FreeNode(yang) - if (errN.ErrCode == CVL_SUCCESS) { + if errN.ErrCode == CVL_SUCCESS { if cvlErrObj, cvlRetCode := c.validateSyntax(yang); cvlRetCode != CVL_SUCCESS { return cvlErrObj, cvlRetCode } } else { - return errN,errN.ErrCode + return errN, errN.ErrCode } //Step 3 : Check keys and perform semantics validation for i := 0; i < cfgDataLen; i++ { - if (cfgData[i].VType != VALIDATE_ALL && cfgData[i].VType != VALIDATE_SEMANTICS) { + if cfgData[i].VType != VALIDATE_ALL && cfgData[i].VType != VALIDATE_SEMANTICS { continue } @@ -489,11 +491,11 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn case OP_CREATE: //Check key should not already exist n, err1 := redisClient.Exists(cfgData[i].Key).Result() - if (err1 == nil && n > 0) { + if err1 == nil && n > 0 { //Check if key deleted and CREATE done in same session, //allow to create the entry deletedInSameSession := false - if tbl != "" && key != "" { + if tbl != "" && key != "" { for _, cachedCfgData := range c.requestCache[tbl][key] { if cachedCfgData.reqData.VOp == OP_DELETE { deletedInSameSession = true @@ -511,8 +513,8 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn return cvlErrObj, CVL_SEMANTIC_KEY_ALREADY_EXIST } else { - TRACE_LOG(TRACE_CREATE, "\nKey %s is deleted in same session, " + - "skipping key existence check for OP_CREATE operation", cfgData[i].Key) + TRACE_LOG(TRACE_CREATE, "\nKey %s is deleted in same session, "+ + "skipping key existence check for OP_CREATE operation", cfgData[i].Key) } } @@ -520,7 +522,7 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn case OP_UPDATE: n, err1 := redisClient.Exists(cfgData[i].Key).Result() - if (err1 != nil || n == 0) { //key must exists + if err1 != nil || n == 0 { //key must exists CVL_LOG(WARNING, "\nValidateEditConfig(): Key = %s does not exist", cfgData[i].Key) cvlErrObj.ErrCode = CVL_SEMANTIC_KEY_NOT_EXIST cvlErrObj.CVLErrDetails = cvlErrorMap[cvlErrObj.ErrCode] @@ -531,14 +533,14 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn // Skip validation if UPDATE is received with only NULL field if _, exists := cfgData[i].Data["NULL"]; exists && len(cfgData[i].Data) == 1 { - continue; + continue } c.yp.SetOperation("UPDATE") case OP_DELETE: n, err1 := redisClient.Exists(cfgData[i].Key).Result() - if (err1 != nil || n == 0) { //key must exists + if err1 != nil || n == 0 { //key must exists CVL_LOG(WARNING, "\nValidateEditConfig(): Key = %s does not exist", cfgData[i].Key) cvlErrObj.ErrCode = CVL_SEMANTIC_KEY_NOT_EXIST cvlErrObj.CVLErrDetails = cvlErrorMap[cvlErrObj.ErrCode] @@ -554,30 +556,29 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn //Get the YANG validator node var node *xmlquery.Node = nil - if (c.requestCache[tbl][key][0].yangData != nil) { //get the node for CREATE/UPDATE or DELETE operation + if c.requestCache[tbl][key][0].yangData != nil { //get the node for CREATE/UPDATE or DELETE operation node = c.requestCache[tbl][key][0].yangData } else { //Find the node from YANG tree node = c.moveToYangList(yangListName, key) } - if (node == nil) { - CVL_LOG(WARNING, "Could not find data for semantic validation, " + - "table %s , key %s", tbl, key) + if node == nil { + CVL_LOG(WARNING, "Could not find data for semantic validation, "+ + "table %s , key %s", tbl, key) continue } //Step 3.2 : Run all custom validations - cvlErrObj= c.doCustomValidation(node, custvCfg, &custvCfg[i], yangListName, - tbl, key) + cvlErrObj = c.doCustomValidation(node, custvCfg, &custvCfg[i], yangListName, + tbl, key) if cvlErrObj.ErrCode != CVL_SUCCESS { - return cvlErrObj,cvlErrObj.ErrCode + return cvlErrObj, cvlErrObj.ErrCode } //Step 3.3 : Perform semantic validation - if cvlErrObj = c.validateSemantics(node, yangListName, key, &cfgData[i]); - cvlErrObj.ErrCode != CVL_SUCCESS { - return cvlErrObj,cvlErrObj.ErrCode + if cvlErrObj = c.validateSemantics(node, yangListName, key, &cfgData[i]); cvlErrObj.ErrCode != CVL_SUCCESS { + return cvlErrObj, cvlErrObj.ErrCode } } @@ -585,37 +586,37 @@ func (c *CVL) ValidateEditConfig(cfgData []CVLEditConfigData) (cvlErr CVLErrorIn return cvlErrObj, CVL_SUCCESS } -//GetErrorString Fetch the Error Message from CVL Return Code. -func GetErrorString(retCode CVLRetCode) string{ +// GetErrorString Fetch the Error Message from CVL Return Code. +func GetErrorString(retCode CVLRetCode) string { return cvlErrorMap[retCode] } -//ValidateKeys Validate key only +// ValidateKeys Validate key only func (c *CVL) ValidateKeys(key []string) CVLRetCode { return CVL_NOT_IMPLEMENTED } -//ValidateKeyData Validate key and data +// ValidateKeyData Validate key and data func (c *CVL) ValidateKeyData(key string, data string) CVLRetCode { return CVL_NOT_IMPLEMENTED } -//ValidateFields Validate key, field and value +// ValidateFields Validate key, field and value func (c *CVL) ValidateFields(key string, field string, value string) CVLRetCode { return CVL_NOT_IMPLEMENTED } func (c *CVL) addDepEdges(graph *toposort.Graph, tableList []string) { //Add all the depedency edges for graph nodes - for ti :=0; ti < len(tableList); ti++ { + for ti := 0; ti < len(tableList); ti++ { redisTblTo := getYangListToRedisTbl(tableList[ti]) - for tj :=0; tj < len(tableList); tj++ { + for tj := 0; tj < len(tableList); tj++ { - if (tableList[ti] == tableList[tj]) { + if tableList[ti] == tableList[tj] { //same table, continue continue } @@ -627,7 +628,7 @@ func (c *CVL) addDepEdges(graph *toposort.Graph, tableList []string) { for _, leafRefs := range modelInfo.tableInfo[tableList[tj]].leafRef { for _, leafRef := range leafRefs { - if !(strings.Contains(leafRef.path, tableList[ti] + "_LIST")) { + if !(strings.Contains(leafRef.path, tableList[ti]+"_LIST")) { continue } @@ -642,17 +643,17 @@ func (c *CVL) addDepEdges(graph *toposort.Graph, tableList []string) { dupEdgeCheck[redisTblFrom] = redisTblTo CVL_LOG(INFO_DEBUG, - "addDepEdges(): Adding edge %s -> %s", redisTblFrom, redisTblTo) + "addDepEdges(): Adding edge %s -> %s", redisTblFrom, redisTblTo) } } } } } -//SortDepTables Sort list of given tables as per their dependency +// SortDepTables Sort list of given tables as per their dependency func (c *CVL) SortDepTables(inTableList []string) ([]string, CVLRetCode) { - tableListMap := make(map[string]bool) + tableListMap := make(map[string]bool) //Skip all unknown tables for ti := 0; ti < len(inTableList); ti++ { @@ -686,14 +687,14 @@ func (c *CVL) SortDepTables(inTableList []string) ([]string, CVLRetCode) { return result, CVL_SUCCESS } -//GetOrderedTables Get the order list(parent then child) of tables in a given YANG module -//within a single model this is obtained using leafref relation +// GetOrderedTables Get the order list(parent then child) of tables in a given YANG module +// within a single model this is obtained using leafref relation func (c *CVL) GetOrderedTables(yangModule string) ([]string, CVLRetCode) { tableList := []string{} //Get all the table names under this model for tblName, tblNameInfo := range modelInfo.tableInfo { - if (tblNameInfo.modelName == yangModule) { + if tblNameInfo.modelName == yangModule { tableList = append(tableList, tblName) } } @@ -710,7 +711,7 @@ func (c *CVL) GetOrderedDepTables(yangModule, tableName string) ([]string, CVLRe //Get all the table names under this yang module for tblName, tblNameInfo := range modelInfo.tableInfo { - if (tblNameInfo.modelName == yangModule) { + if tblNameInfo.modelName == yangModule { tableList = append(tableList, tblName) } } @@ -720,7 +721,7 @@ func (c *CVL) GetOrderedDepTables(yangModule, tableName string) ([]string, CVLRe graph.AddNodes(redisTblTo) for _, tbl := range tableList { - if (tableName == tbl) { + if tableName == tbl { //same table, continue continue } @@ -732,7 +733,7 @@ func (c *CVL) GetOrderedDepTables(yangModule, tableName string) ([]string, CVLRe for _, leafRefs := range modelInfo.tableInfo[tbl].leafRef { for _, leafRef := range leafRefs { // If no relation through leaf-ref, then skip - if !(strings.Contains(leafRef.path, tableName + "_LIST")) { + if !(strings.Contains(leafRef.path, tableName+"_LIST")) { continue } @@ -785,7 +786,7 @@ func (c *CVL) addDepTables(tableMap map[string]bool, tableName string) { } } -//GetDepTables Get the list of dependent tables for a given table in a YANG module +// GetDepTables Get the list of dependent tables for a given table in a YANG module func (c *CVL) GetDepTables(yangModule string, tableName string) ([]string, CVLRetCode) { tableList := []string{} tblMap := make(map[string]bool) @@ -820,9 +821,9 @@ func (c *CVL) GetDepTables(yangModule string, tableName string) ([]string, CVLRe return result, CVL_SUCCESS } -//Parses the JSON string buffer and returns -//array of dependent fields to be deleted -func getDepDeleteField(refKey, hField, hValue, jsonBuf string) ([]CVLDepDataForDelete) { +// Parses the JSON string buffer and returns +// array of dependent fields to be deleted +func getDepDeleteField(refKey, hField, hValue, jsonBuf string) []CVLDepDataForDelete { //Parse the JSON map received from lua script var v interface{} b := []byte(jsonBuf) @@ -841,21 +842,21 @@ func getDepDeleteField(refKey, hField, hValue, jsonBuf string) ([]CVLDepDataForD entryMap[tblKey] = make(map[string]string) for field := range fields.(map[string]interface{}) { - if ((field != hField) && (field != (hField + "@"))){ + if (field != hField) && (field != (hField + "@")) { continue } - if (field == (hField + "@")) { + if field == (hField + "@") { //leaf-list - specific value to be deleted - entryMap[tblKey][field]= hValue + entryMap[tblKey][field] = hValue } else { //leaf - specific field to be deleted - entryMap[tblKey][field]= "" + entryMap[tblKey][field] = "" } } depEntries = append(depEntries, CVLDepDataForDelete{ RefKey: refKey, - Entry: entryMap, + Entry: entryMap, }) } } @@ -863,14 +864,14 @@ func getDepDeleteField(refKey, hField, hValue, jsonBuf string) ([]CVLDepDataForD return depEntries } -//GetDepDataForDelete Get the dependent (Redis keys) to be deleted or modified -//for a given entry getting deleted -func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { +// GetDepDataForDelete Get the dependent (Redis keys) to be deleted or modified +// for a given entry getting deleted +func (c *CVL) GetDepDataForDelete(redisKey string) []CVLDepDataForDelete { type filterScript struct { script string - field string - value string + field string + value string } tableName, key := splitRedisKey(redisKey) @@ -881,7 +882,7 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { if (tableName == "") || (key == "") { CVL_LOG(INFO_DEBUG, "GetDepDataForDelete(): Unknown or invalid table %s\n", - tableName) + tableName) } if _, exists := modelInfo.tableInfo[tableName]; !exists { @@ -905,7 +906,7 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { refRedisTblName := getYangListToRedisTbl(refTbl.tableName) idx := 0 - if (refRedisTblName == "") { + if refRedisTblName == "" { continue } @@ -932,7 +933,7 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { rediskeyTblKeyPatterns := strings.Split(modelInfo.tableInfo[tableName].redisKeyPattern, redisKeySep) for z := 1; z < len(rediskeyTblKeyPatterns); z++ { // Skipping 0th position, as it is a tableName if rediskeyTblKeyPatterns[z] == fmt.Sprintf("{%s}", refTblTargetNodeName) { - key = redisMultiKeys[z - 1] + key = redisMultiKeys[z-1] break } } @@ -944,7 +945,7 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { mCmdArr := mCmd[refTbl.tableName] for ; idx < numKeys; idx++ { - if (modelInfo.tableInfo[refTbl.tableName].keys[idx] != refTbl.field) { + if modelInfo.tableInfo[refTbl.tableName].keys[idx] != refTbl.field { continue } @@ -956,7 +957,7 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { } mCmd[refTbl.tableName] = mCmdArr - if (idx == numKeys) { + if idx == numKeys { //field is hash-set field, not a key, match with hash-set field //prepare the lua filter script // ex: (h['members'] == 'Ethernet4' or h['members@'] == 'Ethernet4' or @@ -966,16 +967,16 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { mFilterScripts[refTbl.tableName] = make([]filterScript, 0) } fltScrs := mFilterScripts[refTbl.tableName] - fltScrs = append(fltScrs, filterScript { - script: fmt.Sprintf("return (h['%s'] ~= nil and (h['%s'] == '%s' or h['%s'] == '[%s|%s]')) or " + - "(h['%s@'] ~= nil and ((h['%s@'] == '%s') or " + - "(string.find(h['%s@']..',', '%s,') ~= nil)))", - refTbl.field, refTbl.field, key, refTbl.field, tableName, key, - refTbl.field, refTbl.field, key, - refTbl.field, key), + fltScrs = append(fltScrs, filterScript{ + script: fmt.Sprintf("return (h['%s'] ~= nil and (h['%s'] == '%s' or h['%s'] == '[%s|%s]')) or "+ + "(h['%s@'] ~= nil and ((h['%s@'] == '%s') or "+ + "(string.find(h['%s@']..',', '%s,') ~= nil)))", + refTbl.field, refTbl.field, key, refTbl.field, tableName, key, + refTbl.field, refTbl.field, key, + refTbl.field, key), field: refTbl.field, value: key, - } ) + }) mFilterScripts[refTbl.tableName] = fltScrs } } @@ -992,23 +993,23 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { for tableName, mFilterScriptArr := range mFilterScripts { for _, mFilterScript := range mFilterScriptArr { refEntries, err := luaScripts["filter_entries"].Run(redisClient, []string{}, - tableName + "|*", strings.Join(modelInfo.tableInfo[tableName].keys, "|"), - mFilterScript.script, mFilterScript.field).Result() + tableName+"|*", strings.Join(modelInfo.tableInfo[tableName].keys, "|"), + mFilterScript.script, mFilterScript.field).Result() - if (err != nil) { + if err != nil { CVL_LOG(WARNING, "Lua script status: (%v)", err) } - if (refEntries == nil) { + if refEntries == nil { //No reference field found continue } refEntriesJson := string(refEntries.(string)) - if (refEntriesJson != "") { - //Add all keys whose fields to be deleted + if refEntriesJson != "" { + //Add all keys whose fields to be deleted depEntries = append(depEntries, getDepDeleteField(redisKey, - mFilterScript.field, mFilterScript.value, refEntriesJson)...) + mFilterScript.field, mFilterScript.value, refEntriesJson)...) } } } @@ -1018,7 +1019,7 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { for idx := range mCmdArr { keys := mCmdArr[idx] res, err := keys.Result() - if (err != nil) { + if err != nil { CVL_LOG(WARNING, "Failed to fetch dependent key details for table %s", tblName) continue } @@ -1029,19 +1030,19 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { entryMap[k] = make(map[string]string) depEntries = append(depEntries, CVLDepDataForDelete{ RefKey: redisKey, - Entry: entryMap, + Entry: entryMap, }) } - keysArr = append(keysArr, res...) + keysArr = append(keysArr, res...) } } - TRACE_LOG(INFO_TRACE, "GetDepDataForDelete() : input key %s, " + - "entries to be deleted : %v", redisKey, depEntries) + TRACE_LOG(INFO_TRACE, "GetDepDataForDelete() : input key %s, "+ + "entries to be deleted : %v", redisKey, depEntries) //For each key, find dependent data for delete recursively - for i :=0; i< len(keysArr); i++ { + for i := 0; i < len(keysArr); i++ { retDepEntries := c.GetDepDataForDelete(keysArr[i]) depEntries = append(depEntries, retDepEntries...) } @@ -1049,12 +1050,12 @@ func (c *CVL) GetDepDataForDelete(redisKey string) ([]CVLDepDataForDelete) { return depEntries } -//Update global stats for all sessions +// Update global stats for all sessions func updateValidationTimeStats(td time.Duration) { statsMutex.Lock() cfgValidationStats.Hits++ - if (td > cfgValidationStats.Peak) { + if td > cfgValidationStats.Peak { cfgValidationStats.Peak = td } @@ -1063,12 +1064,12 @@ func updateValidationTimeStats(td time.Duration) { statsMutex.Unlock() } -//GetValidationTimeStats Retrieve global stats +// GetValidationTimeStats Retrieve global stats func GetValidationTimeStats() ValidationTimeStats { return cfgValidationStats } -//ClearValidationTimeStats Clear global stats +// ClearValidationTimeStats Clear global stats func ClearValidationTimeStats() { statsMutex.Lock() @@ -1079,7 +1080,7 @@ func ClearValidationTimeStats() { statsMutex.Unlock() } -//CreateFindKeyExpression Create expression for searching DB entries based on given key fields and values. +// CreateFindKeyExpression Create expression for searching DB entries based on given key fields and values. // Expressions created will be like CFG_L2MC_STATIC_MEMBER_TABLE|*|*|Ethernet0 func CreateFindKeyExpression(tableName string, keyFldValPair map[string]string) string { var expr string @@ -1090,7 +1091,7 @@ func CreateFindKeyExpression(tableName string, keyFldValPair map[string]string) tblKeyPatterns := strings.Split(modelInfo.tableInfo[tableName].redisKeyPattern, sep) for z := 1; z < len(tblKeyPatterns); z++ { - fldFromPattern := tblKeyPatterns[z][1:len(tblKeyPatterns[z])-1] //remove "{" and "}" + fldFromPattern := tblKeyPatterns[z][1 : len(tblKeyPatterns[z])-1] //remove "{" and "}" if val, exists := keyFldValPair[fldFromPattern]; exists { tempSlice = append(tempSlice, val) } else { @@ -1106,7 +1107,7 @@ func CreateFindKeyExpression(tableName string, keyFldValPair map[string]string) // GetAllReferringTables Returns list of all tables and fields which has leaf-ref // to given table. For ex. tableName="PORT" will return all tables and fields // which has leaf-ref to "PORT" table. -func (c *CVL) GetAllReferringTables(tableName string) (map[string][]string) { +func (c *CVL) GetAllReferringTables(tableName string) map[string][]string { var refTbls = make(map[string][]string) if tblInfo, exists := modelInfo.tableInfo[tableName]; exists { for _, refTbl := range tblInfo.refFromTables { diff --git a/cvl/cvl_cache.go b/cvl/cvl_cache.go index 05631cf27..183db0fd5 100644 --- a/cvl/cvl_cache.go +++ b/cvl/cvl_cache.go @@ -18,34 +18,35 @@ //////////////////////////////////////////////////////////////////////////////// package cvl + import ( "encoding/json" "github.com/go-redis/redis/v7" //lint:ignore ST1001 This is safe to dot import for util package . "github.com/Azure/sonic-mgmt-common/cvl/internal/util" "github.com/Azure/sonic-mgmt-common/cvl/internal/yparser" - "time" - "runtime" "github.com/antchfx/jsonquery" "github.com/antchfx/xmlquery" + "runtime" + "time" ) func (c *CVL) addTableEntryToCache(tableName string, redisKey string) { - if (tableName == "" || redisKey == "") { + if tableName == "" || redisKey == "" { return } - if (c.tmpDbCache[tableName] == nil) { + if c.tmpDbCache[tableName] == nil { c.tmpDbCache[tableName] = map[string]interface{}{redisKey: nil} } else { tblMap := c.tmpDbCache[tableName] - tblMap.(map[string]interface{})[redisKey] =nil + tblMap.(map[string]interface{})[redisKey] = nil c.tmpDbCache[tableName] = tblMap } } // Fetch dependent data from validated data cache, -// Returns the data and flag to indicate that if requested data +// Returns the data and flag to indicate that if requested data // is found in update request, the data should be merged with Redis data func (c *CVL) fetchDataFromRequestCache(tableName string, key string) (d map[string]string, m bool) { defer func() { @@ -53,16 +54,16 @@ func (c *CVL) fetchDataFromRequestCache(tableName string, key string) (d map[str pm := &m TRACE_LOG(TRACE_CACHE, - "Returning data from request cache, data = %v, merge needed = %v", - *pd, *pm) + "Returning data from request cache, data = %v, merge needed = %v", + *pd, *pm) }() cfgDataArr := c.requestCache[tableName][key] for _, cfgReqData := range cfgDataArr { //Delete request doesn't have depedent data - if (cfgReqData.reqData.VOp == OP_CREATE) { + if cfgReqData.reqData.VOp == OP_CREATE { return cfgReqData.reqData.Data, false - } else if (cfgReqData.reqData.VOp == OP_UPDATE) { + } else if cfgReqData.reqData.VOp == OP_UPDATE { return cfgReqData.reqData.Data, true } } @@ -70,13 +71,13 @@ func (c *CVL) fetchDataFromRequestCache(tableName string, key string) (d map[str return nil, false } -//Fetch given table entries using pipeline +// Fetch given table entries using pipeline func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]interface{}) int { TRACE_LOG(TRACE_CACHE, "\n%v, Entered fetchTableDataToTmpCache", time.Now()) totalCount := len(dbKeys) - if (totalCount == 0) { + if totalCount == 0 { //No entry to be fetched return 0 } @@ -86,25 +87,25 @@ func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]inter bulkKeys := []string{} for dbKey, val := range dbKeys { //for all keys - if (val != nil) { //skip entry already fetched - mapTable := c.tmpDbCache[tableName] - delete(mapTable.(map[string]interface{}), dbKey) //delete entry already fetched - totalCount = totalCount - 1 - if(bulkCount != totalCount) { - //If some entries are remaining go back to 'for' loop - continue - } - } else { - //Accumulate entries to be fetched - bulkKeys = append(bulkKeys, dbKey) - bulkCount = bulkCount + 1 - } - - if(bulkCount != totalCount) && ((bulkCount % MAX_BULK_ENTRIES_IN_PIPELINE) != 0) { - //If some entries are remaining and bulk bucket is not filled, - //go back to 'for' loop - continue - } + if val != nil { //skip entry already fetched + mapTable := c.tmpDbCache[tableName] + delete(mapTable.(map[string]interface{}), dbKey) //delete entry already fetched + totalCount = totalCount - 1 + if bulkCount != totalCount { + //If some entries are remaining go back to 'for' loop + continue + } + } else { + //Accumulate entries to be fetched + bulkKeys = append(bulkKeys, dbKey) + bulkCount = bulkCount + 1 + } + + if (bulkCount != totalCount) && ((bulkCount % MAX_BULK_ENTRIES_IN_PIPELINE) != 0) { + //If some entries are remaining and bulk bucket is not filled, + //go back to 'for' loop + continue + } mCmd := map[string]*redis.StringStringMapCmd{} @@ -114,7 +115,7 @@ func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]inter redisKey := tableName + modelInfo.tableInfo[tableName].redisKeyDelim + dbKey //Check in validated cache first and add as dependent data - if entry, mergeNeeded := c.fetchDataFromRequestCache(tableName, dbKey); (entry != nil) { + if entry, mergeNeeded := c.fetchDataFromRequestCache(tableName, dbKey); entry != nil { entryFetched = entryFetched + 1 //Entry found in validated cache, so skip fetching from Redis //if merging is not required with Redis DB @@ -147,11 +148,11 @@ func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]inter for key, val := range mCmd { res, err := val.Result() - if (mapTable == nil) { + if mapTable == nil { break } - if (err != nil || len(res) == 0) { + if err != nil || len(res) == 0 { //no data found, don't keep blank entry delete(mapTable.(map[string]interface{}), key) continue @@ -176,12 +177,12 @@ func (c *CVL) fetchTableDataToTmpCache(tableName string, dbKeys map[string]inter runtime.Gosched() } - TRACE_LOG(TRACE_CACHE,"\n%v, Exiting fetchTableDataToTmpCache", time.Now()) + TRACE_LOG(TRACE_CACHE, "\n%v, Exiting fetchTableDataToTmpCache", time.Now()) return entryFetched } -//populate redis data to cache +// populate redis data to cache func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode { TRACE_LOG(TRACE_CACHE, "\n%v, Entered fetchToTmpCache", time.Now()) @@ -190,7 +191,7 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode { var errObj yparser.YParserError for entryToFetch = 1; entryToFetch > 0; { //Force to enter the loop for first time - //Repeat until all entries are fetched + //Repeat until all entries are fetched entryToFetch = 0 for tableName, dbKeys := range c.tmpDbCache { //for each table entryToFetch = entryToFetch + c.fetchTableDataToTmpCache(tableName, dbKeys.(map[string]interface{})) @@ -198,13 +199,13 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode { //If no table entry delete the table itself for tableName, dbKeys := range c.tmpDbCache { //for each table - if (len(dbKeys.(map[string]interface{})) == 0) { - delete(c.tmpDbCache, tableName) - continue + if len(dbKeys.(map[string]interface{})) == 0 { + delete(c.tmpDbCache, tableName) + continue } } - if (entryToFetch == 0) { + if entryToFetch == 0 { //No more entry to fetch break } @@ -217,16 +218,16 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode { data, err := jsonquery.ParseJsonMap(&c.tmpDbCache) - if (err != nil) { + if err != nil { return nil } //Build yang tree for each table and cache it - for jsonNode := data.FirstChild; jsonNode != nil; jsonNode=jsonNode.NextSibling { + for jsonNode := data.FirstChild; jsonNode != nil; jsonNode = jsonNode.NextSibling { TRACE_LOG(TRACE_CACHE, "Top Node=%v\n", jsonNode.Data) //Visit each top level list in a loop for creating table data topNode, _ := c.generateTableData(true, jsonNode) - if (root == nil) { + if root == nil { root = topNode } else { if root, errObj = c.yp.MergeSubtree(root, topNode); errObj.ErrCode != yparser.YP_SUCCESS { @@ -236,7 +237,7 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode { //Generate YANG data for Yang Validator topYangNode, cvlYErrObj := c.generateYangListData(jsonNode, true) - if topYangNode == nil { + if topYangNode == nil { cvlYErrObj.ErrCode = CVL_SYNTAX_ERROR CVL_LOG(WARNING, "Unable to translate cache data to YANG format") return nil @@ -248,21 +249,21 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode { doc.LastChild = topYangNode topYangNode.Parent = doc - if (IsTraceLevelSet(TRACE_CACHE)) { + if IsTraceLevelSet(TRACE_CACHE) { TRACE_LOG(TRACE_CACHE, "Before cache merge = %s, source = %s", - c.yv.root.OutputXML(false), - doc.OutputXML(false)) + c.yv.root.OutputXML(false), + doc.OutputXML(false)) } if c.mergeYangData(c.yv.root, doc) != CVL_SUCCESS { - CVL_LOG(WARNING, "Unable to merge translated YANG data while " + - "translating from cache data to YANG format") + CVL_LOG(WARNING, "Unable to merge translated YANG data while "+ + "translating from cache data to YANG format") cvlYErrObj.ErrCode = CVL_SYNTAX_ERROR return nil } - if (IsTraceLevelSet(TRACE_CACHE)) { + if IsTraceLevelSet(TRACE_CACHE) { TRACE_LOG(TRACE_CACHE, "After cache merge = %s", - c.yv.root.OutputXML(false)) + c.yv.root.OutputXML(false)) } } } // until all dependent data is fetched @@ -276,7 +277,6 @@ func (c *CVL) fetchDataToTmpCache() *yparser.YParserNode { return root } - func (c *CVL) clearTmpDbCache() { for key := range c.tmpDbCache { delete(c.tmpDbCache, key) diff --git a/cvl/cvl_leafref_test.go b/cvl/cvl_leafref_test.go index b19e76a43..03e759f3b 100644 --- a/cvl/cvl_leafref_test.go +++ b/cvl/cvl_leafref_test.go @@ -21,36 +21,36 @@ package cvl_test import ( "fmt" - "testing" "github.com/Azure/sonic-mgmt-common/cvl" + "testing" ) // EditConfig(Create) with chained leafref from redis func TestValidateEditConfig_Create_Chained_Leafref_DepData_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan100": map[string]interface{} { + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan100": map[string]interface{}{ "members@": "Ethernet1", - "vlanid": "100", + "vlanid": "100", }, }, - "PORT" : map[string]interface{} { - "Ethernet1" : map[string]interface{} { - "alias":"hundredGigE1", + "PORT": map[string]interface{}{ + "Ethernet1": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "81,82,83,84", - "mtu": "9100", + "mtu": "9100", }, - "Ethernet2" : map[string]interface{} { - "alias":"hundredGigE1", + "Ethernet2": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "85,86,87,89", - "mtu": "9100", + "mtu": "9100", }, }, - "ACL_TABLE" : map[string]interface{} { - "TestACL1": map[string] interface{} { - "stage": "INGRESS", - "type": "L3", - "ports@":"Ethernet2", + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ + "stage": "INGRESS", + "type": "L3", + "ports@": "Ethernet2", }, }, } @@ -61,46 +61,45 @@ func TestValidateEditConfig_Create_Chained_Leafref_DepData_Positive(t *testing.T cvSess := NewTestSession(t) - cfgDataVlan := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "VLAN_MEMBER|Vlan100|Ethernet1", - map[string]string { - "tagging_mode" : "tagged", + map[string]string{ + "tagging_mode": "tagged", }, }, } - errInfo, _ := cvSess.ValidateEditConfig(cfgDataVlan) + errInfo, _ := cvSess.ValidateEditConfig(cfgDataVlan) verifyErr(t, errInfo, Success) - - cfgDataAclRule := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAclRule := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "ACL_RULE|TestACL1|Rule1", - map[string]string { - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", + map[string]string{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", "L4_DST_PORT_RANGE": "9000-12000", }, }, } - errInfo, _ = cvSess.ValidateEditConfig(cfgDataAclRule) + errInfo, _ = cvSess.ValidateEditConfig(cfgDataAclRule) verifyErr(t, errInfo, Success) } func TestValidateEditConfig_Create_Leafref_To_NonKey_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "BGP_GLOBALS" : map[string]interface{} { - "default": map[string] interface{} { + depDataMap := map[string]interface{}{ + "BGP_GLOBALS": map[string]interface{}{ + "default": map[string]interface{}{ "router_id": "1.1.1.1", "local_asn": "12338", }, @@ -111,14 +110,14 @@ func TestValidateEditConfig_Create_Leafref_To_NonKey_Positive(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_UPDATE, "DEVICE_METADATA|localhost", - map[string]string { + map[string]string{ "vrf_name": "default", - "bgp_asn": "12338", + "bgp_asn": "12338", }, }, } @@ -127,9 +126,9 @@ func TestValidateEditConfig_Create_Leafref_To_NonKey_Positive(t *testing.T) { } func TestValidateEditConfig_Update_Leafref_To_NonKey_Negative(t *testing.T) { - depDataMap := map[string]interface{} { - "BGP_GLOBALS" : map[string]interface{} { - "default": map[string] interface{} { + depDataMap := map[string]interface{}{ + "BGP_GLOBALS": map[string]interface{}{ + "default": map[string]interface{}{ "router_id": "1.1.1.1", "local_asn": "12338", }, @@ -140,14 +139,14 @@ func TestValidateEditConfig_Update_Leafref_To_NonKey_Negative(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_UPDATE, "DEVICE_METADATA|localhost", - map[string]string { + map[string]string{ "vrf_name": "default", - "bgp_asn": "17698", + "bgp_asn": "17698", }, }, } @@ -164,29 +163,29 @@ func TestValidateEditConfig_Update_Leafref_To_NonKey_Negative(t *testing.T) { } func TestValidateEditConfig_Create_Leafref_Multi_Key_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "ACL_TABLE" : map[string]interface{} { - "TestACL901": map[string] interface{} { + depDataMap := map[string]interface{}{ + "ACL_TABLE": map[string]interface{}{ + "TestACL901": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, - "TestACL902": map[string] interface{} { + "TestACL902": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, - "ACL_RULE" : map[string]interface{} { - "TestACL901|Rule1": map[string] interface{} { + "ACL_RULE": map[string]interface{}{ + "TestACL901|Rule1": map[string]interface{}{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "DST_IP": "20.2.2.2/32", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "DST_IP": "20.2.2.2/32", }, - "TestACL902|Rule1": map[string] interface{} { + "TestACL902|Rule1": map[string]interface{}{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.2/32", - "DST_IP": "20.2.2.4/32", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.2/32", + "DST_IP": "20.2.2.4/32", }, }, } @@ -195,14 +194,14 @@ func TestValidateEditConfig_Create_Leafref_Multi_Key_Positive(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "TAM_INT_IFA_FLOW_TABLE|Flow_1", - map[string]string { + map[string]string{ "acl-table-name": "TestACL901", - "acl-rule-name": "Rule1", + "acl-rule-name": "Rule1", }, }, } @@ -211,23 +210,23 @@ func TestValidateEditConfig_Create_Leafref_Multi_Key_Positive(t *testing.T) { } func TestValidateEditConfig_Create_Leafref_Multi_Key_Negative(t *testing.T) { - depDataMap := map[string]interface{} { - "ACL_TABLE" : map[string]interface{} { - "TestACL901": map[string] interface{} { + depDataMap := map[string]interface{}{ + "ACL_TABLE": map[string]interface{}{ + "TestACL901": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, - "TestACL902": map[string] interface{} { + "TestACL902": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, - "ACL_RULE" : map[string]interface{} { - "TestACL902|Rule1": map[string] interface{} { + "ACL_RULE": map[string]interface{}{ + "TestACL902|Rule1": map[string]interface{}{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.2/32", - "DST_IP": "20.2.2.4/32", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.2/32", + "DST_IP": "20.2.2.4/32", }, }, } @@ -236,14 +235,14 @@ func TestValidateEditConfig_Create_Leafref_Multi_Key_Negative(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "TAM_INT_IFA_FLOW_TABLE|Flow_1", - map[string]string { + map[string]string{ "acl-table-name": "TestACL901", - "acl-rule-name": "Rule1", //This is not there in above depDataMap + "acl-rule-name": "Rule1", //This is not there in above depDataMap }, }, } @@ -278,7 +277,7 @@ func TestValidateEditConfig_Create_Leafref_With_Other_DataType_In_Union_Positive cvl.OP_CREATE, "STP_PORT|StpIntf10", //Non-leafref map[string]string{ - "enabled": "true", + "enabled": "true", "edge_port": "true", "link_type": "shared", }, @@ -307,7 +306,7 @@ func TestValidateEditConfig_Create_Leafref_With_Other_DataType_In_Union_Negative cvl.OP_CREATE, "STP_PORT|Test12", //Non-leafref map[string]string{ - "enabled": "true", + "enabled": "true", "edge_port": "true", "link_type": "shared", }, @@ -343,7 +342,7 @@ func TestValidateEditConfig_Create_Leafref_With_Other_DataType_In_Union_Non_Exis cvl.OP_CREATE, "STP_PORT|Ethernet3999", //Correct PORT format but not existing map[string]string{ - "enabled": "true", + "enabled": "true", "edge_port": "true", "link_type": "shared", }, @@ -377,12 +376,12 @@ func TestValidateEditConfig_Delete_Leafref(t *testing.T) { }, "ACL_TABLE": map[string]interface{}{ "TestACL1": map[string]interface{}{ - "type": "L3", + "type": "L3", "stage": "INGRESS", "ports@": "PortChannel1", }, "TestACL2": map[string]interface{}{ - "type": "L3", + "type": "L3", "stage": "INGRESS", "ports@": "PortChannel3,PortChannel4", }, @@ -401,7 +400,7 @@ func TestValidateEditConfig_Delete_Leafref(t *testing.T) { } func deletePO(poId int, expSuccess bool) func(*testing.T) { - return func (t *testing.T) { + return func(t *testing.T) { session, _ := cvl.ValidationSessOpen() defer cvl.ValidationSessClose(session) validateDeletePO(t, session, nil, poId, expSuccess) @@ -409,7 +408,7 @@ func deletePO(poId int, expSuccess bool) func(*testing.T) { } func deleteACLAndPO(aclName, ports string, poId int, bulk, expSuccess bool) func(*testing.T) { - return func (t *testing.T) { + return func(t *testing.T) { session, _ := cvl.ValidationSessOpen() defer cvl.ValidationSessClose(session) var cfgData []cvl.CVLEditConfigData @@ -418,7 +417,7 @@ func deleteACLAndPO(aclName, ports string, poId int, bulk, expSuccess bool) func cvl.VALIDATE_ALL, cvl.OP_DELETE, fmt.Sprintf("ACL_TABLE|%s", aclName), - map[string]string{ }, + map[string]string{}, }) if ports != "nil" { @@ -447,7 +446,7 @@ func validateDeletePO(t *testing.T, session *cvl.CVL, cfgData []cvl.CVLEditConfi cvl.VALIDATE_ALL, cvl.OP_DELETE, fmt.Sprintf("PORTCHANNEL|PortChannel%d", poId), - map[string]string{ }, + map[string]string{}, }) errInfo, status := session.ValidateEditConfig(cfgData) @@ -458,4 +457,3 @@ func validateDeletePO(t *testing.T, session *cvl.CVL, cfgData []cvl.CVLEditConfi t.Errorf("po%d delete validation should have failed", poId) } } - diff --git a/cvl/cvl_luascript.go b/cvl/cvl_luascript.go index 0950c43bf..945a7ff81 100644 --- a/cvl/cvl_luascript.go +++ b/cvl/cvl_luascript.go @@ -18,12 +18,13 @@ //////////////////////////////////////////////////////////////////////////////// package cvl + import ( - "github.com/go-redis/redis/v7" "github.com/Azure/sonic-mgmt-common/cvl/internal/util" + "github.com/go-redis/redis/v7" ) -//Redis server side script +// Redis server side script func loadLuaScript(luaScripts map[string]*redis.Script) { // Find entry which has given fieldName and value diff --git a/cvl/cvl_must_test.go b/cvl/cvl_must_test.go index 89684d6df..8f690a855 100644 --- a/cvl/cvl_must_test.go +++ b/cvl/cvl_must_test.go @@ -20,50 +20,50 @@ package cvl_test import ( - "testing" "github.com/Azure/sonic-mgmt-common/cvl" + "testing" ) func TestValidateEditConfig_Delete_Must_Check_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "PORT" : map[string]interface{} { - "Ethernet3" : map[string]interface{} { - "alias":"hundredGigE1", + depDataMap := map[string]interface{}{ + "PORT": map[string]interface{}{ + "Ethernet3": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "81,82,83,84", }, - "Ethernet5" : map[string]interface{} { - "alias":"hundredGigE1", + "Ethernet5": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "85,86,87,89", }, }, - "ACL_TABLE" : map[string]interface{} { - "TestACL1": map[string] interface{} { - "stage": "INGRESS", - "type": "L3", + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ + "stage": "INGRESS", + "type": "L3", "ports@": "Ethernet3,Ethernet5", }, - "TestACL2": map[string] interface{} { + "TestACL2": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, - "ACL_RULE" : map[string]interface{} { - "TestACL1|Rule1": map[string] interface{} { - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", + "ACL_RULE": map[string]interface{}{ + "TestACL1|Rule1": map[string]interface{}{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", "L4_DST_PORT_RANGE": "9000-12000", }, - "TestACL2|Rule2": map[string] interface{} { - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", + "TestACL2|Rule2": map[string]interface{}{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", "L4_DST_PORT_RANGE": "9000-12000", }, }, @@ -73,13 +73,12 @@ func TestValidateEditConfig_Delete_Must_Check_Positive(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgDataAclRule := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAclRule := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "ACL_RULE|TestACL2|Rule2", - map[string]string { - }, + map[string]string{}, }, } @@ -87,34 +86,34 @@ func TestValidateEditConfig_Delete_Must_Check_Positive(t *testing.T) { } func TestValidateEditConfig_Delete_Must_Check_Negative(t *testing.T) { - depDataMap := map[string]interface{} { - "PORT" : map[string]interface{} { - "Ethernet3" : map[string]interface{} { - "alias":"hundredGigE1", + depDataMap := map[string]interface{}{ + "PORT": map[string]interface{}{ + "Ethernet3": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "81,82,83,84", //"mtu": "9100", }, - "Ethernet5" : map[string]interface{} { - "alias":"hundredGigE1", + "Ethernet5": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "85,86,87,89", //"mtu": "9100", }, }, - "ACL_TABLE" : map[string]interface{} { - "TestACL1": map[string] interface{} { - "stage": "INGRESS", - "type": "L3", + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ + "stage": "INGRESS", + "type": "L3", "ports@": "Ethernet3,Ethernet5", }, }, - "ACL_RULE" : map[string]interface{} { - "TestACL1|Rule1": map[string] interface{} { - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", + "ACL_RULE": map[string]interface{}{ + "TestACL1|Rule1": map[string]interface{}{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", "L4_DST_PORT_RANGE": "9000-12000", }, }, @@ -124,13 +123,12 @@ func TestValidateEditConfig_Delete_Must_Check_Negative(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgDataAclRule := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAclRule := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "ACL_RULE|TestACL1|Rule1", - map[string]string { - }, + map[string]string{}, }, } @@ -153,7 +151,7 @@ func TestValidateEditConfig_Create_ErrAppTag_In_Must_Negative(t *testing.T) { cvl.OP_CREATE, "VLAN|Vlan1001", map[string]string{ - "vlanid": "102", + "vlanid": "102", }, }, } @@ -168,27 +166,26 @@ func TestValidateEditConfig_Create_ErrAppTag_In_Must_Negative(t *testing.T) { } func TestValidateEditConfig_MustExp_With_Default_Value_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan2001": map[string] interface{} { - "vlanid": "2001", + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan2001": map[string]interface{}{ + "vlanid": "2001", }, }, } - //Try to create er interface collding with vlan interface IP prefix - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "CFG_L2MC_TABLE|Vlan2001", + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "CFG_L2MC_TABLE|Vlan2001", map[string]string{ - "enabled": "true", + "enabled": "true", "query-max-response-time": "25", //default query-interval = 125 }, - }, - } + }, + } loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) @@ -197,27 +194,26 @@ func TestValidateEditConfig_MustExp_With_Default_Value_Positive(t *testing.T) { } func TestValidateEditConfig_MustExp_With_Default_Value_Negative(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan2002": map[string] interface{} { - "vlanid": "2002", + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan2002": map[string]interface{}{ + "vlanid": "2002", }, }, } - //Try to create er interface collding with vlan interface IP prefix - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "CFG_L2MC_TABLE|Vlan2002", + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "CFG_L2MC_TABLE|Vlan2002", map[string]string{ - "enabled": "true", + "enabled": "true", "query-interval": "9", //default query-max-response-time = 10 }, - }, - } + }, + } loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) @@ -246,83 +242,82 @@ func TestValidateEditConfig_MustExp_With_Default_Value_Negative(t *testing.T) { } func TestValidateEditConfig_MustExp_Chained_Predicate_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan701": map[string] interface{} { + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan701": map[string]interface{}{ "vlanid": "701", "members@": "Ethernet20", }, - "Vlan702": map[string] interface{} { + "Vlan702": map[string]interface{}{ "vlanid": "702", "members@": "Ethernet20,Ethernet24,Ethernet28", }, - "Vlan703": map[string] interface{} { + "Vlan703": map[string]interface{}{ "vlanid": "703", "members@": "Ethernet20", }, }, - "VLAN_MEMBER" : map[string]interface{} { - "Vlan701|Ethernet20": map[string] interface{} { + "VLAN_MEMBER": map[string]interface{}{ + "Vlan701|Ethernet20": map[string]interface{}{ "tagging_mode": "tagged", }, - "Vlan702|Ethernet20": map[string] interface{} { + "Vlan702|Ethernet20": map[string]interface{}{ "tagging_mode": "tagged", }, - "Vlan702|Ethernet24": map[string] interface{} { + "Vlan702|Ethernet24": map[string]interface{}{ "tagging_mode": "tagged", }, - "Vlan702|Ethernet28": map[string] interface{} { + "Vlan702|Ethernet28": map[string]interface{}{ "tagging_mode": "tagged", }, - "Vlan703|Ethernet20": map[string] interface{} { + "Vlan703|Ethernet20": map[string]interface{}{ "tagging_mode": "tagged", }, }, - "INTERFACE" : map[string]interface{} { - "Ethernet20|1.1.1.0/32": map[string] interface{} { + "INTERFACE": map[string]interface{}{ + "Ethernet20|1.1.1.0/32": map[string]interface{}{ "NULL": "NULL", }, - "Ethernet24|1.1.2.0/32": map[string] interface{} { + "Ethernet24|1.1.2.0/32": map[string]interface{}{ "NULL": "NULL", }, - "Ethernet28|1.1.2.0/32": map[string] interface{} { + "Ethernet28|1.1.2.0/32": map[string]interface{}{ "NULL": "NULL", }, - "Ethernet20|1.1.3.0/32": map[string] interface{} { + "Ethernet20|1.1.3.0/32": map[string]interface{}{ "NULL": "NULL", }, }, - "VLAN_INTERFACE" : map[string]interface{} { - "Vlan701|2.2.2.0/32": map[string] interface{} { + "VLAN_INTERFACE": map[string]interface{}{ + "Vlan701|2.2.2.0/32": map[string]interface{}{ "NULL": "NULL", }, - "Vlan701|2.2.3.0/32": map[string] interface{} { + "Vlan701|2.2.3.0/32": map[string]interface{}{ "NULL": "NULL", }, - "Vlan702|2.2.4.0/32": map[string] interface{} { + "Vlan702|2.2.4.0/32": map[string]interface{}{ "NULL": "NULL", }, - "Vlan702|2.2.5.0/32": map[string] interface{} { + "Vlan702|2.2.5.0/32": map[string]interface{}{ "NULL": "NULL", }, - "Vlan703|2.2.6.0/32": map[string] interface{} { + "Vlan703|2.2.6.0/32": map[string]interface{}{ "NULL": "NULL", }, }, } - //Try to create er interface collding with vlan interface IP prefix - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "VLAN_INTERFACE|Vlan702|1.1.2.0/32", + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "VLAN_INTERFACE|Vlan702|1.1.2.0/32", map[string]string{ "NULL": "NULL", }, - }, - } + }, + } loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) @@ -339,57 +334,57 @@ func TestValidateEditConfig_MustExp_Chained_Predicate_Positive(t *testing.T) { } func TestValidateEditConfig_MustExp_Within_Same_Table_Negative(t *testing.T) { - //Try to create - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "TAM_COLLECTOR_TABLE|Col10", + //Try to create + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "TAM_COLLECTOR_TABLE|Col10", map[string]string{ "ipaddress-type": "ipv6", //Invalid ip address type - "ipaddress": "10.101.1.2", - }, - }, - } - - verifyValidateEditConfig(t, cfgData, CVLErrorInfo{ - ErrCode: CVL_SEMANTIC_ERROR, - TableName: "TAM_COLLECTOR_TABLE", - Keys: []string{"Col10"}, - Field: "ipaddress-type", - Value: "ipv6", - Msg: mustExpressionErrMessage, - ConstraintErrMsg: "IP address and IP address type does not match.", - ErrAppTag: "ipaddres-type-mismatch", - }) + "ipaddress": "10.101.1.2", + }, + }, + } + + verifyValidateEditConfig(t, cfgData, CVLErrorInfo{ + ErrCode: CVL_SEMANTIC_ERROR, + TableName: "TAM_COLLECTOR_TABLE", + Keys: []string{"Col10"}, + Field: "ipaddress-type", + Value: "ipv6", + Msg: mustExpressionErrMessage, + ConstraintErrMsg: "IP address and IP address type does not match.", + ErrAppTag: "ipaddres-type-mismatch", + }) } -//Check if all data is fetched for xpath without predicate +// Check if all data is fetched for xpath without predicate func TestValidateEditConfig_MustExp_Without_Predicate_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan201": map[string] interface{} { + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan201": map[string]interface{}{ "vlanid": "201", "members@": "Ethernet4,Ethernet8,Ethernet12,Ethernet16", }, - "Vlan202": map[string] interface{} { + "Vlan202": map[string]interface{}{ "vlanid": "202", "members@": "Ethernet4", }, }, } - //Try to create - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "VLAN_INTERFACE|Vlan201", + //Try to create + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "VLAN_INTERFACE|Vlan201", map[string]string{ "NULL": "NULL", }, - }, - } + }, + } loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) @@ -398,40 +393,40 @@ func TestValidateEditConfig_MustExp_Without_Predicate_Positive(t *testing.T) { } func TestValidateEditConfig_MustExp_Non_Key_As_Predicate_Negative(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan201": map[string] interface{} { - "vlanid": "201", + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan201": map[string]interface{}{ + "vlanid": "201", }, - "Vlan202": map[string] interface{} { - "vlanid": "202", + "Vlan202": map[string]interface{}{ + "vlanid": "202", }, }, - "VXLAN_TUNNEL" : map[string]interface{} { - "tun1": map[string] interface{} { - "src_ip": "10.10.1.2", + "VXLAN_TUNNEL": map[string]interface{}{ + "tun1": map[string]interface{}{ + "src_ip": "10.10.1.2", }, }, - "VXLAN_TUNNEL_MAP" : map[string]interface{} { - "tun1|vmap1": map[string] interface{} { + "VXLAN_TUNNEL_MAP": map[string]interface{}{ + "tun1|vmap1": map[string]interface{}{ "vlan": "Vlan201", - "vni": "300", + "vni": "300", }, }, } - //Try to create - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "VXLAN_TUNNEL_MAP|tun1|vmap2", + //Try to create + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "VXLAN_TUNNEL_MAP|tun1|vmap2", map[string]string{ "vlan": "Vlan202", - "vni": "300", //same VNI is not valid + "vni": "300", //same VNI is not valid }, - }, - } + }, + } loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) @@ -448,50 +443,50 @@ func TestValidateEditConfig_MustExp_Non_Key_As_Predicate_Negative(t *testing.T) } func TestValidateEditConfig_MustExp_Non_Key_As_Predicate_In_External_Table_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan201": map[string] interface{} { - "vlanid": "201", + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan201": map[string]interface{}{ + "vlanid": "201", }, - "Vlan202": map[string] interface{} { - "vlanid": "202", + "Vlan202": map[string]interface{}{ + "vlanid": "202", }, - "Vlan203": map[string] interface{} { - "vlanid": "203", + "Vlan203": map[string]interface{}{ + "vlanid": "203", }, }, - "VXLAN_TUNNEL" : map[string]interface{} { - "tun1": map[string] interface{} { - "src_ip": "10.10.1.2", + "VXLAN_TUNNEL": map[string]interface{}{ + "tun1": map[string]interface{}{ + "src_ip": "10.10.1.2", }, }, - "VXLAN_TUNNEL_MAP" : map[string]interface{} { - "tun1|vmap1": map[string] interface{} { + "VXLAN_TUNNEL_MAP": map[string]interface{}{ + "tun1|vmap1": map[string]interface{}{ "vlan": "Vlan201", - "vni": "301", + "vni": "301", }, - "tun1|vmap2": map[string] interface{} { + "tun1|vmap2": map[string]interface{}{ "vlan": "Vlan202", - "vni": "302", + "vni": "302", }, - "tun1|vmap3": map[string] interface{} { + "tun1|vmap3": map[string]interface{}{ "vlan": "Vlan203", - "vni": "303", + "vni": "303", }, }, } - //Try to create - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "VRF|vrf101", + //Try to create + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "VRF|vrf101", map[string]string{ "vni": "302", }, - }, - } + }, + } loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) @@ -500,10 +495,10 @@ func TestValidateEditConfig_MustExp_Non_Key_As_Predicate_In_External_Table_Posit } func TestValidateEditConfig_MustExp_Update_Leaf_List_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan202": map[string] interface{} { - "vlanid": "202", + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan202": map[string]interface{}{ + "vlanid": "202", }, }, } @@ -526,17 +521,17 @@ func TestValidateEditConfig_MustExp_Update_Leaf_List_Positive(t *testing.T) { } func TestValidateEditConfig_MustExp_Add_NULL(t *testing.T) { - depDataMap := map[string]interface{} { - "INTERFACE": map[string]interface{} { - "Ethernet20": map[string] interface{} { + depDataMap := map[string]interface{}{ + "INTERFACE": map[string]interface{}{ + "Ethernet20": map[string]interface{}{ "unnumbered": "Loopback1", }, }, - "LOOPBACK_INTERFACE": map[string]interface{} { - "Loopback1": map[string] interface{} { + "LOOPBACK_INTERFACE": map[string]interface{}{ + "Loopback1": map[string]interface{}{ "NULL": "NULL", }, - "Loopback1|1.2.3.4/32": map[string] interface{} { + "Loopback1|1.2.3.4/32": map[string]interface{}{ "NULL": "NULL", }, }, @@ -549,14 +544,14 @@ func TestValidateEditConfig_MustExp_Add_NULL(t *testing.T) { VType: cvl.VALIDATE_ALL, VOp: cvl.OP_DELETE, Key: "INTERFACE|Ethernet20", - Data: map[string]string{ "unnumbered": "" }, + Data: map[string]string{"unnumbered": ""}, } addNull := cvl.CVLEditConfigData{ VType: cvl.VALIDATE_ALL, VOp: cvl.OP_UPDATE, Key: "INTERFACE|Ethernet20", - Data: map[string]string{ "NULL": "NULL" }, + Data: map[string]string{"NULL": "NULL"}, } t.Run("before", testNullAdd(addNull, delUnnumber)) diff --git a/cvl/cvl_semantics.go b/cvl/cvl_semantics.go index 2a7c4684d..227ad0d43 100644 --- a/cvl/cvl_semantics.go +++ b/cvl/cvl_semantics.go @@ -20,49 +20,48 @@ package cvl import ( - "fmt" - "encoding/xml" "encoding/json" - "strings" - "regexp" - "github.com/antchfx/xpath" - "github.com/antchfx/xmlquery" - "github.com/antchfx/jsonquery" + "encoding/xml" + "fmt" "github.com/Azure/sonic-mgmt-common/cvl/internal/yparser" + "github.com/antchfx/jsonquery" + "github.com/antchfx/xmlquery" + "github.com/antchfx/xpath" + "regexp" + "strings" //lint:ignore ST1001 This is safe to dot import for util package . "github.com/Azure/sonic-mgmt-common/cvl/internal/util" ) -//YValidator YANG Validator used for external semantic -//validation including custom/platform validation +// YValidator YANG Validator used for external semantic +// validation including custom/platform validation type YValidator struct { - root *xmlquery.Node //Top evel root for data + root *xmlquery.Node //Top evel root for data current *xmlquery.Node //Current position //operation string //Edit operation } -//Generate leaf/leaf-list YANG data +// Generate leaf/leaf-list YANG data func (c *CVL) generateYangLeafData(tableName string, jsonNode *jsonquery.Node, -parent *xmlquery.Node) CVLRetCode { + parent *xmlquery.Node) CVLRetCode { //Traverse fields - for jsonFieldNode := jsonNode.FirstChild; jsonFieldNode!= nil; - jsonFieldNode = jsonFieldNode.NextSibling { + for jsonFieldNode := jsonNode.FirstChild; jsonFieldNode != nil; jsonFieldNode = jsonFieldNode.NextSibling { //Add fields as leaf to the list - if (jsonFieldNode.Type == jsonquery.ElementNode && - jsonFieldNode.FirstChild != nil && - jsonFieldNode.FirstChild.Type == jsonquery.TextNode) { + if jsonFieldNode.Type == jsonquery.ElementNode && + jsonFieldNode.FirstChild != nil && + jsonFieldNode.FirstChild.Type == jsonquery.TextNode { - if (len(modelInfo.tableInfo[tableName].mapLeaf) == 2) {//mapping should have two leaf always + if len(modelInfo.tableInfo[tableName].mapLeaf) == 2 { //mapping should have two leaf always //Values should be stored inside another list as map table listNode := c.addYangNode(tableName, parent, tableName, "") //Add the list to the top node c.addYangNode(tableName, - listNode, modelInfo.tableInfo[tableName].mapLeaf[0], - jsonFieldNode.Data) + listNode, modelInfo.tableInfo[tableName].mapLeaf[0], + jsonFieldNode.Data) c.addYangNode(tableName, - listNode, modelInfo.tableInfo[tableName].mapLeaf[1], - jsonFieldNode.FirstChild.Data) + listNode, modelInfo.tableInfo[tableName].mapLeaf[1], + jsonFieldNode.FirstChild.Data) } else { //check if it is hash-ref, then need to add only key from "TABLE|k1" @@ -70,25 +69,24 @@ parent *xmlquery.Node) CVLRetCode { if len(hashRefMatch) == 3 { c.addYangNode(tableName, - parent, jsonFieldNode.Data, - hashRefMatch[2]) //take hashref key value + parent, jsonFieldNode.Data, + hashRefMatch[2]) //take hashref key value } else { c.addYangNode(tableName, - parent, jsonFieldNode.Data, - jsonFieldNode.FirstChild.Data) + parent, jsonFieldNode.Data, + jsonFieldNode.FirstChild.Data) } } - } else if (jsonFieldNode.Type == jsonquery.ElementNode && - jsonFieldNode.FirstChild != nil && - jsonFieldNode.FirstChild.Type == jsonquery.ElementNode) { + } else if jsonFieldNode.Type == jsonquery.ElementNode && + jsonFieldNode.FirstChild != nil && + jsonFieldNode.FirstChild.Type == jsonquery.ElementNode { //Array data e.g. VLAN members@ or 'ports@' - for arrayNode:=jsonFieldNode.FirstChild; arrayNode != nil; - arrayNode = arrayNode.NextSibling { + for arrayNode := jsonFieldNode.FirstChild; arrayNode != nil; arrayNode = arrayNode.NextSibling { node := c.addYangNode(tableName, - parent, jsonFieldNode.Data, - arrayNode.FirstChild.Data) + parent, jsonFieldNode.Data, + arrayNode.FirstChild.Data) //mark these nodes as leaf-list addAttrNode(node, "leaf-list", "") @@ -101,23 +99,23 @@ parent *xmlquery.Node) CVLRetCode { //Check if default node is already present in data var child *xmlquery.Node for child = parent.FirstChild; child != nil; child = child.NextSibling { - if (child.Data == nodeName) { + if child.Data == nodeName { break } } - if (child != nil) { + if child != nil { //node is already present, skip adding it continue } valArr := strings.Split(valStr, ",") - for idx := 0; idx < len(valArr); idx ++ { + for idx := 0; idx < len(valArr); idx++ { node := c.addYangNode(tableName, - parent, nodeName, valArr[idx]) + parent, nodeName, valArr[idx]) //mark these nodes as leaf-list - if (len(valArr) > 1) { + if len(valArr) > 1 { addAttrNode(node, "leaf-list", "") } } @@ -126,9 +124,9 @@ parent *xmlquery.Node) CVLRetCode { return CVL_SUCCESS } -//Add attribute YANG node +// Add attribute YANG node func addAttrNode(n *xmlquery.Node, key, val string) { - var attr xml.Attr = xml.Attr { + var attr xml.Attr = xml.Attr{ Name: xml.Name{Local: key}, Value: val, } @@ -137,7 +135,7 @@ func addAttrNode(n *xmlquery.Node, key, val string) { } func getAttrNodeVal(node *xmlquery.Node, name string) string { - if (node == nil) { + if node == nil { return "" } @@ -146,7 +144,7 @@ func getAttrNodeVal(node *xmlquery.Node, name string) string { } for idx := 0; idx < len(node.Attr); idx++ { - if (node.Attr[idx].Name.Local == name) { + if node.Attr[idx].Name.Local == name { return node.Attr[idx].Value } } @@ -154,27 +152,27 @@ func getAttrNodeVal(node *xmlquery.Node, name string) string { return "" } -//Add YANG node with or without parent, with or without value +// Add YANG node with or without parent, with or without value func (c *CVL) addYangNode(tableName string, parent *xmlquery.Node, - name string, value string) *xmlquery.Node { + name string, value string) *xmlquery.Node { //Create the node node := &xmlquery.Node{Parent: parent, Data: name, Type: xmlquery.ElementNode} - //Set prefix from parent - if (parent != nil) { + //Set prefix from parent + if parent != nil { node.Prefix = parent.Prefix } - if (value != "") { + if value != "" { //Create the value node textNode := &xmlquery.Node{Data: value, Type: xmlquery.TextNode} node.FirstChild = textNode node.LastChild = textNode } - if (parent == nil) { + if parent == nil { //Creating top node return node } @@ -195,13 +193,13 @@ func (c *CVL) addYangNode(tableName string, parent *xmlquery.Node, return node } -//Generate YANG list data along with top container, -//table container. -//If needed, stores the list pointer against each request table/key -//in requestCahce so that YANG data can be reached -//directly on given table/key +// Generate YANG list data along with top container, +// table container. +// If needed, stores the list pointer against each request table/key +// in requestCahce so that YANG data can be reached +// directly on given table/key func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, - storeInReqCache bool)(*xmlquery.Node, CVLErrorInfo) { + storeInReqCache bool) (*xmlquery.Node, CVLErrorInfo) { var cvlErrObj CVLErrorInfo tableName := jsonNode.Data @@ -209,15 +207,15 @@ func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, c.batchLeaf = make([]*yparser.YParserLeafValue, 0) //Every Redis table is mapped as list within a container, - //E.g. ACL_RULE is mapped as + //E.g. ACL_RULE is mapped as // container ACL_RULE { list ACL_RULE_LIST {} } var topNode *xmlquery.Node if _, exists := modelInfo.tableInfo[tableName]; !exists { CVL_LOG(WARNING, "Failed to find schema details for table %s", tableName) cvlErrObj.ErrCode = CVL_SYNTAX_ERROR - cvlErrObj.TableName = tableName - cvlErrObj.Msg ="Schema details not found" + cvlErrObj.TableName = tableName + cvlErrObj.Msg = "Schema details not found" return nil, cvlErrObj } @@ -227,7 +225,7 @@ func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, topNode.Prefix = modelInfo.tableInfo[tableName].modelName topNode.NamespaceURI = modelInfo.modelNs[modelInfo.tableInfo[tableName].modelName].ns - //Add the container node for each list + //Add the container node for each list //e.g. 'container ACL_TABLE { list ACL_TABLE_LIST ...} listConatinerNode := c.addYangNode(tableName, topNode, tableName, "") @@ -240,10 +238,10 @@ func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, //Mark at least one key is present keyPresent = true - //For each field check if is key + //For each field check if is key //If it is key, create list as child of top container // Get all key name/value pairs - if yangListName := getRedisTblToYangList(tableName, redisKey); yangListName!= "" { + if yangListName := getRedisTblToYangList(tableName, redisKey); yangListName != "" { tableName = yangListName } keyValuePair := getRedisToYangKeys(tableName, redisKey) @@ -259,22 +257,22 @@ func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, keyIndices = append(keyIndices, 0) } - for ; totalKeyComb > 0 ; totalKeyComb-- { + for ; totalKeyComb > 0; totalKeyComb-- { //Get the YANG list name from Redis table name //Ideally they are same except when one Redis table is split //into multiple YANG lists //Add table i.e. create list element - listNode := c.addYangNode(tableName, listConatinerNode, tableName + "_LIST", "") //Add the list to the top node + listNode := c.addYangNode(tableName, listConatinerNode, tableName+"_LIST", "") //Add the list to the top node addAttrNode(listNode, "key", redisKey) if storeInReqCache { //store the list pointer in requestCache against the table/key reqCache, exists := c.requestCache[tableName][redisKey] if exists { - //Store same list instance in all requests under same table/key + //Store same list instance in all requests under same table/key for idx := 0; idx < len(reqCache); idx++ { - if (reqCache[idx].yangData == nil) { + if reqCache[idx].yangData == nil { //Save the YANG data tree for using it later reqCache[idx].yangData = listNode } @@ -286,7 +284,7 @@ func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, //Add keys as leaf to the list for idx = 0; idx < keyCompCount; idx++ { c.addYangNode(tableName, listNode, keyValuePair[idx].key, - keyValuePair[idx].values[keyIndices[idx]]) + keyValuePair[idx].values[keyIndices[idx]]) } //Get all fields under the key field and add them as children of the list @@ -294,18 +292,18 @@ func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, //Check which key elements left after current key element var next int = keyCompCount - 1 - for ((next > 0) && ((keyIndices[next] +1) >= len(keyValuePair[next].values))) { + for (next > 0) && ((keyIndices[next] + 1) >= len(keyValuePair[next].values)) { next-- } //No more combination possible - if (next < 0) { + if next < 0 { break } keyIndices[next]++ //Reset indices for all other key elements - for idx = next+1; idx < keyCompCount; idx++ { + for idx = next + 1; idx < keyCompCount; idx++ { keyIndices[idx] = 0 } } @@ -318,21 +316,21 @@ func (c *CVL) generateYangListData(jsonNode *jsonquery.Node, return topNode, cvlErrObj } -//Append given children to destNode +// Append given children to destNode func (c *CVL) appendSubtree(dest, src *xmlquery.Node) CVLRetCode { - if (dest == nil || src == nil) { + if dest == nil || src == nil { return CVL_FAILURE } var lastSibling *xmlquery.Node = nil - for srcNode := src; srcNode != nil ; srcNode = srcNode.NextSibling { + for srcNode := src; srcNode != nil; srcNode = srcNode.NextSibling { //set parent for all nodes srcNode.Parent = dest lastSibling = srcNode } - if (dest.LastChild == nil) { + if dest.LastChild == nil { //No sibling in dest yet dest.FirstChild = src dest.LastChild = lastSibling @@ -346,12 +344,12 @@ func (c *CVL) appendSubtree(dest, src *xmlquery.Node) CVLRetCode { return CVL_SUCCESS } -//Return subtree after detaching from parent -func (c *CVL) detachSubtree(parent *xmlquery.Node) *xmlquery.Node { +// Return subtree after detaching from parent +func (c *CVL) detachSubtree(parent *xmlquery.Node) *xmlquery.Node { child := parent.FirstChild - if (child != nil) { + if child != nil { //set children to nil parent.FirstChild = nil parent.LastChild = nil @@ -361,39 +359,39 @@ func (c *CVL) detachSubtree(parent *xmlquery.Node) *xmlquery.Node { } //Detach all children from parent - for node := child; node != nil; node = node.NextSibling { + for node := child; node != nil; node = node.NextSibling { node.Parent = nil } return child } -//Detach a node from its parent +// Detach a node from its parent func (c *CVL) detachNode(node *xmlquery.Node) CVLRetCode { - if (node == nil) { + if node == nil { return CVL_FAILURE } //get the parent node parent := node.Parent - if (parent == nil) { + if parent == nil { //Already detached node return CVL_SUCCESS } //adjust siblings - if (parent.FirstChild == node && parent.LastChild == node) { + if parent.FirstChild == node && parent.LastChild == node { //this is the only node parent.FirstChild = nil parent.LastChild = nil - } else if (parent.FirstChild == node) { + } else if parent.FirstChild == node { //first child, set new first child parent.FirstChild = node.NextSibling node.NextSibling.PrevSibling = nil } else { node.PrevSibling.NextSibling = node.NextSibling - if (node.NextSibling != nil) { + if node.NextSibling != nil { //if remaining sibling node.NextSibling.PrevSibling = node.PrevSibling } else { @@ -411,20 +409,20 @@ func (c *CVL) detachNode(node *xmlquery.Node) CVLRetCode { return CVL_SUCCESS } -//Delete all leaf-list nodes in destination -//Leaf-list should be replaced from source -//destination -func (c *CVL) deleteDestLeafList(dest *xmlquery.Node) { +// Delete all leaf-list nodes in destination +// Leaf-list should be replaced from source +// destination +func (c *CVL) deleteDestLeafList(dest *xmlquery.Node) { - TRACE_LOG(TRACE_CACHE, "Updating leaf-list by " + - "removing and then adding leaf-list") + TRACE_LOG(TRACE_CACHE, "Updating leaf-list by "+ + "removing and then adding leaf-list") //find start and end of dest leaf list leafListName := dest.Data - for node := dest; node != nil; { - tmpNextNode := node.NextSibling + for node := dest; node != nil; { + tmpNextNode := node.NextSibling - if (node.Data == leafListName) { + if node.Data == leafListName { c.detachNode(node) node = tmpNextNode continue @@ -448,34 +446,34 @@ func (c *CVL) deleteLeafNodes(topNode *xmlquery.Node, cfgData map[string]string) } } -//Check if the given list src node already exists in dest node +// Check if the given list src node already exists in dest node func (c *CVL) checkIfListNodeExists(dest, src *xmlquery.Node) *xmlquery.Node { if (dest == nil) || (src == nil) { - return nil + return nil } tableName := getYangListToRedisTbl(src.Data) redisKey := getAttrNodeVal(src, "key") - if (tableName == "" || redisKey == "") { + if tableName == "" || redisKey == "" { return nil } entry, exists := c.requestCache[tableName][redisKey] if !exists || (len(entry) == 0) { - return nil + return nil } //CREATE/UPDATE/DELETE request for same table/key points to //same yang list in request cache yangList := entry[0].yangData - if (yangList == nil || yangList.Parent == nil) { + if yangList == nil || yangList.Parent == nil { //Source node does not exist in destination return nil } - if (dest.Parent == yangList.Parent) { + if dest.Parent == yangList.Parent { //Same parent means yang list already exists in destination tree return yangList } @@ -483,16 +481,16 @@ func (c *CVL) checkIfListNodeExists(dest, src *xmlquery.Node) *xmlquery.Node { return nil } -//Merge YANG data recursively from dest to src -//Leaf-list is always replaced and appeneded at -//the end of list's children +// Merge YANG data recursively from dest to src +// Leaf-list is always replaced and appeneded at +// the end of list's children func (c *CVL) mergeYangData(dest, src *xmlquery.Node) CVLRetCode { if (dest == nil) || (src == nil) { return CVL_FAILURE } TRACE_LOG((TRACE_SYNTAX | TRACE_SEMANTIC), - "Merging YANG data %s %s", dest.Data, src.Data) + "Merging YANG data %s %s", dest.Data, src.Data) if (dest.Type == xmlquery.TextNode) && (src.Type == xmlquery.TextNode) { //handle leaf node by updating value @@ -507,16 +505,16 @@ func (c *CVL) mergeYangData(dest, src *xmlquery.Node) CVLRetCode { //Find all source nodes and attach to the matching destination node ret := CVL_FAILURE //TRACE_LOG((TRACE_SYNTAX | TRACE_SEMANTIC), "MergeData : src loop\n") -destLoop: + destLoop: destNode := dest for ; destNode != nil; destNode = destNode.NextSibling { //TRACE_LOG((TRACE_SYNTAX | TRACE_SEMANTIC), "MergeData : dest loop\n") - if (destNode.Data != srcNode.Data) { + if destNode.Data != srcNode.Data { //Can proceed to subtree only if current node name matches continue } - if (strings.HasSuffix(destNode.Data, "_LIST")){ + if strings.HasSuffix(destNode.Data, "_LIST") { //Check if src list node already exists in destination tmpNode := c.checkIfListNodeExists(destNode, srcNode) if tmpNode != nil { @@ -533,8 +531,8 @@ destLoop: continue }*/ } else if (len(destNode.Attr) > 0) && (len(srcNode.Attr) > 0) && - (destNode.Attr[0].Name.Local == "leaf-list") && - (srcNode.Attr[0].Name.Local == "leaf-list") { // attribute has type + (destNode.Attr[0].Name.Local == "leaf-list") && + (srcNode.Attr[0].Name.Local == "leaf-list") { // attribute has type delFlag, exists := destLeafListDeleted[srcNode.Data] @@ -542,7 +540,7 @@ destLoop: //Replace all leaf-list nodes from destination first c.deleteDestLeafList(destNode) destLeafListDeleted[srcNode.Data] = true - //Note that 'dest' still points to list keys + //Note that 'dest' still points to list keys //even though all leaf-list might have been deleted //as we never delete key while merging goto destLoop @@ -562,14 +560,14 @@ destLoop: } //dest node loop - if (ret == CVL_FAILURE) { - if (destNode == nil) { + if ret == CVL_FAILURE { + if destNode == nil { //destNode == nil -> node not found //detach srcNode and append to dest - tmpNextSrcNode := srcNode.NextSibling + tmpNextSrcNode := srcNode.NextSibling if CVL_SUCCESS == c.detachNode(srcNode) { if (len(srcNode.Attr) > 0) && - (srcNode.Attr[0].Name.Local == "leaf-list") { + (srcNode.Attr[0].Name.Local == "leaf-list") { //set the flag so that we don't delete leaf-list //from destNode further destLeafListDeleted[srcNode.Data] = true @@ -581,7 +579,7 @@ destLoop: } else { //subtree merge failure ,, append subtree subTree := c.detachSubtree(srcNode) - if (subTree != nil) { + if subTree != nil { c.appendSubtree(destNode, subTree) } } @@ -601,7 +599,7 @@ func (c *CVL) findYangList(tableName string, redisKey string) *xmlquery.Node { return tmpCurrent } -//Locate YANG list instance in root for given table name and key +// Locate YANG list instance in root for given table name and key func (c *CVL) moveToYangList(tableName string, redisKey string) *xmlquery.Node { var nodeTbl *xmlquery.Node = nil @@ -611,13 +609,13 @@ func (c *CVL) moveToYangList(tableName string, redisKey string) *xmlquery.Node { //move to the model first for node := c.yv.root.FirstChild; node != nil; node = node.NextSibling { - if (node.Data != modelName) { + if node.Data != modelName { continue } //Move to container for nodeTbl = node.FirstChild; nodeTbl != nil; nodeTbl = nodeTbl.NextSibling { - if (nodeTbl.Data == redisTableName) { + if nodeTbl.Data == redisTableName { break } } @@ -625,29 +623,29 @@ func (c *CVL) moveToYangList(tableName string, redisKey string) *xmlquery.Node { break } - if (nodeTbl == nil) { + if nodeTbl == nil { TRACE_LOG(TRACE_SEMANTIC, "YANG data for table %s, key %s is not present in YANG tree", - tableName, redisKey) + tableName, redisKey) return nil } //Move to list listName := tableName + "_LIST" for nodeList := nodeTbl.FirstChild; nodeList != nil; nodeList = nodeList.NextSibling { - if (nodeList.Data != listName) { + if nodeList.Data != listName { continue } c.yv.current = nodeList //if no key specified or no other instance exists, //just return the first list instance - if (redisKey == "" || nodeList.NextSibling == nil) { + if redisKey == "" || nodeList.NextSibling == nil { return c.yv.current } - for ; (nodeList != nil); nodeList = nodeList.NextSibling { + for ; nodeList != nil; nodeList = nodeList.NextSibling { if (len(nodeList.Attr) > 0) && - (nodeList.Attr[0].Value == redisKey) { + (nodeList.Attr[0].Value == redisKey) { c.yv.current = nodeList return nodeList } @@ -655,23 +653,23 @@ func (c *CVL) moveToYangList(tableName string, redisKey string) *xmlquery.Node { } CVL_LOG(WARNING, "No list entry matched, unable to find YANG data for table %s, key %s", - tableName, redisKey) + tableName, redisKey) return nil } -//Set operation node value based on operation in request received +// Set operation node value based on operation in request received func (c *CVL) setOperation(op CVLOperation) { var node *xmlquery.Node for node = c.yv.root.FirstChild; node != nil; node = node.NextSibling { - if (node.Data == "operation") { + if node.Data == "operation" { break } } //Add the operation container - if (node == nil) { + if node == nil { node = c.addYangNode("", c.yv.root, "operation", "") node.Prefix = "sonic-common" //"cmn" //modelInfo.modelNs["sonic-common"].prefix @@ -680,7 +678,7 @@ func (c *CVL) setOperation(op CVLOperation) { opNode := node.FirstChild if opNode == nil { - node.Prefix = "sonic-common"//"cmn" + node.Prefix = "sonic-common" //"cmn" opNode = c.addYangNode("", node, "operation", "NONE") } @@ -696,36 +694,36 @@ func (c *CVL) setOperation(op CVLOperation) { } } -//Add given YANG data buffer to Yang Validator -//redisKeys - Set of redis keys -//redisKeyFilter - Redis key filter in glob style pattern -//keyNames - Names of all keys separated by "|" -//predicate - Condition on keys/fields -//fields - Fields to retrieve, separated by "|" -//Return "," separated list of leaf nodes if only one leaf is requested -//One leaf is used as xpath query result in other nested xpath +// Add given YANG data buffer to Yang Validator +// redisKeys - Set of redis keys +// redisKeyFilter - Redis key filter in glob style pattern +// keyNames - Names of all keys separated by "|" +// predicate - Condition on keys/fields +// fields - Fields to retrieve, separated by "|" +// Return "," separated list of leaf nodes if only one leaf is requested +// One leaf is used as xpath query result in other nested xpath func (c *CVL) addDepYangData(redisKeys []string, redisKeyFilter, - keyNames, predicate, fields, count string) string { + keyNames, predicate, fields, count string) string { var v interface{} tmpPredicate := "" - //Get filtered Redis data based on lua script + //Get filtered Redis data based on lua script //filter derived from Xpath predicate - if (predicate != "") { + if predicate != "" { tmpPredicate = "return (" + predicate + ")" } cfgData, err := luaScripts["filter_entries"].Run(redisClient, []string{}, - redisKeyFilter, keyNames, tmpPredicate, fields, count).Result() + redisKeyFilter, keyNames, tmpPredicate, fields, count).Result() singleLeaf := "" //leaf data for single leaf - TRACE_LOG(TRACE_SEMANTIC, "addDepYangData() with redisKeyFilter=%s, " + - "predicate=%s, fields=%s, returned cfgData = %s, err=%v", - redisKeyFilter, predicate, fields, cfgData, err) + TRACE_LOG(TRACE_SEMANTIC, "addDepYangData() with redisKeyFilter=%s, "+ + "predicate=%s, fields=%s, returned cfgData = %s, err=%v", + redisKeyFilter, predicate, fields, cfgData, err) - if (cfgData == nil) { + if cfgData == nil { return "" } @@ -739,28 +737,26 @@ func (c *CVL) addDepYangData(redisKeys []string, redisKeyFilter, dataTop, _ := jsonquery.ParseJsonMap(&dataMap) - for jsonNode := dataTop.FirstChild; jsonNode != nil; jsonNode=jsonNode.NextSibling { + for jsonNode := dataTop.FirstChild; jsonNode != nil; jsonNode = jsonNode.NextSibling { //Generate YANG data for Yang Validator from Redis JSON topYangNode, _ := c.generateYangListData(jsonNode, false) - if topYangNode == nil { + if topYangNode == nil { continue } if (topYangNode.FirstChild != nil) && - (topYangNode.FirstChild.FirstChild != nil) { + (topYangNode.FirstChild.FirstChild != nil) { //Add attribute mentioning that data is from db addAttrNode(topYangNode.FirstChild.FirstChild, "db", "") } //Build single leaf data requested singleLeaf = "" - for redisKey := topYangNode.FirstChild.FirstChild; - redisKey != nil; redisKey = redisKey.NextSibling { + for redisKey := topYangNode.FirstChild.FirstChild; redisKey != nil; redisKey = redisKey.NextSibling { - for field := redisKey.FirstChild; field != nil; - field = field.NextSibling { - if (field.Data == fields && field.FirstChild != nil) { + for field := redisKey.FirstChild; field != nil; field = field.NextSibling { + if field.Data == fields && field.FirstChild != nil { //Single field requested singleLeaf = singleLeaf + field.FirstChild.Data + "," break @@ -778,26 +774,25 @@ func (c *CVL) addDepYangData(redisKeys []string, redisKeyFilter, } } - //remove last comma in case mulitple values returned - if (singleLeaf != "") { - return singleLeaf[:len(singleLeaf) - 1] + if singleLeaf != "" { + return singleLeaf[:len(singleLeaf)-1] } return "" } -//Add all other table data for validating all 'must' exp for tableName -//One entry is needed for incremental loading of must tables +// Add all other table data for validating all 'must' exp for tableName +// One entry is needed for incremental loading of must tables func (c *CVL) addYangDataForMustExp(op CVLOperation, tableName string, oneEntry bool) CVLRetCode { - if (modelInfo.tableInfo[tableName].mustExpr == nil) { + if modelInfo.tableInfo[tableName].mustExpr == nil { return CVL_SUCCESS } for mustTblName, mustOp := range modelInfo.tableInfo[tableName].tablesForMustExp { //First check if must expression should be executed for the given operation if (mustOp != OP_NONE) && ((mustOp & op) == OP_NONE) { - //must to be excuted for particular operation, but current operation + //must to be excuted for particular operation, but current operation //is not the same one continue } @@ -813,14 +808,14 @@ func (c *CVL) addYangDataForMustExp(op CVLOperation, tableName string, oneEntry } redisTblName := getYangListToRedisTbl(mustTblName) //1 yang to N Redis table case - tableKeys, err:= redisClient.Keys(redisTblName + - modelInfo.tableInfo[mustTblName].redisKeyDelim + "*").Result() + tableKeys, err := redisClient.Keys(redisTblName + + modelInfo.tableInfo[mustTblName].redisKeyDelim + "*").Result() - if (err != nil) { + if err != nil { return CVL_FAILURE } - if (len(tableKeys) == 0) { + if len(tableKeys) == 0 { //No dependent data for mustTable available continue } @@ -833,28 +828,28 @@ func (c *CVL) addYangDataForMustExp(op CVLOperation, tableName string, oneEntry tableKey = tableKey[tablePrefixLen:] //remove table prefix tmpKeyArr := strings.Split(tableKey, modelInfo.tableInfo[mustTblName].redisKeyDelim) - if (len(tmpKeyArr) != len(modelInfo.tableInfo[mustTblName].keys)) { + if len(tmpKeyArr) != len(modelInfo.tableInfo[mustTblName].keys) { //Number of keys should be same as in YANG list keys //Need to check this for one Redis table to many YANG list case continue } - if (cvg.cv.tmpDbCache[redisTblName] == nil) { + if cvg.cv.tmpDbCache[redisTblName] == nil { cvg.cv.tmpDbCache[redisTblName] = map[string]interface{}{tableKey: nil} } else { tblMap := cvg.cv.tmpDbCache[redisTblName] - tblMap.(map[string]interface{})[tableKey] =nil + tblMap.(map[string]interface{})[tableKey] = nil cvg.cv.tmpDbCache[redisTblName] = tblMap } - //Load only one entry + //Load only one entry if oneEntry { TRACE_LOG(TRACE_SEMANTIC, "addYangDataForMustExp(): Adding one entry table %s, key %s", - redisTblName, tableKey) + redisTblName, tableKey) break } } - if (cvg.cv.tmpDbCache[redisTblName] == nil) { + if cvg.cv.tmpDbCache[redisTblName] == nil { //No entry present in DB continue } @@ -863,22 +858,22 @@ func (c *CVL) addYangDataForMustExp(op CVLOperation, tableName string, oneEntry cvg.cv.fetchTableDataToTmpCache(redisTblName, cvg.cv.tmpDbCache[redisTblName].(map[string]interface{})) data, err := jsonquery.ParseJsonMap(&cvg.cv.tmpDbCache) - if (err != nil) { + if err != nil { return CVL_FAILURE } //Build yang tree for each table and cache it - for jsonNode := data.FirstChild; jsonNode != nil; jsonNode=jsonNode.NextSibling { + for jsonNode := data.FirstChild; jsonNode != nil; jsonNode = jsonNode.NextSibling { //Visit each top level list in a loop for creating table data topYangNode, _ := c.generateYangListData(jsonNode, false) - if (topYangNode == nil) { + if topYangNode == nil { //No entry found, check next entry continue } if (topYangNode.FirstChild != nil) && - (topYangNode.FirstChild.FirstChild != nil) { + (topYangNode.FirstChild.FirstChild != nil) { //Add attribute mentioning that data is from db addAttrNode(topYangNode.FirstChild.FirstChild, "db", "") } @@ -898,41 +893,41 @@ func (c *CVL) addYangDataForMustExp(op CVLOperation, tableName string, oneEntry return CVL_SUCCESS } -//Compile all must expression and save the expression tree +// Compile all must expression and save the expression tree func compileMustExps() { reMultiPred := regexp.MustCompile(`\][ ]*\[`) for _, tInfo := range modelInfo.tableInfo { - if (tInfo.mustExpr == nil) { + if tInfo.mustExpr == nil { continue } // Replace multiple predicate using 'and' expressiona // xpath engine not accepting multiple predicates - for _, mustExprArr := range tInfo.mustExpr { - for _, mustExpr := range mustExprArr { + for _, mustExprArr := range tInfo.mustExpr { + for _, mustExpr := range mustExprArr { mustExpr.exprTree = xpath.MustCompile( - reMultiPred.ReplaceAllString(mustExpr.expr, " and ")) + reMultiPred.ReplaceAllString(mustExpr.expr, " and ")) } } } } -//Compile all when expression and save the expression tree +// Compile all when expression and save the expression tree func compileWhenExps() { reMultiPred := regexp.MustCompile(`\][ ]*\[`) for _, tInfo := range modelInfo.tableInfo { - if (tInfo.whenExpr == nil) { + if tInfo.whenExpr == nil { continue } // Replace multiple predicate using 'and' expressiona // xpath engine not accepting multiple predicates - for _, whenExprArr := range tInfo.whenExpr { + for _, whenExprArr := range tInfo.whenExpr { for _, whenExpr := range whenExprArr { whenExpr.exprTree = xpath.MustCompile( - reMultiPred.ReplaceAllString(whenExpr.expr, " and ")) + reMultiPred.ReplaceAllString(whenExpr.expr, " and ")) //Store all YANG list used in the expression whenExpr.yangListNames = getYangListNamesInExpr(whenExpr.expr) } @@ -944,14 +939,14 @@ func compileLeafRefPath() { reMultiPred := regexp.MustCompile(`\][ ]*\[`) for _, tInfo := range modelInfo.tableInfo { - if (len(tInfo.leafRef) == 0) { //no leafref + if len(tInfo.leafRef) == 0 { //no leafref continue } //for nodeName, leafRefArr := range tInfo.leafRef { - for _, leafRefArr := range tInfo.leafRef { + for _, leafRefArr := range tInfo.leafRef { for _, leafRefArrItem := range leafRefArr { - if (leafRefArrItem.path == "non-leafref") { + if leafRefArrItem.path == "non-leafref" { //Leaf type has at-least one non-learef data type continue } @@ -960,12 +955,12 @@ func compileLeafRefPath() { leafRefArrItem.yangListNames, leafRefArrItem.targetNodeName = getLeafRefTargetInfo(leafRefArrItem.path) //check if predicate is used in path - //for complex expression, xpath engine is + //for complex expression, xpath engine is //used for evaluation, //else don't build expression tree, //it is handled by just checking redis entry if strings.Contains(leafRefArrItem.path, "[") && - strings.Contains(leafRefArrItem.path, "]") { + strings.Contains(leafRefArrItem.path, "]") { //Compile the xpath in leafref tmpExp := reMultiPred.ReplaceAllString(leafRefArrItem.path, " and ") //tmpExp = nodeName + " = " + tmpExp @@ -977,20 +972,20 @@ func compileLeafRefPath() { } } -//Validate must expression +// Validate must expression func (c *CVL) validateMustExp(node *xmlquery.Node, tableName, key string, op CVLOperation) (r CVLErrorInfo) { defer func() { ret := &r - CVL_LOG(INFO_API, "validateMustExp(): table name = %s, " + - "return value = %v", tableName, *ret) + CVL_LOG(INFO_API, "validateMustExp(): table name = %s, "+ + "return value = %v", tableName, *ret) }() c.setOperation(op) //Set xpath callback for retreiving dependent data xpath.SetDepDataClbk(c, func(ctxt interface{}, redisKeys []string, - redisKeyFilter, keyNames, pred, fields, count string) string { + redisKeyFilter, keyNames, pred, fields, count string) string { c := ctxt.(*CVL) TRACE_LOG(TRACE_SEMANTIC, "validateMustExp(): calling addDepYangData()") @@ -999,14 +994,14 @@ func (c *CVL) validateMustExp(node *xmlquery.Node, //Set xpath callback for retriving dependent data count xpath.SetDepDataCntClbk(c, func(ctxt interface{}, - redisKeyFilter, keyNames, pred, field string) float64 { + redisKeyFilter, keyNames, pred, field string) float64 { - if (pred != "") { + if pred != "" { pred = "return (" + pred + ")" } redisEntries, err := luaScripts["count_entries"].Run(redisClient, - []string{}, redisKeyFilter, keyNames, pred, field).Result() + []string{}, redisKeyFilter, keyNames, pred, field).Result() count := float64(0) @@ -1014,25 +1009,25 @@ func (c *CVL) validateMustExp(node *xmlquery.Node, count = float64(redisEntries.(int64)) } - TRACE_LOG(TRACE_SEMANTIC, "validateMustExp(): depDataCntClbk() with redisKeyFilter=%s, " + - "keyNames= %s, predicate=%s, fields=%s, returned = %v", - redisKeyFilter, keyNames, pred, field, count) + TRACE_LOG(TRACE_SEMANTIC, "validateMustExp(): depDataCntClbk() with redisKeyFilter=%s, "+ + "keyNames= %s, predicate=%s, fields=%s, returned = %v", + redisKeyFilter, keyNames, pred, field, count) return count }) - if (node == nil || node.FirstChild == nil) { + if node == nil || node.FirstChild == nil { return CVLErrorInfo{ - TableName: tableName, - ErrCode: CVL_SEMANTIC_ERROR, + TableName: tableName, + ErrCode: CVL_SEMANTIC_ERROR, CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_ERROR], - Msg: "Failed to find YANG data for must expression validation", + Msg: "Failed to find YANG data for must expression validation", } } //Load all table's any one entry for 'must' expression execution. //This helps building full YANG tree for tables needed. - //Other instances/entries would be fetched as per xpath predicate execution + //Other instances/entries would be fetched as per xpath predicate execution //during expression evaluation c.addYangDataForMustExp(op, tableName, true) @@ -1040,9 +1035,9 @@ func (c *CVL) validateMustExp(node *xmlquery.Node, for nodeName, mustExpArr := range modelInfo.tableInfo[tableName].mustExpr { for _, mustExp := range mustExpArr { ctxNode := node - if (ctxNode.Data != nodeName) { //must expression at list level + if ctxNode.Data != nodeName { //must expression at list level ctxNode = ctxNode.FirstChild - for (ctxNode !=nil) && (ctxNode.Data != nodeName) { + for (ctxNode != nil) && (ctxNode.Data != nodeName) { ctxNode = ctxNode.NextSibling //must expression at leaf level } if ctxNode != nil && op == OP_UPDATE { @@ -1053,71 +1048,71 @@ func (c *CVL) validateMustExp(node *xmlquery.Node, //Check leafref for each leaf-list node /*for ;(ctxNode != nil) && (ctxNode.Data == nodeName); ctxNode = ctxNode.NextSibling { - //Load first data for each referred table. + //Load first data for each referred table. //c.yv.root has all requested data merged and any depdendent //data needed for leafref validation should be available from this. leafRefSuccess := false*/ - if (ctxNode != nil) { + if ctxNode != nil { CVL_LOG(INFO_DEBUG, "Eval must \"%s\"; ctxNode=%s", mustExp.expr, ctxNode.Data) - if (!xmlquery.Eval(c.yv.root, ctxNode, mustExp.exprTree)) { + if !xmlquery.Eval(c.yv.root, ctxNode, mustExp.exprTree) { keys := []string{} - if (len(ctxNode.Parent.Attr) > 0) { - keys = strings.Split(ctxNode.Parent.Attr[0].Value, - modelInfo.tableInfo[tableName].redisKeyDelim) + if len(ctxNode.Parent.Attr) > 0 { + keys = strings.Split(ctxNode.Parent.Attr[0].Value, + modelInfo.tableInfo[tableName].redisKeyDelim) } return CVLErrorInfo{ - TableName: tableName, - ErrCode: CVL_SEMANTIC_ERROR, - CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_ERROR], - Keys: keys, - Value: ctxNode.FirstChild.Data, - Field: nodeName, - Msg: "Must expression validation failed", + TableName: tableName, + ErrCode: CVL_SEMANTIC_ERROR, + CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_ERROR], + Keys: keys, + Value: ctxNode.FirstChild.Data, + Field: nodeName, + Msg: "Must expression validation failed", ConstraintErrMsg: mustExp.errStr, - ErrAppTag: mustExp.errCode, + ErrAppTag: mustExp.errCode, } } } } //for each must exp } //all must exp under one node - return CVLErrorInfo{ErrCode:CVL_SUCCESS} + return CVLErrorInfo{ErrCode: CVL_SUCCESS} } -//Currently supports when expression with current table only +// Currently supports when expression with current table only func (c *CVL) validateWhenExp(node *xmlquery.Node, tableName, key string, op CVLOperation) (r CVLErrorInfo) { defer func() { ret := &r - CVL_LOG(INFO_API, "validateWhenExp(): table name = %s, " + - "return value = %v", tableName, *ret) + CVL_LOG(INFO_API, "validateWhenExp(): table name = %s, "+ + "return value = %v", tableName, *ret) }() - if (op == OP_DELETE) { + if op == OP_DELETE { //No new node getting added so skip when validation - return CVLErrorInfo{ErrCode:CVL_SUCCESS} + return CVLErrorInfo{ErrCode: CVL_SUCCESS} } //Set xpath callback for retreiving dependent data xpath.SetDepDataClbk(c, func(ctxt interface{}, redisKeys []string, - redisKeyFilter, keyNames, pred, fields, count string) string { + redisKeyFilter, keyNames, pred, fields, count string) string { c := ctxt.(*CVL) TRACE_LOG(TRACE_SEMANTIC, "validateWhenExp(): calling addDepYangData()") return c.addDepYangData(redisKeys, redisKeyFilter, keyNames, pred, fields, "") }) - if (node == nil || node.FirstChild == nil) { + if node == nil || node.FirstChild == nil { return CVLErrorInfo{ - TableName: tableName, - ErrCode: CVL_SEMANTIC_ERROR, + TableName: tableName, + ErrCode: CVL_SEMANTIC_ERROR, CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_ERROR], - Msg: "Failed to find YANG data for must expression validation", + Msg: "Failed to find YANG data for must expression validation", } } @@ -1125,9 +1120,9 @@ func (c *CVL) validateWhenExp(node *xmlquery.Node, for nodeName, whenExpArr := range modelInfo.tableInfo[tableName].whenExpr { for _, whenExp := range whenExpArr { //for each when expression ctxNode := node - if (ctxNode.Data != nodeName) { //when expression not at list level + if ctxNode.Data != nodeName { //when expression not at list level ctxNode = ctxNode.FirstChild - for (ctxNode !=nil) && (ctxNode.Data != nodeName) { + for (ctxNode != nil) && (ctxNode.Data != nodeName) { ctxNode = ctxNode.NextSibling //whent expression at leaf level } } @@ -1138,47 +1133,46 @@ func (c *CVL) validateWhenExp(node *xmlquery.Node, refRedisTableName := getYangListToRedisTbl(refListName) filter := refRedisTableName + - modelInfo.tableInfo[refListName].redisKeyDelim + "*" + modelInfo.tableInfo[refListName].redisKeyDelim + "*" c.addDepYangData([]string{}, filter, - strings.Join(modelInfo.tableInfo[refListName].keys, "|"), - "true", "", "1") //fetch one entry only + strings.Join(modelInfo.tableInfo[refListName].keys, "|"), + "true", "", "1") //fetch one entry only } //Validate the when expression if (ctxNode != nil) && !(xmlquery.Eval(c.yv.root, ctxNode, whenExp.exprTree)) { keys := []string{} - if (len(ctxNode.Parent.Attr) > 0) { - keys = strings.Split(ctxNode.Parent.Attr[0].Value, - modelInfo.tableInfo[tableName].redisKeyDelim) + if len(ctxNode.Parent.Attr) > 0 { + keys = strings.Split(ctxNode.Parent.Attr[0].Value, + modelInfo.tableInfo[tableName].redisKeyDelim) } if (len(whenExp.nodeNames) == 1) && //when in leaf - (nodeName == whenExp.nodeNames[0]) { + (nodeName == whenExp.nodeNames[0]) { return CVLErrorInfo{ - TableName: tableName, - ErrCode: CVL_SEMANTIC_ERROR, + TableName: tableName, + ErrCode: CVL_SEMANTIC_ERROR, CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_ERROR], - Keys: keys, - Value: ctxNode.FirstChild.Data, - Field: nodeName, - Msg: "When expression validation failed", + Keys: keys, + Value: ctxNode.FirstChild.Data, + Field: nodeName, + Msg: "When expression validation failed", } } else { //check if any nodes in whenExp.nodeNames //present in request data, when at list level whenNodeList := strings.Join(whenExp.nodeNames, ",") + "," - for cNode := node.FirstChild; cNode !=nil; - cNode = cNode.NextSibling { + for cNode := node.FirstChild; cNode != nil; cNode = cNode.NextSibling { if strings.Contains(whenNodeList, (cNode.Data + ",")) { return CVLErrorInfo{ - TableName: tableName, - ErrCode: CVL_SEMANTIC_ERROR, + TableName: tableName, + ErrCode: CVL_SEMANTIC_ERROR, CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_ERROR], - Keys: keys, - Value: cNode.FirstChild.Data, - Field: cNode.Data, - Msg: "When expression validation failed", + Keys: keys, + Value: cNode.FirstChild.Data, + Field: cNode.Data, + Msg: "When expression validation failed", } } } @@ -1187,42 +1181,42 @@ func (c *CVL) validateWhenExp(node *xmlquery.Node, } } - return CVLErrorInfo{ErrCode:CVL_SUCCESS} + return CVLErrorInfo{ErrCode: CVL_SUCCESS} } -//Validate leafref -//Convert leafref to must expression -//type leafref { path "../../../ACL_TABLE/ACL_TABLE_LIST/aclname";} converts to +// Validate leafref +// Convert leafref to must expression +// type leafref { path "../../../ACL_TABLE/ACL_TABLE_LIST/aclname";} converts to // "current() = ../../../ACL_TABLE/ACL_TABLE_LIST[aclname=current()]/aclname" func (c *CVL) validateLeafRef(node *xmlquery.Node, tableName, key string, op CVLOperation) (r CVLErrorInfo) { defer func() { ret := &r - CVL_LOG(INFO_API, "validateLeafRef(): table name = %s, " + - "return value = %v", tableName, *ret) + CVL_LOG(INFO_API, "validateLeafRef(): table name = %s, "+ + "return value = %v", tableName, *ret) }() - if (op == OP_DELETE) { + if op == OP_DELETE { //No new node getting added so skip leafref validation - return CVLErrorInfo{ErrCode:CVL_SUCCESS} + return CVLErrorInfo{ErrCode: CVL_SUCCESS} } //Set xpath callback for retreiving dependent data xpath.SetDepDataClbk(c, func(ctxt interface{}, redisKeys []string, - redisKeyFilter, keyNames, pred, fields, count string) string { + redisKeyFilter, keyNames, pred, fields, count string) string { c := ctxt.(*CVL) TRACE_LOG(TRACE_SEMANTIC, "validateLeafRef(): calling addDepYangData()") return c.addDepYangData(redisKeys, redisKeyFilter, keyNames, pred, fields, "") }) listNode := node - if (listNode == nil || listNode.FirstChild == nil) { + if listNode == nil || listNode.FirstChild == nil { return CVLErrorInfo{ - TableName: tableName, - Keys: strings.Split(key, modelInfo.tableInfo[tableName].redisKeyDelim), - ErrCode: CVL_SEMANTIC_ERROR, + TableName: tableName, + Keys: strings.Split(key, modelInfo.tableInfo[tableName].redisKeyDelim), + ErrCode: CVL_SEMANTIC_ERROR, CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_ERROR], - Msg: "Failed to find YANG data for leafref expression validation", + Msg: "Failed to find YANG data for leafref expression validation", } } @@ -1232,19 +1226,17 @@ func (c *CVL) validateLeafRef(node *xmlquery.Node, //Reach to the node where leafref is present ctxNode := listNode.FirstChild - for ;(ctxNode !=nil) && (ctxNode.Data != nodeName); - ctxNode = ctxNode.NextSibling { + for ; (ctxNode != nil) && (ctxNode.Data != nodeName); ctxNode = ctxNode.NextSibling { } - if (ctxNode == nil) { + if ctxNode == nil { //No leafref instance present, proceed to next leafref continue } //Check leafref for each leaf-list node - for ;(ctxNode != nil) && (ctxNode.Data == nodeName); - ctxNode = ctxNode.NextSibling { - //Load first data for each referred table. + for ; (ctxNode != nil) && (ctxNode.Data == nodeName); ctxNode = ctxNode.NextSibling { + //Load first data for each referred table. //c.yv.root has all requested data merged and any depdendent //data needed for leafref validation should be available from this. @@ -1254,14 +1246,14 @@ func (c *CVL) validateLeafRef(node *xmlquery.Node, ctxtVal := "" //Get the leaf value - if (ctxNode.FirstChild != nil) { + if ctxNode.FirstChild != nil { ctxtVal = ctxNode.FirstChild.Data } //Excute all leafref checks, multiple leafref for unions - leafRefLoop: + leafRefLoop: for _, leafRefPath := range leafRefs { - if (leafRefPath.path == "non-leafref") { + if leafRefPath.path == "non-leafref" { //Leaf has at-least one non-leaferf data type in union nonLeafRefPresent = true continue @@ -1274,34 +1266,33 @@ func (c *CVL) validateLeafRef(node *xmlquery.Node, filter := "" var err error var tableKeys []string - if (leafRefPath.exprTree == nil) { //no predicate, single key case + if leafRefPath.exprTree == nil { //no predicate, single key case //Context node used for leafref //Keys -> ACL_TABLE|TestACL1 filter = refRedisTableName + - modelInfo.tableInfo[refListName].redisKeyDelim + ctxtVal + modelInfo.tableInfo[refListName].redisKeyDelim + ctxtVal tableKeys, err = redisClient.Keys(filter).Result() } else { //Keys -> ACL_TABLE|* - filter = refRedisTableName + - modelInfo.tableInfo[refListName].redisKeyDelim + "*" + filter = refRedisTableName + + modelInfo.tableInfo[refListName].redisKeyDelim + "*" //tableKeys, _, err = redisClient.Scan(0, filter, 1).Result() tableKeys, err = redisClient.Keys(filter).Result() } if (err != nil) || (len(tableKeys) == 0) { //There must be at least one entry in the ref table - TRACE_LOG(TRACE_SEMANTIC, "Leafref dependent data " + - "table %s, key %s not found in Redis", refRedisTableName, - ctxtVal) + TRACE_LOG(TRACE_SEMANTIC, "Leafref dependent data "+ + "table %s, key %s not found in Redis", refRedisTableName, + ctxtVal) - if (leafRefPath.exprTree == nil) { + if leafRefPath.exprTree == nil { //Check the key in request cache also if _, exists := c.requestCache[refRedisTableName][ctxtVal]; exists { //no predicate and single key is referred leafRefSuccess = true break leafRefLoop - } else if node := c.findYangList(refListName, ctxtVal); - node != nil { + } else if node := c.findYangList(refListName, ctxtVal); node != nil { //Found in the request tree leafRefSuccess = true break leafRefLoop @@ -1309,17 +1300,17 @@ func (c *CVL) validateLeafRef(node *xmlquery.Node, } continue } else { - if (leafRefPath.exprTree == nil) { + if leafRefPath.exprTree == nil { //no predicate and single key is referred leafRefSuccess = true break leafRefLoop } } - //Now add the first data + //Now add the first data c.addDepYangData([]string{}, tableKeys[0], - strings.Join(modelInfo.tableInfo[refListName].keys, "|"), - "true", "", "") + strings.Join(modelInfo.tableInfo[refListName].keys, "|"), + "true", "", "") } //Excute xpath expression for complex leafref path @@ -1333,12 +1324,12 @@ func (c *CVL) validateLeafRef(node *xmlquery.Node, //If union has mixed type with base and leafref type, //check if node value matched with any leafref. //If so non-existence of leafref in DB will be treated as failure. - if (ctxtVal != "") { + if ctxtVal != "" { nodeValMatchedWithLeafref = c.yp.IsLeafrefMatchedInUnion(tblInfo.module, - fmt.Sprintf("/%s:%s/%s/%s_LIST/%s", tblInfo.modelName, - tblInfo.modelName, tblInfo.redisTableName, - tableName, nodeName), - ctxtVal) + fmt.Sprintf("/%s:%s/%s/%s_LIST/%s", tblInfo.modelName, + tblInfo.modelName, tblInfo.redisTableName, + tableName, nodeName), + ctxtVal) } } @@ -1347,38 +1338,38 @@ func (c *CVL) validateLeafRef(node *xmlquery.Node, return CVLErrorInfo{ TableName: tableName, Keys: strings.Split(key, - modelInfo.tableInfo[tableName].redisKeyDelim), - ErrCode: CVL_SEMANTIC_DEPENDENT_DATA_MISSING, - CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_DEPENDENT_DATA_MISSING], - ErrAppTag: "instance-required", + modelInfo.tableInfo[tableName].redisKeyDelim), + ErrCode: CVL_SEMANTIC_DEPENDENT_DATA_MISSING, + CVLErrDetails: cvlErrorMap[CVL_SEMANTIC_DEPENDENT_DATA_MISSING], + ErrAppTag: "instance-required", ConstraintErrMsg: "No instance found for '" + ctxtVal + "'", } } else if !leafRefSuccess { - TRACE_LOG(TRACE_SEMANTIC, "validateLeafRef(): " + - "Leafref dependent data not found but leaf has " + - "other data type in union, returning success.") + TRACE_LOG(TRACE_SEMANTIC, "validateLeafRef(): "+ + "Leafref dependent data not found but leaf has "+ + "other data type in union, returning success.") } } //for each leaf-list node } - return CVLErrorInfo{ErrCode:CVL_SUCCESS} + return CVLErrorInfo{ErrCode: CVL_SUCCESS} } -//This function returns true if any entry -//in request cache is using the given entry -//getting deleted. The given entry can be found -//either in key or in hash-field. -//Example : If T1|K1 is getting deleted, -//check if T2*|K1 or T2|*:{H1: K1} -//was using T1|K1 and getting deleted -//in same session also. +// This function returns true if any entry +// in request cache is using the given entry +// getting deleted. The given entry can be found +// either in key or in hash-field. +// Example : If T1|K1 is getting deleted, +// check if T2*|K1 or T2|*:{H1: K1} +// was using T1|K1 and getting deleted +// in same session also. func (c *CVL) checkDeleteInRequestCache(cfgData []CVLEditConfigData, leafRef *tblFieldPair, depDataKey, keyVal string) bool { for _, cfgDataItem := range cfgData { // All cfgDataItems which have VType as VALIDATE_NONE should be // checked in cache - if (cfgDataItem.VType != VALIDATE_NONE) { + if cfgDataItem.VType != VALIDATE_NONE { continue } @@ -1444,7 +1435,7 @@ func (c *CVL) checkDepDataCompatible(tblName, key, reftblName, refTblKey, leafRe // target tbl key is left of '=' leafrefTargetTblkey := predicate[:strings.Index(predicate, "=")] if strings.Contains(leafrefTargetTblkey, ":") { - leafrefTargetTblkey = leafrefTargetTblkey[strings.Index(leafrefTargetTblkey, ":")+1 :] + leafrefTargetTblkey = leafrefTargetTblkey[strings.Index(leafrefTargetTblkey, ":")+1:] } // current tbl key is right of '=' after last '/'('current()/../vrf_name") leafrefCurrentTblkey := predicate[strings.LastIndex(predicate, "/")+1:] @@ -1472,16 +1463,16 @@ func (c *CVL) checkDepDataCompatible(tblName, key, reftblName, refTblKey, leafRe return true } -//Check delete constraint for leafref if key/field is deleted +// Check delete constraint for leafref if key/field is deleted func (c *CVL) checkDeleteConstraint(cfgData []CVLEditConfigData, - tableName, keyVal, field string) CVLRetCode { + tableName, keyVal, field string) CVLRetCode { // Creating a map of leaf-ref referred tableName and associated fields array refTableFieldsMap := map[string][]string{} for _, leafRef := range modelInfo.tableInfo[tableName].refFromTables { // If field is getting deleted, then collect only those leaf-refs that // refers that field - if (field != "") && ((field != leafRef.field) || (field != leafRef.field + "@")) { + if (field != "") && ((field != leafRef.field) || (field != leafRef.field+"@")) { continue } @@ -1521,7 +1512,7 @@ func (c *CVL) checkDeleteConstraint(cfgData []CVLEditConfigData, for _, leafRefField := range leafRefFieldsArr { TRACE_LOG(TRACE_SEMANTIC, "checkDeleteConstraint--> Checking delete constraint for leafRef %s/%s", refTblName, leafRefField) // Key compatibility to be checked only if no. of keys are more than 1 - // because dep data for key like "BGP_PEER_GROUP|Vrf1|PG1" can be returned as + // because dep data for key like "BGP_PEER_GROUP|Vrf1|PG1" can be returned as // BGP_NEIGHBOR|Vrf1|11.1.1.1 or BGP_NEIGHBOR|default|11.1.1.1 or BGP_NEIGHBOR|Vrf2|11.1.1.1 // So we have to discard imcompatible dep data if !c.checkDepDataCompatible(tableName, keyVal, refTblName, refTblKey, leafRefField, depData.Entry[depEntkey]) { @@ -1554,7 +1545,7 @@ func (c *CVL) checkDeleteConstraint(cfgData []CVLEditConfigData, return CVL_SUCCESS } -//Validate external dependency using leafref, must and when expression +// Validate external dependency using leafref, must and when expression func (c *CVL) validateSemantics(node *xmlquery.Node, yangListName, key string, cfgData *CVLEditConfigData) (r CVLErrorInfo) { @@ -1565,20 +1556,18 @@ func (c *CVL) validateSemantics(node *xmlquery.Node, } //Check all leafref - if errObj := c.validateLeafRef(node, yangListName, key, cfgData.VOp) ; - errObj.ErrCode != CVL_SUCCESS { + if errObj := c.validateLeafRef(node, yangListName, key, cfgData.VOp); errObj.ErrCode != CVL_SUCCESS { return errObj } //Validate when expression - if errObj := c.validateWhenExp(node, yangListName, key, cfgData.VOp) ; - errObj.ErrCode != CVL_SUCCESS { + if errObj := c.validateWhenExp(node, yangListName, key, cfgData.VOp); errObj.ErrCode != CVL_SUCCESS { return errObj } //Validate must expression - if (cfgData.VOp == OP_DELETE) { - if (len(cfgData.Data) > 0) { + if cfgData.VOp == OP_DELETE { + if len(cfgData.Data) > 0 { // Delete leaf nodes from tree. This ensures validateMustExp will // skip all must expressions defined for deleted nodes; and other // must expressions get correct context. @@ -1586,34 +1575,32 @@ func (c *CVL) validateSemantics(node *xmlquery.Node, } } - if errObj := c.validateMustExp(node, yangListName, key, cfgData.VOp) ; - errObj.ErrCode != CVL_SUCCESS { + if errObj := c.validateMustExp(node, yangListName, key, cfgData.VOp); errObj.ErrCode != CVL_SUCCESS { return errObj } - return CVLErrorInfo{ErrCode:CVL_SUCCESS} + return CVLErrorInfo{ErrCode: CVL_SUCCESS} } -//Validate external dependency using leafref, must and when expression +// Validate external dependency using leafref, must and when expression func (c *CVL) validateCfgSemantics(root *xmlquery.Node) (r CVLErrorInfo) { - if (strings.HasSuffix(root.Data, "_LIST")) { - if (len(root.Attr) == 0) { - return CVLErrorInfo{ErrCode:CVL_SUCCESS} + if strings.HasSuffix(root.Data, "_LIST") { + if len(root.Attr) == 0 { + return CVLErrorInfo{ErrCode: CVL_SUCCESS} } - yangListName := root.Data[:len(root.Data) - 5] + yangListName := root.Data[:len(root.Data)-5] return c.validateSemantics(root, yangListName, root.Attr[0].Value, - &CVLEditConfigData{VType: VALIDATE_NONE, VOp: OP_NONE}) + &CVLEditConfigData{VType: VALIDATE_NONE, VOp: OP_NONE}) } //Traverse through all list instances and validate ret := CVLErrorInfo{} - for node := root.FirstChild; node != nil ; node = node.NextSibling { + for node := root.FirstChild; node != nil; node = node.NextSibling { ret = c.validateCfgSemantics(node) - if (ret.ErrCode != CVL_SUCCESS) { + if ret.ErrCode != CVL_SUCCESS { break } } return ret } - diff --git a/cvl/cvl_syntax.go b/cvl/cvl_syntax.go index f60ae86a1..61dbf78b0 100644 --- a/cvl/cvl_syntax.go +++ b/cvl/cvl_syntax.go @@ -18,17 +18,18 @@ //////////////////////////////////////////////////////////////////////////////// package cvl + import ( - "github.com/antchfx/jsonquery" "github.com/Azure/sonic-mgmt-common/cvl/internal/yparser" + "github.com/antchfx/jsonquery" //lint:ignore ST1001 This is safe to dot import for util package . "github.com/Azure/sonic-mgmt-common/cvl/internal/util" ) -//This function should be called before adding any new entry -//Checks max-elements defined with (current number of entries -//getting added + entries already added and present in request -//cache + entries present in Redis DB) +// This function should be called before adding any new entry +// Checks max-elements defined with (current number of entries +// getting added + entries already added and present in request +// cache + entries present in Redis DB) func (c *CVL) checkMaxElemConstraint(op CVLOperation, tableName string) CVLRetCode { var nokey []string @@ -45,10 +46,10 @@ func (c *CVL) checkMaxElemConstraint(op CVLOperation, tableName string) CVLRetCo curSize, exists := c.maxTableElem[tableName] if !exists { //fetch from Redis first time in the session - redisEntries, err := luaScripts["count_entries"].Run(redisClient, nokey, tableName + "|*").Result() + redisEntries, err := luaScripts["count_entries"].Run(redisClient, nokey, tableName+"|*").Result() if err != nil { - CVL_LOG(WARNING,"Unable to fetch current size of table %s from Redis, err= %v", - tableName, err) + CVL_LOG(WARNING, "Unable to fetch current size of table %s from Redis, err= %v", + tableName, err) return CVL_FAILURE } @@ -58,31 +59,31 @@ func (c *CVL) checkMaxElemConstraint(op CVLOperation, tableName string) CVLRetCo c.maxTableElem[tableName] = curSize } - if (op == OP_DELETE) { + if op == OP_DELETE { //For delete operation we need to reduce the count. - //Because same table can be deleted and added back + //Because same table can be deleted and added back //in same session. - if (curSize > 0) { + if curSize > 0 { c.maxTableElem[tableName] = (curSize - 1) } return CVL_SUCCESS } //Otherwise CREATE case - if curSize >= modelInfo.tableInfo[tableName].redisTableSize { + if curSize >= modelInfo.tableInfo[tableName].redisTableSize { CVL_LOG(WARNING, "%s table size has already reached to max-elements %d", - tableName, modelInfo.tableInfo[tableName].redisTableSize) + tableName, modelInfo.tableInfo[tableName].redisTableSize) return CVL_SYNTAX_ERROR } curSize = curSize + 1 - if (curSize > modelInfo.tableInfo[tableName].redisTableSize) { + if curSize > modelInfo.tableInfo[tableName].redisTableSize { //Does not meet the constraint - CVL_LOG(WARNING, "Max-elements check failed for table '%s'," + - " current size = %v, size in schema = %v", - tableName, curSize, modelInfo.tableInfo[tableName].redisTableSize) + CVL_LOG(WARNING, "Max-elements check failed for table '%s',"+ + " current size = %v, size in schema = %v", + tableName, curSize, modelInfo.tableInfo[tableName].redisTableSize) return CVL_SYNTAX_ERROR } @@ -93,9 +94,8 @@ func (c *CVL) checkMaxElemConstraint(op CVLOperation, tableName string) CVLRetCo return CVL_SUCCESS } - -//Add child node to a parent node -func(c *CVL) addChildNode(tableName string, parent *yparser.YParserNode, name string) *yparser.YParserNode { +// Add child node to a parent node +func (c *CVL) addChildNode(tableName string, parent *yparser.YParserNode, name string) *yparser.YParserNode { //return C.lyd_new(parent, modelInfo.tableInfo[tableName].module, C.CString(name)) return c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, parent, name) @@ -105,36 +105,35 @@ func (c *CVL) addChildLeaf(config bool, tableName string, parent *yparser.YParse /* If there is no value then assign default space string. */ if len(value) == 0 { - value = " " - } + value = " " + } //Batch leaf creation *multileaf = append(*multileaf, &yparser.YParserLeafValue{Name: name, Value: value}) } func (c *CVL) generateTableFieldsData(config bool, tableName string, jsonNode *jsonquery.Node, -parent *yparser.YParserNode, multileaf *[]*yparser.YParserLeafValue) CVLErrorInfo { + parent *yparser.YParserNode, multileaf *[]*yparser.YParserLeafValue) CVLErrorInfo { var cvlErrObj CVLErrorInfo //Traverse fields - for jsonFieldNode := jsonNode.FirstChild; jsonFieldNode!= nil; - jsonFieldNode = jsonFieldNode.NextSibling { + for jsonFieldNode := jsonNode.FirstChild; jsonFieldNode != nil; jsonFieldNode = jsonFieldNode.NextSibling { //Add fields as leaf to the list - if (jsonFieldNode.Type == jsonquery.ElementNode && - jsonFieldNode.FirstChild != nil && - jsonFieldNode.FirstChild.Type == jsonquery.TextNode) { + if jsonFieldNode.Type == jsonquery.ElementNode && + jsonFieldNode.FirstChild != nil && + jsonFieldNode.FirstChild.Type == jsonquery.TextNode { - if (len(modelInfo.tableInfo[tableName].mapLeaf) == 2) {//mapping should have two leaf always + if len(modelInfo.tableInfo[tableName].mapLeaf) == 2 { //mapping should have two leaf always batchInnerListLeaf := make([]*yparser.YParserLeafValue, 0) //Values should be stored inside another list as map table listNode := c.addChildNode(tableName, parent, tableName) //Add the list to the top node c.addChildLeaf(config, tableName, - listNode, modelInfo.tableInfo[tableName].mapLeaf[0], - jsonFieldNode.Data, &batchInnerListLeaf) + listNode, modelInfo.tableInfo[tableName].mapLeaf[0], + jsonFieldNode.Data, &batchInnerListLeaf) c.addChildLeaf(config, tableName, - listNode, modelInfo.tableInfo[tableName].mapLeaf[1], - jsonFieldNode.FirstChild.Data, &batchInnerListLeaf) + listNode, modelInfo.tableInfo[tableName].mapLeaf[1], + jsonFieldNode.FirstChild.Data, &batchInnerListLeaf) if errObj := c.yp.AddMultiLeafNodes(modelInfo.tableInfo[tableName].module, listNode, batchInnerListLeaf); errObj.ErrCode != yparser.YP_SUCCESS { cvlErrObj = createCVLErrObj(errObj, jsonNode) @@ -148,25 +147,23 @@ parent *yparser.YParserNode, multileaf *[]*yparser.YParserLeafValue) CVLErrorInf if len(hashRefMatch) == 3 { c.addChildLeaf(config, tableName, - parent, jsonFieldNode.Data, - hashRefMatch[2], multileaf) //take hashref key value + parent, jsonFieldNode.Data, + hashRefMatch[2], multileaf) //take hashref key value } else { c.addChildLeaf(config, tableName, - parent, jsonFieldNode.Data, - jsonFieldNode.FirstChild.Data, multileaf) + parent, jsonFieldNode.Data, + jsonFieldNode.FirstChild.Data, multileaf) } } - } else if (jsonFieldNode.Type == jsonquery.ElementNode && - jsonFieldNode.FirstChild != nil && - jsonFieldNode.FirstChild.Type == jsonquery.ElementNode) { + } else if jsonFieldNode.Type == jsonquery.ElementNode && + jsonFieldNode.FirstChild != nil && + jsonFieldNode.FirstChild.Type == jsonquery.ElementNode { //Array data e.g. VLAN members - for arrayNode:=jsonFieldNode.FirstChild; arrayNode != nil; - - arrayNode = arrayNode.NextSibling { + for arrayNode := jsonFieldNode.FirstChild; arrayNode != nil; arrayNode = arrayNode.NextSibling { c.addChildLeaf(config, tableName, - parent, jsonFieldNode.Data, - arrayNode.FirstChild.Data, multileaf) + parent, jsonFieldNode.Data, + arrayNode.FirstChild.Data, multileaf) } } } @@ -175,7 +172,7 @@ parent *yparser.YParserNode, multileaf *[]*yparser.YParserLeafValue) CVLErrorInf return cvlErrObj } -func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser.YParserNode, CVLErrorInfo) { +func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node) (*yparser.YParserNode, CVLErrorInfo) { var cvlErrObj CVLErrorInfo tableName := jsonNode.Data @@ -183,7 +180,7 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. c.batchLeaf = make([]*yparser.YParserLeafValue, 0) //Every Redis table is mapped as list within a container, - //E.g. ACL_RULE is mapped as + //E.g. ACL_RULE is mapped as // container ACL_RULE { list ACL_RULE_LIST {} } var topNode *yparser.YParserNode @@ -191,25 +188,25 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. if _, exists := modelInfo.tableInfo[tableName]; !exists { CVL_LOG(WARNING, "Schema details not found for %s", tableName) cvlErrObj.ErrCode = CVL_SYNTAX_ERROR - cvlErrObj.TableName = tableName - cvlErrObj.Msg ="Schema details not found" + cvlErrObj.TableName = tableName + cvlErrObj.Msg = "Schema details not found" return nil, cvlErrObj } topNode = c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, - nil, modelInfo.tableInfo[tableName].modelName) + nil, modelInfo.tableInfo[tableName].modelName) - //Add the container node for each list + //Add the container node for each list //e.g. 'container ACL_TABLE { list ACL_TABLE_LIST ...} listConatinerNode := c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, - topNode, tableName) + topNode, tableName) //Traverse each key instance for jsonNode = jsonNode.FirstChild; jsonNode != nil; jsonNode = jsonNode.NextSibling { - //For each field check if is key + //For each field check if is key //If it is key, create list as child of top container // Get all key name/value pairs - if yangListName := getRedisTblToYangList(tableName, jsonNode.Data); yangListName!= "" { + if yangListName := getRedisTblToYangList(tableName, jsonNode.Data); yangListName != "" { tableName = yangListName } keyValuePair := getRedisToYangKeys(tableName, jsonNode.Data) @@ -225,20 +222,20 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. keyIndices = append(keyIndices, 0) } - for ; totalKeyComb > 0 ; totalKeyComb-- { + for ; totalKeyComb > 0; totalKeyComb-- { //Get the YANG list name from Redis table name //Ideally they are same except when one Redis table is split //into multiple YANG lists //Add table i.e. create list element - listNode := c.addChildNode(tableName, listConatinerNode, tableName + "_LIST") //Add the list to the top node + listNode := c.addChildNode(tableName, listConatinerNode, tableName+"_LIST") //Add the list to the top node //For each key combination //Add keys as leaf to the list for idx = 0; idx < keyCompCount; idx++ { c.addChildLeaf(config, tableName, - listNode, keyValuePair[idx].key, - keyValuePair[idx].values[keyIndices[idx]], &c.batchLeaf) + listNode, keyValuePair[idx].key, + keyValuePair[idx].values[keyIndices[idx]], &c.batchLeaf) } //Get all fields under the key field and add them as children of the list @@ -248,18 +245,18 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. //Check which key elements left after current key element var next int = keyCompCount - 1 - for ((next > 0) && ((keyIndices[next] +1) >= len(keyValuePair[next].values))) { + for (next > 0) && ((keyIndices[next] + 1) >= len(keyValuePair[next].values)) { next-- } //No more combination possible - if (next < 0) { + if next < 0 { break } keyIndices[next]++ //Reset indices for all other key elements - for idx = next+1; idx < keyCompCount; idx++ { + for idx = next + 1; idx < keyCompCount; idx++ { keyIndices[idx] = 0 } @@ -278,4 +275,3 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. return topNode, cvlErrObj } - diff --git a/cvl/cvl_test.go b/cvl/cvl_test.go index c446bdf74..4659d8685 100644 --- a/cvl/cvl_test.go +++ b/cvl/cvl_test.go @@ -60,48 +60,48 @@ var rclient *redis.Client var port_map map[string]interface{} var loadDeviceDataMap bool -var deviceDataMap = map[string]interface{} { - "DEVICE_METADATA" : map[string]interface{} { - "localhost": map[string] interface{} { - "hwsku": "Quanta-IX8-54x", - "hostname": "sonic", - "platform": "x86_64-quanta_ix8_54x-r0", - "mac": "4c:76:25:f4:70:82", +var deviceDataMap = map[string]interface{}{ + "DEVICE_METADATA": map[string]interface{}{ + "localhost": map[string]interface{}{ + "hwsku": "Quanta-IX8-54x", + "hostname": "sonic", + "platform": "x86_64-quanta_ix8_54x-r0", + "mac": "4c:76:25:f4:70:82", "deployment_id": "1", }, }, } /* Dependent port channel configuration. */ -var depDataMap = map[string]interface{} { - "PORTCHANNEL" : map[string]interface{} { - "PortChannel001": map[string] interface{} { +var depDataMap = map[string]interface{}{ + "PORTCHANNEL": map[string]interface{}{ + "PortChannel001": map[string]interface{}{ "admin_status": "up", - "mtu": "9100", + "mtu": "9100", }, - "PortChannel002": map[string] interface{} { + "PortChannel002": map[string]interface{}{ "admin_status": "up", - "mtu": "9100", + "mtu": "9100", }, "PortChannel003": map[string]interface{}{ "admin_status": "up", "mtu": "9100", }, }, - "PORTCHANNEL_MEMBER": map[string]interface{} { - "PortChannel001|Ethernet4": map[string] interface{} { + "PORTCHANNEL_MEMBER": map[string]interface{}{ + "PortChannel001|Ethernet4": map[string]interface{}{ "NULL": "NULL", }, - "PortChannel001|Ethernet8": map[string] interface{} { + "PortChannel001|Ethernet8": map[string]interface{}{ "NULL": "NULL", }, - "PortChannel001|Ethernet12": map[string] interface{} { + "PortChannel001|Ethernet12": map[string]interface{}{ "NULL": "NULL", }, - "PortChannel002|Ethernet20": map[string] interface{} { + "PortChannel002|Ethernet20": map[string]interface{}{ "NULL": "NULL", }, - "PortChannel002|Ethernet24": map[string] interface{} { + "PortChannel002|Ethernet24": map[string]interface{}{ "NULL": "NULL", }, }, @@ -238,7 +238,7 @@ func prepareDb() { } //Load device data map on which application of deviation files depends - dm, err:= rclient.Keys("DEVICE_METADATA|localhost").Result() + dm, err := rclient.Keys("DEVICE_METADATA|localhost").Result() if (err != nil) || (len(dm) == 0) { loadConfigDB(rclient, deviceDataMap) loadDeviceDataMap = true @@ -246,13 +246,13 @@ func prepareDb() { port_map = loadConfig("", PortsMapByte) - portKeys, err:= rclient.Keys("PORT|*").Result() + portKeys, err := rclient.Keys("PORT|*").Result() //Load only the port config which are not there in Redis if err == nil { portMapKeys := port_map["PORT"].(map[string]interface{}) for _, portKey := range portKeys { //Delete the port key which is already there in Redis - delete(portMapKeys, portKey[len("PORTS|") - 1:]) + delete(portMapKeys, portKey[len("PORTS|")-1:]) } port_map["PORT"] = portMapKeys } @@ -261,16 +261,16 @@ func prepareDb() { loadConfigDB(rclient, depDataMap) } -//Clear all db entries which are used in the test cases. -//The list of such db should be updated here if new -//table is referred in any test case. -//The test case running may fail if tables are not cleared -//prior to starting execution of test cases. -//"DEVICE_METADATA" should not be cleaned as it is used -//during cvl package init() phase. +// Clear all db entries which are used in the test cases. +// The list of such db should be updated here if new +// table is referred in any test case. +// The test case running may fail if tables are not cleared +// prior to starting execution of test cases. +// "DEVICE_METADATA" should not be cleaned as it is used +// during cvl package init() phase. func clearDb() { - tblList := []string { + tblList := []string{ "ACL_RULE", "ACL_TABLE", "BGP_GLOBALS", @@ -301,8 +301,8 @@ func clearDb() { for _, tbl := range tblList { _, err := exec.Command("/bin/sh", "-c", - "sonic-db-cli CONFIG_DB del `sonic-db-cli CONFIG_DB keys '" + - tbl + "|*' | cut -d ' ' -f 2`").Output() + "sonic-db-cli CONFIG_DB del `sonic-db-cli CONFIG_DB keys '"+ + tbl+"|*' | cut -d ' ' -f 2`").Output() if err != nil { fmt.Println(err.Error()) @@ -315,11 +315,11 @@ func TestMain(m *testing.M) { redisAlreadyRunning := false pidOfRedis, err := exec.Command("pidof", "redis-server").Output() - if err == nil && string(pidOfRedis) != "\n" { + if err == nil && string(pidOfRedis) != "\n" { redisAlreadyRunning = true } - if (redisAlreadyRunning == false) { + if redisAlreadyRunning == false { //Redis not running, lets start it _, err := exec.Command("/bin/sh", "-c", "sudo /etc/init.d/redis-server start").Output() if err != nil { @@ -340,7 +340,7 @@ func TestMain(m *testing.M) { unloadConfigDB(rclient, port_map) unloadConfigDB(rclient, depDataMap) - if (loadDeviceDataMap == true) { + if loadDeviceDataMap == true { unloadConfigDB(rclient, deviceDataMap) } @@ -351,7 +351,7 @@ func TestMain(m *testing.M) { rclient.Close() rclient.FlushDB() - if (redisAlreadyRunning == false) { + if redisAlreadyRunning == false { //If Redis was not already running, close the instance that we ran _, err := exec.Command("/bin/sh", "-c", "sudo /etc/init.d/redis-server stop").Output() if err != nil { @@ -363,23 +363,23 @@ func TestMain(m *testing.M) { os.Exit(code) } -//Test Initialize() API +// Test Initialize() API func TestInitialize(t *testing.T) { ret := cvl.Initialize() - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { t.Errorf("CVl initialization failed") } ret = cvl.Initialize() - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { t.Errorf("CVl re-initialization should not fail") } } -//Test Initialize() API +// Test Initialize() API func TestFinish(t *testing.T) { ret := cvl.Initialize() - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { t.Errorf("CVl initialization failed") } @@ -391,12 +391,12 @@ func TestFinish(t *testing.T) { func NewTestSession(t *testing.T) *cvl.CVL { t.Helper() - c, status := cvl.ValidationSessOpen() + c, status := cvl.ValidationSessOpen() if status != CVL_SUCCESS { t.Fatalf("ValidationSessOpen failed; err=%v", status) } - t.Cleanup(func() { cvl.ValidationSessClose(c) }) - return c + t.Cleanup(func() { cvl.ValidationSessClose(c) }) + return c } /* ValidateEditConfig with user input in file . */ @@ -425,7 +425,6 @@ func TestValidateEditConfig_CfgFile(t *testing.T) { cvl.CVLEditConfigData{cvl.VALIDATE_ALL, cvl.OP_CREATE, "ACL_TABLE|TestACL1", jsonEditCfg_Create_DependentMap}, } - cvlErrObj, err := cvSess.ValidateEditConfig(cfgData) if err != tc.retCode { @@ -436,7 +435,6 @@ func TestValidateEditConfig_CfgFile(t *testing.T) { cvl.CVLEditConfigData{cvl.VALIDATE_ALL, cvl.OP_CREATE, "ACL_RULE|TestACL1|Rule1", jsonEditCfg_Create_ConfigMap}, } - cvlErrObj, err = cvSess.ValidateEditConfig(cfgData) if err != tc.retCode { @@ -478,7 +476,6 @@ func TestValidateEditConfig_CfgStrBuffer(t *testing.T) { cvl.CVLEditConfigData{cvl.VALIDATE_ALL, cvl.OP_CREATE, "ACL_TABLE|TestACL1", jsonEditCfg_Create_DependentMap}, } - cvlErrObj, err := cvSess.ValidateEditConfig(cfgData) if err != tc.retCode { @@ -489,7 +486,6 @@ func TestValidateEditConfig_CfgStrBuffer(t *testing.T) { cvl.CVLEditConfigData{cvl.VALIDATE_ALL, cvl.OP_CREATE, "ACL_RULE|TestACL1|Rule1", jsonEditCfg_Create_ConfigMap}, } - cvlErrObj, err = cvSess.ValidateEditConfig(cfgData) if err != tc.retCode { @@ -500,6 +496,7 @@ func TestValidateEditConfig_CfgStrBuffer(t *testing.T) { cvl.ValidationSessClose(cvSess) } + /* API when config is given as string buffer. */ func TestValidateConfig_CfgStrBuffer(t *testing.T) { type testStruct struct { @@ -511,7 +508,7 @@ func TestValidateConfig_CfgStrBuffer(t *testing.T) { tests := []testStruct{} for index, _ := range json_validate_config_data { - // Fetch the modelName. + // Fetch the modelName. result := strings.Split(json_validate_config_data[index], "{") modelName := strings.Trim(strings.Replace(strings.TrimSpace(result[1]), "\"", "", -1), ":") @@ -525,7 +522,6 @@ func TestValidateConfig_CfgStrBuffer(t *testing.T) { t.Run(fmt.Sprintf("%s [%d]", tc.filedescription, index+1), func(t *testing.T) { err := cvSess.ValidateConfig(tc.jsonString) - if err != tc.retCode { t.Errorf("Config Validation failed.") } @@ -533,11 +529,10 @@ func TestValidateConfig_CfgStrBuffer(t *testing.T) { }) } - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) } - /* API when config is given as json file. */ func TestValidateConfig_CfgFile(t *testing.T) { @@ -559,7 +554,6 @@ func TestValidateConfig_CfgFile(t *testing.T) { jsonString := convertJsonFileToString(t, tc.fileName) err := cvSess.ValidateConfig(jsonString) - if err != tc.retCode { t.Errorf("Config Validation failed.") } @@ -567,10 +561,10 @@ func TestValidateConfig_CfgFile(t *testing.T) { }) } - cvl.ValidationSessClose(cvSess) + cvl.ValidationSessClose(cvSess) } -//Validate invalid json data +// Validate invalid json data func TestValidateConfig_Negative(t *testing.T) { cvSess, _ := cvl.ValidationSessOpen() jsonData := `{ @@ -648,10 +642,10 @@ func TestValidateEditConfig_Delete_Semantic_ACLTableReference_Positive(t *testin func TestValidateEditConfig_Create_Syntax_Valid_FieldValue(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -688,14 +682,14 @@ func TestValidateEditConfig_Create_Syntax_CableLength(t *testing.T) { cvl.OP_CREATE, "CABLE_LENGTH|AZURE", map[string]string{ - "Ethernet8": "5m", - "Ethernet12": "5m", - "PortChannel16": "5m", + "Ethernet8": "5m", + "Ethernet12": "5m", + "PortChannel16": "5m", }, }, - } + } - verifyValidateEditConfig(t, cfgData, CVLErrorInfo{ + verifyValidateEditConfig(t, cfgData, CVLErrorInfo{ ErrCode: CVL_SYNTAX_ERROR, TableName: "CABLE_LENGTH", Keys: []string{"AZURE"}, @@ -731,10 +725,10 @@ func TestValidateEditConfig_Create_Syntax_Invalid_FieldValue(t *testing.T) { /* API to test edit config with valid syntax. */ func TestValidateEditConfig_Create_Syntax_Invalid_PacketAction_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -749,9 +743,9 @@ func TestValidateEditConfig_Create_Syntax_Invalid_PacketAction_Negative(t *testi "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD777", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", + "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", "DST_IP": "20.2.2.2/32", "L4_DST_PORT_RANGE": "9000-12000", @@ -772,10 +766,10 @@ func TestValidateEditConfig_Create_Syntax_Invalid_PacketAction_Negative(t *testi /* API to test edit config with valid syntax. */ func TestValidateEditConfig_Create_Syntax_Invalid_SrcPrefix_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -790,7 +784,7 @@ func TestValidateEditConfig_Create_Syntax_Invalid_SrcPrefix_Negative(t *testing. "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/3288888", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -814,10 +808,10 @@ func TestValidateEditConfig_Create_Syntax_Invalid_SrcPrefix_Negative(t *testing. func TestValidateEditConfig_Create_Syntax_InvalidIPAddress_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -832,7 +826,7 @@ func TestValidateEditConfig_Create_Syntax_InvalidIPAddress_Negative(t *testing.T "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1a.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -855,10 +849,10 @@ func TestValidateEditConfig_Create_Syntax_InvalidIPAddress_Negative(t *testing.T /* API to test edit config with valid syntax. */ func TestValidateEditConfig_Create_Syntax_OutofBound_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -873,7 +867,7 @@ func TestValidateEditConfig_Create_Syntax_OutofBound_Negative(t *testing.T) { "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "19099090909090", "IP_PROTOCOL": "103", @@ -896,10 +890,10 @@ func TestValidateEditConfig_Create_Syntax_OutofBound_Negative(t *testing.T) { /* API to test edit config with valid syntax. */ func TestValidateEditConfig_Create_Syntax_InvalidProtocol_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -914,7 +908,7 @@ func TestValidateEditConfig_Create_Syntax_InvalidProtocol_Negative(t *testing.T) "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "10388888", @@ -939,10 +933,10 @@ func TestValidateEditConfig_Create_Syntax_InvalidProtocol_Negative(t *testing.T) //hence ACL_TABLE is not required here func TestValidateEditConfig_Create_Syntax_InvalidRange_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -957,7 +951,7 @@ func TestValidateEditConfig_Create_Syntax_InvalidRange_Negative(t *testing.T) { "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -980,7 +974,6 @@ func TestValidateEditConfig_Create_Syntax_InvalidRange_Negative(t *testing.T) { /* API to test edit config with valid syntax. */ func TestValidateEditConfig_Create_Syntax_InvalidCharNEw_Negative(t *testing.T) { - cfgData := []cvl.CVLEditConfigData{ cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, @@ -988,7 +981,7 @@ func TestValidateEditConfig_Create_Syntax_InvalidCharNEw_Negative(t *testing.T) "ACL_RULE|TestACL1jjjj|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1011,10 +1004,10 @@ func TestValidateEditConfig_Create_Syntax_InvalidCharNEw_Negative(t *testing.T) func TestValidateEditConfig_Create_Syntax_SpecialChar_Positive(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -1029,7 +1022,7 @@ func TestValidateEditConfig_Create_Syntax_SpecialChar_Positive(t *testing.T) { "ACL_RULE|TestACL1|Rule@##", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1051,7 +1044,7 @@ func TestValidateEditConfig_Create_Syntax_InvalidKeyName_Negative(t *testing.T) "AC&&***L_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1069,10 +1062,10 @@ func TestValidateEditConfig_Create_Syntax_InvalidKeyName_Negative(t *testing.T) func TestValidateEditConfig_Create_Semantic_AdditionalInvalidNode_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL1": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -1086,7 +1079,7 @@ func TestValidateEditConfig_Create_Semantic_AdditionalInvalidNode_Negative(t *te "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1137,7 +1130,7 @@ func TestValidateEditConfig_Create_Syntax_Invalid_Negative(t *testing.T) { "ACL_RULERule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1162,7 +1155,7 @@ func TestValidateEditConfig_Create_Syntax_IncompleteKey_Negative(t *testing.T) { "ACL_RULE|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1189,7 +1182,7 @@ func TestValidateEditConfig_Create_Syntax_InvalidKey_Negative(t *testing.T) { "|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1328,7 +1321,7 @@ func TestValidateEditConfig_Delete_Syntax_InvalidKey_Negative(t *testing.T) { "|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1353,7 +1346,7 @@ func TestValidateEditConfig_Update_Syntax_InvalidKey_Negative(t *testing.T) { "|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1399,7 +1392,7 @@ func TestValidateEditConfig_Update_Semantic_Invalid_Key_Negative(t *testing.T) { "ACL_RULE|TestACL1Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103uuuu", @@ -1482,10 +1475,10 @@ func TestValidateEditConfig_Update_Semantic_MissingKey_Negative(t *testing.T) { func TestValidateEditConfig_Create_Duplicate_Key_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "ACL_TABLE": map[string]interface{} { - "TestACL100": map[string]interface{} { + "ACL_TABLE": map[string]interface{}{ + "TestACL100": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -1638,7 +1631,7 @@ func TestValidateEditConfig_Update_Syntax_DependentData_Invalid_Op_Seq(t *testin "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1713,7 +1706,7 @@ func TestValidateEditConfig_Create_Syntax_DependentData_Redis_Positive(t *testin "ACL_RULE|TestACL22|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1774,7 +1767,7 @@ func TestValidateEditConfig_Create_Dependent_CacheData(t *testing.T) { "ACL_RULE|TestACL14|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1817,7 +1810,7 @@ func TestValidateEditConfig_Create_DepData_In_MultiSess(t *testing.T) { "ACL_RULE|TestACL16|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1829,7 +1822,6 @@ func TestValidateEditConfig_Create_DepData_In_MultiSess(t *testing.T) { _, err2 := cvSess.ValidateEditConfig(cfgDataRule) - cvl.ValidationSessClose(cvSess) if err1 != cvl.CVL_SUCCESS || err2 == cvl.CVL_SUCCESS { @@ -1859,7 +1851,7 @@ func TestValidateEditConfig_Create_DepData_From_Redis_Negative11(t *testing.T) { "ACL_RULE|TestACL188|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1878,7 +1870,6 @@ func TestValidateEditConfig_Create_DepData_From_Redis_Negative11(t *testing.T) { }) } - func TestValidateEditConfig_Create_DepData_From_Redis(t *testing.T) { depDataMap := map[string]interface{}{ @@ -1900,7 +1891,7 @@ func TestValidateEditConfig_Create_DepData_From_Redis(t *testing.T) { "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", + "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -1921,7 +1912,7 @@ func TestValidateEditConfig_Create_Syntax_ErrAppTag_In_Range_Negative(t *testing cvl.OP_CREATE, "VLAN|Vlan701", map[string]string{ - "vlanid": "7001", + "vlanid": "7001", }, }, } @@ -1946,8 +1937,8 @@ func TestValidateEditConfig_Create_Syntax_ErrAppTag_In_Length_Negative(t *testin cvl.OP_CREATE, "ACL_TABLE|TestACL1", map[string]string{ - "stage": "INGRESS", - "type": "MIRROR", + "stage": "INGRESS", + "type": "MIRROR", "policy_desc": longText, }, }, @@ -1972,7 +1963,7 @@ func TestValidateEditConfig_Create_Syntax_ErrAppTag_In_Pattern_Negative(t *testi cvl.OP_CREATE, "VLAN|Vlan5001", map[string]string{ - "vlanid": "102", + "vlanid": "102", }, }, } @@ -1988,23 +1979,23 @@ func TestValidateEditConfig_Create_Syntax_ErrAppTag_In_Pattern_Negative(t *testi }) } -//EditConfig(Delete) deleting entry already used by other table as leafref +// EditConfig(Delete) deleting entry already used by other table as leafref func TestValidateEditConfig_Delete_Dep_Leafref_Negative(t *testing.T) { - depDataMap := map[string]interface{} { - "ACL_TABLE" : map[string]interface{} { - "TestACL1": map[string] interface{} { + depDataMap := map[string]interface{}{ + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, - "ACL_RULE": map[string]interface{} { - "TestACL1|Rule1": map[string] interface{} { - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", + "ACL_RULE": map[string]interface{}{ + "TestACL1|Rule1": map[string]interface{}{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", "L4_DST_PORT_RANGE": "9000-12000", }, }, @@ -2014,13 +2005,12 @@ func TestValidateEditConfig_Delete_Dep_Leafref_Negative(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgDataVlan := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "ACL_TABLE|TestACL1", - map[string]string { - }, + map[string]string{}, }, } @@ -2098,42 +2088,42 @@ func TestValidateEditConfig_Create_Syntax_RangeValidation(t *testing.T) { }) } -//Test Initialize() API +// Test Initialize() API func TestLogging(t *testing.T) { - ret := cvl.Initialize() - str := "Testing" - cvl.CVL_LOG(INFO ,"This is Info Log %s", str) - cvl.CVL_LOG(WARNING,"This is Warning Log %s", str) - cvl.CVL_LOG(ERROR ,"This is Error Log %s", str) - cvl.CVL_LOG(INFO_API ,"This is Info API %s", str) - cvl.CVL_LOG(INFO_TRACE ,"This is Info Trace %s", str) - cvl.CVL_LOG(INFO_DEBUG ,"This is Info Debug %s", str) - cvl.CVL_LOG(INFO_DATA ,"This is Info Data %s", str) - cvl.CVL_LOG(INFO_DETAIL ,"This is Info Detail %s", str) - cvl.CVL_LOG(INFO_ALL ,"This is Info all %s", str) - - if (ret != cvl.CVL_SUCCESS) { - t.Errorf("CVl initialization failed") - } - - cvl.Finish() + ret := cvl.Initialize() + str := "Testing" + cvl.CVL_LOG(INFO, "This is Info Log %s", str) + cvl.CVL_LOG(WARNING, "This is Warning Log %s", str) + cvl.CVL_LOG(ERROR, "This is Error Log %s", str) + cvl.CVL_LOG(INFO_API, "This is Info API %s", str) + cvl.CVL_LOG(INFO_TRACE, "This is Info Trace %s", str) + cvl.CVL_LOG(INFO_DEBUG, "This is Info Debug %s", str) + cvl.CVL_LOG(INFO_DATA, "This is Info Data %s", str) + cvl.CVL_LOG(INFO_DETAIL, "This is Info Detail %s", str) + cvl.CVL_LOG(INFO_ALL, "This is Info all %s", str) + + if ret != cvl.CVL_SUCCESS { + t.Errorf("CVl initialization failed") + } + + cvl.Finish() //Initialize again for other test cases to run cvl.Initialize() } func TestValidateEditConfig_DepData_Through_Cache(t *testing.T) { - depDataMap := map[string]interface{} { - "PORT" : map[string]interface{} { - "Ethernet3" : map[string]interface{} { - "alias":"hundredGigE1", + depDataMap := map[string]interface{}{ + "PORT": map[string]interface{}{ + "Ethernet3": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "81,82,83,84", - "mtu": "9100", + "mtu": "9100", }, - "Ethernet5" : map[string]interface{} { - "alias":"hundredGigE1", + "Ethernet5": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "85,86,87,89", - "mtu": "9100", + "mtu": "9100", }, }, } @@ -2143,9 +2133,9 @@ func TestValidateEditConfig_DepData_Through_Cache(t *testing.T) { defer unloadConfigDB(rclient, depDataMap) //Modify entry - modDepDataMap := map[string]interface{} { - "PORT" : map[string]interface{} { - "Ethernet3" : map[string]interface{} { + modDepDataMap := map[string]interface{}{ + "PORT": map[string]interface{}{ + "Ethernet3": map[string]interface{}{ "mtu": "9200", }, }, @@ -2154,15 +2144,15 @@ func TestValidateEditConfig_DepData_Through_Cache(t *testing.T) { loadConfigDB(rclient, modDepDataMap) defer unloadConfigDB(rclient, modDepDataMap) - cfgDataAclRule := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAclRule := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "ACL_TABLE|TestACL1", - map[string]string { - "stage": "INGRESS", - "type": "L3", - "ports@":"Ethernet3,Ethernet5", + map[string]string{ + "stage": "INGRESS", + "type": "L3", + "ports@": "Ethernet3,Ethernet5", }, }, } @@ -2173,12 +2163,12 @@ func TestValidateEditConfig_DepData_Through_Cache(t *testing.T) { /* Delete field for an existing key.*/ func TestValidateEditConfig_Delete_Single_Field_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "ACL_TABLE" : map[string]interface{} { - "TestACL1": map[string] interface{} { - "stage": "INGRESS", - "type": "L3", - "policy_desc":"Test ACL desc", + depDataMap := map[string]interface{}{ + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ + "stage": "INGRESS", + "type": "L3", + "policy_desc": "Test ACL desc", }, }, } @@ -2193,7 +2183,7 @@ func TestValidateEditConfig_Delete_Single_Field_Positive(t *testing.T) { cvl.OP_DELETE, "ACL_TABLE|TestACL1", map[string]string{ - "policy_desc":"Test ACL desc", + "policy_desc": "Test ACL desc", }, }, } @@ -2202,12 +2192,12 @@ func TestValidateEditConfig_Delete_Single_Field_Positive(t *testing.T) { } func TestValidateEditConfig_Create_Dscp_To_Tc_Map(t *testing.T) { - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "DSCP_TO_TC_MAP|AZURE", - map[string]string { + map[string]string{ "1": "7", "2": "8", "3": "9", @@ -2273,14 +2263,14 @@ func TestValidateConfig_Repeated_Keys_Positive(t *testing.T) { } func TestValidateEditConfig_Delete_Entry_Then_Dep_Leafref_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan20": map[string] interface{} { + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan20": map[string]interface{}{ "vlanid": "20", }, }, - "VLAN_MEMBER": map[string]interface{} { - "Vlan20|Ethernet4": map[string] interface{} { + "VLAN_MEMBER": map[string]interface{}{ + "Vlan20|Ethernet4": map[string]interface{}{ "tagging_mode": "tagged", }, }, @@ -2292,33 +2282,30 @@ func TestValidateEditConfig_Delete_Entry_Then_Dep_Leafref_Positive(t *testing.T) cvSess := NewTestSession(t) - cfgDataAcl := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAcl := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "VLAN_MEMBER|Vlan20|Ethernet4", - map[string]string { - }, + map[string]string{}, }, } cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgDataAcl) verifyErr(t, cvlErrInfo, Success) - cfgDataAcl = []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAcl = []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_DELETE, "VLAN_MEMBER|Vlan20|Ethernet4", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "VLAN|Vlan20", - map[string]string { - }, + map[string]string{}, }, } @@ -2332,8 +2319,8 @@ func TestBadSchema(t *testing.T) { env[0] = env[0] + " " if _, err := os.Stat("/usr/sbin/schema"); os.IsNotExist(err) { - //Corrupt some schema file - exec.Command("/bin/sh", "-c", "/bin/cp testdata/schema/sonic-port.yin testdata/schema/sonic-port.yin.bad" + + //Corrupt some schema file + exec.Command("/bin/sh", "-c", "/bin/cp testdata/schema/sonic-port.yin testdata/schema/sonic-port.yin.bad" + " && /bin/sed -i '1 a ' testdata/schema/sonic-port.yin.bad").Output() //Parse bad schema file @@ -2341,11 +2328,11 @@ func TestBadSchema(t *testing.T) { t.Errorf("Bad schema parsing should fail.") } - //Revert to + //Revert to exec.Command("/bin/sh", "-c", "/bin/rm testdata/schema/sonic-port.yin.bad").Output() } else { - //Corrupt some schema file - exec.Command("/bin/sh", "-c", "/bin/cp /usr/sbin/schema/sonic-port.yin /usr/sbin/schema/sonic-port.yin.bad" + + //Corrupt some schema file + exec.Command("/bin/sh", "-c", "/bin/cp /usr/sbin/schema/sonic-port.yin /usr/sbin/schema/sonic-port.yin.bad" + " && /bin/sed -i '1 a ' /usr/sbin/schema/sonic-port.yin.bad").Output() //Parse bad schema file @@ -2353,7 +2340,7 @@ func TestBadSchema(t *testing.T) { t.Errorf("Bad schema parsing should fail.") } - //Revert to + //Revert to exec.Command("/bin/sh", "-c", "/bin/rm /usr/sbin/schema/sonic-port.yin.bad").Output() } @@ -2414,7 +2401,7 @@ func TestServicability_Debug_Trace(t *testing.T) { cvl.ValidationSessClose(cvSess) //Reload the bad config file by sending SIGUSR2 to ourself - exec.Command("/bin/sh", "-c", "/bin/cp conf/cvl_cfg.json conf/cvl_cfg.json.orig" + + exec.Command("/bin/sh", "-c", "/bin/cp conf/cvl_cfg.json conf/cvl_cfg.json.orig" + " && /bin/echo 'junk' >> conf/cvl_cfg.json").Output() p, err = os.FindProcess(os.Getpid()) if (err == nil) { @@ -2426,18 +2413,18 @@ func TestServicability_Debug_Trace(t *testing.T) { // EditConfig(Create) with chained leafref from redis func TestValidateEditConfig_Delete_Create_Same_Entry_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan100": map[string]interface{} { + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan100": map[string]interface{}{ "members@": "Ethernet1", - "vlanid": "100", + "vlanid": "100", }, }, - "PORT" : map[string]interface{} { - "Ethernet1" : map[string]interface{} { - "alias":"hundredGigE1", + "PORT": map[string]interface{}{ + "Ethernet1": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "81,82,83,84", - "mtu": "9100", + "mtu": "9100", }, }, } @@ -2448,13 +2435,12 @@ func TestValidateEditConfig_Delete_Create_Same_Entry_Positive(t *testing.T) { cvSess := NewTestSession(t) - cfgDataVlan := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "VLAN|Vlan100", - map[string]string { - }, + map[string]string{}, }, } @@ -2462,12 +2448,12 @@ func TestValidateEditConfig_Delete_Create_Same_Entry_Positive(t *testing.T) { verifyErr(t, res, Success) //Same entry getting created again - cfgDataVlan = []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan = []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "VLAN|Vlan100", - map[string]string { + map[string]string{ "vlanid": "100", }, }, @@ -2486,32 +2472,32 @@ func TestValidateStartupConfig_Positive(t *testing.T) { } func TestValidateIncrementalConfig_Positive(t *testing.T) { - existingDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan800": map[string]interface{} { + existingDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan800": map[string]interface{}{ "members@": "Ethernet1", - "vlanid": "800", + "vlanid": "800", }, - "Vlan801": map[string]interface{} { + "Vlan801": map[string]interface{}{ "members@": "Ethernet2", - "vlanid": "801", + "vlanid": "801", }, }, - "VLAN_MEMBER": map[string]interface{} { - "Vlan800|Ethernet1": map[string] interface{} { + "VLAN_MEMBER": map[string]interface{}{ + "Vlan800|Ethernet1": map[string]interface{}{ "tagging_mode": "tagged", }, }, - "PORT" : map[string]interface{} { - "Ethernet1" : map[string]interface{} { - "alias":"hundredGigE1", + "PORT": map[string]interface{}{ + "Ethernet1": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "81,82,83,84", - "mtu": "9100", + "mtu": "9100", }, - "Ethernet2" : map[string]interface{} { - "alias":"hundredGigE1", + "Ethernet2": map[string]interface{}{ + "alias": "hundredGigE1", "lanes": "85,86,87,89", - "mtu": "9100", + "mtu": "9100", }, }, } @@ -2553,7 +2539,7 @@ func TestValidateIncrementalConfig_Positive(t *testing.T) { } } -//Validate key only +// Validate key only func TestValidateKeys(t *testing.T) { cvSess, _ := cvl.ValidationSessOpen() if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateKeys([]string{}) { @@ -2562,7 +2548,7 @@ func TestValidateKeys(t *testing.T) { cvl.ValidationSessClose(cvSess) } -//Validate key and data +// Validate key and data func TestValidateKeyData(t *testing.T) { cvSess, _ := cvl.ValidationSessOpen() if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateKeyData("", "") { @@ -2571,7 +2557,7 @@ func TestValidateKeyData(t *testing.T) { cvl.ValidationSessClose(cvSess) } -//Validate key, field and value +// Validate key, field and value func TestValidateFields(t *testing.T) { cvSess, _ := cvl.ValidationSessOpen() if cvl.CVL_NOT_IMPLEMENTED != cvSess.ValidateFields("", "", "") { @@ -2581,11 +2567,11 @@ func TestValidateFields(t *testing.T) { } func TestValidateEditConfig_Two_Updates_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "ACL_TABLE" : map[string]interface{} { - "TestACL1": map[string] interface{} { + depDataMap := map[string]interface{}{ + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, } @@ -2594,20 +2580,20 @@ func TestValidateEditConfig_Two_Updates_Positive(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgDataAcl := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAcl := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_UPDATE, "ACL_TABLE|TestACL1", - map[string]string { + map[string]string{ "policy_desc": "Test ACL", }, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_UPDATE, "ACL_TABLE|TestACL1", - map[string]string { + map[string]string{ "type": "MIRROR", }, }, @@ -2633,7 +2619,6 @@ func TestValidateEditConfig_Create_Syntax_DependentData_PositivePortChannel(t *t verifyValidateEditConfig(t, cfgData, Success) } - func TestValidateEditConfig_Create_Syntax_DependentData_PositivePortChannelIfName(t *testing.T) { cfgData := []cvl.CVLEditConfigData{ @@ -2701,11 +2686,11 @@ func TestValidateEditConfig_Create_Syntax_DependentData_NegativePortChannelNew(t } func TestValidateEditConfig_Use_Updated_Data_As_Create_DependentData_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan201": map[string] interface{} { + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan201": map[string]interface{}{ "vlanid": "201", - "mtu": "1700", + "mtu": "1700", "members@": "Ethernet8", }, }, @@ -2723,7 +2708,7 @@ func TestValidateEditConfig_Use_Updated_Data_As_Create_DependentData_Positive(t cvl.OP_UPDATE, "VLAN|Vlan201", map[string]string{ - "mtu": "1900", + "mtu": "1900", "members@": "Ethernet8,Ethernet12", }, }, @@ -2748,11 +2733,11 @@ func TestValidateEditConfig_Use_Updated_Data_As_Create_DependentData_Positive(t } func TestValidateEditConfig_Use_Updated_Data_As_Create_DependentData_Single_Call_Positive(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN" : map[string]interface{} { - "Vlan201": map[string] interface{} { + depDataMap := map[string]interface{}{ + "VLAN": map[string]interface{}{ + "Vlan201": map[string]interface{}{ "vlanid": "201", - "mtu": "1700", + "mtu": "1700", "members@": "Ethernet8", }, }, @@ -2768,7 +2753,7 @@ func TestValidateEditConfig_Use_Updated_Data_As_Create_DependentData_Single_Call cvl.OP_UPDATE, "VLAN|Vlan201", map[string]string{ - "mtu": "1900", + "mtu": "1900", "members@": "Ethernet8,Ethernet12", }, }, @@ -2792,8 +2777,7 @@ func TestValidateEditConfig_Create_Syntax_Interface_AllKeys_Positive(t *testing. cvl.VALIDATE_ALL, cvl.OP_CREATE, "INTERFACE|Ethernet24|10.0.0.0/31", - map[string]string{ - }, + map[string]string{}, }, } @@ -2807,8 +2791,7 @@ func TestValidateEditConfig_Create_Syntax_Interface_OptionalKey_Positive(t *test cvl.VALIDATE_ALL, cvl.OP_CREATE, "INTERFACE|Ethernet24", - map[string]string{ - }, + map[string]string{}, }, } @@ -2822,8 +2805,7 @@ func TestValidateEditConfig_Create_Syntax_Interface_IncorrectKey_Negative(t *tes cvl.VALIDATE_ALL, cvl.OP_CREATE, "INTERFACE|10.0.0.0/31", - map[string]string{ - }, + map[string]string{}, }, } @@ -2839,19 +2821,19 @@ func TestValidateEditConfig_Create_Syntax_Interface_IncorrectKey_Negative(t *tes } func TestValidateEditConfig_EmptyNode_Positive(t *testing.T) { - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_UPDATE, - "PORT|Ethernet0", - map[string]string{ - "description": "", - "index": "3", - }, - }, - } + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_UPDATE, + "PORT|Ethernet0", + map[string]string{ + "description": "", + "index": "3", + }, + }, + } - verifyValidateEditConfig(t, cfgData, Success) + verifyValidateEditConfig(t, cfgData, Success) } func TestSortDepTables(t *testing.T) { @@ -2866,7 +2848,7 @@ func TestSortDepTables(t *testing.T) { return } - for i := 0; i < len(expectedResult) ; i++ { + for i := 0; i < len(expectedResult); i++ { if result[i] != expectedResult[i] { t.Errorf("Validation failed, returned value = %v", result) break @@ -2888,7 +2870,7 @@ func TestGetOrderedTables(t *testing.T) { return } - for i := 0; i < len(expectedResult) ; i++ { + for i := 0; i < len(expectedResult); i++ { if result[i] != expectedResult[i] { t.Errorf("Validation failed, returned value = %v", result) break @@ -2910,7 +2892,7 @@ func TestGetOrderedDepTables(t *testing.T) { return } - for i := 0; i < len(expectedResult) ; i++ { + for i := 0; i < len(expectedResult); i++ { if result[i] != expectedResult[i] { t.Errorf("Validation failed, returned value = %v", result) break @@ -2936,45 +2918,44 @@ func TestGetDepTables(t *testing.T) { cvl.ValidationSessClose(cvSess) } - func TestGetDepDataForDelete(t *testing.T) { - depDataMap := map[string]interface{} { - "VLAN_MEMBER" : map[string]interface{} { - "Vlan21|Ethernet7": map[string] interface{} { - "tagging_mode": "tagged", + depDataMap := map[string]interface{}{ + "VLAN_MEMBER": map[string]interface{}{ + "Vlan21|Ethernet7": map[string]interface{}{ + "tagging_mode": "tagged", }, - "Vlan22|Ethernet7": map[string] interface{} { - "tagging_mode": "tagged", + "Vlan22|Ethernet7": map[string]interface{}{ + "tagging_mode": "tagged", }, - "Vlan22|Ethernet72": map[string] interface{} { - "tagging_mode": "tagged", + "Vlan22|Ethernet72": map[string]interface{}{ + "tagging_mode": "tagged", }, }, - "PORTCHANNEL_MEMBER" : map[string]interface{} { - "Ch47|Ethernet7": map[string] interface{} { + "PORTCHANNEL_MEMBER": map[string]interface{}{ + "Ch47|Ethernet7": map[string]interface{}{ "NULL": "NULL", }, - "Ch47|Ethernet75": map[string] interface{} { + "Ch47|Ethernet75": map[string]interface{}{ "NULL": "NULL", }, }, - "ACL_TABLE" : map[string]interface{} { - "TestACL1": map[string] interface{} { - "stage": "INGRESS", - "type": "L3", + "ACL_TABLE": map[string]interface{}{ + "TestACL1": map[string]interface{}{ + "stage": "INGRESS", + "type": "L3", "ports@": "Ethernet3,Ethernet76,Ethernet7", }, }, - "CFG_L2MC_STATIC_MEMBER_TABLE" : map[string]interface{} { - "Vlan24|10.1.1.1|Ethernet7": map[string] interface{} { + "CFG_L2MC_STATIC_MEMBER_TABLE": map[string]interface{}{ + "Vlan24|10.1.1.1|Ethernet7": map[string]interface{}{ "NULL": "NULL", }, - "Vlan25|10.1.1.2|Ethernet78": map[string] interface{} { + "Vlan25|10.1.1.2|Ethernet78": map[string]interface{}{ "NULL": "NULL", }, }, - "CFG_L2MC_MROUTER_TABLE" : map[string]interface{} { - "Vlan21|Ethernet7": map[string] interface{} { + "CFG_L2MC_MROUTER_TABLE": map[string]interface{}{ + "Vlan21|Ethernet7": map[string]interface{}{ "NULL": "NULL", }, }, @@ -2984,20 +2965,20 @@ func TestGetDepDataForDelete(t *testing.T) { "dst_ip": "2.2.2.2", }, }, - "ACL_RULE" : map[string]interface{} { - "TestACL1|Rule1": map[string] interface{} { + "ACL_RULE": map[string]interface{}{ + "TestACL1|Rule1": map[string]interface{}{ "PACKET_ACTION": "FORWARD", "MIRROR_ACTION": "sess1", }, }, - "INTERFACE" : map[string]interface{} { - "Ethernet7": map[string] interface{} { + "INTERFACE": map[string]interface{}{ + "Ethernet7": map[string]interface{}{ "vrf_name": "Vrf1", }, - "Ethernet7|10.2.1.1/16": map[string] interface{} { + "Ethernet7|10.2.1.1/16": map[string]interface{}{ "NULL": "NULL", }, - "Ethernet7|10.2.1.2/16": map[string] interface{} { + "Ethernet7|10.2.1.2/16": map[string]interface{}{ "NULL": "NULL", }, }, @@ -3005,20 +2986,20 @@ func TestGetDepDataForDelete(t *testing.T) { loadConfigDB(rclient, depDataMap) - cvSess, _ := cvl.ValidationSessOpen() + cvSess, _ := cvl.ValidationSessOpen() depEntries := cvSess.GetDepDataForDelete("PORT|Ethernet7") - if (len(depEntries) != 9) { //9 entries to be deleted - t.Errorf("GetDepDataForDelete() failed") - } + if len(depEntries) != 9 { //9 entries to be deleted + t.Errorf("GetDepDataForDelete() failed") + } depEntries1 := cvSess.GetDepDataForDelete("MIRROR_SESSION|sess1") - if (len(depEntries1) != 1) { //1 entry to be deleted - t.Errorf("GetDepDataForDelete() failed") - } - cvl.ValidationSessClose(cvSess) + if len(depEntries1) != 1 { //1 entry to be deleted + t.Errorf("GetDepDataForDelete() failed") + } + cvl.ValidationSessClose(cvSess) unloadConfigDB(rclient, depDataMap) } @@ -3026,34 +3007,34 @@ func TestGetDepDataForDelete(t *testing.T) { func TestMaxElements_All_Entries_In_Request(t *testing.T) { cvSess := NewTestSession(t) - cfgData := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "VXLAN_TUNNEL|tun1", + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "VXLAN_TUNNEL|tun1", map[string]string{ "src_ip": "20.1.1.1", }, - }, - } + }, + } //Check addition of first element cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgData) verifyErr(t, cvlErrInfo, Success) - cfgData1 := []cvl.CVLEditConfigData{ - cvl.CVLEditConfigData{ - cvl.VALIDATE_ALL, - cvl.OP_CREATE, - "VXLAN_TUNNEL|tun2", + cfgData1 := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ + cvl.VALIDATE_ALL, + cvl.OP_CREATE, + "VXLAN_TUNNEL|tun2", map[string]string{ "src_ip": "30.1.1.1", }, - }, - } + }, + } //Try to validate addition of second element - cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgData1) + cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgData1) verifyErr(t, cvlErrInfo, CVLErrorInfo{ ErrCode: CVL_SYNTAX_ERROR, TableName: "VXLAN_TUNNEL", @@ -3065,9 +3046,9 @@ func TestMaxElements_All_Entries_In_Request(t *testing.T) { } func TestMaxElements_Entries_In_Redis(t *testing.T) { - depDataMap := map[string]interface{} { - "VXLAN_TUNNEL" : map[string]interface{} { - "tun1" : map[string]interface{} { + depDataMap := map[string]interface{}{ + "VXLAN_TUNNEL": map[string]interface{}{ + "tun1": map[string]interface{}{ "src_ip": "20.1.1.1", }, }, @@ -3076,69 +3057,69 @@ func TestMaxElements_Entries_In_Redis(t *testing.T) { loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - t.Run("create_new", func(t *testing.T) { - cfgData := []CVLEditConfigData{{ - VType: VALIDATE_ALL, - VOp: OP_CREATE, - Key: "VXLAN_TUNNEL|tun2", - Data: map[string]string{ - "src_ip": "30.1.1.1", - }, - }} - - verifyValidateEditConfig(t, cfgData, CVLErrorInfo{ - ErrCode: CVL_SYNTAX_ERROR, - TableName: "VXLAN_TUNNEL", - Keys: []string{"tun2"}, - Msg: "Max elements limit reached", - ConstraintErrMsg: "Max elements limit 1 reached", - ErrAppTag: "too-many-elements", - }) - }) - - t.Run("delete_and_create", func(t *testing.T) { - cvSess := NewTestSession(t) - - cfgData1 := []CVLEditConfigData{{ - VType: VALIDATE_ALL, - VOp: OP_DELETE, - Key: "VXLAN_TUNNEL|tun1", - Data: map[string]string{}, - }} - - //Delete the existing entry, should succeed - cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgData1) - verifyErr(t, cvlErrInfo, Success) - - cfgData1 = []CVLEditConfigData{{ - VType: VALIDATE_NONE, - VOp: OP_DELETE, - Key: "VXLAN_TUNNEL|tun1", - Data: map[string]string{}, - }, { - VType: VALIDATE_ALL, - VOp: OP_CREATE, - Key: "VXLAN_TUNNEL|tun2", - Data: map[string]string{ - "src_ip": "30.1.1.1", - }, - }} - - //Check validation of new entry, should succeed now - cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgData1) - verifyErr(t, cvlErrInfo, Success) + t.Run("create_new", func(t *testing.T) { + cfgData := []CVLEditConfigData{{ + VType: VALIDATE_ALL, + VOp: OP_CREATE, + Key: "VXLAN_TUNNEL|tun2", + Data: map[string]string{ + "src_ip": "30.1.1.1", + }, + }} + + verifyValidateEditConfig(t, cfgData, CVLErrorInfo{ + ErrCode: CVL_SYNTAX_ERROR, + TableName: "VXLAN_TUNNEL", + Keys: []string{"tun2"}, + Msg: "Max elements limit reached", + ConstraintErrMsg: "Max elements limit 1 reached", + ErrAppTag: "too-many-elements", + }) + }) + + t.Run("delete_and_create", func(t *testing.T) { + cvSess := NewTestSession(t) + + cfgData1 := []CVLEditConfigData{{ + VType: VALIDATE_ALL, + VOp: OP_DELETE, + Key: "VXLAN_TUNNEL|tun1", + Data: map[string]string{}, + }} + + //Delete the existing entry, should succeed + cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgData1) + verifyErr(t, cvlErrInfo, Success) + + cfgData1 = []CVLEditConfigData{{ + VType: VALIDATE_NONE, + VOp: OP_DELETE, + Key: "VXLAN_TUNNEL|tun1", + Data: map[string]string{}, + }, { + VType: VALIDATE_ALL, + VOp: OP_CREATE, + Key: "VXLAN_TUNNEL|tun2", + Data: map[string]string{ + "src_ip": "30.1.1.1", + }, + }} + + //Check validation of new entry, should succeed now + cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgData1) + verifyErr(t, cvlErrInfo, Success) }) } func TestValidateEditConfig_Two_Create_Requests_Positive(t *testing.T) { cvSess := NewTestSession(t) - cfgDataVlan := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "VLAN|Vlan21", - map[string]string { + map[string]string{ "vlanid": "21", }, }, @@ -3147,26 +3128,26 @@ func TestValidateEditConfig_Two_Create_Requests_Positive(t *testing.T) { cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgDataVlan) verifyErr(t, cvlErrInfo, Success) - cfgDataVlan = []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan = []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_CREATE, "VLAN|Vlan21", - map[string]string { + map[string]string{ "vlanid": "21", }, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "STP_VLAN|Vlan21", - map[string]string { - "enabled": "true", + map[string]string{ + "enabled": "true", "forward_delay": "15", - "hello_time": "2", - "max_age" : "20", - "priority": "327", - "vlanid": "21", + "hello_time": "2", + "max_age": "20", + "priority": "327", + "vlanid": "21", }, }, } @@ -3181,15 +3162,15 @@ func TestValidateEditConfig_Two_Delete_Requests_Positive(t *testing.T) { "Vlan51": map[string]interface{}{ "vlanid": "51", }, - }, + }, "STP_VLAN": map[string]interface{}{ "Vlan51": map[string]interface{}{ - "enabled": "true", + "enabled": "true", "forward_delay": "15", - "hello_time": "2", - "max_age" : "20", - "priority": "327", - "vlanid": "51", + "hello_time": "2", + "max_age": "20", + "priority": "327", + "vlanid": "51", }, }, } @@ -3199,33 +3180,30 @@ func TestValidateEditConfig_Two_Delete_Requests_Positive(t *testing.T) { cvSess := NewTestSession(t) - cfgDataVlan := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "STP_VLAN|Vlan51", - map[string]string { - }, + map[string]string{}, }, } cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgDataVlan) verifyErr(t, cvlErrInfo, Success) - cfgDataVlan = []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan = []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_DELETE, "STP_VLAN|Vlan51", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "VLAN|Vlan51", - map[string]string { - }, + map[string]string{}, }, } @@ -3233,7 +3211,7 @@ func TestValidateEditConfig_Two_Delete_Requests_Positive(t *testing.T) { verifyErr(t, cvlErrInfo, Success) } -//Check delete constraing with table having multiple keys +// Check delete constraing with table having multiple keys func TestValidateEditConfig_Multi_Delete_MultiKey_Same_Session_Positive(t *testing.T) { depDataMap := map[string]interface{}{ "VLAN": map[string]interface{}{ @@ -3249,14 +3227,14 @@ func TestValidateEditConfig_Multi_Delete_MultiKey_Same_Session_Positive(t *testi "STP_VLAN_PORT": map[string]interface{}{ "Vlan511|Ethernet16": map[string]interface{}{ "path_cost": "200", - "priority": "128", + "priority": "128", }, }, "STP_PORT": map[string]interface{}{ "Ethernet16": map[string]interface{}{ "bpdu_filter": "global", - "enabled": "true", - "portfast": "true", + "enabled": "true", + "portfast": "true", }, }, } @@ -3265,25 +3243,24 @@ func TestValidateEditConfig_Multi_Delete_MultiKey_Same_Session_Positive(t *testi defer unloadConfigDB(rclient, depDataMap) cvSess := NewTestSession(t) - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "STP_VLAN_PORT|Vlan511|Ethernet16", - map[string]string { - }, + map[string]string{}, }, } cvlErrInfo, _ := cvSess.ValidateEditConfig(cfgData) verifyErr(t, cvlErrInfo, Success) - cfgData = []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData = []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "VLAN_MEMBER|Vlan511|Ethernet16", - map[string]string { + map[string]string{ "tagging_mode": "untagged", }, }, @@ -3292,28 +3269,26 @@ func TestValidateEditConfig_Multi_Delete_MultiKey_Same_Session_Positive(t *testi cvlErrInfo, _ = cvSess.ValidateEditConfig(cfgData) verifyErr(t, cvlErrInfo, Success) - cfgData = []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData = []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_DELETE, "STP_VLAN_PORT|Vlan511|Ethernet16", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_DELETE, "VLAN_MEMBER|Vlan511|Ethernet16", - map[string]string { + map[string]string{ "tagging_mode": "untagged", }, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "STP_PORT|Ethernet16", - map[string]string { - }, + map[string]string{}, }, } @@ -3323,13 +3298,13 @@ func TestValidateEditConfig_Multi_Delete_MultiKey_Same_Session_Positive(t *testi func TestValidateEditConfig_Update_Leaf_List_Max_Elements_Negative(t *testing.T) { depDataMap := map[string]interface{}{ - "VLAN": map[string]interface{} { - "Vlan801": map[string]interface{} { + "VLAN": map[string]interface{}{ + "Vlan801": map[string]interface{}{ "vlanid": "801", }, }, - "CFG_L2MC_STATIC_GROUP_TABLE": map[string]interface{} { - "Vlan801|16.2.2.1": map[string]interface{} { + "CFG_L2MC_STATIC_GROUP_TABLE": map[string]interface{}{ + "Vlan801|16.2.2.1": map[string]interface{}{ "out-intf@": "Ethernet4,Ethernet8,Ethernet16", }, }, @@ -3338,12 +3313,12 @@ func TestValidateEditConfig_Update_Leaf_List_Max_Elements_Negative(t *testing.T) loadConfigDB(rclient, depDataMap) defer unloadConfigDB(rclient, depDataMap) - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_UPDATE, "CFG_L2MC_STATIC_GROUP_TABLE|Vlan801|16.2.2.1", - map[string]string { + map[string]string{ "out-intf@": "Ethernet4,Ethernet8,Ethernet16,Ethernet20", }, }, @@ -3363,19 +3338,19 @@ func TestValidationTimeStats(t *testing.T) { stats := cvl.GetValidationTimeStats() - if (stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0) { + if stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0 { t.Errorf("TestValidationTimeStats : clearing stats failed") return } cvSess, _ := cvl.ValidationSessOpen() - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "VRF|VrfTest", - map[string]string { + map[string]string{ "fallback": "true", }, }, @@ -3387,7 +3362,7 @@ func TestValidationTimeStats(t *testing.T) { stats = cvl.GetValidationTimeStats() - if (stats.Hits == 0 || stats.Time == 0 || stats.Peak == 0) { + if stats.Hits == 0 || stats.Time == 0 || stats.Peak == 0 { t.Errorf("TestValidationTimeStats : getting stats failed") return } @@ -3397,7 +3372,7 @@ func TestValidationTimeStats(t *testing.T) { stats = cvl.GetValidationTimeStats() - if (stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0) { + if stats.Hits != 0 || stats.Time != 0 || stats.Peak != 0 { t.Errorf("TestValidationTimeStats : clearing stats failed") } } diff --git a/cvl/cvl_when_test.go b/cvl/cvl_when_test.go index 9c4b8a9fb..2bef4e175 100644 --- a/cvl/cvl_when_test.go +++ b/cvl/cvl_when_test.go @@ -20,8 +20,8 @@ package cvl_test import ( - "testing" "github.com/Azure/sonic-mgmt-common/cvl" + "testing" ) func TestValidateEditConfig_When_Exp_In_Choice_Negative(t *testing.T) { @@ -45,7 +45,7 @@ func TestValidateEditConfig_When_Exp_In_Choice_Negative(t *testing.T) { "ACL_RULE|TestACL1|Rule1", map[string]string{ "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV6", + "IP_TYPE": "IPV6", "SRC_IP": "10.1.1.1/32", //Invalid field "L4_SRC_PORT": "1909", "IP_PROTOCOL": "103", @@ -83,7 +83,7 @@ func TestValidateEditConfig_When_Exp_In_Leaf_Positive(t *testing.T) { cvl.OP_CREATE, "STP_PORT|Ethernet4", map[string]string{ - "enabled": "true", + "enabled": "true", "edge_port": "true", "link_type": "shared", }, @@ -112,7 +112,7 @@ func TestValidateEditConfig_When_Exp_In_Leaf_Negative(t *testing.T) { cvl.OP_CREATE, "STP_PORT|Ethernet4", map[string]string{ - "enabled": "true", + "enabled": "true", "link_type": "shared", }, }, diff --git a/cvl/internal/util/luascript_util.go b/cvl/internal/util/luascript_util.go index 272566b5b..d8556c812 100644 --- a/cvl/internal/util/luascript_util.go +++ b/cvl/internal/util/luascript_util.go @@ -18,8 +18,9 @@ //////////////////////////////////////////////////////////////////////////////// package util + import ( - "github.com/go-redis/redis/v7" + "github.com/go-redis/redis/v7" ) var FILTER_ENTRIES_LUASCRIPT *redis.Script = redis.NewScript(` diff --git a/cvl/internal/util/util.go b/cvl/internal/util/util.go index e8beceb32..13797dcda 100644 --- a/cvl/internal/util/util.go +++ b/cvl/internal/util/util.go @@ -41,37 +41,39 @@ static void ly_set_log_callback(int enable) { */ import "C" import ( - "os" - "fmt" - "io" - "runtime" "encoding/json" - "io/ioutil" - "os/signal" - "syscall" - "strings" - "strconv" + "fmt" + set "github.com/Workiva/go-datastructures/set" "github.com/go-redis/redis/v7" log "github.com/golang/glog" - set "github.com/Workiva/go-datastructures/set" + "io" + "io/ioutil" fileLog "log" + "os" + "os/signal" + "runtime" + "strconv" + "strings" "sync" + "syscall" ) var CVL_SCHEMA string = "schema/" var CVL_CFG_FILE string = "/usr/sbin/cvl_cfg.json" + const CVL_LOG_FILE = "/tmp/cvl.log" const SONIC_DB_CONFIG_FILE string = "/var/run/redis/sonic-db/database_config.json" const ENV_VAR_SONIC_DB_CONFIG_FILE = "DB_CONFIG_PATH" + var sonic_db_config = make(map[string]interface{}) -//package init function +// package init function func init() { - if (os.Getenv("CVL_SCHEMA_PATH") != "") { + if os.Getenv("CVL_SCHEMA_PATH") != "" { CVL_SCHEMA = os.Getenv("CVL_SCHEMA_PATH") + "/" } - if (os.Getenv("CVL_CFG_FILE") != "") { + if os.Getenv("CVL_CFG_FILE") != "" { CVL_CFG_FILE = os.Getenv("CVL_CFG_FILE") } @@ -88,10 +90,11 @@ var logFileSize int var pLogFile *os.File var logFileMutex *sync.Mutex -//CVLLogLevel Logging Level for CVL global logging +// CVLLogLevel Logging Level for CVL global logging type CVLLogLevel uint8 + const ( - INFO = 0 + iota + INFO = 0 + iota WARNING ERROR FATAL @@ -105,42 +108,42 @@ const ( var cvlTraceFlags uint32 -//CVLTraceLevel Logging levels for CVL Tracing -type CVLTraceLevel uint32 +// CVLTraceLevel Logging levels for CVL Tracing +type CVLTraceLevel uint32 + const ( - TRACE_MIN = 0 - TRACE_MAX = 8 - TRACE_CACHE = 1 << TRACE_MIN - TRACE_LIBYANG = 1 << 1 - TRACE_YPARSER = 1 << 2 - TRACE_CREATE = 1 << 3 - TRACE_UPDATE = 1 << 4 - TRACE_DELETE = 1 << 5 + TRACE_MIN = 0 + TRACE_MAX = 8 + TRACE_CACHE = 1 << TRACE_MIN + TRACE_LIBYANG = 1 << 1 + TRACE_YPARSER = 1 << 2 + TRACE_CREATE = 1 << 3 + TRACE_UPDATE = 1 << 4 + TRACE_DELETE = 1 << 5 TRACE_SEMANTIC = 1 << 6 - TRACE_ONERROR = 1 << 7 - TRACE_SYNTAX = 1 << TRACE_MAX + TRACE_ONERROR = 1 << 7 + TRACE_SYNTAX = 1 << TRACE_MAX ) - -var traceLevelMap = map[int]string { +var traceLevelMap = map[int]string{ /* Caching operation traces */ - TRACE_CACHE : "TRACE_CACHE", + TRACE_CACHE: "TRACE_CACHE", /* Libyang library traces. */ TRACE_LIBYANG: "TRACE_LIBYANG", /* Yang Parser traces. */ - TRACE_YPARSER : "TRACE_YPARSER", + TRACE_YPARSER: "TRACE_YPARSER", /* Create operation traces. */ - TRACE_CREATE : "TRACE_CREATE", + TRACE_CREATE: "TRACE_CREATE", /* Update operation traces. */ - TRACE_UPDATE : "TRACE_UPDATE", + TRACE_UPDATE: "TRACE_UPDATE", /* Delete operation traces. */ - TRACE_DELETE : "TRACE_DELETE", + TRACE_DELETE: "TRACE_DELETE", /* Semantic Validation traces. */ - TRACE_SEMANTIC : "TRACE_SEMANTIC", + TRACE_SEMANTIC: "TRACE_SEMANTIC", /* Syntax Validation traces. */ - TRACE_SYNTAX : "TRACE_SYNTAX", + TRACE_SYNTAX: "TRACE_SYNTAX", /* Trace on Error. */ - TRACE_ONERROR : "TRACE_ONERROR", + TRACE_ONERROR: "TRACE_ONERROR", } var Tracing bool = false @@ -152,13 +155,13 @@ func SetTrace(on bool) { Tracing = true traceFlags = 1 } else { - Tracing = false + Tracing = false traceFlags = 0 } } func IsTraceSet() bool { - if (traceFlags == 0) { + if traceFlags == 0 { return false } else { return true @@ -169,7 +172,7 @@ func IsTraceSet() bool { changing libyang's global log setting */ //export customLogCallback -func customLogCallback(level C.LY_LOG_LEVEL, msg *C.char, path *C.char) { +func customLogCallback(level C.LY_LOG_LEVEL, msg *C.char, path *C.char) { if level == C.LY_LLERR { CVL_LEVEL_LOG(WARNING, "[libyang Error] %s (path: %s)", C.GoString(msg), C.GoString(path)) } else { @@ -184,15 +187,15 @@ func IsTraceLevelSet(tracelevel CVLTraceLevel) bool { func TRACE_LEVEL_LOG(tracelevel CVLTraceLevel, fmtStr string, args ...interface{}) { /* - if (IsTraceSet() == false) { - return - } + if (IsTraceSet() == false) { + return + } - level = (level - INFO_API) + 1; + level = (level - INFO_API) + 1; */ traceEnabled := false - if ((cvlTraceFlags & (uint32)(tracelevel)) != 0) { + if (cvlTraceFlags & (uint32)(tracelevel)) != 0 { traceEnabled = true } if traceEnabled && isLogToFile { @@ -217,14 +220,14 @@ func TRACE_LEVEL_LOG(tracelevel CVLTraceLevel, fmtStr string, args ...interface{ } } -//Logs to /tmp/cvl.log file +// Logs to /tmp/cvl.log file func logToCvlFile(format string, args ...interface{}) { - if (pLogFile == nil) { + if pLogFile == nil { return } logFileMutex.Lock() - if (logFileSize == 0) { + if logFileSize == 0 { fileLog.Printf(format, args...) logFileMutex.Unlock() return @@ -238,7 +241,7 @@ func logToCvlFile(format string, args ...interface{}) { } // Roll over the file contents if size execeeds max defined limit - if (curSize >= int64(logFileSize)) { + if curSize >= int64(logFileSize) { //Write 70% contents from bottom and write to top //Truncate 30% of bottom @@ -246,31 +249,30 @@ func logToCvlFile(format string, args ...interface{}) { pLogFile.Close() pFile, err := os.OpenFile(CVL_LOG_FILE, - os.O_RDONLY, 0666) - pFileOut, errOut := os.OpenFile(CVL_LOG_FILE + ".tmp", - os.O_WRONLY | os.O_CREATE, 0666) - + os.O_RDONLY, 0666) + pFileOut, errOut := os.OpenFile(CVL_LOG_FILE+".tmp", + os.O_WRONLY|os.O_CREATE, 0666) if (err != nil) && (errOut != nil) { fileLog.Printf("Failed to roll over the file, current size %v", curSize) } else { - pFile.Seek(int64(logFileSize * 30/100), io.SeekStart) + pFile.Seek(int64(logFileSize*30/100), io.SeekStart) _, err := io.Copy(pFileOut, pFile) if err == nil { - os.Rename(CVL_LOG_FILE + ".tmp", CVL_LOG_FILE) + os.Rename(CVL_LOG_FILE+".tmp", CVL_LOG_FILE) } } - if (pFile != nil) { + if pFile != nil { pFile.Close() } - if (pFileOut != nil) { + if pFileOut != nil { pFileOut.Close() } - // Reopen the file + // Reopen the file pLogFile, err := os.OpenFile(CVL_LOG_FILE, - os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) + os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { fmt.Printf("Error in opening log file %s, %v", CVL_LOG_FILE, err) } else { @@ -278,7 +280,6 @@ func logToCvlFile(format string, args ...interface{}) { } } - fileLog.Printf(format, args...) logFileMutex.Unlock() @@ -289,7 +290,7 @@ func CVL_LEVEL_LOG(level CVLLogLevel, format string, args ...interface{}) { if isLogToFile { logToCvlFile(format, args...) if level == FATAL { - log.Fatalf("[CVL] : " + format, args...) + log.Fatalf("[CVL] : "+format, args...) } return } @@ -297,26 +298,26 @@ func CVL_LEVEL_LOG(level CVLLogLevel, format string, args ...interface{}) { format = "[CVL] : " + format switch level { - case INFO: - log.Infof(format, args...) - case WARNING: - log.Warningf(format, args...) - case ERROR: - log.Errorf(format, args...) - case FATAL: - log.Fatalf(format, args...) - case INFO_API: - log.V(1).Infof(format, args...) - case INFO_TRACE: - log.V(2).Infof(format, args...) - case INFO_DEBUG: - log.V(3).Infof(format, args...) - case INFO_DATA: - log.V(4).Infof(format, args...) - case INFO_DETAIL: - log.V(5).Infof(format, args...) - case INFO_ALL: - log.V(6).Infof(format, args...) + case INFO: + log.Infof(format, args...) + case WARNING: + log.Warningf(format, args...) + case ERROR: + log.Errorf(format, args...) + case FATAL: + log.Fatalf(format, args...) + case INFO_API: + log.V(1).Infof(format, args...) + case INFO_TRACE: + log.V(2).Infof(format, args...) + case INFO_DEBUG: + log.V(3).Infof(format, args...) + case INFO_DATA: + log.V(4).Infof(format, args...) + case INFO_DETAIL: + log.V(5).Infof(format, args...) + case INFO_ALL: + log.V(6).Infof(format, args...) } } @@ -324,7 +325,7 @@ func CVL_LEVEL_LOG(level CVLLogLevel, format string, args ...interface{}) { // Function to check CVL log file related settings func applyCvlLogFileConfig() { - if (pLogFile != nil) { + if pLogFile != nil { pLogFile.Close() pLogFile = nil } @@ -343,9 +344,9 @@ func applyCvlLogFileConfig() { logFileSize, _ = strconv.Atoi(fileSize) } - if (enabled == "true") { + if enabled == "true" { pFile, err := os.OpenFile(CVL_LOG_FILE, - os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666) + os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { fmt.Printf("Error in opening log file %s, %v", CVL_LOG_FILE, err) @@ -372,9 +373,9 @@ func ConfigFileSyncHandler() { return } - CVL_LEVEL_LOG(INFO ,"Received SIGUSR2. Changed configuration values are %v", cvlCfgMap) + CVL_LEVEL_LOG(INFO, "Received SIGUSR2. Changed configuration values are %v", cvlCfgMap) - if (strings.Compare(cvlCfgMap["LOGTOSTDERR"], "true") == 0) { + if strings.Compare(cvlCfgMap["LOGTOSTDERR"], "true") == 0 { SetTrace(true) } } @@ -382,7 +383,7 @@ func ConfigFileSyncHandler() { } -func ReadConfFile() map[string]string{ +func ReadConfFile() map[string]string { /* Return if CVL configuration file is not present. */ if _, err := os.Stat(CVL_CFG_FILE); os.IsNotExist(err) { @@ -391,22 +392,22 @@ func ReadConfFile() map[string]string{ data, err := ioutil.ReadFile(CVL_CFG_FILE) if err != nil { - CVL_LEVEL_LOG(INFO ,"Error in reading cvl configuration file %v", err) + CVL_LEVEL_LOG(INFO, "Error in reading cvl configuration file %v", err) return nil } err = json.Unmarshal(data, &cvlCfgMap) if err != nil { - CVL_LEVEL_LOG(INFO ,"Error in reading cvl configuration file %v", err) + CVL_LEVEL_LOG(INFO, "Error in reading cvl configuration file %v", err) return nil } - CVL_LEVEL_LOG(INFO ,"Current Values of CVL Configuration File %v", cvlCfgMap) + CVL_LEVEL_LOG(INFO, "Current Values of CVL Configuration File %v", cvlCfgMap) var index uint32 - for index = TRACE_MIN ; index <= TRACE_MAX ; index++ { - if (strings.Compare(cvlCfgMap[traceLevelMap[1 << index]], "true") == 0) { - cvlTraceFlags = cvlTraceFlags | (1 << index) + for index = TRACE_MIN; index <= TRACE_MAX; index++ { + if strings.Compare(cvlCfgMap[traceLevelMap[1<type.info.uni.count; idx++) + for (idx = 0; idx < lNode->type.info.uni.count; idx++) { - if (lNode->type.info.uni.types[idx].base != LY_TYPE_LEAFREF) + if (lNode->type.info.uni.types[idx].base != LY_TYPE_LEAFREF) { //Look for leafref type only continue; @@ -244,85 +244,86 @@ type YParserModule C.struct_lys_module var ypCtx *YParserCtx var ypOpModule *YParserModule -var ypOpRoot *YParserNode //Operation root -var ypOpNode *YParserNode //Operation node +var ypOpRoot *YParserNode //Operation root +var ypOpNode *YParserNode //Operation node type XpathExpression struct { - Expr string + Expr string ErrCode string - ErrStr string + ErrStr string } type WhenExpression struct { - Expr string //when expression + Expr string //when expression NodeNames []string //node names under when condition } -//YParserListInfo Important schema information to be loaded at bootup time +// YParserListInfo Important schema information to be loaded at bootup time type YParserListInfo struct { - ListName string - Module *YParserModule - DbName string - ModelName string - RedisTableName string //To which Redis table it belongs to, used for 1 Redis to N Yang List - Keys []string - RedisKeyDelim string + ListName string + Module *YParserModule + DbName string + ModelName string + RedisTableName string //To which Redis table it belongs to, used for 1 Redis to N Yang List + Keys []string + RedisKeyDelim string RedisKeyPattern string - RedisTableSize int - MapLeaf []string //for 'mapping list' - LeafRef map[string][]string //for storing all leafrefs for a leaf in a table, - //multiple leafref possible for union - DfltLeafVal map[string]string //Default value for leaf/leaf-list - XpathExpr map[string][]*XpathExpression + RedisTableSize int + MapLeaf []string //for 'mapping list' + LeafRef map[string][]string //for storing all leafrefs for a leaf in a table, + //multiple leafref possible for union + DfltLeafVal map[string]string //Default value for leaf/leaf-list + XpathExpr map[string][]*XpathExpression CustValidation map[string]string - WhenExpr map[string][]*WhenExpression //multiple when expression for choice/case etc + WhenExpr map[string][]*WhenExpression //multiple when expression for choice/case etc MandatoryNodes map[string]bool } type YParserLeafValue struct { - Name string + Name string Value string } type YParser struct { - root *YParserNode //Top evel root for validation - operation string //Edit operation + root *YParserNode //Top evel root for validation + operation string //Edit operation } -//YParserError YParser Error Structure +// YParserError YParser Error Structure type YParserError struct { - ErrCode YParserRetCode /* Error Code describing type of error. */ - Msg string /* Detailed error message. */ - ErrTxt string /* High level error message. */ - TableName string /* List/Table having error */ - Keys []string /* Keys of the Table having error. */ - Field string /* Field Name throwing error . */ - Value string /* Field Value throwing error */ - ErrAppTag string /* Error App Tag. */ + ErrCode YParserRetCode /* Error Code describing type of error. */ + Msg string /* Detailed error message. */ + ErrTxt string /* High level error message. */ + TableName string /* List/Table having error */ + Keys []string /* Keys of the Table having error. */ + Field string /* Field Name throwing error . */ + Value string /* Field Value throwing error */ + ErrAppTag string /* Error App Tag. */ } type YParserRetCode int + const ( YP_SUCCESS YParserRetCode = 1000 + iota YP_SYNTAX_ERROR YP_SEMANTIC_ERROR YP_SYNTAX_MISSING_FIELD - YP_SYNTAX_INVALID_FIELD /* Invalid Field */ - YP_SYNTAX_INVALID_INPUT_DATA /*Invalid Input Data */ - YP_SYNTAX_MULTIPLE_INSTANCE /* Multiple Field Instances */ - YP_SYNTAX_DUPLICATE /* Duplicate Fields */ - YP_SYNTAX_ENUM_INVALID /* Invalid enum value */ - YP_SYNTAX_ENUM_INVALID_NAME /* Invalid enum name */ - YP_SYNTAX_ENUM_WHITESPACE /* Enum name with leading/trailing whitespaces */ - YP_SYNTAX_OUT_OF_RANGE /* Value out of range/length/pattern (data) */ - YP_SYNTAX_MINIMUM_INVALID /* min-elements constraint not honored */ - YP_SYNTAX_MAXIMUM_INVALID /* max-elements constraint not honored */ - YP_SEMANTIC_DEPENDENT_DATA_MISSING /* Dependent Data is missing */ + YP_SYNTAX_INVALID_FIELD /* Invalid Field */ + YP_SYNTAX_INVALID_INPUT_DATA /*Invalid Input Data */ + YP_SYNTAX_MULTIPLE_INSTANCE /* Multiple Field Instances */ + YP_SYNTAX_DUPLICATE /* Duplicate Fields */ + YP_SYNTAX_ENUM_INVALID /* Invalid enum value */ + YP_SYNTAX_ENUM_INVALID_NAME /* Invalid enum name */ + YP_SYNTAX_ENUM_WHITESPACE /* Enum name with leading/trailing whitespaces */ + YP_SYNTAX_OUT_OF_RANGE /* Value out of range/length/pattern (data) */ + YP_SYNTAX_MINIMUM_INVALID /* min-elements constraint not honored */ + YP_SYNTAX_MAXIMUM_INVALID /* max-elements constraint not honored */ + YP_SEMANTIC_DEPENDENT_DATA_MISSING /* Dependent Data is missing */ YP_SEMANTIC_MANDATORY_DATA_MISSING /* Mandatory Data is missing */ - YP_SEMANTIC_KEY_ALREADY_EXIST /* Key already existing */ - YP_SEMANTIC_KEY_NOT_EXIST /* Key is missing */ - YP_SEMANTIC_KEY_DUPLICATE /* Duplicate key */ - YP_SEMANTIC_KEY_INVALID /* Invalid key */ + YP_SEMANTIC_KEY_ALREADY_EXIST /* Key already existing */ + YP_SEMANTIC_KEY_NOT_EXIST /* Key is missing */ + YP_SEMANTIC_KEY_DUPLICATE /* Duplicate key */ + YP_SEMANTIC_KEY_INVALID /* Invalid key */ YP_INTERNAL_UNKNOWN ) @@ -339,22 +340,22 @@ const customErrorPrefix = "[Error]" var yparserInitialized bool = false func TRACE_LOG(tracelevel CVLTraceLevel, fmtStr string, args ...interface{}) { - TRACE_LEVEL_LOG(tracelevel , fmtStr, args...) + TRACE_LEVEL_LOG(tracelevel, fmtStr, args...) } func CVL_LOG(level CVLLogLevel, fmtStr string, args ...interface{}) { CVL_LEVEL_LOG(level, fmtStr, args...) } -//package init function +// package init function func init() { - if (os.Getenv("CVL_DEBUG") != "") { + if os.Getenv("CVL_DEBUG") != "" { Debug(true) } } func Debug(on bool) { - if on { + if on { C.ly_verb(C.LY_LLDBG) } else { C.ly_verb(C.LY_LLERR) @@ -365,20 +366,20 @@ func Initialize() { if !yparserInitialized { ypCtx = (*YParserCtx)(C.ly_ctx_new(C.CString(CVL_SCHEMA), 0)) C.ly_verb(C.LY_LLERR) - // yparserInitialized = true + // yparserInitialized = true } } func Finish() { if yparserInitialized { C.ly_ctx_destroy((*C.struct_ly_ctx)(ypCtx), nil) - // yparserInitialized = false + // yparserInitialized = false } } -//ParseSchemaFile Parse YIN schema file +// ParseSchemaFile Parse YIN schema file func ParseSchemaFile(modelFile string) (*YParserModule, YParserError) { - module := C.lys_parse_path((*C.struct_ly_ctx)(ypCtx), C.CString(modelFile), C.LYS_IN_YIN) + module := C.lys_parse_path((*C.struct_ly_ctx)(ypCtx), C.CString(modelFile), C.LYS_IN_YIN) if module == nil { return nil, getErrorDetails() } @@ -389,22 +390,22 @@ func ParseSchemaFile(modelFile string) (*YParserModule, YParserError) { ypOpNode = (*YParserNode)(C.lyd_new_leaf((*C.struct_lyd_node)(ypOpRoot), (*C.struct_lys_module)(ypOpModule), C.CString("operation"), C.CString("NOP"))) } - return (*YParserModule)(module), YParserError {ErrCode : YP_SUCCESS,} + return (*YParserModule)(module), YParserError{ErrCode: YP_SUCCESS} } -//AddChildNode Add child node to a parent node -func(yp *YParser) AddChildNode(module *YParserModule, parent *YParserNode, name string) *YParserNode { - nameCStr := C.CString(name) +// AddChildNode Add child node to a parent node +func (yp *YParser) AddChildNode(module *YParserModule, parent *YParserNode, name string) *YParserNode { + nameCStr := C.CString(name) defer C.free(unsafe.Pointer(nameCStr)) ret := (*YParserNode)(C.lyd_new((*C.struct_lyd_node)(parent), (*C.struct_lys_module)(module), (*C.char)(nameCStr))) - if (ret == nil) { + if ret == nil { TRACE_LOG(TRACE_YPARSER, "Failed parsing node %s", name) } return ret } -//IsLeafrefMatchedInUnion Check if value matches with leafref node in union +// IsLeafrefMatchedInUnion Check if value matches with leafref node in union func (yp *YParser) IsLeafrefMatchedInUnion(module *YParserModule, xpath, value string) bool { xpathCStr := C.CString(xpath) valCStr := C.CString(value) @@ -415,11 +416,11 @@ func (yp *YParser) IsLeafrefMatchedInUnion(module *YParserModule, xpath, value s return C.lyd_node_leafref_match_in_union((*C.struct_lys_module)(module), (*C.char)(xpathCStr), (*C.char)(valCStr)) == 0 } -//AddMultiLeafNodes dd child node to a parent node -func(yp *YParser) AddMultiLeafNodes(module *YParserModule, parent *YParserNode, multiLeaf []*YParserLeafValue) YParserError { +// AddMultiLeafNodes dd child node to a parent node +func (yp *YParser) AddMultiLeafNodes(module *YParserModule, parent *YParserNode, multiLeaf []*YParserLeafValue) YParserError { leafValArr := make([]C.struct_leaf_value, len(multiLeaf)) - tmpArr := make([]*C.char, len(multiLeaf) * 2) + tmpArr := make([]*C.char, len(multiLeaf)*2) size := C.int(0) for index := 0; index < len(multiLeaf); index++ { @@ -451,12 +452,13 @@ func(yp *YParser) AddMultiLeafNodes(module *YParserModule, parent *YParserNode, return getErrorDetails() } - return YParserError {ErrCode : YP_SUCCESS,} + return YParserError{ErrCode: YP_SUCCESS} } -//NodeDump Return entire subtree in XML format in string + +// NodeDump Return entire subtree in XML format in string func (yp *YParser) NodeDump(root *YParserNode) string { - if (root == nil) { + if root == nil { return "" } else { var outBuf *C.char @@ -465,12 +467,12 @@ func (yp *YParser) NodeDump(root *YParserNode) string { } } -//MergeSubtree Merge source with destination +// MergeSubtree Merge source with destination func (yp *YParser) MergeSubtree(root, node *YParserNode) (*YParserNode, YParserError) { rootTmp := (*C.struct_lyd_node)(root) - if (root == nil || node == nil) { - return root, YParserError {ErrCode: YP_SUCCESS} + if root == nil || node == nil { + return root, YParserError{ErrCode: YP_SUCCESS} } if Tracing { @@ -487,38 +489,38 @@ func (yp *YParser) MergeSubtree(root, node *YParserNode) (*YParserNode, YParserE TRACE_LOG(TRACE_YPARSER, "Merged subtree = %v\n", dumpStr) } - return (*YParserNode)(rootTmp), YParserError {ErrCode : YP_SUCCESS,} + return (*YParserNode)(rootTmp), YParserError{ErrCode: YP_SUCCESS} } func (yp *YParser) DestroyCache() YParserError { - if (yp.root != nil) { + if yp.root != nil { C.lyd_free_withsiblings((*C.struct_lyd_node)(yp.root)) yp.root = nil } - return YParserError {ErrCode : YP_SUCCESS,} + return YParserError{ErrCode: YP_SUCCESS} } -//SetOperation Set operation +// SetOperation Set operation func (yp *YParser) SetOperation(op string) YParserError { - if (ypOpNode == nil) { - return YParserError {ErrCode : YP_INTERNAL_UNKNOWN,} + if ypOpNode == nil { + return YParserError{ErrCode: YP_INTERNAL_UNKNOWN} } if C.lyd_change_leaf_data((*C.struct_lyd_node)(ypOpNode), C.CString(op)) != 0 { - return YParserError {ErrCode : YP_INTERNAL_UNKNOWN,} + return YParserError{ErrCode: YP_INTERNAL_UNKNOWN} } yp.operation = op - return YParserError {ErrCode : YP_SUCCESS,} + return YParserError{ErrCode: YP_SUCCESS} } -//ValidateSyntax Perform syntax checks +// ValidateSyntax Perform syntax checks func (yp *YParser) ValidateSyntax(data, depData *YParserNode) YParserError { dataTmp := (*C.struct_lyd_node)(data) - if (data != nil && depData != nil) { + if data != nil && depData != nil { //merge ependent data for synatx validation - Update/Delete case if C.lyd_merge_to_ctx(&dataTmp, (*C.struct_lyd_node)(depData), C.LYD_OPT_DESTRUCT, (*C.struct_ly_ctx)(ypCtx)) != 0 { TRACE_LOG((TRACE_SYNTAX | TRACE_LIBYANG), "Unable to merge dependent data\n") @@ -527,15 +529,15 @@ func (yp *YParser) ValidateSyntax(data, depData *YParserNode) YParserError { } //Just validate syntax - if C.lyd_data_validate(&dataTmp, C.LYD_OPT_EDIT | C.LYD_OPT_NOEXTDEPS, (*C.struct_ly_ctx)(ypCtx)) != 0 { + if C.lyd_data_validate(&dataTmp, C.LYD_OPT_EDIT|C.LYD_OPT_NOEXTDEPS, (*C.struct_ly_ctx)(ypCtx)) != 0 { if Tracing { strData := yp.NodeDump((*YParserNode)(dataTmp)) TRACE_LOG(TRACE_ONERROR, "Failed to validate Syntax, data = %v", strData) } - return getErrorDetails() + return getErrorDetails() } - return YParserError {ErrCode : YP_SUCCESS,} + return YParserError{ErrCode: YP_SUCCESS} } func (yp *YParser) FreeNode(node *YParserNode) YParserError { @@ -544,7 +546,7 @@ func (yp *YParser) FreeNode(node *YParserNode) YParserError { node = nil } - return YParserError {ErrCode : YP_SUCCESS,} + return YParserError{ErrCode: YP_SUCCESS} } /* This function translates LIBYANG error code to valid YPARSER error code. */ @@ -552,42 +554,42 @@ func translateLYErrToYParserErr(LYErrcode int) YParserRetCode { var ypErrCode YParserRetCode switch LYErrcode { - case C.LYVE_SUCCESS: /**< no error */ - ypErrCode = YP_SUCCESS - case C.LYVE_XML_MISS, C.LYVE_INARG, C.LYVE_MISSELEM: /**< missing XML object */ - ypErrCode = YP_SYNTAX_MISSING_FIELD - case C.LYVE_XML_INVAL, C.LYVE_XML_INCHAR, C.LYVE_INMOD, C.LYVE_INELEM , C.LYVE_INVAL, C.LYVE_MCASEDATA:/**< invalid XML object */ - ypErrCode = YP_SYNTAX_INVALID_FIELD - case C.LYVE_EOF, C.LYVE_INSTMT, C.LYVE_INPAR, C.LYVE_INID, C.LYVE_MISSSTMT, C.LYVE_MISSARG: /**< invalid statement (schema) */ - ypErrCode = YP_SYNTAX_INVALID_INPUT_DATA - case C.LYVE_TOOMANY: /**< too many instances of some object */ - ypErrCode = YP_SYNTAX_MULTIPLE_INSTANCE - case C.LYVE_DUPID, C.LYVE_DUPLEAFLIST, C.LYVE_DUPLIST, C.LYVE_NOUNIQ:/**< duplicated identifier (schema) */ - ypErrCode = YP_SYNTAX_DUPLICATE - case C.LYVE_ENUM_INVAL: /**< invalid enum value (schema) */ - ypErrCode = YP_SYNTAX_ENUM_INVALID - case C.LYVE_ENUM_INNAME: /**< invalid enum name (schema) */ - ypErrCode = YP_SYNTAX_ENUM_INVALID_NAME - case C.LYVE_ENUM_WS: /**< enum name with leading/trailing whitespaces (schema) */ - ypErrCode = YP_SYNTAX_ENUM_WHITESPACE - case C.LYVE_KEY_NLEAF, C.LYVE_KEY_CONFIG, C.LYVE_KEY_TYPE : /**< list key is not a leaf (schema) */ - ypErrCode = YP_SEMANTIC_KEY_INVALID - case C.LYVE_KEY_MISS, C.LYVE_PATH_MISSKEY: /**< list key not found (schema) */ - ypErrCode = YP_SEMANTIC_KEY_NOT_EXIST - case C.LYVE_KEY_DUP: /**< duplicated key identifier (schema) */ - ypErrCode = YP_SEMANTIC_KEY_DUPLICATE - case C.LYVE_NOMIN:/**< min-elements constraint not honored (data) */ - ypErrCode = YP_SYNTAX_MINIMUM_INVALID - case C.LYVE_NOMAX:/**< max-elements constraint not honored (data) */ - ypErrCode = YP_SYNTAX_MAXIMUM_INVALID - case C.LYVE_NOMUST, C.LYVE_NOWHEN, C.LYVE_INWHEN, C.LYVE_NOLEAFREF : /**< unsatisfied must condition (data) */ - ypErrCode = YP_SEMANTIC_DEPENDENT_DATA_MISSING - case C.LYVE_NOMANDCHOICE:/**< max-elements constraint not honored (data) */ - ypErrCode = YP_SEMANTIC_MANDATORY_DATA_MISSING - case C.LYVE_PATH_EXISTS: /**< target node already exists (path) */ - ypErrCode = YP_SEMANTIC_KEY_ALREADY_EXIST - default: - ypErrCode = YP_INTERNAL_UNKNOWN + case C.LYVE_SUCCESS: /**< no error */ + ypErrCode = YP_SUCCESS + case C.LYVE_XML_MISS, C.LYVE_INARG, C.LYVE_MISSELEM: /**< missing XML object */ + ypErrCode = YP_SYNTAX_MISSING_FIELD + case C.LYVE_XML_INVAL, C.LYVE_XML_INCHAR, C.LYVE_INMOD, C.LYVE_INELEM, C.LYVE_INVAL, C.LYVE_MCASEDATA: /**< invalid XML object */ + ypErrCode = YP_SYNTAX_INVALID_FIELD + case C.LYVE_EOF, C.LYVE_INSTMT, C.LYVE_INPAR, C.LYVE_INID, C.LYVE_MISSSTMT, C.LYVE_MISSARG: /**< invalid statement (schema) */ + ypErrCode = YP_SYNTAX_INVALID_INPUT_DATA + case C.LYVE_TOOMANY: /**< too many instances of some object */ + ypErrCode = YP_SYNTAX_MULTIPLE_INSTANCE + case C.LYVE_DUPID, C.LYVE_DUPLEAFLIST, C.LYVE_DUPLIST, C.LYVE_NOUNIQ: /**< duplicated identifier (schema) */ + ypErrCode = YP_SYNTAX_DUPLICATE + case C.LYVE_ENUM_INVAL: /**< invalid enum value (schema) */ + ypErrCode = YP_SYNTAX_ENUM_INVALID + case C.LYVE_ENUM_INNAME: /**< invalid enum name (schema) */ + ypErrCode = YP_SYNTAX_ENUM_INVALID_NAME + case C.LYVE_ENUM_WS: /**< enum name with leading/trailing whitespaces (schema) */ + ypErrCode = YP_SYNTAX_ENUM_WHITESPACE + case C.LYVE_KEY_NLEAF, C.LYVE_KEY_CONFIG, C.LYVE_KEY_TYPE: /**< list key is not a leaf (schema) */ + ypErrCode = YP_SEMANTIC_KEY_INVALID + case C.LYVE_KEY_MISS, C.LYVE_PATH_MISSKEY: /**< list key not found (schema) */ + ypErrCode = YP_SEMANTIC_KEY_NOT_EXIST + case C.LYVE_KEY_DUP: /**< duplicated key identifier (schema) */ + ypErrCode = YP_SEMANTIC_KEY_DUPLICATE + case C.LYVE_NOMIN: /**< min-elements constraint not honored (data) */ + ypErrCode = YP_SYNTAX_MINIMUM_INVALID + case C.LYVE_NOMAX: /**< max-elements constraint not honored (data) */ + ypErrCode = YP_SYNTAX_MAXIMUM_INVALID + case C.LYVE_NOMUST, C.LYVE_NOWHEN, C.LYVE_INWHEN, C.LYVE_NOLEAFREF: /**< unsatisfied must condition (data) */ + ypErrCode = YP_SEMANTIC_DEPENDENT_DATA_MISSING + case C.LYVE_NOMANDCHOICE: /**< max-elements constraint not honored (data) */ + ypErrCode = YP_SEMANTIC_MANDATORY_DATA_MISSING + case C.LYVE_PATH_EXISTS: /**< target node already exists (path) */ + ypErrCode = YP_SEMANTIC_KEY_ALREADY_EXIST + default: + ypErrCode = YP_INTERNAL_UNKNOWN } return ypErrCode @@ -601,30 +603,28 @@ func getErrorDetails() YParserError { var errMessage string var ElemName string var errText string - var ypErrCode YParserRetCode = YP_INTERNAL_UNKNOWN + var ypErrCode YParserRetCode = YP_INTERNAL_UNKNOWN var errMsg, errPath, errAppTag string ctx := (*C.struct_ly_ctx)(ypCtx) - ypErrFirst := C.ly_err_first(ctx); - - - if (ypErrFirst == nil) { - return YParserError { - ErrCode : ypErrCode, - } - } + ypErrFirst := C.ly_err_first(ctx) + if ypErrFirst == nil { + return YParserError{ + ErrCode: ypErrCode, + } + } - if ((ypErrFirst != nil) && ypErrFirst.prev.no == C.LY_SUCCESS) { - return YParserError { - ErrCode : YP_SUCCESS, + if (ypErrFirst != nil) && ypErrFirst.prev.no == C.LY_SUCCESS { + return YParserError{ + ErrCode: YP_SUCCESS, } } - if (ypErrFirst != nil) { - errMsg = C.GoString(ypErrFirst.prev.msg) - errPath = C.GoString(ypErrFirst.prev.path) - errAppTag = C.GoString(ypErrFirst.prev.apptag) + if ypErrFirst != nil { + errMsg = C.GoString(ypErrFirst.prev.msg) + errPath = C.GoString(ypErrFirst.prev.path) + errAppTag = C.GoString(ypErrFirst.prev.apptag) } // Try to resolve table, keys and field name from the error path. @@ -667,32 +667,32 @@ func getErrorDetails() YParserError { errMessage = "Internal error" } - errObj := YParserError { - TableName : errtableName, - ErrCode : ypErrCode, - Keys : key, - Value : ElemVal, - Field : ElemName, - Msg : errMessage, - ErrTxt: errText, + errObj := YParserError{ + TableName: errtableName, + ErrCode: ypErrCode, + Keys: key, + Value: ElemVal, + Field: ElemName, + Msg: errMessage, + ErrTxt: errText, ErrAppTag: errAppTag, } TRACE_LOG(TRACE_YPARSER, "YParser error details: %v...", errObj) - return errObj + return errObj } func FindNode(root *YParserNode, xpath string) *YParserNode { - return (*YParserNode)(C.lyd_find_node((*C.struct_lyd_node)(root), C.CString(xpath))) + return (*YParserNode)(C.lyd_find_node((*C.struct_lyd_node)(root), C.CString(xpath))) } func GetModelNs(module *YParserModule) (ns, prefix string) { return C.GoString(((*C.struct_lys_module)(module)).ns), - C.GoString(((*C.struct_lys_module)(module)).prefix) + C.GoString(((*C.struct_lys_module)(module)).prefix) } -//Get model details for child under list/choice/case +// Get model details for child under list/choice/case func getModelChildInfo(l *YParserListInfo, node *C.struct_lys_node, underWhen bool, whenExpr *WhenExpression) { @@ -700,39 +700,39 @@ func getModelChildInfo(l *YParserListInfo, node *C.struct_lys_node, switch sChild.nodetype { case C.LYS_USES: nodeUses := (*C.struct_lys_node_uses)(unsafe.Pointer(sChild)) - if (nodeUses.when != nil) { - usesWhenExp := WhenExpression { + if nodeUses.when != nil { + usesWhenExp := WhenExpression{ Expr: C.GoString(nodeUses.when.cond), } listName := l.ListName + "_LIST" l.WhenExpr[listName] = append(l.WhenExpr[listName], - &usesWhenExp) + &usesWhenExp) getModelChildInfo(l, sChild, true, &usesWhenExp) } else { getModelChildInfo(l, sChild, false, nil) } case C.LYS_CHOICE: nodeChoice := (*C.struct_lys_node_choice)(unsafe.Pointer(sChild)) - if (nodeChoice.when != nil) { - chWhenExp := WhenExpression { + if nodeChoice.when != nil { + chWhenExp := WhenExpression{ Expr: C.GoString(nodeChoice.when.cond), } listName := l.ListName + "_LIST" l.WhenExpr[listName] = append(l.WhenExpr[listName], - &chWhenExp) + &chWhenExp) getModelChildInfo(l, sChild, true, &chWhenExp) } else { getModelChildInfo(l, sChild, false, nil) } case C.LYS_CASE: nodeCase := (*C.struct_lys_node_case)(unsafe.Pointer(sChild)) - if (nodeCase.when != nil) { - csWhenExp := WhenExpression { + if nodeCase.when != nil { + csWhenExp := WhenExpression{ Expr: C.GoString(nodeCase.when.cond), } listName := l.ListName + "_LIST" l.WhenExpr[listName] = append(l.WhenExpr[listName], - &csWhenExp) + &csWhenExp) getModelChildInfo(l, sChild, true, &csWhenExp) } else { if underWhen { @@ -749,19 +749,19 @@ func getModelChildInfo(l *YParserListInfo, node *C.struct_lys_node, leafName := C.GoString(sleaf.name) - if (sChild.nodetype == C.LYS_LEAF) { - if (sleaf.dflt != nil) { + if sChild.nodetype == C.LYS_LEAF { + if sleaf.dflt != nil { l.DfltLeafVal[leafName] = C.GoString(sleaf.dflt) } } else { sLeafList := (*C.struct_lys_node_leaflist)(unsafe.Pointer(sChild)) - if (sleaf.dflt != nil) { + if sleaf.dflt != nil { //array of default values dfltValArr := (*[256]*C.char)(unsafe.Pointer(sLeafList.dflt)) tmpValStr := "" for idx := 0; idx < int(sLeafList.dflt_size); idx++ { - if (idx > 0) { + if idx > 0 { //Separate multiple values by , tmpValStr = tmpValStr + "," } @@ -774,7 +774,7 @@ func getModelChildInfo(l *YParserListInfo, node *C.struct_lys_node, } } - //If parent has when expression, + //If parent has when expression, //just add leaf to when expression node list if underWhen { whenExpr.NodeNames = append(whenExpr.NodeNames, leafName) @@ -782,48 +782,48 @@ func getModelChildInfo(l *YParserListInfo, node *C.struct_lys_node, //Check for leafref expression leafRefs := C.lys_get_leafrefs(sleaf) - if (leafRefs != nil) { + if leafRefs != nil { leafRefPaths := (*[10]*C.char)(unsafe.Pointer(&leafRefs.path)) for idx := 0; idx < int(leafRefs.count); idx++ { l.LeafRef[leafName] = append(l.LeafRef[leafName], - C.GoString(leafRefPaths[idx])) + C.GoString(leafRefPaths[idx])) } } //Check for must expression; one must expession only per leaf - if (sleaf.must_size > 0) { + if sleaf.must_size > 0 { must := (*[10]C.struct_lys_restr)(unsafe.Pointer(sleaf.must)) - for idx := 0; idx < int(sleaf.must_size); idx++ { + for idx := 0; idx < int(sleaf.must_size); idx++ { exp := XpathExpression{Expr: C.GoString(must[idx].expr)} - if (must[idx].eapptag != nil) { + if must[idx].eapptag != nil { exp.ErrCode = C.GoString(must[idx].eapptag) } - if (must[idx].emsg != nil) { + if must[idx].emsg != nil { exp.ErrStr = strings.TrimPrefix(C.GoString(must[idx].emsg), customErrorPrefix) } l.XpathExpr[leafName] = append(l.XpathExpr[leafName], - &exp) + &exp) } } //Check for when expression - if (sleaf.when != nil) { + if sleaf.when != nil { l.WhenExpr[leafName] = append(l.WhenExpr[leafName], - &WhenExpression { - Expr: C.GoString(sleaf.when.cond), - NodeNames: []string{leafName}, - }) + &WhenExpression{ + Expr: C.GoString(sleaf.when.cond), + NodeNames: []string{leafName}, + }) } //Check for custom extension - if (sleaf.ext_size > 0) { + if sleaf.ext_size > 0 { exts := (*[10]*C.struct_lys_ext_instance)(unsafe.Pointer(sleaf.ext)) - for idx := 0; idx < int(sleaf.ext_size); idx++ { - if (C.GoString(exts[idx].def.name) == "custom-validation") { + for idx := 0; idx < int(sleaf.ext_size); idx++ { + if C.GoString(exts[idx].def.name) == "custom-validation" { argVal := C.GoString(exts[idx].arg_value) - if (argVal != "") { + if argVal != "" { l.CustValidation[leafName] = argVal } } @@ -840,15 +840,15 @@ func getModelChildInfo(l *YParserListInfo, node *C.struct_lys_node, } } -//GetModelListInfo Get model info for YANG list and its subtree +// GetModelListInfo Get model info for YANG list and its subtree func GetModelListInfo(module *YParserModule) []*YParserListInfo { var list []*YParserListInfo mod := (*C.struct_lys_module)(module) set := C.lys_find_path(mod, nil, - C.CString(fmt.Sprintf("/%s/*", C.GoString(mod.name)))) + C.CString(fmt.Sprintf("/%s/*", C.GoString(mod.name)))) - if (set == nil) { + if set == nil { return nil } @@ -861,12 +861,12 @@ func GetModelListInfo(module *YParserModule) []*YParserListInfo { //for each list for ; slist != nil; slist = (*C.struct_lys_node_list)(unsafe.Pointer(slist.next)) { var l YParserListInfo - listName := C.GoString(slist.name) + listName := C.GoString(slist.name) l.RedisTableName = C.GoString(snodec.name) tableName := listName - if (strings.HasSuffix(tableName, "_LIST")) { - tableName = tableName[0:len(tableName) - len("_LIST")] + if strings.HasSuffix(tableName, "_LIST") { + tableName = tableName[0 : len(tableName)-len("_LIST")] } l.ListName = tableName l.ModelName = C.GoString(mod.name) @@ -877,7 +877,7 @@ func GetModelListInfo(module *YParserModule) []*YParserListInfo { l.RedisKeyDelim = "|" //Default table size is -1 i.e. size limit l.RedisTableSize = -1 - if (slist.max > 0) { + if slist.max > 0 { l.RedisTableSize = int(slist.max) } @@ -896,33 +896,33 @@ func GetModelListInfo(module *YParserModule) []*YParserListInfo { } //Check for must expression - if (slist.must_size > 0) { + if slist.must_size > 0 { must := (*[10]C.struct_lys_restr)(unsafe.Pointer(slist.must)) - for idx := 0; idx < int(slist.must_size); idx++ { + for idx := 0; idx < int(slist.must_size); idx++ { exp := XpathExpression{Expr: C.GoString(must[idx].expr)} - if (must[idx].eapptag != nil) { + if must[idx].eapptag != nil { exp.ErrCode = C.GoString(must[idx].eapptag) } - if (must[idx].emsg != nil) { + if must[idx].emsg != nil { exp.ErrStr = strings.TrimPrefix(C.GoString(must[idx].emsg), customErrorPrefix) } l.XpathExpr[listName] = append(l.XpathExpr[listName], - &exp) + &exp) } } //Check for custom extension - if (slist.ext_size > 0) { + if slist.ext_size > 0 { exts := (*[10]*C.struct_lys_ext_instance)(unsafe.Pointer(slist.ext)) - for idx := 0; idx < int(slist.ext_size); idx++ { + for idx := 0; idx < int(slist.ext_size); idx++ { extName := C.GoString(exts[idx].def.name) argVal := C.GoString(exts[idx].arg_value) switch extName { case "custom-validation": - if (argVal != "") { + if argVal != "" { l.CustValidation[listName] = argVal } case "db-name": @@ -948,13 +948,12 @@ func GetModelListInfo(module *YParserModule) []*YParserListInfo { } getModelChildInfo(&l, - (*C.struct_lys_node)(unsafe.Pointer(slist)), false, nil) + (*C.struct_lys_node)(unsafe.Pointer(slist)), false, nil) list = append(list, &l) - }//each list inside a container - }//each container + } //each list inside a container + } //each container C.free(unsafe.Pointer(set)) return list } - diff --git a/cvl/jsondata_test.go b/cvl/jsondata_test.go index b0a7d3092..bf0036679 100644 --- a/cvl/jsondata_test.go +++ b/cvl/jsondata_test.go @@ -25,7 +25,7 @@ var json_edit_config_create_acl_table_dependent_data = []string{`{ }`} var json_edit_config_create_acl_rule_config_data = []string{ - `{ + `{ "PACKET_ACTION": "FORWARD", "IP_TYPE": "IPV4", "SRC_IP": "10.1.1.1/32", @@ -44,7 +44,7 @@ var json_validate_config_data = []string{`{ "Ethernet16|10.0.0.4/31": {} } }`, - `{ + `{ "DEVICE_METADATA": { "localhost": { "hwsku": "Force10-S6100", @@ -59,7 +59,7 @@ var json_validate_config_data = []string{`{ } } }`, - `{ + `{ "CABLE_LENGTH": { "AZURE": { "Ethernet8": "5m", diff --git a/cvl/tests/cfg_validator.go b/cvl/tests/cfg_validator.go index ab102439c..20694f7bd 100644 --- a/cvl/tests/cfg_validator.go +++ b/cvl/tests/cfg_validator.go @@ -21,14 +21,14 @@ package main import ( "fmt" + "github.com/Azure/sonic-mgmt-common/cvl" + "io/ioutil" "os" "time" - "io/ioutil" - "github.com/Azure/sonic-mgmt-common/cvl" ) func main() { - jsonData :=`{ + jsonData := `{ "VLAN": { "Vlan100": { "members": [ @@ -72,83 +72,83 @@ func main() { } }*/ -/*jsonData := `{ - "DEVICE_METADATA": { - "localhost": { - "hwsku": "Force10-S6100", - "default_bgp_status": "up", - "docker_routing_config_mode": "unified", - "hostname": "sonic-s6100-01", - "platform": "x86_64-dell_s6100_c2538-r0", - "mac": "4c:76:25:f4:70:82", - "default_pfcwd_status": "disable", - "deployment_id": "1", - "type": "ToRRouter" - } - } - }`*/ -/*jsonData := `{ - "DEVICE_NEIGHBOR": { - "ARISTA04T1": { - "mgmt_addr": "10.20.0.163", - "hwsku": "Arista", - "lo_addr": "2.2.2.2", - "local_port": "Ethernet124", - "type": "LeafRouter", - "port": "Ethernet68" - } - } - }`*/ -/*jsonData := `{ - "BGP_NEIGHBOR": { - "10.0.0.61": { - "local_addr": "10.0.0.60", - "asn": 64015, - "name": "ARISTA15T0" - } - } - }`*/ - -/* jsonData := `{ - "INTERFACE": { - "Ethernet68|10.0.0.0/31": {}, - "Ethernet24|10.0.0.2/31": {}, - "Ethernet112|10.0.0.4/31": {} - } + /*jsonData := `{ + "DEVICE_METADATA": { + "localhost": { + "hwsku": "Force10-S6100", + "default_bgp_status": "up", + "docker_routing_config_mode": "unified", + "hostname": "sonic-s6100-01", + "platform": "x86_64-dell_s6100_c2538-r0", + "mac": "4c:76:25:f4:70:82", + "default_pfcwd_status": "disable", + "deployment_id": "1", + "type": "ToRRouter" + } + } + }`*/ + /*jsonData := `{ + "DEVICE_NEIGHBOR": { + "ARISTA04T1": { + "mgmt_addr": "10.20.0.163", + "hwsku": "Arista", + "lo_addr": "2.2.2.2", + "local_port": "Ethernet124", + "type": "LeafRouter", + "port": "Ethernet68" + } + } + }`*/ + /*jsonData := `{ + "BGP_NEIGHBOR": { + "10.0.0.61": { + "local_addr": "10.0.0.60", + "asn": 64015, + "name": "ARISTA15T0" + } + } + }`*/ + + /* jsonData := `{ + "INTERFACE": { + "Ethernet68|10.0.0.0/31": {}, + "Ethernet24|10.0.0.2/31": {}, + "Ethernet112|10.0.0.4/31": {} + } + }`*/ + + /*jsonData := `{ + "INTERFACE": { + "Ethernet68|10.0.0.0/31": {}, + "Ethernet24|10.0.0.2/31": {}, + "Ethernet112|10.0.0.4/31": {} + } + }`*/ + /*jsonData := `{ + "PORTCHANNEL_INTERFACE": { + "PortChannel01|10.0.0.56/31": {}, + "PortChannel01|FC00::71/126": {}, + "PortChannel02|10.0.0.58/31": {}, + "PortChannel02|FC00::75/126": {} + } + + }`*/ + /*jsonData := `{ + "VLAN_INTERFACE": { + "Vlan1000|192.168.0.1/27": {} + } }`*/ - -/*jsonData := `{ - "INTERFACE": { - "Ethernet68|10.0.0.0/31": {}, - "Ethernet24|10.0.0.2/31": {}, - "Ethernet112|10.0.0.4/31": {} - } - }`*/ -/*jsonData := `{ - "PORTCHANNEL_INTERFACE": { - "PortChannel01|10.0.0.56/31": {}, - "PortChannel01|FC00::71/126": {}, - "PortChannel02|10.0.0.58/31": {}, - "PortChannel02|FC00::75/126": {} - } - - }`*/ -/*jsonData := `{ - "VLAN_INTERFACE": { - "Vlan1000|192.168.0.1/27": {} - } - }`*/ start := time.Now() dataFile := "" - if (len(os.Args) >= 2) { - if (os.Args[1] == "debug") { + if len(os.Args) >= 2 { + if os.Args[1] == "debug" { cvl.Debug(true) } else { - dataFile = os.Args[1] + dataFile = os.Args[1] } } - if (len(os.Args) == 3) { + if len(os.Args) == 3 { dataFile = os.Args[2] } @@ -161,21 +161,20 @@ func main() { jsonData = string(b) } - cv, ret := cvl.ValidationSessOpen() - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("NewDB: Could not create CVL session") return } err := cv.ValidateConfig(jsonData) - fmt.Printf("\nValidating data = %v\n\n", jsonData); + fmt.Printf("\nValidating data = %v\n\n", jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } keyData := make([]cvl.CVLEditConfigData, 4) @@ -183,8 +182,8 @@ func main() { keyData[0].VOp = cvl.OP_NONE keyData[0].Key = "ACL_TABLE|MyACL55_ACL_IPV4" keyData[0].Data = make(map[string]string) - keyData[0].Data["stage"] = "INGRESS" - keyData[0].Data["type"] = "l3" + keyData[0].Data["stage"] = "INGRESS" + keyData[0].Data["type"] = "l3" keyData[1].VType = cvl.VALIDATE_NONE keyData[1].VOp = cvl.OP_NONE @@ -199,14 +198,14 @@ func main() { keyData[2].VOp = cvl.OP_NONE keyData[2].Key = "ACL_TABLE|MyACL11_ACL_IPV4" keyData[2].Data = make(map[string]string) - keyData[2].Data["stage"] = "INGRESS" + keyData[2].Data["stage"] = "INGRESS" keyData[3].VType = cvl.VALIDATE_ALL keyData[3].VOp = cvl.OP_CREATE keyData[3].Key = "VLAN|Vlan901" keyData[3].Data = make(map[string]string) - keyData[3].Data["members"] = "Ethernet8" - keyData[3].Data["vlanid"] = "901" + keyData[3].Data["members"] = "Ethernet8" + keyData[3].Data["vlanid"] = "901" _, ret = cv.ValidateEditConfig(keyData) fmt.Printf("\n\n\n cvl.ValidateEditConfig() = %d\n", ret) @@ -216,8 +215,8 @@ func main() { keyData1[0].VOp = cvl.OP_NONE keyData1[0].Key = "ACL_TABLE|MyACL11_ACL_IPV4" keyData1[0].Data = make(map[string]string) - keyData1[0].Data["stage"] = "INGRESS" - keyData1[0].Data["type"] = "l3" + keyData1[0].Data["stage"] = "INGRESS" + keyData1[0].Data["type"] = "l3" keyData1[1].VType = cvl.VALIDATE_NONE keyData1[1].VOp = cvl.OP_NONE @@ -232,12 +231,11 @@ func main() { keyData1[2].VOp = cvl.OP_UPDATE keyData1[2].Key = "ACL_TABLE|MyACL33_ACL_IPV4" keyData1[2].Data = make(map[string]string) - keyData1[2].Data["stage"] = "INGRESS" + keyData1[2].Data["stage"] = "INGRESS" _, ret = cv.ValidateEditConfig(keyData) fmt.Printf("\n\n\n cvl.ValidateEditConfig() = %d\n", ret) - keyData2 := make([]cvl.CVLEditConfigData, 3) keyData2[0].VType = cvl.VALIDATE_ALL keyData2[0].VOp = cvl.OP_DELETE @@ -257,7 +255,6 @@ func main() { _, ret = cv.ValidateEditConfig(keyData) fmt.Printf("\n\n\n cvl.ValidateEditConfig() = %d\n", ret) - cvl.ValidationSessClose(cv) cvl.Finish() fmt.Printf("\n\n\n Time taken = %v\n", time.Since(start)) @@ -265,9 +262,8 @@ func main() { stopChan := make(chan int, 1) for { select { - case <- stopChan: + case <-stopChan: } } - } diff --git a/cvl/tests/cv_acl.go b/cvl/tests/cv_acl.go index 00637582a..ff073cc1d 100644 --- a/cvl/tests/cv_acl.go +++ b/cvl/tests/cv_acl.go @@ -21,11 +21,11 @@ package main import ( "fmt" - "time" - "os" "github.com/Azure/sonic-mgmt-common/cvl" "github.com/go-redis/redis" + "os" "strconv" + "time" ) func getConfigDbClient() *redis.Client { @@ -55,9 +55,9 @@ func unloadConfigDB(rclient *redis.Client, key string, data map[string]string) { /* Loads the Config DB based on JSON File. */ func loadConfigDB(rclient *redis.Client, key string, data map[string]string) { - dataTmp := make(map[string]interface{}) + dataTmp := make(map[string]interface{}) - for k, v := range data { + for k, v := range data { dataTmp[k] = v } @@ -75,30 +75,30 @@ func main() { cvl.Initialize() - if ((len(os.Args) > 1) && (os.Args[1] == "debug")) { + if (len(os.Args) > 1) && (os.Args[1] == "debug") { cvl.Debug(true) } rclient := getConfigDbClient() - if ((len(os.Args) > 1) && (os.Args[1] == "add")) { + if (len(os.Args) > 1) && (os.Args[1] == "add") { //Add ACL aclNoStart, _ := strconv.Atoi(os.Args[2]) aclNoEnd, _ := strconv.Atoi(os.Args[3]) - for aclNum:= aclNoStart ;aclNum <= aclNoEnd; aclNum++ { + for aclNum := aclNoStart; aclNum <= aclNoEnd; aclNum++ { aclNo := fmt.Sprintf("%d", aclNum) cvSess, _ := cvl.ValidationSessOpen() - cfgDataAclRule := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataAclRule := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, fmt.Sprintf("ACL_TABLE|TestACL%s", aclNo), - map[string]string { + map[string]string{ "stage": "INGRESS", - "type": "L3", + "type": "L3", //"ports@": "Ethernet0", }, }, @@ -106,7 +106,7 @@ func main() { _, ret := cvSess.ValidateEditConfig(cfgDataAclRule) - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") return } @@ -114,29 +114,29 @@ func main() { cfgDataAclRule[0].VType = cvl.VALIDATE_NONE //Create 7 ACL rules - for i:=0; i<7; i++ { - cfgDataAclRule = append(cfgDataAclRule, cvl.CVLEditConfigData { + for i := 0; i < 7; i++ { + cfgDataAclRule = append(cfgDataAclRule, cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, fmt.Sprintf("ACL_RULE|TestACL%s|Rule%d", aclNo, i+1), - map[string]string { - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IPV4", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": fmt.Sprintf("%d", 201 + i), - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", - "L4_DST_PORT": fmt.Sprintf("%d", 701 + i), + map[string]string{ + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPV4", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": fmt.Sprintf("%d", 201+i), + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", + "L4_DST_PORT": fmt.Sprintf("%d", 701+i), }, }) _, ret1 := cvSess.ValidateEditConfig(cfgDataAclRule) - if (ret1 != cvl.CVL_SUCCESS) { + if ret1 != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") return } - cfgDataAclRule[1 + i].VType = cvl.VALIDATE_NONE + cfgDataAclRule[1+i].VType = cvl.VALIDATE_NONE } //Write to DB @@ -148,29 +148,28 @@ func main() { } return - } else if ((len(os.Args) > 1) && (os.Args[1] == "del")) { + } else if (len(os.Args) > 1) && (os.Args[1] == "del") { aclNoStart, _ := strconv.Atoi(os.Args[2]) aclNoEnd, _ := strconv.Atoi(os.Args[3]) - for aclNum:= aclNoStart ;aclNum <= aclNoEnd; aclNum++ { + for aclNum := aclNoStart; aclNum <= aclNoEnd; aclNum++ { aclNo := fmt.Sprintf("%d", aclNum) - cvSess,_ := cvl.ValidationSessOpen() + cvSess, _ := cvl.ValidationSessOpen() //Delete ACL cfgDataAclRule := []cvl.CVLEditConfigData{} //Create 7 ACL rules - for i:=0; i<7; i++ { - cfgDataAclRule = append(cfgDataAclRule, cvl.CVLEditConfigData { + for i := 0; i < 7; i++ { + cfgDataAclRule = append(cfgDataAclRule, cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, fmt.Sprintf("ACL_RULE|TestACL%s|Rule%d", aclNo, i+1), - map[string]string { - }, + map[string]string{}, }) _, ret := cvSess.ValidateEditConfig(cfgDataAclRule) - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") return } @@ -178,16 +177,15 @@ func main() { cfgDataAclRule[i].VType = cvl.VALIDATE_NONE } - cfgDataAclRule = append(cfgDataAclRule, cvl.CVLEditConfigData { + cfgDataAclRule = append(cfgDataAclRule, cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, fmt.Sprintf("ACL_TABLE|TestACL%s", aclNo), - map[string]string { - }, + map[string]string{}, }) _, ret := cvSess.ValidateEditConfig(cfgDataAclRule) - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") return } @@ -204,14 +202,14 @@ func main() { } cv, ret := cvl.ValidationSessOpen() - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("Could not create CVL session") return } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL1": { "stage": "INGRESS", @@ -224,19 +222,19 @@ func main() { } }` - fmt.Printf("\nValidating data = %v\n\n", jsonData); + fmt.Printf("\nValidating data = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL2": { "stage": "EGRESS", @@ -245,20 +243,19 @@ func main() { } }` - - fmt.Printf("\nValidating data for external dependency check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for external dependency check = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL1": { "type": "L3" @@ -266,20 +263,19 @@ func main() { } }` - - fmt.Printf("\nValidating data for mandatory element misssing = %v\n\n", jsonData); + fmt.Printf("\nValidating data for mandatory element misssing = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL1": { "stage": "INGRESS", @@ -296,21 +292,19 @@ func main() { } }` - - - fmt.Printf("\nValidating data for internal dependency check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for internal dependency check = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL1": { "stage": "INGRESS", @@ -325,21 +319,19 @@ func main() { } }` - - - fmt.Printf("\nValidating data for mandatory element check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for mandatory element check = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL1": { "stage": "INGRESS", @@ -355,21 +347,19 @@ func main() { } }` - - - fmt.Printf("\nValidating data for mandatory element check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for mandatory element check = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL1": { "stage": "INGRESS", @@ -389,21 +379,19 @@ func main() { } }` - - - fmt.Printf("\nValidating data for pattern check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for pattern check = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "ACL_TABLE": { "TestACL1": { "stage": "INGRESS", @@ -422,16 +410,14 @@ func main() { } }` - - - fmt.Printf("\nValidating data for type check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for type check = %v\n\n", jsonData) err := cv.ValidateConfig(jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } diff --git a/cvl/tests/cv_edit_op.go b/cvl/tests/cv_edit_op.go index b77270941..2db8bac40 100644 --- a/cvl/tests/cv_edit_op.go +++ b/cvl/tests/cv_edit_op.go @@ -21,9 +21,9 @@ package main import ( "fmt" - "time" - "os" "github.com/Azure/sonic-mgmt-common/cvl" + "os" + "time" ) func main() { @@ -33,155 +33,153 @@ func main() { cvl.Initialize() cv, _ := cvl.ValidationSessOpen() - if ((len(os.Args) > 1) && (os.Args[1] == "debug")) { + if (len(os.Args) > 1) && (os.Args[1] == "debug") { cvl.Debug(true) } { count++ - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "ACL_TABLE|TestACL1", - map[string]string { + map[string]string{ "stage": "INGRESS", - "type": "L3", + "type": "L3", }, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "ACL_RULE|TestACL1|Rule1", - map[string]string { - "PACKET_ACTION": "FORWARD", - "SRC_IP": "10.1.1.1/32", - "L4_SRC_PORT": "1909", - "IP_PROTOCOL": "103", - "DST_IP": "20.2.2.2/32", + map[string]string{ + "PACKET_ACTION": "FORWARD", + "SRC_IP": "10.1.1.1/32", + "L4_SRC_PORT": "1909", + "IP_PROTOCOL": "103", + "DST_IP": "20.2.2.2/32", "L4_DST_PORT_RANGE": "9000-12000", }, }, } - fmt.Printf("\n\n%d. Validating create data = %v\n\n", count, cfgData); + fmt.Printf("\n\n%d. Validating create data = %v\n\n", count, cfgData) _, err := cv.ValidateEditConfig(cfgData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_UPDATE, "ACL_TABLE|MyACL11_ACL_IPV4", - map[string]string { + map[string]string{ "stage": "INGRESS", - "type": "MIRROR", + "type": "MIRROR", }, }, } - fmt.Printf("\n\n%d. Validating update data = %v\n\n", count, cfgData); + fmt.Printf("\n\n%d. Validating update data = %v\n\n", count, cfgData) _, err := cv.ValidateEditConfig(cfgData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "MIRROR_SESSION|everflow", - map[string]string { + map[string]string{ "src_ip": "10.1.0.32", "dst_ip": "2.2.2.2", }, }, } - fmt.Printf("\n\n%d. Validating create data = %v\n\n", count, cfgData); + fmt.Printf("\n\n%d. Validating create data = %v\n\n", count, cfgData) _, err := cv.ValidateEditConfig(cfgData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } count++ - cfgData = []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData = []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "MIRROR_SESSION|everflow", - map[string]string { + map[string]string{ "src_ip": "10.1.0.32", "dst_ip": "2.2.2.2", }, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_UPDATE, "ACL_RULE|MyACL11_ACL_IPV4|RULE_1", - map[string]string { + map[string]string{ "MIRROR_ACTION": "everflow", }, }, } - fmt.Printf("\n\n%d. Validating data for update = %v\n\n", count, cfgData); + fmt.Printf("\n\n%d. Validating data for update = %v\n\n", count, cfgData) _, err = cv.ValidateEditConfig(cfgData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - cfgData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "MIRROR_SESSION|everflow", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "ACL_RULE|MyACL11_ACL_IPV4|RULE_1", - map[string]string { - }, + map[string]string{}, }, } - fmt.Printf("\n\n%d. Validating data for delete = %v\n\n", count, cfgData); + fmt.Printf("\n\n%d. Validating data for delete = %v\n\n", count, cfgData) _, err := cv.ValidateEditConfig(cfgData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } diff --git a/cvl/tests/cv_vlan.go b/cvl/tests/cv_vlan.go index f69f41960..575326f91 100644 --- a/cvl/tests/cv_vlan.go +++ b/cvl/tests/cv_vlan.go @@ -19,14 +19,13 @@ package main - import ( "fmt" - "os" - "time" "github.com/Azure/sonic-mgmt-common/cvl" "github.com/go-redis/redis" + "os" "strconv" + "time" ) func getConfigDbClient() *redis.Client { @@ -56,9 +55,9 @@ func unloadConfigDB(rclient *redis.Client, key string, data map[string]string) { /* Loads the Config DB based on JSON File. */ func loadConfigDB(rclient *redis.Client, key string, data map[string]string) { - dataTmp := make(map[string]interface{}) + dataTmp := make(map[string]interface{}) - for k, v := range data { + for k, v := range data { dataTmp[k] = v } @@ -75,27 +74,27 @@ func main() { count := 0 cvl.Initialize() - if ((len(os.Args) > 1) && (os.Args[1] == "debug")) { + if (len(os.Args) > 1) && (os.Args[1] == "debug") { cvl.Debug(true) } rclient := getConfigDbClient() - if ((len(os.Args) > 1) && (os.Args[1] == "add")) { + if (len(os.Args) > 1) && (os.Args[1] == "add") { //Add ACL vlanNoStart, _ := strconv.Atoi(os.Args[2]) vlanNoEnd, _ := strconv.Atoi(os.Args[3]) - for vlanNum:= vlanNoStart ;vlanNum <= vlanNoEnd; vlanNum++ { + for vlanNum := vlanNoStart; vlanNum <= vlanNoEnd; vlanNum++ { cvSess, _ := cvl.ValidationSessOpen() - cfgDataVlan := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + cfgDataVlan := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, fmt.Sprintf("VLAN|Vlan%d", vlanNum), - map[string]string { - "vlanid": fmt.Sprintf("%d", vlanNum), + map[string]string{ + "vlanid": fmt.Sprintf("%d", vlanNum), "members@": "Ethernet0,Ethernet4,Ethernet8,Ethernet12,Ethernet16,Ethernet20,Ethernet24,Ethernet28", }, }, @@ -103,30 +102,30 @@ func main() { _, ret := cvSess.ValidateEditConfig(cfgDataVlan) - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") return } cfgDataVlan[0].VType = cvl.VALIDATE_NONE - for i:=0; i<7; i++ { - cfgDataVlan = append(cfgDataVlan, cvl.CVLEditConfigData { + for i := 0; i < 7; i++ { + cfgDataVlan = append(cfgDataVlan, cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, - fmt.Sprintf("VLAN_MEMBER|Vlan%d|Ethernet%d", vlanNum, i * 4), - map[string]string { - "tagging_mode" : "tagged", + fmt.Sprintf("VLAN_MEMBER|Vlan%d|Ethernet%d", vlanNum, i*4), + map[string]string{ + "tagging_mode": "tagged", }, }) _, ret1 := cvSess.ValidateEditConfig(cfgDataVlan) - if (ret1 != cvl.CVL_SUCCESS) { + if ret1 != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") return } - cfgDataVlan[1 + i].VType = cvl.VALIDATE_NONE + cfgDataVlan[1+i].VType = cvl.VALIDATE_NONE } //Write to DB @@ -138,28 +137,27 @@ func main() { } return - } else if ((len(os.Args) > 1) && (os.Args[1] == "del")) { + } else if (len(os.Args) > 1) && (os.Args[1] == "del") { vlanNoStart, _ := strconv.Atoi(os.Args[2]) vlanNoEnd, _ := strconv.Atoi(os.Args[3]) - for vlanNum:= vlanNoStart ;vlanNum <= vlanNoEnd; vlanNum++ { - cvSess,_ := cvl.ValidationSessOpen() + for vlanNum := vlanNoStart; vlanNum <= vlanNoEnd; vlanNum++ { + cvSess, _ := cvl.ValidationSessOpen() //Delete ACL cfgDataVlan := []cvl.CVLEditConfigData{} //Create 7 ACL rules - for i:=0; i<7; i++ { - cfgDataVlan = append(cfgDataVlan, cvl.CVLEditConfigData { + for i := 0; i < 7; i++ { + cfgDataVlan = append(cfgDataVlan, cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, - fmt.Sprintf("VLAN_MEMBER|Vlan%d|Ethernet%d", vlanNum, i * 4), - map[string]string { - }, + fmt.Sprintf("VLAN_MEMBER|Vlan%d|Ethernet%d", vlanNum, i*4), + map[string]string{}, }) _, ret := cvSess.ValidateEditConfig(cfgDataVlan) - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") //return } @@ -167,16 +165,15 @@ func main() { cfgDataVlan[i].VType = cvl.VALIDATE_NONE } - cfgDataVlan = append(cfgDataVlan, cvl.CVLEditConfigData { + cfgDataVlan = append(cfgDataVlan, cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, fmt.Sprintf("VLAN|Vlan%d", vlanNum), - map[string]string { - }, + map[string]string{}, }) _, ret := cvSess.ValidateEditConfig(cfgDataVlan) - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("Validation failure\n") //return } @@ -191,97 +188,92 @@ func main() { return } cv, ret := cvl.ValidationSessOpen() - if (ret != cvl.CVL_SUCCESS) { + if ret != cvl.CVL_SUCCESS { fmt.Printf("NewDB: Could not create CVL session") return } { count++ - keyData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + keyData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "PORTCHANNEL|ch1", - map[string]string { + map[string]string{ "admin_status": "up", - "mtu": "9100", + "mtu": "9100", }, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "PORTCHANNEL|ch2", - map[string]string { + map[string]string{ "admin_status": "up", - "mtu": "9100", + "mtu": "9100", }, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "PORTCHANNEL_MEMBER|ch1|Ethernet4", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "PORTCHANNEL_MEMBER|ch1|Ethernet8", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "PORTCHANNEL_MEMBER|ch2|Ethernet12", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "PORTCHANNEL_MEMBER|ch2|Ethernet16", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_NONE, cvl.OP_NONE, "PORTCHANNEL_MEMBER|ch2|Ethernet20", - map[string]string { - }, + map[string]string{}, }, - cvl.CVLEditConfigData { + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_CREATE, "VLAN|Vlan1001", - map[string]string { - "vlanid": "1001", + map[string]string{ + "vlanid": "1001", "members@": "Ethernet24,ch1,Ethernet8", }, }, } - fmt.Printf("\nValidating data for must = %v\n\n", keyData); + fmt.Printf("\nValidating data for must = %v\n\n", keyData) _, err := cv.ValidateEditConfig(keyData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { - keyData := []cvl.CVLEditConfigData { - cvl.CVLEditConfigData { + keyData := []cvl.CVLEditConfigData{ + cvl.CVLEditConfigData{ cvl.VALIDATE_ALL, cvl.OP_DELETE, "ACL_TABLE|MyACL1_ACL_IPV4", - map[string]string { + map[string]string{ "type": "L3", }, }, @@ -289,19 +281,19 @@ func main() { _, err := cv.ValidateEditConfig(keyData) - fmt.Printf("\nValidating field delete...\n\n"); + fmt.Printf("\nValidating field delete...\n\n") - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "VLAN": { "Vlan100": { "members": [ @@ -313,21 +305,20 @@ func main() { } }` - err := cv.ValidateConfig(jsonData) - fmt.Printf("\nValidating data = %v\n\n", jsonData); + fmt.Printf("\nValidating data = %v\n\n", jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "VLAN": { "Vln100": { "members": [ @@ -339,21 +330,20 @@ func main() { } }` - err := cv.ValidateConfig(jsonData) - fmt.Printf("\nValidating data for key syntax = %v\n\n", jsonData); + fmt.Printf("\nValidating data for key syntax = %v\n\n", jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "VLAN": { "Vlan4096": { "members": [ @@ -365,20 +355,19 @@ func main() { } }` - err := cv.ValidateConfig(jsonData) - fmt.Printf("\nValidating data for range check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for range check = %v\n\n", jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { count++ - jsonData :=`{ + jsonData := `{ "VLAN": { "Vlan201": { "members": [ @@ -390,15 +379,14 @@ func main() { } }` - err := cv.ValidateConfig(jsonData) - fmt.Printf("\nValidating data for internal dependency check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for internal dependency check = %v\n\n", jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } { @@ -421,7 +409,7 @@ func main() { } } }`*/ - jsonData :=`{ + jsonData := `{ "VLAN": { "Vlan4095": { "vlanid": "4995" @@ -431,12 +419,12 @@ func main() { err := cv.ValidateConfig(jsonData) - fmt.Printf("\nValidating data for external dependency check = %v\n\n", jsonData); + fmt.Printf("\nValidating data for external dependency check = %v\n\n", jsonData) - if (err == cvl.CVL_SUCCESS) { - fmt.Printf("\nConfig Validation succeeded.\n\n"); + if err == cvl.CVL_SUCCESS { + fmt.Printf("\nConfig Validation succeeded.\n\n") } else { - fmt.Printf("\nConfig Validation failed.\n\n"); + fmt.Printf("\nConfig Validation failed.\n\n") } } diff --git a/translib/api_tests_app.go b/translib/api_tests_app.go index 8c7525f2a..c9003c4b5 100644 --- a/translib/api_tests_app.go +++ b/translib/api_tests_app.go @@ -137,8 +137,8 @@ func (app *apiTests) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) ( resp["message"] = app.echoMsg resp["path"] = app.path resp["depth"] = app.depth - resp["content"] = app.content - resp["fields"] = app.fields + resp["content"] = app.content + resp["fields"] = app.fields gr.Payload, err = json.Marshal(&resp) return gr, err diff --git a/translib/app_interface.go b/translib/app_interface.go index 225332bc1..ba09c3b7f 100644 --- a/translib/app_interface.go +++ b/translib/app_interface.go @@ -60,20 +60,20 @@ type appData struct { // These include RESTCONF query parameters like - depth, fields etc. type appOptions struct { - // depth limits subtree levels in the response data. - // 0 indicates unlimited depth. - // Valid for GET API only. - depth uint - - // content query parameter value receved from the URI - // possible value is one of 'config', 'nonconfig','all','state' or 'operational' - // Valid for GET API only. - content string - - //fields query parameters - // paths of the fields that needs to be filtered in GET payload response - // Valid for GET API only. - fields []string + // depth limits subtree levels in the response data. + // 0 indicates unlimited depth. + // Valid for GET API only. + depth uint + + // content query parameter value receved from the URI + // possible value is one of 'config', 'nonconfig','all','state' or 'operational' + // Valid for GET API only. + content string + + //fields query parameters + // paths of the fields that needs to be filtered in GET payload response + // Valid for GET API only. + fields []string // deleteEmptyEntry indicates if the db entry should be deleted upon // deletion of last field. This is a non standard option. diff --git a/translib/db/db.go b/translib/db/db.go index 03467faa2..dfa0816e2 100644 --- a/translib/db/db.go +++ b/translib/db/db.go @@ -25,82 +25,79 @@ code written in python using that SDK to Go Language. Example: - * Initialization: + - Initialization: - d, _ := db.NewDB(db.Options { - DBNo : db.ConfigDB, - InitIndicator : "CONFIG_DB_INITIALIZED", - TableNameSeparator: "|", - KeySeparator : "|", - }) + d, _ := db.NewDB(db.Options { + DBNo : db.ConfigDB, + InitIndicator : "CONFIG_DB_INITIALIZED", + TableNameSeparator: "|", + KeySeparator : "|", + }) - * Close: + - Close: - d.DeleteDB() + d.DeleteDB() + - No-Transaction SetEntry - * No-Transaction SetEntry + tsa := db.TableSpec { Name: "ACL_TABLE" } + tsr := db.TableSpec { Name: "ACL_RULE" } - tsa := db.TableSpec { Name: "ACL_TABLE" } - tsr := db.TableSpec { Name: "ACL_RULE" } + ca := make([]string, 1, 1) - ca := make([]string, 1, 1) + ca[0] = "MyACL1_ACL_IPV4" + akey := db.Key { Comp: ca} + avalue := db.Value {map[string]string {"ports":"eth0","type":"mirror" }} - ca[0] = "MyACL1_ACL_IPV4" - akey := db.Key { Comp: ca} - avalue := db.Value {map[string]string {"ports":"eth0","type":"mirror" }} + d.SetEntry(&tsa, akey, avalue) - d.SetEntry(&tsa, akey, avalue) + - GetEntry - * GetEntry + avalue, _ := d.GetEntry(&tsa, akey) - avalue, _ := d.GetEntry(&tsa, akey) + - GetKeys - * GetKeys + keys, _ := d.GetKeys(&tsa); - keys, _ := d.GetKeys(&tsa); + - GetKeysPattern - * GetKeysPattern + keys, _ := d.GetKeys(&tsa, akeyPattern); - keys, _ := d.GetKeys(&tsa, akeyPattern); + - No-Transaction DeleteEntry - * No-Transaction DeleteEntry + d.DeleteEntry(&tsa, akey) - d.DeleteEntry(&tsa, akey) + - GetTable - * GetTable + ta, _ := d.GetTable(&tsa) - ta, _ := d.GetTable(&tsa) + - No-Transaction DeleteTable - * No-Transaction DeleteTable + d.DeleteTable(&ts) - d.DeleteTable(&ts) + - Transaction - * Transaction + rkey := db.Key { Comp: []string { "MyACL2_ACL_IPV4", "RULE_1" }} + rvalue := db.Value { Field: map[string]string { + "priority" : "0", + "packet_action" : "eth1", + }, + } - rkey := db.Key { Comp: []string { "MyACL2_ACL_IPV4", "RULE_1" }} - rvalue := db.Value { Field: map[string]string { - "priority" : "0", - "packet_action" : "eth1", - }, - } + d.StartTx([]db.WatchKeys { {Ts: &tsr, Key: &rkey} }, + []*db.TableSpec { &tsa, &tsr }) - d.StartTx([]db.WatchKeys { {Ts: &tsr, Key: &rkey} }, - []*db.TableSpec { &tsa, &tsr }) + d.SetEntry( &tsa, akey, avalue) + d.SetEntry( &tsr, rkey, rvalue) - d.SetEntry( &tsa, akey, avalue) - d.SetEntry( &tsr, rkey, rvalue) - - e := d.CommitTx() - - * Transaction Abort - - d.StartTx([]db.WatchKeys {}, - []*db.TableSpec { &tsa, &tsr }) - d.DeleteEntry( &tsa, rkey) - d.AbortTx() + e := d.CommitTx() + - Transaction Abort + d.StartTx([]db.WatchKeys {}, + []*db.TableSpec { &tsa, &tsr }) + d.DeleteEntry( &tsa, rkey) + d.AbortTx() */ package db @@ -114,9 +111,9 @@ import ( "time" "github.com/Azure/sonic-mgmt-common/cvl" + "github.com/Azure/sonic-mgmt-common/translib/tlerr" "github.com/go-redis/redis/v7" "github.com/golang/glog" - "github.com/Azure/sonic-mgmt-common/translib/tlerr" ) const ( @@ -215,7 +212,7 @@ type TableSpec struct { // can have TableSeparator as part of the key. Otherwise, we cannot // tell where the key component begins. CompCt int - // NoDelete flag (if it is set to true) is to skip the row entry deletion from + // NoDelete flag (if it is set to true) is to skip the row entry deletion from // the table when the "SetEntry" or "ModEntry" method is called with empty Value Field map. NoDelete bool } @@ -261,8 +258,8 @@ type DB struct { onCReg dbOnChangeReg // holds OnChange enabled table names // dbCache is used by both PerConnection cache, and OnChange cache // On a DB handle, the two are mutually exclusive. - cache dbCache - stats DBStats + cache dbCache + stats DBStats dbStatsConfig DBStatsConfig dbCacheConfig DBCacheConfig @@ -285,7 +282,7 @@ func (dbNo DBNum) Name() string { return (getDBInstName(dbNo)) } -func getDBInstName (dbNo DBNum) string { +func getDBInstName(dbNo DBNum) string { switch dbNo { case ApplDB: return "APPL_DB" @@ -550,13 +547,13 @@ func (d *DB) getEntry(ts *TableSpec, key Key, forceReadDB bool) (Value, error) { var ok bool entry := d.key2redis(ts, key) useCache := ((d.Opts.IsOnChangeEnabled && d.onCReg.isCacheTable(ts.Name)) || - (d.dbCacheConfig.PerConnection && - d.dbCacheConfig.isCacheTable(ts.Name))) + (d.dbCacheConfig.PerConnection && + d.dbCacheConfig.isCacheTable(ts.Name))) // check in Tx cache first if value, ok = d.txTsEntryMap[ts.Name][entry]; !ok { // If cache GetFromCache (CacheHit?) - if (useCache && !forceReadDB) { + if useCache && !forceReadDB { if table, ok = d.cache.Tables[ts.Name]; ok { if value, ok = table.entry[entry]; ok { value = value.Copy() @@ -598,11 +595,11 @@ func (d *DB) getEntry(ts *TableSpec, key Key, forceReadDB bool) (Value, error) { d.cache.Tables = make(map[string]Table, d.onCReg.size()) } d.cache.Tables[ts.Name] = Table{ - ts: ts, - entry: make(map[string]Value), + ts: ts, + entry: make(map[string]Value), complete: false, patterns: make(map[string][]Key), - db: d, + db: d, } } d.cache.Tables[ts.Name].entry[entry] = value.Copy() @@ -1207,7 +1204,7 @@ func (d *DB) RunScript(script *redis.Script, keys []string, args ...interface{}) return nil } - return script.Run(d.client, keys, args...) + return script.Run(d.client, keys, args...) } // DeleteEntry deletes an entry(row) in the table. @@ -1258,7 +1255,7 @@ func (d *DB) ModEntry(ts *TableSpec, key Key, value Value) error { glog.Info("ModEntry: Mapping to DeleteEntry()") } e = d.DeleteEntry(ts, key) - } + } goto ModEntryExit } @@ -1677,7 +1674,7 @@ func (d *DB) AbortTx() error { e = errors.New("Cannot issue UNWATCH in txStateMultiExec") default: glog.Error("AbortTx: Unknown, txState: ", d.txState) - e = errors.New("Unknown State: " + string(rune(d.txState))) + e = errors.New("Unknown State: " + string(rune(d.txState))) } if e != nil { diff --git a/translib/db/db_table_pattern_test.go b/translib/db/db_table_pattern_test.go index facef0242..175d6a73d 100644 --- a/translib/db/db_table_pattern_test.go +++ b/translib/db/db_table_pattern_test.go @@ -123,8 +123,8 @@ func TestGetTablePatternCompOrigEmpty(t *testing.T) { func TestGetTablePattern_txCache(t *testing.T) { d := newTestDB(t, Options{ - DBNo: ConfigDB, - DisableCVLCheck: true, + DBNo: ConfigDB, + DisableCVLCheck: true, }) setupTestData(t, d.client, map[string]map[string]interface{}{ "TEST_INTERFACE|Ethernet0": {"vrf": "Vrf1"}, diff --git a/translib/db/subscribe.go b/translib/db/subscribe.go index e66cdaaa8..663738b29 100644 --- a/translib/db/subscribe.go +++ b/translib/db/subscribe.go @@ -38,43 +38,40 @@ import ( // SKey is (TableSpec, Key, []SEvent) 3-tuples to be watched in a Transaction. type SKey struct { - Ts *TableSpec - Key *Key - SEMap map[SEvent]bool // nil map indicates subscribe to all - Opaque interface{} // opaque data set by the caller + Ts *TableSpec + Key *Key + SEMap map[SEvent]bool // nil map indicates subscribe to all + Opaque interface{} // opaque data set by the caller } type SEvent int const ( - SEventNone SEvent = iota // No Op - SEventHSet // HSET, HMSET, and its variants - SEventHDel // HDEL, also SEventDel generated, if HASH is becomes empty - SEventDel // DEL, & also if key gets deleted (empty HASH, expire,..) - SEventOther // Some other command not covered above. + SEventNone SEvent = iota // No Op + SEventHSet // HSET, HMSET, and its variants + SEventHDel // HDEL, also SEventDel generated, if HASH is becomes empty + SEventDel // DEL, & also if key gets deleted (empty HASH, expire,..) + SEventOther // Some other command not covered above. // The below two are always sent regardless of SEMap. - SEventClose // Close requested due to Unsubscribe() called. - SEventErr // Error condition. Call Unsubscribe, after return. + SEventClose // Close requested due to Unsubscribe() called. + SEventErr // Error condition. Call Unsubscribe, after return. ) -var redisPayload2sEventMap map[string]SEvent = map[string]SEvent { - "" : SEventNone, - "hset" : SEventHSet, - "hdel" : SEventHDel, - "del" : SEventDel, +var redisPayload2sEventMap map[string]SEvent = map[string]SEvent{ + "": SEventNone, + "hset": SEventHSet, + "hdel": SEventHDel, + "del": SEventDel, } - func init() { - // Optimization: Start the goroutine that is scanning the SubscribeDB - // channels. Instead of one goroutine per Subscribe. + // Optimization: Start the goroutine that is scanning the SubscribeDB + // channels. Instead of one goroutine per Subscribe. } - // HFunc gives the name of the table, and other per-table customizations. -type HFunc func( *DB, *SKey, *Key, SEvent) (error) - +type HFunc func(*DB, *SKey, *Key, SEvent) error // SubscribeDB is the factory method to create a subscription to the DB. // The returned instance can only be used for Subscription. @@ -90,7 +87,7 @@ func SubscribeDB(opt Options, skeys []*SKey, handler HFunc) (*DB, error) { var s string // NewDB - d , e := NewDB(opt) + d, e := NewDB(opt) if d.client == nil { goto SubscribeDBExit @@ -105,10 +102,10 @@ func SubscribeDB(opt Options, skeys []*SKey, handler HFunc) (*DB, error) { goto SubscribeDBExit } - for i := 0 ; i < len(skeys); i++ { + for i := 0; i < len(skeys); i++ { pattern := d.key2redisChannel(skeys[i].Ts, *(skeys[i].Key)) - if _,present := patMap[pattern] ; ! present { - patMap[pattern] = make([]int, 0, 5) + if _, present := patMap[pattern]; !present { + patMap[pattern] = make([]int, 0, 5) patterns = append(patterns, pattern) } patMap[pattern] = append(patMap[pattern], i) @@ -121,7 +118,7 @@ func SubscribeDB(opt Options, skeys []*SKey, handler HFunc) (*DB, error) { if d.sPubSub == nil { glog.Error("SubscribeDB: PSubscribe() nil: pats: ", patterns) - e = tlerr.TranslibDBSubscribeFail { } + e = tlerr.TranslibDBSubscribeFail{} goto SubscribeDBExit } @@ -130,11 +127,10 @@ func SubscribeDB(opt Options, skeys []*SKey, handler HFunc) (*DB, error) { if e != nil { glog.Error("SubscribeDB: Receive() fails: e: ", e) - e = tlerr.TranslibDBSubscribeFail { } + e = tlerr.TranslibDBSubscribeFail{} goto SubscribeDBExit } - // Start a goroutine to read messages and call handler. go func() { for msg := range d.sPubSub.Channel() { @@ -167,9 +163,8 @@ func SubscribeDB(opt Options, skeys []*SKey, handler HFunc) (*DB, error) { sEvent = SEventErr } glog.Info("SubscribeDB: SEventClose|Err: ", sEvent) - handler(d, & SKey{}, & Key {}, sEvent) - } () - + handler(d, &SKey{}, &Key{}, sEvent) + }() SubscribeDBExit: @@ -193,7 +188,7 @@ SubscribeDBExit: } // UnsubscribeDB is used to close a DB subscription -func (d * DB) UnsubscribeDB() error { +func (d *DB) UnsubscribeDB() error { var e error = nil @@ -208,7 +203,7 @@ func (d * DB) UnsubscribeDB() error { } // Mark close in progress. - d.sCIP = true; + d.sCIP = true // Do the close, ch gets closed too. d.sPubSub.Close() @@ -228,11 +223,10 @@ UnsubscribeDBExit: return e } - func (d *DB) key2redisChannel(ts *TableSpec, key Key) string { if glog.V(5) { - glog.Info("key2redisChannel: ", *ts, " key: " + key.String()) + glog.Info("key2redisChannel: ", *ts, " key: "+key.String()) } return "__keyspace@" + (d.Opts.DBNo).String() + "__:" + d.key2redis(ts, key) @@ -241,7 +235,7 @@ func (d *DB) key2redisChannel(ts *TableSpec, key Key) string { func (d *DB) redisChannel2key(ts *TableSpec, redisChannel string) Key { if glog.V(5) { - glog.Info("redisChannel2key: ", *ts, " redisChannel: " + redisChannel) + glog.Info("redisChannel2key: ", *ts, " redisChannel: "+redisChannel) } splitRedisKey := strings.SplitN(redisChannel, ":", 2) @@ -271,6 +265,5 @@ func (d *DB) redisPayload2sEvent(redisPayload string) SEvent { glog.Info("redisPayload2sEvent: ", sEvent) } - return sEvent + return sEvent } - diff --git a/translib/db/test/arloIssue29.go b/translib/db/test/arloIssue29.go index eb6dadc03..83ad671cb 100644 --- a/translib/db/test/arloIssue29.go +++ b/translib/db/test/arloIssue29.go @@ -28,8 +28,8 @@ import ( "fmt" // "errors" "flag" - "github.com/golang/glog" "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/golang/glog" // "time" // "github.com/Azure/sonic-mgmt-common/translib/tlerr" ) @@ -45,25 +45,25 @@ func main() { fmt.Println("https://github.com/project-arlo/sonic-mgmt-framework/issues/29") fmt.Println("Creating the DB ==============") - d,_ := db.NewDB(db.Options { - DBNo : db.ApplDB, - InitIndicator : "", - TableNameSeparator: ":", - KeySeparator : ":", - }) + d, _ := db.NewDB(db.Options{ + DBNo: db.ApplDB, + InitIndicator: "", + TableNameSeparator: ":", + KeySeparator: ":", + }) - tsi := db.TableSpec { Name: "INTF_TABLE", CompCt: 2 } + tsi := db.TableSpec{Name: "INTF_TABLE", CompCt: 2} ca := make([]string, 2, 2) fmt.Println("Testing SetEntry ==============") ca[0] = "Ethernet20" ca[1] = "a::b/64" - akey = db.Key { Comp: ca} - avalue = db.Value { Field: map[string]string { - "scope" : "global", - "family" : "IPv4", - } } + akey = db.Key{Comp: ca} + avalue = db.Value{Field: map[string]string{ + "scope": "global", + "family": "IPv4", + }} e = d.SetEntry(&tsi, akey, avalue) if e != nil { diff --git a/translib/db/test/testdb.go b/translib/db/test/testdb.go index fbc050799..030ba275c 100644 --- a/translib/db/test/testdb.go +++ b/translib/db/test/testdb.go @@ -23,15 +23,15 @@ import ( "fmt" // "errors" "flag" - "github.com/golang/glog" "github.com/Azure/sonic-mgmt-common/translib/db" - "time" "github.com/Azure/sonic-mgmt-common/translib/tlerr" + "github.com/golang/glog" + "time" ) func main() { - var avalue,rvalue db.Value - var akey,rkey db.Key + var avalue, rvalue db.Value + var akey, rkey db.Key var e error defer glog.Flush() @@ -39,54 +39,53 @@ func main() { flag.Parse() fmt.Println("Creating the DB ==============") - d,_ := db.NewDB(db.Options { - DBNo : db.ConfigDB, - InitIndicator : "CONFIG_DB_INITIALIZED", - TableNameSeparator: "|", - KeySeparator : "|", - }) + d, _ := db.NewDB(db.Options{ + DBNo: db.ConfigDB, + InitIndicator: "CONFIG_DB_INITIALIZED", + TableNameSeparator: "|", + KeySeparator: "|", + }) -// fmt.Println("key: CONFIG_DB_INITIALIZED value: ", -// d.Client.Get("CONFIG_DB_INITIALIZED").String()) + // fmt.Println("key: CONFIG_DB_INITIALIZED value: ", + // d.Client.Get("CONFIG_DB_INITIALIZED").String()) - tsa := db.TableSpec { Name: "ACL_TABLE" } - tsr := db.TableSpec { Name: "ACL_RULE" } + tsa := db.TableSpec{Name: "ACL_TABLE"} + tsr := db.TableSpec{Name: "ACL_RULE"} ca := make([]string, 1, 1) fmt.Println("Testing GetEntry error ==============") ca[0] = "MyACL1_ACL_IPVNOTEXIST" - akey = db.Key { Comp: ca} + akey = db.Key{Comp: ca} avalue, e = d.GetEntry(&tsa, akey) fmt.Println("ts: ", tsa, " ", akey, ": ", avalue, " error: ", e) - if _, ok := e.(tlerr.TranslibRedisClientEntryNotExist) ; ok { - fmt.Println("Type is TranslibRedisClientEntryNotExist") + if _, ok := e.(tlerr.TranslibRedisClientEntryNotExist); ok { + fmt.Println("Type is TranslibRedisClientEntryNotExist") } - fmt.Println("Testing NoTransaction SetEntry ==============") ca[0] = "MyACL1_ACL_IPV4" - akey = db.Key { Comp: ca} - avalue = db.Value { map[string]string {"ports@":"Ethernet0","type":"MIRROR" }} + akey = db.Key{Comp: ca} + avalue = db.Value{map[string]string{"ports@": "Ethernet0", "type": "MIRROR"}} - d.SetEntry(&tsa, akey, avalue) + d.SetEntry(&tsa, akey, avalue) fmt.Println("Testing GetEntry ==============") avalue, _ = d.GetEntry(&tsa, akey) fmt.Println("ts: ", tsa, " ", akey, ": ", avalue) fmt.Println("Testing GetKeys ==============") - keys, _ := d.GetKeys(&tsa); + keys, _ := d.GetKeys(&tsa) fmt.Println("ts: ", tsa, " keys: ", keys) fmt.Println("Testing GetKeys ==============") - keys, _ := d.GetKeysPattern(&tsa, akey); + keys, _ := d.GetKeysPattern(&tsa, akey) fmt.Println("ts: ", tsa, " keys: ", keys) fmt.Println("Testing NoTransaction DeleteEntry ==============") - akey = db.Key { Comp: ca} + akey = db.Key{Comp: ca} - d.DeleteEntry(&tsa, akey) + d.DeleteEntry(&tsa, akey) avalue, e = d.GetEntry(&tsa, akey) if e == nil { @@ -95,11 +94,11 @@ func main() { fmt.Println("Testing 2 more ACLs ==============") ca[0] = "MyACL2_ACL_IPV4" - avalue = db.Value { map[string]string {"ports@":"Ethernet0","type":"MIRROR" }} - d.SetEntry(&tsa, akey, avalue) + avalue = db.Value{map[string]string{"ports@": "Ethernet0", "type": "MIRROR"}} + d.SetEntry(&tsa, akey, avalue) ca[0] = "MyACL3_ACL_IPV4" - d.SetEntry(&tsa, akey, avalue) + d.SetEntry(&tsa, akey, avalue) ta, _ := d.GetTable(&tsa) fmt.Println("ts: ", tsa, " table: ", ta) @@ -108,49 +107,47 @@ func main() { fmt.Println("ts: ", tsr, " table: ", tr) fmt.Println("Testing Transaction =================") - rkey = db.Key { Comp: []string { "MyACL2_ACL_IPV4", "RULE_1" }} - rvalue = db.Value { Field: map[string]string { - "priority" : "0", - "packet_action" : "DROP", - }, - } + rkey = db.Key{Comp: []string{"MyACL2_ACL_IPV4", "RULE_1"}} + rvalue = db.Value{Field: map[string]string{ + "priority": "0", + "packet_action": "DROP", + }, + } -// d.StartTx([]db.WatchKeys { {Ts: &tsr, Key: &rkey} }) - d.StartTx([]db.WatchKeys {{Ts: &tsr, Key: &rkey} }, - []*db.TableSpec { &tsr, &tsa}) + // d.StartTx([]db.WatchKeys { {Ts: &tsr, Key: &rkey} }) + d.StartTx([]db.WatchKeys{{Ts: &tsr, Key: &rkey}}, + []*db.TableSpec{&tsr, &tsa}) fmt.Println("Sleeping 5...") time.Sleep(5 * time.Second) - d.SetEntry( &tsr, rkey, rvalue) + d.SetEntry(&tsr, rkey, rvalue) e = d.CommitTx() if e != nil { fmt.Println("Transaction Failed ======= e: ", e) } - fmt.Println("Testing AbortTx =================") -// d.StartTx([]db.WatchKeys { {Ts: &tsr, Key: &rkey} }) - d.StartTx([]db.WatchKeys {}, []*db.TableSpec { &tsr, &tsa}) - d.DeleteEntry( &tsa, rkey) + // d.StartTx([]db.WatchKeys { {Ts: &tsr, Key: &rkey} }) + d.StartTx([]db.WatchKeys{}, []*db.TableSpec{&tsr, &tsa}) + d.DeleteEntry(&tsa, rkey) d.AbortTx() avalue, e = d.GetEntry(&tsr, rkey) fmt.Println("ts: ", tsr, " ", akey, ": ", avalue) fmt.Println("Testing DeleteKeys =================") - d.DeleteKeys(&tsr, db.Key { Comp: []string {"ToBeDeletedACLs*"} }) + d.DeleteKeys(&tsr, db.Key{Comp: []string{"ToBeDeletedACLs*"}}) fmt.Println("Testing GetTable") tr, _ = d.GetTable(&tsr) fmt.Println("ts: ", tsr, " table: ", tr) - -// d.DeleteTable(&ts) + // d.DeleteTable(&ts) fmt.Println("Testing Tables2TableSpecs =================") var tables []string - tables = []string { "ACL_TABLE", "ACL_RULE" } + tables = []string{"ACL_TABLE", "ACL_RULE"} fmt.Println("Tables: ", tables) fmt.Println("TableSpecs: ") for _, tsi := range db.Tables2TableSpecs(tables) { @@ -158,10 +155,9 @@ func main() { } fmt.Println("Empty TableSpecs: ") - for _, tsi := range db.Tables2TableSpecs([]string { } ) { + for _, tsi := range db.Tables2TableSpecs([]string{}) { fmt.Println(" ", *tsi) } - d.DeleteDB() } diff --git a/translib/db/test/testmap.go b/translib/db/test/testmap.go index 78a22bcc3..a60ac96d4 100644 --- a/translib/db/test/testmap.go +++ b/translib/db/test/testmap.go @@ -23,34 +23,32 @@ import ( "fmt" // "errors" "flag" - "github.com/golang/glog" "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/golang/glog" // "time" // "github.com/Azure/sonic-mgmt-common/translib/tlerr" ) - func handler(d *db.DB, skey *db.SKey, key *db.Key, event db.SEvent) error { fmt.Println("***handler: d: ", d, " skey: ", *skey, " key: ", *key, " event: ", event) return nil } - func main() { defer glog.Flush() flag.Parse() - tsc := db.TableSpec { Name: "COUNTERS_PORT_NAME_MAP" } + tsc := db.TableSpec{Name: "COUNTERS_PORT_NAME_MAP"} fmt.Println("Creating the SubscribeDB ==============") - d,e := db.NewDB(db.Options { - DBNo : db.CountersDB, - InitIndicator : "", - TableNameSeparator: ":", - KeySeparator : ":", - }) + d, e := db.NewDB(db.Options{ + DBNo: db.CountersDB, + InitIndicator: "", + TableNameSeparator: ":", + KeySeparator: ":", + }) if e != nil { fmt.Println("NewDB() returns error e: ", e) @@ -84,14 +82,13 @@ func main() { fmt.Println("r2, r5, r3", r2, r5, r3) - fmt.Println("GetMap NotExist mapKey ==============") rN, e := d.GetMap(&tsc, "EthernetN") if e == nil { fmt.Println("GetMap() NotExist mapKey returns nil !!! ", rN) } - vN, e := d.GetMapAll(& db.TableSpec { Name: "NOTEXITMAP" } ) + vN, e := d.GetMapAll(&db.TableSpec{Name: "NOTEXITMAP"}) if e == nil { fmt.Println("GetMapAll() NotExist returns nil !!! ", vN) } diff --git a/translib/db/test/testsubscribe.go b/translib/db/test/testsubscribe.go index 1272bd819..5b0acd95a 100644 --- a/translib/db/test/testsubscribe.go +++ b/translib/db/test/testsubscribe.go @@ -23,51 +23,49 @@ import ( "fmt" // "errors" "flag" - "github.com/golang/glog" "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/golang/glog" "time" // "github.com/Azure/sonic-mgmt-common/translib/tlerr" ) - func handler(d *db.DB, skey *db.SKey, key *db.Key, event db.SEvent) error { fmt.Println("***handler: d: ", d, " skey: ", *skey, " key: ", *key, " event: ", event) return nil } - func main() { // var avalue,rvalue db.Value var akey db.Key - // var rkey db.Key + // var rkey db.Key // var e error defer glog.Flush() flag.Parse() - tsa := db.TableSpec { Name: "ACL_TABLE" } + tsa := db.TableSpec{Name: "ACL_TABLE"} // tsr := db.TableSpec { Name: "ACL_RULE" } ca := make([]string, 1, 1) ca[0] = "MyACL1_ACL_IPVNOTEXIST*" - akey = db.Key { Comp: ca} - var skeys [] *db.SKey = make([]*db.SKey, 1) - skeys[0] = & (db.SKey { Ts: &tsa, Key: &akey, - SEMap: map[db.SEvent]bool { - db.SEventHSet: true, - db.SEventHDel: true, - db.SEventDel: true, + akey = db.Key{Comp: ca} + var skeys []*db.SKey = make([]*db.SKey, 1) + skeys[0] = &(db.SKey{Ts: &tsa, Key: &akey, + SEMap: map[db.SEvent]bool{ + db.SEventHSet: true, + db.SEventHDel: true, + db.SEventDel: true, }}) fmt.Println("Creating the SubscribeDB ==============") - d,e := db.SubscribeDB(db.Options { - DBNo : db.ConfigDB, - InitIndicator : "CONFIG_DB_INITIALIZED", - TableNameSeparator: "|", - KeySeparator : "|", - }, skeys, handler) + d, e := db.SubscribeDB(db.Options{ + DBNo: db.ConfigDB, + InitIndicator: "CONFIG_DB_INITIALIZED", + TableNameSeparator: "|", + KeySeparator: "|", + }, skeys, handler) if e != nil { fmt.Println("Subscribe() returns error e: ", e) @@ -76,7 +74,6 @@ func main() { fmt.Println("Sleeping 15 ==============") time.Sleep(15 * time.Second) - fmt.Println("Testing UnsubscribeDB ==============") d.UnsubscribeDB() @@ -84,5 +81,4 @@ func main() { fmt.Println("Sleeping 5 ==============") time.Sleep(5 * time.Second) - } diff --git a/translib/intf_app.go b/translib/intf_app.go index a7735c522..4836b1746 100644 --- a/translib/intf_app.go +++ b/translib/intf_app.go @@ -258,8 +258,8 @@ func (app *IntfApp) translateGet(dbs [db.MaxDB]*db.DB) error { } func (app *IntfApp) translateAction(dbs [db.MaxDB]*db.DB) error { - err := errors.New("Not supported") - return err + err := errors.New("Not supported") + return err } func (app *IntfApp) translateSubscribe(req translateSubRequest) (translateSubResponse, error) { @@ -560,10 +560,10 @@ func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (G } func (app *IntfApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) { - var resp ActionResponse - err := errors.New("Not implemented") + var resp ActionResponse + err := errors.New("Not implemented") - return resp, err + return resp, err } /* Checking IP adderss is v4 */ diff --git a/translib/lldp_app.go b/translib/lldp_app.go index 038619ec0..15511716f 100644 --- a/translib/lldp_app.go +++ b/translib/lldp_app.go @@ -33,109 +33,109 @@ import ( ) const ( - LLDP_REMOTE_CAP_ENABLED = "lldp_rem_sys_cap_enabled" - LLDP_REMOTE_SYS_NAME = "lldp_rem_sys_name" - LLDP_REMOTE_PORT_DESC = "lldp_rem_port_desc" - LLDP_REMOTE_CHASS_ID = "lldp_rem_chassis_id" - LLDP_REMOTE_CAP_SUPPORTED = "lldp_rem_sys_cap_supported" - LLDP_REMOTE_PORT_ID_SUBTYPE = "lldp_rem_port_id_subtype" - LLDP_REMOTE_SYS_DESC = "lldp_rem_sys_desc" - LLDP_REMOTE_REM_TIME = "lldp_rem_time_mark" - LLDP_REMOTE_PORT_ID = "lldp_rem_port_id" - LLDP_REMOTE_REM_ID = "lldp_rem_index" - LLDP_REMOTE_CHASS_ID_SUBTYPE = "lldp_rem_chassis_id_subtype" - LLDP_REMOTE_MAN_ADDR = "lldp_rem_man_addr" + LLDP_REMOTE_CAP_ENABLED = "lldp_rem_sys_cap_enabled" + LLDP_REMOTE_SYS_NAME = "lldp_rem_sys_name" + LLDP_REMOTE_PORT_DESC = "lldp_rem_port_desc" + LLDP_REMOTE_CHASS_ID = "lldp_rem_chassis_id" + LLDP_REMOTE_CAP_SUPPORTED = "lldp_rem_sys_cap_supported" + LLDP_REMOTE_PORT_ID_SUBTYPE = "lldp_rem_port_id_subtype" + LLDP_REMOTE_SYS_DESC = "lldp_rem_sys_desc" + LLDP_REMOTE_REM_TIME = "lldp_rem_time_mark" + LLDP_REMOTE_PORT_ID = "lldp_rem_port_id" + LLDP_REMOTE_REM_ID = "lldp_rem_index" + LLDP_REMOTE_CHASS_ID_SUBTYPE = "lldp_rem_chassis_id_subtype" + LLDP_REMOTE_MAN_ADDR = "lldp_rem_man_addr" ) type lldpApp struct { - path *PathInfo - ygotRoot *ygot.GoStruct - ygotTarget *interface{} - appDb *db.DB - neighTs *db.TableSpec - lldpTableMap map[string]db.Value - lldpNeighTableMap map[string]map[string]string - lldpCapTableMap map[string]map[string]bool + path *PathInfo + ygotRoot *ygot.GoStruct + ygotTarget *interface{} + appDb *db.DB + neighTs *db.TableSpec + lldpTableMap map[string]db.Value + lldpNeighTableMap map[string]map[string]string + lldpCapTableMap map[string]map[string]bool } func init() { - log.Info("Init called for LLDP modules module") - err := register("/openconfig-lldp:lldp", - &appInfo{appType: reflect.TypeOf(lldpApp{}), - ygotRootType: reflect.TypeOf(ocbinds.OpenconfigLldp_Lldp{}), - isNative: false}) - if err != nil { - log.Fatal("Register LLDP app module with App Interface failed with error=", err) - } - - err = addModel(&ModelData{Name: "openconfig-lldp", - Org: "OpenConfig working group", - Ver: "1.0.2"}) - if err != nil { - log.Fatal("Adding model data to appinterface failed with error=", err) - } + log.Info("Init called for LLDP modules module") + err := register("/openconfig-lldp:lldp", + &appInfo{appType: reflect.TypeOf(lldpApp{}), + ygotRootType: reflect.TypeOf(ocbinds.OpenconfigLldp_Lldp{}), + isNative: false}) + if err != nil { + log.Fatal("Register LLDP app module with App Interface failed with error=", err) + } + + err = addModel(&ModelData{Name: "openconfig-lldp", + Org: "OpenConfig working group", + Ver: "1.0.2"}) + if err != nil { + log.Fatal("Adding model data to appinterface failed with error=", err) + } } func (app *lldpApp) initialize(data appData) { - log.Info("initialize:lldp:path =", data.path) - *app = lldpApp{path: NewPathInfo(data.path), ygotRoot: data.ygotRoot, ygotTarget: data.ygotTarget} - app.neighTs = &db.TableSpec{Name: "LLDP_ENTRY_TABLE"} - app.lldpTableMap = make(map[string]db.Value) - app.lldpNeighTableMap = make(map[string]map[string]string) - app.lldpCapTableMap = make(map[string]map[string]bool) + log.Info("initialize:lldp:path =", data.path) + *app = lldpApp{path: NewPathInfo(data.path), ygotRoot: data.ygotRoot, ygotTarget: data.ygotTarget} + app.neighTs = &db.TableSpec{Name: "LLDP_ENTRY_TABLE"} + app.lldpTableMap = make(map[string]db.Value) + app.lldpNeighTableMap = make(map[string]map[string]string) + app.lldpCapTableMap = make(map[string]map[string]bool) } -func (app *lldpApp) getAppRootObject() (*ocbinds.OpenconfigLldp_Lldp) { - deviceObj := (*app.ygotRoot).(*ocbinds.Device) - return deviceObj.Lldp +func (app *lldpApp) getAppRootObject() *ocbinds.OpenconfigLldp_Lldp { + deviceObj := (*app.ygotRoot).(*ocbinds.Device) + return deviceObj.Lldp } -func (app *lldpApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateCreate:lldp:path =", app.path) +func (app *lldpApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateCreate:lldp:path =", app.path) - err = errors.New("Not implemented") - return keys, err + err = errors.New("Not implemented") + return keys, err } -func (app *lldpApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateUpdate:lldp:path =", app.path) +func (app *lldpApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateUpdate:lldp:path =", app.path) - err = errors.New("Not implemented") - return keys, err + err = errors.New("Not implemented") + return keys, err } -func (app *lldpApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateReplace:lldp:path =", app.path) +func (app *lldpApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateReplace:lldp:path =", app.path) - err = errors.New("Not implemented") - return keys, err + err = errors.New("Not implemented") + return keys, err } -func (app *lldpApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateDelete:lldp:path =", app.path) +func (app *lldpApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateDelete:lldp:path =", app.path) - err = errors.New("Not implemented") - return keys, err + err = errors.New("Not implemented") + return keys, err } -func (app *lldpApp) translateGet(dbs [db.MaxDB]*db.DB) error { - var err error - log.Info("translateGet:lldp:path = ", app.path) +func (app *lldpApp) translateGet(dbs [db.MaxDB]*db.DB) error { + var err error + log.Info("translateGet:lldp:path = ", app.path) - return err + return err } func (app *lldpApp) translateAction(dbs [db.MaxDB]*db.DB) error { - err := errors.New("Not supported") - return err + err := errors.New("Not supported") + return err } func (app *lldpApp) translateSubscribe(req translateSubRequest) (translateSubResponse, error) { @@ -146,293 +146,291 @@ func (app *lldpApp) processSubscribe(req processSubRequest) (processSubResponse, return processSubResponse{}, tlerr.New("not implemented") } -func (app *lldpApp) processCreate(d *db.DB) (SetResponse, error) { - var err error +func (app *lldpApp) processCreate(d *db.DB) (SetResponse, error) { + var err error - err = errors.New("Not implemented") - var resp SetResponse + err = errors.New("Not implemented") + var resp SetResponse - return resp, err + return resp, err } -func (app *lldpApp) processUpdate(d *db.DB) (SetResponse, error) { - var err error +func (app *lldpApp) processUpdate(d *db.DB) (SetResponse, error) { + var err error - err = errors.New("Not implemented") - var resp SetResponse + err = errors.New("Not implemented") + var resp SetResponse - return resp, err + return resp, err } -func (app *lldpApp) processReplace(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse - err = errors.New("Not implemented") +func (app *lldpApp) processReplace(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse + err = errors.New("Not implemented") - return resp, err + return resp, err } -func (app *lldpApp) processDelete(d *db.DB) (SetResponse, error) { - var err error - err = errors.New("Not implemented") - var resp SetResponse +func (app *lldpApp) processDelete(d *db.DB) (SetResponse, error) { + var err error + err = errors.New("Not implemented") + var resp SetResponse - return resp, err + return resp, err } -func (app *lldpApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) { - var err error - var payload []byte - - app.appDb = dbs[db.ApplDB] - lldpIntfObj := app.getAppRootObject() - - targetUriPath, err := getYangPathFromUri(app.path.Path) - if err != nil { - return GetResponse{}, err - } - - log.Info("lldp processGet") - log.Info("targetUriPath: ", targetUriPath) - - if targetUriPath == "/openconfig-lldp:lldp/interfaces" { - log.Info("Requesting interfaces") - app.getLldpInfoFromDB(nil) - ygot.BuildEmptyTree(lldpIntfObj) - ifInfo := lldpIntfObj.Interfaces - ygot.BuildEmptyTree(ifInfo) - for ifname,_ := range app.lldpNeighTableMap { - oneIfInfo, err := ifInfo.NewInterface(ifname) - if err != nil { - log.Info("Creation of subinterface subtree failed!") - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } - ygot.BuildEmptyTree(oneIfInfo) - app.getLldpNeighInfoFromInternalMap(&ifname, oneIfInfo) - } - } else if targetUriPath == "/openconfig-lldp:lldp/interfaces/interface" { - intfObj := lldpIntfObj.Interfaces - ygot.BuildEmptyTree(intfObj) - if intfObj.Interface != nil && len(intfObj.Interface) > 0 { - for ifname, _ := range intfObj.Interface { - log.Info("if-name = ", ifname) - app.getLldpInfoFromDB(&ifname) - ifInfo := intfObj.Interface[ifname] - ygot.BuildEmptyTree(ifInfo) - app.getLldpNeighInfoFromInternalMap(&ifname, ifInfo) - } - } else { - log.Info("No data") - } - } - - return generateGetResponse(app.path.Path, app.ygotRoot, fmtType) +func (app *lldpApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) { + var err error + var payload []byte + + app.appDb = dbs[db.ApplDB] + lldpIntfObj := app.getAppRootObject() + + targetUriPath, err := getYangPathFromUri(app.path.Path) + if err != nil { + return GetResponse{}, err + } + + log.Info("lldp processGet") + log.Info("targetUriPath: ", targetUriPath) + + if targetUriPath == "/openconfig-lldp:lldp/interfaces" { + log.Info("Requesting interfaces") + app.getLldpInfoFromDB(nil) + ygot.BuildEmptyTree(lldpIntfObj) + ifInfo := lldpIntfObj.Interfaces + ygot.BuildEmptyTree(ifInfo) + for ifname, _ := range app.lldpNeighTableMap { + oneIfInfo, err := ifInfo.NewInterface(ifname) + if err != nil { + log.Info("Creation of subinterface subtree failed!") + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + ygot.BuildEmptyTree(oneIfInfo) + app.getLldpNeighInfoFromInternalMap(&ifname, oneIfInfo) + } + } else if targetUriPath == "/openconfig-lldp:lldp/interfaces/interface" { + intfObj := lldpIntfObj.Interfaces + ygot.BuildEmptyTree(intfObj) + if intfObj.Interface != nil && len(intfObj.Interface) > 0 { + for ifname, _ := range intfObj.Interface { + log.Info("if-name = ", ifname) + app.getLldpInfoFromDB(&ifname) + ifInfo := intfObj.Interface[ifname] + ygot.BuildEmptyTree(ifInfo) + app.getLldpNeighInfoFromInternalMap(&ifname, ifInfo) + } + } else { + log.Info("No data") + } + } + + return generateGetResponse(app.path.Path, app.ygotRoot, fmtType) } func (app *lldpApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) { - var resp ActionResponse - err := errors.New("Not implemented") + var resp ActionResponse + err := errors.New("Not implemented") - return resp, err + return resp, err } /** Helper function to populate JSON response for GET request **/ func (app *lldpApp) getLldpNeighInfoFromInternalMap(ifName *string, ifInfo *ocbinds.OpenconfigLldp_Lldp_Interfaces_Interface) { - ngInfo, err := ifInfo.Neighbors.NewNeighbor(*ifName) - if err != nil { - log.Info("Creation of subinterface subtree failed!") - return - } - ygot.BuildEmptyTree(ngInfo) - neighAttrMap:= app.lldpNeighTableMap[*ifName] - for attr, value := range neighAttrMap { - switch attr { - case LLDP_REMOTE_SYS_NAME: - name := new(string) - *name = value - ngInfo.State.SystemName = name - case LLDP_REMOTE_PORT_DESC: - pdescr := new(string) - *pdescr = value - ngInfo.State.PortDescription = pdescr - case LLDP_REMOTE_CHASS_ID: - chId := new (string) - *chId = value - ngInfo.State.ChassisId = chId - case LLDP_REMOTE_PORT_ID_SUBTYPE: - remPortIdTypeVal, err := strconv.Atoi(value) - if err == nil { - ngInfo.State.PortIdType =ocbinds.E_OpenconfigLldp_PortIdType(remPortIdTypeVal) - } - case LLDP_REMOTE_SYS_DESC: - sdesc:= new(string) - *sdesc = value - ngInfo.State.SystemDescription = sdesc - case LLDP_REMOTE_REM_TIME: - /* Ignore Remote System time */ - case LLDP_REMOTE_PORT_ID: - remPortIdPtr := new(string) - *remPortIdPtr = value - ngInfo.State.PortId = remPortIdPtr - case LLDP_REMOTE_REM_ID: - Id := new(string) - *Id = value - ngInfo.State.Id = Id - case LLDP_REMOTE_CHASS_ID_SUBTYPE: - remChassIdTypeVal , err:=strconv.Atoi(value) - if err == nil { - ngInfo.State.ChassisIdType =ocbinds.E_OpenconfigLldp_ChassisIdType(remChassIdTypeVal) - } - case LLDP_REMOTE_MAN_ADDR: - mgmtAdr:= new(string) - *mgmtAdr = value - ngInfo.State.ManagementAddress = mgmtAdr - default: - log.Info("Not a valid attribute!") - } - } - capLst := app.lldpCapTableMap[*ifName] - for capName, enabled := range capLst { - if capName == "Router" { - capInfo, err := ngInfo.Capabilities.NewCapability(6) - if err == nil { - ygot.BuildEmptyTree(capInfo) - capInfo.State.Name = 6 - capInfo.State.Enabled = &enabled - } - } else if capName == "Repeater" { - capInfo, err := ngInfo.Capabilities.NewCapability(5) - if err == nil { - ygot.BuildEmptyTree(capInfo) - capInfo.State.Name = 5 - capInfo.State.Enabled = &enabled - } - } else if capName == "Bridge" { - capInfo, err := ngInfo.Capabilities.NewCapability(3) - if err == nil { - ygot.BuildEmptyTree(capInfo) - capInfo.State.Name = 3 - capInfo.State.Enabled = &enabled - } - } else { - - } - } + ngInfo, err := ifInfo.Neighbors.NewNeighbor(*ifName) + if err != nil { + log.Info("Creation of subinterface subtree failed!") + return + } + ygot.BuildEmptyTree(ngInfo) + neighAttrMap := app.lldpNeighTableMap[*ifName] + for attr, value := range neighAttrMap { + switch attr { + case LLDP_REMOTE_SYS_NAME: + name := new(string) + *name = value + ngInfo.State.SystemName = name + case LLDP_REMOTE_PORT_DESC: + pdescr := new(string) + *pdescr = value + ngInfo.State.PortDescription = pdescr + case LLDP_REMOTE_CHASS_ID: + chId := new(string) + *chId = value + ngInfo.State.ChassisId = chId + case LLDP_REMOTE_PORT_ID_SUBTYPE: + remPortIdTypeVal, err := strconv.Atoi(value) + if err == nil { + ngInfo.State.PortIdType = ocbinds.E_OpenconfigLldp_PortIdType(remPortIdTypeVal) + } + case LLDP_REMOTE_SYS_DESC: + sdesc := new(string) + *sdesc = value + ngInfo.State.SystemDescription = sdesc + case LLDP_REMOTE_REM_TIME: + /* Ignore Remote System time */ + case LLDP_REMOTE_PORT_ID: + remPortIdPtr := new(string) + *remPortIdPtr = value + ngInfo.State.PortId = remPortIdPtr + case LLDP_REMOTE_REM_ID: + Id := new(string) + *Id = value + ngInfo.State.Id = Id + case LLDP_REMOTE_CHASS_ID_SUBTYPE: + remChassIdTypeVal, err := strconv.Atoi(value) + if err == nil { + ngInfo.State.ChassisIdType = ocbinds.E_OpenconfigLldp_ChassisIdType(remChassIdTypeVal) + } + case LLDP_REMOTE_MAN_ADDR: + mgmtAdr := new(string) + *mgmtAdr = value + ngInfo.State.ManagementAddress = mgmtAdr + default: + log.Info("Not a valid attribute!") + } + } + capLst := app.lldpCapTableMap[*ifName] + for capName, enabled := range capLst { + if capName == "Router" { + capInfo, err := ngInfo.Capabilities.NewCapability(6) + if err == nil { + ygot.BuildEmptyTree(capInfo) + capInfo.State.Name = 6 + capInfo.State.Enabled = &enabled + } + } else if capName == "Repeater" { + capInfo, err := ngInfo.Capabilities.NewCapability(5) + if err == nil { + ygot.BuildEmptyTree(capInfo) + capInfo.State.Name = 5 + capInfo.State.Enabled = &enabled + } + } else if capName == "Bridge" { + capInfo, err := ngInfo.Capabilities.NewCapability(3) + if err == nil { + ygot.BuildEmptyTree(capInfo) + capInfo.State.Name = 3 + capInfo.State.Enabled = &enabled + } + } else { + + } + } } /** Helper function to get information from applDB **/ func (app *lldpApp) getLldpInfoFromDB(ifname *string) { - lldpTbl, err := app.appDb.GetTable(app.neighTs) - if err != nil { - log.Info("Can't get lldp table") - return - } - - keys, err := lldpTbl.GetKeys() - if err != nil { - log.Info("Can't get lldp keys") - return - } - - - for _, key := range keys { - log.Info("lldp key = ", key.Get(0)) - - lldpEntry, err := app.appDb.GetEntry(app.neighTs, db.Key{Comp: []string{key.Get(0)}}) - if err != nil { - log.Info("can't access neighbor table for key: ", key.Get(0)) - return - } - - if lldpEntry.IsPopulated() { - log.Info("lldp entry populated for key: ", key.Get(0)) - app.lldpTableMap[key.Get(0)] = lldpEntry - } - } - - for _, key := range keys { - if (ifname != nil && key.Get(0) != *ifname) { - continue - } - entryData := app.lldpTableMap[key.Get(0)] - if len(app.lldpNeighTableMap[key.Get(0)]) == 0 { - app.lldpNeighTableMap[key.Get(0)] = make(map[string]string) - } - for lldpAttr := range entryData.Field { - switch lldpAttr { - case LLDP_REMOTE_CAP_ENABLED: - app.getRemoteSysCap(entryData.Get(lldpAttr), key.Get(0), true) - case LLDP_REMOTE_SYS_NAME: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_SYS_NAME] = entryData.Get(lldpAttr) - case LLDP_REMOTE_PORT_DESC: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_PORT_DESC] = entryData.Get(lldpAttr) - case LLDP_REMOTE_CHASS_ID: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_CHASS_ID] = entryData.Get(lldpAttr) - case LLDP_REMOTE_CAP_SUPPORTED: - app.getRemoteSysCap(entryData.Get(lldpAttr), key.Get(0), false) - case LLDP_REMOTE_PORT_ID_SUBTYPE: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_PORT_ID_SUBTYPE] = entryData.Get(lldpAttr) - case LLDP_REMOTE_SYS_DESC: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_SYS_DESC] = entryData.Get(lldpAttr) - case LLDP_REMOTE_REM_TIME: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_REM_TIME] = entryData.Get(lldpAttr) - case LLDP_REMOTE_PORT_ID: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_PORT_ID] = entryData.Get(lldpAttr) - case LLDP_REMOTE_REM_ID: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_REM_ID] = entryData.Get(lldpAttr) - case LLDP_REMOTE_CHASS_ID_SUBTYPE: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_CHASS_ID_SUBTYPE] = entryData.Get(lldpAttr) - case LLDP_REMOTE_MAN_ADDR: - app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_MAN_ADDR] = entryData.Get(lldpAttr) - default: - log.Info("Unknown LLDP Attribute") - } - } - } + lldpTbl, err := app.appDb.GetTable(app.neighTs) + if err != nil { + log.Info("Can't get lldp table") + return + } + + keys, err := lldpTbl.GetKeys() + if err != nil { + log.Info("Can't get lldp keys") + return + } + + for _, key := range keys { + log.Info("lldp key = ", key.Get(0)) + + lldpEntry, err := app.appDb.GetEntry(app.neighTs, db.Key{Comp: []string{key.Get(0)}}) + if err != nil { + log.Info("can't access neighbor table for key: ", key.Get(0)) + return + } + + if lldpEntry.IsPopulated() { + log.Info("lldp entry populated for key: ", key.Get(0)) + app.lldpTableMap[key.Get(0)] = lldpEntry + } + } + + for _, key := range keys { + if ifname != nil && key.Get(0) != *ifname { + continue + } + entryData := app.lldpTableMap[key.Get(0)] + if len(app.lldpNeighTableMap[key.Get(0)]) == 0 { + app.lldpNeighTableMap[key.Get(0)] = make(map[string]string) + } + for lldpAttr := range entryData.Field { + switch lldpAttr { + case LLDP_REMOTE_CAP_ENABLED: + app.getRemoteSysCap(entryData.Get(lldpAttr), key.Get(0), true) + case LLDP_REMOTE_SYS_NAME: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_SYS_NAME] = entryData.Get(lldpAttr) + case LLDP_REMOTE_PORT_DESC: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_PORT_DESC] = entryData.Get(lldpAttr) + case LLDP_REMOTE_CHASS_ID: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_CHASS_ID] = entryData.Get(lldpAttr) + case LLDP_REMOTE_CAP_SUPPORTED: + app.getRemoteSysCap(entryData.Get(lldpAttr), key.Get(0), false) + case LLDP_REMOTE_PORT_ID_SUBTYPE: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_PORT_ID_SUBTYPE] = entryData.Get(lldpAttr) + case LLDP_REMOTE_SYS_DESC: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_SYS_DESC] = entryData.Get(lldpAttr) + case LLDP_REMOTE_REM_TIME: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_REM_TIME] = entryData.Get(lldpAttr) + case LLDP_REMOTE_PORT_ID: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_PORT_ID] = entryData.Get(lldpAttr) + case LLDP_REMOTE_REM_ID: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_REM_ID] = entryData.Get(lldpAttr) + case LLDP_REMOTE_CHASS_ID_SUBTYPE: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_CHASS_ID_SUBTYPE] = entryData.Get(lldpAttr) + case LLDP_REMOTE_MAN_ADDR: + app.lldpNeighTableMap[key.Get(0)][LLDP_REMOTE_MAN_ADDR] = entryData.Get(lldpAttr) + default: + log.Info("Unknown LLDP Attribute") + } + } + } } /** Helper function to get remote system capabilities into a map **/ func (app *lldpApp) getRemoteSysCap(capb string, ifname string, setCap bool) { - num_str := strings.Split(capb, " ") - byte, _ := hex.DecodeString(num_str[0] + num_str[1]) - sysCap := byte[0] - sysCap |= byte[1] - - log.Info("sysCap: ", sysCap) - - if (sysCap & (128 >> 1)) != 0 { - if app.lldpCapTableMap[ifname] == nil { - app.lldpCapTableMap[ifname] = make(map[string]bool) - app.lldpCapTableMap[ifname]["Repeater"] = false - } - if (setCap) { - log.Info("Repeater ENABLED") - app.lldpCapTableMap[ifname]["Repeater"] = true - } - } - - if (sysCap & (128 >> 2)) != 0 { - if app.lldpCapTableMap[ifname] == nil { - app.lldpCapTableMap[ifname] = make(map[string]bool) - app.lldpCapTableMap[ifname]["Bridge"] = false - } - if (setCap) { - log.Info("Bridge ENABLED") - app.lldpCapTableMap[ifname]["Bridge"] = true - } - } - - if (sysCap & (128 >> 4)) != 0 { - if app.lldpCapTableMap[ifname] == nil { - app.lldpCapTableMap[ifname] = make(map[string]bool) - app.lldpCapTableMap[ifname]["Router"] = false - } - if (setCap) { - log.Info("Router ENABLED") - app.lldpCapTableMap[ifname]["Router"] = true - } - } + num_str := strings.Split(capb, " ") + byte, _ := hex.DecodeString(num_str[0] + num_str[1]) + sysCap := byte[0] + sysCap |= byte[1] + + log.Info("sysCap: ", sysCap) + + if (sysCap & (128 >> 1)) != 0 { + if app.lldpCapTableMap[ifname] == nil { + app.lldpCapTableMap[ifname] = make(map[string]bool) + app.lldpCapTableMap[ifname]["Repeater"] = false + } + if setCap { + log.Info("Repeater ENABLED") + app.lldpCapTableMap[ifname]["Repeater"] = true + } + } + + if (sysCap & (128 >> 2)) != 0 { + if app.lldpCapTableMap[ifname] == nil { + app.lldpCapTableMap[ifname] = make(map[string]bool) + app.lldpCapTableMap[ifname]["Bridge"] = false + } + if setCap { + log.Info("Bridge ENABLED") + app.lldpCapTableMap[ifname]["Bridge"] = true + } + } + + if (sysCap & (128 >> 4)) != 0 { + if app.lldpCapTableMap[ifname] == nil { + app.lldpCapTableMap[ifname] = make(map[string]bool) + app.lldpCapTableMap[ifname]["Router"] = false + } + if setCap { + log.Info("Router ENABLED") + app.lldpCapTableMap[ifname]["Router"] = true + } + } } - diff --git a/translib/pfm_app.go b/translib/pfm_app.go index bb572849b..f2dab02a3 100644 --- a/translib/pfm_app.go +++ b/translib/pfm_app.go @@ -19,63 +19,62 @@ package translib import ( - "reflect" - "strconv" - "errors" - "github.com/Azure/sonic-mgmt-common/translib/db" - "github.com/Azure/sonic-mgmt-common/translib/ocbinds" - "github.com/Azure/sonic-mgmt-common/translib/tlerr" - "github.com/openconfig/ygot/ygot" - log "github.com/golang/glog" + "errors" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" + "github.com/Azure/sonic-mgmt-common/translib/tlerr" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strconv" ) type PlatformApp struct { - path *PathInfo - reqData []byte - ygotRoot *ygot.GoStruct - ygotTarget *interface{} - eepromTs *db.TableSpec - eepromTable map[string]dbEntry - + path *PathInfo + reqData []byte + ygotRoot *ygot.GoStruct + ygotTarget *interface{} + eepromTs *db.TableSpec + eepromTable map[string]dbEntry } func init() { - log.Info("Init called for Platform module") - err := register("/openconfig-platform:components", - &appInfo{appType: reflect.TypeOf(PlatformApp{}), - ygotRootType: reflect.TypeOf(ocbinds.OpenconfigPlatform_Components{}), - isNative: false}) - if err != nil { - log.Fatal("Register Platform app module with App Interface failed with error=", err) - } - - err = addModel(&ModelData{Name: "openconfig-platform", - Org: "OpenConfig working group", - Ver: "1.0.2"}) - if err != nil { - log.Fatal("Adding model data to appinterface failed with error=", err) - } + log.Info("Init called for Platform module") + err := register("/openconfig-platform:components", + &appInfo{appType: reflect.TypeOf(PlatformApp{}), + ygotRootType: reflect.TypeOf(ocbinds.OpenconfigPlatform_Components{}), + isNative: false}) + if err != nil { + log.Fatal("Register Platform app module with App Interface failed with error=", err) + } + + err = addModel(&ModelData{Name: "openconfig-platform", + Org: "OpenConfig working group", + Ver: "1.0.2"}) + if err != nil { + log.Fatal("Adding model data to appinterface failed with error=", err) + } } func (app *PlatformApp) initialize(data appData) { - log.Info("initialize:if:path =", data.path) + log.Info("initialize:if:path =", data.path) - app.path = NewPathInfo(data.path) - app.reqData = data.payload - app.ygotRoot = data.ygotRoot - app.ygotTarget = data.ygotTarget - app.eepromTs = &db.TableSpec{Name: "EEPROM_INFO"} + app.path = NewPathInfo(data.path) + app.reqData = data.payload + app.ygotRoot = data.ygotRoot + app.ygotTarget = data.ygotTarget + app.eepromTs = &db.TableSpec{Name: "EEPROM_INFO"} } -func (app *PlatformApp) getAppRootObject() (*ocbinds.OpenconfigPlatform_Components) { - deviceObj := (*app.ygotRoot).(*ocbinds.Device) - return deviceObj.Components +func (app *PlatformApp) getAppRootObject() *ocbinds.OpenconfigPlatform_Components { + deviceObj := (*app.ygotRoot).(*ocbinds.Device) + return deviceObj.Components } func (app *PlatformApp) translateAction(dbs [db.MaxDB]*db.DB) error { - err := errors.New("Not supported") - return err + err := errors.New("Not supported") + return err } func (app *PlatformApp) translateSubscribe(req translateSubRequest) (translateSubResponse, error) { @@ -86,418 +85,415 @@ func (app *PlatformApp) processSubscribe(req processSubRequest) (processSubRespo return processSubResponse{}, tlerr.New("not implemented") } -func (app *PlatformApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys +func (app *PlatformApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys - err = errors.New("PlatformApp Not implemented, translateCreate") - return keys, err + err = errors.New("PlatformApp Not implemented, translateCreate") + return keys, err } -func (app *PlatformApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - err = errors.New("PlatformApp Not implemented, translateUpdate") - return keys, err +func (app *PlatformApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + err = errors.New("PlatformApp Not implemented, translateUpdate") + return keys, err } -func (app *PlatformApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys +func (app *PlatformApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys - err = errors.New("Not implemented PlatformApp translateReplace") - return keys, err + err = errors.New("Not implemented PlatformApp translateReplace") + return keys, err } -func (app *PlatformApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys +func (app *PlatformApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys - err = errors.New("Not implemented PlatformApp translateDelete") - return keys, err + err = errors.New("Not implemented PlatformApp translateDelete") + return keys, err } -func (app *PlatformApp) translateGet(dbs [db.MaxDB]*db.DB) error { - var err error - log.Info("PlatformApp: translateGet - path: ", app.path.Path) - return err +func (app *PlatformApp) translateGet(dbs [db.MaxDB]*db.DB) error { + var err error + log.Info("PlatformApp: translateGet - path: ", app.path.Path) + return err } -func (app *PlatformApp) processCreate(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse +func (app *PlatformApp) processCreate(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse - err = errors.New("Not implemented PlatformApp processCreate") - return resp, err + err = errors.New("Not implemented PlatformApp processCreate") + return resp, err } -func (app *PlatformApp) processUpdate(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse +func (app *PlatformApp) processUpdate(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse - err = errors.New("Not implemented PlatformApp processUpdate") - return resp, err + err = errors.New("Not implemented PlatformApp processUpdate") + return resp, err } -func (app *PlatformApp) processReplace(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse - log.Info("processReplace:intf:path =", app.path) - err = errors.New("Not implemented, PlatformApp processReplace") - return resp, err +func (app *PlatformApp) processReplace(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse + log.Info("processReplace:intf:path =", app.path) + err = errors.New("Not implemented, PlatformApp processReplace") + return resp, err } -func (app *PlatformApp) processDelete(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse +func (app *PlatformApp) processDelete(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse - err = errors.New("Not implemented PlatformApp processDelete") - return resp, err + err = errors.New("Not implemented PlatformApp processDelete") + return resp, err } -func (app *PlatformApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) { - pathInfo := app.path - log.Infof("Received GET for PlatformApp Template: %s ,path: %s, vars: %v", - pathInfo.Template, pathInfo.Path, pathInfo.Vars) - - stateDb := dbs[db.StateDB] - - var payload []byte - - // Read eeprom info from DB - app.eepromTable = make(map[string]dbEntry) - - tbl, derr := stateDb.GetTable(app.eepromTs) - if derr != nil { - log.Error("EEPROM_INFO table get failed!") - return GetResponse{Payload: payload}, derr - } - - keys, _ := tbl.GetKeys() - for _, key := range keys { - e, kerr := tbl.GetEntry(key) - if kerr != nil { - log.Error("EEPROM_INFO entry get failed!") - return GetResponse{Payload: payload}, kerr - } - - app.eepromTable[key.Get(0)] = dbEntry{entry: e} - } - - targetUriPath, perr := getYangPathFromUri(app.path.Path) - if perr != nil { - log.Infof("getYangPathFromUri failed.") - return GetResponse{Payload: payload}, perr - } - - var err error - - if isSubtreeRequest(targetUriPath, "/openconfig-platform:components") { - err = app.doGetSysEeprom() - } else { - err = errors.New("Not supported component") - } - - if err == nil { - return generateGetResponse(pathInfo.Path, app.ygotRoot, fmtType) - } - return GetResponse{Payload: payload}, err +func (app *PlatformApp) processGet(dbs [db.MaxDB]*db.DB, fmtType TranslibFmtType) (GetResponse, error) { + pathInfo := app.path + log.Infof("Received GET for PlatformApp Template: %s ,path: %s, vars: %v", + pathInfo.Template, pathInfo.Path, pathInfo.Vars) + + stateDb := dbs[db.StateDB] + + var payload []byte + + // Read eeprom info from DB + app.eepromTable = make(map[string]dbEntry) + + tbl, derr := stateDb.GetTable(app.eepromTs) + if derr != nil { + log.Error("EEPROM_INFO table get failed!") + return GetResponse{Payload: payload}, derr + } + + keys, _ := tbl.GetKeys() + for _, key := range keys { + e, kerr := tbl.GetEntry(key) + if kerr != nil { + log.Error("EEPROM_INFO entry get failed!") + return GetResponse{Payload: payload}, kerr + } + + app.eepromTable[key.Get(0)] = dbEntry{entry: e} + } + + targetUriPath, perr := getYangPathFromUri(app.path.Path) + if perr != nil { + log.Infof("getYangPathFromUri failed.") + return GetResponse{Payload: payload}, perr + } + + var err error + + if isSubtreeRequest(targetUriPath, "/openconfig-platform:components") { + err = app.doGetSysEeprom() + } else { + err = errors.New("Not supported component") + } + + if err == nil { + return generateGetResponse(pathInfo.Path, app.ygotRoot, fmtType) + } + return GetResponse{Payload: payload}, err } func (app *PlatformApp) processAction(dbs [db.MaxDB]*db.DB) (ActionResponse, error) { - var resp ActionResponse - err := errors.New("Not implemented") + var resp ActionResponse + err := errors.New("Not implemented") - return resp, err + return resp, err } - /////////////////////////// - -/** +/* +* Structures to read syseeprom from redis-db */ -type EepromDb struct { - Product_Name string - Part_Number string - Serial_Number string - Base_MAC_Address string - Manufacture_Date string - Device_Version string - Label_Revision string - Platform_Name string - ONIE_Version string - MAC_Addresses int - Manufacturer string - Manufacture_Country string - Vendor_Name string - Diag_Version string - Service_Tag string - Vendor_Extension string - Magic_Number int - Card_Type string - Hardware_Version string - Software_Version string - Model_Name string - +type EepromDb struct { + Product_Name string + Part_Number string + Serial_Number string + Base_MAC_Address string + Manufacture_Date string + Device_Version string + Label_Revision string + Platform_Name string + ONIE_Version string + MAC_Addresses int + Manufacturer string + Manufacture_Country string + Vendor_Name string + Diag_Version string + Service_Tag string + Vendor_Extension string + Magic_Number int + Card_Type string + Hardware_Version string + Software_Version string + Model_Name string } -func (app *PlatformApp) getEepromDbObj () (EepromDb){ - log.Infof("parseEepromDb Enter") - - var eepromDbObj EepromDb - - for epItem, _ := range app.eepromTable { - e := app.eepromTable[epItem].entry - name := e.Get("Name") - - switch name { - case "Device Version": - eepromDbObj.Device_Version = e.Get("Value") - case "Service Tag": - eepromDbObj.Service_Tag = e.Get("Value") - case "Vendor Extension": - eepromDbObj.Vendor_Extension = e.Get("Value") - case "Magic Number": - mag, _ := strconv.ParseInt(e.Get("Value"), 10, 64) - eepromDbObj.Magic_Number = int(mag) - case "Card Type": - eepromDbObj.Card_Type = e.Get("Value") - case "Hardware Version": - eepromDbObj.Hardware_Version = e.Get("Value") - case "Software Version": - eepromDbObj.Software_Version = e.Get("Value") - case "Model Name": - eepromDbObj.Model_Name = e.Get("Value") - case "ONIE Version": - eepromDbObj.ONIE_Version = e.Get("Value") - case "Serial Number": - eepromDbObj.Serial_Number = e.Get("Value") - case "Vendor Name": - eepromDbObj.Vendor_Name = e.Get("Value") - case "Manufacturer": - eepromDbObj.Manufacturer = e.Get("Value") - case "Manufacture Country": - eepromDbObj.Manufacture_Country = e.Get("Value") - case "Platform Name": - eepromDbObj.Platform_Name = e.Get("Value") - case "Diag Version": - eepromDbObj.Diag_Version = e.Get("Value") - case "Label Revision": - eepromDbObj.Label_Revision = e.Get("Value") - case "Part Number": - eepromDbObj.Part_Number = e.Get("Value") - case "Product Name": - eepromDbObj.Product_Name = e.Get("Value") - case "Base MAC Address": - eepromDbObj.Base_MAC_Address = e.Get("Value") - case "Manufacture Date": - eepromDbObj.Manufacture_Date = e.Get("Value") - case "MAC Addresses": - mac, _ := strconv.ParseInt(e.Get("Value"), 10, 16) - eepromDbObj.MAC_Addresses = int(mac) - } - } - - return eepromDbObj +func (app *PlatformApp) getEepromDbObj() EepromDb { + log.Infof("parseEepromDb Enter") + + var eepromDbObj EepromDb + + for epItem, _ := range app.eepromTable { + e := app.eepromTable[epItem].entry + name := e.Get("Name") + + switch name { + case "Device Version": + eepromDbObj.Device_Version = e.Get("Value") + case "Service Tag": + eepromDbObj.Service_Tag = e.Get("Value") + case "Vendor Extension": + eepromDbObj.Vendor_Extension = e.Get("Value") + case "Magic Number": + mag, _ := strconv.ParseInt(e.Get("Value"), 10, 64) + eepromDbObj.Magic_Number = int(mag) + case "Card Type": + eepromDbObj.Card_Type = e.Get("Value") + case "Hardware Version": + eepromDbObj.Hardware_Version = e.Get("Value") + case "Software Version": + eepromDbObj.Software_Version = e.Get("Value") + case "Model Name": + eepromDbObj.Model_Name = e.Get("Value") + case "ONIE Version": + eepromDbObj.ONIE_Version = e.Get("Value") + case "Serial Number": + eepromDbObj.Serial_Number = e.Get("Value") + case "Vendor Name": + eepromDbObj.Vendor_Name = e.Get("Value") + case "Manufacturer": + eepromDbObj.Manufacturer = e.Get("Value") + case "Manufacture Country": + eepromDbObj.Manufacture_Country = e.Get("Value") + case "Platform Name": + eepromDbObj.Platform_Name = e.Get("Value") + case "Diag Version": + eepromDbObj.Diag_Version = e.Get("Value") + case "Label Revision": + eepromDbObj.Label_Revision = e.Get("Value") + case "Part Number": + eepromDbObj.Part_Number = e.Get("Value") + case "Product Name": + eepromDbObj.Product_Name = e.Get("Value") + case "Base MAC Address": + eepromDbObj.Base_MAC_Address = e.Get("Value") + case "Manufacture Date": + eepromDbObj.Manufacture_Date = e.Get("Value") + case "MAC Addresses": + mac, _ := strconv.ParseInt(e.Get("Value"), 10, 16) + eepromDbObj.MAC_Addresses = int(mac) + } + } + + return eepromDbObj } -func (app *PlatformApp) getSysEepromFromDb (eeprom *ocbinds.OpenconfigPlatform_Components_Component_State, all bool) (error) { - - log.Infof("getSysEepromFromDb Enter") - - eepromDb := app.getEepromDbObj() - - empty := false - removable := false - name := "System Eeprom" - location := "Slot 1" - - if all == true { - eeprom.Empty = &empty - eeprom.Removable = &removable - eeprom.Name = &name - eeprom.OperStatus = ocbinds.OpenconfigPlatformTypes_COMPONENT_OPER_STATUS_ACTIVE - eeprom.Location = &location - - if eepromDb.Product_Name != "" { - eeprom.Id = &eepromDb.Product_Name - } - if eepromDb.Part_Number != "" { - eeprom.PartNo = &eepromDb.Part_Number - } - if eepromDb.Serial_Number != "" { - eeprom.SerialNo = &eepromDb.Serial_Number - } - if eepromDb.Base_MAC_Address != "" { - } - if eepromDb.Manufacture_Date != "" { - eeprom.MfgDate = &eepromDb.Manufacture_Date - } - if eepromDb.Label_Revision != "" { - eeprom.HardwareVersion = &eepromDb.Label_Revision - } - if eepromDb.Platform_Name != "" { - eeprom.Description = &eepromDb.Platform_Name - } - if eepromDb.ONIE_Version != "" { - } - if eepromDb.MAC_Addresses != 0 { - } - if eepromDb.Manufacturer != "" { - eeprom.MfgName = &eepromDb.Manufacturer - } - if eepromDb.Manufacture_Country != "" { - } - if eepromDb.Vendor_Name != "" { - if eeprom.MfgName == nil { - eeprom.MfgName = &eepromDb.Vendor_Name - } - } - if eepromDb.Diag_Version != "" { - } - if eepromDb.Service_Tag != "" { - if eeprom.SerialNo == nil { - eeprom.SerialNo = &eepromDb.Service_Tag - } - } - if eepromDb.Hardware_Version != "" { - eeprom.HardwareVersion = &eepromDb.Hardware_Version - } - if eepromDb.Software_Version != "" { - eeprom.SoftwareVersion = &eepromDb.Software_Version - } - } else { - targetUriPath, _ := getYangPathFromUri(app.path.Path) - switch targetUriPath { - case "/openconfig-platform:components/component/state/name": - eeprom.Name = &name - case "/openconfig-platform:components/component/state/location": - eeprom.Location = &location - case "/openconfig-platform:components/component/state/empty": - eeprom.Empty = &empty - case "/openconfig-platform:components/component/state/removable": - eeprom.Removable = &removable - case "/openconfig-platform:components/component/state/oper-status": - eeprom.OperStatus = ocbinds.OpenconfigPlatformTypes_COMPONENT_OPER_STATUS_ACTIVE - case "/openconfig-platform:components/component/state/id": - if eepromDb.Product_Name != "" { - eeprom.Id = &eepromDb.Product_Name - } - case "/openconfig-platform:components/component/state/part-no": - if eepromDb.Part_Number != "" { - eeprom.PartNo = &eepromDb.Part_Number - } - case "/openconfig-platform:components/component/state/serial-no": - if eepromDb.Serial_Number != "" { - eeprom.SerialNo = &eepromDb.Serial_Number - } - if eepromDb.Service_Tag != "" { - if eeprom.SerialNo == nil { - eeprom.SerialNo = &eepromDb.Service_Tag - } - } - case "/openconfig-platform:components/component/state/mfg-date": - if eepromDb.Manufacture_Date != "" { - eeprom.MfgDate = &eepromDb.Manufacture_Date - } - case "/openconfig-platform:components/component/state/hardware-version": - if eepromDb.Label_Revision != "" { - eeprom.HardwareVersion = &eepromDb.Label_Revision - } - if eepromDb.Hardware_Version != "" { - if eeprom.HardwareVersion == nil { - eeprom.HardwareVersion = &eepromDb.Hardware_Version - } - } - case "/openconfig-platform:components/component/state/description": - if eepromDb.Platform_Name != "" { - eeprom.Description = &eepromDb.Platform_Name - } - case "/openconfig-platform:components/component/state/mfg-name": - if eepromDb.Manufacturer != "" { - eeprom.MfgName = &eepromDb.Manufacturer - } - if eepromDb.Vendor_Name != "" { - if eeprom.MfgName == nil { - eeprom.MfgName = &eepromDb.Vendor_Name - } - } - case "/openconfig-platform:components/component/state/software-version": - if eepromDb.Software_Version != "" { - eeprom.SoftwareVersion = &eepromDb.Software_Version - } - } - } - return nil +func (app *PlatformApp) getSysEepromFromDb(eeprom *ocbinds.OpenconfigPlatform_Components_Component_State, all bool) error { + + log.Infof("getSysEepromFromDb Enter") + + eepromDb := app.getEepromDbObj() + + empty := false + removable := false + name := "System Eeprom" + location := "Slot 1" + + if all == true { + eeprom.Empty = &empty + eeprom.Removable = &removable + eeprom.Name = &name + eeprom.OperStatus = ocbinds.OpenconfigPlatformTypes_COMPONENT_OPER_STATUS_ACTIVE + eeprom.Location = &location + + if eepromDb.Product_Name != "" { + eeprom.Id = &eepromDb.Product_Name + } + if eepromDb.Part_Number != "" { + eeprom.PartNo = &eepromDb.Part_Number + } + if eepromDb.Serial_Number != "" { + eeprom.SerialNo = &eepromDb.Serial_Number + } + if eepromDb.Base_MAC_Address != "" { + } + if eepromDb.Manufacture_Date != "" { + eeprom.MfgDate = &eepromDb.Manufacture_Date + } + if eepromDb.Label_Revision != "" { + eeprom.HardwareVersion = &eepromDb.Label_Revision + } + if eepromDb.Platform_Name != "" { + eeprom.Description = &eepromDb.Platform_Name + } + if eepromDb.ONIE_Version != "" { + } + if eepromDb.MAC_Addresses != 0 { + } + if eepromDb.Manufacturer != "" { + eeprom.MfgName = &eepromDb.Manufacturer + } + if eepromDb.Manufacture_Country != "" { + } + if eepromDb.Vendor_Name != "" { + if eeprom.MfgName == nil { + eeprom.MfgName = &eepromDb.Vendor_Name + } + } + if eepromDb.Diag_Version != "" { + } + if eepromDb.Service_Tag != "" { + if eeprom.SerialNo == nil { + eeprom.SerialNo = &eepromDb.Service_Tag + } + } + if eepromDb.Hardware_Version != "" { + eeprom.HardwareVersion = &eepromDb.Hardware_Version + } + if eepromDb.Software_Version != "" { + eeprom.SoftwareVersion = &eepromDb.Software_Version + } + } else { + targetUriPath, _ := getYangPathFromUri(app.path.Path) + switch targetUriPath { + case "/openconfig-platform:components/component/state/name": + eeprom.Name = &name + case "/openconfig-platform:components/component/state/location": + eeprom.Location = &location + case "/openconfig-platform:components/component/state/empty": + eeprom.Empty = &empty + case "/openconfig-platform:components/component/state/removable": + eeprom.Removable = &removable + case "/openconfig-platform:components/component/state/oper-status": + eeprom.OperStatus = ocbinds.OpenconfigPlatformTypes_COMPONENT_OPER_STATUS_ACTIVE + case "/openconfig-platform:components/component/state/id": + if eepromDb.Product_Name != "" { + eeprom.Id = &eepromDb.Product_Name + } + case "/openconfig-platform:components/component/state/part-no": + if eepromDb.Part_Number != "" { + eeprom.PartNo = &eepromDb.Part_Number + } + case "/openconfig-platform:components/component/state/serial-no": + if eepromDb.Serial_Number != "" { + eeprom.SerialNo = &eepromDb.Serial_Number + } + if eepromDb.Service_Tag != "" { + if eeprom.SerialNo == nil { + eeprom.SerialNo = &eepromDb.Service_Tag + } + } + case "/openconfig-platform:components/component/state/mfg-date": + if eepromDb.Manufacture_Date != "" { + eeprom.MfgDate = &eepromDb.Manufacture_Date + } + case "/openconfig-platform:components/component/state/hardware-version": + if eepromDb.Label_Revision != "" { + eeprom.HardwareVersion = &eepromDb.Label_Revision + } + if eepromDb.Hardware_Version != "" { + if eeprom.HardwareVersion == nil { + eeprom.HardwareVersion = &eepromDb.Hardware_Version + } + } + case "/openconfig-platform:components/component/state/description": + if eepromDb.Platform_Name != "" { + eeprom.Description = &eepromDb.Platform_Name + } + case "/openconfig-platform:components/component/state/mfg-name": + if eepromDb.Manufacturer != "" { + eeprom.MfgName = &eepromDb.Manufacturer + } + if eepromDb.Vendor_Name != "" { + if eeprom.MfgName == nil { + eeprom.MfgName = &eepromDb.Vendor_Name + } + } + case "/openconfig-platform:components/component/state/software-version": + if eepromDb.Software_Version != "" { + eeprom.SoftwareVersion = &eepromDb.Software_Version + } + } + } + return nil } -func (app *PlatformApp) doGetSysEeprom () error { - - log.Infof("Preparing collection for system eeprom"); - - var err error - pf_cpts := app.getAppRootObject() - - targetUriPath, _ := getYangPathFromUri(app.path.Path) - switch targetUriPath { - case "/openconfig-platform:components": - pf_comp,_ := pf_cpts.NewComponent("System Eeprom") - ygot.BuildEmptyTree(pf_comp) - err = app.getSysEepromFromDb(pf_comp.State, true) - - case "/openconfig-platform:components/component": - compName := app.path.Var("name") - if compName == "" { - pf_comp,_ := pf_cpts.NewComponent("System Eeprom") - ygot.BuildEmptyTree(pf_comp) - err = app.getSysEepromFromDb(pf_comp.State, true) - } else { - if compName != "System Eeprom" { - err = errors.New("Invalid component name") - break - } - pf_comp := pf_cpts.Component[compName] - if pf_comp != nil { - ygot.BuildEmptyTree(pf_comp) - err = app.getSysEepromFromDb(pf_comp.State, true) - } else { - err = errors.New("Invalid input component name") - } - } - case "/openconfig-platform:components/component/state": - compName := app.path.Var("name") - if compName != "" && compName == "System Eeprom" { - pf_comp := pf_cpts.Component[compName] - if pf_comp != nil { - ygot.BuildEmptyTree(pf_comp) - err = app.getSysEepromFromDb(pf_comp.State, true) - } else { - err = errors.New("Invalid input component name") - } - } else { - err = errors.New("Invalid component name ") - } - - default: - if isSubtreeRequest(targetUriPath, "/openconfig-platform:components/component/state") { - compName := app.path.Var("name") - if compName == "" || compName != "System Eeprom" { - err = errors.New("Invalid input component name") - } else { - pf_comp := pf_cpts.Component[compName] - if pf_comp != nil { - ygot.BuildEmptyTree(pf_comp) - err = app.getSysEepromFromDb(pf_comp.State, false) - } else { - err = errors.New("Invalid input component name") - } - } - } else { - err = errors.New("Invalid Path") - } - } - return err +func (app *PlatformApp) doGetSysEeprom() error { + + log.Infof("Preparing collection for system eeprom") + + var err error + pf_cpts := app.getAppRootObject() + + targetUriPath, _ := getYangPathFromUri(app.path.Path) + switch targetUriPath { + case "/openconfig-platform:components": + pf_comp, _ := pf_cpts.NewComponent("System Eeprom") + ygot.BuildEmptyTree(pf_comp) + err = app.getSysEepromFromDb(pf_comp.State, true) + + case "/openconfig-platform:components/component": + compName := app.path.Var("name") + if compName == "" { + pf_comp, _ := pf_cpts.NewComponent("System Eeprom") + ygot.BuildEmptyTree(pf_comp) + err = app.getSysEepromFromDb(pf_comp.State, true) + } else { + if compName != "System Eeprom" { + err = errors.New("Invalid component name") + break + } + pf_comp := pf_cpts.Component[compName] + if pf_comp != nil { + ygot.BuildEmptyTree(pf_comp) + err = app.getSysEepromFromDb(pf_comp.State, true) + } else { + err = errors.New("Invalid input component name") + } + } + case "/openconfig-platform:components/component/state": + compName := app.path.Var("name") + if compName != "" && compName == "System Eeprom" { + pf_comp := pf_cpts.Component[compName] + if pf_comp != nil { + ygot.BuildEmptyTree(pf_comp) + err = app.getSysEepromFromDb(pf_comp.State, true) + } else { + err = errors.New("Invalid input component name") + } + } else { + err = errors.New("Invalid component name ") + } + + default: + if isSubtreeRequest(targetUriPath, "/openconfig-platform:components/component/state") { + compName := app.path.Var("name") + if compName == "" || compName != "System Eeprom" { + err = errors.New("Invalid input component name") + } else { + pf_comp := pf_cpts.Component[compName] + if pf_comp != nil { + ygot.BuildEmptyTree(pf_comp) + err = app.getSysEepromFromDb(pf_comp.State, false) + } else { + err = errors.New("Invalid input component name") + } + } + } else { + err = errors.New("Invalid Path") + } + } + return err } - diff --git a/translib/pfm_app_test.go b/translib/pfm_app_test.go index 73e1647ea..0ad27bb36 100644 --- a/translib/pfm_app_test.go +++ b/translib/pfm_app_test.go @@ -1,135 +1,135 @@ -package translib - -import ( - "errors" - "fmt" - "testing" - "github.com/Azure/sonic-mgmt-common/translib/db" -) - -// TLV EEPROM Data Types -const ( - _TLV_CODE_PRODUCT_NAME = "0x21" - _TLV_CODE_PART_NUMBER = "0x22" - _TLV_CODE_SERIAL_NUMBER = "0x23" - _TLV_CODE_MAC_BASE = "0x24" - _TLV_CODE_MANUF_DATE = "0x25" - _TLV_CODE_DEVICE_VERSION = "0x26" - _TLV_CODE_LABEL_REVISION = "0x27" - _TLV_CODE_PLATFORM_NAME = "0x28" - _TLV_CODE_ONIE_VERSION = "0x29" - _TLV_CODE_MAC_SIZE = "0x2A" - _TLV_CODE_MANUF_NAME = "0x2B" - _TLV_CODE_MANUF_COUNTRY = "0x2C" - _TLV_CODE_VENDOR_NAME = "0x2D" - _TLV_CODE_DIAG_VERSION = "0x2E" - _TLV_CODE_SERVICE_TAG = "0x2F" - _TLV_CODE_VENDOR_EXT = "0xFD" - _TLV_CODE_CRC_32 = "0xFE" -) - -const ( - TEST_PRODUCT_NAME = "6776-64X-O-AC-F" - TEST_PART_NUMBER = "FP123454321PF" - TEST_PLATFORM_NAME = "x86_64-pfm_test-platform" - TEST_SERVICE_TAG = "6776X6776" - TEST_MANUF_NAME = "TestManufacture" -) - -type EepromEntry struct { - TlvType string - Name string - Value string -} - -var testStateDbList = [...]EepromEntry{ - {_TLV_CODE_PRODUCT_NAME, "Product Name", TEST_PRODUCT_NAME}, - {_TLV_CODE_PLATFORM_NAME, "Platform Name", TEST_PLATFORM_NAME}, - {_TLV_CODE_SERVICE_TAG, "Service Tag", TEST_SERVICE_TAG}, - {_TLV_CODE_MANUF_NAME, "Manufacturer", TEST_MANUF_NAME}, - {_TLV_CODE_PART_NUMBER, "Part Number", TEST_PART_NUMBER}, -} - -func init() { - fmt.Println("+++++ Init pfm_app_test +++++") - - if err := clearPfmDataFromDb(); err == nil { - fmt.Println("+++++ Removed All Platform Data from Db +++++") - } else { - fmt.Printf("Failed to remove All Platform Data from Db: %v", err) - } -} - -// This will test GET on /openconfig-platform:components -func Test_PfmApp_TopLevelPath(t *testing.T) { - url := "/openconfig-platform:components" - - t.Run("Default_Response_Top_Level", processGetRequest(url, bulkPfmShowDefaultResponse, false)) - - //Set the factory DB with pre-defined EEPROM_INFO entry - if err := createPfmFactoryDb(); err != nil { - fmt.Printf("Failed to add Platform Data to Db: %v", err) - } - - t.Run("Get_Full_Pfm_Tree_Top_Level", processGetRequest(url, bulkPfmShowAllJsonResponse, false)) -} - -// THis will delete Platform Table from DB -func clearPfmDataFromDb() error { - var err error - eepromTable := db.TableSpec{Name: "EEPROM_INFO"} - - d := getStateDB() - if d == nil { - err = errors.New("Failed to connect to state Db") - return err - } - if err = d.DeleteTable(&eepromTable); err != nil { - err = errors.New("Failed to delete Eeprom Table") - return err - } - return err -} - -func createPfmFactoryDb() error { - var err error - eepromTable := db.TableSpec{Name: "EEPROM_INFO"} - - d := getStateDB() - if d == nil { - err = errors.New("Failed to connect to state Db") - return err - } - - for _, dbItem := range testStateDbList { - ca := make([]string, 1, 1) - ca[0] = dbItem.TlvType - - akey := db.Key{Comp: ca} - avalue := db.Value{Field: map[string]string{ - "Name": dbItem.Name, - "Value": dbItem.Value, - }, - } - d.SetEntry(&eepromTable, akey, avalue) - } - return err -} - -func getStateDB() *db.DB { - stateDb, _ := db.NewDB(db.Options{ - DBNo: db.StateDB, - InitIndicator: "STATE_DB_INITIALIZED", - TableNameSeparator: "|", - KeySeparator: "|", - }) - - return stateDb -} - -/***************************************************************************/ -/////////// JSON Data for Tests /////////////// -/***************************************************************************/ -var bulkPfmShowDefaultResponse string = "{\"openconfig-platform:components\":{\"component\":[{\"name\":\"System Eeprom\",\"state\":{\"empty\":false,\"location\":\"Slot 1\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"removable\":false}}]}}" - -var bulkPfmShowAllJsonResponse string = "{\"openconfig-platform:components\":{\"component\":[{\"name\":\"System Eeprom\",\"state\":{\"description\":\"" + TEST_PLATFORM_NAME + "\",\"empty\":false,\"id\":\"" + TEST_PRODUCT_NAME + "\",\"location\":\"Slot 1\",\"mfg-name\":\"" + TEST_MANUF_NAME + "\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"part-no\":\"" + TEST_PART_NUMBER + "\",\"removable\":false,\"serial-no\":\"" + TEST_SERVICE_TAG + "\"}}]}}" +package translib + +import ( + "errors" + "fmt" + "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" +) + +// TLV EEPROM Data Types +const ( + _TLV_CODE_PRODUCT_NAME = "0x21" + _TLV_CODE_PART_NUMBER = "0x22" + _TLV_CODE_SERIAL_NUMBER = "0x23" + _TLV_CODE_MAC_BASE = "0x24" + _TLV_CODE_MANUF_DATE = "0x25" + _TLV_CODE_DEVICE_VERSION = "0x26" + _TLV_CODE_LABEL_REVISION = "0x27" + _TLV_CODE_PLATFORM_NAME = "0x28" + _TLV_CODE_ONIE_VERSION = "0x29" + _TLV_CODE_MAC_SIZE = "0x2A" + _TLV_CODE_MANUF_NAME = "0x2B" + _TLV_CODE_MANUF_COUNTRY = "0x2C" + _TLV_CODE_VENDOR_NAME = "0x2D" + _TLV_CODE_DIAG_VERSION = "0x2E" + _TLV_CODE_SERVICE_TAG = "0x2F" + _TLV_CODE_VENDOR_EXT = "0xFD" + _TLV_CODE_CRC_32 = "0xFE" +) + +const ( + TEST_PRODUCT_NAME = "6776-64X-O-AC-F" + TEST_PART_NUMBER = "FP123454321PF" + TEST_PLATFORM_NAME = "x86_64-pfm_test-platform" + TEST_SERVICE_TAG = "6776X6776" + TEST_MANUF_NAME = "TestManufacture" +) + +type EepromEntry struct { + TlvType string + Name string + Value string +} + +var testStateDbList = [...]EepromEntry{ + {_TLV_CODE_PRODUCT_NAME, "Product Name", TEST_PRODUCT_NAME}, + {_TLV_CODE_PLATFORM_NAME, "Platform Name", TEST_PLATFORM_NAME}, + {_TLV_CODE_SERVICE_TAG, "Service Tag", TEST_SERVICE_TAG}, + {_TLV_CODE_MANUF_NAME, "Manufacturer", TEST_MANUF_NAME}, + {_TLV_CODE_PART_NUMBER, "Part Number", TEST_PART_NUMBER}, +} + +func init() { + fmt.Println("+++++ Init pfm_app_test +++++") + + if err := clearPfmDataFromDb(); err == nil { + fmt.Println("+++++ Removed All Platform Data from Db +++++") + } else { + fmt.Printf("Failed to remove All Platform Data from Db: %v", err) + } +} + +// This will test GET on /openconfig-platform:components +func Test_PfmApp_TopLevelPath(t *testing.T) { + url := "/openconfig-platform:components" + + t.Run("Default_Response_Top_Level", processGetRequest(url, bulkPfmShowDefaultResponse, false)) + + //Set the factory DB with pre-defined EEPROM_INFO entry + if err := createPfmFactoryDb(); err != nil { + fmt.Printf("Failed to add Platform Data to Db: %v", err) + } + + t.Run("Get_Full_Pfm_Tree_Top_Level", processGetRequest(url, bulkPfmShowAllJsonResponse, false)) +} + +// THis will delete Platform Table from DB +func clearPfmDataFromDb() error { + var err error + eepromTable := db.TableSpec{Name: "EEPROM_INFO"} + + d := getStateDB() + if d == nil { + err = errors.New("Failed to connect to state Db") + return err + } + if err = d.DeleteTable(&eepromTable); err != nil { + err = errors.New("Failed to delete Eeprom Table") + return err + } + return err +} + +func createPfmFactoryDb() error { + var err error + eepromTable := db.TableSpec{Name: "EEPROM_INFO"} + + d := getStateDB() + if d == nil { + err = errors.New("Failed to connect to state Db") + return err + } + + for _, dbItem := range testStateDbList { + ca := make([]string, 1, 1) + ca[0] = dbItem.TlvType + + akey := db.Key{Comp: ca} + avalue := db.Value{Field: map[string]string{ + "Name": dbItem.Name, + "Value": dbItem.Value, + }, + } + d.SetEntry(&eepromTable, akey, avalue) + } + return err +} + +func getStateDB() *db.DB { + stateDb, _ := db.NewDB(db.Options{ + DBNo: db.StateDB, + InitIndicator: "STATE_DB_INITIALIZED", + TableNameSeparator: "|", + KeySeparator: "|", + }) + + return stateDb +} + +/***************************************************************************/ +/////////// JSON Data for Tests /////////////// +/***************************************************************************/ +var bulkPfmShowDefaultResponse string = "{\"openconfig-platform:components\":{\"component\":[{\"name\":\"System Eeprom\",\"state\":{\"empty\":false,\"location\":\"Slot 1\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"removable\":false}}]}}" + +var bulkPfmShowAllJsonResponse string = "{\"openconfig-platform:components\":{\"component\":[{\"name\":\"System Eeprom\",\"state\":{\"description\":\"" + TEST_PLATFORM_NAME + "\",\"empty\":false,\"id\":\"" + TEST_PRODUCT_NAME + "\",\"location\":\"Slot 1\",\"mfg-name\":\"" + TEST_MANUF_NAME + "\",\"name\":\"System Eeprom\",\"oper-status\":\"openconfig-platform-types:ACTIVE\",\"part-no\":\"" + TEST_PART_NUMBER + "\",\"removable\":false,\"serial-no\":\"" + TEST_SERVICE_TAG + "\"}}]}}" diff --git a/translib/request_binder.go b/translib/request_binder.go index 7e004e6dd..56d9935ac 100644 --- a/translib/request_binder.go +++ b/translib/request_binder.go @@ -29,9 +29,9 @@ import ( "github.com/openconfig/ygot/ygot" "github.com/openconfig/ygot/ytypes" - "github.com/openconfig/goyang/pkg/yang" "github.com/Azure/sonic-mgmt-common/translib/ocbinds" "github.com/Azure/sonic-mgmt-common/translib/tlerr" + "github.com/openconfig/goyang/pkg/yang" ) const ( @@ -94,22 +94,22 @@ func (binder *requestBinder) unMarshallPayload(workObj *interface{}) error { return nil } -func (binder *requestBinder) validateObjectType (errObj error) error { - +func (binder *requestBinder) validateObjectType(errObj error) error { + if errObj == nil { return nil } - + errStr := errObj.Error() if binder.opcode == GET || binder.isSonicModel { tmpStr := strings.Replace(errStr, "ERROR_READONLY_OBJECT_FOUND", "", -1) - if len (tmpStr) > 0 { + if len(tmpStr) > 0 { log.Info("validateObjectType ==> GET == return err string ==> ", tmpStr) return errors.New(tmpStr) } else { return nil - } + } } else { if strings.Contains(errStr, "ERROR_READONLY_OBJECT_FOUND") { log.Info("validateObjectType ==> WRITE == return err string") @@ -125,14 +125,14 @@ func (binder *requestBinder) validateRequest(deviceObj *ocbinds.Device) error { // Skipping the validation for the sonic yang model if binder.isSonicModel { - log.Warning("Translib: RequestBinder: Skipping the vaidatiion of the given sonic yang model request..") + log.Warning("Translib: RequestBinder: Skipping the vaidatiion of the given sonic yang model request..") return nil } - + if binder.pathTmp == nil || len(binder.pathTmp.Elem) == 0 { if binder.opcode == UPDATE || binder.opcode == REPLACE { err := deviceObj.Validate(&ytypes.LeafrefOptions{IgnoreMissingData: true}) - err = binder.validateObjectType (err) + err = binder.validateObjectType(err) if err != nil { return err } @@ -155,7 +155,7 @@ func (binder *requestBinder) validateRequest(deviceObj *ocbinds.Device) error { basePathObj, ok := (baseTreeNode[0].Data).(ygot.ValidatedGoStruct) if ok { err := basePathObj.Validate(&ytypes.LeafrefOptions{IgnoreMissingData: true}) - err = binder.validateObjectType (err) + err = binder.validateObjectType(err) if err != nil { return err } @@ -253,7 +253,7 @@ func (binder *requestBinder) unMarshall() (*ygot.GoStruct, *interface{}, error) if ok { if !binder.isSonicModel { err := targetObj.Validate(&ytypes.LeafrefOptions{IgnoreMissingData: true}) - err = binder.validateObjectType (err) + err = binder.validateObjectType(err) if err != nil { return nil, nil, tlerr.TranslibSyntaxValidationError{StatusCode: 400, ErrorStr: err} } @@ -303,7 +303,7 @@ func (binder *requestBinder) unMarshallUri(deviceObj *ocbinds.Device) (*interfac } else { binder.pathTmp = path } - + for idx, p := range path.Elem { pathSlice := strings.Split(p.Name, ":") if idx == 0 && len(pathSlice) > 0 && strings.HasPrefix(pathSlice[0], "sonic-") { diff --git a/translib/request_binder_test.go b/translib/request_binder_test.go index 94a35cf54..2a72d7da3 100644 --- a/translib/request_binder_test.go +++ b/translib/request_binder_test.go @@ -21,12 +21,12 @@ package translib import ( "fmt" - "github.com/openconfig/ygot/ygot" + "github.com/Azure/sonic-mgmt-common/translib/ocbinds" "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/ygot/ygot" "reflect" "strings" "testing" - "github.com/Azure/sonic-mgmt-common/translib/ocbinds" ) func TestInitSchema(t *testing.T) { @@ -79,15 +79,15 @@ func TestValidateRequest(t *testing.T) { appRootType: reflect.TypeOf(ocbinds.OpenconfigAcl_Acl{}), want: "no match found", }} - + for _, tt := range tests { deviceObj := ocbinds.Device{} deviceObj.Acl = &ocbinds.OpenconfigAcl_Acl{} deviceObj.Acl.AclSets = &ocbinds.OpenconfigAcl_Acl_AclSets{} - deviceObj.Acl.AclSets.NewAclSet ("SampleACL", ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4) - + deviceObj.Acl.AclSets.NewAclSet("SampleACL", ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4) + binder := getRequestBinder(&tt.uri, &tt.payload, tt.opcode, &tt.appRootType) - + path, err := binder.getUriPath() if err != nil { tmpPath := gnmi.Path{} @@ -95,9 +95,9 @@ func TestValidateRequest(t *testing.T) { } else { binder.pathTmp = path } - + err = binder.validateRequest(&deviceObj) - + if err != nil { // Negative test case if strings.Contains(err.Error(), tt.want) == false { @@ -226,12 +226,12 @@ func TestUnMarshallUri(t *testing.T) { } else { _, ok := (*workObj).(ygot.GoStruct) if ok == false { -// objFieldName, err := getObjectFieldName(&tt.uri, &deviceObj, workObj) -// if err != nil { -// t.Error("Error in unmarshalling the URI: ", err) -// } else if objFieldName != tt.want { -// t.Error("Error in unmarshalling the URI: Invalid target node: ", objFieldName) -// } + // objFieldName, err := getObjectFieldName(&tt.uri, &deviceObj, workObj) + // if err != nil { + // t.Error("Error in unmarshalling the URI: ", err) + // } else if objFieldName != tt.want { + // t.Error("Error in unmarshalling the URI: Invalid target node: ", objFieldName) + // } } else if tt.tid == 4 { aclSet, ok := (*workObj).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet) if ok == true { @@ -284,26 +284,26 @@ func TestUnMarshallUri(t *testing.T) { func TestUnMarshallPayload(t *testing.T) { tests := []struct { - tid int - objIntf interface{} - uri string - opcode int - payload []byte - want string //target object name + tid int + objIntf interface{} + uri string + opcode int + payload []byte + want string //target object name }{{ - tid: 1, - objIntf: "TestObj", - uri: "/openconfig-acl:acl/acl-sets/", - opcode: 2, - payload: []byte{}, - want: "Error in casting the target object", + tid: 1, + objIntf: "TestObj", + uri: "/openconfig-acl:acl/acl-sets/", + opcode: 2, + payload: []byte{}, + want: "Error in casting the target object", }, { - tid: 2, - objIntf: ocbinds.OpenconfigAcl_Acl{}, - uri: "/openconfig-acl:acl/acl-sets/", - opcode: 3, - payload: []byte{}, - want: "Request payload is empty", + tid: 2, + objIntf: ocbinds.OpenconfigAcl_Acl{}, + uri: "/openconfig-acl:acl/acl-sets/", + opcode: 3, + payload: []byte{}, + want: "Request payload is empty", }} for _, tt := range tests { @@ -312,15 +312,17 @@ func TestUnMarshallPayload(t *testing.T) { var deviceObj ocbinds.Device = ocbinds.Device{} var workObj *interface{} var err error - workObj, err = reqBinder.unMarshallUri(&deviceObj); if err != nil { + workObj, err = reqBinder.unMarshallUri(&deviceObj) + if err != nil { t.Error(err) } - if (tt.tid == 1) { + if tt.tid == 1 { workObj = &tt.objIntf } - - err = reqBinder.unMarshallPayload(workObj); if err != nil { + + err = reqBinder.unMarshallPayload(workObj) + if err != nil { if strings.Contains(err.Error(), tt.want) == false { t.Error("Negative test case failed: ", err) } @@ -345,14 +347,15 @@ func TestGetUriPath(t *testing.T) { appRootType: reflect.TypeOf(ocbinds.OpenconfigAcl_Acl{}), want: "error formatting path", }} - + for _, tt := range tests { reqBinder := getRequestBinder(&tt.uri, &tt.payload, tt.opcode, &tt.appRootType) - _, err := reqBinder.getUriPath(); if err != nil { + _, err := reqBinder.getUriPath() + if err != nil { if strings.Contains(err.Error(), tt.want) == false { t.Error("Negative test case failed: ", err) } - } + } } } @@ -499,12 +502,12 @@ func TestUnMarshall(t *testing.T) { } else { _, ok := (*workObj).(ygot.GoStruct) if ok == false { -// objFieldName, err := getObjectFieldName(&tt.uri, (*rootObj).(*ocbinds.Device), workObj) -// if err != nil { -// t.Error("Error in unmarshalling the URI: ", err) -// } else if objFieldName != tt.want { -// t.Error("Error in unmarshalling the payload: Invalid target node: ", objFieldName) -// } + // objFieldName, err := getObjectFieldName(&tt.uri, (*rootObj).(*ocbinds.Device), workObj) + // if err != nil { + // t.Error("Error in unmarshalling the URI: ", err) + // } else if objFieldName != tt.want { + // t.Error("Error in unmarshalling the payload: Invalid target node: ", objFieldName) + // } } else if reflect.TypeOf(*workObj).Elem().Name() != tt.want { t.Error("Error in unmarshalling the payload: Invalid target node: ", reflect.TypeOf(*workObj).Elem().Name()) } diff --git a/translib/test/translibtest.go b/translib/test/translibtest.go index ab138d99f..0afb8a029 100644 --- a/translib/test/translibtest.go +++ b/translib/test/translibtest.go @@ -11,7 +11,7 @@ // // // 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. // +// 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. // // // @@ -20,48 +20,48 @@ package main import ( - "flag" - "io/ioutil" - "github.com/Azure/sonic-mgmt-common/translib" - "strings" - //"sync" - "github.com/Workiva/go-datastructures/queue" - log "github.com/golang/glog" + "flag" + "github.com/Azure/sonic-mgmt-common/translib" + "io/ioutil" + "strings" + //"sync" + "github.com/Workiva/go-datastructures/queue" + log "github.com/golang/glog" ) func main() { - var err error - operationPtr := flag.String("o", "get", "Operation: create,update,replace,delete,get,getmodels,subscribe,supportsubscribe") - uriPtr := flag.String("u", "", "URI string") - payloadFilePtr := flag.String("p", "", "JSON payload file") - flag.Parse() - log.Info("operation =", *operationPtr) - log.Info("uri =", *uriPtr) - log.Info("payload =", *payloadFilePtr) - - payloadFromFile, err := ioutil.ReadFile(*payloadFilePtr) - if err != nil { - log.Fatal(err) - } + var err error + operationPtr := flag.String("o", "get", "Operation: create,update,replace,delete,get,getmodels,subscribe,supportsubscribe") + uriPtr := flag.String("u", "", "URI string") + payloadFilePtr := flag.String("p", "", "JSON payload file") + flag.Parse() + log.Info("operation =", *operationPtr) + log.Info("uri =", *uriPtr) + log.Info("payload =", *payloadFilePtr) + + payloadFromFile, err := ioutil.ReadFile(*payloadFilePtr) + if err != nil { + log.Fatal(err) + } if *operationPtr == "create" { - req := translib.SetRequest{Path:*uriPtr, Payload:[]byte(payloadFromFile)} + req := translib.SetRequest{Path: *uriPtr, Payload: []byte(payloadFromFile)} translib.Create(req) } else if *operationPtr == "update" { - req := translib.SetRequest{Path:*uriPtr, Payload:[]byte(payloadFromFile)} + req := translib.SetRequest{Path: *uriPtr, Payload: []byte(payloadFromFile)} translib.Update(req) } else if *operationPtr == "replace" { - req := translib.SetRequest{Path:*uriPtr, Payload:[]byte(payloadFromFile)} + req := translib.SetRequest{Path: *uriPtr, Payload: []byte(payloadFromFile)} translib.Replace(req) } else if *operationPtr == "delete" { - req := translib.SetRequest{Path:*uriPtr} + req := translib.SetRequest{Path: *uriPtr} translib.Delete(req) } else if *operationPtr == "get" { - req := translib.GetRequest{Path:*uriPtr} + req := translib.GetRequest{Path: *uriPtr} resp, _ := translib.Get(req) log.Info("Response payload =", string(resp.Payload)) } else if *operationPtr == "getmodels" { - models,_ := translib.GetModels() + models, _ := translib.GetModels() log.Info("Models =", models) } else if *operationPtr == "supportsubscribe" { paths := strings.Split(*uriPtr, ",") @@ -77,8 +77,8 @@ func main() { } else if *operationPtr == "subscribe" { paths := strings.Split(*uriPtr, ",") log.Info("Paths =", paths) - var q *queue.PriorityQueue - var stop chan struct{} + var q *queue.PriorityQueue + var stop chan struct{} q = queue.NewPriorityQueue(1, false) stop = make(chan struct{}, 1) @@ -107,33 +107,33 @@ func main() { } } - var q1 *queue.PriorityQueue - var stop1 chan struct{} - - q1 = queue.NewPriorityQueue(1, false) - stop1 = make(chan struct{}, 1) - translib.Subscribe(paths, q1, stop1) - log.Info("Subscribe completed") - for { - log.Info("Before calling Get") - items, err := q1.Get(1) - log.Info("After calling Get") - - if items == nil { - log.V(1).Infof("%v", err) - break - } - if err != nil { - log.V(1).Infof("%v", err) - break - } - - resp, _ := (items[0]).(*translib.SubscribeResponse) - log.Info("SubscribeResponse received =", string(resp.Payload)) - log.Info("IsSync complete = ", resp.SyncComplete) - - if resp.SyncComplete { - } + var q1 *queue.PriorityQueue + var stop1 chan struct{} + + q1 = queue.NewPriorityQueue(1, false) + stop1 = make(chan struct{}, 1) + translib.Subscribe(paths, q1, stop1) + log.Info("Subscribe completed") + for { + log.Info("Before calling Get") + items, err := q1.Get(1) + log.Info("After calling Get") + + if items == nil { + log.V(1).Infof("%v", err) + break + } + if err != nil { + log.V(1).Infof("%v", err) + break + } + + resp, _ := (items[0]).(*translib.SubscribeResponse) + log.Info("SubscribeResponse received =", string(resp.Payload)) + log.Info("IsSync complete = ", resp.SyncComplete) + + if resp.SyncComplete { + } } } else { diff --git a/translib/tlerr/app_errors.go b/translib/tlerr/app_errors.go index 289cb84b3..fca7f2be9 100644 --- a/translib/tlerr/app_errors.go +++ b/translib/tlerr/app_errors.go @@ -95,6 +95,5 @@ func New(msg string, args ...interface{}) InternalError { } func (e AuthorizationError) Error() string { - return p.Sprintf(e.Format, e.Args...) + return p.Sprintf(e.Format, e.Args...) } - diff --git a/translib/transformer/host_comm.go b/translib/transformer/host_comm.go index c33fa547e..317805462 100644 --- a/translib/transformer/host_comm.go +++ b/translib/transformer/host_comm.go @@ -4,20 +4,20 @@ import ( "strings" "github.com/godbus/dbus/v5" - log "github.com/golang/glog" + log "github.com/golang/glog" ) -// HostResult contains the body of the response and the error if any, when the +// HostResult contains the body of the response and the error if any, when the // endpoint finishes servicing the D-Bus request. type HostResult struct { - Body []interface{} - Err error + Body []interface{} + Err error } // HostQuery calls the corresponding D-Bus endpoint on the host and returns // any error and response body func HostQuery(endpoint string, args ...interface{}) (result HostResult) { - log.Infof("HostQuery called") + log.Infof("HostQuery called") result_ch, err := hostQueryAsync(endpoint, args...) if err != nil { @@ -32,13 +32,13 @@ func HostQuery(endpoint string, args ...interface{}) (result HostResult) { // hostQueryAsync calls the corresponding D-Bus endpoint on the host and returns // a channel for the result, and any error func hostQueryAsync(endpoint string, args ...interface{}) (chan HostResult, error) { - log.Infof("HostQueryAsync called") + log.Infof("HostQueryAsync called") var result_ch = make(chan HostResult, 1) conn, err := dbus.SystemBus() if err != nil { return result_ch, err } - log.Infof("HostQueryAsync conn established") + log.Infof("HostQueryAsync conn established") service := strings.SplitN(endpoint, ".", 2) const bus_name_base = "org.SONiC.HostService." @@ -48,8 +48,8 @@ func hostQueryAsync(endpoint string, args ...interface{}) (chan HostResult, erro obj := conn.Object(bus_name, bus_path) dest := bus_name_base + endpoint dbus_ch := make(chan *dbus.Call, 1) - //log.Infof("HostQueryAsync dbus called %s "% string(bus_path)) - //log.Infof("HostQueryAsync dbus called %s "% string(bus_name)) + //log.Infof("HostQueryAsync dbus called %s "% string(bus_path)) + //log.Infof("HostQueryAsync dbus called %s "% string(bus_name)) go func() { var result HostResult @@ -58,10 +58,10 @@ func hostQueryAsync(endpoint string, args ...interface{}) (chan HostResult, erro call := <-dbus_ch if call.Err != nil { - log.Infof("HostQueryAsync Err is not nill while reading") + log.Infof("HostQueryAsync Err is not nill while reading") result.Err = call.Err } else { - log.Infof("HostQueryAsync Body is taken") + log.Infof("HostQueryAsync Body is taken") result.Body = call.Body } @@ -69,11 +69,11 @@ func hostQueryAsync(endpoint string, args ...interface{}) (chan HostResult, erro result_ch <- result }() - log.Infof("HostQueryAsync Before objgo") + log.Infof("HostQueryAsync Before objgo") call := obj.Go(dest, 0, dbus_ch, args...) if call.Err != nil { - log.Infof("HostQueryAsync Err is not after obj.Go") + log.Infof("HostQueryAsync Err is not after obj.Go") return result_ch, call.Err } diff --git a/translib/transformer/sflow_openconfig_test.go b/translib/transformer/sflow_openconfig_test.go index d112cfa83..5b5ca8136 100644 --- a/translib/transformer/sflow_openconfig_test.go +++ b/translib/transformer/sflow_openconfig_test.go @@ -23,137 +23,135 @@ package transformer_test import ( "errors" - "testing" - "time" + "github.com/Azure/sonic-mgmt-common/translib/db" "github.com/Azure/sonic-mgmt-common/translib/tlerr" - "github.com/Azure/sonic-mgmt-common/translib/db" + "testing" + "time" ) - - func Test_node_on_openconfig_sflow(t *testing.T) { - var pre_req_map, expected_map, cleanuptbl map[string]interface{} - var url, url_body_json string + var pre_req_map, expected_map, cleanuptbl map[string]interface{} + var url, url_body_json string - t.Log("\n\n+++++++++++++ Performing Set on sflow node ++++++++++++") - url = "/openconfig-sampling-sflow:sampling/sflow/config" + t.Log("\n\n+++++++++++++ Performing Set on sflow node ++++++++++++") + url = "/openconfig-sampling-sflow:sampling/sflow/config" url_body_json = "{ \"openconfig-sampling-sflow:enabled\": true, \"openconfig-sampling-sflow:polling-interval\": 100, \"openconfig-sampling-sflow:agent\": \"Ethernet0\"}" - expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet0" , "polling_interval":"100"}}} - cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - loadDB(db.ConfigDB, pre_req_map) - time.Sleep(1 * time.Second) - t.Run("Test set on sflow node", processSetRequest(url, url_body_json, "POST", false, nil)) - time.Sleep(1 * time.Second) - t.Run("Verify set on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) - time.Sleep(1 * time.Second) + expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} + cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} + loadDB(db.ConfigDB, pre_req_map) + time.Sleep(1 * time.Second) + t.Run("Test set on sflow node", processSetRequest(url, url_body_json, "POST", false, nil)) + time.Sleep(1 * time.Second) + t.Run("Verify set on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) + time.Sleep(1 * time.Second) unloadDB(db.ConfigDB, cleanuptbl) - time.Sleep(1 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Set on sflow node ++++++++++++") + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Set on sflow node ++++++++++++") - t.Log("\n\n+++++++++++++ Performing Delete on sflow node ++++++++++++") - pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet4" , "polling_interval":"200"}}} - loadDB(db.ConfigDB, pre_req_map) - time.Sleep(1 * time.Second) - url = "/openconfig-sampling-sflow:sampling/sflow/config" + t.Log("\n\n+++++++++++++ Performing Delete on sflow node ++++++++++++") + pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet4", "polling_interval": "200"}}} + loadDB(db.ConfigDB, pre_req_map) + time.Sleep(1 * time.Second) + url = "/openconfig-sampling-sflow:sampling/sflow/config" expected_err := errors.New("DELETE not supported on attribute") - t.Run("Test delete on sflow node", processDeleteRequest(url, true, expected_err )) - time.Sleep(1 * time.Second) - cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - unloadDB(db.ConfigDB, cleanuptbl) - time.Sleep(1 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Delete on sflow node ++++++++++++") + t.Run("Test delete on sflow node", processDeleteRequest(url, true, expected_err)) + time.Sleep(1 * time.Second) + cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} + unloadDB(db.ConfigDB, cleanuptbl) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Delete on sflow node ++++++++++++") t.Log("\n\n+++++++++++++ Performing Get on Sflow node ++++++++++++") - pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet8" , "polling_interval":"300"}}} - loadDB(db.ConfigDB, pre_req_map) - expected_get_json := "{\"openconfig-sampling-sflow:state\":{\"agent\":\"Ethernet8\",\"enabled\":true,\"polling-interval\":300}}" - url = "/openconfig-sampling-sflow:sampling/sflow/state" - t.Run("Test get on sflow node", processGetRequest(url, nil, expected_get_json, false)) - time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) - t.Log("\n\n+++++++++++++ Done Performing Get on Sflow node ++++++++++++") + pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet8", "polling_interval": "300"}}} + loadDB(db.ConfigDB, pre_req_map) + expected_get_json := "{\"openconfig-sampling-sflow:state\":{\"agent\":\"Ethernet8\",\"enabled\":true,\"polling-interval\":300}}" + url = "/openconfig-sampling-sflow:sampling/sflow/state" + t.Run("Test get on sflow node", processGetRequest(url, nil, expected_get_json, false)) + time.Sleep(1 * time.Second) + unloadDB(db.ConfigDB, cleanuptbl) + t.Log("\n\n+++++++++++++ Done Performing Get on Sflow node ++++++++++++") - t.Log("\n\n+++++++++++++ Performing Put/Replace on sflow leaf node ++++++++++++") - url = "/openconfig-sampling-sflow:sampling/sflow/config" + t.Log("\n\n+++++++++++++ Performing Put/Replace on sflow leaf node ++++++++++++") + url = "/openconfig-sampling-sflow:sampling/sflow/config" url_body_json = "{ \"openconfig-sampling-sflow:enabled\": true, \"openconfig-sampling-sflow:polling-interval\": 100, \"openconfig-sampling-sflow:agent\": \"Ethernet0\"}" - pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet0" , "polling_interval":"100"}}} - expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet0" , "polling_interval":"300"}}} - cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - loadDB(db.ConfigDB, pre_req_map) - time.Sleep(1 * time.Second) - url = "/openconfig-sampling-sflow:sampling/sflow/config/polling-interval" + pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} + expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "300"}}} + cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} + loadDB(db.ConfigDB, pre_req_map) + time.Sleep(1 * time.Second) + url = "/openconfig-sampling-sflow:sampling/sflow/config/polling-interval" url_body_json = "{ \"openconfig-sampling-sflow:polling-interval\": 300}" - t.Run("Update polling-interval on sflow node", processSetRequest(url, url_body_json, "PUT", false, nil)) - time.Sleep(1 * time.Second) - t.Run("Verify polling-interval on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) - time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) - time.Sleep(1 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Put/Replace on sflow leaf node ++++++++++++") + t.Run("Update polling-interval on sflow node", processSetRequest(url, url_body_json, "PUT", false, nil)) + time.Sleep(1 * time.Second) + t.Run("Verify polling-interval on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) + time.Sleep(1 * time.Second) + unloadDB(db.ConfigDB, cleanuptbl) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Put/Replace on sflow leaf node ++++++++++++") - t.Log("\n\n+++++++++++++ Performing Patch on sflow leaf node ++++++++++++") - url = "/openconfig-sampling-sflow:sampling/sflow/config" + t.Log("\n\n+++++++++++++ Performing Patch on sflow leaf node ++++++++++++") + url = "/openconfig-sampling-sflow:sampling/sflow/config" url_body_json = "{ \"openconfig-sampling-sflow:enabled\": true, \"openconfig-sampling-sflow:polling-interval\": 100, \"openconfig-sampling-sflow:agent\": \"Ethernet0\"}" - pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet0" , "polling_interval":"100"}}} - expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet4" , "polling_interval":"100"}}} - cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - loadDB(db.ConfigDB, pre_req_map) - time.Sleep(1 * time.Second) - url = "/openconfig-sampling-sflow:sampling/sflow/config/agent" + pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} + expected_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet4", "polling_interval": "100"}}} + cleanuptbl = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} + loadDB(db.ConfigDB, pre_req_map) + time.Sleep(1 * time.Second) + url = "/openconfig-sampling-sflow:sampling/sflow/config/agent" url_body_json = "{ \"openconfig-sampling-sflow:agent\": \"Ethernet4\"}" - t.Run("Update Agent on sflow node", processSetRequest(url, url_body_json, "PATCH", false, nil)) - time.Sleep(1 * time.Second) - t.Run("Verify Agent on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) - time.Sleep(1 * time.Second) - unloadDB(db.ConfigDB, cleanuptbl) - time.Sleep(1 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Patch on sflow leaf node ++++++++++++") + t.Run("Update Agent on sflow node", processSetRequest(url, url_body_json, "PATCH", false, nil)) + time.Sleep(1 * time.Second) + t.Run("Verify Agent on sflow node", verifyDbResult(rclient, "SFLOW|global", expected_map, false)) + time.Sleep(1 * time.Second) + unloadDB(db.ConfigDB, cleanuptbl) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Patch on sflow leaf node ++++++++++++") } func Test_node_openconfig_sflow_collector(t *testing.T) { - var pre_req_map, expected_map, cleanuptbl map[string]interface{} - var url, url_body_json string + var pre_req_map, expected_map, cleanuptbl map[string]interface{} + var url, url_body_json string - t.Log("\n\n+++++++++++++ Performing Set on Collector ++++++++++++") - url = "/openconfig-sampling-sflow:sampling/sflow/collectors" + t.Log("\n\n+++++++++++++ Performing Set on Collector ++++++++++++") + url = "/openconfig-sampling-sflow:sampling/sflow/collectors" url_body_json = "{ \"openconfig-sampling-sflow:collector\": [ { \"address\": \"1.1.1.1\", \"port\": 6343, \"network-instance\": \"default\", \"config\": { \"address\": \"1.1.1.1\", \"port\": 6343, \"network-instance\": \"default\" } } ]}" expected_map = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"1.1.1.1_6343_default": map[string]interface{}{ - "collector_ip": "1.1.1.1", + "collector_ip": "1.1.1.1", "collector_port": "6343", - "collector_vrf": "default"}}} - cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"1.1.1.1_6343_default": ""}} - t.Run("Test set on collector node for sflow", processSetRequest(url, url_body_json, "POST", false, nil)) - time.Sleep(1 * time.Second) - t.Run("Verify set on collector node for sflow", verifyDbResult(rclient, "SFLOW_COLLECTOR|1.1.1.1_6343_default", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) - time.Sleep(1 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Set on Collector ++++++++++++") + "collector_vrf": "default"}}} + cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"1.1.1.1_6343_default": ""}} + t.Run("Test set on collector node for sflow", processSetRequest(url, url_body_json, "POST", false, nil)) + time.Sleep(1 * time.Second) + t.Run("Verify set on collector node for sflow", verifyDbResult(rclient, "SFLOW_COLLECTOR|1.1.1.1_6343_default", expected_map, false)) + unloadDB(db.ConfigDB, cleanuptbl) + time.Sleep(1 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Set on Collector ++++++++++++") t.Log("\n\n+++++++++++++ Performing Delete on Collector ++++++++++++") pre_req_map = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"2.2.2.2_4444_default": map[string]interface{}{ - "collector_ip": "2.2.2.2", + "collector_ip": "2.2.2.2", "collector_port": "4444", - "collector_vrf": "default"}}} - cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"2.2.2.2_4444_default": ""}} + "collector_vrf": "default"}}} + cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"2.2.2.2_4444_default": ""}} loadDB(db.ConfigDB, pre_req_map) time.Sleep(1 * time.Second) url = "/openconfig-sampling-sflow:sampling/sflow/collectors/collector[address=2.2.2.2][port=4444][network-instance=default]" t.Run("Test delete on collector for sflow", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) delete_expected := make(map[string]interface{}) - t.Run("Verify delete on collector node for sflow", verifyDbResult(rclient, "SFLOW_COLLECTOR|2.2.2.2_4444_default", delete_expected, false)) + t.Run("Verify delete on collector node for sflow", verifyDbResult(rclient, "SFLOW_COLLECTOR|2.2.2.2_4444_default", delete_expected, false)) unloadDB(db.ConfigDB, cleanuptbl) time.Sleep(1 * time.Second) t.Log("\n\n+++++++++++++ Done Performing Delete on Collector ++++++++++++") t.Log("\n\n+++++++++++++ Performing Get on Collector ++++++++++++") pre_req_map = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"3.3.3.3_6666_default": map[string]interface{}{ - "collector_ip": "3.3.3.3", + "collector_ip": "3.3.3.3", "collector_port": "6666", - "collector_vrf": "default"}}} + "collector_vrf": "default"}}} loadDB(db.ConfigDB, pre_req_map) expected_get_json := "{ \"openconfig-sampling-sflow:collectors\":{\"collector\":[{\"address\":\"3.3.3.3\",\"config\":{\"address\":\"3.3.3.3\",\"network-instance\":\"default\",\"port\":6666},\"network-instance\":\"default\",\"port\":6666,\"state\":{\"address\":\"3.3.3.3\",\"network-instance\":\"default\",\"port\":6666}}]}}" - url = "/openconfig-sampling-sflow:sampling/sflow/collectors" + url = "/openconfig-sampling-sflow:sampling/sflow/collectors" t.Run("Test get on collector node for sflow", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(1 * time.Second) cleanuptbl = map[string]interface{}{"SFLOW_COLLECTOR": map[string]interface{}{"3.3.3.3_6666_default": ""}} @@ -161,27 +159,26 @@ func Test_node_openconfig_sflow_collector(t *testing.T) { t.Log("\n\n+++++++++++++ Done Performing Get on Collector ++++++++++++") } - func Test_node_openconfig_sflow_interface(t *testing.T) { - var pre_req_map, non_pre_req_map, expected_map, cleanuptbl , cleanuptbl_sflow map[string]interface{} - var url, url_body_json string + var pre_req_map, non_pre_req_map, expected_map, cleanuptbl, cleanuptbl_sflow map[string]interface{} + var url, url_body_json string //Sflow needs to be enabled to configure for an sflow interface - t.Log("\n\n+++++++++++++ Performing Set on Sflow Interface ++++++++++++") - url = "/openconfig-sampling-sflow:sampling/sflow/interfaces" + t.Log("\n\n+++++++++++++ Performing Set on Sflow Interface ++++++++++++") + url = "/openconfig-sampling-sflow:sampling/sflow/interfaces" url_body_json = "{ \"openconfig-sampling-sflow:interface\": [ { \"name\": \"Ethernet0\", \"config\": { \"name\": \"Ethernet0\", \"enabled\": true, \"sampling-rate\": 10000 } } ]}" - pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id":"Ethernet0" , "polling_interval":"100"}}} - loadDB(db.ConfigDB, pre_req_map) + pre_req_map = map[string]interface{}{"SFLOW": map[string]interface{}{"global": map[string]interface{}{"admin_state": "up", "agent_id": "Ethernet0", "polling_interval": "100"}}} + loadDB(db.ConfigDB, pre_req_map) expected_map = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": map[string]interface{}{ "admin_state": "up", "sample_rate": "10000"}}} - cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} - t.Run("Test set on sflow interface", processSetRequest(url, url_body_json, "POST", false, nil)) - time.Sleep(2 * time.Second) - t.Run("Verify set on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) - time.Sleep(2 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Set on Sflow interface ++++++++++++") + cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} + t.Run("Test set on sflow interface", processSetRequest(url, url_body_json, "POST", false, nil)) + time.Sleep(2 * time.Second) + t.Run("Verify set on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) + unloadDB(db.ConfigDB, cleanuptbl) + time.Sleep(2 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Set on Sflow interface ++++++++++++") t.Log("\n\n+++++++++++++ Performing Delete on Sflow interface ++++++++++++") pre_req_map = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet4": map[string]interface{}{ @@ -190,7 +187,7 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { non_pre_req_map = map[string]interface{}{"SFLOW_SESSION_TABLE": map[string]interface{}{"Ethernet4": map[string]interface{}{ "admin_state": "down", "sample_rate": "20000"}}} - cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet4": ""}} + cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet4": ""}} loadDB(db.ConfigDB, pre_req_map) loadDB(db.ApplDB, non_pre_req_map) time.Sleep(2 * time.Second) @@ -198,7 +195,7 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { t.Run("Test delete on sflow interface", processDeleteRequest(url, false)) time.Sleep(2 * time.Second) delete_expected := make(map[string]interface{}) - t.Run("Verify delete on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet4", delete_expected, false)) + t.Run("Verify delete on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet4", delete_expected, false)) unloadDB(db.ConfigDB, cleanuptbl) unloadDB(db.ApplDB, non_pre_req_map) time.Sleep(2 * time.Second) @@ -214,7 +211,7 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { loadDB(db.ConfigDB, pre_req_map) loadDB(db.ApplDB, non_pre_req_map) expected_get_json := "{\"openconfig-sampling-sflow:state\":{\"enabled\":true,\"name\":\"Ethernet8\",\"sampling-rate\":30000}}" - url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet8]/state" + url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet8]/state" t.Run("Test get on sflow interface", processGetRequest(url, nil, expected_get_json, false)) time.Sleep(2 * time.Second) cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet8": ""}} @@ -222,7 +219,7 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { unloadDB(db.ApplDB, non_pre_req_map) t.Log("\n\n+++++++++++++ Done Performing Get on SFlow Interface ++++++++++++") - t.Log("\n\n+++++++++++++ Performing Put/Replace on Sflow Interface ++++++++++++") + t.Log("\n\n+++++++++++++ Performing Put/Replace on Sflow Interface ++++++++++++") pre_req_map = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": map[string]interface{}{ "admin_state": "up", "sample_rate": "10000"}}} @@ -232,20 +229,20 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { expected_map = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": map[string]interface{}{ "admin_state": "down", "sample_rate": "10000"}}} - cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} - loadDB(db.ConfigDB, pre_req_map) - loadDB(db.ApplDB, non_pre_req_map) - url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet0]/config/enabled" + cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} + loadDB(db.ConfigDB, pre_req_map) + loadDB(db.ApplDB, non_pre_req_map) + url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet0]/config/enabled" url_body_json = "{ \"openconfig-sampling-sflow:enabled\": false}" - t.Run("Update admin-state for sflow interface", processSetRequest(url, url_body_json, "PUT", false, nil)) - time.Sleep(2 * time.Second) - t.Run("Verify admin-state for sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) - unloadDB(db.ApplDB, non_pre_req_map) - time.Sleep(2 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Put/Replace on Sflow interface ++++++++++++") + t.Run("Update admin-state for sflow interface", processSetRequest(url, url_body_json, "PUT", false, nil)) + time.Sleep(2 * time.Second) + t.Run("Verify admin-state for sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) + unloadDB(db.ConfigDB, cleanuptbl) + unloadDB(db.ApplDB, non_pre_req_map) + time.Sleep(2 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Put/Replace on Sflow interface ++++++++++++") - t.Log("\n\n+++++++++++++ Performing Patch on Sflow Interface ++++++++++++") + t.Log("\n\n+++++++++++++ Performing Patch on Sflow Interface ++++++++++++") pre_req_map = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": map[string]interface{}{ "admin_state": "up", "sample_rate": "10000"}}} @@ -255,26 +252,26 @@ func Test_node_openconfig_sflow_interface(t *testing.T) { expected_map = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": map[string]interface{}{ "admin_state": "up", "sample_rate": "20000"}}} - cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} - loadDB(db.ConfigDB, pre_req_map) - loadDB(db.ApplDB, non_pre_req_map) - cleanuptbl_sflow = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} - url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet0]/config/sampling-rate" + cleanuptbl = map[string]interface{}{"SFLOW_SESSION": map[string]interface{}{"Ethernet0": ""}} + loadDB(db.ConfigDB, pre_req_map) + loadDB(db.ApplDB, non_pre_req_map) + cleanuptbl_sflow = map[string]interface{}{"SFLOW": map[string]interface{}{"global": ""}} + url = "/openconfig-sampling-sflow:sampling/sflow/interfaces/interface[name=Ethernet0]/config/sampling-rate" url_body_json = "{ \"openconfig-sampling-sflow:sampling-rate\": 20000}" - t.Run("Update sampling-rate on sflow interface", processSetRequest(url, url_body_json, "PATCH", false, nil)) - time.Sleep(2 * time.Second) - t.Run("Verify sampling-rate on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) - unloadDB(db.ConfigDB, cleanuptbl) + t.Run("Update sampling-rate on sflow interface", processSetRequest(url, url_body_json, "PATCH", false, nil)) + time.Sleep(2 * time.Second) + t.Run("Verify sampling-rate on sflow interface", verifyDbResult(rclient, "SFLOW_SESSION|Ethernet0", expected_map, false)) + unloadDB(db.ConfigDB, cleanuptbl) unloadDB(db.ConfigDB, cleanuptbl_sflow) - unloadDB(db.ApplDB, non_pre_req_map) - time.Sleep(2 * time.Second) - t.Log("\n\n+++++++++++++ Done Performing Patch on Sflow interface ++++++++++++") + unloadDB(db.ApplDB, non_pre_req_map) + time.Sleep(2 * time.Second) + t.Log("\n\n+++++++++++++ Done Performing Patch on Sflow interface ++++++++++++") t.Log("\n\n+++++++++++++ Performing Delete on Interfaces when sflow is disabled ++++++++++++") //Sflow global interfaces deletion is not supported url = "/openconfig-sampling-sflow:sampling/sflow/interfaces" err_str := "DELETE not supported" expected_err := tlerr.NotSupportedError{Format: err_str} - t.Run("Test delete on sflow interfaces", processDeleteRequest(url, true, expected_err )) + t.Run("Test delete on sflow interfaces", processDeleteRequest(url, true, expected_err)) t.Log("\n\n+++++++++++++ Done Delete on Interfaces when sflow is disabled ++++++++++++") } diff --git a/translib/transformer/sflow_sonic_test.go b/translib/transformer/sflow_sonic_test.go index 7c3a7655e..1cc4bc35d 100644 --- a/translib/transformer/sflow_sonic_test.go +++ b/translib/transformer/sflow_sonic_test.go @@ -22,19 +22,18 @@ package transformer_test import ( - "testing" - "time" "github.com/Azure/sonic-mgmt-common/translib/tlerr" + "testing" + "time" ) - func Test_node_sonic_sflow(t *testing.T) { - var url, url_body_json string + var url, url_body_json string //Add sflow node url = "/sonic-sflow:sonic-sflow/SFLOW" url_body_json = "{ \"sonic-sflow:global\": { \"admin_state\": \"down\", \"polling_interval\": 0, \"agent_id\": \"Ethernet0\" }}" - t.Run("Add sFlow collector", processSetRequest(url, url_body_json, "POST", false,nil)) + t.Run("Add sFlow collector", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) //Set admin state @@ -72,12 +71,12 @@ func Test_node_sonic_sflow(t *testing.T) { } func Test_node_sonic_sflow_collector(t *testing.T) { - var url, url_body_json string + var url, url_body_json string //Add sFlow collector url = "/sonic-sflow:sonic-sflow/SFLOW_COLLECTOR" url_body_json = "{ \"sonic-sflow:SFLOW_COLLECTOR_LIST\": [ { \"name\": \"1.1.1.1_6343_default\", \"collector_ip\": \"1.1.1.1\", \"collector_port\": 6343, \"collector_vrf\": \"default\" } ]}" - t.Run("Add sFlow collector", processSetRequest(url, url_body_json, "POST", false,nil)) + t.Run("Add sFlow collector", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) // Verify sFlow collector configurations @@ -108,18 +107,18 @@ func Test_node_sonic_sflow_collector(t *testing.T) { } func Test_node_sonic_sflow_interface(t *testing.T) { - var url, url_body_json string + var url, url_body_json string //Sflow needs to be enabled to configure for the interface url = "/sonic-sflow:sonic-sflow/SFLOW" url_body_json = "{ \"sonic-sflow:global\": { \"admin_state\": \"up\", \"polling_interval\": 0, \"agent_id\": \"Ethernet0\" }}" - t.Run("Enable sFlow", processSetRequest(url, url_body_json, "POST", false,nil)) + t.Run("Enable sFlow", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) //Configure for the sflow interface url = "/sonic-sflow:sonic-sflow/SFLOW_SESSION" url_body_json = "{ \"sonic-sflow:SFLOW_SESSION_LIST\": [ { \"port\": \"Ethernet0\", \"admin_state\": \"up\", \"sample_rate\": 10000 } ]}" - t.Run("Configure sFlow interface", processSetRequest(url, url_body_json, "POST", false,nil)) + t.Run("Configure sFlow interface", processSetRequest(url, url_body_json, "POST", false, nil)) time.Sleep(1 * time.Second) //Changing the sampling-rate @@ -128,7 +127,7 @@ func Test_node_sonic_sflow_interface(t *testing.T) { t.Run("Configuring the sampling_rate in sflow interface", processSetRequest(url, url_body_json, "PATCH", false)) time.Sleep(1 * time.Second) - //Deleting the configured interface + //Deleting the configured interface url = "/sonic-sflow:sonic-sflow/SFLOW_SESSION/SFLOW_SESSION_LIST[port=Ethernet0]" t.Run("Delete on configured sflow interface", processDeleteRequest(url, false)) time.Sleep(1 * time.Second) @@ -136,7 +135,7 @@ func Test_node_sonic_sflow_interface(t *testing.T) { //Verify the deleted sflow interface url_body_json = "{}" err_str := "Resource not found" - expected_err := tlerr.NotFoundError{Format: err_str} + expected_err := tlerr.NotFoundError{Format: err_str} t.Run("Verify delete on sFlow Interface", processGetRequest(url, nil, url_body_json, true, expected_err)) //Delete sflow global configurations @@ -147,5 +146,5 @@ func Test_node_sonic_sflow_interface(t *testing.T) { //Verify deleted sflow global configuration url = "/sonic-sflow:sonic-sflow/SFLOW" url_body_json = "{}" - t.Run("Verify delete on sFlow collector", processGetRequest(url, nil, url_body_json, false)) + t.Run("Verify delete on sFlow collector", processGetRequest(url, nil, url_body_json, false)) } diff --git a/translib/transformer/testxfmryang_test.go b/translib/transformer/testxfmryang_test.go index b3951ad9f..5cefb77d4 100644 --- a/translib/transformer/testxfmryang_test.go +++ b/translib/transformer/testxfmryang_test.go @@ -818,8 +818,11 @@ func Test_OC_Sonic_OneOnOne_Composite_KeyMapping(t *testing.T) { unloadDB(db.ConfigDB, parent_prereq) } -/*Test OC List having config container with leaves, that are referenced by list key-leafs and have no annotation. - Also covers the list's state container that have leaves same as list keys */ +/* +Test OC List having config container with leaves, that are referenced by list key-leafs and have no annotation. + + Also covers the list's state container that have leaves same as list keys +*/ func Test_NodeWithListHavingConfigLeafRefByKey_OC_Yang(t *testing.T) { t.Log("++++++++++++++ Test_set_on_OC_yang_node_with_list_having_config_leaf_referenced_by_list_key +++++++++++++") diff --git a/translib/transformer/transformer_test.go b/translib/transformer/transformer_test.go index 7504380b5..1a98df0e4 100644 --- a/translib/transformer/transformer_test.go +++ b/translib/transformer/transformer_test.go @@ -139,10 +139,10 @@ func prepareDb() bool { rclient = rclientDBNum[db.ConfigDB] rclientDBNum[db.ApplDB] = getDbClient(int(db.ApplDB)) - if rclientDBNum[db.ApplDB] == nil { - fmt.Printf("error in getDbClient(int(db.ApplDB)") - return false - } + if rclientDBNum[db.ApplDB] == nil { + fmt.Printf("error in getDbClient(int(db.ApplDB)") + return false + } return true } diff --git a/translib/transformer/utils_test.go b/translib/transformer/utils_test.go index ef3e0db3b..e54193a6c 100644 --- a/translib/transformer/utils_test.go +++ b/translib/transformer/utils_test.go @@ -107,7 +107,7 @@ func processGetRequestWithFile(url string, expectedJsonFile string, errorCase bo } else if expErr != nil { checkErr(t, err, expErr[0]) } - return + return } respJson := response.Payload diff --git a/translib/transformer/xfmr_path_utils.go b/translib/transformer/xfmr_path_utils.go index 6fbd8830e..26a05c745 100644 --- a/translib/transformer/xfmr_path_utils.go +++ b/translib/transformer/xfmr_path_utils.go @@ -22,8 +22,8 @@ type PathInfo struct { // HasVar checks if the PathInfo contains given variable. func (p *PathInfo) HasVar(name string) bool { - _, exists := p.Vars[name] - return exists + _, exists := p.Vars[name] + return exists } // Var returns the string value for a path variable. Returns @@ -51,14 +51,14 @@ func NewPathInfo(path string) *PathInfo { name := readUntil(r, '=') value := readUntil(r, ']') - // Handle duplicate parameter names by suffixing "#N" to it. - // N is the number of occurance of that parameter name. - if info.HasVar(name) { - namePrefix := name - for k := 2; info.HasVar(name); k++ { - name = fmt.Sprintf("%s#%d", namePrefix, k) - } - } + // Handle duplicate parameter names by suffixing "#N" to it. + // N is the number of occurance of that parameter name. + if info.HasVar(name) { + namePrefix := name + for k := 2; info.HasVar(name); k++ { + name = fmt.Sprintf("%s#%d", namePrefix, k) + } + } if len(name) != 0 { fmt.Fprintf(&template, "{}") @@ -72,22 +72,22 @@ func NewPathInfo(path string) *PathInfo { } func readUntil(r *strings.Reader, delim byte) string { - var buff strings.Builder - var escaped bool - - for { - c, err := r.ReadByte() - if err != nil || (c == delim && !escaped) { - break - } else if c == '\\' && !escaped { - escaped = true - } else { - escaped = false - buff.WriteByte(c) - } - } - - return buff.String() + var buff strings.Builder + var escaped bool + + for { + c, err := r.ReadByte() + if err != nil || (c == delim && !escaped) { + break + } else if c == '\\' && !escaped { + escaped = true + } else { + escaped = false + buff.WriteByte(c) + } + } + + return buff.String() } // SplitPath splits the ygot path into parts. diff --git a/translib/transformer/xfmr_sflow.go b/translib/transformer/xfmr_sflow.go index f035dc7bb..214a0c927 100644 --- a/translib/transformer/xfmr_sflow.go +++ b/translib/transformer/xfmr_sflow.go @@ -243,7 +243,7 @@ var YangToDb_sflow_xfmr SubTreeXfmrYangToDb = func(inParams XfmrParams) (map[str } if sflowObj.Sflow.Config.Agent != nil { - global_map[SFLOW_GLOBAL_KEY].Field[SFLOW_AGENT_KEY] = *(sflowObj.Sflow.Config.Agent) + global_map[SFLOW_GLOBAL_KEY].Field[SFLOW_AGENT_KEY] = *(sflowObj.Sflow.Config.Agent) } res_map[SFLOW_GLOBAL_TBL] = global_map @@ -277,7 +277,6 @@ var YangToDb_sflow_collector_xfmr SubTreeXfmrYangToDb = func(inParams XfmrParams col_map := make(map[string]db.Value) sflowObj := getSflowRootObject(inParams.ygRoot) - key := makeColKey(inParams.uri) if inParams.oper == DELETE { if key != "" { diff --git a/translib/transformer/xfmr_showtech.go b/translib/transformer/xfmr_showtech.go index 5aa98f600..c73937205 100644 --- a/translib/transformer/xfmr_showtech.go +++ b/translib/transformer/xfmr_showtech.go @@ -19,82 +19,81 @@ package transformer import ( - "encoding/json" - "github.com/Azure/sonic-mgmt-common/translib/tlerr" - "github.com/Azure/sonic-mgmt-common/translib/db" - "github.com/golang/glog" - "regexp" + "encoding/json" + "github.com/Azure/sonic-mgmt-common/translib/db" + "github.com/Azure/sonic-mgmt-common/translib/tlerr" + "github.com/golang/glog" + "regexp" ) func init() { - XlateFuncBind("rpc_showtech_cb", rpc_showtech_cb) + XlateFuncBind("rpc_showtech_cb", rpc_showtech_cb) } var rpc_showtech_cb RpcCallpoint = func(body []byte, dbs [db.MaxDB]*db.DB) ([]byte, error) { - var err error - var matched bool - var output string - var operand struct { - Input struct { - Date string `json:"date"` - } `json:"sonic-show-techsupport:input"` - } + var err error + var matched bool + var output string + var operand struct { + Input struct { + Date string `json:"date"` + } `json:"sonic-show-techsupport:input"` + } - err = json.Unmarshal(body, &operand) - if err != nil { - glog.Errorf("%Error: Failed to parse rpc input; err=%v", err) - return nil,tlerr.InvalidArgs("Invalid rpc input") - } + err = json.Unmarshal(body, &operand) + if err != nil { + glog.Errorf("%Error: Failed to parse rpc input; err=%v", err) + return nil, tlerr.InvalidArgs("Invalid rpc input") + } - if operand.Input.Date == "" { - matched = true - } else { - matched, _ = regexp.MatchString((`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?` + - `(Z|[\+\-]\d{2}:\d{2})`), operand.Input.Date) - if err != nil { - glog.Errorf("%Error: Failed to match regex pattern for parsesd rpc input; err=%v", err) - } + if operand.Input.Date == "" { + matched = true + } else { + matched, _ = regexp.MatchString((`\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?` + + `(Z|[\+\-]\d{2}:\d{2})`), operand.Input.Date) + if err != nil { + glog.Errorf("%Error: Failed to match regex pattern for parsesd rpc input; err=%v", err) + } - } + } - var showtech struct { - Output struct { - Status string `json:"output-status"` - Filename string `json:"output-filename"` - } `json:"sonic-show-techsupport:output"` - } + var showtech struct { + Output struct { + Status string `json:"output-status"` + Filename string `json:"output-filename"` + } `json:"sonic-show-techsupport:output"` + } - if !(matched) { - showtech.Output.Status = "Invalid input: Incorrect DateTime format" - showtech.Output.Filename = "" - result, _ := json.Marshal(&showtech) - return result, nil - } + if !(matched) { + showtech.Output.Status = "Invalid input: Incorrect DateTime format" + showtech.Output.Filename = "" + result, _ := json.Marshal(&showtech) + return result, nil + } - host_output := HostQuery("showtech.info", operand.Input.Date) - if host_output.Err != nil { - glog.Errorf("%Error: Showtech host Query failed: err=%v", host_output.Err) - glog.Flush() - showtech.Output.Status = host_output.Err.Error() - showtech.Output.Filename = "" - result, _ := json.Marshal(&showtech) - return result, nil - } + host_output := HostQuery("showtech.info", operand.Input.Date) + if host_output.Err != nil { + glog.Errorf("%Error: Showtech host Query failed: err=%v", host_output.Err) + glog.Flush() + showtech.Output.Status = host_output.Err.Error() + showtech.Output.Filename = "" + result, _ := json.Marshal(&showtech) + return result, nil + } - output, _ = host_output.Body[1].(string) - matched, _ = regexp.MatchString(`\/var\/.*dump.*\.gz`, output) - if err != nil { - glog.Errorf("%Error: Failed to find a filename in rpc output: %v", output) - showtech.Output.Status = output - showtech.Output.Filename = "" - result, _ := json.Marshal(&showtech) - return result, nil - } + output, _ = host_output.Body[1].(string) + matched, _ = regexp.MatchString(`\/var\/.*dump.*\.gz`, output) + if err != nil { + glog.Errorf("%Error: Failed to find a filename in rpc output: %v", output) + showtech.Output.Status = output + showtech.Output.Filename = "" + result, _ := json.Marshal(&showtech) + return result, nil + } - showtech.Output.Status = "Success" - showtech.Output.Filename = output - result, _ := json.Marshal(&showtech) + showtech.Output.Status = "Success" + showtech.Output.Filename = output + result, _ := json.Marshal(&showtech) - return result, nil + return result, nil } - diff --git a/translib/transformer/xfmr_testxfmr_callbacks.go b/translib/transformer/xfmr_testxfmr_callbacks.go index c4acdc547..e9b35893d 100644 --- a/translib/transformer/xfmr_testxfmr_callbacks.go +++ b/translib/transformer/xfmr_testxfmr_callbacks.go @@ -670,7 +670,7 @@ func convertSonicTestSetTypeToOC(testSetType string) ocbinds.E_OpenconfigTestXfm return testSetOrigType } -//Sonic yang key transformer functions +// Sonic yang key transformer functions var DbToYang_test_sensor_mode_key_xfmr SonicKeyXfmrDbToYang = func(inParams SonicXfmrParams) (map[string]interface{}, error) { res_map := make(map[string]interface{}) /* from DB-key string(inParams.key) extract mode and id to fill into the res_map diff --git a/translib/transformer/xlate_datastructs.go b/translib/transformer/xlate_datastructs.go index 25a7686f3..9c7cf176f 100644 --- a/translib/transformer/xlate_datastructs.go +++ b/translib/transformer/xlate_datastructs.go @@ -140,7 +140,6 @@ type qpSubtreePruningErr struct { type Operation int - type ContentType uint8 type QueryParams struct { @@ -165,4 +164,3 @@ type ygotUnMarshalCtx struct { type ygotXlator struct { ygotCtx *ygotUnMarshalCtx } - diff --git a/translib/transformer/xlate_tbl_info.go b/translib/transformer/xlate_tbl_info.go index 4edcc85bf..e7c499479 100644 --- a/translib/transformer/xlate_tbl_info.go +++ b/translib/transformer/xlate_tbl_info.go @@ -110,7 +110,7 @@ func ordTblListCreate(ordTblList map[string][]string, tnMap map[string]*gphNode) } } -//sort transformer result table list based on dependenciesi(using CVL API) tables to be used for CRUD operations +// sort transformer result table list based on dependenciesi(using CVL API) tables to be used for CRUD operations func sortPerTblDeps(ordTblListMap map[string][]string) error { var err error diff --git a/translib/transformer/xlate_to_db.go b/translib/transformer/xlate_to_db.go index 6e04a8ead..24a30e082 100644 --- a/translib/transformer/xlate_to_db.go +++ b/translib/transformer/xlate_to_db.go @@ -1111,8 +1111,11 @@ func verifyParentTableSonic(d *db.DB, dbs [db.MaxDB]*db.DB, oper Operation, uri } } -/* This function checks the existence of Parent tables in DB for the given URI request - and returns a boolean indicating if the operation is permitted based on the operation type*/ +/* +This function checks the existence of Parent tables in DB for the given URI request + + and returns a boolean indicating if the operation is permitted based on the operation type +*/ func verifyParentTable(d *db.DB, dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, oper Operation, uri string, dbData RedisDbMap, txCache interface{}, subOpDataMap map[Operation]*RedisDbMap) (bool, error) { xfmrLogDebug("Checking for Parent table existence for uri: %v", uri) if isSonicYang(uri) { diff --git a/translib/utils/utils.go b/translib/utils/utils.go index 466c618bf..13517c9fb 100644 --- a/translib/utils/utils.go +++ b/translib/utils/utils.go @@ -17,55 +17,51 @@ // // //////////////////////////////////////////////////////////////////////////////// - package utils import ( - //"github.com/Azure/sonic-mgmt-common/translib/db" - "github.com/Azure/sonic-mgmt-common/cvl" - "fmt" - log "github.com/golang/glog" + //"github.com/Azure/sonic-mgmt-common/translib/db" + "fmt" + "github.com/Azure/sonic-mgmt-common/cvl" + log "github.com/golang/glog" ) // SortAsPerTblDeps - sort transformer result table list based on dependencies (using CVL API) tables to be used for CRUD operations func SortAsPerTblDeps(tblLst []string) ([]string, error) { - var resultTblLst []string - var err error - logStr := "Failure in CVL API to sort table list as per dependencies." + var resultTblLst []string + var err error + logStr := "Failure in CVL API to sort table list as per dependencies." - cvSess, cvlRetSess := cvl.ValidationSessOpen() - if cvlRetSess != cvl.CVL_SUCCESS { + cvSess, cvlRetSess := cvl.ValidationSessOpen() + if cvlRetSess != cvl.CVL_SUCCESS { - log.Errorf("Failure in creating CVL validation session object required to use CVl API(sort table list as per dependencies) - %v", cvlRetSess) - err = fmt.Errorf("%v", logStr) - return resultTblLst, err - } - cvlSortDepTblList, cvlRetDepTbl := cvSess.SortDepTables(tblLst) - if cvlRetDepTbl != cvl.CVL_SUCCESS { - log.Warningf("Failure in cvlSess.SortDepTables: %v", cvlRetDepTbl) - cvl.ValidationSessClose(cvSess) - err = fmt.Errorf("%v", logStr) - return resultTblLst, err - } - log.Info("cvlSortDepTblList = ", cvlSortDepTblList) - resultTblLst = cvlSortDepTblList + log.Errorf("Failure in creating CVL validation session object required to use CVl API(sort table list as per dependencies) - %v", cvlRetSess) + err = fmt.Errorf("%v", logStr) + return resultTblLst, err + } + cvlSortDepTblList, cvlRetDepTbl := cvSess.SortDepTables(tblLst) + if cvlRetDepTbl != cvl.CVL_SUCCESS { + log.Warningf("Failure in cvlSess.SortDepTables: %v", cvlRetDepTbl) + cvl.ValidationSessClose(cvSess) + err = fmt.Errorf("%v", logStr) + return resultTblLst, err + } + log.Info("cvlSortDepTblList = ", cvlSortDepTblList) + resultTblLst = cvlSortDepTblList - cvl.ValidationSessClose(cvSess) - return resultTblLst, err + cvl.ValidationSessClose(cvSess) + return resultTblLst, err } // RemoveElement - Remove a specific string from a list of strings func RemoveElement(sl []string, str string) []string { - for i := 0; i < len(sl); i++ { - if sl[i] == str { - sl = append(sl[:i], sl[i+1:]...) - i-- - break - } - } - return sl + for i := 0; i < len(sl); i++ { + if sl[i] == str { + sl = append(sl[:i], sl[i+1:]...) + i-- + break + } + } + return sl } - - - diff --git a/translib/version.go b/translib/version.go index 4676a2703..297af7327 100644 --- a/translib/version.go +++ b/translib/version.go @@ -22,10 +22,10 @@ package translib import ( "encoding/xml" "fmt" - "os" - "path/filepath" "github.com/Azure/sonic-mgmt-common/translib/tlerr" "github.com/golang/glog" + "os" + "path/filepath" ) // theYangBundleVersion indicates the current yang bundle version.