Skip to content

Commit 80f369e

Browse files
authored
CVL Changes sonic-net#5: YParser enhancement (sonic-net#23)
Adding following YParser enhancement : Add multiple nodes to the tree from array instead of using "#" delimiter Read YIN file schema Read leafref, must, when expression details API IsLeafrefMatchedInUnion() to check if data instance type in union is of leafref type.
1 parent 904ce18 commit 80f369e

File tree

4 files changed

+522
-60
lines changed

4 files changed

+522
-60
lines changed

cvl/cvl.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ type CVL struct {
106106
yp *yparser.YParser
107107
tmpDbCache map[string]interface{} //map of table storing map of key-value pair
108108
requestCache map[string]map[string][]*requestCacheType//Cache of validated data,
109-
//per table, per key. Can be used as dependent data in next request
110-
batchLeaf string
109+
//per table, per key. Can be used as dependent data in next request
110+
batchLeaf []*yparser.YParserLeafValue //field name and value
111111
chkLeafRefWithOthCache bool
112112
yv *YValidator //Custom YANG validator for validating external dependencies
113113
}
@@ -1159,7 +1159,7 @@ func (c *CVL) validate (data *yparser.YParserNode) CVLRetCode {
11591159
return CVL_SUCCESS
11601160
}
11611161

1162-
func CreateCVLErrObj(errObj yparser.YParserError) CVLErrorInfo {
1162+
func createCVLErrObj(errObj yparser.YParserError) CVLErrorInfo {
11631163

11641164
cvlErrObj := CVLErrorInfo {
11651165
TableName : errObj.TableName,

cvl/cvl_syntax.go

+41-25
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package cvl
2121
import (
22-
"fmt"
2322
"github.com/antchfx/jsonquery"
2423
"github.com/Azure/sonic-mgmt-common/cvl/internal/yparser"
2524
//lint:ignore ST1001 This is safe to dot import for util package
@@ -33,15 +32,16 @@ func(c *CVL) addChildNode(tableName string, parent *yparser.YParserNode, name st
3332
return c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, parent, name)
3433
}
3534

36-
func (c *CVL) addChildLeaf(config bool, tableName string, parent *yparser.YParserNode, name string, value string) {
35+
func (c *CVL) addChildLeaf(config bool, tableName string, parent *yparser.YParserNode, name string, value string, multileaf *[]*yparser.YParserLeafValue) {
3736

3837
/* If there is no value then assign default space string. */
3938
if len(value) == 0 {
4039
value = " "
4140
}
4241

4342
//Batch leaf creation
44-
c.batchLeaf = c.batchLeaf + name + "#" + value + "#"
43+
*multileaf = append(*multileaf, &yparser.YParserLeafValue{Name: name, Value: value})
44+
4545
//Check if this leaf has leafref,
4646
//If so add the add redis key to its table so that those
4747
// details can be fetched for dependency validation
@@ -50,7 +50,8 @@ func (c *CVL) addChildLeaf(config bool, tableName string, parent *yparser.YParse
5050
}
5151

5252
func (c *CVL) generateTableFieldsData(config bool, tableName string, jsonNode *jsonquery.Node,
53-
parent *yparser.YParserNode) CVLRetCode {
53+
parent *yparser.YParserNode, multileaf *[]*yparser.YParserLeafValue) CVLErrorInfo {
54+
var cvlErrObj CVLErrorInfo
5455

5556
//Traverse fields
5657
for jsonFieldNode := jsonNode.FirstChild; jsonFieldNode!= nil;
@@ -61,32 +62,35 @@ parent *yparser.YParserNode) CVLRetCode {
6162
jsonFieldNode.FirstChild.Type == jsonquery.TextNode) {
6263

6364
if (len(modelInfo.tableInfo[tableName].mapLeaf) == 2) {//mapping should have two leaf always
65+
batchInnerListLeaf := make([]*yparser.YParserLeafValue, 0)
6466
//Values should be stored inside another list as map table
6567
listNode := c.addChildNode(tableName, parent, tableName) //Add the list to the top node
6668
c.addChildLeaf(config, tableName,
6769
listNode, modelInfo.tableInfo[tableName].mapLeaf[0],
68-
jsonFieldNode.Data)
70+
jsonFieldNode.Data, &batchInnerListLeaf)
6971

7072
c.addChildLeaf(config, tableName,
7173
listNode, modelInfo.tableInfo[tableName].mapLeaf[1],
72-
jsonFieldNode.FirstChild.Data)
74+
jsonFieldNode.FirstChild.Data, &batchInnerListLeaf)
7375

76+
if errObj := c.yp.AddMultiLeafNodes(modelInfo.tableInfo[tableName].module, listNode, batchInnerListLeaf); errObj.ErrCode != yparser.YP_SUCCESS {
77+
cvlErrObj = createCVLErrObj(errObj)
78+
CVL_LOG(ERROR, "Failed to create innner list leaf nodes, data = %v", batchInnerListLeaf)
79+
return cvlErrObj
80+
}
7481
} else {
7582
//check if it is hash-ref, then need to add only key from "TABLE|k1"
7683
hashRefMatch := reHashRef.FindStringSubmatch(jsonFieldNode.FirstChild.Data)
7784

78-
if (hashRefMatch != nil && len(hashRefMatch) == 3) {
79-
/*if (strings.HasPrefix(jsonFieldNode.FirstChild.Data, "[")) &&
80-
(strings.HasSuffix(jsonFieldNode.FirstChild.Data, "]")) &&
81-
(strings.Index(jsonFieldNode.FirstChild.Data, "|") > 0) {*/
85+
if len(hashRefMatch) == 3 {
8286

8387
c.addChildLeaf(config, tableName,
8488
parent, jsonFieldNode.Data,
85-
hashRefMatch[2]) //take hashref key value
89+
hashRefMatch[2], multileaf) //take hashref key value
8690
} else {
8791
c.addChildLeaf(config, tableName,
8892
parent, jsonFieldNode.Data,
89-
jsonFieldNode.FirstChild.Data)
93+
jsonFieldNode.FirstChild.Data, multileaf)
9094
}
9195
}
9296

@@ -99,28 +103,34 @@ parent *yparser.YParserNode) CVLRetCode {
99103
arrayNode = arrayNode.NextSibling {
100104
c.addChildLeaf(config, tableName,
101105
parent, jsonFieldNode.Data,
102-
arrayNode.FirstChild.Data)
106+
arrayNode.FirstChild.Data, multileaf)
103107
}
104108
}
105109
}
106110

