Skip to content

Commit cf6a601

Browse files
authored
Merge pull request #297 from alexandernorth/fix/logging-and-getconfig-convert
Fix/logging and getconfig convert
2 parents 1e6f457 + ff42827 commit cf6a601

File tree

10 files changed

+100
-49
lines changed

10 files changed

+100
-49
lines changed

pkg/datastore/target/nc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (t *ncTarget) Get(ctx context.Context, req *sdcpb.GetDataRequest) (*sdcpb.G
100100
return nil, err
101101
}
102102

103-
log.Debugf("netconf response:\n%s", ncResponse.DocAsString())
103+
log.Debugf("%s: netconf response:\n%s", t.name, ncResponse.DocAsString())
104104

105105
// cmlImport := xml.NewXmlTreeImporter(ncResponse.Doc.Root())
106106

@@ -203,7 +203,7 @@ func (t *ncTarget) internalSync(ctx context.Context, sc *config.SyncProtocol, fo
203203
// execute netconf get
204204
resp, err := t.Get(ctx, req)
205205
if err != nil {
206-
log.Errorf("failed getting config: %T | %v", err, err)
206+
log.Errorf("failed getting config from target %v: %T | %v", t.name, err, err)
207207
if strings.Contains(err.Error(), "EOF") {
208208
t.Close()
209209
go t.reconnect()

pkg/datastore/target/nc_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ func Test_ncTarget_Get(t *testing.T) {
9191
Keys: []*sdcpb.LeafSchema{
9292
{
9393
Name: "name",
94+
Type: &sdcpb.SchemaLeafType{
95+
Type: "string",
96+
},
9497
},
9598
},
9699
},
@@ -110,6 +113,9 @@ func Test_ncTarget_Get(t *testing.T) {
110113
Keys: []*sdcpb.LeafSchema{
111114
{
112115
Name: "name",
116+
Type: &sdcpb.SchemaLeafType{
117+
Type: "string",
118+
},
113119
},
114120
},
115121
},

pkg/datastore/target/netconf/xml2SchemapbAdapter.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,12 @@ func (x *XML2sdcpbConfigAdapter) transformContainer(ctx context.Context, e *etre
123123
if cPElem[len(cPElem)-1].Key == nil {
124124
cPElem[len(cPElem)-1].Key = map[string]string{}
125125
}
126-
cPElem[len(cPElem)-1].Key[ls.Name] = e.FindElement("./" + ls.Name).Text()
126+
tv, err := utils.Convert(e.FindElement("./"+ls.Name).Text(), ls.Type)
127+
if err != nil {
128+
return err
129+
}
130+
131+
cPElem[len(cPElem)-1].Key[ls.Name] = tv.ToString()
127132
}
128133

129134
ntc := NewTransformationContext(cPElem)
@@ -145,7 +150,8 @@ func (x *XML2sdcpbConfigAdapter) transformContainer(ctx context.Context, e *etre
145150
// transformField transforms an etree.element of a configuration as an update into the provided *sdcpb.Notification.
146151
func (x *XML2sdcpbConfigAdapter) transformField(ctx context.Context, e *etree.Element, pelems []*sdcpb.PathElem, ls *sdcpb.LeafSchema, result *sdcpb.Notification) error {
147152
path := pelems
148-
for ls.GetType().GetLeafref() != "" {
153+
schemaLeafType := ls.GetType()
154+
for schemaLeafType.GetLeafref() != "" {
149155
path, err := utils.NormalizedAbsPath(ls.Type.Leafref, path)
150156
if err != nil {
151157
return err
@@ -156,18 +162,20 @@ func (x *XML2sdcpbConfigAdapter) transformField(ctx context.Context, e *etree.El
156162
return err
157163
}
158164

159-
var schemaElem *sdcpb.SchemaElem_Field
160-
var ok bool
161-
if schemaElem, ok = schema.GetSchema().GetSchema().(*sdcpb.SchemaElem_Field); !ok {
162-
return fmt.Errorf("leafref resolved to non-field schema type")
165+
switch se := schema.GetSchema().GetSchema().(type) {
166+
case *sdcpb.SchemaElem_Leaflist:
167+
schemaLeafType = se.Leaflist.GetType()
168+
case *sdcpb.SchemaElem_Field:
169+
schemaLeafType = se.Field.GetType()
170+
default:
171+
return fmt.Errorf("node [%s] with leafref [%s] has non-field or leaflist target type [%T]", e.GetPath(), ls.GetType().GetLeafref(), se)
163172
}
164-
ls = schemaElem.Field
165173
}
166174

167175
// process terminal values
168-
tv, err := StringElementToTypedValue(e.Text(), ls)
176+
tv, err := utils.Convert(e.Text(), schemaLeafType)
169177
if err != nil {
170-
return err
178+
return fmt.Errorf("unable to convert value [%s] at path [%s] according to SchemaLeafType [%+v]: %w", e.Text(), e.GetPath(), schemaLeafType, err)
171179
}
172180
// copy pathElems
173181
npelem := make([]*sdcpb.PathElem, 0, len(pelems))

pkg/datastore/target/netconf/xml2SchemapbAdapter_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ func TestXML2sdcpbConfigAdapter_Transform(t *testing.T) {
9090
Keys: []*sdcpb.LeafSchema{
9191
{
9292
Name: "name",
93+
Type: &sdcpb.SchemaLeafType{
94+
Type: "string",
95+
},
9396
},
9497
},
9598
},

pkg/server/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ func (s *Server) createInitialDatastores(ctx context.Context) {
275275

276276
for _, dsCfg := range s.config.Datastores {
277277
log.Debugf("creating datastore %s", dsCfg.Name)
278+
dsCfg.Validation = s.config.Validation.DeepCopy()
278279
go func(dsCfg *config.DatastoreConfig) {
279280
defer wg.Done()
280281
// TODO: handle error

pkg/tree/leaf_variants.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ func (lv *LeafVariants) GetDeviations(ch chan<- *types.DeviationEntry, isActiveC
335335
}
336336

337337
// get the path via the first LeafEntry
338-
// is valida for all entries
338+
// is valid for all entries
339339
sdcpbPath, err := lv.parentEntry.SdcpbPath()
340340
if err != nil {
341341
log.Error(err)
@@ -375,7 +375,7 @@ func (lv *LeafVariants) GetDeviations(ch chan<- *types.DeviationEntry, isActiveC
375375
overruled = append(overruled, de)
376376
highest = le
377377
}
378-
// if precedence of actual (le) is lower then le needs to be adeded to overruled
378+
// if precedence of actual (le) is lower then le needs to be added to overruled
379379
if le.Priority() >= highest.Priority() {
380380
de := types.NewDeviationEntry(le.Owner(), types.DeviationReasonOverruled, sdcpbPath).SetExpectedValue(le.Value())
381381
overruled = append(overruled, de)
@@ -398,7 +398,7 @@ func (lv *LeafVariants) GetDeviations(ch chan<- *types.DeviationEntry, isActiveC
398398
return
399399
}
400400

401-
// if higeste exists but not running OR running != highest
401+
// if highest exists but not running OR running != highest
402402
if (running == nil && highest != nil) || running.Value().Cmp(highest.Value()) != 0 {
403403
de := types.NewDeviationEntry(highest.Owner(), types.DeviationReasonNotApplied, sdcpbPath).SetExpectedValue(highest.Value())
404404
if running != nil {

pkg/tree/sharedEntryAttributes.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,9 @@ func (s *sharedEntryAttributes) checkAndCreateKeysAsLeafs(ctx context.Context, i
212212
// if we're in the last level of keys, then we need to add the defaults
213213
if len(ancestorContainerSchema.Keys) == levelsUp {
214214
// iterate through the keys
215-
for idx, k := range ancestor.GetSchemaKeys() {
215+
schemaKeys := ancestor.GetSchemaKeys()
216+
slices.Sort(schemaKeys)
217+
for idx, k := range schemaKeys {
216218
child, entryExists := s.childs.GetEntry(k)
217219
// if the key Leaf exists continue with next key
218220
if entryExists {
@@ -951,6 +953,9 @@ func (s *sharedEntryAttributes) Validate(ctx context.Context, resultChan chan<-
951953

952954
// validate the mandatory statement on this entry
953955
if s.remainsToExist() {
956+
957+
// TODO: Validate Enums
958+
954959
if !vCfg.DisabledValidators.Mandatory {
955960
s.validateMandatory(ctx, resultChan)
956961
}
@@ -1137,13 +1142,13 @@ func (s *sharedEntryAttributes) ImportConfig(ctx context.Context, t importer.Imp
11371142
var exists bool
11381143
var actualEntry Entry = s
11391144
var keyChild Entry
1140-
for _, keySchema := range s.schema.GetContainer().GetKeys() {
1145+
schemaKeys := s.GetSchemaKeys()
1146+
slices.Sort(schemaKeys)
1147+
for _, schemaKey := range schemaKeys {
11411148

1142-
keyElemName := keySchema.Name
1143-
1144-
keyTransf := t.GetElement(keyElemName)
1149+
keyTransf := t.GetElement(schemaKey)
11451150
if keyTransf == nil {
1146-
return fmt.Errorf("unable to find key attribute %s under %s", keyElemName, s.Path())
1151+
return fmt.Errorf("unable to find key attribute %s under %s", schemaKey, s.Path())
11471152
}
11481153
keyElemValue, err := keyTransf.GetKeyValue()
11491154
if err != nil {
@@ -1654,18 +1659,18 @@ func (s *sharedEntryAttributes) getKeyName() (string, error) {
16541659
return "", fmt.Errorf("error %s is a schema element, can only get KeyNames for key element", strings.Join(s.Path(), " "))
16551660
}
16561661

1657-
// get ancestro schema
1662+
// get ancestor schema
16581663
ancestorWithSchema, levelUp := s.GetFirstAncestorWithSchema()
16591664

1660-
// only Contaieners have keys, so check for that
1661-
switch sch := ancestorWithSchema.GetSchema().GetSchema().(type) {
1662-
case *sdcpb.SchemaElem_Container:
1663-
// return the name of the levelUp-1 key
1664-
return sch.Container.GetKeys()[levelUp-1].Name, nil
1665+
// only Containers have keys, so check for that
1666+
schemaKeys := ancestorWithSchema.GetSchemaKeys()
1667+
if len(schemaKeys) == 0 {
1668+
// we probably called the function on a LeafList or LeafEntry which is not a valid call to be made.
1669+
return "", fmt.Errorf("error LeafList and Field should not have keys %s", strings.Join(s.Path(), " "))
16651670
}
16661671

1667-
// we probably called the function on a LeafList or LeafEntry which is not a valid call to be made.
1668-
return "", fmt.Errorf("error LeafList and Field should not have keys %s", strings.Join(s.Path(), " "))
1672+
slices.Sort(schemaKeys)
1673+
return schemaKeys[levelUp-1], nil
16691674
}
16701675

16711676
func (s *sharedEntryAttributes) getOrCreateChilds(ctx context.Context, path types.PathSlice) (Entry, error) {

pkg/tree/validation_entry_leafref.go

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ func (s *sharedEntryAttributes) BreadthSearch(ctx context.Context, path string)
109109
// NavigateLeafRef
110110
func (s *sharedEntryAttributes) NavigateLeafRef(ctx context.Context) ([]Entry, error) {
111111

112+
// leafref path takes as an argument a string that MUST refer to a leaf or leaf-list node.
113+
// e.g.
114+
// leaf foo {
115+
// type leafref {
116+
// path "/bar/baz";
117+
// }
118+
// }
119+
// the runtime semantics are:
120+
// If /bar/baz resolves to a leaf, then foo must have exactly the same value as that leaf.
121+
// If /bar/baz resolves to a leaf-list, then foo must have a value equal to one of the existing entries in that leaf-list.
122+
// Thus, the "pointer" is not to the entire leaf-list node, but to one instance of it, selected by value.
123+
112124
var lref string
113125
switch {
114126
case s.GetSchema().GetField().GetType().GetLeafref() != "":
@@ -121,34 +133,34 @@ func (s *sharedEntryAttributes) NavigateLeafRef(ctx context.Context) ([]Entry, e
121133

122134
lv := s.leafVariants.GetHighestPrecedence(false, true)
123135

136+
// value of node with type leafref
124137
tv := lv.Value()
125-
var values []*sdcpb.TypedValue
126-
127-
switch ttv := tv.Value.(type) {
128-
case *sdcpb.TypedValue_LeaflistVal:
129-
values = append(values, ttv.LeaflistVal.GetElement()...)
130-
default:
131-
values = append(values, tv)
132-
}
133-
134-
var resultEntries []Entry
135138

136139
foundEntries, err := s.BreadthSearch(ctx, lref)
137140
if err != nil {
138141
return nil, err
139142
}
140143

141-
resultEntries = []Entry{}
144+
var resultEntries []Entry
142145

143146
for _, e := range foundEntries {
144-
145147
r, err := e.getHighestPrecedenceLeafValue(ctx)
146148
if err != nil {
147149
return nil, err
148150
}
149-
val := r.Value()
150-
for _, value := range values {
151-
if utils.EqualTypedValues(val, value) {
151+
// Value of the resolved leafref
152+
refVal := r.Value()
153+
var vals []*sdcpb.TypedValue
154+
155+
switch tVal := refVal.Value.(type) {
156+
case *sdcpb.TypedValue_LeaflistVal:
157+
vals = append(vals, tVal.LeaflistVal.GetElement()...)
158+
default:
159+
vals = append(vals, refVal)
160+
}
161+
// loop through possible values of found reference (leaf -> 1 value, leaf-list -> 1+ values)
162+
for _, val := range vals {
163+
if utils.EqualTypedValues(val, tv) {
152164
resultEntries = append(resultEntries, e)
153165
break
154166
}

pkg/utils/converter.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,8 @@ func (c *Converter) ExpandUpdate(ctx context.Context, upd *sdcpb.Update) ([]*sdc
140140
}
141141
}
142142

143-
if rsp.Field.GetType().Type == "identityref" {
143+
// We expect that all identityrefs are sent by schema-server as a identityref type now, not string
144+
if rsp.Field.GetType().Type == "identityref" && upd.GetValue().GetStringVal() != "" {
144145
upd.Value, err = Convert(upd.GetValue().GetStringVal(), rsp.Field.GetType())
145146
if err != nil {
146147
return nil, err
@@ -421,6 +422,8 @@ func TypedValueToYANGType(tv *sdcpb.TypedValue, schemaObject *sdcpb.SchemaElem)
421422
return tv, nil
422423
case *sdcpb.TypedValue_AnyVal:
423424
return tv, nil
425+
case *sdcpb.TypedValue_IdentityrefVal:
426+
return ConvertToTypedValue(schemaObject, tv.GetStringVal(), tv.GetTimestamp())
424427
}
425428
return tv, nil
426429
}

pkg/utils/leaf_convert.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import (
2727
)
2828

2929
func Convert(value string, lst *sdcpb.SchemaLeafType) (*sdcpb.TypedValue, error) {
30+
if lst == nil {
31+
return nil, fmt.Errorf("schemaleaftype cannot be nil")
32+
}
3033
switch lst.Type {
3134
case "string":
3235
return ConvertString(value, lst)
@@ -140,16 +143,26 @@ func ConvertSdcpbNumberToUint64(mm *sdcpb.Number) (uint64, error) {
140143
return mm.Value, nil
141144
}
142145

143-
func ConvertSdcpbNumberToInt64(mm *sdcpb.Number) (int64, error) {
144-
if mm.Value > math.MaxInt64 {
145-
return 0, fmt.Errorf("error converting %d to int64 overflow", mm.Value)
146+
func intAbs(x int64) uint64 {
147+
ui := uint64(x)
148+
if x < 0 {
149+
return ^(ui) + 1
146150
}
151+
return ui
152+
}
147153

154+
func ConvertSdcpbNumberToInt64(mm *sdcpb.Number) (int64, error) {
148155
if mm.Negative {
156+
if mm.Value > intAbs(math.MinInt64) {
157+
return 0, fmt.Errorf("error converting -%d to int64: overflow", mm.Value)
158+
}
149159
return -int64(mm.Value), nil
150-
} else {
151-
return int64(mm.Value), nil
152160
}
161+
162+
if mm.Value > math.MaxInt64 {
163+
return 0, fmt.Errorf("error converting %d to int64 overflow", mm.Value)
164+
}
165+
return int64(mm.Value), nil
153166
}
154167

155168
func convertUint(value string, minMaxs []*sdcpb.SchemaMinMaxType, ranges *URnges) (*sdcpb.TypedValue, error) {

0 commit comments

Comments
 (0)