diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..a6838f4 --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,90 @@ +name: Go + +on: + push: + branches: [ main ] + pull_request: + schedule: + - cron: "0 0 * * *" + +jobs: + build: + name: Build + runs-on: ubuntu-latest + strategy: + matrix: + go: ['1.16', '1.17', '1.18', '1.x'] + steps: + + - name: Set up Go ${{ matrix.go }} + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + id: go + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + + - name: Get dependencies + run: | + go get -v -t -d ./... + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -v -coverprofile=profile.cov ./... + + static_analysis: + name: Static Analysis + runs-on: ubuntu-latest + + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: '1.x' + id: go + + - name: Install required static analysis tools + run: | + go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Check out code + uses: actions/checkout@v2 + + - name: Go vet + run: go vet -composites=false ./... + + - name: Check gofmt + run: diff -u <(echo -n) <(gofmt -d -s .) + + - name: Staticcheck + run: | + staticcheck ./... + + coverage: + name: Submit coverage + runs-on: ubuntu-latest + + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: '1.x' + id: go + + - name: Install required static analysis tools + run: | + go install honnef.co/go/tools/cmd/staticcheck@latest + + - name: Check out code + uses: actions/checkout@v2 + + - name: Test + run: go test -v -coverprofile=profile.cov ./... + + - name: Submit coverage + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: profile.cov diff --git a/cache/cache.go b/cache/cache.go index 84ef333..33837fb 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -43,6 +43,10 @@ import ( // int64 (nanoseconds since epoch). func T(n int64) time.Time { return time.Unix(0, n) } +// Now is a function that can be overridden in tests to alter the timestamps +// applied to deletes and metadata updates. +var Now = time.Now + // A Target hosts an indexed cache of state for a single target. type Target struct { name string // name of the target @@ -502,28 +506,49 @@ func (t *Target) gnmiUpdate(n *pb.Notification) (*ctree.Leaf, error) { return t.t.GetLeaf(path), nil } +func toDeleteNotification(n *pb.Notification, timestamp int64) *pb.Notification { + d := &pb.Notification{ + Timestamp: timestamp, + Prefix: &pb.Path{ + Target: n.GetPrefix().GetTarget(), + Origin: n.GetPrefix().GetOrigin(), + }, + } + prefix := n.GetPrefix() + path := n.Update[0].GetPath() + // Set origin if the origin is in the update + if origin := path.GetOrigin(); n.GetPrefix().GetOrigin() == "" && origin != "" { + d.Prefix.Origin = origin + } + switch { + case n.GetAtomic(): + d.Delete = []*pb.Path{{Elem: prefix.GetElem(), Element: prefix.GetElement()}} + case len(prefix.GetElem()) > 0 || len(path.GetElem()) > 0: + d.Delete = []*pb.Path{{Elem: append(prefix.GetElem(), path.GetElem()...)}} + default: + d.Delete = []*pb.Path{{Element: append(prefix.GetElement(), path.GetElement()...)}} + } + return d +} + func (t *Target) gnmiRemove(n *pb.Notification) []*ctree.Leaf { path := joinPrefixAndPath(n.Prefix, n.Delete[0]) if path[0] == metadata.Root { t.meta.ResetEntry(path[1]) } - leaves := t.t.DeleteConditional(path, func(v interface{}) bool { return v.(*pb.Notification).GetTimestamp() < n.GetTimestamp() }) + var leaves []*ctree.Leaf + f := func(v interface{}) { + d := v.(*pb.Notification) + leaves = append(leaves, ctree.DetachedLeaf(toDeleteNotification(d, n.GetTimestamp()))) + } + t.t.WalkDeleted(path, func(v interface{}) bool { return v.(*pb.Notification).GetTimestamp() < n.GetTimestamp() }, f) if len(leaves) == 0 { return nil } deleted := int64(len(leaves)) t.meta.AddInt(metadata.LeafCount, -deleted) t.meta.AddInt(metadata.DelCount, deleted) - var ls []*ctree.Leaf - for _, l := range leaves { - noti := &pb.Notification{ - Timestamp: n.GetTimestamp(), - Prefix: &pb.Path{Target: n.GetPrefix().GetTarget()}, - Delete: []*pb.Path{{Element: l}}, - } - ls = append(ls, ctree.DetachedLeaf(noti)) - } - return ls + return leaves } // updateCache calls fn for each Target. @@ -645,7 +670,7 @@ func deleteNoti(t, o string, p []string) *pb.Notification { pe = append(pe, &pb.PathElem{Name: e}) } return &pb.Notification{ - Timestamp: time.Now().UnixNano(), + Timestamp: Now().UnixNano(), Prefix: &pb.Path{Target: t, Origin: o}, Delete: []*pb.Path{&pb.Path{Elem: pe}}, } @@ -658,7 +683,7 @@ func metaNoti(t, m string, v *pb.TypedValue) *pb.Notification { pe = append(pe, &pb.PathElem{Name: p}) } return &pb.Notification{ - Timestamp: time.Now().UnixNano(), + Timestamp: Now().UnixNano(), Prefix: &pb.Path{Target: t}, Update: []*pb.Update{ &pb.Update{ diff --git a/cache/cache_test.go b/cache/cache_test.go index 1d5dd4c..3c6174d 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -30,8 +30,10 @@ import ( "time" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" "github.com/openconfig/gnmi/ctree" "github.com/openconfig/gnmi/errdiff" "github.com/openconfig/gnmi/latency" @@ -317,11 +319,12 @@ func sendUpdates(u updateQueryData, c *Cache, n int, wg *sync.WaitGroup) { r := rand.New(rand.NewSource(5)) for i := 0; i < n; i++ { target := u.targets[r.Intn(len(u.targets))] - path := append([]string{target}, u.paths[r.Intn(len(u.paths))]...) + path := u.paths[r.Intn(len(u.paths))] val, _ := value.FromScalar(u.values[r.Intn(len(u.values))]) c.GnmiUpdate(&pb.Notification{ + Prefix: &pb.Path{Target: target}, Update: []*pb.Update{{ - Path: &pb.Path{Element: path}, + Path: &pb.Path{Elem: toPathElem(path)}, Val: val, }}, Timestamp: int64(n), @@ -393,14 +396,26 @@ type update struct { val interface{} } +func toPathElem(path []string) []*pb.PathElem { + n := len(path) + if n == 0 { + return nil + } + pes := make([]*pb.PathElem, 0, n) + for _, pe := range path { + pes = append(pes, &pb.PathElem{Name: pe}) + } + return pes +} + func notificationBundle(dev string, prefix []string, ts int64, updates []update) *pb.Notification { n := &pb.Notification{ - Prefix: &pb.Path{Element: prefix, Target: dev}, + Prefix: &pb.Path{Elem: toPathElem(prefix), Target: dev}, Timestamp: ts, } for _, u := range updates { if u.delete { - n.Delete = append(n.Delete, &pb.Path{Element: u.path}) + n.Delete = append(n.Delete, &pb.Path{Elem: toPathElem(u.path)}) } else { val, err := value.FromScalar(u.val) if err != nil { @@ -408,7 +423,7 @@ func notificationBundle(dev string, prefix []string, ts int64, updates []update) } n.Update = append(n.Update, &pb.Update{ Path: &pb.Path{ - Element: u.path, + Elem: toPathElem(u.path), }, Val: val, }) @@ -1365,3 +1380,218 @@ func less(p, p2 []string) bool { } return len(p) < len(p2) } + +func TestGNMIUpdateForDelete(t *testing.T) { + dev := "dev1" + origin := "openconfig" + timestamp1 := int64(1234567890000000) + timestamp2 := int64(1234567890100000) + initial := []*pb.Notification{{ + Timestamp: timestamp1, + Atomic: true, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + Elem: []*pb.PathElem{{Name: "a"}, {Name: "b", Key: map[string]string{"k1": "c1"}}}, + }, + Update: []*pb.Update{{ + Path: &pb.Path{Elem: []*pb.PathElem{{Name: "f1"}}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v1"}}, + }, { + Path: &pb.Path{Elem: []*pb.PathElem{{Name: "f2"}}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v2"}}, + }}, + }, { + Timestamp: timestamp1, + Atomic: true, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + Element: []string{"a", "b", "c2"}, + }, + Update: []*pb.Update{{ + Path: &pb.Path{Element: []string{"f1"}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v1"}}, + }, { + Path: &pb.Path{Element: []string{"f2"}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v2"}}, + }}, + }, { + Timestamp: timestamp1, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + Elem: []*pb.PathElem{{Name: "a"}, {Name: "d", Key: map[string]string{"k1": "c1"}}}, + }, + Update: []*pb.Update{{ + Path: &pb.Path{Elem: []*pb.PathElem{{Name: "f3"}}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v3"}}, + }, { + Path: &pb.Path{Elem: []*pb.PathElem{{Name: "f4"}}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v4"}}, + }}, + }, { + Timestamp: timestamp1, + Prefix: &pb.Path{ + Target: dev, + }, + Update: []*pb.Update{{ + Path: &pb.Path{ + Origin: origin, + Elem: []*pb.PathElem{{Name: "a"}, {Name: "e", Key: map[string]string{"k1": "c1"}}, {Name: "f5"}}, + }, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v5"}}, + }}, + }, { + Timestamp: timestamp1, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + Element: []string{"a", "g"}, + }, + Update: []*pb.Update{{ + Path: &pb.Path{Element: []string{"f6"}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v6"}}, + }, { + Path: &pb.Path{Element: []string{"f7"}}, + Val: &pb.TypedValue{Value: &pb.TypedValue_StringVal{StringVal: "v7"}}, + }}, + }} + tests := []struct { + desc string + n *pb.Notification + want []*pb.Notification + }{{ + desc: "Delete atomic notification using PathElem", + n: &pb.Notification{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + Elem: []*pb.PathElem{{Name: "a"}}, + }, + Delete: []*pb.Path{{Elem: []*pb.PathElem{{Name: "b", Key: map[string]string{"k1": "c1"}}}}}, + }, + want: []*pb.Notification{{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Elem: []*pb.PathElem{{Name: "a"}, {Name: "b", Key: map[string]string{"k1": "c1"}}}}}, + }}, + }, { + desc: "Delete atomic notification using Element", + n: &pb.Notification{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + Element: []string{"a"}, + }, + Delete: []*pb.Path{{Element: []string{"b", "c2"}}}, + }, + want: []*pb.Notification{{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Element: []string{"a", "b", "c2"}}}, + }}, + }, { + desc: "Delete non-atomic notification using PathElem", + n: &pb.Notification{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + Elem: []*pb.PathElem{{Name: "a"}}, + }, + Delete: []*pb.Path{{Elem: []*pb.PathElem{{Name: "d", Key: map[string]string{"k1": "c1"}}}}}, + }, + want: []*pb.Notification{{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Elem: []*pb.PathElem{{Name: "a"}, {Name: "d", Key: map[string]string{"k1": "c1"}}, {Name: "f3"}}}}, + }, { + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Elem: []*pb.PathElem{{Name: "a"}, {Name: "d", Key: map[string]string{"k1": "c1"}}, {Name: "f4"}}}}, + }}, + }, { + desc: "Delete non-atomic notification using Element", + n: &pb.Notification{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Element: []string{"a", "g"}}}, + }, + want: []*pb.Notification{{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Element: []string{"a", "g", "f6"}}}, + }, { + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Element: []string{"a", "g", "f7"}}}, + }}, + }, { + desc: "Delete notification with origin in update path", + n: &pb.Notification{ + Timestamp: timestamp2, + Prefix: &pb.Path{Target: dev}, + Delete: []*pb.Path{{ + Origin: origin, + Elem: []*pb.PathElem{{Name: "a"}, {Name: "e"}}, + }}, + }, + want: []*pb.Notification{{ + Timestamp: timestamp2, + Prefix: &pb.Path{ + Target: dev, + Origin: origin, + }, + Delete: []*pb.Path{{Elem: []*pb.PathElem{{Name: "a"}, {Name: "e", Key: map[string]string{"k1": "c1"}}, {Name: "f5"}}}}, + }}, + }} + c := New([]string{dev}) + for _, n := range initial { + if err := c.GnmiUpdate(n); err != nil { + t.Fatalf("Could not initialize cache: %v ", err) + } + } + var out []*pb.Notification + c.SetClient(func(l *ctree.Leaf) { + out = append(out, l.Value().(*pb.Notification)) + }) + index := 0 + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + c.GnmiUpdate(tt.n) + count := len(out) + got := out[index:count] + index = count + lessFunc := func(a, b *pb.Notification) bool { + return a.String() < b.String() + } + if diff := cmp.Diff(tt.want, got, protocmp.Transform(), cmpopts.SortSlices(lessFunc)); diff != "" { + t.Errorf("GnmiUpdate got diff (+got-want) for deletes: %s", diff) + } + }) + } +} diff --git a/client/client_test.go b/client/client_test.go index f4dd41a..20e4949 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -486,7 +486,7 @@ func (f fakeStreamingClient) Close() error { return nil } // Once client will run the query and once complete you can act on the // returned tree. -func ExampleClient_Once() { +func ExampleClient_once() { q := client.Query{ Addrs: []string{"127.0.0.1:1234"}, Target: "dev", @@ -507,7 +507,7 @@ func ExampleClient_Once() { // Poll client is like Once client, but can be re-triggered via Poll to // re-execute the query. -func ExampleClient_Poll() { +func ExampleClient_poll() { q := client.Query{ Addrs: []string{"127.0.0.1:1234"}, Target: "dev", @@ -536,7 +536,7 @@ func ExampleClient_Poll() { // Stream client returns the current state for the query and keeps running // until closed or the underlying connection breaks. -func ExampleClient_Stream() { +func ExampleClient_stream() { q := client.Query{ Addrs: []string{"127.0.0.1:1234"}, Target: "dev", diff --git a/cmd/gnmi_collector/gnmi_collector.go b/cmd/gnmi_collector/gnmi_collector.go index 2ef992e..1cac22c 100644 --- a/cmd/gnmi_collector/gnmi_collector.go +++ b/cmd/gnmi_collector/gnmi_collector.go @@ -37,7 +37,7 @@ import ( "github.com/openconfig/gnmi/cache" coll "github.com/openconfig/gnmi/collector" "github.com/openconfig/gnmi/connection" - "github.com/openconfig/gnmi/manager/manager" + "github.com/openconfig/gnmi/manager" "github.com/openconfig/gnmi/subscribe" "github.com/openconfig/gnmi/target" "github.com/openconfig/gnmi/tunnel/dialer" diff --git a/ctree/tree.go b/ctree/tree.go index 64a91a8..7a09669 100644 --- a/ctree/tree.go +++ b/ctree/tree.go @@ -343,10 +343,26 @@ func (t *Tree) WalkSorted(f VisitFunc) error { return t.walkInternalSorted(nil, f) } -// internalDelete removes nodes recursively that match subpath. It returns true -// if the current node is to be removed from the parent and a slice of subpaths -// ([]string) for all leaves deleted thus far. -func (t *Tree) internalDelete(subpath []string, condition func(interface{}) bool) (bool, [][]string) { +// WalkDeleted removes nodes recursively that match path and satisfy the +// condition function and calls function f on every removed node. +func (t *Tree) WalkDeleted(path []string, condition func(interface{}) bool, f func(interface{})) { + // It is possible that a single delete operation will remove the whole Tree, + // so only the top level write lock is obtained to prevent concurrent accesses + // to the entire Tree. + defer t.mu.Unlock() + t.mu.Lock() + if delBr, _ := t.internalDelete(path, condition, f, false); delBr { + t.leafBranch = nil + } +} + +// internalDelete removes nodes recursively that match subpath and satisfy +// function condition. It also calls function f on every removed leaf. It +// returns true if the current node is to be removed from the parent and +// a slice of subpaths ([]string) for all leaves deleted thus far if +// retDeletedPaths is true. If retDeletedPaths is false, the returned slice +// of subpaths is nil. +func (t *Tree) internalDelete(subpath []string, condition func(interface{}) bool, f func(interface{}), retDeletedPaths bool) (bool, [][]string) { if len(subpath) == 0 || subpath[0] == "*" { if len(subpath) != 0 { subpath = subpath[1:] @@ -356,12 +372,14 @@ func (t *Tree) internalDelete(subpath []string, condition func(interface{}) bool case branch: // The subpath terminates in a branch node and will recursively delete any // progeny leaves. - allLeaves := [][]string{} + var allLeaves [][]string for k, v := range b { - del, leaves := v.internalDelete(subpath, condition) - leaf := []string{k} - for _, l := range leaves { - allLeaves = append(allLeaves, append(leaf, l...)) + del, leaves := v.internalDelete(subpath, condition, f, retDeletedPaths) + if retDeletedPaths { + leaf := []string{k} + for _, l := range leaves { + allLeaves = append(allLeaves, append(leaf, l...)) + } } if del { delete(b, k) @@ -372,19 +390,25 @@ func (t *Tree) internalDelete(subpath []string, condition func(interface{}) bool if condition(t.leafBranch) { // The second parameter is an empty path that will be filled as recursion // unwinds for this leaf that will be deleted in its parent. - return true, [][]string{[]string{}} + f(t.leafBranch) + if retDeletedPaths { + return true, [][]string{[]string{}} + } + return true, nil } - return false, [][]string{} + return false, nil } } if b, ok := t.leafBranch.(branch); ok { // Continue to recurse on subpath while it matches nodes in the Tree. if br := b[subpath[0]]; br != nil { - delBr, allLeaves := br.internalDelete(subpath[1:], condition) - leaf := []string{subpath[0]} - // Prepend branch node name to all progeny leaves of branch. - for i := range allLeaves { - allLeaves[i] = append(leaf, allLeaves[i]...) + delBr, allLeaves := br.internalDelete(subpath[1:], condition, f, retDeletedPaths) + if retDeletedPaths { + leaf := []string{subpath[0]} + // Prepend branch node name to all progeny leaves of branch. + for i := range allLeaves { + allLeaves[i] = append(leaf, allLeaves[i]...) + } } // Remove branch if requested. if delBr { @@ -399,7 +423,7 @@ func (t *Tree) internalDelete(subpath []string, condition func(interface{}) bool } } // The subpath doesn't match any Tree branch, return empty list of leaves. - return false, [][]string{} + return false, nil } // DeleteConditional removes all leaves at or below subpath as well as any @@ -412,7 +436,7 @@ func (t *Tree) DeleteConditional(subpath []string, condition func(interface{}) b // to the entire Tree. defer t.mu.Unlock() t.mu.Lock() - delBr, leaves := t.internalDelete(subpath, condition) + delBr, leaves := t.internalDelete(subpath, condition, func(interface{}) {}, true) if delBr { t.leafBranch = nil } diff --git a/ctree/tree_test.go b/ctree/tree_test.go index 84ec2ff..a0a63fc 100644 --- a/ctree/tree_test.go +++ b/ctree/tree_test.go @@ -279,13 +279,8 @@ type expectedDelete struct { leaves map[string]bool } -func TestDelete(t *testing.T) { - tr := &Tree{} - deleted := tr.Delete([]string{"a", "b"}) - if len(deleted) > 0 { - t.Errorf("Delete on empty tree should return empty slice.") - } - for x, tt := range []expectedDelete{ +func expectedDeletes() []expectedDelete { + return []expectedDelete{ {[]string{"x"}, map[string]bool{}}, // root delete with glob appended for a non-existing root {[]string{"x", "*"}, map[string]bool{}}, @@ -303,7 +298,72 @@ func TestDelete(t *testing.T) { {[]string{}, map[string]bool{"a/d": true, "a/b/c": true, "b/a/d": true, "b/c/d": true, "c/d/e/f/g/h/i": true, "d": true}}, // just glob in the path to delete all the tree {[]string{"*"}, map[string]bool{"a/d": true, "a/b/c": true, "b/a/d": true, "b/c/d": true, "c/d/e/f/g/h/i": true, "d": true}}, - } { + } +} + +func TestWalkDeleted(t *testing.T) { + tr := &Tree{} + always := func(interface{}) bool { return true } + var ds []string + tr.WalkDeleted([]string{"a", "b"}, always, func(v interface{}) { ds = append(ds, v.(string)) }) + if len(ds) > 0 { + t.Errorf("Delete on empty tree should return empty slice.") + } + for x, tt := range expectedDeletes() { + // Rebuild tree for each query. + buildTree(tr) + var deletes []string + tr.WalkDeleted(tt.subpath, always, func(v interface{}) { deletes = append(deletes, v.(string)) }) + for _, leafPath := range deletes { + if _, ok := tt.leaves[leafPath]; !ok { + t.Errorf("#%d: unexpected deleted leaf %v", x, leafPath) + } + delete(tt.leaves, leafPath) + } + if len(tt.leaves) > 0 { + t.Errorf("#%d: expected leaves missing from return: %v", x, tt.leaves) + } + } + if tr.leafBranch != nil { + t.Errorf("tree should be empty, but root still has branches %#v", tr.leafBranch) + } +} + +func TestWalkDeletedWithCondition(t *testing.T) { + never := func(interface{}) bool { return false } + tr := &Tree{} + buildTree(tr) + var leaves []string + tr.WalkDeleted([]string{}, never, func(v interface{}) { leaves = append(leaves, v.(string)) }) + if len(leaves) > 0 { + t.Errorf("Leaves deleted for false condition: %v", leaves) + } + always := func(interface{}) bool { return true } + // This is the same test as the last case for TestWalkDeleted. + leaves = nil + tr.WalkDeleted([]string{}, always, func(v interface{}) { leaves = append(leaves, v.(string)) }) + if len(leaves) != 6 { + t.Errorf("Not all leaves deleted: %v", leaves) + } + valEqualsD := func(v interface{}) bool { return v == "d" } + buildTree(tr) + leaves = nil + tr.WalkDeleted([]string{}, valEqualsD, func(v interface{}) { leaves = append(leaves, v.(string)) }) + if expected := []string{"d"}; !reflect.DeepEqual(expected, leaves) { + t.Errorf("got %v, expected %v", leaves, expected) + } + if v := tr.GetLeafValue([]string{"d"}); nil != v { + t.Errorf("got %v, expected %v", v, nil) + } +} + +func TestDelete(t *testing.T) { + tr := &Tree{} + deleted := tr.Delete([]string{"a", "b"}) + if len(deleted) > 0 { + t.Errorf("Delete on empty tree should return empty slice.") + } + for x, tt := range expectedDeletes() { // Rebuild tree for each query. buildTree(tr) for _, leaf := range tr.Delete(tt.subpath) { diff --git a/go.mod b/go.mod index 123f2a8..36d9b08 100644 --- a/go.mod +++ b/go.mod @@ -3,19 +3,18 @@ module github.com/openconfig/gnmi go 1.12 require ( - github.com/cenkalti/backoff/v4 v4.1.0 - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b - github.com/golang/protobuf v1.4.3 - github.com/google/go-cmp v0.5.0 + github.com/cenkalti/backoff/v4 v4.1.3 + github.com/golang/glog v1.0.0 + github.com/golang/protobuf v1.5.2 + github.com/google/go-cmp v0.5.8 github.com/kylelemons/godebug v1.1.0 - github.com/openconfig/goyang v0.0.0-20200115183954-d0a48929f0ea // indirect - github.com/openconfig/grpctunnel v0.0.0-20210610163803-fde4a9dc048d - github.com/openconfig/ygot v0.6.0 - golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 - golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 - golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e // indirect - golang.org/x/text v0.3.4 // indirect - google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d // indirect - google.golang.org/grpc v1.34.0 - google.golang.org/protobuf v1.25.0 + github.com/openconfig/grpctunnel v0.0.0-20220412182401-2d6d258f73d1 + github.com/openconfig/ygot v0.20.2 + golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 + golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 + golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 // indirect + google.golang.org/genproto v0.0.0-20220523171625-347a074981d8 // indirect + google.golang.org/grpc v1.46.2 + google.golang.org/protobuf v1.28.0 ) diff --git a/go.sum b/go.sum index 0f2862d..bf33d17 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,40 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc= -github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -22,77 +42,150 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/protobuf v3.11.4+incompatible/go.mod h1:lUQ9D1ePzbH2PrIS7ob/bjm9HXyH5WHB0Akwh7URreM= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/openconfig/goyang v0.0.0-20200115183954-d0a48929f0ea h1:5MyIz4bN4vpH6aHDN339bkWXAjTkhg1ZKMhR4aIi5Rk= +github.com/openconfig/gnmi v0.0.0-20200414194230-1597cc0f2600/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A= +github.com/openconfig/gnmi v0.0.0-20200508230933-d19cebf5e7be/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A= github.com/openconfig/goyang v0.0.0-20200115183954-d0a48929f0ea/go.mod h1:dhXaV0JgHJzdrHi2l+w0fZrwArtXL7jEFoiqLEdmkvU= -github.com/openconfig/grpctunnel v0.0.0-20210610163803-fde4a9dc048d h1:zrs4U92QEAadFotQyidT4U8iZDJO67pXsS4r64uAHik= -github.com/openconfig/grpctunnel v0.0.0-20210610163803-fde4a9dc048d/go.mod h1:x9tAZ4EwqCQ0jI8D6S8Yhw9Z0ee7/BxWQX0k0Uib5Q8= -github.com/openconfig/ygot v0.6.0 h1:kJJFPBrczC6TDnz/HMlFTJEdW2CuyUftV13XveIukg0= +github.com/openconfig/goyang v0.2.2/go.mod h1:vX61x01Q46AzbZUzG617vWqh/cB+aisc+RrNkXRd3W8= +github.com/openconfig/goyang v1.0.0 h1:nYaFu7BOAk/eQn4CgAUjgYPfp3J6CdXrBryp32E5CjI= +github.com/openconfig/goyang v1.0.0/go.mod h1:vX61x01Q46AzbZUzG617vWqh/cB+aisc+RrNkXRd3W8= +github.com/openconfig/gribi v0.1.1-0.20210423184541-ce37eb4ba92f/go.mod h1:OoH46A2kV42cIXGyviYmAlGmn6cHjGduyC2+I9d/iVs= +github.com/openconfig/grpctunnel v0.0.0-20220412182401-2d6d258f73d1 h1:NGg2KF70ZZsCcQ2jOYl+icqej+pHSVDqRRjnnICmrbM= +github.com/openconfig/grpctunnel v0.0.0-20220412182401-2d6d258f73d1/go.mod h1:OmTWe7RyZj2CIzIgy4ovEBzCLBJzRvWSZmn7u02U9gU= github.com/openconfig/ygot v0.6.0/go.mod h1:o30svNf7O0xK+R35tlx95odkDmZWS9JyWWQSmIhqwAs= +github.com/openconfig/ygot v0.10.4/go.mod h1:oCQNdXnv7dWc8scTDgoFkauv1wwplJn5HspHcjlxSAQ= +github.com/openconfig/ygot v0.20.2 h1:1a/4fwM0obv+zA13lag6uTmk8Wihdsp9PE5nDQ7t49s= +github.com/openconfig/ygot v0.20.2/go.mod h1:7ZiBFNc4n/1Hkv2v2dAEpxisqDznp0JVpLR13Toe4AY= +github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 h1:SLP7Q4Di66FONjDJbCYrCRrh97focO6sLogHO7/g8F0= +golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs= -golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8= +golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200519141106-08726f379972/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d h1:HV9Z9qMhQEsdlvxNFELgQ11RkMzO3CMkjEySjCtuLes= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210811021853-ddbe55d93216/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8 h1:4NSrVrQGh6+UqBEd+Kwdh6ZDwESH0Sj2bNUQN+VjoQk= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -103,9 +196,15 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/proto/collector/collector.pb.go b/proto/collector/collector.pb.go index 050b45a..c9fb82f 100644 --- a/proto/collector/collector.pb.go +++ b/proto/collector/collector.pb.go @@ -16,8 +16,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.2 +// protoc-gen-go v1.28.0 +// protoc v3.21.0--rc1 // source: github.com/openconfig/gnmi/proto/collector/collector.proto package gnmi diff --git a/proto/collector/collector_grpc.pb.go b/proto/collector/collector_grpc.pb.go index fce75c7..7df4072 100644 --- a/proto/collector/collector_grpc.pb.go +++ b/proto/collector/collector_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.0--rc1 +// source: github.com/openconfig/gnmi/proto/collector/collector.proto package gnmi diff --git a/proto/gnmi/gnmi.pb.go b/proto/gnmi/gnmi.pb.go index 3daa7d0..3f9040a 100644 --- a/proto/gnmi/gnmi.pb.go +++ b/proto/gnmi/gnmi.pb.go @@ -16,8 +16,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.2 +// protoc-gen-go v1.28.0 +// protoc v3.21.0--rc1 // source: github.com/openconfig/gnmi/proto/gnmi/gnmi.proto // Package gNMI defines a service specification for the gRPC Network Management diff --git a/proto/gnmi/gnmi_grpc.pb.go b/proto/gnmi/gnmi_grpc.pb.go index 0ee6cba..1e1055f 100644 --- a/proto/gnmi/gnmi_grpc.pb.go +++ b/proto/gnmi/gnmi_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.0--rc1 +// source: github.com/openconfig/gnmi/proto/gnmi/gnmi.proto package gnmi diff --git a/proto/gnmi_ext/gnmi_ext.pb.go b/proto/gnmi_ext/gnmi_ext.pb.go index aca9c4a..75315a7 100644 --- a/proto/gnmi_ext/gnmi_ext.pb.go +++ b/proto/gnmi_ext/gnmi_ext.pb.go @@ -16,8 +16,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.2 +// protoc-gen-go v1.28.0 +// protoc v3.21.0--rc1 // source: github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto // Package gnmi_ext defines a set of extensions messages which can be optionally diff --git a/proto/target/target.pb.go b/proto/target/target.pb.go index e25e2c8..6fbbe43 100644 --- a/proto/target/target.pb.go +++ b/proto/target/target.pb.go @@ -16,8 +16,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.2 +// protoc-gen-go v1.28.0 +// protoc v3.21.0--rc1 // source: github.com/openconfig/gnmi/proto/target/target.proto // Package target contains messages for defining a configuration of a caching diff --git a/testing/fake/proto/fake.pb.go b/testing/fake/proto/fake.pb.go index 2eeae6d..b3b01a5 100644 --- a/testing/fake/proto/fake.pb.go +++ b/testing/fake/proto/fake.pb.go @@ -4,8 +4,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.2 +// protoc-gen-go v1.28.0 +// protoc v3.21.0--rc1 // source: github.com/openconfig/gnmi/testing/fake/proto/fake.proto package gnmi_fake diff --git a/testing/fake/proto/fake_grpc.pb.go b/testing/fake/proto/fake_grpc.pb.go index 9cb1e04..0292f4c 100644 --- a/testing/fake/proto/fake_grpc.pb.go +++ b/testing/fake/proto/fake_grpc.pb.go @@ -1,4 +1,8 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.0--rc1 +// source: github.com/openconfig/gnmi/testing/fake/proto/fake.proto package gnmi_fake diff --git a/tunnel/dialer.go b/tunnel/dialer/dialer.go similarity index 100% rename from tunnel/dialer.go rename to tunnel/dialer/dialer.go diff --git a/tunnel/dialer_test.go b/tunnel/dialer/dialer_test.go similarity index 100% rename from tunnel/dialer_test.go rename to tunnel/dialer/dialer_test.go