Skip to content
This repository was archived by the owner on Jul 21, 2021. It is now read-only.

Commit e56f918

Browse files
committed
MOD: support chroot for a connection
1 parent 1d7be4e commit e56f918

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

zk/conn.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"fmt"
1717
"io"
1818
"net"
19+
"reflect"
1920
"strconv"
2021
"strings"
2122
"sync"
@@ -73,6 +74,7 @@ type Conn struct {
7374
xid uint32
7475
sessionTimeoutMs int32 // session timeout in milliseconds
7576
passwd []byte
77+
chroot string
7678

7779
dialer Dialer
7880
hostProvider HostProvider
@@ -196,6 +198,7 @@ func Connect(servers []string, sessionTimeout time.Duration, options ...connOpti
196198
requests: make(map[int32]*request),
197199
watchers: make(map[watchPathType][]chan Event),
198200
passwd: emptyPassword,
201+
chroot: "",
199202
logger: DefaultLogger,
200203
buf: make([]byte, bufferSize),
201204

@@ -611,6 +614,19 @@ func (c *Conn) sendData(req *request) error {
611614
return nil
612615
}
613616

617+
if req != nil && req.pkt != nil && c.chroot != "" {
618+
v := reflect.ValueOf(req.pkt)
619+
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
620+
v = v.Elem()
621+
}
622+
if v.Kind() == reflect.Struct {
623+
field := v.FieldByName("Path")
624+
if field.Kind() == reflect.String {
625+
field.SetString(c.chroot + field.String())
626+
}
627+
}
628+
}
629+
614630
n2, err := encodePacket(c.buf[4+n:], req.pkt)
615631
if err != nil {
616632
req.recvChan <- response{-1, err}
@@ -708,6 +724,9 @@ func (c *Conn) recvLoop(conn net.Conn) error {
708724
if err != nil {
709725
return err
710726
}
727+
if c.chroot != "" {
728+
res.Path = strings.TrimPrefix(res.Path, c.chroot)
729+
}
711730
ev := Event{
712731
Type: res.Type,
713732
State: res.State,
@@ -760,6 +779,19 @@ func (c *Conn) recvLoop(conn net.Conn) error {
760779
} else {
761780
_, err = decodePacket(buf[16:blen], req.recvStruct)
762781
}
782+
783+
if req != nil && req.recvStruct != nil && c.chroot != "" {
784+
v := reflect.ValueOf(req.recvStruct)
785+
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
786+
v = v.Elem()
787+
}
788+
if v.Kind() == reflect.Struct {
789+
field := v.FieldByName("Path")
790+
if field.Kind() == reflect.String {
791+
field.SetString(strings.TrimPrefix(field.String(), c.chroot))
792+
}
793+
}
794+
}
763795
if req.recvFunc != nil {
764796
req.recvFunc(req, &res, err)
765797
}
@@ -804,6 +836,16 @@ func (c *Conn) request(opcode int32, req interface{}, res interface{}, recvFunc
804836
return r.zxid, r.err
805837
}
806838

839+
func (c *Conn) Chroot(path string) error {
840+
res := &existsResponse{}
841+
_, err := c.request(opExists, &existsRequest{Path: path, Watch: false}, res, nil)
842+
if err != nil {
843+
return err
844+
}
845+
c.chroot = path
846+
return nil
847+
}
848+
807849
func (c *Conn) AddAuth(scheme string, auth []byte) error {
808850
_, err := c.request(opSetAuth, &setAuthRequest{Type: 0, Scheme: scheme, Auth: auth}, &setAuthResponse{}, nil)
809851

zk/zk_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,49 @@ func TestExpiringWatch(t *testing.T) {
575575
}
576576
}
577577

578+
func TestChroot(t *testing.T) {
579+
ts, err := StartTestCluster(1, nil, logWriter{t: t, p: "[ZKERR] "})
580+
if err != nil {
581+
t.Fatal(err)
582+
}
583+
defer ts.Stop()
584+
zk, _, err := ts.ConnectAll()
585+
if err != nil {
586+
t.Fatalf("Connect returned error: %+v", err)
587+
}
588+
defer zk.Close()
589+
590+
path := "/gozk-test-chroot"
591+
err = zk.Chroot(path)
592+
if err == nil {
593+
t.Fatal("Chroot expect error when path is not exist")
594+
}
595+
_, err = zk.Create(path, []byte{1, 2, 3, 4}, 0, WorldACL(PermAll))
596+
if err != nil {
597+
t.Fatalf("Chroot create path error, %s", err.Error())
598+
}
599+
err = zk.Chroot(path)
600+
if err != nil {
601+
t.Fatalf("Chroot error, %s", err.Error())
602+
}
603+
subPath := "/abc"
604+
actualPath, err := zk.Create(subPath, []byte{1, 2, 3, 4}, 0, WorldACL(PermAll))
605+
if err != nil {
606+
t.Fatalf("Chroot create path error, %s", err.Error())
607+
}
608+
if actualPath != subPath {
609+
t.Fatalf("path expect %s, got %s", path+subPath, actualPath)
610+
}
611+
err = zk.Chroot("")
612+
if err != nil {
613+
t.Fatalf("Chroot error, %s", err.Error())
614+
}
615+
exists, _, err := zk.Exists(path + subPath)
616+
if !exists || err != nil {
617+
t.Fatal("Chroot error as node exists")
618+
}
619+
}
620+
578621
func TestRequestFail(t *testing.T) {
579622
// If connecting fails to all servers in the list then pending requests
580623
// should be errored out so they don't hang forever.

0 commit comments

Comments
 (0)