Skip to content

Commit d8fff76

Browse files
committed
update error mappings
1 parent fdaad5f commit d8fff76

File tree

2 files changed

+119
-13
lines changed

2 files changed

+119
-13
lines changed

cvl/internal/yparser/ly_path.go

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,18 +136,92 @@ type lyPathElem struct {
136136
// Such predicates cannot be parsed.
137137
var lyPredicatePattern = regexp.MustCompile(`^\[([^=]*)=('[^']*'|"[^"]*")]`)
138138

139+
/* Extracting error details requires knowledge of text strings within libyang.
140+
* Enumeration of known text strings (extracted from libyang 3.7.8) below:
141+
*
142+
* apptag:
143+
* - missing-choice
144+
* - too-few-elements
145+
* - too-many-elements
146+
* - data-not-unique
147+
* - must-violation
148+
* - not-left
149+
* - instance-required
150+
*
151+
* error messages:
152+
* NOTE: Mappings not listed here are in ly_common.h as defines prefixed with LY_VCODE_
153+
* - "Invalid non-empty-encoded %s value \"%.*s\"."
154+
* - "Invalid non-boolean-encoded %s value \"%.*s\"."
155+
* - "Invalid non-string-encoded %s value \"%.*s\"."
156+
* - "Invalid non-num64-encoded %s value \"%.*s\"."
157+
* - "Invalid non-number-encoded %s value \"%.*s\"."
158+
* - "Invalid %zu. character of decimal64 value \"%.*s\"."
159+
* - "Invalid empty decimal64 value."
160+
* - "Invalid empty value length %zu."
161+
* - "Invalid type %s empty value."
162+
* - "Invalid type %s value \"%.*s\"."
163+
* - "Invalid %" PRIu64 ". character of decimal64 value \"%.*s\"."
164+
* - "Invalid type %s value \"%.*s\"."
165+
* - "Invalid enumeration value \"%.*s\"."
166+
* - "Invalid enumeration value % " PRIi32 "."
167+
* - "Invalid boolean value \"%.*s\"."
168+
* - "Invalid bit \"%.*s\"."
169+
* - "Invalid Base64 character 0x%x."
170+
* - "Invalid Base64 character '%c'."
171+
* - "Invalid character 0x%hhx."
172+
* - "Invalid node-instance-identifier \"%.*s\" value - semantic error."
173+
* - "Invalid node-instance-identifier \"%.*s\" value - syntax error."
174+
* - "Invalid first character '%c', list key predicates expected."
175+
* - "Invalid LYB boolean value size %zu (expected 1)."
176+
* - "Invalid LYB date-and-time character '%c' (expected a digit)."
177+
* - "Invalid LYB date-and-time value size %zu (expected at least 8)."
178+
* - "Invalid LYB bits value size %zu (expected %zu)."
179+
* - "Invalid LYB union value size %zu (expected at least 4)."
180+
* - "Invalid LYB union type index %" PRIu64 " (type count %" LY_PRI_ARRAY_COUNT_TYPE ")."
181+
* - "Invalid LYB signed integer value size %zu (expected %zu)."
182+
* - "Invalid LYB unsigned integer value size %zu (expected %zu)."
183+
* - "Invalid LYB enumeration value size %zu (expected 4)."
184+
* - "Invalid LYB decimal64 value size %zu (expected 8)."
185+
* - "Invalid LYB ipv6-address-no-zone value size %zu (expected 16)."
186+
* - "Invalid LYB ipv6-address zone character 0x%x."
187+
* - "Invalid LYB ipv6-address value size %zu (expected at least 16)."
188+
* - "Invalid LYB ipv6-prefix value size %zu (expected %d)."
189+
* - "Invalid LYB ipv6-prefix prefix length %" PRIu8 "."
190+
* - "Invalid LYB ipv4-address value size %zu (expected at least 4)."
191+
* - "Invalid LYB ipv4-address zone character 0x%x."
192+
* - "Invalid LYB ipv4-address-no-zone value size %zu (expected 4)."
193+
* - "Invalid LYB ipv4-prefix value size %zu (expected %d)."
194+
* - "Invalid identityref \"%.*s\" value - identity is disabled by if-feature."
195+
* - "Invalid identityref \"%.*s\" value - identity found in non-implemented module \"%s\"."
196+
* - "Invalid identityref \"%.*s\" value - identity not derived from all the bases %s."
197+
* - "Invalid identityref \"%.*s\" value - identity not derived from the base %s."
198+
* - "Invalid identityref \"%.*s\" value - identity not found in module \"%s\"."
199+
* - "Invalid identityref \"%.*s\" value - unable to map prefix to YANG schema."
200+
* - "Invalid empty identityref value."
201+
* - "Unsatisfied range - value \"%.*s\" is out of the allowed range."
202+
* - "Unsatisfied length - string \"%.*s\" length is not allowed."
203+
* - "Unsatisfied pattern - \"%.*s\" does not conform to %s\"%s\"."
204+
* - "Value \"%.*s\" of decimal64 type exceeds defined number (%u) of fraction digits."
205+
* - "Value \"%.*s\" is out of type %s min/max bounds."
206+
* - "A %s definition \"%s\" is not allowed to reference %s value \"%s\"."
207+
* - "Failed to convert IPv6 address \"%s\"."
208+
* - "Failed to convert IPv4 address \"%s\"."
209+
* - "Failed to resolve prefix \"%.*s\"."
210+
* - "Failed to convert IPv4 address \"%s\"."
211+
* - "Duplicate bit \"%s\"."
212+
* - "Newlines are expected every 64 Base64 characters."
213+
* - "Base64 encoded value length must be divisible by 4."
214+
* - "No memory."
215+
*/
216+
139217
// Regex patterns to extract target node name and value from libyang error message.
140-
// Example messages:
141-
// - Invalid value "9999999" in "vlanid" element
142-
// - Missing required element "vlanid" in "VLAN_LIST"
143-
// - Value "xyz" does not satisfy the constraint "Ethernet([1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[0-9])" (range, length, or pattern)
144-
// - Leafref "/sonic-port:sonic-port/sonic-port:PORT/sonic-port:ifname" of value "Ethernet668" points to a non-existing leaf
145-
// - Failed to find "extra" as a sibling to "sonic-acl:aclname"
146218
var (
147-
lyBadValue = regexp.MustCompile(`[Vv]alue "([^"]*)" `)
219+
lyBadValue = regexp.MustCompile(`[Vv]alue "([^"]*)"[ \.]`)
220+
lyUnsatisfied = regexp.MustCompile(`Unsatisfied (?:pattern|range|length) - (?:value |string |)"([^"]*)" `)
148221
lyElemPrefix = regexp.MustCompile(`[Ee]lement "([^"]*)"`)
149222
lyElemSuffix = regexp.MustCompile(`"([^"]*)" element`)
150-
lyUnknownElem = regexp.MustCompile(`Failed to find "([^"]*)" `)
223+
lyUnknownElem = regexp.MustCompile(`Term node "([^"]*)" not found\.`)
224+
lyMandatory = regexp.MustCompile(`Mandatory node "([^"]*)" instance does not exist\.`)
151225
)
152226

153227
// parseLyMessage matches a libyang returned log message using given
@@ -159,6 +233,7 @@ func parseLyMessage(s string, regex ...*regexp.Regexp) string {
159233
}
160234
}
161235
return ""
236+
}
162237

