Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,17 @@ build:
CGO_ENABLED=0 ${GO_BIN} build -o bin/datactl client/main.go
CGO_ENABLED=0 ${GO_BIN} build -o bin/data-server main.go

test:
install-sdctl:
${GO_BIN} install github.com/sdcio/sdctl@latest

robot-tests: build
robot tests/robot

go-tests:
go test ./...

test: go-tests robot-tests

docker-build:
ssh-add ./keys/id_rsa 2>/dev/null; true
docker build --build-arg USERID=$(USERID) . -t $(IMAGE) --ssh default=$(SSH_AUTH_SOCK)
Expand Down
23 changes: 23 additions & 0 deletions pkg/datastore/data_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,29 @@ func (d *Datastore) expandUpdate(ctx context.Context, upd *sdcpb.Update, include
upds := append(upds, rs...)
return upds, nil
case *sdcpb.SchemaElem_Field:
var v interface{}
var err error

var jsonValue []byte
switch upd.GetValue().Value.(type) {
case *sdcpb.TypedValue_JsonVal:
jsonValue = upd.GetValue().GetJsonVal()
case *sdcpb.TypedValue_JsonIetfVal:
jsonValue = upd.GetValue().GetJsonIetfVal()
}

// process value
if jsonValue != nil {
err = json.Unmarshal(jsonValue, &v)
if err != nil {
return nil, err
}
switch v := v.(type) {
case string:
upd.Value = &sdcpb.TypedValue{Value: &sdcpb.TypedValue_StringVal{StringVal: v}}
}
}

// TODO: Check if value is json and convert to String ?
upds = append(upds, upd)
return upds, nil
Expand Down
1 change: 0 additions & 1 deletion pkg/datastore/datastore_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,6 @@ func (d *Datastore) resolveLeafref(ctx context.Context, candidate string, leafRe
leafRefPath.Elem[len(leafRefPath.Elem)-2].Key[leafRefPath.Elem[len(leafRefPath.Elem)-1].Name] = value
// remove the last elem, we now have the key value stored in the one before last
leafRefPath.Elem = leafRefPath.Elem[:len(leafRefPath.Elem)-1]
return nil
}
}

Expand Down
16 changes: 14 additions & 2 deletions pkg/utils/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,24 @@ func StripPathElemPrefix(p string) (string, error) {
if i := strings.Index(pe.Name, ":"); i > 0 {
pe.Name = pe.Name[i+1:]
}
// delete prefix from keys
// process keys
for k, v := range pe.Key {
// delete prefix from key name
if i := strings.Index(k, ":"); i > 0 {
delete(pe.Key, k)
pe.Key[k[i+1:]] = v
k = k[i+1:]
}
// delete prefix from key value
if strings.Contains(v, ":") {
kelems := strings.Split(v, "/")
for idx, kelem := range kelems {
if i := strings.Index(kelem, ":"); i > 0 {
kelems[idx] = kelem[i+1:]
}
}
v = strings.Join(kelems, "/")
}
pe.Key[k] = v
}
}
prefix := ""
Expand Down
156 changes: 155 additions & 1 deletion pkg/utils/path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@

package utils

import "testing"
import (
"testing"

sdcpb "github.com/sdcio/sdc-protos/sdcpb"
)

func TestStripPathElemPrefix(t *testing.T) {
type args struct {
Expand Down Expand Up @@ -98,6 +102,14 @@ func TestStripPathElemPrefix(t *testing.T) {
want: "",
wantErr: true,
},
{
name: "path with current() function in key",
args: args{
p: "/srl_nokia-netinst:network-instance[srl_nokia-netinst:name = current()/../../../../../srl_nokia-netinst:name]/srl_nokia-netinst:interface/srl_nokia-netinst:name",
},
want: "/network-instance[name = current()/../../../../../name]/interface/name",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -112,3 +124,145 @@ func TestStripPathElemPrefix(t *testing.T) {
})
}
}

func TestToXPath(t *testing.T) {
type args struct {
p *sdcpb.Path
noKeys bool
}
tests := []struct {
name string
args args
want string
}{
{
name: "Path without keys, noKeys = false",
args: args{
noKeys: false,
p: &sdcpb.Path{
Elem: []*sdcpb.PathElem{
{
Name: "One",
},
{
Name: "Two",
},
{
Name: "Three",
},
},
},
},
want: "One/Two/Three",
},
{
name: "Path without keys, noKeys = true",
args: args{
noKeys: true,
p: &sdcpb.Path{
Elem: []*sdcpb.PathElem{
{
Name: "One",
},
{
Name: "Two",
},
{
Name: "Three",
},
},
},
},
want: "One/Two/Three",
},
{
name: "Path with keys, NoKeys = True",
args: args{
noKeys: true,
p: &sdcpb.Path{Elem: []*sdcpb.PathElem{
{Name: "interface", Key: map[string]string{
"name": "ethernet-1/1",
}},
{
Name: "subinterface", Key: map[string]string{
"index": "0",
},
},
{
Name: "admin-state",
},
}},
},
want: "interface/subinterface/admin-state",
},
{
name: "Path with keys, NoKeys = false",
args: args{
noKeys: false,
p: &sdcpb.Path{Elem: []*sdcpb.PathElem{
{Name: "interface", Key: map[string]string{
"name": "ethernet-1/1",
}},
{
Name: "subinterface", Key: map[string]string{
"index": "0",
},
},
{
Name: "admin-state",
},
}},
},
want: "interface[name=ethernet-1/1]/subinterface[index=0]/admin-state",
},
{
name: "Path with multiple keys, NoKeys = True",
args: args{
noKeys: true,
p: &sdcpb.Path{Elem: []*sdcpb.PathElem{
{Name: "interface", Key: map[string]string{
"name": "ethernet-1/1",
"schnitzel": "foo",
}},
{
Name: "subinterface", Key: map[string]string{
"index": "0",
},
},
{
Name: "admin-state",
},
}},
},
want: "interface/subinterface/admin-state",
},
{
name: "Path with multiple keys, NoKeys = false",
args: args{
noKeys: false,
p: &sdcpb.Path{Elem: []*sdcpb.PathElem{
{Name: "interface", Key: map[string]string{
"name": "ethernet-1/1",
"schnitzel": "foo",
}},
{
Name: "subinterface", Key: map[string]string{
"index": "0",
},
},
{
Name: "admin-state",
},
}},
},
want: "interface[name=ethernet-1/1][schnitzel=foo]/subinterface[index=0]/admin-state",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ToXPath(tt.args.p, tt.args.noKeys); got != tt.want {
t.Errorf("ToXPath() = %v, want %v", got, tt.want)
}
})
}
}
Loading