-
Notifications
You must be signed in to change notification settings - Fork 94
Uses Augmentation #272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Uses Augmentation #272
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -660,6 +660,22 @@ func ToEntry(n Node) (e *Entry) { | |
| // when the group is used in multiple locations and the | ||
| // grouping has a leafref that references outside the group. | ||
| e = ToEntry(g).dup() | ||
|
|
||
| switch determineYangVersion(g) { | ||
| case YangVersion10: | ||
| if len(s.Augment) > 1 { | ||
| return newError(s, "multiple augments not allowed in yang version 1.0: %s", s.Name) | ||
| } | ||
| } | ||
|
|
||
| // process augments | ||
| for _, x := range s.Augment { | ||
| a := ToEntry(x) | ||
| a.Parent = e | ||
| a.Augments = append(a.Augments, e) | ||
| e.Find(a.Name).merge(nil, a.Namespace(), a) | ||
| } | ||
|
|
||
| addExtraKeywordsToLeafEntry(n, e) | ||
| return e | ||
| } | ||
|
|
@@ -1045,6 +1061,32 @@ func ToEntry(n Node) (e *Entry) { | |
| return e | ||
| } | ||
|
|
||
| type YangVersion string | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a docstring comment please?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| const ( | ||
| YangVersion10 YangVersion = "1.0" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| YangVersion11 YangVersion = "1.1" | ||
| ) | ||
|
|
||
| func determineYangVersion(n Node) YangVersion { | ||
| p := n.ParentNode() | ||
| if p != nil { | ||
| return determineYangVersion(p) | ||
| } | ||
| var m *Module | ||
| var ok bool | ||
| if m, ok = n.(*Module); ok { | ||
| switch m.YangVersion.asString() { | ||
| case string(YangVersion10): | ||
| return YangVersion10 | ||
| case string(YangVersion11): | ||
| return YangVersion11 | ||
| } | ||
| } | ||
| // default to 1.0 | ||
| return YangVersion10 | ||
| } | ||
|
|
||
| // addExtraKeywordsToLeafEntry stores the values for unimplemented keywords in leaf entries. | ||
| func addExtraKeywordsToLeafEntry(n Node, e *Entry) { | ||
| v := reflect.ValueOf(n).Elem() | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -3871,6 +3871,260 @@ func TestLeafEntry(t *testing.T) { | |||
| } | ||||
| } | ||||
|
|
||||
| func TestAugmentUses(t *testing.T) { | ||||
|
|
||||
| tests := []struct { | ||||
| name string | ||||
| inModules map[string]string | ||||
| WantErrors []string | ||||
| pathExist [][]string | ||||
| }{ | ||||
| { | ||||
| name: "Yang 1.0 fail multiple augment in use", | ||||
| WantErrors: []string{"multiple augments not allowed in yang version 1.0: grouping-a"}, | ||||
| inModules: map[string]string{ | ||||
| "a.yang": ` | ||||
| module mod-a { | ||||
| yang-version 1.1; | ||||
| namespace "urn:mod-a"; | ||||
| prefix moda; | ||||
|
|
||||
| include submod-a-one; | ||||
| include submod-a-two; | ||||
| } | ||||
| `, | ||||
| "b.yang": ` | ||||
| submodule submod-a-one { | ||||
| belongs-to mod-a { | ||||
| prefix moda; | ||||
| } | ||||
| yang-version 1.0; | ||||
| include submod-a-two; | ||||
|
|
||||
| grouping grouping-a { | ||||
| list range { | ||||
| must 'end >= start' { | ||||
| error-message | ||||
| "'end' must be greater than or equal to 'start'."; | ||||
| } | ||||
| leaf start { | ||||
| type uint16 { | ||||
| range "1..10"; | ||||
| } | ||||
| } | ||||
| leaf end { | ||||
| type uint16 { | ||||
| range "1..10"; | ||||
| } | ||||
| } | ||||
| key "start end"; | ||||
| } | ||||
| container z { | ||||
|
|
||||
| } | ||||
| } | ||||
|
|
||||
| augment "/moda:container-a" { | ||||
| container augment-a { | ||||
| uses grouping-a { | ||||
| augment "range" { | ||||
| choice timeout-type { | ||||
| mandatory true; | ||||
| case period { | ||||
| leaf period { | ||||
| type uint16 { | ||||
| range "2..100"; | ||||
| } | ||||
| units second; | ||||
| } | ||||
| } | ||||
| case boolean { | ||||
| container boolean { | ||||
| leaf enabled { | ||||
| type boolean; | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| augment "z" { | ||||
| leaf enableZ { | ||||
| type boolean; | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| `, | ||||
| "c.yang": ` | ||||
| submodule submod-a-two { | ||||
| belongs-to mod-a { | ||||
| prefix moda; | ||||
| } | ||||
| yang-version 1.1; | ||||
|
|
||||
| container container-a { | ||||
|
|
||||
| container a { | ||||
| } | ||||
|
|
||||
| container b { | ||||
| } | ||||
| } | ||||
| } | ||||
| `, | ||||
| }, | ||||
| }, | ||||
| { | ||||
| name: "Yang 1.1 pass multiple augment in use", | ||||
| pathExist: [][]string{ | ||||
| {"container-a", "a"}, | ||||
| {"container-a", "b"}, | ||||
| {"container-a", "augment-a", "range", "start"}, | ||||
| {"container-a", "augment-a", "z", "enableZ"}, | ||||
| }, | ||||
| inModules: map[string]string{ | ||||
| "a.yang": ` | ||||
| module mod-a { | ||||
| yang-version 1.1; | ||||
| namespace "urn:mod-a"; | ||||
| prefix moda; | ||||
|
|
||||
| include submod-a-one; | ||||
| include submod-a-two; | ||||
| } | ||||
| `, | ||||
| "b.yang": ` | ||||
| submodule submod-a-one { | ||||
| belongs-to mod-a { | ||||
| prefix moda; | ||||
| } | ||||
| yang-version 1.1; | ||||
| include submod-a-two; | ||||
|
|
||||
| grouping grouping-a { | ||||
| list range { | ||||
| must 'end >= start' { | ||||
| error-message | ||||
| "'end' must be greater than or equal to 'start'."; | ||||
| } | ||||
| leaf start { | ||||
| type uint16 { | ||||
| range "1..10"; | ||||
| } | ||||
| } | ||||
| leaf end { | ||||
| type uint16 { | ||||
| range "1..10"; | ||||
| } | ||||
| } | ||||
| key "start end"; | ||||
| } | ||||
| container z { | ||||
|
|
||||
| } | ||||
| } | ||||
|
|
||||
| augment "/moda:container-a" { | ||||
| container augment-a { | ||||
| uses grouping-a { | ||||
| augment "range" { | ||||
| choice timeout-type { | ||||
| mandatory true; | ||||
| case period { | ||||
| leaf period { | ||||
| type uint16 { | ||||
| range "2..100"; | ||||
| } | ||||
| units second; | ||||
| } | ||||
| } | ||||
| case boolean { | ||||
| container boolean { | ||||
| leaf enabled { | ||||
| type boolean; | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| augment "z" { | ||||
| leaf enableZ { | ||||
| type boolean; | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| } | ||||
| `, | ||||
| "c.yang": ` | ||||
| submodule submod-a-two { | ||||
| belongs-to mod-a { | ||||
| prefix moda; | ||||
| } | ||||
| yang-version 1.1; | ||||
|
|
||||
| container container-a { | ||||
|
|
||||
| container a { | ||||
| } | ||||
|
|
||||
| container b { | ||||
| } | ||||
| } | ||||
| } | ||||
| `, | ||||
| }, | ||||
| }, | ||||
| } | ||||
|
|
||||
| for _, tt := range tests { | ||||
| t.Run(tt.name, func(t *testing.T) { | ||||
| ms := NewModules() | ||||
| var errs []error | ||||
|
|
||||
| for n, m := range tt.inModules { | ||||
| if err := ms.Parse(m, n); err != nil { | ||||
| errs = append(errs, err) | ||||
|
|
||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||
| } | ||||
| } | ||||
|
|
||||
| if len(errs) > 0 { | ||||
| t.Fatalf("ms.Parse(), got unexpected error parsing input modules: %v", errs) | ||||
| } | ||||
|
|
||||
| errs = append(errs, ms.Process()...) | ||||
|
|
||||
| var errsStr = strings.Builder{} | ||||
| for _, e := range errs { | ||||
| errsStr.WriteString(e.Error()) | ||||
| } | ||||
|
|
||||
| for _, errStr := range tt.WantErrors { | ||||
| strings.Contains(errsStr.String(), errStr) | ||||
| } | ||||
|
|
||||
| var m *Entry | ||||
| m, errs = ms.GetModule("mod-a") | ||||
| x := m | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest to make these variable names a little less pithy --
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||
| for _, p := range tt.pathExist { | ||||
| for _, pe := range p { | ||||
| y, ok := x.Dir[pe] | ||||
| if !ok { | ||||
| t.Fatalf("expected module %s to contain path %s", m.Name, strings.Join(p, "/")) | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add more debugging output here -- e.g., "expected module %s to contain path %s, could not find element %s in parent, got children: %v"
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||||
| } | ||||
| x = y | ||||
| } | ||||
| x = m | ||||
| } | ||||
|
|
||||
| }) | ||||
| } | ||||
| } | ||||
|
|
||||
| func TestLess(t *testing.T) { | ||||
| sErrors := sortedErrors{ | ||||
| {"testfile0", errors.New("test error0")}, | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -624,13 +624,13 @@ type Uses struct { | |
| Parent Node `yang:"Parent,nomerge" json:"-"` | ||
| Extensions []*Statement `yang:"Ext" json:"-"` | ||
|
|
||
| Augment *Augment `yang:"augment" json:",omitempty"` | ||
| Description *Value `yang:"description" json:",omitempty"` | ||
| IfFeature []*Value `yang:"if-feature" json:"-"` | ||
| Refine []*Refine `yang:"refine" json:"-"` | ||
| Reference *Value `yang:"reference" json:"-"` | ||
| Status *Value `yang:"status" json:"-"` | ||
| When *Value `yang:"when" json:",omitempty"` | ||
| Augment []*Augment `yang:"augment" json:",omitempty"` | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we create a different field here, since this means that this change is backwards-incompatible for existing API users. There was some discussion historically about making such changes for YANG 1.1. If we don't do this, then we need to mark this as goyang v2. I'd prefer to see whether we can group up other API changes that would be needed to fully support y1.1 into such a release.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm unsure what exactly you want me to do here.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't support changing I suggest this is implemented using a new field |
||
| Description *Value `yang:"description" json:",omitempty"` | ||
| IfFeature []*Value `yang:"if-feature" json:"-"` | ||
| Refine []*Refine `yang:"refine" json:"-"` | ||
| Reference *Value `yang:"reference" json:"-"` | ||
| Status *Value `yang:"status" json:"-"` | ||
| When *Value `yang:"when" json:",omitempty"` | ||
| } | ||
|
|
||
| func (Uses) Kind() string { return "uses" } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We haven't added this kind of error checking elsewhere -- I wonder whether we should try and include the parsed YANG version somewhere in the output entry. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we want to be strict then thats probably a good idea.