163238
// This function takes a when, must, or leafref path in its original form as
164239
// written in the YANG schema files, and converts it into its fully qualified

cvl/internal/yparser/yparser.go

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,28 @@ func (yp *YParser) FreeNode(node *YParserNode) YParserError {
638638
}
639639

640640
/* This function translates LIBYANG error code to valid YPARSER error code. */
641-
func translateLYErrToYParserErr(LYErrcode int) YParserRetCode {
641+
func translateLYErrToYParserErr(LYErrcode int, apptag string, msg string) YParserRetCode {
642642
var ypErrCode YParserRetCode
643643

644+
// YP_SYNTAX_MISSING_FIELD
645+
// YP_SYNTAX_INVALID_FIELD /* Invalid Field */
646+
// YP_SYNTAX_INVALID_INPUT_DATA /* Invalid Input Data */
647+
// YP_SYNTAX_MULTIPLE_INSTANCE /* Multiple Field Instances */
648+
// YP_SYNTAX_DUPLICATE /* Duplicate Fields */
649+
// YP_SYNTAX_ENUM_INVALID /* Invalid enum value */
650+
// YP_SYNTAX_ENUM_INVALID_NAME /* Invalid enum name */
651+
// YP_SYNTAX_ENUM_WHITESPACE /* Enum name with leading/trailing whitespaces */
652+
// YP_SYNTAX_OUT_OF_RANGE /* Value out of range/length/pattern (data) */
653+
// YP_SYNTAX_MINIMUM_INVALID /* min-elements constraint not honored */
654+
// YP_SYNTAX_MAXIMUM_INVALID /* max-elements constraint not honored */
655+
// YP_SEMANTIC_DEPENDENT_DATA_MISSING /* Dependent Data is missing */
656+
// YP_SEMANTIC_MANDATORY_DATA_MISSING /* Mandatory Data is missing */
657+
// YP_SEMANTIC_KEY_ALREADY_EXIST /* Key already existing */
658+
// YP_SEMANTIC_KEY_NOT_EXIST /* Key is missing */
659+
// YP_SEMANTIC_KEY_DUPLICATE /* Duplicate key */
660+
// YP_SEMANTIC_KEY_INVALID /* Invalid key */
661+
// YP_INTERNAL_UNKNOWN
662+
644663
switch LYErrcode {
645664
case C.LYVE_SUCCESS: /**< no error */
646665
ypErrCode = YP_SUCCESS
@@ -661,7 +680,19 @@ func translateLYErrToYParserErr(LYErrcode int) YParserRetCode {
661680
case C.LYVE_SYNTAX_JSON: /**< JSON-related syntax error */
662681
ypErrCode = YP_SYNTAX_INVALID_FIELD
663682
case C.LYVE_DATA: /**< YANG data does not reflect some of the module restrictions */
664-
ypErrCode = YP_SEMANTIC_DEPENDENT_DATA_MISSING
683+
if apptag == "too-few-elements" {
684+
ypErrCode = YP_SYNTAX_MINIMUM_INVALID
685+
} else if apptag == "too-many-elements" {
686+
ypErrCode = YP_SYNTAX_MAXIMUM_INVALID
687+
} else if strings.HasPrefix(msg, "Invalid enumeration value") {
688+
ypErrCode = YP_SYNTAX_ENUM_INVALID
689+
} else if strings.HasPrefix(msg, "Unsatisfied") {
690+
ypErrCode = YP_SYNTAX_OUT_OF_RANGE
691+
} else if strings.HasPrefix(msg, "Mandatory") {
692+
ypErrCode = YP_SYNTAX_MISSING_FIELD
693+
} else {
694+
ypErrCode = YP_SYNTAX_INVALID_INPUT_DATA
695+
}
665696
case C.LYVE_OTHER:
666697
ypErrCode = YP_INTERNAL_UNKNOWN
667698
default:
@@ -709,9 +740,9 @@ func getErrorDetails() YParserError {
709740

710741
if !strings.HasPrefix(errMsg, customErrorPrefix) {
711742
// libyang generated error message.. try to extract the field value & name
712-
ElemVal = parseLyMessage(errMsg, lyBadValue)
743+
ElemVal = parseLyMessage(errMsg, lyBadValue, lyUnsatisfied)
713744
if len(ElemName) == 0 { // if not resolved from path
714-
ElemName = parseLyMessage(errMsg, lyElemPrefix, lyElemSuffix)
745+
ElemName = parseLyMessage(errMsg, lyMandatory)
715746
}
716747
} else {
717748
/* Custom contraint error message like in must statement.
@@ -723,7 +754,7 @@ func getErrorDetails() YParserError {
723754
switch ypErrLast.err {
724755
case C.LY_EVALID:
725756
// validation failure
726-
ypErrCode = translateLYErrToYParserErr(int(ypErrLast.vecode))
757+
ypErrCode = translateLYErrToYParserErr(int(ypErrLast.vecode), errAppTag, errMsg)
727758
if len(ElemName) != 0 {
728759
errMessage = "Field \"" + ElemName + "\" has invalid value"
729760
if len(ElemVal) != 0 {

0 commit comments

Comments
 (0)