Skip to content

Commit

Permalink
Merge f0f3bd2 into e60257f
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanCondon committed Sep 11, 2020
2 parents e60257f + f0f3bd2 commit 3a3c90b
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 81 deletions.
5 changes: 4 additions & 1 deletion pkg/modelregistry/jsonvalues/convertJsonTd2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,13 @@ func Test_DecomposeJSONWithPathsTd2OpState(t *testing.T) {
"/cont1b-state/list2b[index1=101][index2=102]/leaf3c",
"/cont1b-state/list2b[index1=101][index2=103]/leaf3c",
"/cont1b-state/list2b[index1=101][index2=102]/leaf3d",
"/cont1b-state/list2b[index1=101][index2=103]/leaf3d",
"/cont1b-state/cont2c/leaf3b":
assert.Equal(t, pathValue.GetValue().GetType(), devicechange.ValueType_STRING, pathValue.Path)
assert.Equal(t, len(pathValue.GetValue().GetTypeOpts()), 0)
case "/cont1b-state/list2b[index1=101][index2=103]/leaf3d":
assert.Equal(t, pathValue.GetValue().GetType(), devicechange.ValueType_STRING, pathValue.Path)
strVal := (*devicechange.TypedString)(pathValue.GetValue()).String()
assert.Equal(t, "IDTYPE2", strVal) // Should do the conversion fron "2" to "IDTYPE2"
case
"/cont1b-state/leaf2d":
assert.Equal(t, pathValue.GetValue().GetType(), devicechange.ValueType_UINT, pathValue.Path)
Expand Down
70 changes: 37 additions & 33 deletions pkg/modelregistry/jsonvalues/jsonToValues.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ import (
devicechange "github.com/onosproject/onos-config/api/types/change/device"
"github.com/onosproject/onos-config/pkg/modelregistry"
"math"
"regexp"
"sort"
"strconv"
"strings"
)

const matchOnIndex = `(\[.*?]).*?`
const (
slash = "/"
equals = "="
Expand All @@ -36,8 +34,6 @@ const (
colon = ":"
)

var rOnIndex = regexp.MustCompile(matchOnIndex)

type indexValue struct {
name string
value *devicechange.TypedValue
Expand Down Expand Up @@ -90,7 +86,7 @@ func extractValuesWithPaths(f interface{}, parentPath string,
for _, obj := range objs {
isIndex := false
for i, idxName := range indexNames {
if removePathIndices(obj.Path) == fmt.Sprintf("%s/%s", removePathIndices(parentPath), idxName) {
if modelregistry.RemovePathIndices(obj.Path) == fmt.Sprintf("%s/%s", modelregistry.RemovePathIndices(parentPath), idxName) {
indices = append(indices, indexValue{name: idxName, value: obj.Value, order: i})
isIndex = true
break
Expand Down Expand Up @@ -234,6 +230,7 @@ func handleAttribute(value interface{}, parentPath string, modelROpaths modelreg
var ok bool
var pathElem *modelregistry.ReadWritePathElem
var subPath *modelregistry.ReadOnlyAttrib
var enum map[int]string
var err error
pathElem, modelPath, ok = findModelRwPathNoIndices(modelRWpaths, parentPath)
if !ok {
Expand All @@ -246,6 +243,7 @@ func handleAttribute(value interface{}, parentPath string, modelROpaths modelreg
return nil, fmt.Errorf("unable to locate %s in model", parentPath)
}
modeltype = subPath.Datatype
enum = subPath.Enum
} else {
modeltype = pathElem.ValueType
}
Expand All @@ -255,7 +253,31 @@ func handleAttribute(value interface{}, parentPath string, modelROpaths modelreg
var stringVal string
switch valueTyped := value.(type) {
case string:
stringVal = valueTyped
if len(enum) > 0 {
// Compare values and convert from digit if necessary
for k, v := range enum {
if v == valueTyped {
stringVal = valueTyped
break
} else if fmt.Sprintf("%d", k) == valueTyped {
stringVal = v
break
}
}
if stringVal == "" {
enumOpts := make([]string, len(enum)*2)
i := 0
for k, v := range enum {
enumOpts[i*2] = fmt.Sprintf("%d", k)
enumOpts[i*2+1] = v
i++
}
return nil, fmt.Errorf("value %s for %s does not match any enumerated value %s",
valueTyped, parentPath, strings.Join(enumOpts, ";"))
}
} else {
stringVal = valueTyped
}
case float64:
stringVal = fmt.Sprintf("%g", value)
case bool:
Expand Down Expand Up @@ -392,9 +414,9 @@ func handleAttributeLeafList(modeltype devicechange.ValueType,
func findModelRwPathNoIndices(modelRWpaths modelregistry.ReadWritePathMap,
searchpath string) (*modelregistry.ReadWritePathElem, string, bool) {

searchpathNoIndices := removePathIndices(searchpath)
searchpathNoIndices := modelregistry.RemovePathIndices(searchpath)
for path, value := range modelRWpaths {
if removePathIndices(path) == searchpathNoIndices {
if modelregistry.RemovePathIndices(path) == searchpathNoIndices {
pathWithNumericalIdx, err := insertNumericalIndices(path, searchpath)
if err != nil {
return nil, fmt.Sprintf("could not replace wildcards in model path with numerical ids %v", err), false
Expand All @@ -408,7 +430,7 @@ func findModelRwPathNoIndices(modelRWpaths modelregistry.ReadWritePathMap,
func findModelRoPathNoIndices(modelROpaths modelregistry.ReadOnlyPathMap,
searchpath string) (*modelregistry.ReadOnlyAttrib, string, bool) {

searchpathNoIndices := removePathIndices(searchpath)
searchpathNoIndices := modelregistry.RemovePathIndices(searchpath)
for path, value := range modelROpaths {
for subpath, subpathValue := range value {
var fullpath string
Expand All @@ -417,7 +439,7 @@ func findModelRoPathNoIndices(modelROpaths modelregistry.ReadOnlyPathMap,
} else {
fullpath = fmt.Sprintf("%s%s", path, subpath)
}
if removePathIndices(fullpath) == searchpathNoIndices {
if modelregistry.RemovePathIndices(fullpath) == searchpathNoIndices {
pathWithNumericalIdx, err := insertNumericalIndices(fullpath, searchpath)
if err != nil {
return nil, fmt.Sprintf("could not replace wildcards in model path with numerical ids %v", err), false
Expand Down Expand Up @@ -447,13 +469,13 @@ func stripNamespace(path string) string {
func indicesOfPath(modelROpaths modelregistry.ReadOnlyPathMap,
modelRWpaths modelregistry.ReadWritePathMap, searchpath string) []string {

searchpathNoIndices := removePathIndices(searchpath)
searchpathNoIndices := modelregistry.RemovePathIndices(searchpath)
// First search through the RW paths
for path := range modelRWpaths {
pathNoIndices := removePathIndices(path)
pathNoIndices := modelregistry.RemovePathIndices(path)
// Find a short path
if pathNoIndices[:strings.LastIndex(pathNoIndices, slash)] == searchpathNoIndices {
return extractIndexNames(path)
return modelregistry.ExtractIndexNames(path)
}
}

Expand All @@ -466,35 +488,17 @@ func indicesOfPath(modelROpaths modelregistry.ReadOnlyPathMap,
} else {
fullpath = fmt.Sprintf("%s%s", path, subpath)
}
pathNoIndices := removePathIndices(fullpath)
pathNoIndices := modelregistry.RemovePathIndices(fullpath)
// Find a short path
if pathNoIndices[:strings.LastIndex(pathNoIndices, slash)] == searchpathNoIndices {
return extractIndexNames(fullpath)
return modelregistry.ExtractIndexNames(fullpath)
}
}
}

return []string{}
}

func removePathIndices(path string) string {
jsonMatches := rOnIndex.FindAllStringSubmatch(path, -1)
for _, m := range jsonMatches {
path = strings.ReplaceAll(path, m[1], "")
}
return path
}

func extractIndexNames(path string) []string {
indexNames := make([]string, 0)
jsonMatches := rOnIndex.FindAllStringSubmatch(path, -1)
for _, m := range jsonMatches {
idxName := m[1][1:strings.LastIndex(m[1], "=")]
indexNames = append(indexNames, idxName)
}
return indexNames
}

func insertNumericalIndices(modelPath string, jsonPath string) (string, error) {
jsonParts := strings.Split(jsonPath, slash)
modelParts := strings.Split(modelPath, slash)
Expand Down
19 changes: 0 additions & 19 deletions pkg/modelregistry/jsonvalues/jsonToValues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,25 +162,6 @@ func Test_indicesOfPath(t *testing.T) {
assert.Equal(t, "severity", indices[2])
}

func Test_removePathIndices(t *testing.T) {
const jsonPath = "/p/q/r[10]/s/t[20]/u/v[30]/w"
const jsonPathRemovedIdx = "/p/q/r/s/t/u/v/w"
noIndices := removePathIndices(jsonPath)
assert.Equal(t, jsonPathRemovedIdx, noIndices)
}

func Test_extractIndexNames(t *testing.T) {
const modelPath = "/p/q/r[a=*]/s/t[b=*][c=*]/u/v[d=*][e=*][f=*]/w"
indexNames := extractIndexNames(modelPath)
assert.Equal(t, 6, len(indexNames))
assert.Equal(t, "a", indexNames[0])
assert.Equal(t, "b", indexNames[1])
assert.Equal(t, "c", indexNames[2])
assert.Equal(t, "d", indexNames[3])
assert.Equal(t, "e", indexNames[4])
assert.Equal(t, "f", indexNames[5])
}

func Test_insertNumericalIndices(t *testing.T) {
const modelPath = "/p/q/r[a=*]/s/t[b=*][c=*]/u/v[d=*][e=*][f=*]/w"
const jsonPath = "/p/q/r[10]/s/t[20]/u/v[30]/w"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"index1": 101,
"index2": 103,
"leaf3c": "Second mock Value",
"leaf3d": "IDTYPE2"
"leaf3d": "2"
}
],
"leaf2d": 10001,
Expand Down
48 changes: 43 additions & 5 deletions pkg/modelregistry/modelregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,15 @@ const (
GetStateExplicitRoPathsExpandWildcards
)

// MatchOnIndex - regexp to find indices in paths names
const MatchOnIndex = `(\[.*?]).*?`

// ReadOnlyAttrib is the known metadata about a Read Only leaf
type ReadOnlyAttrib struct {
Datatype devicechange.ValueType
Description string
Units string
Enum map[int]string
}

// ReadOnlySubPathMap abstracts the read only subpath
Expand All @@ -70,6 +74,8 @@ type ReadOnlySubPathMap map[string]ReadOnlyAttrib
// ReadOnlyPathMap abstracts the read only path
type ReadOnlyPathMap map[string]ReadOnlySubPathMap

var rOnIndex = regexp.MustCompile(MatchOnIndex)

// JustPaths extracts keys from a read only path map
func (ro ReadOnlyPathMap) JustPaths() []string {
keys := make([]string, 0)
Expand Down Expand Up @@ -112,6 +118,7 @@ type ReadWritePathElem struct {
Default string
Range []string
Length []string
Enum map[int]string
}

// ReadWritePathMap is a map of ReadWrite paths a their metadata
Expand Down Expand Up @@ -265,6 +272,11 @@ func ExtractPaths(deviceEntry *yang.Entry, parentState yang.TriState, parentPath
if err != nil {
log.Errorf(err.Error())
}
var enum map[int]string
if dirEntry.Type.Kind == yang.Yidentityref {
enum = handleIdentity(dirEntry.Type)
}
tObj.Enum = enum
if parentState == yang.TSFalse {
leafMap, ok := readOnlyPaths[parentPath]
if !ok {
Expand Down Expand Up @@ -293,6 +305,7 @@ func ExtractPaths(deviceEntry *yang.Entry, parentState yang.TriState, parentPath
Default: dirEntry.Default,
Range: ranges,
Length: lengths,
Enum: enum,
}
readWritePaths[itemPath] = rwElem
}
Expand Down Expand Up @@ -345,7 +358,14 @@ func ExtractPaths(deviceEntry *yang.Entry, parentState yang.TriState, parentPath
// Need to copy the index of the list across to the RO list too
roIdxName := k[:strings.LastIndex(k, "/")]
roIdxSubPath := k[strings.LastIndex(k, "/"):]
if roIdxName == itemPath {
indices := ExtractIndexNames(itemPath[strings.LastIndex(itemPath, "/"):])
kIsIdxAttr := false
for _, idx := range indices {
if roIdxSubPath == fmt.Sprintf("/%s", idx) {
kIsIdxAttr = true
}
}
if roIdxName == itemPath && kIsIdxAttr {
roIdx := ReadOnlyAttrib{
Datatype: v.ValueType,
Description: v.Description,
Expand Down Expand Up @@ -374,15 +394,24 @@ func ExtractPaths(deviceEntry *yang.Entry, parentState yang.TriState, parentPath

// RemovePathIndices removes the index value from a path to allow it to be compared to a model path
func RemovePathIndices(path string) string {
const indexPattern = `=.*?]`
rname := regexp.MustCompile(indexPattern)
indices := rname.FindAllStringSubmatch(path, -1)
indices := rOnIndex.FindAllStringSubmatch(path, -1)
for _, i := range indices {
path = strings.Replace(path, i[0], "=*]", 1)
path = strings.Replace(path, i[0], "", 1)
}
return path
}

// ExtractIndexNames - get an ordered array of index names
func ExtractIndexNames(path string) []string {
indexNames := make([]string, 0)
jsonMatches := rOnIndex.FindAllStringSubmatch(path, -1)
for _, m := range jsonMatches {
idxName := m[1][1:strings.LastIndex(m[1], "=")]
indexNames = append(indexNames, idxName)
}
return indexNames
}

func formatName(dirEntry *yang.Entry, isList bool, parentPath string, subpathPrefix string) string {
parentAndSubPath := parentPath
if subpathPrefix != "/" {
Expand Down Expand Up @@ -464,3 +493,12 @@ func toValueType(entry *yang.YangType, isLeafList bool) (devicechange.ValueType,
return devicechange.ValueType_STRING, nil
}
}

func handleIdentity(yangType *yang.YangType) map[int]string {
identityMap := make(map[int]string)
identityMap[0] = "UNSET"
for i, val := range yangType.IdentityBase.Values {
identityMap[i+1] = val.Name
}
return identityMap
}
39 changes: 27 additions & 12 deletions pkg/modelregistry/modelregistry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,24 +661,27 @@ func Test_Ntp(t *testing.T) {
}

func Test_RemovePathIndices(t *testing.T) {
assert.Equal(t,
RemovePathIndices("/cont1b-state"),
"/cont1b-state")
assert.Equal(t, "/cont1b-state",
RemovePathIndices("/cont1b-state"))

assert.Equal(t,
RemovePathIndices("/cont1b-state/list2b[index=test1]/index"),
"/cont1b-state/list2b[index=*]/index")
assert.Equal(t, "/cont1b-state/list2b/index",
RemovePathIndices("/cont1b-state/list2b[index=test1]/index"))

assert.Equal(t,
RemovePathIndices("/cont1b-state/list2b[index=test1,test2]/index"),
"/cont1b-state/list2b[index=*]/index")
assert.Equal(t, "/cont1b-state/list2b/index",
RemovePathIndices("/cont1b-state/list2b[index=test1,test2]/index"))

assert.Equal(t,
RemovePathIndices("/cont1b-state/list2b[index=test1]/index/t3[name=5]"),
"/cont1b-state/list2b[index=*]/index/t3[name=*]")
assert.Equal(t, "/cont1b-state/list2b/index/t3",
RemovePathIndices("/cont1b-state/list2b[index=test1]/index/t3[name=5]"))

}

func Test_RemovePathIndices2(t *testing.T) {
const jsonPath = "/p/q/r[10]/s/t[20]/u/v[30]/w"
const jsonPathRemovedIdx = "/p/q/r/s/t/u/v/w"
noIndices := RemovePathIndices(jsonPath)
assert.Equal(t, jsonPathRemovedIdx, noIndices)
}

func Test_formatName1(t *testing.T) {
dirEntry1 := yang.Entry{
Name: "testname",
Expand All @@ -695,3 +698,15 @@ func Test_formatName2(t *testing.T) {
}
assert.Equal(t, formatName(&dirEntry1, true, "/testpath/testpath2", ""), "/testpath/testpath2/testname[name=*]")
}

func Test_extractIndexNames(t *testing.T) {
const modelPath = "/p/q/r[a=*]/s/t[b=*][c=*]/u/v[d=*][e=*][f=*]/w"
indexNames := ExtractIndexNames(modelPath)
assert.Equal(t, 6, len(indexNames))
assert.Equal(t, "a", indexNames[0])
assert.Equal(t, "b", indexNames[1])
assert.Equal(t, "c", indexNames[2])
assert.Equal(t, "d", indexNames[3])
assert.Equal(t, "e", indexNames[4])
assert.Equal(t, "f", indexNames[5])
}
Loading

0 comments on commit 3a3c90b

Please sign in to comment.