Merge "veyron/lib/testutil/integration: add more godoc"
diff --git a/lib/exec/config.go b/lib/exec/config.go
index 52c622f..71fffd5 100644
--- a/lib/exec/config.go
+++ b/lib/exec/config.go
@@ -1,12 +1,10 @@
package exec
import (
- "bytes"
- "strings"
"sync"
"v.io/core/veyron2/verror2"
- "v.io/core/veyron2/vom"
+ "v.io/core/veyron2/vom2"
)
// Config defines a simple key-value configuration. Keys and values are
@@ -52,13 +50,13 @@
return &cfg{m: make(map[string]string)}
}
-func (c cfg) Set(key, value string) {
+func (c *cfg) Set(key, value string) {
c.Lock()
defer c.Unlock()
c.m[key] = value
}
-func (c cfg) Get(key string) (string, error) {
+func (c *cfg) Get(key string) (string, error) {
c.RLock()
defer c.RUnlock()
v, ok := c.m[key]
@@ -68,7 +66,7 @@
return v, nil
}
-func (c cfg) Dump() (res map[string]string) {
+func (c *cfg) Dump() (res map[string]string) {
res = make(map[string]string)
c.RLock()
defer c.RUnlock()
@@ -78,31 +76,31 @@
return
}
-func (c cfg) Clear(key string) {
+func (c *cfg) Clear(key string) {
c.Lock()
defer c.Unlock()
delete(c.m, key)
}
-func (c cfg) Serialize() (string, error) {
- var buf bytes.Buffer
+func (c *cfg) Serialize() (string, error) {
c.RLock()
- defer c.RUnlock()
- if err := vom.NewEncoder(&buf).Encode(c.m); err != nil {
+ data, err := vom2.Encode(c.m)
+ c.RUnlock()
+ if err != nil {
return "", err
}
- return buf.String(), nil
+ return string(data), nil
}
-func (c cfg) MergeFrom(serialized string) error {
+func (c *cfg) MergeFrom(serialized string) error {
var newM map[string]string
- if err := vom.NewDecoder(strings.NewReader(serialized)).Decode(&newM); err != nil {
+ if err := vom2.Decode([]byte(serialized), &newM); err != nil {
return err
}
c.Lock()
- defer c.Unlock()
for k, v := range newM {
c.m[k] = v
}
+ c.Unlock()
return nil
}
diff --git a/lib/modules/shell.go b/lib/modules/shell.go
index ecaefde..6ed18d4 100644
--- a/lib/modules/shell.go
+++ b/lib/modules/shell.go
@@ -155,7 +155,7 @@
return nil, err
}
syscall.CloseOnExec(fd)
- p, err := agent.NewAgentPrincipal(ctx, fd)
+ p, err := agent.NewAgentPrincipal(ctx, fd, veyron2.GetClient(ctx))
if err != nil {
return nil, err
}
diff --git a/lib/signals/signals.go b/lib/signals/signals.go
index e2d64a6..564c6c6 100644
--- a/lib/signals/signals.go
+++ b/lib/signals/signals.go
@@ -4,6 +4,7 @@
"os"
"os/signal"
"syscall"
+ "time"
"v.io/core/veyron2"
"v.io/core/veyron2/context"
@@ -19,6 +20,25 @@
DoubleStopExitCode = 1
)
+// TODO(caprita): Needless to say, this is a hack. The motivator was getting
+// the device manager (run by the security agent) to shut down cleanly when the
+// process group containing both the agent and device manager receives a signal
+// (and the agent propagates that signal to the child). We should be able to
+// finesse this by demonizing the device manager and/or being smarter about how
+// and when the agent sends the signal to the child.
+
+// SameSignalTimeWindow specifies the time window during which multiple
+// deliveries of the same signal are counted as one signal. If set to zero, no
+// such de-duping occurs. This is useful in situations where a process receives
+// a signal explicitly sent by its parent when the parent receives the signal,
+// but also receives it independently by virtue of being part of the same
+// process group.
+//
+// This is a variable, so that I can be set appropriately. Note, there is no
+// locking around it, the assumption being that it's set during initialization
+// and never reset afterwards.
+var SameSignalTimeWindow time.Duration
+
// defaultSignals returns a set of platform-specific signals that an application
// is encouraged to listen on.
func defaultSignals() []os.Signal {
@@ -68,11 +88,19 @@
go func() {
// First signal received.
sig := <-ch
+ sigTime := time.Now()
ret <- sig
// Wait for a second signal, and force an exit if the process is
// still executing cleanup code.
- <-ch
- os.Exit(DoubleStopExitCode)
+ for {
+ secondSig := <-ch
+ // If signal de-duping is enabled, ignore the signal if
+ // it's the same signal and has occured within the
+ // specified time window.
+ if SameSignalTimeWindow <= 0 || secondSig.String() != sig.String() || sigTime.Add(SameSignalTimeWindow).Before(time.Now()) {
+ os.Exit(DoubleStopExitCode)
+ }
+ }
}()
return ret
}
diff --git a/profiles/chrome/chromeinit.go b/profiles/chrome/chromeinit.go
index e7c37cb..b18108d 100644
--- a/profiles/chrome/chromeinit.go
+++ b/profiles/chrome/chromeinit.go
@@ -19,6 +19,6 @@
if err != nil {
return nil, nil, shutdown, err
}
- veyron2.GetLogger(ctx).VI(1).Infof("Initializing chrome profile.")
+ runtime.GetLogger(ctx).VI(1).Infof("Initializing chrome profile.")
return runtime, ctx, shutdown, nil
}
diff --git a/profiles/gce/initx.go b/profiles/gce/initx.go
index 60f1e69..4aa63c8 100644
--- a/profiles/gce/initx.go
+++ b/profiles/gce/initx.go
@@ -41,7 +41,7 @@
if err != nil {
return nil, nil, shutdown, err
}
- veyron2.GetLogger(ctx).VI(1).Infof("Initializing GCE profile.")
+ runtime.GetLogger(ctx).VI(1).Infof("Initializing GCE profile.")
lf := commonFlags.ListenFlags()
listenSpec := ipc.ListenSpec{
diff --git a/profiles/genericinit.go b/profiles/genericinit.go
index 73224f6..cbd7312 100644
--- a/profiles/genericinit.go
+++ b/profiles/genericinit.go
@@ -20,7 +20,7 @@
if err != nil {
return nil, nil, nil, err
}
- veyron2.GetLogger(ctx).VI(1).Infof("Initializing generic profile.")
+ runtime.GetLogger(ctx).VI(1).Infof("Initializing generic profile.")
ac := appcycle.New()
ctx = runtime.SetAppCycle(ctx, ac)
diff --git a/profiles/roaming/roaminginit.go b/profiles/roaming/roaminginit.go
index f36720d..533cabb 100644
--- a/profiles/roaming/roaminginit.go
+++ b/profiles/roaming/roaminginit.go
@@ -76,7 +76,7 @@
}
}
- publisher := veyron2.GetPublisher(ctx)
+ publisher := runtime.GetPublisher(ctx)
// Create stream in Init function to avoid a race between any
// goroutines started here and consumers started after Init returns.
@@ -106,13 +106,13 @@
cleanupCh := make(chan struct{})
watcherCh := make(chan struct{})
- listenSpec.StreamPublisher = veyron2.GetPublisher(ctx)
+ listenSpec.StreamPublisher = publisher
listenSpec.StreamName = SettingsStreamName
listenSpec.AddressChooser = internal.IPAddressChooser
ctx = runtime.SetListenSpec(ctx, listenSpec)
- go monitorNetworkSettingsX(ctx, watcher, prev, stop, cleanupCh, watcherCh, ch, ListenSpec)
+ go monitorNetworkSettingsX(runtime, ctx, watcher, prev, stop, cleanupCh, watcherCh, ch)
profileShutdown := func() {
close(cleanupCh)
shutdown()
@@ -124,11 +124,18 @@
// monitorNetworkSettings will monitor network configuration changes and
// publish subsequent Settings to reflect any changes detected.
-func monitorNetworkSettingsX(ctx *context.T, watcher netconfig.NetConfigWatcher, prev netstate.AddrList, pubStop, cleanup <-chan struct{},
- watcherLoop chan<- struct{}, ch chan<- config.Setting, listenSpec ipc.ListenSpec) {
+func monitorNetworkSettingsX(
+ runtime *grt.RuntimeX,
+ ctx *context.T,
+ watcher netconfig.NetConfigWatcher,
+ prev netstate.AddrList,
+ pubStop, cleanup <-chan struct{},
+ watcherLoop chan<- struct{},
+ ch chan<- config.Setting) {
defer close(ch)
- log := veyron2.GetLogger(ctx)
+ log := runtime.GetLogger(ctx)
+ listenSpec := runtime.GetListenSpec(ctx)
// TODO(cnicolaou): add support for listening on multiple network addresses.
diff --git a/runtimes/google/ipc/benchmark/service.vdl.go b/runtimes/google/ipc/benchmark/service.vdl.go
index cea2802..a09b115 100644
--- a/runtimes/google/ipc/benchmark/service.vdl.go
+++ b/runtimes/google/ipc/benchmark/service.vdl.go
@@ -14,14 +14,8 @@
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
__vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// BenchmarkClientMethods is the client interface
// containing Benchmark methods.
type BenchmarkClientMethods interface {
@@ -80,17 +74,6 @@
return
}
-func (c implBenchmarkClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// BenchmarkEchoStreamClientStream is the client stream for Benchmark.EchoStream.
type BenchmarkEchoStreamClientStream interface {
// RecvStream returns the receiver side of the Benchmark.EchoStream client stream.
@@ -220,8 +203,6 @@
BenchmarkServerStubMethods
// Describe the Benchmark interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// BenchmarkServer returns a server stub for Benchmark.
@@ -293,33 +274,6 @@
},
}
-func (s implBenchmarkServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Echo"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "Payload", Type: 66},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 66},
- {Name: "", Type: 67},
- },
- }
- result.Methods["EchoStream"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 67},
- },
- InStream: 66,
- OutStream: 66,
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
- return result, nil
-}
-
// BenchmarkEchoStreamServerStream is the server stream for Benchmark.EchoStream.
type BenchmarkEchoStreamServerStream interface {
// RecvStream returns the receiver side of the Benchmark.EchoStream server stream.
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index a472e68..2199a8d 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -21,7 +21,6 @@
old_verror "v.io/core/veyron2/verror"
verror "v.io/core/veyron2/verror2"
"v.io/core/veyron2/vlog"
- "v.io/core/veyron2/vom"
"v.io/core/veyron2/vom2"
"v.io/core/veyron2/vtrace"
@@ -67,7 +66,7 @@
errArgEncoding = verror.Register(pkgPath+".argEncoding", verror.NoRetry, "failed to encode arg #{3}{:4:}")
- errMismatchedResults = verror.Register(pkgPath+".mismatchedResults", verror.NoRetry, "expected {3} results, but got {4}")
+ errMismatchedResults = verror.Register(pkgPath+".mismatchedResults", verror.NoRetry, "got {3} results, but want {4}")
errResultDecoding = verror.Register(pkgPath+".resultDecoding", verror.NoRetry, "failed to decode result #{3}{:4}")
@@ -399,8 +398,8 @@
var servers []string
var pattern security.BlessingPattern
- if resolved, err := c.ns.ResolveX(ctx, name, resolveOpts...); err != nil {
- vlog.Errorf("ResolveX: %v", err)
+ if resolved, err := c.ns.Resolve(ctx, name, resolveOpts...); err != nil {
+ vlog.Errorf("Resolve: %v", err)
if verror.Is(err, naming.ErrNoSuchName.ID) {
return nil, verror.RetryRefetch, verror.Make(verror.NoServers, ctx, name)
}
@@ -674,12 +673,12 @@
// flowClient implements the RPC client-side protocol for a single RPC, over a
// flow that's already connected to the server.
type flowClient struct {
- ctx *context.T // context to annotate with call details
- dec vomDecoder // to decode responses and results from the server
- enc vomEncoder // to encode requests and args to the server
- server []string // Blessings bound to the server that authorize it to receive the IPC request from the client.
- flow stream.Flow // the underlying flow
- response ipc.Response // each decoded response message is kept here
+ ctx *context.T // context to annotate with call details
+ dec *vom2.Decoder // to decode responses and results from the server
+ enc *vom2.Encoder // to encode requests and args to the server
+ server []string // Blessings bound to the server that authorize it to receive the IPC request from the client.
+ flow stream.Flow // the underlying flow
+ response ipc.Response // each decoded response message is kept here
discharges []security.Discharge // discharges used for this request
dc vc.DischargeClient // client-global discharge-client
@@ -697,25 +696,18 @@
func newFlowClient(ctx *context.T, server []string, flow stream.Flow, dc vc.DischargeClient) (*flowClient, error) {
fc := &flowClient{
ctx: ctx,
- dec: vom.NewDecoder(flow),
- enc: vom.NewEncoder(flow),
server: server,
flow: flow,
dc: dc,
}
- if vom2.IsEnabled() {
- var err error
- if fc.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
- berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomEncoder, fc.ctx, err))
- return nil, fc.close(berr)
- }
- if fc.dec, err = vom2.NewDecoder(flow); err != nil {
- berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomDecoder, fc.ctx, err))
- return nil, fc.close(berr)
- }
- } else {
- fc.dec = vom.NewDecoder(flow)
- fc.enc = vom.NewEncoder(flow)
+ var err error
+ if fc.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
+ berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomEncoder, fc.ctx, err))
+ return nil, fc.close(berr)
+ }
+ if fc.dec, err = vom2.NewDecoder(flow); err != nil {
+ berr := verror.Make(verror.BadProtocol, fc.ctx, verror.Make(errVomDecoder, fc.ctx, err))
+ return nil, fc.close(berr)
}
return fc, nil
}
diff --git a/runtimes/google/ipc/client_test.go b/runtimes/google/ipc/client_test.go
index a124355..e44b5bb 100644
--- a/runtimes/google/ipc/client_test.go
+++ b/runtimes/google/ipc/client_test.go
@@ -98,7 +98,7 @@
}
func numServers(t *testing.T, name string) int {
- me, err := veyron2.GetNamespace(gctx).ResolveX(gctx, name)
+ me, err := veyron2.GetNamespace(gctx).Resolve(gctx, name)
if err != nil {
return 0
}
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 3db30e5..e8d702d 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -233,7 +233,7 @@
}
func verifyMount(t *testing.T, ns naming.Namespace, name string) []string {
- me, err := ns.ResolveX(testContext(), name)
+ me, err := ns.Resolve(testContext(), name)
if err != nil {
t.Errorf("%s: %s not found in mounttable", loc(1), name)
return nil
@@ -242,7 +242,7 @@
}
func verifyMountMissing(t *testing.T, ns naming.Namespace, name string) {
- if me, err := ns.ResolveX(testContext(), name); err == nil {
+ if me, err := ns.Resolve(testContext(), name); err == nil {
names := me.Names()
t.Errorf("%s: %s not supposed to be found in mounttable; got %d servers instead: %v", loc(1), name, len(names), names)
}
@@ -280,7 +280,7 @@
// It must return a name since it'll be passed to StartCall.
func fakeWSName(ns naming.Namespace, name string) (string, error) {
// Find the ws endpoint and use that.
- me, err := ns.ResolveX(testContext(), name)
+ me, err := ns.Resolve(testContext(), name)
if err != nil {
return "", err
}
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index e9b7066..d6df99b 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -22,7 +22,6 @@
old_verror "v.io/core/veyron2/verror"
verror "v.io/core/veyron2/verror2"
"v.io/core/veyron2/vlog"
- "v.io/core/veyron2/vom"
"v.io/core/veyron2/vom2"
"v.io/core/veyron2/vtrace"
@@ -35,7 +34,6 @@
// TODO(cnicolaou): finish verror -> verror2 transition, in particular
// for communicating from server to client.
- // TODO(cnicolaou): remove the vom1 code now that vom2 is in place.
)
var (
@@ -122,7 +120,6 @@
s.preferredProtocols = []string(opt)
}
}
- // TODO(suharshs,mattr): Get a client from the context.
client, err := InternalNewClient(streamMgr, ns)
if err != nil {
return nil, fmt.Errorf("failed to create discharge-client: %v", err)
@@ -158,7 +155,7 @@
if s.ns != nil {
var entry *naming.MountEntry
var err error
- if entry, err = s.ns.ResolveX(s.ctx, address); err != nil {
+ if entry, err = s.ns.Resolve(s.ctx, address); err != nil {
return "", err
}
names = entry.Names()
@@ -796,23 +793,14 @@
return nil
}
-// TODO(toddw): Remove these interfaces after the vom2 transition.
-type vomEncoder interface {
- Encode(v interface{}) error
-}
-
-type vomDecoder interface {
- Decode(v interface{}) error
-}
-
// flowServer implements the RPC server-side protocol for a single RPC, over a
// flow that's already connected to the client.
type flowServer struct {
*context.T
server *server // ipc.Server that this flow server belongs to
disp ipc.Dispatcher // ipc.Dispatcher that will serve RPCs on this flow
- dec vomDecoder // to decode requests and args from the client
- enc vomEncoder // to encode responses and results to the client
+ dec *vom2.Decoder // to decode requests and args from the client
+ enc *vom2.Encoder // to encode responses and results to the client
flow stream.Flow // underlying flow
// Fields filled in during the server invocation.
@@ -841,66 +829,18 @@
flow: flow,
discharges: make(map[string]security.Discharge),
}
- if vom2.IsEnabled() {
- var err error
- if fs.dec, err = vom2.NewDecoder(flow); err != nil {
- flow.Close()
- return nil, err
- }
- if fs.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
- flow.Close()
- return nil, err
- }
- } else {
- fs.dec = vom.NewDecoder(flow)
- fs.enc = vom.NewEncoder(flow)
+ var err error
+ if fs.dec, err = vom2.NewDecoder(flow); err != nil {
+ flow.Close()
+ return nil, err
+ }
+ if fs.enc, err = vom2.NewBinaryEncoder(flow); err != nil {
+ flow.Close()
+ return nil, err
}
return fs, nil
}
-// Vom does not encode untyped nils.
-// Consequently, the ipc system does not allow nil results with an interface
-// type from server methods. The one exception being errors.
-//
-// For now, the following hacky assumptions are made, which will be revisited when
-// a decision is made on how untyped nils should be encoded/decoded in
-// vom/vom2:
-//
-// - Server methods return 0 or more results
-// - Any values returned by the server that have an interface type are either
-// non-nil or of type error.
-func vomErrorHack(res interface{}) vom.Value {
- v := vom.ValueOf(res)
- if !v.IsValid() {
- // Untyped nils are assumed to be nil-errors.
- var boxed old_verror.E
- return vom.ValueOf(&boxed).Elem()
- }
- if err, iserr := res.(error); iserr {
- // Convert errors to verror since errors are often not
- // serializable via vom/gob (errors.New and fmt.Errorf return a
- // type with no exported fields).
- return vom.ValueOf(old_verror.Convert(err))
- }
- return v
-}
-
-// TODO(toddw): Remove this function and encodeValueHack after the vom2 transition.
-func vom2ErrorHack(res interface{}) interface{} {
- if err, ok := res.(error); ok {
- return &err
- }
- return res
-}
-
-// TODO(toddw): Remove this function and vom2ErrorHack after the vom2 transition.
-func (fs *flowServer) encodeValueHack(res interface{}) error {
- if vom2.IsEnabled() {
- return fs.enc.Encode(vom2ErrorHack(res))
- }
- return fs.enc.(*vom.Encoder).EncodeValue(vomErrorHack(res))
-}
-
func (fs *flowServer) serve() error {
defer fs.flow.Close()
@@ -931,7 +871,7 @@
return response.Error
}
for ix, res := range results {
- if err := fs.encodeValueHack(res); err != nil {
+ if err := fs.enc.Encode(res); err != nil {
if err == io.EOF {
return err
}
diff --git a/runtimes/google/ipc/server_test.go b/runtimes/google/ipc/server_test.go
index 1f362be..b71aed9 100644
--- a/runtimes/google/ipc/server_test.go
+++ b/runtimes/google/ipc/server_test.go
@@ -198,7 +198,7 @@
waitfor := func(expect int) {
then := time.Now().Add(time.Minute)
for {
- me, err := ns.ResolveX(testContext(), name)
+ me, err := ns.Resolve(testContext(), name)
if err == nil && len(me.Servers) == expect {
close(ch)
return
@@ -268,7 +268,7 @@
}
for {
- if _, err := ns.ResolveX(testContext(), name); err != nil {
+ if _, err := ns.Resolve(testContext(), name); err != nil {
break
}
time.Sleep(10 * time.Millisecond)
diff --git a/runtimes/google/lib/deque/deque.go b/runtimes/google/lib/deque/deque.go
index 54ddbfb..a104de2 100644
--- a/runtimes/google/lib/deque/deque.go
+++ b/runtimes/google/lib/deque/deque.go
@@ -105,10 +105,9 @@
q.contents = make([]interface{}, initialQueueSize)
return
}
- contents := make([]interface{}, len(q.contents)*2)
- for i := 0; i != q.size; i++ {
- contents[i] = q.contents[(q.fx+i)%len(q.contents)]
- }
+ contents := make([]interface{}, q.size*2)
+ i := copy(contents[:], q.contents[q.fx:])
+ copy(contents[i:], q.contents[:q.fx])
q.contents = contents
q.fx = 0
q.bx = q.size
diff --git a/runtimes/google/lib/deque/deque_test.go b/runtimes/google/lib/deque/deque_test.go
index 2e34c41..ae0d4d3 100644
--- a/runtimes/google/lib/deque/deque_test.go
+++ b/runtimes/google/lib/deque/deque_test.go
@@ -209,3 +209,41 @@
t.Errorf("Iteration did not stop correctly,expected 6 iterations, got %d", iterations)
}
}
+
+func BenchmarkPushFront(b *testing.B) {
+ var q T
+ for i := 0; i < b.N; i++ {
+ q.PushFront(i)
+ }
+}
+
+func BenchmarkPushBack(b *testing.B) {
+ var q T
+ for i := 0; i < b.N; i++ {
+ q.PushBack(i)
+ }
+}
+
+func BenchmarkPopFront(b *testing.B) {
+ var q T
+ for i := 0; i < b.N; i++ {
+ q.PushBack(i)
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ q.PopFront()
+ }
+}
+
+func BenchmarkPopBack(b *testing.B) {
+ var q T
+ for i := 0; i < b.N; i++ {
+ q.PushFront(i)
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ q.PopBack()
+ }
+}
diff --git a/runtimes/google/lib/publisher/publisher.go b/runtimes/google/lib/publisher/publisher.go
index c5d35ed..5ccf6e7 100644
--- a/runtimes/google/lib/publisher/publisher.go
+++ b/runtimes/google/lib/publisher/publisher.go
@@ -342,7 +342,7 @@
func (ps *pubState) published() []string {
var ret []string
for name, _ := range ps.names {
- e, err := ps.ns.ResolveToMountTableX(ps.ctx, name)
+ e, err := ps.ns.ResolveToMountTable(ps.ctx, name)
if err != nil {
vlog.Errorf("ipc pub: couldn't resolve %v to mount table: %v", name, err)
continue
diff --git a/runtimes/google/lib/publisher/publisher_test.go b/runtimes/google/lib/publisher/publisher_test.go
index c0d0c4d..a947799 100644
--- a/runtimes/google/lib/publisher/publisher_test.go
+++ b/runtimes/google/lib/publisher/publisher_test.go
@@ -28,11 +28,11 @@
}
func resolve(t *testing.T, ns naming.Namespace, name string) []string {
- servers, err := ns.Resolve(testContext(), name)
+ me, err := ns.Resolve(testContext(), name)
if err != nil {
t.Fatalf("failed to resolve %q", name)
}
- return servers
+ return me.Names()
}
func TestAddAndRemove(t *testing.T) {
diff --git a/runtimes/google/naming/namespace/all_test.go b/runtimes/google/naming/namespace/all_test.go
index 406a884..ad898a7 100644
--- a/runtimes/google/naming/namespace/all_test.go
+++ b/runtimes/google/naming/namespace/all_test.go
@@ -149,19 +149,19 @@
}
func testResolveToMountTable(t *testing.T, ctx *context.T, ns naming.Namespace, name string, want ...string) {
- doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTableX, ctx, name, want)
+ doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, ctx, name, want)
}
func testResolveToMountTableWithPattern(t *testing.T, ctx *context.T, ns naming.Namespace, name string, pattern naming.ResolveOpt, want ...string) {
- doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTableX, ctx, name, want, pattern)
+ doResolveTest(t, "ResolveToMountTable", ns.ResolveToMountTable, ctx, name, want, pattern)
}
func testResolve(t *testing.T, ctx *context.T, ns naming.Namespace, name string, want ...string) {
- doResolveTest(t, "Resolve", ns.ResolveX, ctx, name, want)
+ doResolveTest(t, "Resolve", ns.Resolve, ctx, name, want)
}
func testResolveWithPattern(t *testing.T, ctx *context.T, ns naming.Namespace, name string, pattern naming.ResolveOpt, want ...string) {
- doResolveTest(t, "Resolve", ns.ResolveX, ctx, name, want, pattern)
+ doResolveTest(t, "Resolve", ns.Resolve, ctx, name, want, pattern)
}
type serverEntry struct {
@@ -562,7 +562,7 @@
for i := 0; i < 40; i++ {
cycle += "/c3/c4"
}
- if _, err := ns.ResolveX(c, "c1/"+cycle); !verror.Is(err, naming.ErrResolutionDepthExceeded.ID) {
+ if _, err := ns.Resolve(c, "c1/"+cycle); !verror.Is(err, naming.ErrResolutionDepthExceeded.ID) {
boom(t, "Failed to detect cycle")
}
diff --git a/runtimes/google/naming/namespace/mount.go b/runtimes/google/naming/namespace/mount.go
index 9b7d186..66bf6d0 100644
--- a/runtimes/google/naming/namespace/mount.go
+++ b/runtimes/google/naming/namespace/mount.go
@@ -85,10 +85,11 @@
// dispatch executes f in parallel for each mount table implementing mTName.
func (ns *namespace) dispatch(ctx *context.T, mTName string, f func(*context.T, string, string) status) error {
// Resolve to all the mount tables implementing name.
- mts, err := ns.ResolveToMountTable(ctx, mTName)
+ me, err := ns.ResolveToMountTable(ctx, mTName)
if err != nil {
return err
}
+ mts := me.Names()
// Apply f to each of the returned mount tables.
c := make(chan status, len(mts))
for _, mt := range mts {
diff --git a/runtimes/google/naming/namespace/resolve.go b/runtimes/google/naming/namespace/resolve.go
index bc79cc8..97f8e9b 100644
--- a/runtimes/google/naming/namespace/resolve.go
+++ b/runtimes/google/naming/namespace/resolve.go
@@ -32,7 +32,7 @@
}
// Not in cache, call the real server.
callCtx, _ := context.WithTimeout(ctx, callTimeout)
- call, err := client.StartCall(callCtx, pattern_and_name, "ResolveStepX", nil, append(opts, options.NoResolve{})...)
+ call, err := client.StartCall(callCtx, pattern_and_name, "ResolveStep", nil, append(opts, options.NoResolve{})...)
if err != nil {
finalErr = err
vlog.VI(2).Infof("ResolveStep.StartCall %s failed: %s", name, err)
@@ -68,14 +68,14 @@
return len(e.Name) == 0
}
-// ResolveX implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
+// Resolve implements veyron2/naming.Namespace.
+func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
defer vlog.LogCall()()
e, _ := ns.rootMountEntry(name)
if vlog.V(2) {
_, file, line, _ := runtime.Caller(1)
- vlog.Infof("ResolveX(%s) called from %s:%d", name, file, line)
- vlog.Infof("ResolveX(%s) -> rootMountEntry %v", name, *e)
+ vlog.Infof("Resolve(%s) called from %s:%d", name, file, line)
+ vlog.Infof("Resolve(%s) -> rootMountEntry %v", name, *e)
}
if skipResolve(opts) {
return e, nil
@@ -93,9 +93,9 @@
}
// Iterate walking through mount table servers.
for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
- vlog.VI(2).Infof("ResolveX(%s) loop %v", name, *e)
+ vlog.VI(2).Infof("Resolve(%s) loop %v", name, *e)
if !e.ServesMountTable() || terminal(e) {
- vlog.VI(1).Infof("ResolveX(%s) -> %v", name, *e)
+ vlog.VI(1).Infof("Resolve(%s) -> %v", name, *e)
return e, nil
}
var err error
@@ -104,13 +104,13 @@
// Lots of reasons why another error can happen. We are trying
// to single out "this isn't a mount table".
if notAnMT(err) {
- vlog.VI(1).Infof("ResolveX(%s) -> %v", name, curr)
+ vlog.VI(1).Infof("Resolve(%s) -> %v", name, curr)
return curr, nil
}
if verror.Is(err, naming.ErrNoSuchNameRoot.ID) {
err = verror.Make(naming.ErrNoSuchName, ctx, name)
}
- vlog.VI(1).Infof("ResolveX(%s) -> (%s: %v)", err, name, curr)
+ vlog.VI(1).Infof("Resolve(%s) -> (%s: %v)", err, name, curr)
return nil, err
}
pattern = ""
@@ -118,24 +118,14 @@
return nil, verror.Make(naming.ErrResolutionDepthExceeded, ctx)
}
-// Resolve implements veyron2/naming.Namespace.
-func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
- defer vlog.LogCall()()
- e, err := ns.ResolveX(ctx, name, opts...)
- if err != nil {
- return nil, err
- }
- return e.Names(), nil
-}
-
-// ResolveToMountTableX implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveToMountTableX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
+// ResolveToMountTable implements veyron2/naming.Namespace.
+func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
defer vlog.LogCall()()
e, _ := ns.rootMountEntry(name)
if vlog.V(2) {
_, file, line, _ := runtime.Caller(1)
- vlog.Infof("ResolveToMountTableX(%s) called from %s:%d", name, file, line)
- vlog.Infof("ResolveToMountTableX(%s) -> rootNames %v", name, e)
+ vlog.Infof("ResolveToMountTable(%s) called from %s:%d", name, file, line)
+ vlog.Infof("ResolveToMountTable(%s) -> rootNames %v", name, e)
}
if len(e.Servers) == 0 {
return nil, verror.Make(naming.ErrNoMountTable, ctx)
@@ -144,33 +134,33 @@
client := veyron2.GetClient(ctx)
last := e
for remaining := ns.maxResolveDepth; remaining > 0; remaining-- {
- vlog.VI(2).Infof("ResolveToMountTableX(%s) loop %v", name, e)
+ vlog.VI(2).Infof("ResolveToMountTable(%s) loop %v", name, e)
var err error
curr := e
// If the next name to resolve doesn't point to a mount table, we're done.
if !e.ServesMountTable() || terminal(e) {
- vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v", name, last)
+ vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v", name, last)
return last, nil
}
if e, err = ns.resolveAgainstMountTable(ctx, client, e, pattern); err != nil {
if verror.Is(err, naming.ErrNoSuchNameRoot.ID) {
- vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v (NoSuchRoot: %v)", name, last, curr)
+ vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v (NoSuchRoot: %v)", name, last, curr)
return last, nil
}
if verror.Is(err, naming.ErrNoSuchName.ID) {
- vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v (NoSuchName: %v)", name, curr, curr)
+ vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v (NoSuchName: %v)", name, curr, curr)
return curr, nil
}
// Lots of reasons why another error can happen. We are trying
// to single out "this isn't a mount table".
if notAnMT(err) {
- vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v", name, last)
+ vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v", name, last)
return last, nil
}
// TODO(caprita): If the server is unreachable for
// example, we may still want to return its parent
// mounttable rather than an error.
- vlog.VI(1).Infof("ResolveToMountTableX(%s) -> %v", name, err)
+ vlog.VI(1).Infof("ResolveToMountTable(%s) -> %v", name, err)
return nil, err
}
last = curr
@@ -179,16 +169,6 @@
return nil, verror.Make(naming.ErrResolutionDepthExceeded, ctx)
}
-// ResolveToMountTable implements veyron2/naming.Namespace.
-func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
- defer vlog.LogCall()()
- e, err := ns.ResolveToMountTableX(ctx, name, opts...)
- if err != nil {
- return nil, err
- }
- return e.Names(), nil
-}
-
// FlushCache flushes the most specific entry found for name. It returns true if anything was
// actually flushed.
func (ns *namespace) FlushCacheEntry(name string) bool {
diff --git a/runtimes/google/rt/rt.go b/runtimes/google/rt/rt.go
index 77f1258..c7bcafa 100644
--- a/runtimes/google/rt/rt.go
+++ b/runtimes/google/rt/rt.go
@@ -137,15 +137,16 @@
}
}
- // This call to NewClient creates a client that is attached to the context used
- // by the NewAgentPrincipal call in initSecurity. The context used by NewAgentPrincipal
- // is incomplete and only works because the agent uses anonymous unix sockets and
+ // This call to NewClient creates a client that is used by the
+ // NewAgentPrincipal call in initSecurity. This client is incomplete
+ // and only works because the agent uses anonymous unix sockets and
// VCSecurityNone.
- if rt.client, err = rt.NewClient(); err != nil {
+ client, err := rt.NewClient()
+ if err != nil {
return nil, fmt.Errorf("failed to create new client: %s", err)
}
- if err := rt.initSecurity(handle, rt.flags.Credentials); err != nil {
+ if err := rt.initSecurity(handle, rt.flags.Credentials, client); err != nil {
return nil, fmt.Errorf("failed to init security: %s", err)
}
diff --git a/runtimes/google/rt/runtimex.go b/runtimes/google/rt/runtimex.go
index c2a5ac3..ff35b2d 100644
--- a/runtimes/google/rt/runtimex.go
+++ b/runtimes/google/rt/runtimex.go
@@ -166,16 +166,16 @@
return nil, nil, nil, err
}
- // The client we attach here is incomplete (has a nil principal) and only works
+ // The client we create here is incomplete (has a nil principal) and only works
// because the agent uses anonymous unix sockets and VCSecurityNone.
// After security is initialized we will attach a real client.
- ctx, _, err = r.SetNewClient(ctx)
+ _, client, err := r.SetNewClient(ctx)
if err != nil {
return nil, nil, nil, err
}
// Initialize security.
- principal, err := initSecurity(ctx, handle, flags.Credentials)
+ principal, err := initSecurity(ctx, handle, flags.Credentials, client)
if err != nil {
return nil, nil, nil, err
}
diff --git a/runtimes/google/rt/security.go b/runtimes/google/rt/security.go
index 5f6a14d..1ea73f4 100644
--- a/runtimes/google/rt/security.go
+++ b/runtimes/google/rt/security.go
@@ -4,6 +4,7 @@
"os"
"syscall"
+ "v.io/core/veyron2/ipc"
"v.io/core/veyron2/security"
"v.io/core/veyron/lib/exec"
@@ -16,8 +17,8 @@
return rt.principal
}
-func (rt *vrt) initSecurity(handle *exec.ChildHandle, credentials string) error {
- if err := rt.setupPrincipal(handle, credentials); err != nil {
+func (rt *vrt) initSecurity(handle *exec.ChildHandle, credentials string, client ipc.Client) error {
+ if err := rt.setupPrincipal(handle, credentials, client); err != nil {
return err
}
stats.NewString("security/principal/key").Set(rt.principal.PublicKey().String())
@@ -26,7 +27,7 @@
return nil
}
-func (rt *vrt) setupPrincipal(handle *exec.ChildHandle, credentials string) error {
+func (rt *vrt) setupPrincipal(handle *exec.ChildHandle, credentials string, client ipc.Client) error {
if rt.principal != nil {
return nil
}
@@ -34,7 +35,7 @@
return err
} else if fd >= 0 {
var err error
- rt.principal, err = rt.connectToAgent(fd)
+ rt.principal, err = rt.connectToAgent(fd, client)
return err
}
if len(credentials) > 0 {
@@ -60,7 +61,7 @@
return vsecurity.InitDefaultBlessings(rt.principal, defaultBlessingName())
}
-func (rt *vrt) connectToAgent(fd int) (security.Principal, error) {
+func (rt *vrt) connectToAgent(fd int, client ipc.Client) (security.Principal, error) {
// Dup the fd, so we can create multiple runtimes.
syscall.ForkLock.Lock()
newfd, err := syscall.Dup(fd)
@@ -71,5 +72,5 @@
if err != nil {
return nil, err
}
- return agent.NewAgentPrincipal(rt.NewContext(), newfd)
+ return agent.NewAgentPrincipal(rt.NewContext(), newfd, client)
}
diff --git a/runtimes/google/rt/securityx.go b/runtimes/google/rt/securityx.go
index 0c8ca3f..040ca83 100644
--- a/runtimes/google/rt/securityx.go
+++ b/runtimes/google/rt/securityx.go
@@ -8,6 +8,7 @@
"syscall"
"v.io/core/veyron2/context"
+ "v.io/core/veyron2/ipc"
"v.io/core/veyron2/mgmt"
"v.io/core/veyron2/security"
@@ -17,8 +18,8 @@
"v.io/core/veyron/security/agent"
)
-func initSecurity(ctx *context.T, handle *exec.ChildHandle, credentials string) (security.Principal, error) {
- principal, err := setupPrincipal(ctx, handle, credentials)
+func initSecurity(ctx *context.T, handle *exec.ChildHandle, credentials string, client ipc.Client) (security.Principal, error) {
+ principal, err := setupPrincipal(ctx, handle, credentials, client)
if err != nil {
return nil, err
}
@@ -30,7 +31,7 @@
return principal, nil
}
-func setupPrincipal(ctx *context.T, handle *exec.ChildHandle, credentials string) (security.Principal, error) {
+func setupPrincipal(ctx *context.T, handle *exec.ChildHandle, credentials string, client ipc.Client) (security.Principal, error) {
var err error
var principal security.Principal
if principal, _ = ctx.Value(principalKey).(security.Principal); principal != nil {
@@ -39,7 +40,7 @@
if fd, err := agentFD(handle); err != nil {
return nil, err
} else if fd >= 0 {
- return agent.NewAgentPrincipal(ctx, fd)
+ return agent.NewAgentPrincipal(ctx, fd, client)
}
if len(credentials) > 0 {
// TODO(ataly, ashankar): If multiple runtimes are getting
diff --git a/runtimes/google/testing/mocks/ipc/simple_client.go b/runtimes/google/testing/mocks/ipc/simple_client.go
index 23a6b89..d90ccd7 100644
--- a/runtimes/google/testing/mocks/ipc/simple_client.go
+++ b/runtimes/google/testing/mocks/ipc/simple_client.go
@@ -3,13 +3,14 @@
import (
"errors"
"fmt"
- "reflect"
"sync"
"v.io/core/veyron2/context"
"v.io/core/veyron2/ipc"
"v.io/core/veyron2/security"
+ "v.io/core/veyron2/vdl/valconv"
"v.io/core/veyron2/vlog"
+ "v.io/core/veyron2/vom2"
)
// NewSimpleClient creates a new mocked ipc client where the given map of method name
@@ -51,8 +52,21 @@
return nil, errors.New(fmt.Sprintf("method %s not found", method))
}
+ // Copy the results so that they can be modified without effecting the original.
+ // This must be done via vom encode and decode rather than a direct deep copy because (among other reasons)
+ // reflect-based deep copy on vdl.Type objects will fail because of their private fields. This is not a problem with vom
+ // as it manually creates the type objects. It is also more realistic to use the same mechanism as the ultimate calls.
+ vomBytes, err := vom2.Encode(results)
+ if err != nil {
+ panic(fmt.Sprintf("Error copying value with vom (failed on encode): %v", err))
+ }
+ var copiedResults []interface{}
+ if err := vom2.Decode(vomBytes, &copiedResults); err != nil {
+ panic(fmt.Sprintf("Error copying value with vom (failed on decode): %v", err))
+ }
+
clientCall := mockCall{
- results: results,
+ results: copiedResults,
}
c.Lock()
@@ -92,10 +106,11 @@
}
for ax, res := range resultptrs {
if mc.results[ax] != nil {
- reflect.ValueOf(res).Elem().Set(reflect.ValueOf(mc.results[ax]))
+ if err := valconv.Convert(res, mc.results[ax]); err != nil {
+ panic(fmt.Sprintf("Error converting out argument %#v: %v", mc.results[ax], err))
+ }
}
}
-
return nil
}
diff --git a/runtimes/google/testing/mocks/ipc/simple_client_test.go b/runtimes/google/testing/mocks/ipc/simple_client_test.go
index 0cf23e6..a4bd4f0 100644
--- a/runtimes/google/testing/mocks/ipc/simple_client_test.go
+++ b/runtimes/google/testing/mocks/ipc/simple_client_test.go
@@ -35,7 +35,7 @@
return
}
var resultOne string
- var resultTwo int
+ var resultTwo int64
method1Call.Finish(&resultOne, &resultTwo)
if resultOne != "one" {
t.Errorf(`FinishCall: first result was "%v", want "one"`, resultOne)
@@ -73,21 +73,21 @@
}
type sampleStruct struct {
- name string
+ Name string
}
func TestStructResult(t *testing.T) {
client := NewSimpleClient(map[string][]interface{}{
"foo": []interface{}{
- sampleStruct{name: "bar"},
+ sampleStruct{Name: "bar"},
},
})
ctx := testContext()
call, _ := client.StartCall(ctx, "name/obj", "foo", []interface{}{})
var result sampleStruct
call.Finish(&result)
- if result.name != "bar" {
- t.Errorf(`FinishCall: second result was "%v", want "bar"`, result.name)
+ if result.Name != "bar" {
+ t.Errorf(`FinishCall: second result was "%v", want "bar"`, result.Name)
return
}
}
diff --git a/runtimes/google/testing/mocks/naming/namespace.go b/runtimes/google/testing/mocks/naming/namespace.go
index c46eca8..ad9a139 100644
--- a/runtimes/google/testing/mocks/naming/namespace.go
+++ b/runtimes/google/testing/mocks/naming/namespace.go
@@ -65,29 +65,9 @@
return nil
}
-func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
+func (ns *namespace) Resolve(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
defer vlog.LogCall()()
- if address, _ := naming.SplitAddressName(name); len(address) > 0 {
- return []string{name}, nil
- }
- ns.Lock()
- defer ns.Unlock()
- for prefix, servers := range ns.mounts {
- if strings.HasPrefix(name, prefix) {
- suffix := strings.TrimLeft(strings.TrimPrefix(name, prefix), "/")
- var ret []string
- for _, s := range servers {
- ret = append(ret, naming.JoinAddressName(s, suffix))
- }
- return ret, nil
- }
- }
- return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
-}
-
-func (ns *namespace) ResolveX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
- defer vlog.LogCall()()
- e, err := ns.ns.ResolveX(ctx, name, options.NoResolve{})
+ e, err := ns.ns.Resolve(ctx, name, options.NoResolve{})
if err != nil {
return e, err
}
@@ -111,14 +91,7 @@
return nil, verror.Make(naming.ErrNoSuchName, ctx, fmt.Sprintf("Resolve name %q not found in %v", name, ns.mounts))
}
-func (ns *namespace) ResolveToMountTableX(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
- defer vlog.LogCall()()
- // TODO(mattr): Implement this method for tests that might need it.
- panic("ResolveToMountTable not implemented")
- return nil, nil
-}
-
-func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) ([]string, error) {
+func (ns *namespace) ResolveToMountTable(ctx *context.T, name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
defer vlog.LogCall()()
// TODO(mattr): Implement this method for tests that might need it.
panic("ResolveToMountTable not implemented")
diff --git a/security/agent/agent_test.go b/security/agent/agent_test.go
index 7236034..bfc7ddd 100644
--- a/security/agent/agent_test.go
+++ b/security/agent/agent_test.go
@@ -11,6 +11,7 @@
"v.io/core/veyron/security/agent"
"v.io/core/veyron/security/agent/server"
+ "v.io/core/veyron2"
"v.io/core/veyron2/context"
"v.io/core/veyron2/rt"
"v.io/core/veyron2/security"
@@ -25,7 +26,7 @@
defer sock.Close()
var agentP security.Principal
- if agentP, err = agent.NewAgentPrincipal(ctx, int(sock.Fd())); err != nil {
+ if agentP, err = agent.NewAgentPrincipal(ctx, int(sock.Fd()), veyron2.GetClient(ctx)); err != nil {
t.Fatal(err)
}
return agentP
diff --git a/security/agent/client.go b/security/agent/client.go
index e5604d2..0c2912a 100644
--- a/security/agent/client.go
+++ b/security/agent/client.go
@@ -8,7 +8,6 @@
"os"
"v.io/core/veyron/lib/unixfd"
- "v.io/core/veyron2"
"v.io/core/veyron2/context"
"v.io/core/veyron2/ipc"
"v.io/core/veyron2/naming"
@@ -40,7 +39,7 @@
ctx, _ := vtrace.SetNewTrace(c.ctx)
// VCSecurityNone is safe here since we're using anonymous unix sockets.
- if call, err = c.client.StartCall(ctx, c.name, name, args, options.VCSecurityNone); err == nil {
+ if call, err = c.client.StartCall(ctx, c.name, name, args, options.VCSecurityNone, options.NoResolve{}); err == nil {
if ierr := call.Finish(results...); ierr != nil {
err = ierr
}
@@ -59,7 +58,7 @@
// 'fd' is the socket for connecting to the agent, typically obtained from
// os.GetEnv(agent.FdVarName).
// 'ctx' should not have a deadline, and should never be cancelled.
-func NewAgentPrincipal(ctx *context.T, fd int) (security.Principal, error) {
+func NewAgentPrincipal(ctx *context.T, fd int, insecureClient ipc.Client) (security.Principal, error) {
f := os.NewFile(uintptr(fd), "agent_client")
defer f.Close()
conn, err := net.FileConn(f)
@@ -73,7 +72,7 @@
return nil, err
}
caller := caller{
- client: veyron2.GetClient(ctx),
+ client: insecureClient,
name: naming.JoinAddressName(naming.FormatEndpoint(addr.Network(), addr.String()), ""),
ctx: ctx,
}
diff --git a/security/agent/keymgr/keymgr_test.go b/security/agent/keymgr/keymgr_test.go
index f9d18b7..422767a 100644
--- a/security/agent/keymgr/keymgr_test.go
+++ b/security/agent/keymgr/keymgr_test.go
@@ -12,6 +12,7 @@
"v.io/core/veyron/security/agent"
"v.io/core/veyron/security/agent/server"
+ "v.io/core/veyron2"
"v.io/core/veyron2/context"
"v.io/core/veyron2/rt"
"v.io/core/veyron2/security"
@@ -70,7 +71,7 @@
return nil, err
}
- return agent.NewAgentPrincipal(ctx, fd)
+ return agent.NewAgentPrincipal(ctx, fd, veyron2.GetClient(ctx))
}
func TestSigning(t *testing.T) {
diff --git a/security/agent/pingpong/wire.vdl.go b/security/agent/pingpong/wire.vdl.go
index 4344728..2f1915b 100644
--- a/security/agent/pingpong/wire.vdl.go
+++ b/security/agent/pingpong/wire.vdl.go
@@ -8,15 +8,8 @@
__veyron2 "v.io/core/veyron2"
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
- __vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// PingPongClientMethods is the client interface
// containing PingPong methods.
//
@@ -65,17 +58,6 @@
return
}
-func (c implPingPongClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// PingPongServerMethods is the interface a server writer
// implements for PingPong.
//
@@ -95,8 +77,6 @@
PingPongServerStubMethods
// Describe the PingPong interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// PingPongServer returns a server stub for PingPong.
@@ -154,22 +134,3 @@
},
},
}
-
-func (s implPingPongServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Ping"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "message", Type: 3},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 3},
- {Name: "", Type: 65},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
- return result, nil
-}
diff --git a/security/agent/server/wire.vdl.go b/security/agent/server/wire.vdl.go
index 1fa94ac..ddd4eab 100644
--- a/security/agent/server/wire.vdl.go
+++ b/security/agent/server/wire.vdl.go
@@ -11,14 +11,8 @@
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
__vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// AgentClientMethods is the client interface
// containing Agent methods.
type AgentClientMethods interface {
@@ -257,17 +251,6 @@
return
}
-func (c implAgentClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// AgentServerMethods is the interface a server writer
// implements for Agent.
type AgentServerMethods interface {
@@ -301,8 +284,6 @@
AgentServerStubMethods
// Describe the Agent interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// AgentServer returns a server stub for Agent.
@@ -574,188 +555,3 @@
},
},
}
-
-func (s implAgentServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["AddToRoots"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "blessing", Type: 74},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 75},
- },
- }
- result.Methods["Bless"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "key", Type: 66},
- {Name: "wit", Type: 74},
- {Name: "extension", Type: 3},
- {Name: "caveat", Type: 67},
- {Name: "additionalCaveats", Type: 68},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 74},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessSelf"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "name", Type: 3},
- {Name: "caveats", Type: 68},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 74},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingRootsAdd"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "root", Type: 66},
- {Name: "pattern", Type: 77},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingRootsDebugString"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 3},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingRootsRecognized"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "root", Type: 66},
- {Name: "blessing", Type: 3},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingStoreDebugString"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 3},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingStoreDefault"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 74},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingStoreForPeer"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "peerBlessings", Type: 61},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 74},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingStorePeerBlessings"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 80},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingStoreSet"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "blessings", Type: 74},
- {Name: "forPeers", Type: 77},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 74},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingStoreSetDefault"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "blessings", Type: 74},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingsByName"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "name", Type: 77},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 78},
- {Name: "", Type: 75},
- },
- }
- result.Methods["BlessingsInfo"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "blessings", Type: 74},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 79},
- {Name: "", Type: 75},
- },
- }
- result.Methods["MintDischarge"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "tp", Type: 76},
- {Name: "caveat", Type: 67},
- {Name: "additionalCaveats", Type: 68},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 76},
- {Name: "", Type: 75},
- },
- }
- result.Methods["PublicKey"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 66},
- {Name: "", Type: 75},
- },
- }
- result.Methods["Sign"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "message", Type: 66},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 70},
- {Name: "", Type: 75},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x42, Name: "ValidatorVOM"},
- },
- "v.io/core/veyron2/security.Caveat", []string(nil)},
- __wiretype.SliceType{Elem: 0x43, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.Hash", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x42, Name: "Purpose"},
- __wiretype.FieldType{Type: 0x45, Name: "Hash"},
- __wiretype.FieldType{Type: 0x42, Name: "R"},
- __wiretype.FieldType{Type: 0x42, Name: "S"},
- },
- "v.io/core/veyron2/security.Signature", []string(nil)},
- __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x3, Name: "Extension"},
- __wiretype.FieldType{Type: 0x42, Name: "PublicKey"},
- __wiretype.FieldType{Type: 0x44, Name: "Caveats"},
- __wiretype.FieldType{Type: 0x46, Name: "Signature"},
- },
- "v.io/core/veyron2/security.Certificate", []string(nil)},
- __wiretype.SliceType{Elem: 0x47, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x48, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
- },
- "v.io/core/veyron2/security.WireBlessings", []string(nil)},
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.BlessingPattern", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x4a, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x3, Elem: 0x44, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x4d, Elem: 0x4a, Name: "", Tags: []string(nil)}}
-
- return result, nil
-}
diff --git a/services/identity/identity.vdl.go b/services/identity/identity.vdl.go
index c369461..97d9997 100644
--- a/services/identity/identity.vdl.go
+++ b/services/identity/identity.vdl.go
@@ -11,15 +11,8 @@
__veyron2 "v.io/core/veyron2"
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
- __vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// OAuthBlesserClientMethods is the client interface
// containing OAuthBlesser methods.
//
@@ -82,17 +75,6 @@
return
}
-func (c implOAuthBlesserClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// OAuthBlesserServerMethods is the interface a server writer
// implements for OAuthBlesser.
//
@@ -126,8 +108,6 @@
OAuthBlesserServerStubMethods
// Describe the OAuthBlesser interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// OAuthBlesserServer returns a server stub for OAuthBlesser.
@@ -188,52 +168,6 @@
},
}
-func (s implOAuthBlesserServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["BlessUsingAccessToken"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "token", Type: 3},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "blessing", Type: 74},
- {Name: "email", Type: 3},
- {Name: "err", Type: 75},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x42, Name: "ValidatorVOM"},
- },
- "v.io/core/veyron2/security.Caveat", []string(nil)},
- __wiretype.SliceType{Elem: 0x43, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.Hash", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x42, Name: "Purpose"},
- __wiretype.FieldType{Type: 0x45, Name: "Hash"},
- __wiretype.FieldType{Type: 0x42, Name: "R"},
- __wiretype.FieldType{Type: 0x42, Name: "S"},
- },
- "v.io/core/veyron2/security.Signature", []string(nil)},
- __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x3, Name: "Extension"},
- __wiretype.FieldType{Type: 0x42, Name: "PublicKey"},
- __wiretype.FieldType{Type: 0x44, Name: "Caveats"},
- __wiretype.FieldType{Type: 0x46, Name: "Signature"},
- },
- "v.io/core/veyron2/security.Certificate", []string(nil)},
- __wiretype.SliceType{Elem: 0x47, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x48, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
- },
- "v.io/core/veyron2/security.WireBlessings", []string(nil)},
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
- return result, nil
-}
-
// MacaroonBlesserClientMethods is the client interface
// containing MacaroonBlesser methods.
//
@@ -284,17 +218,6 @@
return
}
-func (c implMacaroonBlesserClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// MacaroonBlesserServerMethods is the interface a server writer
// implements for MacaroonBlesser.
//
@@ -316,8 +239,6 @@
MacaroonBlesserServerStubMethods
// Describe the MacaroonBlesser interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// MacaroonBlesserServer returns a server stub for MacaroonBlesser.
@@ -376,48 +297,3 @@
},
},
}
-
-func (s implMacaroonBlesserServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Bless"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "macaroon", Type: 3},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "blessing", Type: 74},
- {Name: "err", Type: 75},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x42, Name: "ValidatorVOM"},
- },
- "v.io/core/veyron2/security.Caveat", []string(nil)},
- __wiretype.SliceType{Elem: 0x43, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.Hash", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x42, Name: "Purpose"},
- __wiretype.FieldType{Type: 0x45, Name: "Hash"},
- __wiretype.FieldType{Type: 0x42, Name: "R"},
- __wiretype.FieldType{Type: 0x42, Name: "S"},
- },
- "v.io/core/veyron2/security.Signature", []string(nil)},
- __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x3, Name: "Extension"},
- __wiretype.FieldType{Type: 0x42, Name: "PublicKey"},
- __wiretype.FieldType{Type: 0x44, Name: "Caveats"},
- __wiretype.FieldType{Type: 0x46, Name: "Signature"},
- },
- "v.io/core/veyron2/security.Certificate", []string(nil)},
- __wiretype.SliceType{Elem: 0x47, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x48, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x49, Name: "CertificateChains"},
- },
- "v.io/core/veyron2/security.WireBlessings", []string(nil)},
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
- return result, nil
-}
diff --git a/services/identity/server/identityd.go b/services/identity/server/identityd.go
index 5eb3938..c1b2c99 100644
--- a/services/identity/server/identityd.go
+++ b/services/identity/server/identityd.go
@@ -154,24 +154,28 @@
if err != nil {
return nil, nil, fmt.Errorf("failed to create new ipc.Server: %v", err)
}
- eps, err := server.Listen(*listenSpec)
- if err != nil {
- return nil, nil, fmt.Errorf("server.Listen(%v) failed: %v", *listenSpec, err)
- }
- ep := eps[0]
- dispatcher := newDispatcher(macaroonKey, oauthBlesserParams(s.oauthBlesserParams, s.revocationManager, ep))
principal := veyron2.GetPrincipal(ctx)
- objectname := naming.Join("identity", fmt.Sprintf("%v", principal.BlessingStore().Default()))
- if err := server.ServeDispatcher(objectname, dispatcher); err != nil {
+ objectAddr := naming.Join("identity", fmt.Sprintf("%v", principal.BlessingStore().Default()))
+ var rootedObjectAddr string
+ if eps, err := server.Listen(*listenSpec); err != nil {
+ defer server.Stop()
+ return nil, nil, fmt.Errorf("server.Listen(%v) failed: %v", *listenSpec, err)
+ } else if nsroots := veyron2.GetNamespace(ctx).Roots(); len(nsroots) >= 1 {
+ rootedObjectAddr = naming.Join(nsroots[0], objectAddr)
+ } else {
+ rootedObjectAddr = eps[0].Name()
+ }
+ dispatcher := newDispatcher(macaroonKey, oauthBlesserParams(s.oauthBlesserParams, rootedObjectAddr))
+ if err := server.ServeDispatcher(objectAddr, dispatcher); err != nil {
return nil, nil, fmt.Errorf("failed to start Veyron services: %v", err)
}
published, _ := server.Published()
if len(published) == 0 {
- // No addresses published, publish the endpoint instead (which may not be usable everywhere, but oh-well).
- published = append(published, ep.String())
+ // No addresses successfully published, return what we expect to be published at.
+ published = []string{rootedObjectAddr}
}
- vlog.Infof("Blessing and discharger services enabled at %v", published)
+ vlog.Infof("Blessing and discharger services will be published at %v", rootedObjectAddr)
return server, published, nil
}
@@ -199,8 +203,8 @@
return nil, nil, verror.Make(verror.NoExist, nil, suffix)
}
-func oauthBlesserParams(inputParams blesser.OAuthBlesserParams, revocationManager revocation.RevocationManager, ep naming.Endpoint) blesser.OAuthBlesserParams {
- inputParams.DischargerLocation = naming.JoinAddressName(ep.String(), dischargerService)
+func oauthBlesserParams(inputParams blesser.OAuthBlesserParams, servername string) blesser.OAuthBlesserParams {
+ inputParams.DischargerLocation = naming.Join(servername, dischargerService)
return inputParams
}
diff --git a/services/mgmt/application/impl/acl_test.go b/services/mgmt/application/impl/acl_test.go
index c603e34..1f682a0 100644
--- a/services/mgmt/application/impl/acl_test.go
+++ b/services/mgmt/application/impl/acl_test.go
@@ -36,8 +36,6 @@
var globalCtx *context.T
var globalCancel context.CancelFunc
-// This is also a modules world.
-// Insert necessary code here to be a modules test.
func init() {
// TODO(rjkroege): Remove when vom2 is ready.
vdlutil.Register(&naming.VDLMountedServer{})
diff --git a/services/mgmt/application/impl/service.go b/services/mgmt/application/impl/service.go
index b0c6cc4..8ad14cd 100644
--- a/services/mgmt/application/impl/service.go
+++ b/services/mgmt/application/impl/service.go
@@ -265,7 +265,7 @@
return acl, etag, nil
}
-// setACL wites a TaggedACLMap into the Memstore at the provided path.
+// setACL writes a TaggedACLMap into the Memstore at the provided path.
// where path is expected to have already been cleaned by naming.Join.
func setACL(store *fs.Memstore, path string, acl access.TaggedACLMap, etag string) error {
_, oetag, err := getACL(store, path)
diff --git a/services/mgmt/binary/impl/fs_utils.go b/services/mgmt/binary/impl/fs_utils.go
index 1147d21..9468fb6 100644
--- a/services/mgmt/binary/impl/fs_utils.go
+++ b/services/mgmt/binary/impl/fs_utils.go
@@ -26,10 +26,10 @@
func checksumExists(path string) error {
switch _, err := os.Stat(path); {
case os.IsNotExist(err):
- return verror.Make(errInvalidPart, nil, path)
+ return verror.Make(ErrInvalidPart, nil, path)
case err != nil:
vlog.Errorf("Stat(%v) failed: %v", path, err)
- return verror.Make(errOperationFailed, nil, path)
+ return verror.Make(ErrOperationFailed, nil, path)
}
checksumFile := filepath.Join(path, checksum)
_, err := os.Stat(checksumFile)
@@ -38,7 +38,7 @@
return verror.Make(verror.NoExist, nil, path)
case err != nil:
vlog.Errorf("Stat(%v) failed: %v", checksumFile, err)
- return verror.Make(errOperationFailed, nil, path)
+ return verror.Make(ErrOperationFailed, nil, path)
default:
return nil
}
@@ -58,7 +58,7 @@
infos, err := ioutil.ReadDir(path)
if err != nil {
vlog.Errorf("ReadDir(%v) failed: %v", path, err)
- return []string{}, verror.Make(errOperationFailed, nil, path)
+ return []string{}, verror.Make(ErrOperationFailed, nil, path)
}
nDirs := 0
for _, info := range infos {
@@ -73,10 +73,10 @@
idx, err := strconv.Atoi(partName)
if err != nil {
vlog.Errorf("Atoi(%v) failed: %v", partName, err)
- return []string{}, verror.Make(errOperationFailed, nil, path)
+ return []string{}, verror.Make(ErrOperationFailed, nil, path)
}
if idx < 0 || idx >= len(infos) || result[idx] != "" {
- return []string{}, verror.Make(errOperationFailed, nil, path)
+ return []string{}, verror.Make(ErrOperationFailed, nil, path)
}
result[idx] = filepath.Join(path, partName)
} else {
@@ -84,7 +84,7 @@
continue
}
// The only entries should correspond to the part dirs.
- return []string{}, verror.Make(errOperationFailed, nil, path)
+ return []string{}, verror.Make(ErrOperationFailed, nil, path)
}
}
return result, nil
diff --git a/services/mgmt/binary/impl/http.go b/services/mgmt/binary/impl/http.go
index 23363c1..1b34812 100644
--- a/services/mgmt/binary/impl/http.go
+++ b/services/mgmt/binary/impl/http.go
@@ -43,7 +43,7 @@
var err error
if partFiles[i], err = os.Open(dataPath); err != nil {
vlog.Errorf("Open(%v) failed: %v", dataPath, err)
- return nil, verror.Make(errOperationFailed, nil, dataPath)
+ return nil, verror.Make(ErrOperationFailed, nil, dataPath)
}
}
return multipart.NewFile(name, partFiles)
diff --git a/services/mgmt/binary/impl/http_test.go b/services/mgmt/binary/impl/http_test.go
index 601ddd3..db4b0a5 100644
--- a/services/mgmt/binary/impl/http_test.go
+++ b/services/mgmt/binary/impl/http_test.go
@@ -1,4 +1,4 @@
-package impl
+package impl_test
import (
"bytes"
@@ -11,6 +11,7 @@
"v.io/core/veyron2/services/mgmt/repository"
"v.io/core/veyron/lib/testutil"
+ "v.io/core/veyron/services/mgmt/binary/impl"
)
// TestHTTP checks that HTTP download works.
@@ -24,7 +25,7 @@
data := make([][]byte, length)
for i := 0; i < length; i++ {
// Random size, but at least 1 (avoid empty parts).
- size := testutil.Rand.Intn(1000*bufferLength) + 1
+ size := testutil.Rand.Intn(1000*impl.BufferLength) + 1
data[i] = testutil.RandomBytes(size)
}
mediaInfo := repository.MediaInfo{Type: "application/octet-stream"}
@@ -32,7 +33,7 @@
t.Fatalf("Create() failed: %v", err)
}
for i := 0; i < length; i++ {
- if streamErr, err := invokeUpload(t, binary, data[i], int32(i)); streamErr != nil || err != nil {
+ if streamErr, err := invokeUpload(t, gctx, binary, data[i], int32(i)); streamErr != nil || err != nil {
t.FailNow()
}
}
diff --git a/services/mgmt/binary/impl/impl_test.go b/services/mgmt/binary/impl/impl_test.go
index 5b52ad3..09fb3a4 100644
--- a/services/mgmt/binary/impl/impl_test.go
+++ b/services/mgmt/binary/impl/impl_test.go
@@ -1,19 +1,15 @@
-package impl
+package impl_test
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
- "io/ioutil"
"net"
"net/http"
- "os"
- "path/filepath"
"reflect"
"testing"
- "v.io/core/veyron2"
"v.io/core/veyron2/context"
"v.io/core/veyron2/naming"
"v.io/core/veyron2/rt"
@@ -22,7 +18,9 @@
"v.io/core/veyron2/vlog"
"v.io/core/veyron/lib/testutil"
- "v.io/core/veyron/profiles"
+ _ "v.io/core/veyron/profiles/static"
+ "v.io/core/veyron/services/mgmt/binary/impl"
+ mgmttest "v.io/core/veyron/services/mgmt/lib/testutil"
)
const (
@@ -41,121 +39,41 @@
gctx = runtime.NewContext()
}
-// invokeUpload invokes the Upload RPC using the given client binary
-// <binary> and streams the given binary <binary> to it.
-func invokeUpload(t *testing.T, binary repository.BinaryClientMethods, data []byte, part int32) (error, error) {
- stream, err := binary.Upload(gctx, part)
- if err != nil {
- t.Errorf("Upload() failed: %v", err)
- return nil, err
- }
- sender := stream.SendStream()
- if streamErr := sender.Send(data); streamErr != nil {
- err := stream.Finish()
- if err != nil {
- t.Logf("Finish() failed: %v", err)
- }
- t.Logf("Send() failed: %v", streamErr)
- return streamErr, err
- }
- if streamErr := sender.Close(); streamErr != nil {
- err := stream.Finish()
- if err != nil {
- t.Logf("Finish() failed: %v", err)
- }
- t.Logf("Close() failed: %v", streamErr)
- return streamErr, err
- }
- if err := stream.Finish(); err != nil {
- t.Logf("Finish() failed: %v", err)
- return nil, err
- }
- return nil, nil
-}
-
-// invokeDownload invokes the Download RPC using the given client binary
-// <binary> and streams binary from to it.
-func invokeDownload(t *testing.T, binary repository.BinaryClientMethods, part int32) ([]byte, error, error) {
- stream, err := binary.Download(gctx, part)
- if err != nil {
- t.Errorf("Download() failed: %v", err)
- return nil, nil, err
- }
- output := make([]byte, 0)
- rStream := stream.RecvStream()
- for rStream.Advance() {
- bytes := rStream.Value()
- output = append(output, bytes...)
- }
-
- if streamErr := rStream.Err(); streamErr != nil {
- err := stream.Finish()
- if err != nil {
- t.Logf("Finish() failed: %v", err)
- }
- t.Logf("Advance() failed with: %v", streamErr)
- return nil, streamErr, err
- }
-
- if err := stream.Finish(); err != nil {
- t.Logf("Finish() failed: %v", err)
- return nil, nil, err
- }
- return output, nil, nil
-}
-
// startServer starts the binary repository server.
func startServer(t *testing.T, depth int) (repository.BinaryClientMethods, string, string, func()) {
// Setup the root of the binary repository.
- rootDir, err := ioutil.TempDir("", veyronPrefix)
- if err != nil {
- t.Fatalf("TempDir() failed: %v", err)
- }
- path, perm := filepath.Join(rootDir, VersionFile), os.FileMode(0600)
- if err := ioutil.WriteFile(path, []byte(Version), perm); err != nil {
- vlog.Fatalf("WriteFile(%v, %v, %v) failed: %v", path, Version, perm, err)
- }
+ rootDir, cleanup := mgmttest.SetupRootDir(t, "bindir")
+ prepDirectory(t, rootDir)
+
// Setup and start the binary repository server.
- server, err := veyron2.NewServer(gctx)
- if err != nil {
- t.Fatalf("NewServer() failed: %v", err)
- }
+ server, endpoint := mgmttest.NewServer(gctx)
+
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
- state, err := NewState(rootDir, listener.Addr().String(), depth)
+ state, err := impl.NewState(rootDir, listener.Addr().String(), depth)
if err != nil {
t.Fatalf("NewState(%v, %v) failed: %v", rootDir, listener.Addr().String(), depth, err)
}
go func() {
- if err := http.Serve(listener, http.FileServer(NewHTTPRoot(state))); err != nil {
+ if err := http.Serve(listener, http.FileServer(impl.NewHTTPRoot(state))); err != nil {
vlog.Fatalf("Serve() failed: %v", err)
}
}()
- dispatcher := NewDispatcher(state, nil)
- endpoints, err := server.Listen(profiles.LocalListenSpec)
- if err != nil {
- t.Fatalf("Listen(%s) failed: %v", profiles.LocalListenSpec, err)
- }
- endpoint := endpoints[0]
+ dispatcher := impl.NewDispatcher(state, nil)
dontPublishName := ""
if err := server.ServeDispatcher(dontPublishName, dispatcher); err != nil {
t.Fatalf("Serve(%q) failed: %v", dontPublishName, err)
}
- name := naming.JoinAddressName(endpoint.String(), "test")
+ name := naming.JoinAddressName(endpoint, "test")
binary := repository.BinaryClient(name)
- return binary, endpoint.String(), fmt.Sprintf("http://%s/test", listener.Addr()), func() {
+ return binary, endpoint, fmt.Sprintf("http://%s/test", listener.Addr()), func() {
// Shutdown the binary repository server.
if err := server.Stop(); err != nil {
t.Fatalf("Stop() failed: %v", err)
}
- if err := os.RemoveAll(path); err != nil {
- t.Fatalf("RemoveAll(%v) failed: %v", path, err)
- }
- if err := os.RemoveAll(rootDir); err != nil {
- t.Fatalf("RemoveAll(%v) failed: %v", rootDir, err)
- }
+ cleanup()
}
}
@@ -166,14 +84,13 @@
for i := 0; i < md5.Size; i++ {
binary, ep, _, cleanup := startServer(t, i)
defer cleanup()
- // Create up to 4MB of random bytes.
- size := testutil.Rand.Intn(1000 * bufferLength)
- data := testutil.RandomBytes(size)
+ data := testData()
+
// Test the binary repository interface.
if err := binary.Create(gctx, 1, repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
t.Fatalf("Create() failed: %v", err)
}
- if streamErr, err := invokeUpload(t, binary, data, 0); streamErr != nil || err != nil {
+ if streamErr, err := invokeUpload(t, gctx, binary, data, 0); streamErr != nil || err != nil {
t.FailNow()
}
parts, _, err := binary.Stat(gctx)
@@ -189,7 +106,7 @@
if expected, got := len(data), int(parts[0].Size); expected != got {
t.Fatalf("Unexpected size: expected %v, got %v", expected, got)
}
- output, streamErr, err := invokeDownload(t, binary, 0)
+ output, streamErr, err := invokeDownload(t, gctx, binary, 0)
if streamErr != nil || err != nil {
t.FailNow()
}
@@ -219,15 +136,14 @@
// Create <length> chunks of up to 4MB of random bytes.
data := make([][]byte, length)
for i := 0; i < length; i++ {
- size := testutil.Rand.Intn(1000 * bufferLength)
- data[i] = testutil.RandomBytes(size)
+ data[i] = testData()
}
// Test the binary repository interface.
if err := binary.Create(gctx, int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
t.Fatalf("Create() failed: %v", err)
}
for i := 0; i < length; i++ {
- if streamErr, err := invokeUpload(t, binary, data[i], int32(i)); streamErr != nil || err != nil {
+ if streamErr, err := invokeUpload(t, gctx, binary, data[i], int32(i)); streamErr != nil || err != nil {
t.FailNow()
}
}
@@ -237,7 +153,7 @@
}
for i := 0; i < length; i++ {
hpart := md5.New()
- output, streamErr, err := invokeDownload(t, binary, int32(i))
+ output, streamErr, err := invokeDownload(t, gctx, binary, int32(i))
if streamErr != nil || err != nil {
t.FailNow()
}
@@ -269,8 +185,7 @@
// Create <length> chunks of up to 4MB of random bytes.
data := make([][]byte, length)
for i := 0; i < length; i++ {
- size := testutil.Rand.Intn(1000 * bufferLength)
- data[i] = testutil.RandomBytes(size)
+ data[i] = testData()
}
if err := binary.Create(gctx, int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
t.Fatalf("Create() failed: %v", err)
@@ -284,15 +199,15 @@
}
finished := true
for _, part := range parts {
- finished = finished && (part != MissingPart)
+ finished = finished && (part != impl.MissingPart)
}
if finished {
break
}
for i := 0; i < length; i++ {
fail := testutil.Rand.Intn(2)
- if parts[i] == MissingPart && fail != 0 {
- if streamErr, err := invokeUpload(t, binary, data[i], int32(i)); streamErr != nil || err != nil {
+ if parts[i] == impl.MissingPart && fail != 0 {
+ if streamErr, err := invokeUpload(t, gctx, binary, data[i], int32(i)); streamErr != nil || err != nil {
t.FailNow()
}
}
@@ -311,9 +226,8 @@
const length = 2
data := make([][]byte, length)
for i := 0; i < length; i++ {
- size := testutil.Rand.Intn(1000 * bufferLength)
- data[i] = make([]byte, size)
- for j := 0; j < size; j++ {
+ data[i] = testData()
+ for j := 0; j < len(data[i]); j++ {
data[i][j] = byte(testutil.Rand.Int())
}
}
@@ -325,36 +239,36 @@
} else if want := verror.Exist.ID; !verror.Is(err, want) {
t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
}
- if streamErr, err := invokeUpload(t, binary, data[0], 0); streamErr != nil || err != nil {
+ if streamErr, err := invokeUpload(t, gctx, binary, data[0], 0); streamErr != nil || err != nil {
t.Fatalf("Upload() failed: %v", err)
}
- if _, err := invokeUpload(t, binary, data[0], 0); err == nil {
+ if _, err := invokeUpload(t, gctx, binary, data[0], 0); err == nil {
t.Fatalf("Upload() did not fail when it should have")
} else if want := verror.Exist.ID; !verror.Is(err, want) {
t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
}
- if _, _, err := invokeDownload(t, binary, 1); err == nil {
+ if _, _, err := invokeDownload(t, gctx, binary, 1); err == nil {
t.Fatalf("Download() did not fail when it should have")
} else if want := verror.NoExist.ID; !verror.Is(err, want) {
t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
}
- if streamErr, err := invokeUpload(t, binary, data[1], 1); streamErr != nil || err != nil {
+ if streamErr, err := invokeUpload(t, gctx, binary, data[1], 1); streamErr != nil || err != nil {
t.Fatalf("Upload() failed: %v", err)
}
- if _, streamErr, err := invokeDownload(t, binary, 0); streamErr != nil || err != nil {
+ if _, streamErr, err := invokeDownload(t, gctx, binary, 0); streamErr != nil || err != nil {
t.Fatalf("Download() failed: %v", err)
}
// Upload/Download on a part number that's outside the range set forth in
// Create should fail.
for _, part := range []int32{-1, length} {
- if _, err := invokeUpload(t, binary, []byte("dummy"), part); err == nil {
+ if _, err := invokeUpload(t, gctx, binary, []byte("dummy"), part); err == nil {
t.Fatalf("Upload() did not fail when it should have")
- } else if want := errInvalidPart.ID; !verror.Is(err, want) {
+ } else if want := impl.ErrInvalidPart.ID; !verror.Is(err, want) {
t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
}
- if _, _, err := invokeDownload(t, binary, part); err == nil {
+ if _, _, err := invokeDownload(t, gctx, binary, part); err == nil {
t.Fatalf("Download() did not fail when it should have")
- } else if want := errInvalidPart.ID; !verror.Is(err, want) {
+ } else if want := impl.ErrInvalidPart.ID; !verror.Is(err, want) {
t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
}
}
@@ -371,9 +285,7 @@
func TestGlob(t *testing.T) {
_, ep, _, cleanup := startServer(t, 2)
defer cleanup()
- // Create up to 4MB of random bytes.
- size := testutil.Rand.Intn(1000 * bufferLength)
- data := testutil.RandomBytes(size)
+ data := testData()
objects := []string{"foo", "bar", "hello world", "a/b/c"}
for _, obj := range objects {
@@ -383,7 +295,7 @@
if err := binary.Create(gctx, 1, repository.MediaInfo{Type: "application/octet-stream"}); err != nil {
t.Fatalf("Create() failed: %v", err)
}
- if streamErr, err := invokeUpload(t, binary, data, 0); streamErr != nil || err != nil {
+ if streamErr, err := invokeUpload(t, gctx, binary, data, 0); streamErr != nil || err != nil {
t.FailNow()
}
}
diff --git a/services/mgmt/binary/impl/service.go b/services/mgmt/binary/impl/service.go
index 5ec3fc5..0ce7bbe 100644
--- a/services/mgmt/binary/impl/service.go
+++ b/services/mgmt/binary/impl/service.go
@@ -53,10 +53,10 @@
const pkgPath = "v.io/core/veyron/services/mgmt/binary/impl"
var (
- errInProgress = verror.Register(pkgPath+".errInProgress", verror.NoRetry, "{1:}{2:} identical upload already in progress{:_}")
- errInvalidParts = verror.Register(pkgPath+".errInvalidParts", verror.NoRetry, "{1:}{2:} invalid number of binary parts{:_}")
- errInvalidPart = verror.Register(pkgPath+".errInvalidPart", verror.NoRetry, "{1:}{2:} invalid binary part number{:_}")
- errOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
+ ErrInProgress = verror.Register(pkgPath+".errInProgress", verror.NoRetry, "{1:}{2:} identical upload already in progress{:_}")
+ ErrInvalidParts = verror.Register(pkgPath+".errInvalidParts", verror.NoRetry, "{1:}{2:} invalid number of binary parts{:_}")
+ ErrInvalidPart = verror.Register(pkgPath+".errInvalidPart", verror.NoRetry, "{1:}{2:} invalid binary part number{:_}")
+ ErrOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
)
// TODO(jsimsa): When VDL supports composite literal constants, remove
@@ -75,38 +75,38 @@
}
}
-const bufferLength = 4096
+const BufferLength = 4096
func (i *binaryService) Create(context ipc.ServerContext, nparts int32, mediaInfo repository.MediaInfo) error {
vlog.Infof("%v.Create(%v, %v)", i.suffix, nparts, mediaInfo)
if nparts < 1 {
- return verror.Make(errInvalidParts, context.Context())
+ return verror.Make(ErrInvalidParts, context.Context())
}
parent, perm := filepath.Dir(i.path), os.FileMode(0700)
if err := os.MkdirAll(parent, perm); err != nil {
vlog.Errorf("MkdirAll(%v, %v) failed: %v", parent, perm, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
prefix := "creating-"
tmpDir, err := ioutil.TempDir(parent, prefix)
if err != nil {
vlog.Errorf("TempDir(%v, %v) failed: %v", parent, prefix, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
nameFile := filepath.Join(tmpDir, "name")
if err := ioutil.WriteFile(nameFile, []byte(i.suffix), os.FileMode(0600)); err != nil {
vlog.Errorf("WriteFile(%q) failed: %v", nameFile)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
infoFile := filepath.Join(tmpDir, "mediainfo")
jInfo, err := json.Marshal(mediaInfo)
if err != nil {
vlog.Errorf("json.Marshal(%v) failed: %v", mediaInfo, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
if err := ioutil.WriteFile(infoFile, jInfo, os.FileMode(0600)); err != nil {
vlog.Errorf("WriteFile(%q) failed: %v", infoFile, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
for j := 0; j < int(nparts); j++ {
partPath, partPerm := generatePartPath(tmpDir, j), os.FileMode(0700)
@@ -115,7 +115,7 @@
if err := os.RemoveAll(tmpDir); err != nil {
vlog.Errorf("RemoveAll(%v) failed: %v", tmpDir, err)
}
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
}
// Use os.Rename() to atomically create the binary directory
@@ -130,7 +130,7 @@
return verror.Make(verror.Exist, context.Context(), i.path)
}
vlog.Errorf("Rename(%v, %v) failed: %v", tmpDir, i.path, err)
- return verror.Make(errOperationFailed, context.Context(), i.path)
+ return verror.Make(ErrOperationFailed, context.Context(), i.path)
}
return nil
}
@@ -142,18 +142,18 @@
return verror.Make(verror.NoExist, context.Context(), i.path)
}
vlog.Errorf("Stat(%v) failed: %v", i.path, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
// Use os.Rename() to atomically remove the binary directory
// structure.
path := filepath.Join(filepath.Dir(i.path), "removing-"+filepath.Base(i.path))
if err := os.Rename(i.path, path); err != nil {
vlog.Errorf("Rename(%v, %v) failed: %v", i.path, path, err)
- return verror.Make(errOperationFailed, context.Context(), i.path)
+ return verror.Make(ErrOperationFailed, context.Context(), i.path)
}
if err := os.RemoveAll(path); err != nil {
vlog.Errorf("Remove(%v) failed: %v", path, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
for {
// Remove the binary and all directories on the path back to the
@@ -167,7 +167,7 @@
break
}
vlog.Errorf("Remove(%v) failed: %v", path, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
}
return nil
@@ -183,23 +183,23 @@
file, err := os.Open(dataPath)
if err != nil {
vlog.Errorf("Open(%v) failed: %v", dataPath, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
defer file.Close()
- buffer := make([]byte, bufferLength)
+ buffer := make([]byte, BufferLength)
sender := context.SendStream()
for {
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
vlog.Errorf("Read() failed: %v", err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
if n == 0 {
break
}
if err := sender.Send(buffer[:n]); err != nil {
vlog.Errorf("Send() failed: %v", err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
}
return nil
@@ -228,7 +228,7 @@
continue
}
vlog.Errorf("ReadFile(%v) failed: %v", checksumFile, err)
- return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
}
dataFile := filepath.Join(part, data)
fi, err := os.Stat(dataFile)
@@ -238,7 +238,7 @@
continue
}
vlog.Errorf("Stat(%v) failed: %v", dataFile, err)
- return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
}
result = append(result, binary.PartInfo{Checksum: string(bytes), Size: fi.Size()})
}
@@ -246,12 +246,12 @@
jInfo, err := ioutil.ReadFile(infoFile)
if err != nil {
vlog.Errorf("ReadFile(%q) failed: %v", infoFile)
- return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
}
var mediaInfo repository.MediaInfo
if err := json.Unmarshal(jInfo, &mediaInfo); err != nil {
vlog.Errorf("json.Unmarshal(%v) failed: %v", jInfo, err)
- return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context.Context())
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(ErrOperationFailed, context.Context())
}
return result, mediaInfo, nil
}
@@ -270,17 +270,17 @@
lockFile, err := os.OpenFile(lockPath, flags, perm)
if err != nil {
if os.IsExist(err) {
- return verror.Make(errInProgress, context.Context(), path)
+ return verror.Make(ErrInProgress, context.Context(), path)
}
vlog.Errorf("OpenFile(%v, %v, %v) failed: %v", lockPath, flags, suffix, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
defer os.Remove(lockFile.Name())
defer lockFile.Close()
file, err := ioutil.TempFile(path, suffix)
if err != nil {
vlog.Errorf("TempFile(%v, %v) failed: %v", path, suffix, err)
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
defer file.Close()
h := md5.New()
@@ -292,7 +292,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
h.Write(bytes)
}
@@ -302,7 +302,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
hash := hex.EncodeToString(h.Sum(nil))
@@ -312,7 +312,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
dataFile := filepath.Join(path, data)
if err := os.Rename(file.Name(), dataFile); err != nil {
@@ -320,7 +320,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return verror.Make(errOperationFailed, context.Context())
+ return verror.Make(ErrOperationFailed, context.Context())
}
return nil
}
@@ -332,7 +332,7 @@
}
n := i.createObjectNameTree().find(elems, false)
if n == nil {
- return nil, verror.Make(errOperationFailed, context.Context())
+ return nil, verror.Make(ErrOperationFailed, context.Context())
}
ch := make(chan string)
go func() {
diff --git a/services/mgmt/binary/impl/util_test.go b/services/mgmt/binary/impl/util_test.go
new file mode 100644
index 0000000..d747dd7
--- /dev/null
+++ b/services/mgmt/binary/impl/util_test.go
@@ -0,0 +1,91 @@
+package impl_test
+
+import (
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "testing"
+
+ "v.io/core/veyron2/context"
+ "v.io/core/veyron2/services/mgmt/repository"
+
+ "v.io/core/veyron/lib/testutil"
+ "v.io/core/veyron/services/mgmt/binary/impl"
+)
+
+// invokeUpload invokes the Upload RPC using the given client binary
+// <binary> and streams the given binary <binary> to it.
+func invokeUpload(t *testing.T, ctx *context.T, binary repository.BinaryClientMethods, data []byte, part int32) (error, error) {
+ stream, err := binary.Upload(ctx, part)
+ if err != nil {
+ t.Errorf("Upload() failed: %v", err)
+ return nil, err
+ }
+ sender := stream.SendStream()
+ if streamErr := sender.Send(data); streamErr != nil {
+ err := stream.Finish()
+ if err != nil {
+ t.Logf("Finish() failed: %v", err)
+ }
+ t.Logf("Send() failed: %v", streamErr)
+ return streamErr, err
+ }
+ if streamErr := sender.Close(); streamErr != nil {
+ err := stream.Finish()
+ if err != nil {
+ t.Logf("Finish() failed: %v", err)
+ }
+ t.Logf("Close() failed: %v", streamErr)
+ return streamErr, err
+ }
+ if err := stream.Finish(); err != nil {
+ t.Logf("Finish() failed: %v", err)
+ return nil, err
+ }
+ return nil, nil
+}
+
+// invokeDownload invokes the Download RPC using the given client binary
+// <binary> and streams binary from to it.
+func invokeDownload(t *testing.T, ctx *context.T, binary repository.BinaryClientMethods, part int32) ([]byte, error, error) {
+ stream, err := binary.Download(ctx, part)
+ if err != nil {
+ t.Errorf("Download() failed: %v", err)
+ return nil, nil, err
+ }
+ output := make([]byte, 0)
+ rStream := stream.RecvStream()
+ for rStream.Advance() {
+ bytes := rStream.Value()
+ output = append(output, bytes...)
+ }
+
+ if streamErr := rStream.Err(); streamErr != nil {
+ err := stream.Finish()
+ if err != nil {
+ t.Logf("Finish() failed: %v", err)
+ }
+ t.Logf("Advance() failed with: %v", streamErr)
+ return nil, streamErr, err
+ }
+
+ if err := stream.Finish(); err != nil {
+ t.Logf("Finish() failed: %v", err)
+ return nil, nil, err
+ }
+ return output, nil, nil
+}
+
+func prepDirectory(t *testing.T, rootDir string) {
+ path, perm := filepath.Join(rootDir, impl.VersionFile), os.FileMode(0600)
+ if err := ioutil.WriteFile(path, []byte(impl.Version), perm); err != nil {
+ t.Fatalf(testutil.FormatLogLine(2, "WriteFile(%v, %v, %v) failed: %v", path, impl.Version, perm, err))
+ }
+}
+
+// testData creates up to 4MB of random bytes.
+func testData() []byte {
+ size := testutil.Rand.Intn(1000 * impl.BufferLength)
+ data := testutil.RandomBytes(size)
+ return data
+}
diff --git a/services/mgmt/device/config.vdl.go b/services/mgmt/device/config.vdl.go
index 4e35ccc..1a14ccb 100644
--- a/services/mgmt/device/config.vdl.go
+++ b/services/mgmt/device/config.vdl.go
@@ -8,15 +8,8 @@
__veyron2 "v.io/core/veyron2"
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
- __vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// ConfigClientMethods is the client interface
// containing Config methods.
//
@@ -66,17 +59,6 @@
return
}
-func (c implConfigClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// ConfigServerMethods is the interface a server writer
// implements for Config.
//
@@ -97,8 +79,6 @@
ConfigServerStubMethods
// Describe the Config interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// ConfigServer returns a server stub for Config.
@@ -157,22 +137,3 @@
},
},
}
-
-func (s implConfigServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Set"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "key", Type: 3},
- {Name: "value", Type: 3},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
- return result, nil
-}
diff --git a/services/mgmt/device/deviced/commands.go b/services/mgmt/device/deviced/commands.go
index edf5e95..1689b77 100644
--- a/services/mgmt/device/deviced/commands.go
+++ b/services/mgmt/device/deviced/commands.go
@@ -15,8 +15,10 @@
installFrom string
suidHelper string
agent string
+ initHelper string
singleUser bool
sessionMode bool
+ initMode bool
)
const deviceDirEnv = "VANADIUM_DEVICE_DIR"
@@ -47,8 +49,10 @@
cmdInstall.Flags.StringVar(&installFrom, "from", "", "if specified, performs the installation from the provided application envelope object name")
cmdInstall.Flags.StringVar(&suidHelper, "suid_helper", "", "path to suid helper")
cmdInstall.Flags.StringVar(&agent, "agent", "", "path to security agent")
+ cmdInstall.Flags.StringVar(&initHelper, "init_helper", "", "path to sysinit helper")
cmdInstall.Flags.BoolVar(&singleUser, "single_user", false, "if set, performs the installation assuming a single-user system")
cmdInstall.Flags.BoolVar(&sessionMode, "session_mode", false, "if set, installs the device manager to run a single session. Otherwise, the device manager is configured to get restarted upon exit")
+ cmdInstall.Flags.BoolVar(&initMode, "init_mode", false, "if set, installs the device manager with the system init service manager")
}
func runInstall(cmd *cmdline.Command, args []string) error {
@@ -66,7 +70,10 @@
if agent == "" {
return cmd.UsageErrorf("--agent must be set")
}
- if err := impl.SelfInstall(installationDir(), suidHelper, agent, singleUser, sessionMode, args, os.Environ()); err != nil {
+ if initMode && initHelper == "" {
+ return cmd.UsageErrorf("--init_helper must be set")
+ }
+ if err := impl.SelfInstall(installationDir(), suidHelper, agent, initHelper, singleUser, sessionMode, initMode, args, os.Environ(), cmd.Stderr(), cmd.Stdout()); err != nil {
vlog.Errorf("SelfInstall failed: %v", err)
return err
}
@@ -80,8 +87,8 @@
Long: fmt.Sprintf("Removes the device manager installation from %s (if the env var set), or the current dir otherwise", deviceDirEnv),
}
-func runUninstall(*cmdline.Command, []string) error {
- if err := impl.Uninstall(installationDir()); err != nil {
+func runUninstall(cmd *cmdline.Command, _ []string) error {
+ if err := impl.Uninstall(installationDir(), cmd.Stderr(), cmd.Stdout()); err != nil {
vlog.Errorf("Uninstall failed: %v", err)
return err
}
@@ -95,8 +102,8 @@
Long: fmt.Sprintf("Starts the device manager installed under from %s (if the env var set), or the current dir otherwise", deviceDirEnv),
}
-func runStart(*cmdline.Command, []string) error {
- if err := impl.Start(installationDir(), nil, nil); err != nil {
+func runStart(cmd *cmdline.Command, _ []string) error {
+ if err := impl.Start(installationDir(), cmd.Stderr(), cmd.Stdout()); err != nil {
vlog.Errorf("Start failed: %v", err)
return err
}
@@ -110,16 +117,33 @@
Long: fmt.Sprintf("Stops the device manager installed under from %s (if the env var set), or the current dir otherwise", deviceDirEnv),
}
-func runStop(*cmdline.Command, []string) error {
+func runStop(cmd *cmdline.Command, _ []string) error {
runtime, err := rt.New()
if err != nil {
vlog.Errorf("Could not initialize runtime: %v", err)
return err
}
defer runtime.Cleanup()
- if err := impl.Stop(runtime.NewContext(), installationDir()); err != nil {
+ if err := impl.Stop(runtime.NewContext(), installationDir(), cmd.Stderr(), cmd.Stdout()); err != nil {
vlog.Errorf("Stop failed: %v", err)
return err
}
return nil
}
+
+var cmdProfile = &cmdline.Command{
+ Run: runProfile,
+ Name: "profile",
+ Short: "Dumps profile for the device manager.",
+ Long: "Prints the internal profile description for the device manager.",
+}
+
+func runProfile(cmd *cmdline.Command, _ []string) error {
+ spec, err := impl.ComputeDeviceProfile()
+ if err != nil {
+ vlog.Errorf("ComputeDeviceProfile failed: %v", err)
+ return err
+ }
+ fmt.Fprintf(cmd.Stdout(), "Profile: %#v\n", spec)
+ return nil
+}
diff --git a/services/mgmt/device/deviced/main.go b/services/mgmt/device/deviced/main.go
index 9b21878..710b33f 100644
--- a/services/mgmt/device/deviced/main.go
+++ b/services/mgmt/device/deviced/main.go
@@ -9,7 +9,7 @@
Long: `
deviced can be used to launch, configure, or manage the device manager.
`,
- Children: []*cmdline.Command{cmdInstall, cmdUninstall, cmdStart, cmdStop},
+ Children: []*cmdline.Command{cmdInstall, cmdUninstall, cmdStart, cmdStop, cmdProfile},
Run: runServer,
}
rootCmd.Main()
diff --git a/services/mgmt/device/deviced/server.go b/services/mgmt/device/deviced/server.go
index 5ec30e7..69eef3a 100644
--- a/services/mgmt/device/deviced/server.go
+++ b/services/mgmt/device/deviced/server.go
@@ -2,6 +2,7 @@
import (
"flag"
+ "time"
"v.io/lib/cmdline"
@@ -15,10 +16,10 @@
)
var (
- // TODO(caprita): publishAs and stopExitCode should be provided by the
+ // TODO(caprita): publishAs and restartExitCode should be provided by the
// config?
- publishAs = flag.String("name", "", "name to publish the device manager at")
- stopExitCode = flag.Int("stop_exit_code", 0, "exit code to return when stopped via the Stop RPC")
+ publishAs = flag.String("name", "", "name to publish the device manager at")
+ restartExitCode = flag.Int("restart_exit_code", 0, "exit code to return when device manager should be restarted")
)
func runServer(*cmdline.Command, []string) error {
@@ -54,7 +55,7 @@
// implementation detail).
var exitErr error
- dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, func() { exitErr = cmdline.ErrExitCode(*stopExitCode) })
+ dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(ctx), configState, func() { exitErr = cmdline.ErrExitCode(*restartExitCode) })
if err != nil {
vlog.Errorf("Failed to create dispatcher: %v", err)
return err
@@ -66,7 +67,9 @@
vlog.VI(0).Infof("Device manager published as: %v", *publishAs)
impl.InvokeCallback(runtime.NewContext(), name)
- // Wait until shutdown.
+ // Wait until shutdown. Ignore duplicate signals (sent by agent and
+ // received as part of process group).
+ signals.SameSignalTimeWindow = 500 * time.Millisecond
<-signals.ShutdownOnSignals(ctx)
return exitErr
diff --git a/services/mgmt/device/impl/app_service.go b/services/mgmt/device/impl/app_service.go
index 5ccb84e..940df40 100644
--- a/services/mgmt/device/impl/app_service.go
+++ b/services/mgmt/device/impl/app_service.go
@@ -147,6 +147,7 @@
"v.io/core/veyron/security/agent"
"v.io/core/veyron/security/agent/keymgr"
iconfig "v.io/core/veyron/services/mgmt/device/config"
+ "v.io/core/veyron/services/mgmt/lib/acls"
libbinary "v.io/core/veyron/services/mgmt/lib/binary"
libpackages "v.io/core/veyron/services/mgmt/lib/packages"
)
@@ -206,7 +207,7 @@
// instance.
suffix []string
uat BlessingSystemAssociationStore
- locks aclLocks
+ locks *acls.Locks
// Reference to the devicemanager top-level ACL list.
deviceACL access.TaggedACLMap
// securityAgent holds state related to the security agent (nil if not
@@ -393,20 +394,6 @@
return versionDir, updateLink(versionDir, filepath.Join(installationDir, "current"))
}
-// TODO(rjkroege): Refactor this code with the instance creation code.
-func initializeInstallationACLs(principal security.Principal, dir string, blessings []string, acl access.TaggedACLMap) error {
- // Add the invoker's blessings.
- for _, b := range blessings {
- for _, tag := range access.AllTypicalTags() {
- acl.Add(security.BlessingPattern(b), string(tag))
- }
- }
- aclDir := path.Join(dir, "acls")
- aclData := path.Join(aclDir, "data")
- aclSig := path.Join(aclDir, "signature")
- return writeACLs(principal, aclData, aclSig, aclDir, acl)
-}
-
func (i *appService) Install(call ipc.ServerContext, applicationVON string, config device.Config) (string, error) {
if len(i.suffix) > 0 {
return "", verror2.Make(ErrInvalidSuffix, call.Context())
@@ -443,7 +430,7 @@
// TODO(caprita,rjkroege): Should the installation ACLs really be
// seeded with the device ACL? Instead, might want to hide the deviceACL
// from the app?
- if err := initializeInstallationACLs(call.LocalPrincipal(), installationDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
+ if err := i.initializeSubACLs(call.LocalPrincipal(), installationDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
return "", err
}
deferrer = nil
@@ -500,7 +487,7 @@
defer conn.Close()
// TODO(caprita): release the socket created by NewAgentPrincipal.
- if p, err = agent.NewAgentPrincipal(ctx, int(conn.Fd())); err != nil {
+ if p, err = agent.NewAgentPrincipal(ctx, int(conn.Fd()), veyron2.GetClient(ctx)); err != nil {
vlog.Errorf("NewAgentPrincipal() failed: %v", err)
return verror2.Make(ErrOperationFailed, nil)
}
@@ -629,16 +616,14 @@
return nil
}
-func initializeInstanceACLs(principal security.Principal, instanceDir string, blessings []string, acl access.TaggedACLMap) error {
+func (i *appService) initializeSubACLs(principal security.Principal, instanceDir string, blessings []string, acl access.TaggedACLMap) error {
for _, b := range blessings {
for _, tag := range access.AllTypicalTags() {
acl.Add(security.BlessingPattern(b), string(tag))
}
}
aclDir := path.Join(instanceDir, "acls")
- aclData := path.Join(aclDir, "data")
- aclSig := path.Join(aclDir, "signature")
- return writeACLs(principal, aclData, aclSig, aclDir, acl)
+ return i.locks.SetPathACL(principal, aclDir, acl, "")
}
// newInstance sets up the directory for a new application instance.
@@ -686,7 +671,7 @@
return instanceDir, instanceID, err
}
- if err := initializeInstanceACLs(call.LocalPrincipal(), instanceDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
+ if err := i.initializeSubACLs(call.LocalPrincipal(), instanceDir, call.RemoteBlessings().ForContext(call), i.deviceACL.Copy()); err != nil {
return instanceDir, instanceID, err
}
return instanceDir, instanceID, nil
@@ -1311,13 +1296,13 @@
if err != nil {
return err
}
- return setAppACL(ctx.LocalPrincipal(), i.locks, dir, acl, etag)
+ return i.locks.SetPathACL(ctx.LocalPrincipal(), path.Join(dir, "acls"), acl, etag)
}
-func (i *appService) GetACL(_ ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
+func (i *appService) GetACL(ctx ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
dir, err := dirFromSuffix(i.suffix, i.config.Root)
if err != nil {
return nil, "", err
}
- return getAppACL(i.locks, dir)
+ return i.locks.GetPathACL(ctx.LocalPrincipal(), path.Join(dir, "acls"))
}
diff --git a/services/mgmt/device/impl/device_installer.go b/services/mgmt/device/impl/device_installer.go
index 15cf0ca..cfa0015 100644
--- a/services/mgmt/device/impl/device_installer.go
+++ b/services/mgmt/device/impl/device_installer.go
@@ -1,11 +1,39 @@
package impl
+// The device installer logic is responsible for managing the device manager
+// server, including setting it up / tearing it down, and starting / stopping
+// it.
+//
+// When setting up the device manager installation, the installer creates a
+// directory structure from which the device manager can be run. It sets up:
+//
+// <installDir> - provided when installer is invoked
+// dmroot/ - created/owned by the installation
+// device-manager/ - will be the root for the device manager server;
+// set as <Config.Root> (see comment in
+// device_service.go for what goes under here)
+// base/ - initial installation of device manager
+// deviced - link to deviced (self)
+// deviced.sh - script to start the device manager
+// logs/ - device manager logs will go here
+// current - set as <Config.CurrentLink>
+// agent_deviced.sh - script to launch device manager under agent
+// security/ - security agent keeps credentials here
+// keys/
+// principal/
+// agent_logs/ - security agent logs
+// STDERR-<timestamp>
+// STDOUT-<timestamp>
+// service_description - json-encoded sysinit device manager config
+// inithelper - soft link to init helper
+
import (
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
+ "os/user"
"path/filepath"
"regexp"
"strings"
@@ -16,12 +44,14 @@
"v.io/core/veyron/lib/flags/consts"
"v.io/core/veyron/services/mgmt/device/config"
+ "v.io/core/veyron/services/mgmt/sysinit"
)
-// stopExitCode is the exit code that the device manager should return when it
-// gets a Stop RPC. This number is picked quasi-arbitrarily from the set of
+// restartExitCode is the exit code that the device manager should return when it
+// wants to be restarted by its parent (i.e., the security agent).
+// This number is picked quasi-arbitrarily from the set of
// exit codes without prior special meanings.
-const stopExitCode = 140
+const restartExitCode = 140
// dmRoot is the directory name where the device manager installs itself.
const dmRoot = "dmroot"
@@ -62,9 +92,34 @@
return filterEnvironment(env, allowedVarsRE, deniedVarsRE)
}
+// initCommand verifies if init mode is enabled, and if so executes the
+// appropriate sysinit command. Returns whether init mode was detected, as well
+// as any error encountered.
+func initCommand(root, command string, stderr, stdout io.Writer) (bool, error) {
+ sdFile := filepath.Join(root, "service_description")
+ if _, err := os.Stat(sdFile); err != nil {
+ if os.IsNotExist(err) {
+ return false, nil
+ }
+ return false, fmt.Errorf("Stat(%v) failed: %v", sdFile, err)
+ }
+ helperLink := filepath.Join(root, "inithelper")
+ cmd := exec.Command(helperLink, fmt.Sprintf("--service_description=%s", sdFile), command)
+ if stderr != nil {
+ cmd.Stderr = stderr
+ }
+ if stdout != nil {
+ cmd.Stdout = stdout
+ }
+ if err := cmd.Run(); err != nil {
+ return true, fmt.Errorf("Running init helper %v failed: %v", command, err)
+ }
+ return true, nil
+}
+
// SelfInstall installs the device manager and configures it using the
// environment and the supplied command-line flags.
-func SelfInstall(installDir, suidHelper, agent string, singleUser, sessionMode bool, args, env []string) error {
+func SelfInstall(installDir, suidHelper, agent, initHelper string, singleUser, sessionMode, init bool, args, env []string, stderr, stdout io.Writer) error {
root := filepath.Join(installDir, dmRoot)
if _, err := os.Stat(root); err == nil || !os.IsNotExist(err) {
return fmt.Errorf("%v already exists", root)
@@ -89,7 +144,7 @@
extraArgs = append(extraArgs, fmt.Sprintf("--name=%q", name))
}
if !sessionMode {
- extraArgs = append(extraArgs, fmt.Sprintf("--stop_exit_code=%d", stopExitCode))
+ extraArgs = append(extraArgs, fmt.Sprintf("--restart_exit_code=%d", restartExitCode))
}
envelope := &application.Envelope{
Args: append(extraArgs, args...),
@@ -106,7 +161,8 @@
if err != nil {
return fmt.Errorf("failed to serialize config %v: %v", configState, err)
}
- if err := generateScript(deviceDir, configSettings, envelope); err != nil {
+ logs := filepath.Join(root, "device-manager", "logs")
+ if err := generateScript(deviceDir, configSettings, envelope, logs); err != nil {
return err
}
@@ -115,8 +171,37 @@
return err
}
- return generateAgentScript(root, agent, currLink, singleUser, sessionMode)
- // TODO(caprita): Update system management daemon.
+ if err := generateAgentScript(root, agent, currLink, singleUser, sessionMode); err != nil {
+ return err
+ }
+ if init {
+ agentScript := filepath.Join(root, "agent_deviced.sh")
+ currentUser, err := user.Current()
+ if err != nil {
+ return err
+ }
+ sd := &sysinit.ServiceDescription{
+ Service: "deviced",
+ Description: "Vanadium Device Manager",
+ Binary: agentScript,
+ Command: []string{agentScript},
+ User: currentUser.Username,
+ }
+ sdFile := filepath.Join(root, "service_description")
+ if err := sd.SaveTo(sdFile); err != nil {
+ return fmt.Errorf("SaveTo for %v failed: %v", sd, err)
+ }
+ helperLink := filepath.Join(root, "inithelper")
+ if err := os.Symlink(initHelper, helperLink); err != nil {
+ return fmt.Errorf("Symlink(%v, %v) failed: %v", initHelper, helperLink, err)
+ }
+ if initMode, err := initCommand(root, "install", stderr, stdout); err != nil {
+ return err
+ } else if !initMode {
+ return fmt.Errorf("enabling init mode failed")
+ }
+ }
+ return nil
}
func generateAgentScript(workspace, agent, currLink string, singleUser, sessionMode bool) error {
@@ -130,8 +215,13 @@
if err := os.MkdirAll(keyDir, perm); err != nil {
return fmt.Errorf("MkdirAll(%v, %v) failed: %v", keyDir, perm, err)
}
+ logs := filepath.Join(workspace, "agent_logs")
+ if err := os.MkdirAll(logs, perm); err != nil {
+ return fmt.Errorf("MkdirAll(%v, %v) failed: %v", logs, perm, err)
+ }
// TODO(caprita): Switch all our generated bash scripts to use templates.
output := "#!/bin/bash\n"
+ output += fmt.Sprintln("readonly TIMESTAMP=$(date +%s%N)")
output += fmt.Sprintf("%s=%q ", consts.VeyronCredentials, principalDir)
// Escape the path to the binary; %q uses Go-syntax escaping, but it's
// close enough to Bash that we're using it as an approximation.
@@ -143,10 +233,13 @@
output += "--no_passphrase "
}
if !sessionMode {
- output += fmt.Sprintf("--restart_exit_code=!%d ", stopExitCode)
+ output += fmt.Sprintf("--restart_exit_code=!0 ")
}
output += fmt.Sprintf("--additional_principals=%q ", keyDir)
- output += fmt.Sprintf("%q\n", currLink)
+ stdoutLog, stderrLog := filepath.Join(logs, "STDERR"), filepath.Join(logs, "STDOUT")
+ // Write stdout and stderr both to the standard streams, and also to
+ // timestamped files.
+ output += fmt.Sprintf("%q > >(tee %s-$TIMESTAMP) 2> >(tee %s-$TIMESTAMP >&2)\n", currLink, stdoutLog, stderrLog)
path := filepath.Join(workspace, "agent_deviced.sh")
if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
return fmt.Errorf("WriteFile(%v) failed: %v", path, err)
@@ -157,16 +250,18 @@
// Uninstall undoes SelfInstall, removing the device manager's installation
// directory.
-func Uninstall(installDir string) error {
+func Uninstall(installDir string, stdout, stderr io.Writer) error {
// TODO(caprita): ensure device is stopped?
root := filepath.Join(installDir, dmRoot)
+ if _, err := initCommand(root, "uninstall", stdout, stderr); err != nil {
+ return err
+ }
// TODO(caprita): Use suidhelper to delete dirs/files owned by other
// users under the app work dirs.
if err := os.RemoveAll(root); err != nil {
return fmt.Errorf("RemoveAll(%v) failed: %v", root, err)
}
- // TODO(caprita): Update system management daemon.
return nil
}
@@ -175,7 +270,13 @@
// TODO(caprita): make sure it's not already running?
root := filepath.Join(installDir, dmRoot)
- // TODO(caprita): In non-session mode, use system management daemon.
+
+ if initMode, err := initCommand(root, "start", stderr, stdout); err != nil {
+ return err
+ } else if initMode {
+ return nil
+ }
+
agentScript := filepath.Join(root, "agent_deviced.sh")
cmd := exec.Command(agentScript)
if stderr != nil {
@@ -191,8 +292,13 @@
}
// Stop stops the device manager.
-func Stop(ctx *context.T, installDir string) error {
+func Stop(ctx *context.T, installDir string, stderr, stdout io.Writer) error {
root := filepath.Join(installDir, dmRoot)
+ if initMode, err := initCommand(root, "stop", stderr, stdout); err != nil {
+ return err
+ } else if initMode {
+ return nil
+ }
info, err := loadManagerInfo(filepath.Join(root, "device-manager"))
if err != nil {
return fmt.Errorf("loadManagerInfo failed: %v", err)
@@ -201,7 +307,5 @@
return fmt.Errorf("Stop failed: %v", err)
}
// TODO(caprita): Wait for the (device|agent) process to be gone.
-
- // TODO(caprita): In non-session mode, use system management daemon.
return nil
}
diff --git a/services/mgmt/device/impl/device_service.go b/services/mgmt/device/impl/device_service.go
index 02d1113..e8c9617 100644
--- a/services/mgmt/device/impl/device_service.go
+++ b/services/mgmt/device/impl/device_service.go
@@ -8,14 +8,18 @@
// device-manager/
// info - metadata for the device manager (such as object
// name and process id)
+// logs/ - device manager logs
+// STDERR-<timestamp> - one for each execution of device manager
+// STDOUT-<timestamp> - one for each execution of device manager
// <version 1 timestamp>/ - timestamp of when the version was downloaded
// deviced - the device manager binary
// deviced.sh - a shell script to start the binary
// <version 2 timestamp>
// ...
// device-data/
-// acl.devicemanager
-// acl.signature
+// acls/
+// data
+// signature
// associated.accounts
//
// The device manager is always expected to be started through the symbolic link
@@ -90,12 +94,12 @@
// deviceService implements the Device manager's Device interface.
type deviceService struct {
- updating *updatingState
- stopHandler func()
- callback *callbackState
- config *config.State
- disp *dispatcher
- uat BlessingSystemAssociationStore
+ updating *updatingState
+ restartHandler func()
+ callback *callbackState
+ config *config.State
+ disp *dispatcher
+ uat BlessingSystemAssociationStore
}
// managerInfo holds state about a running device manager.
@@ -140,31 +144,21 @@
}
func (*deviceService) Describe(ipc.ServerContext) (device.Description, error) {
- empty := device.Description{}
- deviceProfile, err := computeDeviceProfile()
- if err != nil {
- return empty, err
- }
- knownProfiles, err := getKnownProfiles()
- if err != nil {
- return empty, err
- }
- result := matchProfiles(deviceProfile, knownProfiles)
- return result, nil
+ return describe()
}
func (*deviceService) IsRunnable(_ ipc.ServerContext, description binary.Description) (bool, error) {
- deviceProfile, err := computeDeviceProfile()
+ deviceProfile, err := ComputeDeviceProfile()
if err != nil {
return false, err
}
- binaryProfiles := make([]profile.Specification, 0)
+ binaryProfiles := make([]*profile.Specification, 0)
for name, _ := range description.Profiles {
profile, err := getProfile(name)
if err != nil {
return false, err
}
- binaryProfiles = append(binaryProfiles, *profile)
+ binaryProfiles = append(binaryProfiles, profile)
}
result := matchProfiles(deviceProfile, binaryProfiles)
return len(result.Profiles) > 0, nil
@@ -196,6 +190,9 @@
if err := updateLink(s.config.Previous, s.config.CurrentLink); err != nil {
return err
}
+ if s.restartHandler != nil {
+ s.restartHandler()
+ }
veyron2.GetAppCycle(ctx).Stop()
return nil
}
@@ -311,7 +308,7 @@
// TODO(caprita): Move this to util.go since device_installer is also using it now.
-func generateScript(workspace string, configSettings []string, envelope *application.Envelope) error {
+func generateScript(workspace string, configSettings []string, envelope *application.Envelope, logs string) error {
// TODO(caprita): Remove this snippet of code, it doesn't seem to serve
// any purpose.
path, err := filepath.EvalSymlinks(os.Args[0])
@@ -321,6 +318,7 @@
}
output := "#!/bin/bash\n"
+ output += fmt.Sprintln("readonly TIMESTAMP=$(date +%s%N)")
output += strings.Join(config.QuoteEnv(append(envelope.Env, configSettings...)), " ") + " "
// Escape the path to the binary; %q uses Go-syntax escaping, but it's
// close enough to Bash that we're using it as an approximation.
@@ -329,7 +327,14 @@
// veyron/tools/debug/impl.go) instead.
output += fmt.Sprintf("exec %q", filepath.Join(workspace, "deviced")) + " "
output += strings.Join(envelope.Args, " ")
- output += "\n"
+ if err := os.MkdirAll(logs, 0700); err != nil {
+ vlog.Errorf("MkdirAll(%v) failed: %v", logs, err)
+ return verror2.Make(ErrOperationFailed, nil)
+ }
+ stderrLog, stdoutLog := filepath.Join(logs, "STDERR"), filepath.Join(logs, "STDOUT")
+ // Write stdout and stderr both to the standard streams, and also to
+ // timestamped files.
+ output += fmt.Sprintf(" > >(tee %s-$TIMESTAMP) 2> >(tee %s-$TIMESTAMP >&2)\n", stdoutLog, stderrLog)
path = filepath.Join(workspace, "deviced.sh")
if err := ioutil.WriteFile(path, []byte(output), 0700); err != nil {
vlog.Errorf("WriteFile(%v) failed: %v", path, err)
@@ -389,7 +394,8 @@
return verror2.Make(ErrOperationFailed, ctx)
}
- if err := generateScript(workspace, configSettings, envelope); err != nil {
+ logs := filepath.Join(s.config.Root, "device-manager", "logs")
+ if err := generateScript(workspace, configSettings, envelope, logs); err != nil {
return err
}
@@ -401,6 +407,9 @@
return err
}
+ if s.restartHandler != nil {
+ s.restartHandler()
+ }
veyron2.GetAppCycle(ctx).Stop()
deferrer = nil
return nil
@@ -443,15 +452,17 @@
return nil, verror2.Make(ErrInvalidSuffix, ctx.Context())
}
-func (s *deviceService) Stop(call ipc.ServerContext, _ uint32) error {
- if s.stopHandler != nil {
- s.stopHandler()
- }
+func (*deviceService) Stop(call ipc.ServerContext, _ uint32) error {
veyron2.GetAppCycle(call.Context()).Stop()
return nil
}
-func (*deviceService) Suspend(call ipc.ServerContext) error {
+func (s *deviceService) Suspend(call ipc.ServerContext) error {
+ // TODO(caprita): move this to Restart and disable Suspend for device
+ // manager?
+ if s.restartHandler != nil {
+ s.restartHandler()
+ }
veyron2.GetAppCycle(call.Context()).Stop()
return nil
}
@@ -482,11 +493,11 @@
}
func (s *deviceService) SetACL(ctx ipc.ServerContext, acl access.TaggedACLMap, etag string) error {
- return s.disp.setACL(ctx.LocalPrincipal(), acl, etag, true /* store ACL on disk */)
+ return s.disp.locks.SetPathACL(ctx.LocalPrincipal(), s.disp.getACLDir(), acl, etag)
}
-func (s *deviceService) GetACL(_ ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
- return s.disp.getACL()
+func (s *deviceService) GetACL(ctx ipc.ServerContext) (acl access.TaggedACLMap, etag string, err error) {
+ return s.disp.locks.GetPathACL(ctx.LocalPrincipal(), s.disp.getACLDir())
}
func sameMachineCheck(ctx ipc.ServerContext) error {
diff --git a/services/mgmt/device/impl/dispatcher.go b/services/mgmt/device/impl/dispatcher.go
index dabfcbc..30cf651 100644
--- a/services/mgmt/device/impl/dispatcher.go
+++ b/services/mgmt/device/impl/dispatcher.go
@@ -2,7 +2,6 @@
import (
"fmt"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -11,8 +10,7 @@
"v.io/core/veyron/security/agent"
"v.io/core/veyron/security/agent/keymgr"
- vflag "v.io/core/veyron/security/flag"
- "v.io/core/veyron/security/serialization"
+ "v.io/core/veyron/security/flag"
idevice "v.io/core/veyron/services/mgmt/device"
"v.io/core/veyron/services/mgmt/device/config"
"v.io/core/veyron/services/mgmt/lib/acls"
@@ -32,25 +30,14 @@
// internalState wraps state shared between different device manager
// invocations.
type internalState struct {
- callback *callbackState
- updating *updatingState
- securityAgent *securityAgentState
- stopHandler func()
+ callback *callbackState
+ updating *updatingState
+ securityAgent *securityAgentState
+ restartHandler func()
}
-// aclLocks provides a mutex lock for each acl file path.
-type aclLocks map[string]*sync.Mutex
-
// dispatcher holds the state of the device manager dispatcher.
type dispatcher struct {
- // acl/auth hold the acl and authorizer used to authorize access to the
- // device manager methods.
- acl access.TaggedACLMap
- auth security.Authorizer
- // etag holds the version string for the ACL. We use this for optimistic
- // concurrency control when clients update the ACLs for the device
- // manager.
- etag string
// internal holds the state that persists across RPC method invocations.
internal *internalState
// config holds the device manager's (immutable) configuration state.
@@ -59,9 +46,9 @@
// dispatcher methods.
mu sync.RWMutex
// TODO(rjkroege): Consider moving this inside internal.
- uat BlessingSystemAssociationStore
- // TODO(rjkroege): Eliminate need for locks.
- locks aclLocks
+ uat BlessingSystemAssociationStore
+ locks *acls.Locks
+ principal security.Principal
}
var _ ipc.Dispatcher = (*dispatcher)(nil)
@@ -85,7 +72,7 @@
)
// NewDispatcher is the device manager dispatcher factory.
-func NewDispatcher(principal security.Principal, config *config.State, stopHandler func()) (*dispatcher, error) {
+func NewDispatcher(principal security.Principal, config *config.State, restartHandler func()) (*dispatcher, error) {
if err := config.Validate(); err != nil {
return nil, fmt.Errorf("invalid config %v: %v", config, err)
}
@@ -104,48 +91,25 @@
return nil, fmt.Errorf("cannot create persistent store for identity to system account associations: %v", err)
}
d := &dispatcher{
- etag: "default",
internal: &internalState{
- callback: newCallbackState(config.Name),
- updating: newUpdatingState(),
- stopHandler: stopHandler,
+ callback: newCallbackState(config.Name),
+ updating: newUpdatingState(),
+ restartHandler: restartHandler,
},
- config: config,
- uat: uat,
- locks: make(aclLocks),
+ config: config,
+ uat: uat,
+ locks: acls.NewLocks(),
+ principal: principal,
}
- // If there exists a signed ACL from a previous instance we prefer that.
- aclFile, sigFile, _ := d.getACLFilePaths()
- if _, err := os.Stat(aclFile); err == nil {
- perm := os.FileMode(0700)
- data, err := os.OpenFile(aclFile, os.O_RDONLY, perm)
- if err != nil {
- return nil, fmt.Errorf("failed to open acl file:%v", err)
- }
- defer data.Close()
- sig, err := os.OpenFile(sigFile, os.O_RDONLY, perm)
- if err != nil {
- return nil, fmt.Errorf("failed to open signature file:%v", err)
- }
- defer sig.Close()
- // read and verify the signature of the acl file
- reader, err := serialization.NewVerifyingReader(data, sig, principal.PublicKey())
- if err != nil {
- return nil, fmt.Errorf("failed to read devicemanager ACL file:%v", err)
- }
- acl, err := access.ReadTaggedACLMap(reader)
- if err != nil {
- return nil, fmt.Errorf("failed to load devicemanager ACL:%v", err)
- }
- if err := d.setACL(principal, acl, d.etag, false /* just update etag */); err != nil {
+
+ tam, err := flag.TaggedACLMapFromFlag()
+ if err != nil {
+ return nil, err
+ }
+ if tam != nil {
+ if err := d.locks.SetPathACL(principal, d.getACLDir(), tam, ""); err != nil {
return nil, err
}
- } else {
- if d.auth = vflag.NewAuthorizerOrDie(); d.auth == nil {
- // If there are no specified ACLs we grant devicemanager
- // access to all principals until it is claimed.
- d.auth = allowEveryone{}
- }
}
// If we're in 'security agent mode', set up the key manager agent.
if len(os.Getenv(agent.FdVarName)) > 0 {
@@ -160,10 +124,8 @@
return d, nil
}
-func (d *dispatcher) getACLFilePaths() (acl, signature, devicedata string) {
- devicedata = filepath.Join(d.config.Root, "device-manager", "device-data")
- acl, signature = filepath.Join(devicedata, "acl.devicemanager"), filepath.Join(devicedata, "acl.signature")
- return
+func (d *dispatcher) getACLDir() string {
+ return filepath.Join(d.config.Root, "device-manager", "device-data", "acls")
}
func (d *dispatcher) claimDeviceManager(ctx ipc.ServerContext) error {
@@ -193,157 +155,32 @@
acl.Add(security.BlessingPattern(n), string(tag))
}
}
- _, etag, err := d.getACL()
- if err != nil {
- vlog.Errorf("Failed to getACL:%v", err)
- return verror.Make(ErrOperationFailed, nil)
- }
- if err := d.setACL(principal, acl, etag, true /* store ACL on disk */); err != nil {
+ if err := d.locks.SetPathACL(principal, d.getACLDir(), acl, ""); err != nil {
vlog.Errorf("Failed to setACL:%v", err)
return verror.Make(ErrOperationFailed, nil)
}
return nil
}
-// TODO(rjkroege): Further refactor ACL-setting code.
-func setAppACL(principal security.Principal, locks aclLocks, dir string, acl access.TaggedACLMap, etag string) error {
- aclpath := path.Join(dir, "acls", "data")
- sigpath := path.Join(dir, "acls", "signature")
+// TODO(rjkroege): Consider refactoring authorizer implementations to
+// be shareable with other components.
+func newAuthorizer(principal security.Principal, dir string, locks *acls.Locks) (security.Authorizer, error) {
+ rootTam, _, err := locks.GetPathACL(principal, dir)
- // Acquire lock. Locks are per path to an acls file.
- lck, contains := locks[dir]
- if !contains {
- lck = new(sync.Mutex)
- locks[dir] = lck
+ if err != nil && os.IsNotExist(err) {
+ vlog.Errorf("GetPathACL(%s) failed: %v", dir, err)
+ return allowEveryone{}, nil
+ } else if err != nil {
+ return nil, err
}
- lck.Lock()
- defer lck.Unlock()
- f, err := os.Open(aclpath)
+ auth, err := access.TaggedACLAuthorizer(rootTam, access.TypicalTagType())
if err != nil {
- vlog.Errorf("LoadACL(%s) failed: %v", aclpath, err)
- return err
+ vlog.Errorf("Successfully obtained an ACL from the filesystem but TaggedACLAuthorizer couldn't use it: %v", err)
+ return nil, err
}
- defer f.Close()
+ return auth, nil
- curACL, err := access.ReadTaggedACLMap(f)
- if err != nil {
- vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
- return err
- }
- curEtag, err := acls.ComputeEtag(curACL)
- if err != nil {
- vlog.Errorf("acls.ComputeEtag failed: %v", err)
- return err
- }
-
- if len(etag) > 0 && etag != curEtag {
- return verror.Make(access.BadEtag, nil, etag, curEtag)
- }
-
- return writeACLs(principal, aclpath, sigpath, dir, acl)
-}
-
-func getAppACL(locks aclLocks, dir string) (access.TaggedACLMap, string, error) {
- aclpath := path.Join(dir, "acls", "data")
-
- // Acquire lock. Locks are per path to an acls file.
- lck, contains := locks[dir]
- if !contains {
- lck = new(sync.Mutex)
- locks[dir] = lck
- }
- lck.Lock()
- defer lck.Unlock()
-
- f, err := os.Open(aclpath)
- if err != nil {
- vlog.Errorf("Open(%s) failed: %v", aclpath, err)
- return nil, "", err
- }
- defer f.Close()
-
- acl, err := access.ReadTaggedACLMap(f)
- if err != nil {
- vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
- return nil, "", err
- }
- curEtag, err := acls.ComputeEtag(acl)
- if err != nil {
- return nil, "", err
- }
- return acl, curEtag, nil
-}
-
-func writeACLs(principal security.Principal, aclFile, sigFile, dir string, acl access.TaggedACLMap) error {
- // Create dir directory if it does not exist
- os.MkdirAll(dir, os.FileMode(0700))
- // Save the object to temporary data and signature files, and then move
- // those files to the actual data and signature file.
- data, err := ioutil.TempFile(dir, "data")
- if err != nil {
- vlog.Errorf("Failed to open tmpfile data:%v", err)
- return verror.Make(ErrOperationFailed, nil)
- }
- defer os.Remove(data.Name())
- sig, err := ioutil.TempFile(dir, "sig")
- if err != nil {
- vlog.Errorf("Failed to open tmpfile sig:%v", err)
- return verror.Make(ErrOperationFailed, nil)
- }
- defer os.Remove(sig.Name())
- writer, err := serialization.NewSigningWriteCloser(data, sig, principal, nil)
- if err != nil {
- vlog.Errorf("Failed to create NewSigningWriteCloser:%v", err)
- return verror.Make(ErrOperationFailed, nil)
- }
- if err = acl.WriteTo(writer); err != nil {
- vlog.Errorf("Failed to SaveACL:%v", err)
- return verror.Make(ErrOperationFailed, nil)
- }
- if err = writer.Close(); err != nil {
- vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
- return verror.Make(ErrOperationFailed, nil)
- }
- if err := os.Rename(data.Name(), aclFile); err != nil {
- return err
- }
- if err := os.Rename(sig.Name(), sigFile); err != nil {
- return err
- }
- return nil
-}
-
-func (d *dispatcher) setACL(principal security.Principal, acl access.TaggedACLMap, etag string, writeToFile bool) error {
- d.mu.Lock()
- defer d.mu.Unlock()
- aclFile, sigFile, devicedata := d.getACLFilePaths()
-
- if len(etag) > 0 && etag != d.etag {
- return verror.Make(access.BadEtag, nil, etag, d.etag)
- }
- if writeToFile {
- if err := writeACLs(principal, aclFile, sigFile, devicedata, acl); err != nil {
- return err
- }
- }
-
- etag, err := acls.ComputeEtag(acl)
- if err != nil {
- return err
- }
- auth, err := access.TaggedACLAuthorizer(acl, access.TypicalTagType())
- if err != nil {
- return err
- }
- d.acl, d.etag, d.auth = acl, etag, auth
- return nil
-}
-
-func (d *dispatcher) getACL() (acl access.TaggedACLMap, etag string, err error) {
- d.mu.RLock()
- defer d.mu.RUnlock()
- return d.acl, d.etag, nil
}
// DISPATCHER INTERFACE IMPLEMENTATION
@@ -355,8 +192,13 @@
i--
}
}
+ auth, err := newAuthorizer(d.principal, d.getACLDir(), d.locks)
+ if err != nil {
+ return nil, nil, err
+ }
+
if len(components) == 0 {
- return ipc.ChildrenGlobberInvoker(deviceSuffix, appsSuffix), d.auth, nil
+ return ipc.ChildrenGlobberInvoker(deviceSuffix, appsSuffix), auth, nil
}
// The implementation of the device manager is split up into several
// invokers, which are instantiated depending on the receiver name
@@ -364,14 +206,14 @@
switch components[0] {
case deviceSuffix:
receiver := device.DeviceServer(&deviceService{
- callback: d.internal.callback,
- updating: d.internal.updating,
- stopHandler: d.internal.stopHandler,
- config: d.config,
- disp: d,
- uat: d.uat,
+ callback: d.internal.callback,
+ updating: d.internal.updating,
+ restartHandler: d.internal.restartHandler,
+ config: d.config,
+ disp: d,
+ uat: d.uat,
})
- return receiver, d.auth, nil
+ return receiver, auth, nil
case appsSuffix:
// Requests to apps/*/*/*/logs are handled locally by LogFileService.
// Requests to apps/*/*/*/pprof are proxied to the apps' __debug/pprof object.
@@ -386,7 +228,7 @@
case "logs":
logsDir := filepath.Join(appInstanceDir, "logs")
suffix := naming.Join(components[5:]...)
- return logsimpl.NewLogFileService(logsDir, suffix), d.auth, nil
+ return logsimpl.NewLogFileService(logsDir, suffix), auth, nil
case "pprof", "stats":
info, err := loadInstanceInfo(appInstanceDir)
if err != nil {
@@ -395,23 +237,19 @@
if !instanceStateIs(appInstanceDir, started) {
return nil, nil, verror.Make(ErrInvalidSuffix, nil)
}
- var sigStub signatureStub
- if kind == "pprof" {
- sigStub = pprof.PProfServer(nil)
- } else {
- sigStub = stats.StatsServer(nil)
+ var desc []ipc.InterfaceDesc
+ switch kind {
+ case "pprof":
+ desc = pprof.PProfServer(nil).Describe__()
+ case "stats":
+ desc = stats.StatsServer(nil).Describe__()
}
suffix := naming.Join("__debug", naming.Join(components[4:]...))
remote := naming.JoinAddressName(info.AppCycleMgrName, suffix)
- invoker := &proxyInvoker{
- remote: remote,
- access: access.Debug,
- sigStub: sigStub,
- }
- return invoker, d.auth, nil
+ invoker := newProxyInvoker(remote, access.Debug, desc)
+ return invoker, auth, nil
}
}
- deviceACLs, _, err := d.getACL()
if err != nil {
return nil, nil, err
}
@@ -421,10 +259,9 @@
suffix: components[1:],
uat: d.uat,
locks: d.locks,
- deviceACL: deviceACLs,
securityAgent: d.internal.securityAgent,
})
- appSpecificAuthorizer, err := newAppSpecificAuthorizer(d.auth, d.config, components[1:])
+ appSpecificAuthorizer, err := newAppSpecificAuthorizer(auth, d.config, components[1:])
if err != nil {
return nil, nil, err
}
diff --git a/services/mgmt/device/impl/impl_test.go b/services/mgmt/device/impl/impl_test.go
index d509be9..0e52bd3 100644
--- a/services/mgmt/device/impl/impl_test.go
+++ b/services/mgmt/device/impl/impl_test.go
@@ -187,7 +187,7 @@
}
configState.Root, configState.Helper, configState.Origin, configState.CurrentLink = args[0], args[1], args[2], args[3]
}
- dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(globalCtx), configState, func() { fmt.Println("stop handler") })
+ dispatcher, err := impl.NewDispatcher(veyron2.GetPrincipal(globalCtx), configState, func() { fmt.Println("restart handler") })
if err != nil {
vlog.Fatalf("Failed to create device manager dispatcher: %v", err)
}
@@ -400,6 +400,7 @@
dmh.CloseStdin()
+ dms.Expect("restart handler")
dms.Expect("factoryDM terminating")
dmh.Shutdown(os.Stderr, os.Stderr)
@@ -431,6 +432,7 @@
t.Fatalf("current link didn't change")
}
+ dms.Expect("restart handler")
dms.Expect("v2DM terminating")
dmh.Shutdown(os.Stderr, os.Stderr)
@@ -449,6 +451,7 @@
revertDevice(t, "v3DM")
revertDeviceExpectError(t, "v3DM", impl.ErrOperationInProgress.ID) // Revert already in progress.
dmh.CloseStdin()
+ dms.Expect("restart handler")
dms.Expect("v3DM terminating")
if evalLink() != scriptPathV2 {
t.Fatalf("current link was not reverted correctly")
@@ -463,6 +466,7 @@
// Revert the device manager to its previous version (factory).
revertDevice(t, "v2DM")
+ dms.Expect("restart handler")
dms.Expect("v2DM terminating")
if evalLink() != scriptPathFactory {
t.Fatalf("current link was not reverted correctly")
@@ -475,7 +479,6 @@
mgmttest.ReadPID(t, dms)
resolve(t, "factoryDM", 1) // Current link should have been launching factory version.
stopDevice(t, "factoryDM")
- dms.Expect("stop handler")
dms.Expect("factoryDM terminating")
dms.ExpectEOF()
@@ -485,6 +488,7 @@
mgmttest.ReadPID(t, dms)
resolve(t, "factoryDM", 1)
suspendDevice(t, "factoryDM")
+ dms.Expect("restart handler")
dms.Expect("factoryDM terminating")
dms.ExpectEOF()
}
@@ -879,13 +883,10 @@
// Create an envelope for an app.
*envelope = envelopeFromShell(sh, nil, appCmd, "google naps")
- deviceStub := device.DeviceClient("dm//device")
- acl, etag, err := deviceStub.GetACL(selfCtx)
- if err != nil {
- t.Fatalf("GetACL failed:%v", err)
- }
- if etag != "default" {
- t.Fatalf("getACL expected:default, got:%v(%v)", etag, acl)
+ // On an unclaimed device manager, there will be no ACLs.
+ deviceStub := device.DeviceClient("dm/device")
+ if _, _, err := deviceStub.GetACL(selfCtx); err == nil {
+ t.Fatalf("GetACL should have failed but didn't.")
}
// Claim the devicemanager as "root/self/mydevice"
@@ -902,7 +903,8 @@
}
md5hash := md5.Sum(b.Bytes())
expectedETAG := hex.EncodeToString(md5hash[:])
- if acl, etag, err = deviceStub.GetACL(selfCtx); err != nil {
+ acl, etag, err := deviceStub.GetACL(selfCtx)
+ if err != nil {
t.Fatal(err)
}
if etag != expectedETAG {
@@ -949,17 +951,19 @@
defer cleanup()
// Create a script wrapping the test target that implements suidhelper.
- helperPath := generateSuidHelperScript(t, testDir)
+ suidHelperPath := generateSuidHelperScript(t, testDir)
// Create a dummy script mascarading as the security agent.
agentPath := generateAgentScript(t, testDir)
+ initHelperPath := ""
// Create an 'envelope' for the device manager that we can pass to the
// installer, to ensure that the device manager that the installer
// configures can run.
dmargs, dmenv := sh.CommandEnvelope(deviceManagerCmd, nil, "dm")
dmDir := filepath.Join(testDir, "dm")
- singleUser, sessionMode := true, true
- if err := impl.SelfInstall(dmDir, helperPath, agentPath, singleUser, sessionMode, dmargs[1:], dmenv); err != nil {
+ // TODO(caprita): Add test logic when initMode = true.
+ singleUser, sessionMode, initMode := true, true, false
+ if err := impl.SelfInstall(dmDir, suidHelperPath, agentPath, initHelperPath, singleUser, sessionMode, initMode, dmargs[1:], dmenv, os.Stderr, os.Stdout); err != nil {
t.Fatalf("SelfInstall failed: %v", err)
}
@@ -975,14 +979,13 @@
revertDeviceExpectError(t, "dm", impl.ErrUpdateNoOp.ID) // No previous version available.
// Stop the device manager.
- if err := impl.Stop(globalCtx, dmDir); err != nil {
+ if err := impl.Stop(globalCtx, dmDir, os.Stderr, os.Stdout); err != nil {
t.Fatalf("Stop failed: %v", err)
}
- dms.Expect("stop handler")
dms.Expect("dm terminating")
// Uninstall.
- if err := impl.Uninstall(dmDir); err != nil {
+ if err := impl.Uninstall(dmDir, os.Stderr, os.Stdout); err != nil {
t.Fatalf("Uninstall failed: %v", err)
}
// Ensure that the installation is gone.
diff --git a/services/mgmt/device/impl/mock_repo_test.go b/services/mgmt/device/impl/mock_repo_test.go
index 16fed19..4c2dd10 100644
--- a/services/mgmt/device/impl/mock_repo_test.go
+++ b/services/mgmt/device/impl/mock_repo_test.go
@@ -3,9 +3,11 @@
import (
"crypto/md5"
"encoding/hex"
+ "fmt"
"io"
"io/ioutil"
"os"
+ "reflect"
"testing"
"v.io/core/veyron2/ipc"
@@ -62,8 +64,11 @@
}
// APPLICATION REPOSITORY INTERFACE IMPLEMENTATION
-func (i *arInvoker) Match(ipc.ServerContext, []string) (application.Envelope, error) {
+func (i *arInvoker) Match(_ ipc.ServerContext, profiles []string) (application.Envelope, error) {
vlog.VI(1).Infof("Match()")
+ if want := []string{"test-profile"}; !reflect.DeepEqual(profiles, want) {
+ return application.Envelope{}, fmt.Errorf("Expected profiles %v, got %v", want, profiles)
+ }
return i.envelope, nil
}
diff --git a/services/mgmt/device/impl/only_for_test.go b/services/mgmt/device/impl/only_for_test.go
index 62a69cb..a0fc4a2 100644
--- a/services/mgmt/device/impl/only_for_test.go
+++ b/services/mgmt/device/impl/only_for_test.go
@@ -5,6 +5,7 @@
"os"
"path/filepath"
+ "v.io/core/veyron2/services/mgmt/device"
"v.io/core/veyron2/vlog"
)
@@ -40,6 +41,10 @@
}
}
isSetuid = possiblyMockIsSetuid
+
+ describe = func() (descr device.Description, err error) {
+ return device.Description{Profiles: map[string]struct{}{"test-profile": struct{}{}}}, nil
+ }
}
func possiblyMockIsSetuid(fileStat os.FileInfo) bool {
diff --git a/services/mgmt/device/impl/profile.go b/services/mgmt/device/impl/profile.go
index 275fc3d..4e784af 100644
--- a/services/mgmt/device/impl/profile.go
+++ b/services/mgmt/device/impl/profile.go
@@ -13,13 +13,13 @@
"v.io/core/veyron2/services/mgmt/device"
)
-// computeDeviceProfile generates a description of the runtime
+// ComputeDeviceProfile generates a description of the runtime
// environment (supported file format, OS, architecture, libraries) of
// the host device.
//
// TODO(jsimsa): Avoid computing the host device description from
// scratch if a recent cached copy exists.
-func computeDeviceProfile() (*profile.Specification, error) {
+func ComputeDeviceProfile() (*profile.Specification, error) {
result := profile.Specification{}
// Find out what the supported file format, operating system, and
@@ -52,8 +52,8 @@
switch runtime.GOOS {
case "linux":
// For Linux, we identify what dynamically linked libraries are
- // install by parsing the output of "ldconfig -p".
- command := exec.Command("ldconfig", "-p")
+ // installed by parsing the output of "ldconfig -p".
+ command := exec.Command("/sbin/ldconfig", "-p")
output, err := command.CombinedOutput()
if err != nil {
return nil, err
@@ -101,32 +101,43 @@
// TODO(jsimsa): Avoid retrieving the list of known profiles from a
// remote server if a recent cached copy exists.
func getProfile(name string) (*profile.Specification, error) {
+ profiles, err := getKnownProfiles()
+ if err != nil {
+ return nil, err
+ }
+ for _, p := range profiles {
+ if p.Label == name {
+ return p, nil
+ }
+ }
+ return nil, nil
+
// TODO(jsimsa): This function assumes the existence of a profile
// server from which the profiles can be retrieved. The profile
// server is a work in progress. When it exists, the commented out
// code below should work.
- var profile profile.Specification
/*
- client, err := r.NewClient()
- if err != nil {
- vlog.Errorf("NewClient() failed: %v", err)
- return nil, err
- }
- defer client.Close()
- server := // TODO
- method := "Specification"
- inputs := make([]interface{}, 0)
- call, err := client.StartCall(server + "/" + name, method, inputs)
- if err != nil {
- vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server + "/" + name, method, inputs, err)
- return nil, err
- }
- if err := call.Finish(&profiles); err != nil {
- vlog.Errorf("Finish(%v) failed: %v\n", &profiles, err)
- return nil, err
- }
+ var profile profile.Specification
+ client, err := r.NewClient()
+ if err != nil {
+ vlog.Errorf("NewClient() failed: %v", err)
+ return nil, err
+ }
+ defer client.Close()
+ server := // TODO
+ method := "Specification"
+ inputs := make([]interface{}, 0)
+ call, err := client.StartCall(server + "/" + name, method, inputs)
+ if err != nil {
+ vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server + "/" + name, method, inputs, err)
+ return nil, err
+ }
+ if err := call.Finish(&profiles); err != nil {
+ vlog.Errorf("Finish(%v) failed: %v\n", &profiles, err)
+ return nil, err
+ }
+ return &profile, nil
*/
- return &profile, nil
}
// getKnownProfiles gets a list of description for all publicly known
@@ -134,39 +145,51 @@
//
// TODO(jsimsa): Avoid retrieving the list of known profiles from a
// remote server if a recent cached copy exists.
-func getKnownProfiles() ([]profile.Specification, error) {
+func getKnownProfiles() ([]*profile.Specification, error) {
+ return []*profile.Specification{
+ {
+ Label: "linux-amd64",
+ Description: "",
+ Arch: build.AMD64,
+ OS: build.Linux,
+ Format: build.ELF,
+ },
+ // TODO(caprita): Add profiles for Mac, Pi, etc.
+ }, nil
+
// TODO(jsimsa): This function assumes the existence of a profile
// server from which a list of known profiles can be retrieved. The
// profile server is a work in progress. When it exists, the
// commented out code below should work.
- knownProfiles := make([]profile.Specification, 0)
+
/*
- client, err := r.NewClient()
- if err != nil {
- vlog.Errorf("NewClient() failed: %v\n", err)
- return nil, err
- }
- defer client.Close()
- server := // TODO
- method := "List"
- inputs := make([]interface{}, 0)
- call, err := client.StartCall(server, method, inputs)
- if err != nil {
- vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server, method, inputs, err)
- return nil, err
- }
- if err := call.Finish(&knownProfiles); err != nil {
- vlog.Errorf("Finish(&knownProfile) failed: %v\n", err)
- return nil, err
- }
+ knownProfiles := make([]profile.Specification, 0)
+ client, err := r.NewClient()
+ if err != nil {
+ vlog.Errorf("NewClient() failed: %v\n", err)
+ return nil, err
+ }
+ defer client.Close()
+ server := // TODO
+ method := "List"
+ inputs := make([]interface{}, 0)
+ call, err := client.StartCall(server, method, inputs)
+ if err != nil {
+ vlog.Errorf("StartCall(%s, %q, %v) failed: %v\n", server, method, inputs, err)
+ return nil, err
+ }
+ if err := call.Finish(&knownProfiles); err != nil {
+ vlog.Errorf("Finish(&knownProfile) failed: %v\n", err)
+ return nil, err
+ }
+ return knownProfiles, nil
*/
- return knownProfiles, nil
}
// matchProfiles inputs a profile that describes the host device and a
// set of publicly known profiles and outputs a device description that
// identifies the publicly known profiles supported by the host device.
-func matchProfiles(p *profile.Specification, known []profile.Specification) device.Description {
+func matchProfiles(p *profile.Specification, known []*profile.Specification) device.Description {
result := device.Description{Profiles: make(map[string]struct{})}
loop:
for _, profile := range known {
@@ -189,3 +212,29 @@
}
return result
}
+
+// describe returns a Description containing the profile that matches the
+// current device. It's declared as a variable so we can override it for
+// testing.
+var describe = func() (device.Description, error) {
+ empty := device.Description{}
+ deviceProfile, err := ComputeDeviceProfile()
+ if err != nil {
+ return empty, err
+ }
+ knownProfiles, err := getKnownProfiles()
+ if err != nil {
+ return empty, err
+ }
+ result := matchProfiles(deviceProfile, knownProfiles)
+ if len(result.Profiles) == 0 {
+ // For now, return "unknown" as the profile, if no known profile
+ // matches the device's profile.
+ //
+ // TODO(caprita): Get rid of this crutch once we have profiles
+ // defined for our supported systems; for now it helps us make
+ // the integration test work on e.g. Mac.
+ result.Profiles["unknown"] = struct{}{}
+ }
+ return result, nil
+}
diff --git a/services/mgmt/device/impl/proxy_invoker.go b/services/mgmt/device/impl/proxy_invoker.go
index 506d57f..9f82f88 100644
--- a/services/mgmt/device/impl/proxy_invoker.go
+++ b/services/mgmt/device/impl/proxy_invoker.go
@@ -17,19 +17,25 @@
//
// remote is the name of the remote object.
// access is the access tag require to access the object.
-// sigStub is used to get the signature of the remote object.
+// desc is used to determine the number of results for a given method.
+func newProxyInvoker(remote string, access access.Tag, desc []ipc.InterfaceDesc) *proxyInvoker {
+ methodNumResults := make(map[string]int)
+ for _, iface := range desc {
+ for _, method := range iface.Methods {
+ methodNumResults[method.Name] = len(method.OutArgs)
+ }
+ }
+ return &proxyInvoker{remote, access, methodNumResults}
+}
+
type proxyInvoker struct {
- remote string
- access access.Tag
- sigStub signatureStub
+ remote string
+ access access.Tag
+ methodNumResults map[string]int
}
var _ ipc.Invoker = (*proxyInvoker)(nil)
-type signatureStub interface {
- Signature(ipc.ServerContext) (ipc.ServiceSignature, error)
-}
-
func (p *proxyInvoker) Prepare(method string, numArgs int) (argptrs, tags []interface{}, err error) {
argptrs = make([]interface{}, numArgs)
for i, _ := range argptrs {
@@ -218,21 +224,15 @@
// numResults returns the number of result values for the given method.
func (p *proxyInvoker) numResults(method string) (int, error) {
- // TODO(toddw): Replace this mechanism when the new signature mechanism is
- // complete.
switch method {
case ipc.GlobMethod:
return 1, nil
case ipc.ReservedSignature, ipc.ReservedMethodSignature:
return 2, nil
}
- sig, err := p.sigStub.Signature(nil)
- if err != nil {
- return 0, err
- }
- m, ok := sig.Methods[method]
+ num, ok := p.methodNumResults[method]
if !ok {
return 0, fmt.Errorf("unknown method %q", method)
}
- return len(m.OutArgs), nil
+ return num, nil
}
diff --git a/services/mgmt/device/impl/proxy_invoker_test.go b/services/mgmt/device/impl/proxy_invoker_test.go
index 2da3bdc..2009a8c 100644
--- a/services/mgmt/device/impl/proxy_invoker_test.go
+++ b/services/mgmt/device/impl/proxy_invoker_test.go
@@ -53,7 +53,7 @@
disp := &proxyDispatcher{
runtime,
naming.JoinAddressName(eps1[0].String(), "__debug/stats"),
- stats.StatsServer(nil),
+ stats.StatsServer(nil).Describe__(),
}
if err := server2.ServeDispatcher("", disp); err != nil {
t.Fatalf("server2.Serve: %v", err)
@@ -87,15 +87,10 @@
type proxyDispatcher struct {
runtime veyron2.Runtime
remote string
- sigStub signatureStub
+ desc []ipc.InterfaceDesc
}
func (d *proxyDispatcher) Lookup(suffix string) (interface{}, security.Authorizer, error) {
vlog.Infof("LOOKUP(%s): remote .... %s", suffix, d.remote)
- invoker := &proxyInvoker{
- remote: naming.Join(d.remote, suffix),
- access: access.Debug,
- sigStub: d.sigStub,
- }
- return invoker, nil, nil
+ return newProxyInvoker(naming.Join(d.remote, suffix), access.Debug, d.desc), nil, nil
}
diff --git a/services/mgmt/device/impl/util.go b/services/mgmt/device/impl/util.go
index 50d892e..09fa70a 100644
--- a/services/mgmt/device/impl/util.go
+++ b/services/mgmt/device/impl/util.go
@@ -41,7 +41,15 @@
stub := repository.ApplicationClient(origin)
// TODO(jsimsa): Include logic that computes the set of supported
// profiles.
- profiles := []string{"test"}
+ profilesSet, err := describe()
+ if err != nil {
+ vlog.Errorf("Failed to obtain profile labels: %v", err)
+ return nil, verror2.Make(ErrOperationFailed, ctx)
+ }
+ var profiles []string
+ for label := range profilesSet.Profiles {
+ profiles = append(profiles, label)
+ }
envelope, err := stub.Match(ctx, profiles)
if err != nil {
vlog.Errorf("Match(%v) failed: %v", profiles, err)
diff --git a/services/mgmt/device/impl/util_test.go b/services/mgmt/device/impl/util_test.go
index dd072de..4d8be6d 100644
--- a/services/mgmt/device/impl/util_test.go
+++ b/services/mgmt/device/impl/util_test.go
@@ -45,8 +45,8 @@
// resolveExpectNotFound verifies that the given name is not in the mounttable.
func resolveExpectNotFound(t *testing.T, name string) {
- if results, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name); err == nil {
- t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) succeeded with results %v when it was expected to fail", name, results))
+ if me, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name); err == nil {
+ t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) succeeded with results %v when it was expected to fail", name, me.Names()))
} else if expectErr := naming.ErrNoSuchName.ID; !verror2.Is(err, expectErr) {
t.Fatalf(testutil.FormatLogLine(2, "Resolve(%v) failed with error %v, expected error ID %v", name, err, expectErr))
}
@@ -54,13 +54,13 @@
// resolve looks up the given name in the mounttable.
func resolve(t *testing.T, name string, replicas int) []string {
- results, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name)
+ me, err := veyron2.GetNamespace(globalCtx).Resolve(globalCtx, name)
if err != nil {
t.Fatalf("Resolve(%v) failed: %v", name, err)
}
filteredResults := []string{}
- for _, r := range results {
+ for _, r := range me.Names() {
if strings.Index(r, "@tcp") != -1 {
filteredResults = append(filteredResults, r)
}
diff --git a/services/mgmt/inithelper/main.go b/services/mgmt/inithelper/main.go
new file mode 100644
index 0000000..a6f3fb4
--- /dev/null
+++ b/services/mgmt/inithelper/main.go
@@ -0,0 +1,98 @@
+package main
+
+// TODO(caprita): The separation of responsibilities between root/non-root code
+// can be shifted away from root a bit more, by having the init daemon files
+// created as non-root and root just installs files and runs a specific set of
+// commands. Figure out if worth it. Also consider combining with suidhelper.
+// For now they're separate since we don't always need both at the same time.
+
+// TODO(caprita): Add unit test.
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "os"
+
+ "v.io/core/veyron/services/mgmt/sysinit"
+)
+
+func usage() {
+ const usage = `Usage:
+%s [flags] [command]
+
+ Flags:
+%s
+ Command:
+ print: prints the file that would be installed
+ install: installs the service
+ uninstall: uninstalls the service
+ start: starts the service
+ stop: stops the service
+`
+ var flagDefaults bytes.Buffer
+ flag.CommandLine.SetOutput(&flagDefaults)
+ flag.CommandLine.PrintDefaults()
+ flag.CommandLine.SetOutput(nil)
+ fmt.Fprintf(os.Stderr, usage, os.Args[0], flagDefaults.String())
+}
+
+func main() {
+ flag.Usage = usage
+ sdFlag := flag.String("service_description", "", "File containing a JSON-encoded sysinit.ServiceDescription object.")
+ systemFlag := flag.String("system", sysinit.InitSystem(), "System label, to select the appropriate sysinit mechanism.")
+ flag.Parse()
+ if *sdFlag == "" {
+ fmt.Fprintf(os.Stderr, "--service_description must be set.\n")
+ flag.Usage()
+ os.Exit(1)
+ }
+ if *systemFlag == "" {
+ fmt.Fprintf(os.Stderr, "--system must be set.\n")
+ flag.Usage()
+ os.Exit(1)
+ }
+ var sd sysinit.ServiceDescription
+ if err := sd.LoadFrom(*sdFlag); err != nil {
+ fmt.Fprintf(os.Stderr, "LoadFrom(%v) failed: %v\n", *sdFlag, err)
+ os.Exit(2)
+ }
+ si := sysinit.New(*systemFlag, &sd)
+ args := flag.Args()
+ if len(args) != 1 {
+ fmt.Fprintf(os.Stderr, "Command must be specified.\n")
+ flag.Usage()
+ os.Exit(1)
+ }
+ switch args[0] {
+ case "print":
+ if err := si.Print(); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to print %v: %s\n", si, err)
+ os.Exit(2)
+ }
+ case "install":
+ if err := si.Install(); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to install %v: %s\n", si, err)
+ os.Exit(2)
+ }
+ case "uninstall":
+ if err := si.Uninstall(); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to uninstall %v: %s\n", si, err)
+ os.Exit(2)
+ }
+ case "start":
+ if err := si.Start(); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to start %v: %s\n", si, err)
+ os.Exit(2)
+ }
+ case "stop":
+ if err := si.Stop(); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to stop %v: %s\n", si, err)
+ os.Exit(2)
+ }
+ default:
+ fmt.Fprintf(os.Stderr, "Invalid command: %s\n", args[0])
+ flag.Usage()
+ os.Exit(1)
+ }
+}
diff --git a/services/mgmt/lib/acls/aclaccess.go b/services/mgmt/lib/acls/aclaccess.go
new file mode 100644
index 0000000..07e63a6
--- /dev/null
+++ b/services/mgmt/lib/acls/aclaccess.go
@@ -0,0 +1,157 @@
+// Package acls provides a library to assist servers implementing
+// GetACL/SetACL functions where there are path-specific ACLs
+// stored individually in files in the filesystem.
+// TODO(rjkroege): Add unit tests.
+package acls
+
+import (
+ "io/ioutil"
+ "os"
+ "path"
+ "sync"
+
+ "v.io/core/veyron2/security"
+ "v.io/core/veyron2/services/security/access"
+ verror "v.io/core/veyron2/verror2"
+ "v.io/core/veyron2/vlog"
+
+ "v.io/core/veyron/security/serialization"
+)
+
+const (
+ pkgPath = "v.io/core/veyron/services/mgmt/lib/acls"
+ sigName = "signature"
+ aclName = "data"
+)
+
+var (
+ ErrOperationFailed = verror.Register(pkgPath+".OperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
+)
+
+// Locks provides a mutex lock for each acl file path.
+type Locks struct {
+ pthlks map[string]*sync.Mutex
+ lk sync.Mutex
+}
+
+// NewLocks creates a new instance of the lock map.
+func NewLocks() *Locks {
+ return &Locks{pthlks: make(map[string]*sync.Mutex)}
+}
+
+// GetPathACL returns the TaggedACLMap from the data file in dir.
+func (locks Locks) GetPathACL(principal security.Principal, dir string) (access.TaggedACLMap, string, error) {
+ aclpath := path.Join(dir, aclName)
+ sigpath := path.Join(dir, sigName)
+ defer locks.lockPath(dir)()
+ return getCore(principal, aclpath, sigpath)
+}
+
+// TODO(rjkroege): Improve lock handling.
+func (locks Locks) lockPath(dir string) func() {
+ locks.lk.Lock()
+ lck, contains := locks.pthlks[dir]
+ if !contains {
+ lck = new(sync.Mutex)
+ locks.pthlks[dir] = lck
+ }
+ locks.lk.Unlock()
+ lck.Lock()
+ return lck.Unlock
+}
+
+func getCore(principal security.Principal, aclpath, sigpath string) (access.TaggedACLMap, string, error) {
+ f, err := os.Open(aclpath)
+ if err != nil {
+ // This path is rarely a fatal error so log informationally only.
+ vlog.VI(2).Infof("os.Open(%s) failed: %v", aclpath, err)
+ return nil, "", err
+ }
+ defer f.Close()
+
+ s, err := os.Open(sigpath)
+ if err != nil {
+ vlog.Errorf("Signatures for ACLs are required: %s unavailable: %v", aclpath, err)
+ return nil, "", verror.Make(ErrOperationFailed, nil)
+ }
+ defer s.Close()
+
+ // read and verify the signature of the acl file
+ vf, err := serialization.NewVerifyingReader(f, s, principal.PublicKey())
+ if err != nil {
+ vlog.Errorf("NewVerifyingReader() failed: %v", err)
+ return nil, "", verror.Make(ErrOperationFailed, nil)
+ }
+
+ acl, err := access.ReadTaggedACLMap(vf)
+ if err != nil {
+ vlog.Errorf("ReadTaggedACLMap(%s) failed: %v", aclpath, err)
+ return nil, "", err
+ }
+ etag, err := ComputeEtag(acl)
+ if err != nil {
+ vlog.Errorf("acls.ComputeEtag failed: %v", err)
+ return nil, "", err
+ }
+ return acl, etag, nil
+}
+
+// SetPathACL writes the specified TaggedACLMap to the provided
+// directory with enforcement of etag synchronization mechanism and
+// locking.
+func (locks Locks) SetPathACL(principal security.Principal, dir string, acl access.TaggedACLMap, etag string) error {
+ aclpath := path.Join(dir, aclName)
+ sigpath := path.Join(dir, sigName)
+ defer locks.lockPath(dir)()
+ _, oetag, err := getCore(principal, aclpath, sigpath)
+ if err != nil && !os.IsNotExist(err) {
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ if len(etag) > 0 && etag != oetag {
+ return verror.Make(access.BadEtag, nil, etag, oetag)
+ }
+ return write(principal, aclpath, sigpath, dir, acl)
+}
+
+// write writes the specified TaggedACLMap to the aclFile with a
+// signature in sigFile.
+func write(principal security.Principal, aclFile, sigFile, dir string, acl access.TaggedACLMap) error {
+ // Create dir directory if it does not exist
+ os.MkdirAll(dir, os.FileMode(0700))
+ // Save the object to temporary data and signature files, and then move
+ // those files to the actual data and signature file.
+ data, err := ioutil.TempFile(dir, aclName)
+ if err != nil {
+ vlog.Errorf("Failed to open tmpfile data:%v", err)
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ defer os.Remove(data.Name())
+ sig, err := ioutil.TempFile(dir, sigName)
+ if err != nil {
+ vlog.Errorf("Failed to open tmpfile sig:%v", err)
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ defer os.Remove(sig.Name())
+ writer, err := serialization.NewSigningWriteCloser(data, sig, principal, nil)
+ if err != nil {
+ vlog.Errorf("Failed to create NewSigningWriteCloser:%v", err)
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ if err = acl.WriteTo(writer); err != nil {
+ vlog.Errorf("Failed to SaveACL:%v", err)
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ if err = writer.Close(); err != nil {
+ vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ if err := os.Rename(data.Name(), aclFile); err != nil {
+ vlog.Errorf("os.Rename() failed:%v", err)
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ if err := os.Rename(sig.Name(), sigFile); err != nil {
+ vlog.Errorf("os.Rename() failed:%v", err)
+ return verror.Make(ErrOperationFailed, nil)
+ }
+ return nil
+}
diff --git a/services/mgmt/profile/profile.vdl b/services/mgmt/profile/profile.vdl
index 1e12ec8..63240ec 100644
--- a/services/mgmt/profile/profile.vdl
+++ b/services/mgmt/profile/profile.vdl
@@ -17,17 +17,17 @@
// Specification is how we represent a profile internally. It should
// provide enough information to allow matching of binaries to devices.
type Specification struct {
- // Arch is the target hardware architecture of the profile.
- Arch build.Architecture
+ // Label is a human-friendly concise label for the profile,
+ // e.g. "linux-media".
+ Label string
// Description is a human-friendly description of the profile.
Description string
+ // Arch is the target hardware architecture of the profile.
+ Arch build.Architecture
+ // OS is the target operating system of the profile.
+ OS build.OperatingSystem
// Format is the file format supported by the profile.
Format build.Format
// Libraries is a set of libraries the profile requires.
Libraries set[Library]
- // Label is a human-friendly concise label for the profile,
- // e.g. "linux-media".
- Label string
- // OS is the target operating system of the profile.
- OS build.OperatingSystem
}
diff --git a/services/mgmt/profile/profile.vdl.go b/services/mgmt/profile/profile.vdl.go
index 8b50064..6db310d 100644
--- a/services/mgmt/profile/profile.vdl.go
+++ b/services/mgmt/profile/profile.vdl.go
@@ -30,19 +30,19 @@
// Specification is how we represent a profile internally. It should
// provide enough information to allow matching of binaries to devices.
type Specification struct {
- // Arch is the target hardware architecture of the profile.
- Arch build.Architecture
+ // Label is a human-friendly concise label for the profile,
+ // e.g. "linux-media".
+ Label string
// Description is a human-friendly description of the profile.
Description string
+ // Arch is the target hardware architecture of the profile.
+ Arch build.Architecture
+ // OS is the target operating system of the profile.
+ OS build.OperatingSystem
// Format is the file format supported by the profile.
Format build.Format
// Libraries is a set of libraries the profile requires.
Libraries map[Library]struct{}
- // Label is a human-friendly concise label for the profile,
- // e.g. "linux-media".
- Label string
- // OS is the target operating system of the profile.
- OS build.OperatingSystem
}
func (Specification) __VDLReflect(struct {
diff --git a/services/mgmt/profile/profiled/test.sh b/services/mgmt/profile/profiled/test.sh
index 756916d..685dfee 100755
--- a/services/mgmt/profile/profiled/test.sh
+++ b/services/mgmt/profile/profiled/test.sh
@@ -55,7 +55,7 @@
OUTPUT=$(shell::tmp_file)
"${PROFILE_BIN}" specification "${PROFILE}" | tee "${OUTPUT}" || shell_test::fail "line ${LINENO}: 'spec' failed"
GOT=$(cat "${OUTPUT}")
- WANT='profile.Specification{Arch:"amd64", Description:"Example profile to test the profile manager implementation.", Format:"ELF", Libraries:map[profile.Library]struct {}{profile.Library{Name:"foo", MajorVersion:"1", MinorVersion:"0"}:struct {}{}}, Label:"example", OS:"linux"}'
+ WANT='profile.Specification{Label:"example", Description:"Example profile to test the profile manager implementation.", Arch:"amd64", OS:"linux", Format:"ELF", Libraries:map[profile.Library]struct {}{profile.Library{Name:"foo", MajorVersion:"1", MinorVersion:"0"}:struct {}{}}}'
shell_test::assert_eq "${GOT}" "${WANT}" "${LINENO}"
# Remove the profile.
diff --git a/services/mgmt/repository/repository.vdl.go b/services/mgmt/repository/repository.vdl.go
index 75842f2..b320b6c 100644
--- a/services/mgmt/repository/repository.vdl.go
+++ b/services/mgmt/repository/repository.vdl.go
@@ -19,14 +19,8 @@
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
__vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// ApplicationClientMethods is the client interface
// containing Application methods.
//
@@ -112,17 +106,6 @@
return
}
-func (c implApplicationClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// ApplicationServerMethods is the interface a server writer
// implements for Application.
//
@@ -166,8 +149,6 @@
ApplicationServerStubMethods
// Describe the Application interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// ApplicationServer returns a server stub for Application.
@@ -248,97 +229,6 @@
},
}
-func (s implApplicationServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Put"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "Profiles", Type: 61},
- {Name: "Envelope", Type: 66},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 67},
- },
- }
- result.Methods["Remove"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "Profile", Type: 3},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 67},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.MapType{Key: 0x3, Elem: 0x3, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x3, Name: "Title"},
- __wiretype.FieldType{Type: 0x3d, Name: "Args"},
- __wiretype.FieldType{Type: 0x3, Name: "Binary"},
- __wiretype.FieldType{Type: 0x3d, Name: "Env"},
- __wiretype.FieldType{Type: 0x41, Name: "Packages"},
- },
- "v.io/core/veyron2/services/mgmt/application.Envelope", []string(nil)},
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
- var ss __ipc.ServiceSignature
- var firstAdded int
- ss, _ = s.ApplicationServerStub.Signature(ctx)
- firstAdded = len(result.TypeDefs)
- for k, v := range ss.Methods {
- for i, _ := range v.InArgs {
- if v.InArgs[i].Type >= __wiretype.TypeIDFirst {
- v.InArgs[i].Type += __wiretype.TypeID(firstAdded)
- }
- }
- for i, _ := range v.OutArgs {
- if v.OutArgs[i].Type >= __wiretype.TypeIDFirst {
- v.OutArgs[i].Type += __wiretype.TypeID(firstAdded)
- }
- }
- if v.InStream >= __wiretype.TypeIDFirst {
- v.InStream += __wiretype.TypeID(firstAdded)
- }
- if v.OutStream >= __wiretype.TypeIDFirst {
- v.OutStream += __wiretype.TypeID(firstAdded)
- }
- result.Methods[k] = v
- }
- //TODO(bprosnitz) combine type definitions from embeded interfaces in a way that doesn't cause duplication.
- for _, d := range ss.TypeDefs {
- switch wt := d.(type) {
- case __wiretype.SliceType:
- if wt.Elem >= __wiretype.TypeIDFirst {
- wt.Elem += __wiretype.TypeID(firstAdded)
- }
- d = wt
- case __wiretype.ArrayType:
- if wt.Elem >= __wiretype.TypeIDFirst {
- wt.Elem += __wiretype.TypeID(firstAdded)
- }
- d = wt
- case __wiretype.MapType:
- if wt.Key >= __wiretype.TypeIDFirst {
- wt.Key += __wiretype.TypeID(firstAdded)
- }
- if wt.Elem >= __wiretype.TypeIDFirst {
- wt.Elem += __wiretype.TypeID(firstAdded)
- }
- d = wt
- case __wiretype.StructType:
- for i, fld := range wt.Fields {
- if fld.Type >= __wiretype.TypeIDFirst {
- wt.Fields[i].Type += __wiretype.TypeID(firstAdded)
- }
- }
- d = wt
- // NOTE: other types are missing, but we are upgrading anyways.
- }
- result.TypeDefs = append(result.TypeDefs, d)
- }
-
- return result, nil
-}
-
// ProfileClientMethods is the client interface
// containing Profile methods.
//
@@ -425,17 +315,6 @@
return
}
-func (c implProfileClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// ProfileServerMethods is the interface a server writer
// implements for Profile.
//
@@ -469,8 +348,6 @@
ProfileServerStubMethods
// Describe the Profile interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// ProfileServer returns a server stub for Profile.
@@ -559,106 +436,3 @@
},
},
}
-
-func (s implProfileServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Put"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "Specification", Type: 70},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 71},
- },
- }
- result.Methods["Remove"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 71},
- },
- }
- result.Methods["Specification"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 70},
- {Name: "", Type: 71},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/services/mgmt/build.Architecture", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/services/mgmt/build.Format", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x3, Name: "Name"},
- __wiretype.FieldType{Type: 0x3, Name: "MajorVersion"},
- __wiretype.FieldType{Type: 0x3, Name: "MinorVersion"},
- },
- "v.io/core/veyron/services/mgmt/profile.Library", []string(nil)},
- __wiretype.MapType{Key: 0x43, Elem: 0x2, Name: "", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/services/mgmt/build.OperatingSystem", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x41, Name: "Arch"},
- __wiretype.FieldType{Type: 0x3, Name: "Description"},
- __wiretype.FieldType{Type: 0x42, Name: "Format"},
- __wiretype.FieldType{Type: 0x44, Name: "Libraries"},
- __wiretype.FieldType{Type: 0x3, Name: "Label"},
- __wiretype.FieldType{Type: 0x45, Name: "OS"},
- },
- "v.io/core/veyron/services/mgmt/profile.Specification", []string(nil)},
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
- var ss __ipc.ServiceSignature
- var firstAdded int
- ss, _ = s.ProfileServerStub.Signature(ctx)
- firstAdded = len(result.TypeDefs)
- for k, v := range ss.Methods {
- for i, _ := range v.InArgs {
- if v.InArgs[i].Type >= __wiretype.TypeIDFirst {
- v.InArgs[i].Type += __wiretype.TypeID(firstAdded)
- }
- }
- for i, _ := range v.OutArgs {
- if v.OutArgs[i].Type >= __wiretype.TypeIDFirst {
- v.OutArgs[i].Type += __wiretype.TypeID(firstAdded)
- }
- }
- if v.InStream >= __wiretype.TypeIDFirst {
- v.InStream += __wiretype.TypeID(firstAdded)
- }
- if v.OutStream >= __wiretype.TypeIDFirst {
- v.OutStream += __wiretype.TypeID(firstAdded)
- }
- result.Methods[k] = v
- }
- //TODO(bprosnitz) combine type definitions from embeded interfaces in a way that doesn't cause duplication.
- for _, d := range ss.TypeDefs {
- switch wt := d.(type) {
- case __wiretype.SliceType:
- if wt.Elem >= __wiretype.TypeIDFirst {
- wt.Elem += __wiretype.TypeID(firstAdded)
- }
- d = wt
- case __wiretype.ArrayType:
- if wt.Elem >= __wiretype.TypeIDFirst {
- wt.Elem += __wiretype.TypeID(firstAdded)
- }
- d = wt
- case __wiretype.MapType:
- if wt.Key >= __wiretype.TypeIDFirst {
- wt.Key += __wiretype.TypeID(firstAdded)
- }
- if wt.Elem >= __wiretype.TypeIDFirst {
- wt.Elem += __wiretype.TypeID(firstAdded)
- }
- d = wt
- case __wiretype.StructType:
- for i, fld := range wt.Fields {
- if fld.Type >= __wiretype.TypeIDFirst {
- wt.Fields[i].Type += __wiretype.TypeID(firstAdded)
- }
- }
- d = wt
- // NOTE: other types are missing, but we are upgrading anyways.
- }
- result.TypeDefs = append(result.TypeDefs, d)
- }
-
- return result, nil
-}
diff --git a/services/mgmt/sysinit/init_darwin.go b/services/mgmt/sysinit/init_darwin.go
new file mode 100644
index 0000000..e56e07f
--- /dev/null
+++ b/services/mgmt/sysinit/init_darwin.go
@@ -0,0 +1,11 @@
+package sysinit
+
+func InitSystem() string {
+ panic("Darwin not supported yet")
+ return ""
+}
+
+func New(system string, sd *ServiceDescription) InstallSystemInit {
+ panic("Darwin not supported yet")
+ return nil
+}
diff --git a/services/mgmt/sysinit/init_linux.go b/services/mgmt/sysinit/init_linux.go
index beacc8e..e6da324 100644
--- a/services/mgmt/sysinit/init_linux.go
+++ b/services/mgmt/sysinit/init_linux.go
@@ -1,6 +1,3 @@
-//
-// +build linux
-
package sysinit
// TODO(cnicolaou): will need to figure out a simple of way of handling the
@@ -13,22 +10,35 @@
"log"
"os"
"os/exec"
+ "syscall"
)
// action is a var so we can override it for testing.
var action = func(command, action, service string) error {
- output, err := exec.Command(command, action, service).CombinedOutput()
- log.Printf("%s output: for %s %s: %s\n",
- command, action, service, output)
+ cmd := exec.Command(command, action, service)
+ if os.Geteuid() == 0 && os.Getuid() > 0 {
+ // Set uid to root (e.g. when running from a suid binary),
+ // otherwise initctl doesn't work.
+ sysProcAttr := new(syscall.SysProcAttr)
+ sysProcAttr.Credential = new(syscall.Credential)
+ sysProcAttr.Credential.Gid = uint32(0)
+ sysProcAttr.Credential.Uid = uint32(0)
+ cmd.SysProcAttr = sysProcAttr
+ }
+ // Clear env. In particular, initctl doesn't like USER being set to
+ // something other than root.
+ cmd.Env = []string{}
+ output, err := cmd.CombinedOutput()
+ log.Printf("%s output: for %s %s: %s\n", command, action, service, output)
return err
}
var (
upstartDir = "/etc/init"
+ upstartBin = "/sbin/initctl"
systemdDir = "/usr/lib/systemd/system"
systemdTmpFileDir = "/usr/lib/tmpfiles.d"
dockerDir = "/home/veyron/init"
- logDir = "/var/log/veyron"
)
// InitSystem attempts to determine what kind of init system is in use on
@@ -46,7 +56,7 @@
if fi, err := os.Stat("/home/veyron/init"); err == nil && fi.Mode().IsDir() {
return "docker"
}
- if fi, err := os.Stat("/sbin/initctl"); err == nil {
+ if fi, err := os.Stat(upstartBin); err == nil {
if (fi.Mode() & os.ModePerm & 0100) != 0 {
return "upstart"
}
@@ -64,6 +74,21 @@
return ""
}
+// New returns the appropriate implementation of InstallSystemInit for the
+// underlying system.
+func New(system string, sd *ServiceDescription) InstallSystemInit {
+ switch system {
+ case "docker":
+ return (*DockerService)(sd)
+ case "upstart":
+ return (*UpstartService)(sd)
+ case "systemd":
+ return (*SystemdService)(sd)
+ default:
+ return nil
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Upstart support
@@ -101,19 +126,13 @@
script
set -e
- # setuid {{.User}} - causes the subsequent exec to fail for unknown reasons.
echo '{{.Service}} starting'
- exec{{range $cmd := .Command}} {{$cmd}}{{end}}
+ exec sudo -u {{.User}} {{range $cmd := .Command}} {{$cmd}}{{end}}
end script
`
-// Install implements the InstallSystemInit method.
+// Implements the InstallSystemInit method.
func (u *UpstartService) Install() error {
- if u.Setup != nil {
- if err := u.Setup((*ServiceDescription)(u)); err != nil {
- return err
- }
- }
file := fmt.Sprintf("%s/%s.conf", upstartDir, u.Service)
return (*ServiceDescription)(u).writeTemplate(upstartTemplate, file)
}
@@ -123,23 +142,24 @@
return (*ServiceDescription)(u).writeTemplate(upstartTemplate, "")
}
-// Uninstall implements the InstallSystemInit method.
+// Implements the InstallSystemInit method.
func (u *UpstartService) Uninstall() error {
- if err := u.Stop(); err != nil {
- return err
- }
+ // For now, ignore any errors returned by Stop, since Stop complains
+ // when there is no instance to stop.
+ // TODO(caprita): Only call Stop if there are running instances.
+ u.Stop()
file := fmt.Sprintf("%s/%s.conf", upstartDir, u.Service)
return os.Remove(file)
}
// Start implements the InstallSystemInit method.
func (u *UpstartService) Start() error {
- return action("initctl", "start", u.Service)
+ return action(upstartBin, "start", u.Service)
}
// Stop implements the InstallSystemInit method.
func (u *UpstartService) Stop() error {
- return action("initctl", "stop", u.Service)
+ return action(upstartBin, "stop", u.Service)
}
///////////////////////////////////////////////////////////////////////////////
@@ -174,11 +194,6 @@
// Install implements the InstallSystemInit method.
func (s *SystemdService) Install() error {
- if s.Setup != nil {
- if err := s.Setup((*ServiceDescription)(s)); err != nil {
- return err
- }
- }
file := fmt.Sprintf("%s/%s.service", systemdDir, s.Service)
if err := (*ServiceDescription)(s).writeTemplate(systemdTemplate, file); err != nil {
return err
@@ -253,11 +268,6 @@
// Install implements the InstallSystemInit method.
func (s *DockerService) Install() error {
- if s.Setup != nil {
- if err := s.Setup((*ServiceDescription)(s)); err != nil {
- return err
- }
- }
file := fmt.Sprintf("%s/%s.sh", dockerDir, s.Service)
if err := (*ServiceDescription)(s).writeTemplate(dockerTemplate, file); err != nil {
return err
diff --git a/services/mgmt/sysinit/linux_test.go b/services/mgmt/sysinit/linux_test.go
index a926229..d21634e 100644
--- a/services/mgmt/sysinit/linux_test.go
+++ b/services/mgmt/sysinit/linux_test.go
@@ -30,23 +30,15 @@
}()
defer os.RemoveAll(upstartDir)
- serviceName := ""
u := &UpstartService{
Service: "tester",
Description: "my test",
Binary: "/bin/echo",
Command: []string{"/bin/echo -n foo"},
- Setup: func(s *ServiceDescription) error {
- serviceName = s.Service
- return nil
- },
}
if err := u.Install(); err != nil {
t.Fatalf("unexpected error: %s", err)
}
- if serviceName != "tester" {
- t.Errorf("Setup was not called")
- }
rc, _ := os.Open(upstartDir + "/tester.conf")
lines := bufio.NewScanner(rc)
lines.Scan()
diff --git a/services/mgmt/sysinit/service_description.go b/services/mgmt/sysinit/service_description.go
index 925c8c1..ba1150d 100644
--- a/services/mgmt/sysinit/service_description.go
+++ b/services/mgmt/sysinit/service_description.go
@@ -1,6 +1,9 @@
package sysinit
import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
"os"
"text/template"
"time"
@@ -11,14 +14,37 @@
// ServiceDescription is a generic service description that represents the
// common configuration details for specific systems.
type ServiceDescription struct {
- Service string // The name of the Service
- Description string // A description of the Service
- Environment map[string]string // Environment variables needed by the service
- Binary string // The binary to be run
- Command []string // The script/binary and command line options to use to start/stop the binary
- User string // The username this service is to run as
- Setup func(*ServiceDescription) error // Optional function to run before install.
- SetupParams map[string]string // Params for the Setup function.
+ Service string // The name of the Service
+ Description string // A description of the Service
+ Environment map[string]string // Environment variables needed by the service
+ Binary string // The binary to be run
+ Command []string // The script/binary and command line options to use to start/stop the binary
+ User string // The username this service is to run as
+}
+
+// TODO(caprita): Unit test.
+
+// SaveTo serializes the service description object to a file.
+func (sd *ServiceDescription) SaveTo(fName string) error {
+ jsonSD, err := json.Marshal(sd)
+ if err != nil {
+ return fmt.Errorf("Marshal(%v) failed: %v", sd, err)
+ }
+ if err := ioutil.WriteFile(fName, jsonSD, 0600); err != nil {
+ return fmt.Errorf("WriteFile(%v) failed: %v", fName, err)
+ }
+ return nil
+}
+
+// LoadFrom de-serializes the service description object from a file created by
+// SaveTo.
+func (sd *ServiceDescription) LoadFrom(fName string) error {
+ if sdBytes, err := ioutil.ReadFile(fName); err != nil {
+ return fmt.Errorf("ReadFile(%v) failed: %v", fName, err)
+ } else if err := json.Unmarshal(sdBytes, sd); err != nil {
+ return fmt.Errorf("Unmarshal(%v) failed: %v", sdBytes, err)
+ }
+ return nil
}
func (sd *ServiceDescription) writeTemplate(templateContents, file string) error {
diff --git a/services/mounttable/lib/collection_test_interface.vdl.go b/services/mounttable/lib/collection_test_interface.vdl.go
index 621160f..612f212 100644
--- a/services/mounttable/lib/collection_test_interface.vdl.go
+++ b/services/mounttable/lib/collection_test_interface.vdl.go
@@ -8,15 +8,8 @@
__veyron2 "v.io/core/veyron2"
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
- __vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// CollectionClientMethods is the client interface
// containing Collection methods.
type CollectionClientMethods interface {
@@ -81,17 +74,6 @@
return
}
-func (c implCollectionClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// CollectionServerMethods is the interface a server writer
// implements for Collection.
type CollectionServerMethods interface {
@@ -116,8 +98,6 @@
CollectionServerStubMethods
// Describe the Collection interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// CollectionServer returns a server stub for Collection.
@@ -187,29 +167,3 @@
},
},
}
-
-func (s implCollectionServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Export"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "Val", Type: 3},
- {Name: "Overwrite", Type: 2},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
- }
- result.Methods["Lookup"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 67},
- {Name: "", Type: 65},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}}
-
- return result, nil
-}
diff --git a/services/mounttable/lib/mounttable.go b/services/mounttable/lib/mounttable.go
index 335aa11..9280527 100644
--- a/services/mounttable/lib/mounttable.go
+++ b/services/mounttable/lib/mounttable.go
@@ -371,28 +371,13 @@
// ResolveStep returns the next server in a resolution, the name remaining below that server,
// and whether or not that server is another mount table.
-func (ms *mountContext) ResolveStep(ctx ipc.ServerContext) (servers []naming.VDLMountedServer, suffix string, err error) {
- vlog.VI(2).Infof("ResolveStep %q", ms.name)
- mt := ms.mt
- // Find the next mount point for the name.
- n, elems, err := mt.findMountPoint(ctx, ms.elems)
- if err != nil {
- return nil, "", err
- }
- if n == nil {
- if len(ms.elems) == 0 {
- return nil, ms.name, verror2.Make(naming.ErrNoSuchNameRoot, ctx.Context(), ms.name)
- }
- return nil, ms.name, verror2.Make(naming.ErrNoSuchName, ctx.Context(), ms.name)
- }
- n.parent.Unlock()
- defer n.Unlock()
- return n.mount.servers.copyToSlice(), strings.Join(elems, "/"), nil
+func (ms *mountContext) ResolveStepX(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
+ return ms.ResolveStep(ctx)
}
-// ResolveStepX returns the next server in a resolution in the form of a MountEntry. The name
+// ResolveStep returns the next server in a resolution in the form of a MountEntry. The name
// in the mount entry is the name relative to the server's root.
-func (ms *mountContext) ResolveStepX(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
+func (ms *mountContext) ResolveStep(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
vlog.VI(2).Infof("ResolveStep %q", ms.name)
mt := ms.mt
// Find the next mount point for the name.
diff --git a/services/mounttable/lib/mounttable_test.go b/services/mounttable/lib/mounttable_test.go
index ba228b8..85cb3ff 100644
--- a/services/mounttable/lib/mounttable_test.go
+++ b/services/mounttable/lib/mounttable_test.go
@@ -185,7 +185,7 @@
func resolve(ctx *context.T, name string) (string, error) {
// Resolve the name one level.
client := veyron2.GetClient(ctx)
- call, err := client.StartCall(ctx, name, "ResolveStepX", nil, options.NoResolve{})
+ call, err := client.StartCall(ctx, name, "ResolveStep", nil, options.NoResolve{})
if err != nil {
return "", err
}
diff --git a/services/mounttable/lib/neighborhood.go b/services/mounttable/lib/neighborhood.go
index 32e6193..0f9103e 100644
--- a/services/mounttable/lib/neighborhood.go
+++ b/services/mounttable/lib/neighborhood.go
@@ -206,25 +206,13 @@
return neighbors
}
-// ResolveStep implements ResolveStep
-func (ns *neighborhoodService) ResolveStep(ctx ipc.ServerContext) (servers []naming.VDLMountedServer, suffix string, err error) {
- nh := ns.nh
- vlog.VI(2).Infof("ResolveStep %v\n", ns.elems)
- if len(ns.elems) == 0 {
- //nothing can be mounted at the root
- return nil, "", verror.Make(naming.ErrNoSuchNameRoot, ctx.Context(), ns.elems)
- }
-
- // We can only resolve the first element and it always refers to a mount table (for now).
- neighbor := nh.neighbor(ns.elems[0])
- if neighbor == nil {
- return nil, "", verror.Make(naming.ErrNoSuchName, ctx.Context(), ns.elems)
- }
- return neighbor, naming.Join(ns.elems[1:]...), nil
-}
-
// ResolveStepX implements ResolveStepX
func (ns *neighborhoodService) ResolveStepX(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
+ return ns.ResolveStep(ctx)
+}
+
+// ResolveStep implements ResolveStep
+func (ns *neighborhoodService) ResolveStep(ctx ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
nh := ns.nh
vlog.VI(2).Infof("ResolveStep %v\n", ns.elems)
if len(ns.elems) == 0 {
diff --git a/services/mounttable/lib/neighborhood_test.go b/services/mounttable/lib/neighborhood_test.go
index 7b48e53..6f197d6 100644
--- a/services/mounttable/lib/neighborhood_test.go
+++ b/services/mounttable/lib/neighborhood_test.go
@@ -83,13 +83,13 @@
client := veyron2.GetClient(rootCtx)
name := naming.JoinAddressName(estr, serverName+"/"+expectedSuffix)
- call, cerr := client.StartCall(rootCtx, name, "ResolveStepX", nil, options.NoResolve{})
+ call, cerr := client.StartCall(rootCtx, name, "ResolveStep", nil, options.NoResolve{})
if cerr != nil {
- boom(t, "ResolveStepX.StartCall: %s", cerr)
+ boom(t, "ResolveStep.StartCall: %s", cerr)
}
var entry naming.VDLMountEntry
if cerr = call.Finish(&entry, &err); cerr != nil {
- boom(t, "ResolveStepX: %s", cerr)
+ boom(t, "ResolveStep: %s", cerr)
}
// Resolution returned something. Make sure its correct.
diff --git a/services/security/discharger.vdl.go b/services/security/discharger.vdl.go
index c98b9b6..46805eb 100644
--- a/services/security/discharger.vdl.go
+++ b/services/security/discharger.vdl.go
@@ -11,14 +11,8 @@
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
__vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
// DischargerClientMethods is the client interface
// containing Discharger methods.
//
@@ -75,17 +69,6 @@
return
}
-func (c implDischargerClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
- err = ierr
- }
- return
-}
-
// DischargerServerMethods is the interface a server writer
// implements for Discharger.
//
@@ -113,8 +96,6 @@
DischargerServerStubMethods
// Describe the Discharger interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// DischargerServer returns a server stub for Discharger.
@@ -174,30 +155,3 @@
},
},
}
-
-func (s implDischargerServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["Discharge"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "Caveat", Type: 65},
- {Name: "Impetus", Type: 69},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "Discharge", Type: 65},
- {Name: "err", Type: 70},
- },
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "anydata", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x3, Name: "v.io/core/veyron2/security.BlessingPattern", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x41, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x43, Name: "Server"},
- __wiretype.FieldType{Type: 0x3, Name: "Method"},
- __wiretype.FieldType{Type: 0x44, Name: "Arguments"},
- },
- "v.io/core/veyron2/security.DischargeImpetus", []string(nil)},
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}}
-
- return result, nil
-}
diff --git a/tools/mgmt/device/devicex b/tools/mgmt/device/devicex
index 813d842..17fc8ea 100755
--- a/tools/mgmt/device/devicex
+++ b/tools/mgmt/device/devicex
@@ -29,7 +29,7 @@
echo "VANADIUM_DEVICE_DIR=<installation dir> ./devicex stop"
}
-readonly BIN_NAMES=(deviced suidhelper agentd)
+readonly BIN_NAMES=(deviced suidhelper agentd inithelper)
###############################################################################
# Copies one binary from source to destination.
@@ -153,25 +153,31 @@
echo "Binaries are in ${BIN_INSTALL}."
# Set up the suidhelper.
- echo "Configuring suidhelper ..."
- local -r SETUID_SCRIPT="${BIN_INSTALL}/suidhelper"
+ echo "Configuring helpers ..."
local SINGLE_USER=false
+ local INIT_MODE=false
for ARG in $*; do
if [[ ${ARG} = "--" ]]; then
break
- elif [[ ${ARG} = "--single_user" ]]; then
+ elif [[ ${ARG} = "--single_user" || ${ARG} = "--single_user=true" ]]; then
SINGLE_USER=true
- break
+ elif [[ ${ARG} = "--init_mode" || ${ARG} = "--init_mode=true" ]]; then
+ INIT_MODE=true
fi
done
+ local -r SETUID_SCRIPT="${BIN_INSTALL}/suidhelper"
if [[ ${SINGLE_USER} == false ]]; then
sudo bash -c "chown root:root \"${SETUID_SCRIPT}\"; chmod 4551 \"${SETUID_SCRIPT}\""
fi
- echo "Suidhelper configured."
+ local -r INIT_SCRIPT="${BIN_INSTALL}/inithelper"
+ if [[ ${INIT_MODE} == true ]]; then
+ sudo bash -c "chown root:root \"${INIT_SCRIPT}\"; chmod 4551 \"${INIT_SCRIPT}\""
+ fi
+ echo "Helpers configured."
# Install the device manager.
echo "Installing device manager under ${VANADIUM_DEVICE_DIR} ..."
- "${BIN_INSTALL}/deviced" install --suid_helper="${SETUID_SCRIPT}" --agent="${BIN_INSTALL}/agentd" "$@"
+ "${BIN_INSTALL}/deviced" install --suid_helper="${SETUID_SCRIPT}" --agent="${BIN_INSTALL}/agentd" --init_helper="${INIT_SCRIPT}" "$@"
echo "Device manager installed."
}
diff --git a/tools/mgmt/device/impl.go b/tools/mgmt/device/impl.go
index fced994..9a6aaf9 100644
--- a/tools/mgmt/device/impl.go
+++ b/tools/mgmt/device/impl.go
@@ -102,6 +102,29 @@
return nil
}
+var cmdDescribe = &cmdline.Command{
+ Run: runDescribe,
+ Name: "describe",
+ Short: "Describe the device.",
+ Long: "Describe the device.",
+ ArgsName: "<device>",
+ ArgsLong: `
+<device> is the veyron object name of the device manager's app service.`,
+}
+
+func runDescribe(cmd *cmdline.Command, args []string) error {
+ if expected, got := 1, len(args); expected != got {
+ return cmd.UsageErrorf("describe: incorrect number of arguments, expected %d, got %d", expected, got)
+ }
+ deviceName := args[0]
+ if description, err := device.DeviceClient(deviceName).Describe(gctx); err != nil {
+ return fmt.Errorf("Describe failed: %v", err)
+ } else {
+ fmt.Fprintf(cmd.Stdout(), "%+v\n", description)
+ }
+ return nil
+}
+
func root() *cmdline.Command {
return &cmdline.Command{
Name: "device",
@@ -109,6 +132,6 @@
Long: `
The device tool facilitates interaction with the veyron device manager.
`,
- Children: []*cmdline.Command{cmdInstall, cmdStart, associateRoot(), cmdClaim, cmdStop, cmdSuspend, cmdResume, aclRoot()},
+ Children: []*cmdline.Command{cmdInstall, cmdStart, associateRoot(), cmdDescribe, cmdClaim, cmdStop, cmdSuspend, cmdResume, aclRoot()},
}
}
diff --git a/tools/mgmt/test.sh b/tools/mgmt/test.sh
index 7c52a27..c42fa1d 100755
--- a/tools/mgmt/test.sh
+++ b/tools/mgmt/test.sh
@@ -16,6 +16,7 @@
APPLICATION_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/application')"
AGENTD_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/security/agent/agentd')"
SUIDHELPER_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/services/mgmt/suidhelper')"
+ INITHELPER_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/services/mgmt/inithelper')"
DEVICEMANAGER_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/services/mgmt/device/deviced')"
DEVICE_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/mgmt/device')"
NAMESPACE_BIN="$(shell_test::build_go_binary 'v.io/core/veyron/tools/namespace')"
@@ -86,7 +87,7 @@
build
BIN_STAGING_DIR=$(shell::tmp_dir)
- cp "${AGENTD_BIN}" "${SUIDHELPER_BIN}" "${DEVICEMANAGER_BIN}" "${BIN_STAGING_DIR}"
+ cp "${AGENTD_BIN}" "${SUIDHELPER_BIN}" "${INITHELPER_BIN}" "${DEVICEMANAGER_BIN}" "${BIN_STAGING_DIR}"
shell_test::setup_server_test
# TODO(caprita): Expose an option to turn --single_user off, so we can run
@@ -122,6 +123,9 @@
shell_test::assert_eq "$("${DEBUG_BIN}" stats read "${DM_NAME}/__debug/stats/security/principal/blessingstore" | head -1 | sed -e 's/^.*Default blessings: '//)" \
"alice/myworkstation" "${LINENO}"
+ # Get the device's profile.
+ local -r DEVICE_PROFILE=$("${DEVICE_BIN}" describe "${DM_NAME}/device" | sed -e 's/{Profiles:map\[\(.*\):{}]}/\1/')
+
# Start a binary server under the blessing "alice/myworkstation/binaryd" so that
# the device ("alice/myworkstation") can talk to it.
local -r BINARYD_NAME="binaryd"
@@ -149,10 +153,10 @@
local -r SAMPLE_APP_NAME="${APPLICATIOND_NAME}/testapp/v0"
local -r APP_PUBLISH_NAME="testbinaryd"
echo "{\"Title\":\"BINARYD\", \"Args\":[\"--name=${APP_PUBLISH_NAME}\", \"--root_dir=./binstore\", \"--veyron.tcp.address=127.0.0.1:0\"], \"Binary\":\"${SAMPLE_APP_BIN_NAME}\", \"Env\":[]}" > ./app.envelope && \
- "${APPLICATION_BIN}" put "${SAMPLE_APP_NAME}" test ./app.envelope && rm ./app.envelope
+ "${APPLICATION_BIN}" put "${SAMPLE_APP_NAME}" "${DEVICE_PROFILE}" ./app.envelope && rm ./app.envelope
# Verify that the envelope we uploaded shows up with glob.
- shell_test::assert_eq "$("${APPLICATION_BIN}" match "${SAMPLE_APP_NAME}" test | grep Title | sed -e 's/^.*"Title": "'// | sed -e 's/",//')" \
+ shell_test::assert_eq "$("${APPLICATION_BIN}" match "${SAMPLE_APP_NAME}" "${DEVICE_PROFILE}" | grep Title | sed -e 's/^.*"Title": "'// | sed -e 's/",//')" \
"BINARYD" "${LINENO}"
# Install the app on the device.
diff --git a/tools/mgmt/vbash b/tools/mgmt/vbash
index ea5047f..92c5c4d 100755
--- a/tools/mgmt/vbash
+++ b/tools/mgmt/vbash
@@ -191,7 +191,6 @@
default_blessing() {
"${BIN_INSTALL}/principal" dump | grep "Default blessings" | sed -e 's/Default blessings: //'
}
-export PATH="${PATH}:${BIN_INSTALL}"
export PS1="\${PS1}(\${GREENBOLD}\$(default_blessing)\[\033[0m\])$ "
EOF
diff --git a/tools/mounttable/impl.go b/tools/mounttable/impl.go
index be3df84..d949dab 100644
--- a/tools/mounttable/impl.go
+++ b/tools/mounttable/impl.go
@@ -172,7 +172,7 @@
ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
defer cancel()
client := veyron2.GetClient(ctx)
- call, err := client.StartCall(ctx, args[0], "ResolveStepX", []interface{}{}, options.NoResolve{})
+ call, err := client.StartCall(ctx, args[0], "ResolveStep", []interface{}{}, options.NoResolve{})
if err != nil {
return err
}
diff --git a/tools/mounttable/impl_test.go b/tools/mounttable/impl_test.go
index f4c6d75..d5026d8 100644
--- a/tools/mounttable/impl_test.go
+++ b/tools/mounttable/impl_test.go
@@ -41,10 +41,10 @@
return nil
}
-func (s *server) ResolveStep(ipc.ServerContext) (servers []naming.VDLMountedServer, suffix string, err error) {
+func (s *server) ResolveStep(ipc.ServerContext) (entry naming.VDLMountEntry, err error) {
vlog.VI(2).Infof("ResolveStep() was called. suffix=%v", s.suffix)
- servers = []naming.VDLMountedServer{{"server1", 123}}
- suffix = s.suffix
+ entry.Servers = []naming.VDLMountedServer{{"server1", 123}}
+ entry.Name = s.suffix
return
}
diff --git a/tools/namespace/impl.go b/tools/namespace/impl.go
index b2df4db..cae7c40 100644
--- a/tools/namespace/impl.go
+++ b/tools/namespace/impl.go
@@ -145,12 +145,12 @@
ns := veyron2.GetNamespace(ctx)
- servers, err := ns.Resolve(ctx, name)
+ me, err := ns.Resolve(ctx, name)
if err != nil {
vlog.Infof("ns.Resolve(%q) failed: %v", name, err)
return err
}
- for _, s := range servers {
+ for _, s := range me.Names() {
fmt.Fprintln(cmd.Stdout(), s)
}
return nil
@@ -176,9 +176,9 @@
ns := veyron2.GetNamespace(ctx)
- e, err := ns.ResolveToMountTableX(ctx, name)
+ e, err := ns.ResolveToMountTable(ctx, name)
if err != nil {
- vlog.Infof("ns.ResolveToMountTableX(%q) failed: %v", name, err)
+ vlog.Infof("ns.ResolveToMountTable(%q) failed: %v", name, err)
return err
}
for _, s := range e.Servers {
diff --git a/tools/naming/simulator/shell_functions.go b/tools/naming/simulator/shell_functions.go
index 396fe6d..552635b 100644
--- a/tools/naming/simulator/shell_functions.go
+++ b/tools/naming/simulator/shell_functions.go
@@ -87,18 +87,19 @@
return nil
}
-type resolver func(ctx *context.T, name string, opts ...naming.ResolveOpt) (names []string, err error)
+type resolver func(ctx *context.T, name string, opts ...naming.ResolveOpt) (me *naming.MountEntry, err error)
func resolve(fn resolver, stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
if err := checkArgs(args[1:], 1, "<name>"); err != nil {
return err
}
name := args[1]
- servers, err := fn(ctx, name)
+ me, err := fn(ctx, name)
if err != nil {
fmt.Fprintf(stdout, "RN=0\n")
return err
}
+ servers := me.Names()
fmt.Fprintf(stdout, "RN=%d\n", len(servers))
for i, s := range servers {
fmt.Fprintf(stdout, "R%d=%s\n", i, s)
diff --git a/tools/vrpc/doc.go b/tools/vrpc/doc.go
index ffb250a..f5ff56d 100644
--- a/tools/vrpc/doc.go
+++ b/tools/vrpc/doc.go
@@ -2,16 +2,16 @@
// DO NOT UPDATE MANUALLY
/*
-The vrpc tool facilitates interaction with Veyron RPC servers. In particular, it
-can be used to 1) find out what API a Veyron RPC server exports and 2) send
-requests to a Veyron RPC server.
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
Usage:
vrpc <command>
The vrpc commands are:
- describe Describe the API of an Veyron RPC server
- invoke Invoke a method of an Veyron RPC server
+ signature Describe the interfaces of a Vanadium server
+ call Call a method of a Vanadium server
+ identify Reveal blessings presented by a Vanadium server
help Display help for commands or topics
Run "vrpc help [command]" for command usage.
@@ -38,44 +38,73 @@
local namespace root; can be repeated to provided multiple roots
-veyron.vtrace.cache_size=1024
The number of vtrace traces to store in memory.
- -veyron.vtrace.dump_on_shutdown=false
+ -veyron.vtrace.collect_regexp=
+ Spans and annotations that match this regular expression will trigger trace
+ collection.
+ -veyron.vtrace.dump_on_shutdown=true
If true, dump all stored traces on runtime shutdown.
-veyron.vtrace.sample_rate=0
Rate (from 0.0 to 1.0) to sample vtrace traces.
-vmodule=
comma-separated list of pattern=N settings for file-filtered logging
-Vrpc Describe
+Vrpc Signature
-Describe connects to the Veyron RPC server identified by <server>, finds out
-what its API is, and outputs a succint summary of this API to the standard
-output.
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
Usage:
- vrpc describe <server>
+ vrpc signature <server> [method]
-<server> identifies the Veyron RPC server. It can either be the object address
-of the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
+<server> identifies a Vanadium server. It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
-Vrpc Invoke
+[method] is the optional server method name.
-Invoke connects to the Veyron RPC server identified by <server>, invokes the
-method identified by <method>, supplying the arguments identified by <args>, and
-outputs the results of the invocation to the standard output.
+Vrpc Call
+
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server. An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions. Positional arguments
+may also be specified as separate command-line arguments. Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step. This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
Usage:
- vrpc invoke <server> <method> <args>
+ vrpc call <server> <method> [args...]
-<server> identifies the Veyron RPC server. It can either be the object address
-of the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
+<server> identifies a Vanadium server. It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
-<method> identifies the name of the method to be invoked.
+<method> is the server method to call.
-<args> identifies the arguments of the method to be invoked. It should be a list
-of values in a VOM JSON format that can be reflected to the correct type using
-Go's reflection.
+[args...] are the positional input arguments, specified as VDL expressions.
+
+Vrpc Identify
+
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+
+Usage:
+ vrpc identify <server>
+
+<server> identifies a Vanadium server. It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
Vrpc Help
diff --git a/tools/vrpc/impl.go b/tools/vrpc/impl.go
deleted file mode 100644
index 9c672f4..0000000
--- a/tools/vrpc/impl.go
+++ /dev/null
@@ -1,348 +0,0 @@
-package main
-
-import (
- "bytes"
- "fmt"
- "io"
- "time"
-
- idl_test_base "v.io/core/veyron/tools/vrpc/test_base"
- "v.io/core/veyron2"
- "v.io/core/veyron2/context"
- "v.io/core/veyron2/ipc"
- "v.io/core/veyron2/naming"
- "v.io/core/veyron2/vdl/vdlutil"
- "v.io/core/veyron2/vom"
- "v.io/core/veyron2/wiretype"
- "v.io/lib/cmdline"
-
- idl_binary "v.io/core/veyron2/services/mgmt/binary"
- idl_device "v.io/core/veyron2/services/mgmt/device"
-)
-
-const serverDesc = `
-<server> identifies the Veyron RPC server. It can either be the object address of
-the server or an Object name in which case the vrpc will use Veyron's name
-resolution to match this name to an end-point.
-`
-const methodDesc = `
-<method> identifies the name of the method to be invoked.
-`
-const argsDesc = `
-<args> identifies the arguments of the method to be invoked. It should be a list
-of values in a VOM JSON format that can be reflected to the correct type
-using Go's reflection.
-`
-
-var cmdDescribe = &cmdline.Command{
- Run: runDescribe,
- Name: "describe",
- Short: "Describe the API of an Veyron RPC server",
- Long: `
-Describe connects to the Veyron RPC server identified by <server>, finds out what
-its API is, and outputs a succint summary of this API to the standard output.
-`,
- ArgsName: "<server>",
- ArgsLong: serverDesc,
-}
-
-func runDescribe(cmd *cmdline.Command, args []string) error {
- if len(args) != 1 {
- return cmd.UsageErrorf("describe: incorrect number of arguments, expected 1, got %d", len(args))
- }
- ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
- defer cancel()
- signature, err := getSignature(ctx, cmd, args[0])
- if err != nil {
- return err
- }
-
- for methodName, methodSignature := range signature.Methods {
- fmt.Fprintf(cmd.Stdout(), "%s\n", formatSignature(methodName, methodSignature, signature.TypeDefs))
- }
- return nil
-}
-
-var cmdInvoke = &cmdline.Command{
- Run: runInvoke,
- Name: "invoke",
- Short: "Invoke a method of an Veyron RPC server",
- Long: `
-Invoke connects to the Veyron RPC server identified by <server>, invokes the method
-identified by <method>, supplying the arguments identified by <args>, and outputs
-the results of the invocation to the standard output.
-`,
- ArgsName: "<server> <method> <args>",
- ArgsLong: serverDesc + methodDesc + argsDesc,
-}
-
-func runInvoke(cmd *cmdline.Command, args []string) error {
- if len(args) < 2 {
- return cmd.UsageErrorf("invoke: incorrect number of arguments, expected at least 2, got %d", len(args))
- }
- server, method, args := args[0], args[1], args[2:]
-
- ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
- defer cancel()
- signature, err := getSignature(ctx, cmd, server)
- if err != nil {
- return fmt.Errorf("invoke: failed to get signature for %v: %v", server, err)
- }
- if len(signature.Methods) == 0 {
- return fmt.Errorf("invoke: empty signature for %v", server)
- }
-
- methodSignature, found := signature.Methods[method]
- if !found {
- return fmt.Errorf("invoke: method %s not found", method)
- }
-
- if len(args) != len(methodSignature.InArgs) {
- return cmd.UsageErrorf("invoke: incorrect number of arguments, expected %d, got %d", len(methodSignature.InArgs), len(args))
- }
-
- // Register all user-defined types you would like to use.
- //
- // TODO(jsimsa): This is a temporary hack to get vrpc to work. When
- // Benj implements support for decoding arbitrary structs to an
- // empty interface, this will no longer be needed.
- var x1 idl_test_base.Struct
- vdlutil.Register(x1)
- var x2 idl_device.Description
- vdlutil.Register(x2)
- var x3 idl_binary.Description
- vdlutil.Register(x3)
- var x4 naming.VDLMountedServer
- vdlutil.Register(x4)
- var x5 naming.VDLMountEntry
- vdlutil.Register(x5)
-
- // Decode the inputs from vomJSON-formatted command-line arguments.
- inputs := make([]interface{}, len(args))
- for i := range args {
- var buf bytes.Buffer
- buf.WriteString(args[i])
- buf.WriteByte(0)
- decoder := vom.NewDecoder(&buf)
- if err := decoder.Decode(&inputs[i]); err != nil {
- return fmt.Errorf("decoder.Decode() failed for %s with %v", args[i], err)
- }
- }
-
- // Initiate the method invocation.
- client := veyron2.GetClient(ctx)
- call, err := client.StartCall(ctx, server, method, inputs)
- if err != nil {
- return fmt.Errorf("client.StartCall(%q, %q, %v) failed with %v", server, method, inputs, err)
- }
-
- fmt.Fprintf(cmd.Stdout(), "%s = ", formatInput(method, inputs))
-
- // Handle streaming results, if the method happens to be streaming.
- var item interface{}
- nStream := 0
-forloop:
- for ; ; nStream++ {
- switch err := call.Recv(&item); err {
- case io.EOF:
- break forloop
- case nil:
- if nStream == 0 {
- fmt.Fprintln(cmd.Stdout(), "<<")
- }
- fmt.Fprintf(cmd.Stdout(), "%d: %v\n", nStream, item)
- default:
- return fmt.Errorf("call.Recv failed with %v", err)
- }
- }
- if nStream > 0 {
- fmt.Fprintf(cmd.Stdout(), ">> ")
- }
-
- // Receive the outputs of the method invocation.
- outputs := make([]interface{}, len(methodSignature.OutArgs))
- outputPtrs := make([]interface{}, len(methodSignature.OutArgs))
- for i := range outputs {
- outputPtrs[i] = &outputs[i]
- }
- if err := call.Finish(outputPtrs...); err != nil {
- return fmt.Errorf("call.Finish() failed with %v", err)
- }
- fmt.Fprintf(cmd.Stdout(), "%s\n", formatOutput(outputs))
-
- return nil
-}
-
-var cmdIdentify = &cmdline.Command{
- Run: runIdentify,
- Name: "identify",
- Short: "Reveal blessings presented by a Veyron RPC server",
- Long: `
-Identify connects to the Veyron RPC server identified by <server> and dumps
-out the blessings presented by that server (and the subset of those that are
-considered valid by the principal running this tool) to standard output.
-`,
- ArgsName: "[<server>]",
- ArgsLong: serverDesc,
-}
-
-func runIdentify(cmd *cmdline.Command, args []string) error {
- if len(args) > 1 {
- return cmd.UsageErrorf("identify: incorrect number of arguments, expected at most 1, got %d", len(args))
- }
- ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
- defer cancel()
- client := veyron2.GetClient(ctx)
- var server string
- if len(args) > 0 {
- server = args[0]
- }
- // The method name does not matter - only interested in authentication,
- // not in actually making an RPC.
- call, err := client.StartCall(ctx, server, "", nil)
- if err != nil {
- return fmt.Errorf("client.StartCall(%q, \"\", nil) failed with %v", server, err)
- }
- valid, presented := call.RemoteBlessings()
- fmt.Fprintf(cmd.Stdout(), "PRESENTED: %v\nVALID: %v\n", presented, valid)
- return nil
-}
-
-// root returns the root command for the vrpc tool.
-func root() *cmdline.Command {
- return &cmdline.Command{
- Name: "vrpc",
- Short: "Tool for interacting with Veyron RPC servers.",
- Long: `
-The vrpc tool facilitates interaction with Veyron RPC servers. In particular,
-it can be used to 1) find out what API a Veyron RPC server exports and
-2) send requests to a Veyron RPC server.
-`,
- Children: []*cmdline.Command{cmdDescribe, cmdInvoke, cmdIdentify},
- }
-}
-
-func getSignature(ctx *context.T, cmd *cmdline.Command, server string) (ipc.ServiceSignature, error) {
- client := veyron2.GetClient(ctx)
- call, err := client.StartCall(ctx, server, "Signature", nil)
- if err != nil {
- return ipc.ServiceSignature{}, fmt.Errorf("client.StartCall(%q, \"Signature\", nil) failed with %v", server, err)
- }
- var signature ipc.ServiceSignature
- var sigerr error
- if err = call.Finish(&signature, &sigerr); err != nil {
- return ipc.ServiceSignature{}, fmt.Errorf("client.Finish(&signature, &sigerr) failed with %v", err)
- }
- return signature, sigerr
-}
-
-// formatWiretype generates a string representation of the specified type.
-func formatWiretype(td []vdlutil.Any, tid wiretype.TypeID) string {
- var wt vdlutil.Any
- if tid >= wiretype.TypeIDFirst {
- wt = td[tid-wiretype.TypeIDFirst]
- } else {
- for _, pair := range wiretype.BootstrapTypes {
- if pair.TID == tid {
- wt = pair.WT
- }
- }
- if wt == nil {
- return fmt.Sprintf("UNKNOWN_TYPE[%v]", tid)
- }
- }
-
- switch t := wt.(type) {
- case wiretype.NamedPrimitiveType:
- if t.Name != "" {
- return t.Name
- }
- return tid.Name()
- case wiretype.SliceType:
- return fmt.Sprintf("[]%s", formatWiretype(td, t.Elem))
- case wiretype.ArrayType:
- return fmt.Sprintf("[%d]%s", t.Len, formatWiretype(td, t.Elem))
- case wiretype.MapType:
- return fmt.Sprintf("map[%s]%s", formatWiretype(td, t.Key), formatWiretype(td, t.Elem))
- case wiretype.StructType:
- var buf bytes.Buffer
- buf.WriteString("struct{")
- for i, fld := range t.Fields {
- if i > 0 {
- buf.WriteString(", ")
- }
- buf.WriteString(fld.Name)
- buf.WriteString(" ")
- buf.WriteString(formatWiretype(td, fld.Type))
- }
- buf.WriteString("}")
- return buf.String()
- default:
- panic(fmt.Sprintf("unknown writetype: %T", wt))
- }
-}
-
-func formatSignature(name string, ms ipc.MethodSignature, defs []vdlutil.Any) string {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "func %s(", name)
- for index, arg := range ms.InArgs {
- if index > 0 {
- buf.WriteString(", ")
- }
- fmt.Fprintf(&buf, "%s %s", arg.Name, formatWiretype(defs, arg.Type))
- }
- buf.WriteString(") ")
- if ms.InStream != wiretype.TypeIDInvalid || ms.OutStream != wiretype.TypeIDInvalid {
- buf.WriteString("stream<")
- if ms.InStream == wiretype.TypeIDInvalid {
- buf.WriteString("_")
- } else {
- fmt.Fprintf(&buf, "%s", formatWiretype(defs, ms.InStream))
- }
- buf.WriteString(", ")
- if ms.OutStream == wiretype.TypeIDInvalid {
- buf.WriteString("_")
- } else {
- fmt.Fprintf(&buf, "%s", formatWiretype(defs, ms.OutStream))
- }
- buf.WriteString("> ")
- }
- buf.WriteString("(")
- for index, arg := range ms.OutArgs {
- if index > 0 {
- buf.WriteString(", ")
- }
- if arg.Name != "" {
- fmt.Fprintf(&buf, "%s ", arg.Name)
- }
- fmt.Fprintf(&buf, "%s", formatWiretype(defs, arg.Type))
- }
- buf.WriteString(")")
- return buf.String()
-}
-
-func formatInput(name string, inputs []interface{}) string {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "%s(", name)
- for index, value := range inputs {
- if index > 0 {
- buf.WriteString(", ")
- }
- fmt.Fprintf(&buf, "%v", value)
- }
- buf.WriteString(")")
- return buf.String()
-}
-
-func formatOutput(outputs []interface{}) string {
- var buf bytes.Buffer
- buf.WriteString("[")
- for index, value := range outputs {
- if index > 0 {
- buf.WriteString(", ")
- }
- fmt.Fprintf(&buf, "%v", value)
- }
- buf.WriteString("]")
- return buf.String()
-}
diff --git a/tools/vrpc/impl_test.go b/tools/vrpc/impl_test.go
deleted file mode 100644
index 6f32b71..0000000
--- a/tools/vrpc/impl_test.go
+++ /dev/null
@@ -1,293 +0,0 @@
-package main
-
-import (
- "bytes"
- "sort"
- "strings"
- "testing"
-
- "v.io/core/veyron2"
- "v.io/core/veyron2/context"
- "v.io/core/veyron2/ipc"
- "v.io/core/veyron2/naming"
- "v.io/core/veyron2/rt"
- "v.io/core/veyron2/vlog"
-
- "v.io/core/veyron/profiles"
- "v.io/core/veyron/tools/vrpc/test_base"
- "v.io/lib/cmdline"
-)
-
-type server struct{}
-
-// TypeTester interface implementation
-
-func (*server) EchoBool(call ipc.ServerContext, i1 bool) (bool, error) {
- vlog.VI(2).Info("EchoBool(%v) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoFloat32(call ipc.ServerContext, i1 float32) (float32, error) {
- vlog.VI(2).Info("EchoFloat32(%u) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoFloat64(call ipc.ServerContext, i1 float64) (float64, error) {
- vlog.VI(2).Info("EchoFloat64(%u) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoInt32(call ipc.ServerContext, i1 int32) (int32, error) {
- vlog.VI(2).Info("EchoInt32(%v) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoInt64(call ipc.ServerContext, i1 int64) (int64, error) {
- vlog.VI(2).Info("EchoInt64(%v) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoString(call ipc.ServerContext, i1 string) (string, error) {
- vlog.VI(2).Info("EchoString(%v) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoByte(call ipc.ServerContext, i1 byte) (byte, error) {
- vlog.VI(2).Info("EchoByte(%v) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoUInt32(call ipc.ServerContext, i1 uint32) (uint32, error) {
- vlog.VI(2).Info("EchoUInt32(%u) was called.", i1)
- return i1, nil
-}
-
-func (*server) EchoUInt64(call ipc.ServerContext, i1 uint64) (uint64, error) {
- vlog.VI(2).Info("EchoUInt64(%u) was called.", i1)
- return i1, nil
-}
-
-func (*server) InputArray(call ipc.ServerContext, i1 [2]uint8) error {
- vlog.VI(2).Info("CInputArray(%v) was called.", i1)
- return nil
-}
-
-func (*server) OutputArray(call ipc.ServerContext) ([2]uint8, error) {
- vlog.VI(2).Info("COutputArray() was called.")
- return [2]uint8{1, 2}, nil
-}
-
-func (*server) InputMap(call ipc.ServerContext, i1 map[uint8]uint8) error {
- vlog.VI(2).Info("CInputMap(%v) was called.", i1)
- return nil
-}
-
-func (*server) OutputMap(call ipc.ServerContext) (map[uint8]uint8, error) {
- vlog.VI(2).Info("COutputMap() was called.")
- return map[uint8]uint8{1: 2}, nil
-}
-
-func (*server) InputSlice(call ipc.ServerContext, i1 []uint8) error {
- vlog.VI(2).Info("CInputSlice(%v) was called.", i1)
- return nil
-}
-
-func (*server) OutputSlice(call ipc.ServerContext) ([]uint8, error) {
- vlog.VI(2).Info("COutputSlice() was called.")
- return []uint8{1, 2}, nil
-}
-
-func (*server) InputStruct(call ipc.ServerContext, i1 test_base.Struct) error {
- vlog.VI(2).Info("CInputStruct(%v) was called.", i1)
- return nil
-}
-
-func (*server) OutputStruct(call ipc.ServerContext) (test_base.Struct, error) {
- vlog.VI(2).Info("COutputStruct() was called.")
- return test_base.Struct{X: 1, Y: 2}, nil
-}
-
-func (*server) NoArguments(call ipc.ServerContext) error {
- vlog.VI(2).Info("NoArguments() was called.")
- return nil
-}
-
-func (*server) MultipleArguments(call ipc.ServerContext, i1, i2 int32) (int32, int32, error) {
- vlog.VI(2).Info("MultipleArguments(%v,%v) was called.", i1, i2)
- return i1, i2, nil
-}
-
-func (*server) StreamingOutput(ctx test_base.TypeTesterStreamingOutputContext, nStream int32, item bool) error {
- vlog.VI(2).Info("StreamingOutput(%v,%v) was called.", nStream, item)
- sender := ctx.SendStream()
- for i := int32(0); i < nStream; i++ {
- sender.Send(item)
- }
- return nil
-}
-
-func startServer(t *testing.T, ctx *context.T) (ipc.Server, naming.Endpoint, error) {
- obj := test_base.TypeTesterServer(&server{})
- server, err := veyron2.NewServer(ctx)
- if err != nil {
- t.Errorf("NewServer failed: %v", err)
- return nil, nil, err
- }
-
- endpoints, err := server.Listen(profiles.LocalListenSpec)
- if err != nil {
- t.Errorf("Listen failed: %v", err)
- return nil, nil, err
- }
- if err := server.Serve("", obj, nil); err != nil {
- t.Errorf("Serve failed: %v", err)
- return nil, nil, err
- }
- return server, endpoints[0], nil
-}
-
-func stopServer(t *testing.T, server ipc.Server) {
- if err := server.Stop(); err != nil {
- t.Errorf("server.Stop failed: %v", err)
- }
-}
-
-func testInvocation(t *testing.T, buffer *bytes.Buffer, cmd *cmdline.Command, args []string, expected string) {
- buffer.Reset()
- if err := cmd.Execute(args); err != nil {
- t.Errorf("%v", err)
- return
- }
- if output := strings.Trim(buffer.String(), "\n"); output != expected {
- t.Errorf("Incorrect invoke output: expected %s, got %s", expected, output)
- return
- }
-}
-
-func testError(t *testing.T, cmd *cmdline.Command, args []string, expected string) {
- if err := cmd.Execute(args); err == nil || !strings.Contains(err.Error(), expected) {
- t.Errorf("Expected error: ...%v..., got: %v", expected, err)
- }
-}
-
-func TestVRPC(t *testing.T) {
- var err error
- runtime, err = rt.New()
- if err != nil {
- t.Fatalf("Unexpected error initializing runtime: %s", err)
- }
- defer runtime.Cleanup()
- ctx := runtime.NewContext()
-
- // Skip defer runtime.Cleanup() to avoid messing up other tests in the
- // same process.
- server, endpoint, err := startServer(t, ctx)
- if err != nil {
- return
- }
- defer stopServer(t, server)
-
- // Setup the command-line.
- cmd := root()
- var stdout, stderr bytes.Buffer
- cmd.Init(nil, &stdout, &stderr)
-
- name := endpoint.Name()
- // Test the 'describe' command.
- if err := cmd.Execute([]string{"describe", name}); err != nil {
- t.Errorf("%v", err)
- return
- }
-
- // TODO(toddw): Switch VRPC to new __Signature, and update these tests.
- expectedSignature := []string{
- "func EchoBool(I1 bool) (O1 bool, err error)",
- "func EchoFloat32(I1 float32) (O1 float32, err error)",
- "func EchoFloat64(I1 float64) (O1 float64, err error)",
- "func EchoInt32(I1 int32) (O1 int32, err error)",
- "func EchoInt64(I1 int64) (O1 int64, err error)",
- "func EchoString(I1 string) (O1 string, err error)",
- "func EchoByte(I1 byte) (O1 byte, err error)",
- "func EchoUInt32(I1 uint32) (O1 uint32, err error)",
- "func EchoUInt64(I1 uint64) (O1 uint64, err error)",
- "func InputArray(I1 [2]byte) (error)",
- "func InputMap(I1 map[byte]byte) (error)",
- "func InputSlice(I1 []byte) (error)",
- "func InputStruct(I1 struct{X int32, Y int32}) (error)",
- "func OutputArray() (O1 [2]byte, err error)",
- "func OutputMap() (O1 map[byte]byte, err error)",
- "func OutputSlice() (O1 []byte, err error)",
- "func OutputStruct() (O1 struct{X int32, Y int32}, err error)",
- "func NoArguments() (error)",
- "func MultipleArguments(I1 int32, I2 int32) (O1 int32, O2 int32, err error)",
- "func StreamingOutput(NumStreamItems int32, StreamItem bool) stream<_, bool> (error)",
- }
-
- signature := make([]string, 0, len(expectedSignature))
- line, err := stdout.ReadBytes('\n')
- for err == nil {
- signature = append(signature, strings.Trim(string(line), "\n"))
- line, err = stdout.ReadBytes('\n')
- }
-
- sort.Strings(signature)
- sort.Strings(expectedSignature)
-
- if len(signature) != len(expectedSignature) {
- t.Fatalf("signature lengths don't match %v and %v.", len(signature), len(expectedSignature))
- }
-
- for i, expectedSig := range expectedSignature {
- if expectedSig != signature[i] {
- t.Errorf("signature line doesn't match: %v and %v\n", expectedSig, signature[i])
- }
- }
-
- // Test the 'invoke' command.
-
- tests := [][]string{
- []string{"EchoBool", "EchoBool(true) = [true, <nil>]", "[\"bool\",true]"},
- []string{"EchoFloat32", "EchoFloat32(3.2) = [3.2, <nil>]", "[\"float32\",3.2]"},
- []string{"EchoFloat64", "EchoFloat64(6.4) = [6.4, <nil>]", "[\"float64\",6.4]"},
- []string{"EchoInt32", "EchoInt32(-32) = [-32, <nil>]", "[\"int32\",-32]"},
- []string{"EchoInt64", "EchoInt64(-64) = [-64, <nil>]", "[\"int64\",-64]"},
- []string{"EchoString", "EchoString(Hello World!) = [Hello World!, <nil>]", "[\"string\",\"Hello World!\"]"},
- []string{"EchoByte", "EchoByte(8) = [8, <nil>]", "[\"byte\",8]"},
- []string{"EchoUInt32", "EchoUInt32(32) = [32, <nil>]", "[\"uint32\",32]"},
- []string{"EchoUInt64", "EchoUInt64(64) = [64, <nil>]", "[\"uint64\",64]"},
- // TODO(jsimsa): The InputArray currently triggers an error in the
- // vom decoder. Benj is looking into this.
- //
- // []string{"InputArray", "InputArray([1 2]) = []", "[\"[2]uint\",[1,2]]"},
- []string{"InputMap", "InputMap(map[1:2]) = [<nil>]", "[\"map[uint]uint\",{\"1\":\"2\"}]"},
- // TODO(jsimsa): The InputSlice currently triggers an error in the
- // vom decoder. Benj is looking into this.
- //
- // []string{"InputSlice", "InputSlice([1 2]) = []", "[\"[]uint\",[1,2]]"},
- []string{"InputStruct", "InputStruct({1 2}) = [<nil>]",
- "[\"type\",\"v.io/core/veyron2/vrpc/test_base.Struct struct{X int32;Y int32}\"] [\"Struct\",{\"X\":1,\"Y\":2}]"},
- // TODO(jsimsa): The OutputArray currently triggers an error in the
- // vom decoder. Benj is looking into this.
- //
- // []string{"OutputArray", "OutputArray() = [1 2]"}
- []string{"OutputMap", "OutputMap() = [map[1:2], <nil>]"},
- []string{"OutputSlice", "OutputSlice() = [[1 2], <nil>]"},
- []string{"OutputStruct", "OutputStruct() = [{1 2}, <nil>]"},
- []string{"NoArguments", "NoArguments() = [<nil>]"},
- []string{"MultipleArguments", "MultipleArguments(1, 2) = [1, 2, <nil>]", "[\"uint32\",1]", "[\"uint32\",2]"},
- []string{"StreamingOutput", "StreamingOutput(3, true) = <<\n0: true\n1: true\n2: true\n>> [<nil>]", "[\"int8\",3]", "[\"bool\",true ]"},
- []string{"StreamingOutput", "StreamingOutput(0, true) = [<nil>]", "[\"int8\",0]", "[\"bool\",true ]"},
- }
-
- for _, test := range tests {
- testInvocation(t, &stdout, cmd, append([]string{"invoke", name, test[0]}, test[2:]...), test[1])
- }
-
- testErrors := [][]string{
- []string{"EchoBool", "exit code 1"},
- []string{"DoesNotExist", "invoke: method DoesNotExist not found"},
- }
- for _, test := range testErrors {
- testError(t, cmd, append([]string{"invoke", name, test[0]}, test[2:]...), test[1])
- }
-}
diff --git a/tools/vrpc/main.go b/tools/vrpc/main.go
deleted file mode 100644
index 7368a9c..0000000
--- a/tools/vrpc/main.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// The following enables go generate to generate the doc.go file.
-//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
-
-package main
-
-import (
- "v.io/core/veyron2"
- "v.io/core/veyron2/rt"
-
- _ "v.io/core/veyron/profiles"
-)
-
-var runtime veyron2.Runtime
-
-func main() {
- var err error
- runtime, err = rt.New()
- if err != nil {
- panic(err)
- }
- defer runtime.Cleanup()
- root().Main()
-}
diff --git a/tools/vrpc/test_base/test_base.vdl b/tools/vrpc/test_base/test_base.vdl
index 8f6b15e..e0406da 100644
--- a/tools/vrpc/test_base/test_base.vdl
+++ b/tools/vrpc/test_base/test_base.vdl
@@ -4,32 +4,31 @@
X,Y int32
}
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
type TypeTester interface {
- // Methods to test support for generic types.
- EchoBool(I1 bool) (O1 bool | error)
- EchoFloat32(I1 float32) (O1 float32 | error)
- EchoFloat64(I1 float64) (O1 float64 | error)
- EchoInt32(I1 int32) (O1 int32 | error)
- EchoInt64(I1 int64) (O1 int64 | error)
- EchoString(I1 string) (O1 string | error)
- EchoByte(I1 byte) (O1 byte | error)
- EchoUInt32(I1 uint32) (O1 uint32 | error)
- EchoUInt64(I1 uint64) (O1 uint64 | error)
+ // Methods to test support for primitive types.
+ EchoBool(I1 bool) (O1 bool | error)
+ EchoFloat32(I1 float32) (O1 float32 | error)
+ EchoFloat64(I1 float64) (O1 float64 | error)
+ EchoInt32(I1 int32) (O1 int32 | error)
+ EchoInt64(I1 int64) (O1 int64 | error)
+ EchoString(I1 string) (O1 string | error)
+ EchoByte(I1 byte) (O1 byte | error)
+ EchoUint32(I1 uint32) (O1 uint32 | error)
+ EchoUint64(I1 uint64) (O1 uint64 | error)
- // Methods to test support for composite types.
- InputArray(I1 [2]byte) error
- InputMap(I1 map[byte]byte) error
- InputSlice(I1 []byte) error
- InputStruct(I1 Struct) error
- OutputArray() (O1 [2]byte | error)
- OutputMap() (O1 map[byte]byte | error)
- OutputSlice() (O1 []byte | error)
- OutputStruct() (O1 Struct | error)
+ // Methods to test support for composite types.
+ XEchoArray(I1 [2]int32) (O1 [2]int32 | error)
+ XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+ XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+ XEchoSlice(I1 []int32) (O1 []int32 | error)
+ XEchoStruct(I1 Struct) (O1 Struct | error)
- // Methods to test support for different number of arguments.
- NoArguments() error
- MultipleArguments(I1, I2 int32) (O1, O2 int32 | error)
+ // Methods to test support for different number of arguments.
+ YMultiArg(I1, I2 int32) (O1, O2 int32 | error)
+ YNoArgs() error
- // Methods to test support for streaming.
- StreamingOutput(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+ // Methods to test support for streaming.
+ ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
}
diff --git a/tools/vrpc/test_base/test_base.vdl.go b/tools/vrpc/test_base/test_base.vdl.go
index 87a4708..af0e095 100644
--- a/tools/vrpc/test_base/test_base.vdl.go
+++ b/tools/vrpc/test_base/test_base.vdl.go
@@ -10,15 +10,8 @@
__context "v.io/core/veyron2/context"
__ipc "v.io/core/veyron2/ipc"
__vdl "v.io/core/veyron2/vdl"
- __vdlutil "v.io/core/veyron2/vdl/vdlutil"
- __wiretype "v.io/core/veyron2/wiretype"
)
-// TODO(toddw): Remove this line once the new signature support is done.
-// It corrects a bug where __wiretype is unused in VDL pacakges where only
-// bootstrap types are used on interfaces.
-const _ = __wiretype.TypeIDInvalid
-
type Struct struct {
X int32
Y int32
@@ -35,8 +28,11 @@
// TypeTesterClientMethods is the client interface
// containing TypeTester methods.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
type TypeTesterClientMethods interface {
- // Methods to test support for generic types.
+ // Methods to test support for primitive types.
EchoBool(ctx *__context.T, I1 bool, opts ...__ipc.CallOpt) (O1 bool, err error)
EchoFloat32(ctx *__context.T, I1 float32, opts ...__ipc.CallOpt) (O1 float32, err error)
EchoFloat64(ctx *__context.T, I1 float64, opts ...__ipc.CallOpt) (O1 float64, err error)
@@ -44,22 +40,19 @@
EchoInt64(ctx *__context.T, I1 int64, opts ...__ipc.CallOpt) (O1 int64, err error)
EchoString(ctx *__context.T, I1 string, opts ...__ipc.CallOpt) (O1 string, err error)
EchoByte(ctx *__context.T, I1 byte, opts ...__ipc.CallOpt) (O1 byte, err error)
- EchoUInt32(ctx *__context.T, I1 uint32, opts ...__ipc.CallOpt) (O1 uint32, err error)
- EchoUInt64(ctx *__context.T, I1 uint64, opts ...__ipc.CallOpt) (O1 uint64, err error)
+ EchoUint32(ctx *__context.T, I1 uint32, opts ...__ipc.CallOpt) (O1 uint32, err error)
+ EchoUint64(ctx *__context.T, I1 uint64, opts ...__ipc.CallOpt) (O1 uint64, err error)
// Methods to test support for composite types.
- InputArray(ctx *__context.T, I1 [2]byte, opts ...__ipc.CallOpt) error
- InputMap(ctx *__context.T, I1 map[byte]byte, opts ...__ipc.CallOpt) error
- InputSlice(ctx *__context.T, I1 []byte, opts ...__ipc.CallOpt) error
- InputStruct(ctx *__context.T, I1 Struct, opts ...__ipc.CallOpt) error
- OutputArray(*__context.T, ...__ipc.CallOpt) (O1 [2]byte, err error)
- OutputMap(*__context.T, ...__ipc.CallOpt) (O1 map[byte]byte, err error)
- OutputSlice(*__context.T, ...__ipc.CallOpt) (O1 []byte, err error)
- OutputStruct(*__context.T, ...__ipc.CallOpt) (O1 Struct, err error)
+ XEchoArray(ctx *__context.T, I1 [2]int32, opts ...__ipc.CallOpt) (O1 [2]int32, err error)
+ XEchoMap(ctx *__context.T, I1 map[int32]string, opts ...__ipc.CallOpt) (O1 map[int32]string, err error)
+ XEchoSet(ctx *__context.T, I1 map[int32]struct{}, opts ...__ipc.CallOpt) (O1 map[int32]struct{}, err error)
+ XEchoSlice(ctx *__context.T, I1 []int32, opts ...__ipc.CallOpt) (O1 []int32, err error)
+ XEchoStruct(ctx *__context.T, I1 Struct, opts ...__ipc.CallOpt) (O1 Struct, err error)
// Methods to test support for different number of arguments.
- NoArguments(*__context.T, ...__ipc.CallOpt) error
- MultipleArguments(ctx *__context.T, I1 int32, I2 int32, opts ...__ipc.CallOpt) (O1 int32, O2 int32, err error)
+ YMultiArg(ctx *__context.T, I1 int32, I2 int32, opts ...__ipc.CallOpt) (O1 int32, O2 int32, err error)
+ YNoArgs(*__context.T, ...__ipc.CallOpt) error
// Methods to test support for streaming.
- StreamingOutput(ctx *__context.T, NumStreamItems int32, StreamItem bool, opts ...__ipc.CallOpt) (TypeTesterStreamingOutputCall, error)
+ ZStream(ctx *__context.T, NumStreamItems int32, StreamItem bool, opts ...__ipc.CallOpt) (TypeTesterZStreamCall, error)
}
// TypeTesterClientStub adds universal methods to TypeTesterClientMethods.
@@ -168,9 +161,9 @@
return
}
-func (c implTypeTesterClientStub) EchoUInt32(ctx *__context.T, i0 uint32, opts ...__ipc.CallOpt) (o0 uint32, err error) {
+func (c implTypeTesterClientStub) EchoUint32(ctx *__context.T, i0 uint32, opts ...__ipc.CallOpt) (o0 uint32, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUInt32", []interface{}{i0}, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint32", []interface{}{i0}, opts...); err != nil {
return
}
if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -179,9 +172,9 @@
return
}
-func (c implTypeTesterClientStub) EchoUInt64(ctx *__context.T, i0 uint64, opts ...__ipc.CallOpt) (o0 uint64, err error) {
+func (c implTypeTesterClientStub) EchoUint64(ctx *__context.T, i0 uint64, opts ...__ipc.CallOpt) (o0 uint64, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUInt64", []interface{}{i0}, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "EchoUint64", []interface{}{i0}, opts...); err != nil {
return
}
if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -190,53 +183,9 @@
return
}
-func (c implTypeTesterClientStub) InputArray(ctx *__context.T, i0 [2]byte, opts ...__ipc.CallOpt) (err error) {
+func (c implTypeTesterClientStub) XEchoArray(ctx *__context.T, i0 [2]int32, opts ...__ipc.CallOpt) (o0 [2]int32, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "InputArray", []interface{}{i0}, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&err); ierr != nil {
- err = ierr
- }
- return
-}
-
-func (c implTypeTesterClientStub) InputMap(ctx *__context.T, i0 map[byte]byte, opts ...__ipc.CallOpt) (err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "InputMap", []interface{}{i0}, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&err); ierr != nil {
- err = ierr
- }
- return
-}
-
-func (c implTypeTesterClientStub) InputSlice(ctx *__context.T, i0 []byte, opts ...__ipc.CallOpt) (err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "InputSlice", []interface{}{i0}, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&err); ierr != nil {
- err = ierr
- }
- return
-}
-
-func (c implTypeTesterClientStub) InputStruct(ctx *__context.T, i0 Struct, opts ...__ipc.CallOpt) (err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "InputStruct", []interface{}{i0}, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&err); ierr != nil {
- err = ierr
- }
- return
-}
-
-func (c implTypeTesterClientStub) OutputArray(ctx *__context.T, opts ...__ipc.CallOpt) (o0 [2]byte, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputArray", nil, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoArray", []interface{}{i0}, opts...); err != nil {
return
}
if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -245,9 +194,9 @@
return
}
-func (c implTypeTesterClientStub) OutputMap(ctx *__context.T, opts ...__ipc.CallOpt) (o0 map[byte]byte, err error) {
+func (c implTypeTesterClientStub) XEchoMap(ctx *__context.T, i0 map[int32]string, opts ...__ipc.CallOpt) (o0 map[int32]string, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputMap", nil, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoMap", []interface{}{i0}, opts...); err != nil {
return
}
if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -256,9 +205,9 @@
return
}
-func (c implTypeTesterClientStub) OutputSlice(ctx *__context.T, opts ...__ipc.CallOpt) (o0 []byte, err error) {
+func (c implTypeTesterClientStub) XEchoSet(ctx *__context.T, i0 map[int32]struct{}, opts ...__ipc.CallOpt) (o0 map[int32]struct{}, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputSlice", nil, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSet", []interface{}{i0}, opts...); err != nil {
return
}
if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -267,9 +216,9 @@
return
}
-func (c implTypeTesterClientStub) OutputStruct(ctx *__context.T, opts ...__ipc.CallOpt) (o0 Struct, err error) {
+func (c implTypeTesterClientStub) XEchoSlice(ctx *__context.T, i0 []int32, opts ...__ipc.CallOpt) (o0 []int32, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "OutputStruct", nil, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoSlice", []interface{}{i0}, opts...); err != nil {
return
}
if ierr := call.Finish(&o0, &err); ierr != nil {
@@ -278,20 +227,20 @@
return
}
-func (c implTypeTesterClientStub) NoArguments(ctx *__context.T, opts ...__ipc.CallOpt) (err error) {
+func (c implTypeTesterClientStub) XEchoStruct(ctx *__context.T, i0 Struct, opts ...__ipc.CallOpt) (o0 Struct, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "NoArguments", nil, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "XEchoStruct", []interface{}{i0}, opts...); err != nil {
return
}
- if ierr := call.Finish(&err); ierr != nil {
+ if ierr := call.Finish(&o0, &err); ierr != nil {
err = ierr
}
return
}
-func (c implTypeTesterClientStub) MultipleArguments(ctx *__context.T, i0 int32, i1 int32, opts ...__ipc.CallOpt) (o0 int32, o1 int32, err error) {
+func (c implTypeTesterClientStub) YMultiArg(ctx *__context.T, i0 int32, i1 int32, opts ...__ipc.CallOpt) (o0 int32, o1 int32, err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "MultipleArguments", []interface{}{i0, i1}, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "YMultiArg", []interface{}{i0, i1}, opts...); err != nil {
return
}
if ierr := call.Finish(&o0, &o1, &err); ierr != nil {
@@ -300,29 +249,29 @@
return
}
-func (c implTypeTesterClientStub) StreamingOutput(ctx *__context.T, i0 int32, i1 bool, opts ...__ipc.CallOpt) (ocall TypeTesterStreamingOutputCall, err error) {
+func (c implTypeTesterClientStub) YNoArgs(ctx *__context.T, opts ...__ipc.CallOpt) (err error) {
var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "StreamingOutput", []interface{}{i0, i1}, opts...); err != nil {
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "YNoArgs", nil, opts...); err != nil {
return
}
- ocall = &implTypeTesterStreamingOutputCall{Call: call}
- return
-}
-
-func (c implTypeTesterClientStub) Signature(ctx *__context.T, opts ...__ipc.CallOpt) (o0 __ipc.ServiceSignature, err error) {
- var call __ipc.Call
- if call, err = c.c(ctx).StartCall(ctx, c.name, "Signature", nil, opts...); err != nil {
- return
- }
- if ierr := call.Finish(&o0, &err); ierr != nil {
+ if ierr := call.Finish(&err); ierr != nil {
err = ierr
}
return
}
-// TypeTesterStreamingOutputClientStream is the client stream for TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputClientStream interface {
- // RecvStream returns the receiver side of the TypeTester.StreamingOutput client stream.
+func (c implTypeTesterClientStub) ZStream(ctx *__context.T, i0 int32, i1 bool, opts ...__ipc.CallOpt) (ocall TypeTesterZStreamCall, err error) {
+ var call __ipc.Call
+ if call, err = c.c(ctx).StartCall(ctx, c.name, "ZStream", []interface{}{i0, i1}, opts...); err != nil {
+ return
+ }
+ ocall = &implTypeTesterZStreamCall{Call: call}
+ return
+}
+
+// TypeTesterZStreamClientStream is the client stream for TypeTester.ZStream.
+type TypeTesterZStreamClientStream interface {
+ // RecvStream returns the receiver side of the TypeTester.ZStream client stream.
RecvStream() interface {
// Advance stages an item so that it may be retrieved via Value. Returns
// true iff there is an item to retrieve. Advance must be called before
@@ -336,9 +285,9 @@
}
}
-// TypeTesterStreamingOutputCall represents the call returned from TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputCall interface {
- TypeTesterStreamingOutputClientStream
+// TypeTesterZStreamCall represents the call returned from TypeTester.ZStream.
+type TypeTesterZStreamCall interface {
+ TypeTesterZStreamClientStream
// Finish blocks until the server is done, and returns the positional return
// values for call.
//
@@ -352,38 +301,38 @@
Finish() error
}
-type implTypeTesterStreamingOutputCall struct {
+type implTypeTesterZStreamCall struct {
__ipc.Call
valRecv bool
errRecv error
}
-func (c *implTypeTesterStreamingOutputCall) RecvStream() interface {
+func (c *implTypeTesterZStreamCall) RecvStream() interface {
Advance() bool
Value() bool
Err() error
} {
- return implTypeTesterStreamingOutputCallRecv{c}
+ return implTypeTesterZStreamCallRecv{c}
}
-type implTypeTesterStreamingOutputCallRecv struct {
- c *implTypeTesterStreamingOutputCall
+type implTypeTesterZStreamCallRecv struct {
+ c *implTypeTesterZStreamCall
}
-func (c implTypeTesterStreamingOutputCallRecv) Advance() bool {
+func (c implTypeTesterZStreamCallRecv) Advance() bool {
c.c.errRecv = c.c.Recv(&c.c.valRecv)
return c.c.errRecv == nil
}
-func (c implTypeTesterStreamingOutputCallRecv) Value() bool {
+func (c implTypeTesterZStreamCallRecv) Value() bool {
return c.c.valRecv
}
-func (c implTypeTesterStreamingOutputCallRecv) Err() error {
+func (c implTypeTesterZStreamCallRecv) Err() error {
if c.c.errRecv == __io.EOF {
return nil
}
return c.c.errRecv
}
-func (c *implTypeTesterStreamingOutputCall) Finish() (err error) {
+func (c *implTypeTesterZStreamCall) Finish() (err error) {
if ierr := c.Call.Finish(&err); ierr != nil {
err = ierr
}
@@ -392,8 +341,11 @@
// TypeTesterServerMethods is the interface a server writer
// implements for TypeTester.
+//
+// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
type TypeTesterServerMethods interface {
- // Methods to test support for generic types.
+ // Methods to test support for primitive types.
EchoBool(ctx __ipc.ServerContext, I1 bool) (O1 bool, err error)
EchoFloat32(ctx __ipc.ServerContext, I1 float32) (O1 float32, err error)
EchoFloat64(ctx __ipc.ServerContext, I1 float64) (O1 float64, err error)
@@ -401,22 +353,19 @@
EchoInt64(ctx __ipc.ServerContext, I1 int64) (O1 int64, err error)
EchoString(ctx __ipc.ServerContext, I1 string) (O1 string, err error)
EchoByte(ctx __ipc.ServerContext, I1 byte) (O1 byte, err error)
- EchoUInt32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
- EchoUInt64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
+ EchoUint32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
+ EchoUint64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
// Methods to test support for composite types.
- InputArray(ctx __ipc.ServerContext, I1 [2]byte) error
- InputMap(ctx __ipc.ServerContext, I1 map[byte]byte) error
- InputSlice(ctx __ipc.ServerContext, I1 []byte) error
- InputStruct(ctx __ipc.ServerContext, I1 Struct) error
- OutputArray(__ipc.ServerContext) (O1 [2]byte, err error)
- OutputMap(__ipc.ServerContext) (O1 map[byte]byte, err error)
- OutputSlice(__ipc.ServerContext) (O1 []byte, err error)
- OutputStruct(__ipc.ServerContext) (O1 Struct, err error)
+ XEchoArray(ctx __ipc.ServerContext, I1 [2]int32) (O1 [2]int32, err error)
+ XEchoMap(ctx __ipc.ServerContext, I1 map[int32]string) (O1 map[int32]string, err error)
+ XEchoSet(ctx __ipc.ServerContext, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+ XEchoSlice(ctx __ipc.ServerContext, I1 []int32) (O1 []int32, err error)
+ XEchoStruct(ctx __ipc.ServerContext, I1 Struct) (O1 Struct, err error)
// Methods to test support for different number of arguments.
- NoArguments(__ipc.ServerContext) error
- MultipleArguments(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+ YMultiArg(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+ YNoArgs(__ipc.ServerContext) error
// Methods to test support for streaming.
- StreamingOutput(ctx TypeTesterStreamingOutputContext, NumStreamItems int32, StreamItem bool) error
+ ZStream(ctx TypeTesterZStreamContext, NumStreamItems int32, StreamItem bool) error
}
// TypeTesterServerStubMethods is the server interface containing
@@ -424,7 +373,7 @@
// The only difference between this interface and TypeTesterServerMethods
// is the streaming methods.
type TypeTesterServerStubMethods interface {
- // Methods to test support for generic types.
+ // Methods to test support for primitive types.
EchoBool(ctx __ipc.ServerContext, I1 bool) (O1 bool, err error)
EchoFloat32(ctx __ipc.ServerContext, I1 float32) (O1 float32, err error)
EchoFloat64(ctx __ipc.ServerContext, I1 float64) (O1 float64, err error)
@@ -432,22 +381,19 @@
EchoInt64(ctx __ipc.ServerContext, I1 int64) (O1 int64, err error)
EchoString(ctx __ipc.ServerContext, I1 string) (O1 string, err error)
EchoByte(ctx __ipc.ServerContext, I1 byte) (O1 byte, err error)
- EchoUInt32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
- EchoUInt64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
+ EchoUint32(ctx __ipc.ServerContext, I1 uint32) (O1 uint32, err error)
+ EchoUint64(ctx __ipc.ServerContext, I1 uint64) (O1 uint64, err error)
// Methods to test support for composite types.
- InputArray(ctx __ipc.ServerContext, I1 [2]byte) error
- InputMap(ctx __ipc.ServerContext, I1 map[byte]byte) error
- InputSlice(ctx __ipc.ServerContext, I1 []byte) error
- InputStruct(ctx __ipc.ServerContext, I1 Struct) error
- OutputArray(__ipc.ServerContext) (O1 [2]byte, err error)
- OutputMap(__ipc.ServerContext) (O1 map[byte]byte, err error)
- OutputSlice(__ipc.ServerContext) (O1 []byte, err error)
- OutputStruct(__ipc.ServerContext) (O1 Struct, err error)
+ XEchoArray(ctx __ipc.ServerContext, I1 [2]int32) (O1 [2]int32, err error)
+ XEchoMap(ctx __ipc.ServerContext, I1 map[int32]string) (O1 map[int32]string, err error)
+ XEchoSet(ctx __ipc.ServerContext, I1 map[int32]struct{}) (O1 map[int32]struct{}, err error)
+ XEchoSlice(ctx __ipc.ServerContext, I1 []int32) (O1 []int32, err error)
+ XEchoStruct(ctx __ipc.ServerContext, I1 Struct) (O1 Struct, err error)
// Methods to test support for different number of arguments.
- NoArguments(__ipc.ServerContext) error
- MultipleArguments(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+ YMultiArg(ctx __ipc.ServerContext, I1 int32, I2 int32) (O1 int32, O2 int32, err error)
+ YNoArgs(__ipc.ServerContext) error
// Methods to test support for streaming.
- StreamingOutput(ctx *TypeTesterStreamingOutputContextStub, NumStreamItems int32, StreamItem bool) error
+ ZStream(ctx *TypeTesterZStreamContextStub, NumStreamItems int32, StreamItem bool) error
}
// TypeTesterServerStub adds universal methods to TypeTesterServerStubMethods.
@@ -455,8 +401,6 @@
TypeTesterServerStubMethods
// Describe the TypeTester interfaces.
Describe__() []__ipc.InterfaceDesc
- // Signature will be replaced with Describe__.
- Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error)
}
// TypeTesterServer returns a server stub for TypeTester.
@@ -509,56 +453,44 @@
return s.impl.EchoByte(ctx, i0)
}
-func (s implTypeTesterServerStub) EchoUInt32(ctx __ipc.ServerContext, i0 uint32) (uint32, error) {
- return s.impl.EchoUInt32(ctx, i0)
+func (s implTypeTesterServerStub) EchoUint32(ctx __ipc.ServerContext, i0 uint32) (uint32, error) {
+ return s.impl.EchoUint32(ctx, i0)
}
-func (s implTypeTesterServerStub) EchoUInt64(ctx __ipc.ServerContext, i0 uint64) (uint64, error) {
- return s.impl.EchoUInt64(ctx, i0)
+func (s implTypeTesterServerStub) EchoUint64(ctx __ipc.ServerContext, i0 uint64) (uint64, error) {
+ return s.impl.EchoUint64(ctx, i0)
}
-func (s implTypeTesterServerStub) InputArray(ctx __ipc.ServerContext, i0 [2]byte) error {
- return s.impl.InputArray(ctx, i0)
+func (s implTypeTesterServerStub) XEchoArray(ctx __ipc.ServerContext, i0 [2]int32) ([2]int32, error) {
+ return s.impl.XEchoArray(ctx, i0)
}
-func (s implTypeTesterServerStub) InputMap(ctx __ipc.ServerContext, i0 map[byte]byte) error {
- return s.impl.InputMap(ctx, i0)
+func (s implTypeTesterServerStub) XEchoMap(ctx __ipc.ServerContext, i0 map[int32]string) (map[int32]string, error) {
+ return s.impl.XEchoMap(ctx, i0)
}
-func (s implTypeTesterServerStub) InputSlice(ctx __ipc.ServerContext, i0 []byte) error {
- return s.impl.InputSlice(ctx, i0)
+func (s implTypeTesterServerStub) XEchoSet(ctx __ipc.ServerContext, i0 map[int32]struct{}) (map[int32]struct{}, error) {
+ return s.impl.XEchoSet(ctx, i0)
}
-func (s implTypeTesterServerStub) InputStruct(ctx __ipc.ServerContext, i0 Struct) error {
- return s.impl.InputStruct(ctx, i0)
+func (s implTypeTesterServerStub) XEchoSlice(ctx __ipc.ServerContext, i0 []int32) ([]int32, error) {
+ return s.impl.XEchoSlice(ctx, i0)
}
-func (s implTypeTesterServerStub) OutputArray(ctx __ipc.ServerContext) ([2]byte, error) {
- return s.impl.OutputArray(ctx)
+func (s implTypeTesterServerStub) XEchoStruct(ctx __ipc.ServerContext, i0 Struct) (Struct, error) {
+ return s.impl.XEchoStruct(ctx, i0)
}
-func (s implTypeTesterServerStub) OutputMap(ctx __ipc.ServerContext) (map[byte]byte, error) {
- return s.impl.OutputMap(ctx)
+func (s implTypeTesterServerStub) YMultiArg(ctx __ipc.ServerContext, i0 int32, i1 int32) (int32, int32, error) {
+ return s.impl.YMultiArg(ctx, i0, i1)
}
-func (s implTypeTesterServerStub) OutputSlice(ctx __ipc.ServerContext) ([]byte, error) {
- return s.impl.OutputSlice(ctx)
+func (s implTypeTesterServerStub) YNoArgs(ctx __ipc.ServerContext) error {
+ return s.impl.YNoArgs(ctx)
}
-func (s implTypeTesterServerStub) OutputStruct(ctx __ipc.ServerContext) (Struct, error) {
- return s.impl.OutputStruct(ctx)
-}
-
-func (s implTypeTesterServerStub) NoArguments(ctx __ipc.ServerContext) error {
- return s.impl.NoArguments(ctx)
-}
-
-func (s implTypeTesterServerStub) MultipleArguments(ctx __ipc.ServerContext, i0 int32, i1 int32) (int32, int32, error) {
- return s.impl.MultipleArguments(ctx, i0, i1)
-}
-
-func (s implTypeTesterServerStub) StreamingOutput(ctx *TypeTesterStreamingOutputContextStub, i0 int32, i1 bool) error {
- return s.impl.StreamingOutput(ctx, i0, i1)
+func (s implTypeTesterServerStub) ZStream(ctx *TypeTesterZStreamContextStub, i0 int32, i1 bool) error {
+ return s.impl.ZStream(ctx, i0, i1)
}
func (s implTypeTesterServerStub) Globber() *__ipc.GlobState {
@@ -576,10 +508,11 @@
var descTypeTester = __ipc.InterfaceDesc{
Name: "TypeTester",
PkgPath: "v.io/core/veyron/tools/vrpc/test_base",
+ Doc: "// TypeTester methods are listed in alphabetical order, to make it easier to\n// test Signature output, which sorts methods alphabetically.",
Methods: []__ipc.MethodDesc{
{
Name: "EchoBool",
- Doc: "// Methods to test support for generic types.",
+ Doc: "// Methods to test support for primitive types.",
InArgs: []__ipc.ArgDesc{
{"I1", ``}, // bool
},
@@ -649,7 +582,7 @@
},
},
{
- Name: "EchoUInt32",
+ Name: "EchoUint32",
InArgs: []__ipc.ArgDesc{
{"I1", ``}, // uint32
},
@@ -659,7 +592,7 @@
},
},
{
- Name: "EchoUInt64",
+ Name: "EchoUint64",
InArgs: []__ipc.ArgDesc{
{"I1", ``}, // uint64
},
@@ -669,79 +602,59 @@
},
},
{
- Name: "InputArray",
+ Name: "XEchoArray",
Doc: "// Methods to test support for composite types.",
InArgs: []__ipc.ArgDesc{
- {"I1", ``}, // [2]byte
+ {"I1", ``}, // [2]int32
},
OutArgs: []__ipc.ArgDesc{
- {"", ``}, // error
+ {"O1", ``}, // [2]int32
+ {"err", ``}, // error
},
},
{
- Name: "InputMap",
+ Name: "XEchoMap",
InArgs: []__ipc.ArgDesc{
- {"I1", ``}, // map[byte]byte
+ {"I1", ``}, // map[int32]string
},
OutArgs: []__ipc.ArgDesc{
- {"", ``}, // error
+ {"O1", ``}, // map[int32]string
+ {"err", ``}, // error
},
},
{
- Name: "InputSlice",
+ Name: "XEchoSet",
InArgs: []__ipc.ArgDesc{
- {"I1", ``}, // []byte
+ {"I1", ``}, // map[int32]struct{}
},
OutArgs: []__ipc.ArgDesc{
- {"", ``}, // error
+ {"O1", ``}, // map[int32]struct{}
+ {"err", ``}, // error
},
},
{
- Name: "InputStruct",
+ Name: "XEchoSlice",
+ InArgs: []__ipc.ArgDesc{
+ {"I1", ``}, // []int32
+ },
+ OutArgs: []__ipc.ArgDesc{
+ {"O1", ``}, // []int32
+ {"err", ``}, // error
+ },
+ },
+ {
+ Name: "XEchoStruct",
InArgs: []__ipc.ArgDesc{
{"I1", ``}, // Struct
},
OutArgs: []__ipc.ArgDesc{
- {"", ``}, // error
- },
- },
- {
- Name: "OutputArray",
- OutArgs: []__ipc.ArgDesc{
- {"O1", ``}, // [2]byte
- {"err", ``}, // error
- },
- },
- {
- Name: "OutputMap",
- OutArgs: []__ipc.ArgDesc{
- {"O1", ``}, // map[byte]byte
- {"err", ``}, // error
- },
- },
- {
- Name: "OutputSlice",
- OutArgs: []__ipc.ArgDesc{
- {"O1", ``}, // []byte
- {"err", ``}, // error
- },
- },
- {
- Name: "OutputStruct",
- OutArgs: []__ipc.ArgDesc{
{"O1", ``}, // Struct
{"err", ``}, // error
},
},
{
- Name: "NoArguments",
+ Name: "YMultiArg",
Doc: "// Methods to test support for different number of arguments.",
- OutArgs: []__ipc.ArgDesc{
- {"", ``}, // error
- },
- },
- {
- Name: "MultipleArguments",
InArgs: []__ipc.ArgDesc{
{"I1", ``}, // int32
{"I2", ``}, // int32
@@ -753,7 +666,13 @@
},
},
{
- Name: "StreamingOutput",
+ Name: "YNoArgs",
+ OutArgs: []__ipc.ArgDesc{
+ {"", ``}, // error
+ },
+ },
+ {
+ Name: "ZStream",
Doc: "// Methods to test support for streaming.",
InArgs: []__ipc.ArgDesc{
{"NumStreamItems", ``}, // int32
@@ -766,194 +685,9 @@
},
}
-func (s implTypeTesterServerStub) Signature(ctx __ipc.ServerContext) (__ipc.ServiceSignature, error) {
- // TODO(toddw): Replace with new Describe__ implementation.
- result := __ipc.ServiceSignature{Methods: make(map[string]__ipc.MethodSignature)}
- result.Methods["EchoBool"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 2},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 2},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoByte"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 66},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 66},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoFloat32"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 25},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 25},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoFloat64"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 26},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 26},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoInt32"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 36},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 36},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoInt64"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 37},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 37},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoString"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 3},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 3},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoUInt32"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 52},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 52},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["EchoUInt64"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 53},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 53},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["InputArray"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 67},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
- }
- result.Methods["InputMap"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 68},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
- }
- result.Methods["InputSlice"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 69},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
- }
- result.Methods["InputStruct"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 70},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
- }
- result.Methods["MultipleArguments"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "I1", Type: 36},
- {Name: "I2", Type: 36},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 36},
- {Name: "O2", Type: 36},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["NoArguments"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
- }
- result.Methods["OutputArray"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 67},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["OutputMap"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 68},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["OutputSlice"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 69},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["OutputStruct"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{},
- OutArgs: []__ipc.MethodArgument{
- {Name: "O1", Type: 70},
- {Name: "err", Type: 65},
- },
- }
- result.Methods["StreamingOutput"] = __ipc.MethodSignature{
- InArgs: []__ipc.MethodArgument{
- {Name: "NumStreamItems", Type: 36},
- {Name: "StreamItem", Type: 2},
- },
- OutArgs: []__ipc.MethodArgument{
- {Name: "", Type: 65},
- },
-
- OutStream: 2,
- }
-
- result.TypeDefs = []__vdlutil.Any{
- __wiretype.NamedPrimitiveType{Type: 0x1, Name: "error", Tags: []string(nil)}, __wiretype.NamedPrimitiveType{Type: 0x32, Name: "byte", Tags: []string(nil)}, __wiretype.ArrayType{Elem: 0x42, Len: 0x2, Name: "", Tags: []string(nil)}, __wiretype.MapType{Key: 0x42, Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.SliceType{Elem: 0x42, Name: "", Tags: []string(nil)}, __wiretype.StructType{
- []__wiretype.FieldType{
- __wiretype.FieldType{Type: 0x24, Name: "X"},
- __wiretype.FieldType{Type: 0x24, Name: "Y"},
- },
- "v.io/core/veyron/tools/vrpc/test_base.Struct", []string(nil)},
- }
-
- return result, nil
-}
-
-// TypeTesterStreamingOutputServerStream is the server stream for TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputServerStream interface {
- // SendStream returns the send side of the TypeTester.StreamingOutput server stream.
+// TypeTesterZStreamServerStream is the server stream for TypeTester.ZStream.
+type TypeTesterZStreamServerStream interface {
+ // SendStream returns the send side of the TypeTester.ZStream server stream.
SendStream() interface {
// Send places the item onto the output stream. Returns errors encountered
// while sending. Blocks if there is no buffer space; will unblock when
@@ -962,34 +696,34 @@
}
}
-// TypeTesterStreamingOutputContext represents the context passed to TypeTester.StreamingOutput.
-type TypeTesterStreamingOutputContext interface {
+// TypeTesterZStreamContext represents the context passed to TypeTester.ZStream.
+type TypeTesterZStreamContext interface {
__ipc.ServerContext
- TypeTesterStreamingOutputServerStream
+ TypeTesterZStreamServerStream
}
-// TypeTesterStreamingOutputContextStub is a wrapper that converts ipc.ServerCall into
-// a typesafe stub that implements TypeTesterStreamingOutputContext.
-type TypeTesterStreamingOutputContextStub struct {
+// TypeTesterZStreamContextStub is a wrapper that converts ipc.ServerCall into
+// a typesafe stub that implements TypeTesterZStreamContext.
+type TypeTesterZStreamContextStub struct {
__ipc.ServerCall
}
-// Init initializes TypeTesterStreamingOutputContextStub from ipc.ServerCall.
-func (s *TypeTesterStreamingOutputContextStub) Init(call __ipc.ServerCall) {
+// Init initializes TypeTesterZStreamContextStub from ipc.ServerCall.
+func (s *TypeTesterZStreamContextStub) Init(call __ipc.ServerCall) {
s.ServerCall = call
}
-// SendStream returns the send side of the TypeTester.StreamingOutput server stream.
-func (s *TypeTesterStreamingOutputContextStub) SendStream() interface {
+// SendStream returns the send side of the TypeTester.ZStream server stream.
+func (s *TypeTesterZStreamContextStub) SendStream() interface {
Send(item bool) error
} {
- return implTypeTesterStreamingOutputContextSend{s}
+ return implTypeTesterZStreamContextSend{s}
}
-type implTypeTesterStreamingOutputContextSend struct {
- s *TypeTesterStreamingOutputContextStub
+type implTypeTesterZStreamContextSend struct {
+ s *TypeTesterZStreamContextStub
}
-func (s implTypeTesterStreamingOutputContextSend) Send(item bool) error {
+func (s implTypeTesterZStreamContextSend) Send(item bool) error {
return s.s.Send(item)
}
diff --git a/tools/vrpc/vrpc.go b/tools/vrpc/vrpc.go
new file mode 100644
index 0000000..5c025d3
--- /dev/null
+++ b/tools/vrpc/vrpc.go
@@ -0,0 +1,276 @@
+// The following enables go generate to generate the doc.go file.
+//go:generate go run $VANADIUM_ROOT/release/go/src/v.io/lib/cmdline/testdata/gendoc.go .
+
+package main
+
+import (
+ "fmt"
+ "io"
+ "strings"
+ "time"
+
+ "v.io/core/veyron2"
+ "v.io/core/veyron2/context"
+ "v.io/core/veyron2/ipc/reserved"
+ "v.io/core/veyron2/rt"
+ "v.io/core/veyron2/vdl"
+ "v.io/core/veyron2/vdl/build"
+ "v.io/core/veyron2/vdl/codegen/vdlgen"
+ "v.io/core/veyron2/vdl/compile"
+ "v.io/core/veyron2/vdl/vdlroot/src/signature"
+ "v.io/lib/cmdline"
+
+ _ "v.io/core/veyron/profiles"
+)
+
+var runtime veyron2.Runtime
+
+func main() {
+ var err error
+ runtime, err = rt.New()
+ if err != nil {
+ panic(err)
+ }
+ defer runtime.Cleanup()
+ cmdVRPC.Main()
+}
+
+var cmdVRPC = &cmdline.Command{
+ Name: "vrpc",
+ Short: "Vanadium Remote Procedure Call tool",
+ Long: `
+The vrpc tool provides command-line access to Vanadium servers via Remote
+Procedure Call.
+`,
+ // TODO(toddw): Add cmdServe, which will take an interface as input, and set
+ // up a server capable of handling the given methods. When a request is
+ // received, it'll allow the user to respond via stdin.
+ Children: []*cmdline.Command{cmdSignature, cmdCall, cmdIdentify},
+}
+
+const serverDesc = `
+<server> identifies a Vanadium server. It can either be the object address of
+the server, or an object name that will be resolved to an end-point.
+`
+
+var cmdSignature = &cmdline.Command{
+ Run: runSignature,
+ Name: "signature",
+ Short: "Describe the interfaces of a Vanadium server",
+ Long: `
+Signature connects to the Vanadium server identified by <server>.
+
+If no [method] is provided, returns all interfaces implemented by the server.
+
+If a [method] is provided, returns the signature of just that method.
+`,
+ ArgsName: "<server> [method]",
+ ArgsLong: serverDesc + `
+[method] is the optional server method name.
+`,
+}
+
+var cmdCall = &cmdline.Command{
+ Run: runCall,
+ Name: "call",
+ Short: "Call a method of a Vanadium server",
+ Long: `
+Call connects to the Vanadium server identified by <server> and calls the
+<method> with the given positional [args...], returning results on stdout.
+
+TODO(toddw): stdin is read for streaming arguments sent to the server. An EOF
+on stdin (e.g. via ^D) causes the send stream to be closed.
+
+Regardless of whether the call is streaming, the main goroutine blocks for
+streaming and positional results received from the server.
+
+All input arguments (both positional and streaming) are specified as VDL
+expressions, with commas separating multiple expressions. Positional arguments
+may also be specified as separate command-line arguments. Streaming arguments
+may also be specified as separate newline-terminated expressions.
+
+The method signature is always retrieved from the server as a first step. This
+makes it easier to input complex typed arguments, since the top-level type for
+each argument is implicit and doesn't need to be specified.
+`,
+ ArgsName: "<server> <method> [args...]",
+ ArgsLong: serverDesc + `
+<method> is the server method to call.
+
+[args...] are the positional input arguments, specified as VDL expressions.
+`,
+}
+
+var cmdIdentify = &cmdline.Command{
+ Run: runIdentify,
+ Name: "identify",
+ Short: "Reveal blessings presented by a Vanadium server",
+ Long: `
+Identify connects to the Vanadium server identified by <server> and dumps out
+the blessings presented by that server (and the subset of those that are
+considered valid by the principal running this tool) to standard output.
+`,
+ ArgsName: "<server>",
+ ArgsLong: serverDesc,
+}
+
+func runSignature(cmd *cmdline.Command, args []string) error {
+ // Error-check args.
+ var server, method string
+ switch len(args) {
+ case 1:
+ server = args[0]
+ case 2:
+ server, method = args[0], args[1]
+ default:
+ return cmd.UsageErrorf("wrong number of arguments")
+ }
+ // Get the interface or method signature, and pretty-print. We print the
+ // named types after the signatures, to aid in readability.
+ ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+ defer cancel()
+ var types signature.NamedTypes
+ if method != "" {
+ methodSig, err := reserved.MethodSignature(ctx, server, method)
+ if err != nil {
+ return fmt.Errorf("MethodSignature failed: %v", err)
+ }
+ methodSig.Print(cmd.Stdout(), &types)
+ fmt.Fprintln(cmd.Stdout())
+ types.Print(cmd.Stdout())
+ return nil
+ }
+ ifacesSig, err := reserved.Signature(ctx, server)
+ if err != nil {
+ return fmt.Errorf("Signature failed: %v", err)
+ }
+ for i, iface := range ifacesSig {
+ if i > 0 {
+ fmt.Fprintln(cmd.Stdout())
+ }
+ iface.Print(cmd.Stdout(), &types)
+ fmt.Fprintln(cmd.Stdout())
+ }
+ types.Print(cmd.Stdout())
+ return nil
+}
+
+func runCall(cmd *cmdline.Command, args []string) error {
+ // Error-check args, and set up argsdata with a comma-separated list of
+ // arguments, allowing each individual arg to already be comma-separated.
+ //
+ // TODO(toddw): Should we just space-separate the args instead?
+ if len(args) < 2 {
+ return cmd.UsageErrorf("must specify <server> and <method>")
+ }
+ server, method := args[0], args[1]
+ var argsdata string
+ for _, arg := range args[2:] {
+ arg := strings.TrimSpace(arg)
+ if argsdata == "" || strings.HasSuffix(argsdata, ",") || strings.HasPrefix(arg, ",") {
+ argsdata += arg
+ } else {
+ argsdata += "," + arg
+ }
+ }
+ // Get the method signature and parse args.
+ ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+ defer cancel()
+ methodSig, err := reserved.MethodSignature(ctx, server, method)
+ if err != nil {
+ return fmt.Errorf("MethodSignature failed: %v", err)
+ }
+ inargs, err := parseInArgs(argsdata, methodSig)
+ if err != nil {
+ // TODO: Print signature and example.
+ return err
+ }
+ // Start the method call.
+ call, err := veyron2.GetClient(ctx).StartCall(ctx, server, method, inargs)
+ if err != nil {
+ return fmt.Errorf("StartCall failed: %v", err)
+ }
+ // TODO(toddw): Fire off a goroutine to handle streaming inputs.
+ // Handle streaming results.
+StreamingResultsLoop:
+ for {
+ var item *vdl.Value
+ switch err := call.Recv(&item); {
+ case err == io.EOF:
+ break StreamingResultsLoop
+ case err != nil:
+ return fmt.Errorf("call.Recv failed: %v", err)
+ }
+ fmt.Fprintf(cmd.Stdout(), "<< %v\n", vdlgen.TypedConst(item, "", nil))
+ }
+ // Finish the method call.
+ outargs := make([]*vdl.Value, len(methodSig.OutArgs))
+ outptrs := make([]interface{}, len(outargs))
+ for i := range outargs {
+ outptrs[i] = &outargs[i]
+ }
+ if err := call.Finish(outptrs...); err != nil {
+ return fmt.Errorf("call.Finish failed: %v", err)
+ }
+ // Handle application errors, reported as a final error out-arg.
+ //
+ // TODO(toddw): Change call.Finish to report the error directly.
+ outlen := len(outargs)
+ if outlen > 0 && methodSig.OutArgs[outlen-1].Type == vdl.ErrorType {
+ if errarg := outargs[outlen-1]; !errarg.IsNil() {
+ return fmt.Errorf(vdlgen.TypedConst(errarg, "", nil))
+ }
+ outargs = outargs[:outlen-1]
+ }
+ // Pretty-print results.
+ for i, arg := range outargs {
+ if i > 0 {
+ fmt.Fprint(cmd.Stdout(), " ")
+ }
+ fmt.Fprint(cmd.Stdout(), vdlgen.TypedConst(arg, "", nil))
+ }
+ fmt.Fprintln(cmd.Stdout())
+ return nil
+}
+
+func parseInArgs(argsdata string, methodSig signature.Method) ([]interface{}, error) {
+ if len(methodSig.InArgs) == 0 {
+ return nil, nil
+ }
+ var intypes []*vdl.Type
+ for _, inarg := range methodSig.InArgs {
+ intypes = append(intypes, inarg.Type)
+ }
+ env := compile.NewEnv(-1)
+ inargs := build.BuildExprs(argsdata, intypes, env)
+ if err := env.Errors.ToError(); err != nil {
+ return nil, fmt.Errorf("can't parse in-args:\n%v", err)
+ }
+ if got, want := len(inargs), len(methodSig.InArgs); got != want {
+ return nil, fmt.Errorf("got %d args, want %d", got, want)
+ }
+ // Translate []*vdl.Value to []interface, with each item still *vdl.Value.
+ var ret []interface{}
+ for _, arg := range inargs {
+ ret = append(ret, arg)
+ }
+ return ret, nil
+}
+
+func runIdentify(cmd *cmdline.Command, args []string) error {
+ if len(args) != 1 {
+ return cmd.UsageErrorf("wrong number of arguments")
+ }
+ server := args[0]
+ ctx, cancel := context.WithTimeout(runtime.NewContext(), time.Minute)
+ defer cancel()
+ // The method name does not matter - only interested in authentication,
+ // not in actually making an RPC.
+ call, err := veyron2.GetClient(ctx).StartCall(ctx, server, "", nil)
+ if err != nil {
+ return fmt.Errorf(`client.StartCall(%q, "", nil) failed with %v`, server, err)
+ }
+ valid, presented := call.RemoteBlessings()
+ fmt.Fprintf(cmd.Stdout(), "PRESENTED: %v\nVALID: %v\n", presented, valid)
+ return nil
+}
diff --git a/tools/vrpc/vrpc_test.go b/tools/vrpc/vrpc_test.go
new file mode 100644
index 0000000..3b71012
--- /dev/null
+++ b/tools/vrpc/vrpc_test.go
@@ -0,0 +1,311 @@
+package main
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+
+ "v.io/core/veyron2"
+ "v.io/core/veyron2/ipc"
+ "v.io/core/veyron2/rt"
+ "v.io/core/veyron2/vlog"
+
+ "v.io/core/veyron/profiles"
+ "v.io/core/veyron/tools/vrpc/test_base"
+)
+
+type server struct{}
+
+// TypeTester interface implementation
+
+func (*server) EchoBool(call ipc.ServerContext, i1 bool) (bool, error) {
+ vlog.VI(2).Info("EchoBool(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoFloat32(call ipc.ServerContext, i1 float32) (float32, error) {
+ vlog.VI(2).Info("EchoFloat32(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoFloat64(call ipc.ServerContext, i1 float64) (float64, error) {
+ vlog.VI(2).Info("EchoFloat64(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoInt32(call ipc.ServerContext, i1 int32) (int32, error) {
+ vlog.VI(2).Info("EchoInt32(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoInt64(call ipc.ServerContext, i1 int64) (int64, error) {
+ vlog.VI(2).Info("EchoInt64(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoString(call ipc.ServerContext, i1 string) (string, error) {
+ vlog.VI(2).Info("EchoString(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoByte(call ipc.ServerContext, i1 byte) (byte, error) {
+ vlog.VI(2).Info("EchoByte(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoUint32(call ipc.ServerContext, i1 uint32) (uint32, error) {
+ vlog.VI(2).Info("EchoUint32(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) EchoUint64(call ipc.ServerContext, i1 uint64) (uint64, error) {
+ vlog.VI(2).Info("EchoUint64(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) XEchoArray(call ipc.ServerContext, i1 [2]int32) ([2]int32, error) {
+ vlog.VI(2).Info("XEchoArray(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) XEchoMap(call ipc.ServerContext, i1 map[int32]string) (map[int32]string, error) {
+ vlog.VI(2).Info("XEchoMap(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) XEchoSet(call ipc.ServerContext, i1 map[int32]struct{}) (map[int32]struct{}, error) {
+ vlog.VI(2).Info("XEchoSet(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) XEchoSlice(call ipc.ServerContext, i1 []int32) ([]int32, error) {
+ vlog.VI(2).Info("XEchoSlice(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) XEchoStruct(call ipc.ServerContext, i1 test_base.Struct) (test_base.Struct, error) {
+ vlog.VI(2).Info("XEchoStruct(%v) was called.", i1)
+ return i1, nil
+}
+
+func (*server) YMultiArg(call ipc.ServerContext, i1, i2 int32) (int32, int32, error) {
+ vlog.VI(2).Info("YMultiArg(%v,%v) was called.", i1, i2)
+ return i1, i2, nil
+}
+
+func (*server) YNoArgs(call ipc.ServerContext) error {
+ vlog.VI(2).Info("YNoArgs() was called.")
+ return nil
+}
+
+func (*server) ZStream(ctx test_base.TypeTesterZStreamContext, nStream int32, item bool) error {
+ vlog.VI(2).Info("ZStream(%v,%v) was called.", nStream, item)
+ sender := ctx.SendStream()
+ for i := int32(0); i < nStream; i++ {
+ sender.Send(item)
+ }
+ return nil
+}
+
+func initTest(t *testing.T) (name string, cleanup func()) {
+ // The runtime initialized here is the global runtime defined in vrpc.go.
+ var ipcServer ipc.Server
+ cleanup = func() {
+ if ipcServer != nil {
+ if err := ipcServer.Stop(); err != nil {
+ t.Errorf("server.Stop failed: %v", err)
+ }
+ }
+ if runtime != nil {
+ runtime.Cleanup()
+ }
+ }
+ var err error
+ if runtime, err = rt.New(); err != nil {
+ t.Fatalf("rt.New() failed: %v", err)
+ return
+ }
+ if ipcServer, err = veyron2.NewServer(runtime.NewContext()); err != nil {
+ t.Fatalf("NewServer failed: %v", err)
+ return
+ }
+ endpoints, err := ipcServer.Listen(profiles.LocalListenSpec)
+ if err != nil {
+ t.Fatalf("Listen failed: %v", err)
+ return
+ }
+ name = endpoints[0].Name()
+ obj := test_base.TypeTesterServer(&server{})
+ if err := ipcServer.Serve("", obj, nil); err != nil {
+ t.Fatalf("Serve failed: %v", err)
+ return
+ }
+ return
+}
+
+func TestSignature(t *testing.T) {
+ name, cleanup := initTest(t)
+ defer cleanup()
+ var stdout, stderr bytes.Buffer
+ cmdVRPC.Init(nil, &stdout, &stderr)
+
+ if err := cmdVRPC.Execute([]string{"signature", name}); err != nil {
+ t.Errorf("%v", err)
+ return
+ }
+ wantSig := `// TypeTester methods are listed in alphabetical order, to make it easier to
+// test Signature output, which sorts methods alphabetically.
+type "v.io/core/veyron/tools/vrpc/test_base".TypeTester interface {
+ // Methods to test support for primitive types.
+ EchoBool(I1 bool) (O1 bool | error)
+ EchoByte(I1 byte) (O1 byte | error)
+ EchoFloat32(I1 float32) (O1 float32 | error)
+ EchoFloat64(I1 float64) (O1 float64 | error)
+ EchoInt32(I1 int32) (O1 int32 | error)
+ EchoInt64(I1 int64) (O1 int64 | error)
+ EchoString(I1 string) (O1 string | error)
+ EchoUint32(I1 uint32) (O1 uint32 | error)
+ EchoUint64(I1 uint64) (O1 uint64 | error)
+ // Methods to test support for composite types.
+ XEchoArray(I1 [2]int32) (O1 [2]int32 | error)
+ XEchoMap(I1 map[int32]string) (O1 map[int32]string | error)
+ XEchoSet(I1 set[int32]) (O1 set[int32] | error)
+ XEchoSlice(I1 []int32) (O1 []int32 | error)
+ XEchoStruct(I1 "v.io/core/veyron/tools/vrpc/test_base".Struct) (O1 "v.io/core/veyron/tools/vrpc/test_base".Struct | error)
+ // Methods to test support for different number of arguments.
+ YMultiArg(I1 int32, I2 int32) (O1 int32, O2 int32 | error)
+ YNoArgs() error
+ // Methods to test support for streaming.
+ ZStream(NumStreamItems int32, StreamItem bool) stream<_, bool> error
+}
+
+// Reserved methods implemented by the IPC framework. Each method name is prefixed with a double underscore "__".
+type __Reserved interface {
+ // Glob returns all entries matching the pattern.
+ __Glob(pattern string) stream<any, any> error
+ // MethodSignature returns the signature for the given method.
+ __MethodSignature(method string) ("signature".Method | error)
+ // Signature returns all interface signatures implemented by the object.
+ __Signature() ([]"signature".Interface | error)
+}
+
+type "signature".Arg struct {
+ Name string
+ Doc string
+ Type typeobject
+}
+
+type "signature".Embed struct {
+ Name string
+ PkgPath string
+ Doc string
+}
+
+type "signature".Interface struct {
+ Name string
+ PkgPath string
+ Doc string
+ Embeds []"signature".Embed
+ Methods []"signature".Method
+}
+
+type "signature".Method struct {
+ Name string
+ Doc string
+ InArgs []"signature".Arg
+ OutArgs []"signature".Arg
+ InStream ?"signature".Arg
+ OutStream ?"signature".Arg
+ Tags []any
+}
+
+type "v.io/core/veyron/tools/vrpc/test_base".Struct struct {
+ X int32
+ Y int32
+}
+`
+ if got, want := stdout.String(), wantSig; got != want {
+ t.Errorf("got stdout %q, want %q", got, want)
+ }
+ if got, want := stderr.String(), ""; got != want {
+ t.Errorf("got stderr %q, want %q", got, want)
+ }
+}
+
+func TestMethodSignature(t *testing.T) {
+ name, cleanup := initTest(t)
+ defer cleanup()
+
+ tests := []struct {
+ Method, Want string
+ }{
+ // Spot-check some individual methods.
+ {"EchoByte", `EchoByte(I1 byte) (O1 byte | error)`},
+ {"EchoFloat32", `EchoFloat32(I1 float32) (O1 float32 | error)`},
+ {"XEchoStruct", `
+XEchoStruct(I1 "v.io/core/veyron/tools/vrpc/test_base".Struct) (O1 "v.io/core/veyron/tools/vrpc/test_base".Struct | error)
+
+type "v.io/core/veyron/tools/vrpc/test_base".Struct struct {
+ X int32
+ Y int32
+}
+`},
+ }
+ for _, test := range tests {
+ var stdout, stderr bytes.Buffer
+ cmdVRPC.Init(nil, &stdout, &stderr)
+ if err := cmdVRPC.Execute([]string{"signature", name, test.Method}); err != nil {
+ t.Errorf("%q failed: %v", test.Method, err)
+ continue
+ }
+ if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+ t.Errorf("got stdout %q, want %q", got, want)
+ }
+ if got, want := stderr.String(), ""; got != want {
+ t.Errorf("got stderr %q, want %q", got, want)
+ }
+ }
+}
+
+func TestCall(t *testing.T) {
+ name, cleanup := initTest(t)
+ defer cleanup()
+
+ tests := []struct {
+ Method, InArgs, Want string
+ }{
+ {"EchoBool", `true`, `true`},
+ {"EchoBool", `false`, `false`},
+ {"EchoFloat32", `1.2`, `float32(1.2)`},
+ {"EchoFloat64", `-3.4`, `float64(-3.4)`},
+ {"EchoInt32", `11`, `int32(11)`},
+ {"EchoInt64", `-22`, `int64(-22)`},
+ {"EchoString", `"abc"`, `"abc"`},
+ {"EchoByte", `33`, `byte(33)`},
+ {"EchoUint32", `44`, `uint32(44)`},
+ {"EchoUint64", `55`, `uint64(55)`},
+ {"XEchoArray", `{1,2}`, `[2]int32{1, 2}`},
+ {"XEchoMap", `{1:"a"}`, `map[int32]string{1: "a"}`},
+ {"XEchoSet", `{1}`, `set[int32]{1}`},
+ {"XEchoSlice", `{1,2}`, `[]int32{1, 2}`},
+ {"XEchoStruct", `{1,2}`, `"v.io/core/veyron/tools/vrpc/test_base".Struct{X: 1, Y: 2}`},
+ {"YMultiArg", `1,2`, `int32(1) int32(2)`},
+ {"YNoArgs", ``, ``},
+ {"ZStream", `2,true`, `<< true
+<< true`},
+ }
+ for _, test := range tests {
+ var stdout, stderr bytes.Buffer
+ cmdVRPC.Init(nil, &stdout, &stderr)
+ if err := cmdVRPC.Execute([]string{"call", name, test.Method, test.InArgs}); err != nil {
+ t.Errorf("%q(%s) failed: %v", test.Method, test.InArgs, err)
+ continue
+ }
+ if got, want := strings.TrimSpace(stdout.String()), strings.TrimSpace(test.Want); got != want {
+ t.Errorf("got stdout %q, want %q", got, want)
+ }
+ if got, want := stderr.String(), ""; got != want {
+ t.Errorf("got stderr %q, want %q", got, want)
+ }
+ }
+}
diff --git a/tools/vrun/vrun.go b/tools/vrun/vrun.go
index cefeebd..8ebdf7c 100644
--- a/tools/vrun/vrun.go
+++ b/tools/vrun/vrun.go
@@ -134,7 +134,7 @@
return nil, nil, err
}
syscall.CloseOnExec(fd)
- principal, err := agent.NewAgentPrincipal(ctx, fd)
+ principal, err := agent.NewAgentPrincipal(ctx, fd, veyron2.GetClient(ctx))
if err != nil {
vlog.Errorf("Couldn't connect to principal")
return nil, nil, err