107-
return CVL_SUCCESS
111+
cvlErrObj.ErrCode = CVL_SUCCESS
112+
return cvlErrObj
108113
}
109114

110115
func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser.YParserNode, CVLErrorInfo) {
111116
var cvlErrObj CVLErrorInfo
112117

113-
tableName := fmt.Sprintf("%s",jsonNode.Data)
114-
c.batchLeaf = ""
118+
tableName := jsonNode.Data
119+
c.batchLeaf = nil
120+
c.batchLeaf = make([]*yparser.YParserLeafValue, 0)
115121

116122
//Every Redis table is mapped as list within a container,
117123
//E.g. ACL_RULE is mapped as
118124
// container ACL_RULE { list ACL_RULE_LIST {} }
119125
var topNode *yparser.YParserNode
120126

121127
// Add top most conatiner e.g. 'container sonic-acl {...}'
122-
if _, exists := modelInfo.tableInfo[tableName]; exists == false {
123-
return nil, cvlErrObj
128+
if _, exists := modelInfo.tableInfo[tableName]; !exists {
129+
CVL_LOG(ERROR, "Schema details not found for %s", tableName)
130+
cvlErrObj.ErrCode = CVL_SYNTAX_ERROR
131+
cvlErrObj.TableName = tableName
132+
cvlErrObj.Msg ="Schema details not found"
133+
return nil, cvlErrObj
124134
}
125135
topNode = c.yp.AddChildNode(modelInfo.tableInfo[tableName].module,
126136
nil, modelInfo.tableInfo[tableName].modelName)
@@ -147,7 +157,7 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser.
147157
//Find number of all key combinations
148158
//Each key can have one or more key values, which results in nk1 * nk2 * nk2 combinations
149159
idx := 0
150-
for i,_ := range keyValuePair {
160+
for i := range keyValuePair {
151161
totalKeyComb = totalKeyComb * len(keyValuePair[i].values)
152162
keyIndices = append(keyIndices, 0)
153163
}
@@ -165,11 +175,13 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser.
165175
for idx = 0; idx < keyCompCount; idx++ {
166176
c.addChildLeaf(config, tableName,
167177
listNode, keyValuePair[idx].key,
168-
keyValuePair[idx].values[keyIndices[idx]])
178+
keyValuePair[idx].values[keyIndices[idx]], &c.batchLeaf)
169179
}
170180

171181
//Get all fields under the key field and add them as children of the list
172-
c.generateTableFieldsData(config, tableName, jsonNode, listNode)
182+
if fldDataErrObj := c.generateTableFieldsData(config, tableName, jsonNode, listNode, &c.batchLeaf); fldDataErrObj.ErrCode != CVL_SUCCESS {
183+
return nil, fldDataErrObj
184+
}
173185

174186
//Check which key elements left after current key element
175187
var next int = keyCompCount - 1
@@ -188,13 +200,17 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser.
188200
keyIndices[idx] = 0
189201
}
190202

191-
TRACE_LOG(INFO_API, TRACE_CACHE, "Starting batch leaf creation - %s\n", c.batchLeaf)
203+
TRACE_LOG(INFO_API, TRACE_CACHE, "Starting batch leaf creation - %v\n", c.batchLeaf)
192204
//process batch leaf creation
193205
if errObj := c.yp.AddMultiLeafNodes(modelInfo.tableInfo[tableName].module, listNode, c.batchLeaf); errObj.ErrCode != yparser.YP_SUCCESS {
194-
cvlErrObj = CreateCVLErrObj(errObj)
195-
return nil, cvlErrObj
206+
cvlErrObj = createCVLErrObj(errObj)
207+
CVL_LOG(ERROR, "Failed to create leaf nodes, data = %v",
208+
c.batchLeaf)
209+
return nil, cvlErrObj
196210
}
197-
c.batchLeaf = ""
211+
212+
c.batchLeaf = nil
213+
c.batchLeaf = make([]*yparser.YParserLeafValue, 0)
198214
}
199215
}
200216

cvl/cvl_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ func TestValidateEditConfig_Create_Syntax_CableLength(t *testing.T) {
759759
map[string]string{
760760
"Ethernet8": "5m",
761761
"Ethernet12": "5m",
762-
"Ethernet16": "5m",
762+
"PortChannel16": "5m",
763763
},
764764
},
765765
}

0 commit comments

Comments
 (0)