Skip to content

Commit 5ae17ff

Browse files
[sonic_cli_gen] Add YANG refine support (sonic-net#2804)
#### What I did Add [YANG "refine"](https://www.rfc-editor.org/rfc/rfc7950.html#section-7.13.2) support for the `sonic_cli_gen` utility. YANG refine is used to override the `description` and `mandatory` statements for YANG `grouping`. #### How I did it Modify the `sonic_cli_gen/yang_parser.py` #### How to verify it Modify the `sonic_cli_gen` UT
1 parent 4b547ef commit 5ae17ff

File tree

3 files changed

+79
-9
lines changed

3 files changed

+79
-9
lines changed

sonic_cli_gen/yang_parser.py

+57-4
Original file line numberDiff line numberDiff line change
@@ -259,16 +259,17 @@ def on_uses(y_module: OrderedDict,
259259
# trim prefixes in order to the next checks
260260
trim_uses_prefixes(y_uses)
261261

262-
# TODO: 'refine' support
263262
for group in y_grouping:
264263
if isinstance(y_uses, list):
265264
for use in y_uses:
266265
if group.get('@name') == use.get('@name'):
266+
resolve_refine(group, use)
267267
ret_attrs.extend(get_leafs(group, group.get('@name')))
268268
ret_attrs.extend(get_leaf_lists(group, group.get('@name')))
269269
ret_attrs.extend(get_choices(y_module, group, conf_mgmt, group.get('@name')))
270270
else:
271271
if group.get('@name') == y_uses.get('@name'):
272+
resolve_refine(group, y_uses)
272273
ret_attrs.extend(get_leafs(group, group.get('@name')))
273274
ret_attrs.extend(get_leaf_lists(group, group.get('@name')))
274275
ret_attrs.extend(get_choices(y_module, group, conf_mgmt, group.get('@name')))
@@ -401,10 +402,10 @@ def get_mandatory(y_leaf: OrderedDict) -> bool:
401402
'leaf' 'mandatory' value
402403
"""
403404

404-
if y_leaf.get('mandatory') is not None:
405-
return True
405+
if y_leaf.get('mandatory') is None:
406+
return False
406407

407-
return False
408+
return y_leaf.get('mandatory').get('@value') == 'true'
408409

409410

410411
def get_description(y_entity: OrderedDict) -> str:
@@ -506,6 +507,58 @@ def get_uses(y_module: OrderedDict,
506507
return []
507508

508509

510+
def refine_cb(refine: OrderedDict, entity: OrderedDict):
511+
if refine.get('@target-node') != entity.get('@name'):
512+
return
513+
514+
if refine.get('description') is not None:
515+
entity['description'] = OrderedDict([('text', refine.get('description').get('text'))])
516+
517+
if refine.get('mandatory') is not None:
518+
entity['mandatory'] = OrderedDict([('@value', refine.get('mandatory').get('@value'))])
519+
520+
521+
def resolve_refine_list(y_uses_refine: OrderedDict, y_entity: OrderedDict):
522+
if isinstance(y_uses_refine, list):
523+
if isinstance(y_entity, list):
524+
for refine in y_uses_refine:
525+
for e in y_entity:
526+
refine_cb(refine, e)
527+
else:
528+
for refine in y_uses_refine:
529+
refine_cb(refine, y_entity)
530+
else:
531+
if isinstance(y_entity, list):
532+
for e in y_entity:
533+
refine_cb(y_uses_refine, e)
534+
else:
535+
refine_cb(y_uses_refine, y_entity)
536+
537+
538+
def resolve_refine(y_group: OrderedDict, y_uses: OrderedDict):
539+
""" Check if the YANG 'uses' entity have the 'refine' entity, if so
540+
this function will override values in 'y_group' using 'refine' values
541+
542+
Args:
543+
y_group: reference to 'grouping'
544+
y_uses: reference to 'uses'
545+
"""
546+
547+
y_uses_refine = y_uses.get('refine')
548+
549+
if y_uses_refine is None:
550+
return
551+
552+
y_group_leaf = y_group.get('leaf')
553+
y_group_leaf_list = y_group.get('leaf-list')
554+
555+
if y_group_leaf is not None:
556+
resolve_refine_list(y_uses_refine, y_group_leaf)
557+
558+
if y_group_leaf_list is not None:
559+
resolve_refine_list(y_uses_refine, y_group_leaf_list)
560+
561+
509562
def get_all_grouping(y_module: OrderedDict,
510563
y_uses: OrderedDict,
511564
conf_mgmt: ConfigMgmt) -> list:

tests/cli_autogen_input/yang_parser_test/assert_dictionaries.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -535,14 +535,14 @@
535535
"attrs":[
536536
{
537537
"name":"GR_5_LEAF_1",
538-
"description": "",
538+
"description": "GR_5_LEAF_1 refine description",
539539
"is-mandatory": False,
540540
"is-leaf-list": False,
541541
"group": "GR_5",
542542
},
543543
{
544544
"name":"GR_5_LEAF_LIST_1",
545-
"description": "",
545+
"description": "GR_5_LEAF_LIST_1 refine description",
546546
"is-mandatory": False,
547547
"is-leaf-list": True,
548548
"group": "GR_5",
@@ -556,7 +556,7 @@
556556
},
557557
{
558558
"name":"GR_6_LEAF_2",
559-
"description": "",
559+
"description": "GR_6_LEAF_2 refine description",
560560
"is-mandatory": False,
561561
"is-leaf-list": False,
562562
"group": "GR_6",

tests/cli_autogen_input/yang_parser_test/sonic-grouping-complex.yang

+19-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ module sonic-grouping-complex {
1515

1616
grouping GR_5 {
1717
leaf GR_5_LEAF_1 {
18+
mandatory true;
19+
description "GR_5_LEAF_1 description";
1820
type string;
1921
}
2022

@@ -87,8 +89,23 @@ module sonic-grouping-complex {
8789

8890
description "OBJECT_2 description";
8991

90-
uses GR_5;
91-
uses GR_6;
92+
uses GR_5 {
93+
refine GR_5_LEAF_1 {
94+
mandatory false;
95+
description "GR_5_LEAF_1 refine description";
96+
}
97+
98+
refine GR_5_LEAF_LIST_1 {
99+
description "GR_5_LEAF_LIST_1 refine description";
100+
}
101+
}
102+
103+
uses GR_6 {
104+
refine GR_6_LEAF_2 {
105+
description "GR_6_LEAF_2 refine description";
106+
}
107+
}
108+
92109
uses sgroup2:GR_4;
93110
}
94111
}

0 commit comments

Comments
 (0)