Merge "Update IPC benchmark results with Go 1.4."
diff --git a/lib/testutil/integration/util.go b/lib/testutil/integration/util.go
index b535576..fdc0afa 100644
--- a/lib/testutil/integration/util.go
+++ b/lib/testutil/integration/util.go
@@ -2,20 +2,317 @@
import (
"bufio"
+ "bytes"
"fmt"
+ "io"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
+ "syscall"
+ "testing"
"time"
"veyron.io/veyron/veyron/lib/expect"
"veyron.io/veyron/veyron/lib/modules"
"veyron.io/veyron/veyron/lib/modules/core"
+ tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
+ "veyron.io/veyron/veyron2/security"
)
+// TestEnvironment represents a test environment. You should obtain
+// an instance with NewTestEnvironment. Typically, an end-to-end
+// test will begin with:
+// func TestFoo(t *testing.T) {
+// env := integration.NewTestEnvironment(t)
+// defer env.Cleanup()
+//
+// ...
+// }
+type TestEnvironment interface {
+ // Cleanup cleans up the environment and deletes all its artifacts.
+ Cleanup()
+
+ // BuildGoPkg expects a Go package path that identifies a "main"
+ // package and returns a TestBinary representing the newly built
+ // binary.
+ BuildGoPkg(path string) TestBinary
+
+ // RootMT returns the endpoint to the root mounttable for this test
+ // environment.
+ RootMT() string
+
+ // Principal returns the security principal of this environment.
+ Principal() security.Principal
+
+ // DebugShell drops the user into a debug shell. If there is no
+ // controlling TTY, DebugShell will emit a warning message and take no
+ // futher action.
+ DebugShell()
+
+ // TempFile creates a temporary file. Temporary files will be deleted
+ // by Cleanup.
+ TempFile() *os.File
+}
+
+type TestBinary interface {
+ // Start starts the given binary with the given arguments.
+ Start(args ...string) Invocation
+
+ // Path returns the path to the binary.
+ Path() string
+}
+
+type Invocation interface {
+ Stdin() io.Writer
+ Stdout() io.Reader
+ Stderr() io.Reader
+
+ // Output reads the invocation's stdout until EOF and then returns what
+ // was read as a string.
+ Output() string
+
+ // ErrorOutput reads the invocation's stderr until EOF and then returns
+ // what was read as a string.
+ ErrorOutput() string
+
+ // Wait waits for this invocation to finish. If either stdout or stderr
+ // is non-nil, any remaining unread output from those sources will be
+ // written to the corresponding writer.
+ Wait(stdout, stderr io.Writer)
+}
+
+type integrationTestEnvironment struct {
+ // The testing framework.
+ t *testing.T
+
+ // The shell to use to start commands.
+ shell *modules.Shell
+
+ // The environment's root security principal.
+ principal security.Principal
+
+ // Maps path to TestBinary.
+ builtBinaries map[string]*integrationTestBinary
+
+ mtHandle *modules.Handle
+ mtEndpoint string
+
+ tempFiles []*os.File
+}
+
+type integrationTestBinary struct {
+ // The environment to which this binary belongs.
+ env *integrationTestEnvironment
+
+ // The path to the binary.
+ path string
+
+ // The cleanup function to run when the binary exits.
+ cleanupFunc func()
+}
+
+type integrationTestBinaryInvocation struct {
+ // The environment to which this invocation belongs.
+ env *integrationTestEnvironment
+
+ // The handle to the process that was run when this invocation was started.
+ handle *modules.Handle
+}
+
+func (i *integrationTestBinaryInvocation) Stdin() io.Writer {
+ return (*i.handle).Stdin()
+}
+
+func (i *integrationTestBinaryInvocation) Stdout() io.Reader {
+ return (*i.handle).Stdout()
+}
+
+func readerToString(t *testing.T, r io.Reader) string {
+ buf := bytes.Buffer{}
+ _, err := buf.ReadFrom(r)
+ if err != nil {
+ t.Fatalf("ReadFrom() failed: %v", err)
+ }
+ return buf.String()
+}
+
+func (i *integrationTestBinaryInvocation) Output() string {
+ return readerToString(i.env.t, i.Stdout())
+}
+
+func (i *integrationTestBinaryInvocation) Stderr() io.Reader {
+ return (*i.handle).Stderr()
+}
+
+func (i *integrationTestBinaryInvocation) ErrorOutput() string {
+ return readerToString(i.env.t, i.Stderr())
+}
+
+func (i *integrationTestBinaryInvocation) Wait(stdout, stderr io.Writer) {
+ if err := (*i.handle).Shutdown(stdout, stderr); err != nil {
+ i.env.t.Fatalf("Shutdown() failed: %v", err)
+ }
+}
+
+func (b *integrationTestBinary) cleanup() {
+ binaryDir := path.Dir(b.path)
+ b.env.t.Logf("cleaning up %s", binaryDir)
+ if err := os.RemoveAll(binaryDir); err != nil {
+ b.env.t.Logf("WARNING: RemoveAll(%s) failed (%v)", binaryDir, err)
+ }
+}
+
+func (b *integrationTestBinary) Path() string {
+ return b.path
+}
+
+func (b *integrationTestBinary) Start(args ...string) Invocation {
+ b.env.t.Logf("starting %s %s", b.Path(), strings.Join(args, " "))
+ handle, err := b.env.shell.Start("exec", nil, append([]string{b.Path()}, args...)...)
+ if err != nil {
+ b.env.t.Fatalf("Start(%v, %v) failed: %v", b.Path(), strings.Join(args, ", "), err)
+ }
+ return &integrationTestBinaryInvocation{
+ env: b.env,
+ handle: &handle,
+ }
+}
+
+func (e *integrationTestEnvironment) RootMT() string {
+ return e.mtEndpoint
+}
+
+func (e *integrationTestEnvironment) Principal() security.Principal {
+ return e.principal
+}
+
+func (e *integrationTestEnvironment) Cleanup() {
+ for _, binary := range e.builtBinaries {
+ binary.cleanupFunc()
+ }
+
+ for _, tempFile := range e.tempFiles {
+ e.t.Logf("cleaning up %s", tempFile.Name())
+ if err := tempFile.Close(); err != nil {
+ e.t.Logf("WARNING: Close(%s) failed", tempFile, err)
+ }
+ if err := os.Remove(tempFile.Name()); err != nil {
+ e.t.Logf("WARNING: Remove(%s) failed: %v", tempFile.Name(), err)
+ }
+ }
+
+ if err := e.shell.Cleanup(os.Stdout, os.Stderr); err != nil {
+ e.t.Fatalf("WARNING: could not clean up shell (%v)", err)
+ }
+}
+
+func (e *integrationTestEnvironment) DebugShell() {
+ // Get the current working directory.
+ cwd, err := os.Getwd()
+ if err != nil {
+ e.t.Fatalf("Getwd() failed: %v", err)
+ }
+
+ // Transfer stdin, stdout, and stderr to the new process
+ // and also set target directory for the shell to start in.
+ dev := "/dev/tty"
+ fd, err := syscall.Open(dev, 0, 0)
+ if err != nil {
+ e.t.Logf("WARNING: Open(%v) failed, not going to create a debug shell: %v", dev, err)
+ return
+ }
+ attr := os.ProcAttr{
+ Files: []*os.File{os.NewFile(uintptr(fd), "/dev/tty"), os.Stdout, os.Stderr},
+ Dir: cwd,
+ }
+
+ // Start up a new shell.
+ fmt.Printf(">> Starting a new interactive shell\n")
+ fmt.Printf("Hit CTRL-D to resume the test\n")
+ if len(e.builtBinaries) > 0 {
+ fmt.Println("Built binaries:")
+ for _, value := range e.builtBinaries {
+ fmt.Println(value.Path())
+ }
+ }
+ fmt.Println("Root mounttable endpoint:", e.RootMT())
+
+ shellPath := "/bin/sh"
+ proc, err := os.StartProcess(shellPath, []string{}, &attr)
+ if err != nil {
+ e.t.Fatalf("StartProcess(%v) failed: %v", shellPath, err)
+ }
+
+ // Wait until user exits the shell
+ state, err := proc.Wait()
+ if err != nil {
+ e.t.Fatalf("Wait(%v) failed: %v", shellPath, err)
+ }
+
+ fmt.Printf("<< Exited shell: %s\n", state.String())
+}
+
+func (e *integrationTestEnvironment) BuildGoPkg(binary_path string) TestBinary {
+ e.t.Logf("building %s...", binary_path)
+ if cached_binary := e.builtBinaries[binary_path]; cached_binary != nil {
+ e.t.Logf("using cached binary for %s at %s.", binary_path, cached_binary.Path())
+ return cached_binary
+ }
+ built_path, cleanup, err := BuildPkgs([]string{binary_path})
+ if err != nil {
+ e.t.Fatalf("BuildPkgs() failed: %v", err)
+ return nil
+ }
+ output_path := path.Join(built_path, path.Base(binary_path))
+ e.t.Logf("done building %s, written to %s.", binary_path, output_path)
+ binary := &integrationTestBinary{
+ env: e,
+ path: output_path,
+ cleanupFunc: cleanup,
+ }
+ e.builtBinaries[binary_path] = binary
+ return binary
+}
+
+func (e *integrationTestEnvironment) TempFile() *os.File {
+ f, err := ioutil.TempFile("", "")
+ if err != nil {
+ e.t.Fatalf("TempFile() failed: %v", err)
+ }
+ e.t.Logf("created temporary file at %s", f.Name())
+ e.tempFiles = append(e.tempFiles, f)
+ return f
+}
+
+func NewTestEnvironment(t *testing.T) TestEnvironment {
+ t.Log("creating root principal")
+ principal := tsecurity.NewPrincipal("root")
+ shell, err := modules.NewShell(principal)
+ if err != nil {
+ t.Fatalf("NewShell() failed: %v", err)
+ }
+
+ t.Log("starting root mounttable...")
+ mtHandle, mtEndpoint, err := StartRootMT(shell)
+ if err != nil {
+ t.Fatalf("StartRootMT() failed: %v", err)
+ }
+ t.Logf("mounttable available at %s", mtEndpoint)
+
+ return &integrationTestEnvironment{
+ t: t,
+ principal: principal,
+ builtBinaries: make(map[string]*integrationTestBinary),
+ shell: shell,
+ mtHandle: &mtHandle,
+ mtEndpoint: mtEndpoint,
+ tempFiles: []*os.File{},
+ }
+}
+
// BuildPkgs returns a path to a directory that contains the built
// binaries for the given set of packages and a function that should
// be invoked to clean up the build artifacts. Note that the clients
@@ -61,7 +358,7 @@
if err != nil {
return nil, "", err
}
- s := expect.NewSession(nil, handle.Stdout(), time.Second)
+ s := expect.NewSession(nil, handle.Stdout(), 10*time.Second)
s.ExpectVar("PID")
if err := s.Error(); err != nil {
return nil, "", err
diff --git a/security/principal.go b/security/principal.go
index 4ebf6e6..304c4d1 100644
--- a/security/principal.go
+++ b/security/principal.go
@@ -114,23 +114,31 @@
return NewPrincipalFromSigner(security.NewInMemoryECDSASigner(key), state)
}
+// SetDefaultBlessings sets the provided blessings as default and shareable with
+// all peers on provided principal's BlessingStore, and also adds it as a root to
+// the principal's BlessingRoots.
+func SetDefaultBlessings(p security.Principal, blessings security.Blessings) error {
+ if err := p.BlessingStore().SetDefault(blessings); err != nil {
+ return err
+ }
+ if _, err := p.BlessingStore().Set(blessings, security.AllPrincipals); err != nil {
+ return err
+ }
+ if err := p.AddToRoots(blessings); err != nil {
+ return err
+ }
+ return nil
+}
+
// InitDefaultBlessings uses the provided principal to create a self blessing for name 'name',
// sets it as default on the principal's BlessingStore and adds it as root to the principal's BlessingRoots.
+// TODO(ataly): Get rid this function given that we have SetDefaultBlessings.
func InitDefaultBlessings(p security.Principal, name string) error {
blessing, err := p.BlessSelf(name)
if err != nil {
return err
}
- if err := p.BlessingStore().SetDefault(blessing); err != nil {
- return err
- }
- if _, err := p.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
- return err
- }
- if err := p.AddToRoots(blessing); err != nil {
- return err
- }
- return nil
+ return SetDefaultBlessings(p, blessing)
}
func mkDir(dir string) error {
diff --git a/services/mgmt/binary/impl/fs_utils.go b/services/mgmt/binary/impl/fs_utils.go
index 3240d31..d87fd9b 100644
--- a/services/mgmt/binary/impl/fs_utils.go
+++ b/services/mgmt/binary/impl/fs_utils.go
@@ -8,6 +8,7 @@
"strconv"
"strings"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
)
@@ -25,19 +26,19 @@
func checksumExists(path string) error {
switch _, err := os.Stat(path); {
case os.IsNotExist(err):
- return errInvalidPart
+ return verror.Make(errInvalidPart, nil, path)
case err != nil:
vlog.Errorf("Stat(%v) failed: %v", path, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, nil, path)
}
checksumFile := filepath.Join(path, checksum)
_, err := os.Stat(checksumFile)
switch {
case os.IsNotExist(err):
- return errNotFound
+ return verror.Make(verror.NoExist, nil, path)
case err != nil:
vlog.Errorf("Stat(%v) failed: %v", checksumFile, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, nil, path)
default:
return nil
}
@@ -57,7 +58,7 @@
infos, err := ioutil.ReadDir(path)
if err != nil {
vlog.Errorf("ReadDir(%v) failed: %v", path, err)
- return []string{}, errOperationFailed
+ return []string{}, verror.Make(errOperationFailed, nil, path)
}
nDirs := 0
for _, info := range infos {
@@ -72,10 +73,10 @@
idx, err := strconv.Atoi(partName)
if err != nil {
vlog.Errorf("Atoi(%v) failed: %v", partName, err)
- return []string{}, errOperationFailed
+ return []string{}, verror.Make(errOperationFailed, nil, path)
}
if idx < 0 || idx >= len(infos) || result[idx] != "" {
- return []string{}, errOperationFailed
+ return []string{}, verror.Make(errOperationFailed, nil, path)
}
result[idx] = filepath.Join(path, partName)
} else {
@@ -83,7 +84,7 @@
continue
}
// The only entries should correspond to the part dirs.
- return []string{}, errOperationFailed
+ 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 251ff00..1242bd2 100644
--- a/services/mgmt/binary/impl/http.go
+++ b/services/mgmt/binary/impl/http.go
@@ -6,6 +6,7 @@
"path/filepath"
"strings"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
"veyron.io/veyron/veyron/services/mgmt/binary/impl/multipart"
@@ -42,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, errOperationFailed
+ return nil, verror.Make(errOperationFailed, nil, dataPath)
}
}
return multipart.NewFile(name, partFiles)
diff --git a/services/mgmt/binary/impl/impl_test.go b/services/mgmt/binary/impl/impl_test.go
index a34937f..0f1f1ee 100644
--- a/services/mgmt/binary/impl/impl_test.go
+++ b/services/mgmt/binary/impl/impl_test.go
@@ -17,7 +17,7 @@
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/rt"
"veyron.io/veyron/veyron2/services/mgmt/repository"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
"veyron.io/veyron/veyron/lib/testutil"
@@ -320,7 +320,7 @@
}
if err := binary.Create(runtime.NewContext(), int32(length), repository.MediaInfo{Type: "application/octet-stream"}); err == nil {
t.Fatalf("Create() did not fail when it should have")
- } else if want := verror.Exists; !verror.Is(err, want) {
+ } 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 {
@@ -328,12 +328,12 @@
}
if _, err := invokeUpload(t, binary, data[0], 0); err == nil {
t.Fatalf("Upload() did not fail when it should have")
- } else if want := verror.Exists; !verror.Is(err, want) {
+ } 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 {
t.Fatalf("Download() did not fail when it should have")
- } else if want := verror.NoExist; !verror.Is(err, want) {
+ } 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 {
@@ -347,12 +347,12 @@
for _, part := range []int32{-1, length} {
if _, err := invokeUpload(t, binary, []byte("dummy"), part); err == nil {
t.Fatalf("Upload() did not fail when it should have")
- } else if want := verror.BadArg; !verror.Is(err, want) {
+ } else if want := 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 {
t.Fatalf("Download() did not fail when it should have")
- } else if want := verror.BadArg; !verror.Is(err, want) {
+ } else if want := errInvalidPart.ID; !verror.Is(err, want) {
t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
}
}
@@ -361,7 +361,7 @@
}
if err := binary.Delete(runtime.NewContext()); err == nil {
t.Fatalf("Delete() did not fail when it should have")
- } else if want := verror.NoExist; !verror.Is(err, want) {
+ } else if want := verror.NoExist.ID; !verror.Is(err, want) {
t.Fatalf("Unexpected error: %v, expected error id %v", err, want)
}
}
diff --git a/services/mgmt/binary/impl/service.go b/services/mgmt/binary/impl/service.go
index 6249891..e7cfc9d 100644
--- a/services/mgmt/binary/impl/service.go
+++ b/services/mgmt/binary/impl/service.go
@@ -34,7 +34,7 @@
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/services/mgmt/binary"
"veyron.io/veyron/veyron2/services/mgmt/repository"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
)
@@ -50,13 +50,13 @@
suffix string
}
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/binary/impl"
+
var (
- errExists = verror.Existsf("binary already exists")
- errNotFound = verror.NoExistf("binary not found")
- errInProgress = verror.Internalf("identical upload already in progress")
- errInvalidParts = verror.BadArgf("invalid number of binary parts")
- errInvalidPart = verror.BadArgf("invalid binary part number")
- errOperationFailed = verror.Internalf("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
@@ -77,36 +77,36 @@
const bufferLength = 4096
-func (i *binaryService) Create(_ ipc.ServerContext, nparts int32, mediaInfo repository.MediaInfo) error {
+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 errInvalidParts
+ return verror.Make(errInvalidParts, 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 errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
prefix := "creating-"
tmpDir, err := ioutil.TempDir(parent, prefix)
if err != nil {
vlog.Errorf("TempDir(%v, %v) failed: %v", parent, prefix, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, 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 errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
infoFile := filepath.Join(tmpDir, "mediainfo")
jInfo, err := json.Marshal(mediaInfo)
if err != nil {
vlog.Errorf("json.Marshal(%v) failed: %v", mediaInfo, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
if err := ioutil.WriteFile(infoFile, jInfo, os.FileMode(0600)); err != nil {
vlog.Errorf("WriteFile(%q) failed: %v", infoFile, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, 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 errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
}
// Use os.Rename() to atomically create the binary directory
@@ -127,10 +127,10 @@
}
}()
if linkErr, ok := err.(*os.LinkError); ok && linkErr.Err == syscall.ENOTEMPTY {
- return errExists
+ return verror.Make(verror.Exist, context, i.path)
}
vlog.Errorf("Rename(%v, %v) failed: %v", tmpDir, i.path, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, context, i.path)
}
return nil
}
@@ -139,21 +139,21 @@
vlog.Infof("%v.Delete()", i.suffix)
if _, err := os.Stat(i.path); err != nil {
if os.IsNotExist(err) {
- return errNotFound
+ return verror.Make(verror.NoExist, context, i.path)
}
vlog.Errorf("Stat(%v) failed: %v", i.path, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, 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 errOperationFailed
+ return verror.Make(errOperationFailed, context, i.path)
}
if err := os.RemoveAll(path); err != nil {
vlog.Errorf("Remove(%v) failed: %v", path, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, 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 errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
}
return nil
@@ -183,7 +183,7 @@
file, err := os.Open(dataPath)
if err != nil {
vlog.Errorf("Open(%v) failed: %v", dataPath, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
defer file.Close()
buffer := make([]byte, bufferLength)
@@ -192,14 +192,14 @@
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
vlog.Errorf("Read() failed: %v", err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
if n == 0 {
break
}
if err := sender.Send(buffer[:n]); err != nil {
vlog.Errorf("Send() failed: %v", err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
}
return nil
@@ -212,7 +212,7 @@
return i.state.rootURL + "/" + i.suffix, 0, nil
}
-func (i *binaryService) Stat(ipc.ServerContext) ([]binary.PartInfo, repository.MediaInfo, error) {
+func (i *binaryService) Stat(context ipc.ServerContext) ([]binary.PartInfo, repository.MediaInfo, error) {
vlog.Infof("%v.Stat()", i.suffix)
result := make([]binary.PartInfo, 0)
parts, err := getParts(i.path)
@@ -228,7 +228,7 @@
continue
}
vlog.Errorf("ReadFile(%v) failed: %v", checksumFile, err)
- return []binary.PartInfo{}, repository.MediaInfo{}, errOperationFailed
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, 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{}, errOperationFailed
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, 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{}, errOperationFailed
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, 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{}, errOperationFailed
+ return []binary.PartInfo{}, repository.MediaInfo{}, verror.Make(errOperationFailed, context)
}
return result, mediaInfo, nil
}
@@ -260,11 +260,9 @@
vlog.Infof("%v.Upload(%v)", i.suffix, part)
path, suffix := i.generatePartPath(int(part)), ""
err := checksumExists(path)
- switch err {
- case nil:
- return errExists
- case errNotFound:
- default:
+ if err == nil {
+ return verror.Make(verror.Exist, context, path)
+ } else if !verror.Is(err, verror.NoExist.ID) {
return err
}
// Use os.OpenFile() to resolve races.
@@ -272,17 +270,17 @@
lockFile, err := os.OpenFile(lockPath, flags, perm)
if err != nil {
if os.IsExist(err) {
- return errInProgress
+ return verror.Make(errInProgress, context, path)
}
vlog.Errorf("OpenFile(%v, %v, %v) failed: %v", lockPath, flags, suffix, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, 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 errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
defer file.Close()
h := md5.New()
@@ -294,7 +292,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
h.Write(bytes)
}
@@ -304,7 +302,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
hash := hex.EncodeToString(h.Sum(nil))
@@ -314,7 +312,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
dataFile := filepath.Join(path, data)
if err := os.Rename(file.Name(), dataFile); err != nil {
@@ -322,19 +320,19 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, context)
}
return nil
}
-func (i *binaryService) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
+func (i *binaryService) GlobChildren__(context ipc.ServerContext) (<-chan string, error) {
elems := strings.Split(i.suffix, "/")
if len(elems) == 1 && elems[0] == "" {
elems = nil
}
n := i.createObjectNameTree().find(elems, false)
if n == nil {
- return nil, errOperationFailed
+ return nil, verror.Make(errOperationFailed, context)
}
ch := make(chan string, 100)
go func() {
diff --git a/services/mgmt/build/impl/impl_test.go b/services/mgmt/build/impl/impl_test.go
index 4dfc78a..85b4773 100644
--- a/services/mgmt/build/impl/impl_test.go
+++ b/services/mgmt/build/impl/impl_test.go
@@ -48,7 +48,7 @@
t.Fatalf("LookPath(%q) failed: %v", name, err)
}
}
- return pathbin, ""
+ return pathbin, os.Getenv("GOROOT")
}
// startServer starts the build server.
diff --git a/services/mgmt/build/impl/service.go b/services/mgmt/build/impl/service.go
index 83a93ef..59bec9f 100644
--- a/services/mgmt/build/impl/service.go
+++ b/services/mgmt/build/impl/service.go
@@ -12,13 +12,15 @@
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/services/mgmt/binary"
"veyron.io/veyron/veyron2/services/mgmt/build"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
)
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/build/impl"
+
+// Errors
var (
- errBuildFailed = verror.Internalf("build failed")
- errInternalError = verror.Internalf("internal error")
+ errBuildFailed = verror.Register(pkgPath+".errBuildFailed", verror.NoRetry, "{1:}{2:} build failed{:_}")
)
// builderService implements the Builder server interface.
@@ -47,7 +49,7 @@
root, err := ioutil.TempDir(dir, prefix)
if err != nil {
vlog.Errorf("TempDir(%v, %v) failed: %v", dir, prefix, err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
defer os.RemoveAll(root)
if err := os.Chdir(root); err != nil {
@@ -56,7 +58,7 @@
srcDir := filepath.Join(root, "go", "src")
if err := os.MkdirAll(srcDir, dirPerm); err != nil {
vlog.Errorf("MkdirAll(%v, %v) failed: %v", srcDir, dirPerm, err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
iterator := ctx.RecvStream()
for iterator.Advance() {
@@ -65,16 +67,16 @@
dir := filepath.Dir(filePath)
if err := os.MkdirAll(dir, dirPerm); err != nil {
vlog.Errorf("MkdirAll(%v, %v) failed: %v", dir, dirPerm, err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
if err := ioutil.WriteFile(filePath, srcFile.Contents, filePerm); err != nil {
vlog.Errorf("WriteFile(%v, %v) failed: %v", filePath, filePerm, err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
}
if err := iterator.Err(); err != nil {
vlog.Errorf("Advance() failed: %v", err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
cmd := exec.Command(i.gobin, "install", "-v", "./...")
cmd.Env = append(cmd.Env, "GOARCH="+string(arch))
@@ -91,7 +93,7 @@
if output.Len() != 0 {
vlog.Errorf("%v", output.String())
}
- return output.Bytes(), errBuildFailed
+ return output.Bytes(), verror.Make(errBuildFailed, ctx)
}
binDir := filepath.Join(root, "go", "bin")
if runtime.GOARCH != string(arch) || runtime.GOOS != string(opsys) {
@@ -100,14 +102,14 @@
files, err := ioutil.ReadDir(binDir)
if err != nil && !os.IsNotExist(err) {
vlog.Errorf("ReadDir(%v) failed: %v", binDir, err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
for _, file := range files {
binPath := filepath.Join(binDir, file.Name())
bytes, err := ioutil.ReadFile(binPath)
if err != nil {
vlog.Errorf("ReadFile(%v) failed: %v", binPath, err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
result := build.File{
Name: "bin/" + file.Name(),
@@ -115,7 +117,7 @@
}
if err := ctx.SendStream().Send(result); err != nil {
vlog.Errorf("Send() failed: %v", err)
- return nil, errInternalError
+ return nil, verror.Make(verror.Internal, ctx)
}
}
return output.Bytes(), nil
diff --git a/services/mgmt/debug/dispatcher_test.go b/services/mgmt/debug/dispatcher_test.go
index 4a65eaf..84ba35e 100644
--- a/services/mgmt/debug/dispatcher_test.go
+++ b/services/mgmt/debug/dispatcher_test.go
@@ -20,7 +20,7 @@
"veyron.io/veyron/veyron2/services/mgmt/logreader"
"veyron.io/veyron/veyron2/services/mgmt/stats"
vtracesvc "veyron.io/veyron/veyron2/services/mgmt/vtrace"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vtrace"
libstats "veyron.io/veyron/veyron/lib/stats"
@@ -116,7 +116,7 @@
{
lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "debug/logs/nosuchfile.INFO"))
_, err = lf.Size(tracedContext())
- if expected := verror.NoExist; !verror.Is(err, expected) {
+ if expected := verror.NoExist.ID; !verror.Is(err, expected) {
t.Errorf("unexpected error value, got %v, want: %v", err, expected)
}
}
@@ -140,7 +140,7 @@
{
st := stats.StatsClient(naming.JoinAddressName(endpoint, "debug/stats/testing/nobodyhome"))
_, err = st.Value(tracedContext())
- if expected := verror.NoExist; !verror.Is(err, expected) {
+ if expected := verror.NoExist.ID; !verror.Is(err, expected) {
t.Errorf("unexpected error value, got %v, want: %v", err, expected)
}
}
diff --git a/services/mgmt/device/impl/app_service.go b/services/mgmt/device/impl/app_service.go
index bc37a2a..dc61c02 100644
--- a/services/mgmt/device/impl/app_service.go
+++ b/services/mgmt/device/impl/app_service.go
@@ -446,7 +446,7 @@
installationDir := filepath.Join(root, applicationDirName(app), installationDirName(installation))
if _, err := os.Stat(installationDir); err != nil {
if os.IsNotExist(err) {
- return "", verror2.Make(ErrObjectNoExist, nil)
+ return "", verror2.Make(verror2.NoExist, nil, naming.Join(components...))
}
vlog.Errorf("Stat(%v) failed: %v", installationDir, err)
return "", verror2.Make(ErrOperationFailed, nil)
@@ -1220,7 +1220,7 @@
}
i.scanInstance(tree, i.suffix[0], dir)
default:
- return nil, verror2.Make(ErrObjectNoExist, nil)
+ return nil, verror2.Make(verror2.NoExist, nil, i.suffix)
}
n := tree.find(i.suffix, false)
if n == nil {
diff --git a/services/mgmt/device/impl/dispatcher.go b/services/mgmt/device/impl/dispatcher.go
index 1e5bcbb..59bad06 100644
--- a/services/mgmt/device/impl/dispatcher.go
+++ b/services/mgmt/device/impl/dispatcher.go
@@ -27,8 +27,7 @@
"veyron.io/veyron/veyron2/services/mgmt/pprof"
"veyron.io/veyron/veyron2/services/mgmt/stats"
"veyron.io/veyron/veyron2/services/security/access"
- "veyron.io/veyron/veyron2/verror"
- "veyron.io/veyron/veyron2/verror2"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
)
@@ -77,14 +76,13 @@
)
var (
- ErrInvalidSuffix = verror2.Register(pkgPath+".InvalidSuffix", verror2.NoRetry, "")
- ErrOperationFailed = verror2.Register(pkgPath+".OperationFailed", verror2.NoRetry, "")
- ErrOperationInProgress = verror2.Register(pkgPath+".OperationInProgress", verror2.NoRetry, "")
- ErrAppTitleMismatch = verror2.Register(pkgPath+".AppTitleMismatch", verror2.NoRetry, "")
- ErrUpdateNoOp = verror2.Register(pkgPath+".UpdateNoOp", verror2.NoRetry, "")
- ErrObjectNoExist = verror2.Register(pkgPath+".ObjectNoExist", verror2.NoRetry, "")
- ErrInvalidOperation = verror2.Register(pkgPath+".InvalidOperation", verror2.NoRetry, "")
- ErrInvalidBlessing = verror2.Register(pkgPath+".InvalidBlessing", verror2.NoRetry, "")
+ ErrInvalidSuffix = verror.Register(pkgPath+".InvalidSuffix", verror.NoRetry, "{1:}{2:} invalid suffix{:_}")
+ ErrOperationFailed = verror.Register(pkgPath+".OperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
+ ErrOperationInProgress = verror.Register(pkgPath+".OperationInProgress", verror.NoRetry, "{1:}{2:} operation in progress{:_}")
+ ErrAppTitleMismatch = verror.Register(pkgPath+".AppTitleMismatch", verror.NoRetry, "{1:}{2:} app title mismatch{:_}")
+ ErrUpdateNoOp = verror.Register(pkgPath+".UpdateNoOp", verror.NoRetry, "{1:}{2:} update is no op{:_}")
+ ErrInvalidOperation = verror.Register(pkgPath+".InvalidOperation", verror.NoRetry, "{1:}{2:} invalid operation{:_}")
+ ErrInvalidBlessing = verror.Register(pkgPath+".InvalidBlessing", verror.NoRetry, "{1:}{2:} invalid blessing{:_}")
)
// NewDispatcher is the device manager dispatcher factory.
@@ -164,17 +162,17 @@
// Get the blessings to be used by the claimant.
blessings := ctx.Blessings()
if blessings == nil {
- return verror2.Make(ErrInvalidBlessing, ctx)
+ return verror.Make(ErrInvalidBlessing, ctx)
}
principal := ctx.LocalPrincipal()
if err := principal.AddToRoots(blessings); err != nil {
vlog.Errorf("principal.AddToRoots(%s) failed: %v", blessings, err)
- return verror2.Make(ErrInvalidBlessing, ctx)
+ return verror.Make(ErrInvalidBlessing, ctx)
}
names := blessings.ForContext(ctx)
if len(names) == 0 {
vlog.Errorf("No names for claimer(%v) are trusted", blessings)
- return verror2.Make(ErrOperationFailed, nil)
+ return verror.Make(ErrOperationFailed, nil)
}
principal.BlessingStore().Set(blessings, security.AllPrincipals)
principal.BlessingStore().SetDefault(blessings)
@@ -188,11 +186,11 @@
_, etag, err := d.getACL()
if err != nil {
vlog.Errorf("Failed to getACL:%v", err)
- return verror2.Make(ErrOperationFailed, nil)
+ return verror.Make(ErrOperationFailed, nil)
}
if err := d.setACL(principal, acl, etag, true /* store ACL on disk */); err != nil {
vlog.Errorf("Failed to setACL:%v", err)
- return verror2.Make(ErrOperationFailed, nil)
+ return verror.Make(ErrOperationFailed, nil)
}
return nil
}
@@ -230,7 +228,7 @@
}
if len(etag) > 0 && etag != curEtag {
- return verror.Make(access.ErrBadEtag, fmt.Sprintf("etag mismatch in:%s vers:%s", etag, curEtag))
+ return verror.Make(access.BadEtag, nil, etag, curEtag)
}
return writeACLs(principal, aclpath, sigpath, dir, acl)
@@ -287,27 +285,27 @@
data, err := ioutil.TempFile(dir, "data")
if err != nil {
vlog.Errorf("Failed to open tmpfile data:%v", err)
- return verror2.Make(ErrOperationFailed, nil)
+ 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 verror2.Make(ErrOperationFailed, nil)
+ 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 verror2.Make(ErrOperationFailed, nil)
+ return verror.Make(ErrOperationFailed, nil)
}
if err = acl.WriteTo(writer); err != nil {
vlog.Errorf("Failed to SaveACL:%v", err)
- return verror2.Make(ErrOperationFailed, nil)
+ return verror.Make(ErrOperationFailed, nil)
}
if err = writer.Close(); err != nil {
vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
- return verror2.Make(ErrOperationFailed, nil)
+ return verror.Make(ErrOperationFailed, nil)
}
if err := os.Rename(data.Name(), aclFile); err != nil {
return err
@@ -324,7 +322,7 @@
aclFile, sigFile, devicedata := d.getACLFilePaths()
if len(etag) > 0 && etag != d.etag {
- return verror.Make(access.ErrBadEtag, fmt.Sprintf("etag mismatch in:%s vers:%s", etag, d.etag))
+ return verror.Make(access.BadEtag, nil, etag, d.etag)
}
if writeToFile {
if err := writeACLs(principal, aclFile, sigFile, devicedata, acl); err != nil {
@@ -396,7 +394,7 @@
return nil, nil, err
}
if !instanceStateIs(appInstanceDir, started) {
- return nil, nil, verror2.Make(ErrInvalidSuffix, nil)
+ return nil, nil, verror.Make(ErrInvalidSuffix, nil)
}
var sigStub signatureStub
if kind == "pprof" {
@@ -434,7 +432,7 @@
return receiver, appSpecificAuthorizer, nil
case configSuffix:
if len(components) != 2 {
- return nil, nil, verror2.Make(ErrInvalidSuffix, nil)
+ return nil, nil, verror.Make(ErrInvalidSuffix, nil)
}
receiver := idevice.ConfigServer(&configService{
callback: d.internal.callback,
@@ -449,7 +447,7 @@
// (and not other apps).
return receiver, nil, nil
default:
- return nil, nil, verror2.Make(ErrInvalidSuffix, nil)
+ return nil, nil, verror.Make(ErrInvalidSuffix, nil)
}
}
@@ -479,7 +477,7 @@
}
return access.TaggedACLAuthorizerFromFile(path.Join(p, "acls", "data"), access.TypicalTagType())
}
- return nil, verror2.Make(ErrInvalidSuffix, nil)
+ return nil, verror.Make(ErrInvalidSuffix, nil)
}
// allowEveryone implements the authorization policy that allows all principals
diff --git a/services/mgmt/device/impl/impl_test.go b/services/mgmt/device/impl/impl_test.go
index 6ba121e..4f2e138 100644
--- a/services/mgmt/device/impl/impl_test.go
+++ b/services/mgmt/device/impl/impl_test.go
@@ -41,7 +41,7 @@
"veyron.io/veyron/veyron2/services/mgmt/stats"
"veyron.io/veyron/veyron2/services/security/access"
"veyron.io/veyron/veyron2/vdl/vdlutil"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
"veyron.io/veyron/veyron/lib/expect"
@@ -1405,7 +1405,7 @@
// Start an instance of the app but this time it should fail: we do not
// have an associated uname for the invoking identity.
- startAppExpectError(t, appID, verror.NoAccess, selfRT)
+ startAppExpectError(t, appID, verror.NoAccess.ID, selfRT)
// Create an association for selfRT
if err := deviceStub.AssociateAccount(selfRT.NewContext(), []string{"root/self"}, testUserName); err != nil {
@@ -1417,7 +1417,7 @@
stopApp(t, appID, instance1ID, selfRT)
vlog.VI(2).Infof("other attempting to run an app without access. Should fail.")
- startAppExpectError(t, appID, verror.NoAccess, otherRT)
+ startAppExpectError(t, appID, verror.NoAccess.ID, otherRT)
// Self will now let other also install apps.
if err := deviceStub.AssociateAccount(selfRT.NewContext(), []string{"root/other"}, testUserName); err != nil {
@@ -1438,7 +1438,7 @@
// other doesn't have execution permissions for the app. So this will
// fail.
vlog.VI(2).Infof("other attempting to run an app still without access. Should fail.")
- startAppExpectError(t, appID, verror.NoAccess, otherRT)
+ startAppExpectError(t, appID, verror.NoAccess.ID, otherRT)
// But self can give other permissions to start applications.
vlog.VI(2).Infof("self attempting to give other permission to start %s", appID)
@@ -1477,7 +1477,7 @@
}
vlog.VI(2).Infof("Show that Resume with a different systemName fails.")
- resumeAppExpectError(t, appID, instance2ID, verror.NoAccess, otherRT)
+ resumeAppExpectError(t, appID, instance2ID, verror.NoAccess.ID, otherRT)
// Clean up.
stopApp(t, appID, instance2ID, otherRT)
diff --git a/services/mgmt/lib/binary/impl.go b/services/mgmt/lib/binary/impl.go
index 2688fbd..e66a2a6 100644
--- a/services/mgmt/lib/binary/impl.go
+++ b/services/mgmt/lib/binary/impl.go
@@ -17,15 +17,16 @@
"veyron.io/veyron/veyron2/context"
"veyron.io/veyron/veyron2/services/mgmt/binary"
"veyron.io/veyron/veyron2/services/mgmt/repository"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
"veyron.io/veyron/veyron/services/mgmt/lib/packages"
)
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/lib/binary"
+
var (
- errOperationFailed = verror.Internalf("operation failed")
- errNotExist = verror.NoExistf("binary does not exist")
+ errOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
)
const (
@@ -53,7 +54,7 @@
}
for _, part := range parts {
if part.Checksum == binary.MissingChecksum {
- return repository.MediaInfo{}, errNotExist
+ return repository.MediaInfo{}, verror.Make(verror.NoExist, ctx)
}
}
offset, whence := int64(0), 0
@@ -104,7 +105,7 @@
success = true
}
if !success {
- return repository.MediaInfo{}, errOperationFailed
+ return repository.MediaInfo{}, verror.Make(errOperationFailed, ctx)
}
offset += part.Size
}
@@ -116,7 +117,7 @@
file, err := ioutil.TempFile(dir, prefix)
if err != nil {
vlog.Errorf("TempFile(%v, %v) failed: %v", dir, prefix, err)
- return nil, repository.MediaInfo{}, errOperationFailed
+ return nil, repository.MediaInfo{}, verror.Make(errOperationFailed, ctx)
}
defer os.Remove(file.Name())
defer file.Close()
@@ -124,12 +125,12 @@
defer cancel()
mediaInfo, err := download(ctx, file, von)
if err != nil {
- return nil, repository.MediaInfo{}, errOperationFailed
+ return nil, repository.MediaInfo{}, verror.Make(errOperationFailed, ctx)
}
bytes, err := ioutil.ReadFile(file.Name())
if err != nil {
vlog.Errorf("ReadFile(%v) failed: %v", file.Name(), err)
- return nil, repository.MediaInfo{}, errOperationFailed
+ return nil, repository.MediaInfo{}, verror.Make(errOperationFailed, ctx)
}
return bytes, mediaInfo, nil
}
@@ -139,7 +140,7 @@
file, err := ioutil.TempFile(dir, prefix)
if err != nil {
vlog.Errorf("TempFile(%v, %v) failed: %v", dir, prefix, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
defer file.Close()
ctx, cancel := ctx.WithTimeout(time.Minute)
@@ -149,7 +150,7 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
perm := os.FileMode(0600)
if err := file.Chmod(perm); err != nil {
@@ -157,21 +158,21 @@
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
if err := os.Rename(file.Name(), path); err != nil {
vlog.Errorf("Rename(%v, %v) failed: %v", file.Name(), path, err)
if err := os.Remove(file.Name()); err != nil {
vlog.Errorf("Remove(%v) failed: %v", file.Name(), err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
if err := packages.SaveMediaInfo(path, mediaInfo); err != nil {
vlog.Errorf("packages.SaveMediaInfo(%v, %v) failed: %v", path, mediaInfo, err)
if err := os.Remove(path); err != nil {
vlog.Errorf("Remove(%v) failed: %v", path, err)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
return nil
}
@@ -193,7 +194,7 @@
size, err := r.Seek(offset, whence)
if err != nil {
vlog.Errorf("Seek(%v, %v) failed: %v", offset, whence, err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
nparts := (size-1)/partSize + 1
if err := client.Create(ctx, int32(nparts), mediaInfo); err != nil {
@@ -272,7 +273,7 @@
success = true
}
if !success {
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
}
return nil
@@ -290,7 +291,7 @@
defer file.Close()
if err != nil {
vlog.Errorf("Open(%v) failed: %v", err)
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx)
}
ctx, cancel := ctx.WithTimeout(time.Minute)
defer cancel()
diff --git a/services/mgmt/lib/fs/simplestore.go b/services/mgmt/lib/fs/simplestore.go
index cf1d3b1..329d348 100644
--- a/services/mgmt/lib/fs/simplestore.go
+++ b/services/mgmt/lib/fs/simplestore.go
@@ -12,12 +12,25 @@
"veyron.io/veyron/veyron/services/mgmt/profile"
"veyron.io/veyron/veyron2/services/mgmt/application"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
)
// TODO(rjkroege@google.com) Switch Memstore to the mid-August 2014
// style store API.
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/lib/fs"
+
+// Errors
+var (
+ ErrNoRecursiveCreateTransaction = verror.Register(pkgPath+".ErrNoRecursiveCreateTransaction", verror.NoRetry, "{1:}{2:} recursive CreateTransaction() not permitted{:_}")
+ ErrDoubleCommit = verror.Register(pkgPath+".ErrDoubleCommit", verror.NoRetry, "{1:}{2:} illegal attempt to commit previously committed or abandonned transaction{:_}")
+ ErrAbortWithoutTransaction = verror.Register(pkgPath+".ErrAbortWithoutTransaction", verror.NoRetry, "{1:}{2:} illegal attempt to abort non-existent transaction{:_}")
+ ErrWithoutTransaction = verror.Register(pkgPath+".ErrRemoveWithoutTransaction", verror.NoRetry, "{1:}{2:} call without a transaction{:_}")
+ ErrNotInMemStore = verror.Register(pkgPath+".ErrNotInMemStore", verror.NoRetry, "{1:}{2:} not in Memstore{:_}")
+ ErrUnsupportedType = verror.Register(pkgPath+".ErrUnsupportedType", verror.NoRetry, "{1:}{2:} attempted Put to Memstore of unsupported type{:_}")
+ ErrChildrenWithoutLock = verror.Register(pkgPath+".ErrChildrenWithoutLock", verror.NoRetry, "{1:}{2:} Children() without a lock{:_}")
+)
+
// Memstore contains the state of the memstore. It supports a single
// transaction at a time. The current state of a Memstore under a
// transactional name binding is the contents of puts then the contents
@@ -175,7 +188,7 @@
// CreateTransaction requires the caller to acquire a lock on the Memstore.
func (ms *Memstore) CreateTransaction(_ interface{}) (string, error) {
if ms.puts != nil || ms.removes != nil {
- return "", verror.BadProtocolf("recursive CreateTransaction() not permitted")
+ return "", verror.Make(ErrNoRecursiveCreateTransaction, nil)
}
ms.newTransactionState()
return transactionNamePrefix, nil
@@ -184,7 +197,7 @@
// Commit updates the store and persists the result.
func (ms *Memstore) Commit(_ interface{}) error {
if !ms.locked || ms.puts == nil || ms.removes == nil {
- return verror.BadProtocolf("illegal attempt to commit previously committed or abandonned transaction")
+ return verror.Make(ErrDoubleCommit, nil)
}
for k, v := range ms.puts {
ms.data[k] = v
@@ -197,23 +210,23 @@
func (ms *Memstore) Abort(_ interface{}) error {
if !ms.locked {
- return verror.BadProtocolf("illegal attempt to abort non-existent transaction")
+ return verror.Make(ErrAbortWithoutTransaction, nil)
}
return nil
}
func (o *boundObject) Remove(_ interface{}) error {
if !o.ms.locked {
- return verror.BadProtocolf("Remove() without a transaction.")
+ return verror.Make(ErrWithoutTransaction, nil, "Remove()")
}
if _, pendingRemoval := o.ms.removes[o.path]; pendingRemoval {
- return verror.NoExistf("path %s not in Memstore", o.path)
+ return verror.Make(ErrNotInMemStore, nil, o.path)
}
_, found := o.ms.data[o.path]
if !found && !o.ms.removeChildren(o.path) {
- return verror.NoExistf("path %s not in Memstore", o.path)
+ return verror.Make(ErrNotInMemStore, nil, o.path)
}
delete(o.ms.puts, o.path)
o.ms.removes[o.path] = keyExists
@@ -287,7 +300,7 @@
found := inPuts || (inBase && !inRemoves)
if !found {
- return nil, verror.NoExistf("path %s not in Memstore", o.path)
+ return nil, verror.Make(ErrNotInMemStore, nil, o.path)
}
if inPuts {
@@ -302,7 +315,7 @@
bv, inBase := o.ms.data[o.path]
if !inBase {
- return nil, verror.NoExistf("path %s not in Memstore", o.path)
+ return nil, verror.Make(ErrNotInMemStore, nil, o.path)
}
o.Value = bv
@@ -319,7 +332,7 @@
func (o *boundObject) Put(_ interface{}, envelope interface{}) (*boundObject, error) {
if !o.ms.locked {
- return nil, verror.BadProtocolf("Put() without a transaction.")
+ return nil, verror.Make(ErrWithoutTransaction, nil, "Put()")
}
switch v := envelope.(type) {
case application.Envelope, profile.Specification:
@@ -328,13 +341,13 @@
o.Value = o.path
return o, nil
default:
- return o, verror.BadProtocolf("attempted Put to Memstore of unsupported type")
+ return o, verror.Make(ErrUnsupportedType, nil)
}
}
func (o *boundObject) Children() ([]string, error) {
if !o.ms.locked {
- return nil, verror.BadProtocolf("Children() without a lock.")
+ return nil, verror.Make(ErrChildrenWithoutLock, nil)
}
found := false
set := make(map[string]struct{})
@@ -359,7 +372,7 @@
}
}
if !found {
- return nil, verror.NoExistf("object %q does not exist", o.path)
+ return nil, verror.Make(verror.NoExist, nil, o.path)
}
children := make([]string, len(set))
i := 0
diff --git a/services/mgmt/lib/fs/simplestore_test.go b/services/mgmt/lib/fs/simplestore_test.go
index 9957121..b644f76 100644
--- a/services/mgmt/lib/fs/simplestore_test.go
+++ b/services/mgmt/lib/fs/simplestore_test.go
@@ -11,7 +11,7 @@
_ "veyron.io/veyron/veyron/services/mgmt/profile"
"veyron.io/veyron/veyron2/naming"
"veyron.io/veyron/veyron2/services/mgmt/application"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
)
func tempFile(t *testing.T) string {
@@ -247,18 +247,18 @@
}
// At which point, Get() on the transaction won't find anything.
- if _, err := memstoreOriginal.BindObject(fs.TP("/test/a")).Get(nil); !verror.Is(err, verror.NoExist) {
- t.Fatalf("Get() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/test/a"))
+ if _, err := memstoreOriginal.BindObject(fs.TP("/test/a")).Get(nil); !verror.Is(err, fs.ErrNotInMemStore.ID) {
+ t.Fatalf("Get() should have failed: got %v, expected %v", err, verror.Make(fs.ErrNotInMemStore, nil, tname+"/test/a"))
}
// Attempting to Remove() it over again will fail.
- if err := memstoreOriginal.BindObject(fs.TP("/test/a")).Remove(nil); !verror.Is(err, verror.NoExist) {
- t.Fatalf("Remove() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/test/a"))
+ if err := memstoreOriginal.BindObject(fs.TP("/test/a")).Remove(nil); !verror.Is(err, fs.ErrNotInMemStore.ID) {
+ t.Fatalf("Remove() should have failed: got %v, expected %v", err, verror.Make(fs.ErrNotInMemStore, nil, tname+"/test/a"))
}
// Attempting to Remove() a non-existing path will fail.
- if err := memstoreOriginal.BindObject(fs.TP("/foo")).Remove(nil); !verror.Is(err, verror.NoExist) {
- t.Fatalf("Remove() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/foo"))
+ if err := memstoreOriginal.BindObject(fs.TP("/foo")).Remove(nil); !verror.Is(err, fs.ErrNotInMemStore.ID) {
+ t.Fatalf("Remove() should have failed: got %v, expected %v", err, verror.Make(fs.ErrNotInMemStore, nil, tname+"/foo"))
}
// Exists() a non-existing path will fail.
@@ -282,8 +282,8 @@
}
// Validate that Get will fail on a non-existent path.
- if _, err := memstoreOriginal.BindObject("/test/c").Get(nil); !verror.Is(err, verror.NoExist) {
- t.Fatalf("Get() should have failed: got %v, expected %v", err, verror.NoExistf("path %s not in Memstore", tname+"/test/c"))
+ if _, err := memstoreOriginal.BindObject("/test/c").Get(nil); !verror.Is(err, fs.ErrNotInMemStore.ID) {
+ t.Fatalf("Get() should have failed: got %v, expected %v", err, verror.Make(fs.ErrNotInMemStore, nil, tname+"/test/c"))
}
// Verify that the previous Commit() operations have persisted to
@@ -405,18 +405,18 @@
// Put outside ot a transaction should fail.
bindingTnameTestA := memstoreOriginal.BindObject(naming.Join("fooey", "/test/a"))
- if _, err := bindingTnameTestA.Put(nil, envelope); !verror.Is(err, verror.BadProtocol) {
- t.Fatalf("Put() failed: got %v, expected %v", err, verror.BadProtocolf("Put() without a transactional binding"))
+ if _, err := bindingTnameTestA.Put(nil, envelope); !verror.Is(err, fs.ErrWithoutTransaction.ID) {
+ t.Fatalf("Put() failed: got %v, expected %v", err, verror.Make(fs.ErrWithoutTransaction, nil, "Put()"))
}
// Remove outside of a transaction should fail
- if err := bindingTnameTestA.Remove(nil); !verror.Is(err, verror.BadProtocol) {
- t.Fatalf("Put() failed: got %v, expected %v", err, verror.BadProtocolf("Remove() without a transactional binding"))
+ if err := bindingTnameTestA.Remove(nil); !verror.Is(err, fs.ErrWithoutTransaction.ID) {
+ t.Fatalf("Put() failed: got %v, expected %v", err, verror.Make(fs.ErrWithoutTransaction, nil, "Remove()"))
}
// Commit outside of a transaction should fail
- if err := memstoreOriginal.BindTransaction(tname).Commit(nil); !verror.Is(err, verror.BadProtocol) {
- t.Fatalf("Commit() failed: got %v, expected %v", err, verror.BadProtocolf("illegal attempt to commit previously committed or abandonned transaction"))
+ if err := memstoreOriginal.BindTransaction(tname).Commit(nil); !verror.Is(err, fs.ErrDoubleCommit.ID) {
+ t.Fatalf("Commit() failed: got %v, expected %v", err, verror.Make(fs.ErrDoubleCommit, nil))
}
// Attempt inserting a value at /test/b
@@ -434,8 +434,8 @@
memstoreOriginal.Unlock()
// Remove should definitely fail on an abndonned transaction.
- if err := bindingTnameTestB.Remove(nil); !verror.Is(err, verror.BadProtocol) {
- t.Fatalf("Remove() failed: got %v, expected %v", err, verror.Internalf("Remove() without a transactional binding"))
+ if err := bindingTnameTestB.Remove(nil); !verror.Is(err, fs.ErrWithoutTransaction.ID) {
+ t.Fatalf("Remove() failed: got %v, expected %v", err, verror.Make(fs.ErrWithoutTransaction, nil, "Remove()"))
}
}
diff --git a/services/mgmt/logreader/impl/logfile.go b/services/mgmt/logreader/impl/logfile.go
index cbf4606..280e5d3 100644
--- a/services/mgmt/logreader/impl/logfile.go
+++ b/services/mgmt/logreader/impl/logfile.go
@@ -14,15 +14,15 @@
"veyron.io/veyron/veyron2/ipc"
"veyron.io/veyron/veyron2/services/mgmt/logreader"
"veyron.io/veyron/veyron2/services/mgmt/logreader/types"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
)
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/logreader/impl"
+
var (
- errCanceled = verror.Abortedf("operation canceled")
- errNotFound = verror.NoExistf("log file not found")
- errEOF = verror.Make(types.EOF, "EOF")
- errOperationFailed = verror.Internalf("operation failed")
+ errEOF = verror.Register(types.EOF, verror.NoRetry, "{1:}{2:} EOF{:_}")
+ errOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
)
// NewLogFileService returns a new log file server.
@@ -39,7 +39,7 @@
// directory. This could happen if suffix contains "../", which get
// collapsed by filepath.Join().
if !strings.HasPrefix(p, root) {
- return "", errOperationFailed
+ return "", verror.Make(errOperationFailed, nil, name)
}
return p, nil
}
@@ -54,7 +54,7 @@
}
// Size returns the size of the log file, in bytes.
-func (i *logfileService) Size(ipc.ServerContext) (int64, error) {
+func (i *logfileService) Size(ctx ipc.ServerContext) (int64, error) {
vlog.VI(1).Infof("%v.Size()", i.suffix)
fname, err := translateNameToFilename(i.root, i.suffix)
if err != nil {
@@ -63,13 +63,13 @@
fi, err := os.Stat(fname)
if err != nil {
if os.IsNotExist(err) {
- return 0, errNotFound
+ return 0, verror.Make(verror.NoExist, ctx, fname)
}
vlog.Errorf("Stat(%v) failed: %v", fname, err)
- return 0, errOperationFailed
+ return 0, verror.Make(errOperationFailed, ctx, fname)
}
if fi.IsDir() {
- return 0, errOperationFailed
+ return 0, verror.Make(errOperationFailed, ctx, fname)
}
return fi.Size(), nil
}
@@ -84,9 +84,9 @@
f, err := os.Open(fname)
if err != nil {
if os.IsNotExist(err) {
- return 0, errNotFound
+ return 0, verror.Make(verror.NoExist, ctx, fname)
}
- return 0, errOperationFailed
+ return 0, verror.Make(errOperationFailed, ctx, fname)
}
reader := newFollowReader(ctx, f, startpos, follow)
if numEntries == types.AllEntries {
@@ -98,10 +98,10 @@
return reader.tell(), nil
}
if err == io.EOF {
- return reader.tell(), errEOF
+ return reader.tell(), verror.Make(errEOF, ctx)
}
if err != nil {
- return reader.tell(), errOperationFailed
+ return reader.tell(), verror.Make(errOperationFailed, ctx, fname)
}
if err := ctx.SendStream().Send(types.LogEntry{Position: offset, Line: line}); err != nil {
return reader.tell(), err
@@ -112,7 +112,7 @@
// GlobChildren__ returns the list of files in a directory streamed on a
// channel. The list is empty if the object is a file.
-func (i *logfileService) GlobChildren__(ipc.ServerContext) (<-chan string, error) {
+func (i *logfileService) GlobChildren__(ctx ipc.ServerContext) (<-chan string, error) {
vlog.VI(1).Infof("%v.GlobChildren__()", i.suffix)
dirName, err := translateNameToFilename(i.root, i.suffix)
if err != nil {
@@ -121,9 +121,9 @@
stat, err := os.Stat(dirName)
if err != nil {
if os.IsNotExist(err) {
- return nil, errNotFound
+ return nil, verror.Make(verror.NoExist, ctx, dirName)
}
- return nil, errOperationFailed
+ return nil, verror.Make(errOperationFailed, ctx, dirName)
}
if !stat.IsDir() {
return nil, nil
diff --git a/services/mgmt/logreader/impl/logfile_test.go b/services/mgmt/logreader/impl/logfile_test.go
index fb7833c..91db6f3 100644
--- a/services/mgmt/logreader/impl/logfile_test.go
+++ b/services/mgmt/logreader/impl/logfile_test.go
@@ -16,7 +16,7 @@
"veyron.io/veyron/veyron2/security"
"veyron.io/veyron/veyron2/services/mgmt/logreader"
"veyron.io/veyron/veyron2/services/mgmt/logreader/types"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
)
func startServer(t *testing.T, runtime veyron2.Runtime, disp ipc.Dispatcher) (ipc.Server, string, error) {
@@ -99,7 +99,7 @@
// Try to access a file that doesn't exist.
lf := logreader.LogFileClient(naming.JoinAddressName(endpoint, "doesntexist"))
_, err = lf.Size(runtime.NewContext())
- if expected := verror.NoExist; !verror.Is(err, expected) {
+ if expected := verror.NoExist.ID; !verror.Is(err, expected) {
t.Errorf("unexpected error value, got %v, want: %v", err, expected)
}
diff --git a/services/mgmt/logreader/impl/reader.go b/services/mgmt/logreader/impl/reader.go
index 97d1272..301a9c4 100644
--- a/services/mgmt/logreader/impl/reader.go
+++ b/services/mgmt/logreader/impl/reader.go
@@ -7,6 +7,7 @@
"time"
"veyron.io/veyron/veyron2/ipc"
+ verror "veyron.io/veyron/veyron2/verror2"
)
// followReader implements the functionality of io.Reader, plus:
@@ -46,7 +47,7 @@
if f.ctx != nil {
select {
case <-f.ctx.Done():
- return 0, errCanceled
+ return 0, verror.Make(verror.Cancelled, nil)
default:
}
}
diff --git a/services/mgmt/pprof/impl/server.go b/services/mgmt/pprof/impl/server.go
index 21e300d..fd05f30 100644
--- a/services/mgmt/pprof/impl/server.go
+++ b/services/mgmt/pprof/impl/server.go
@@ -9,7 +9,15 @@
"veyron.io/veyron/veyron2/ipc"
spprof "veyron.io/veyron/veyron2/services/mgmt/pprof"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
+)
+
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/pprof/impl"
+
+// Errors
+var (
+ errNoProfile = verror.Register(pkgPath+".errNoProfile", verror.NoRetry, "{1:}{2:} profile does not exist{:_}")
+ errInvalidSeconds = verror.Register(pkgPath+".errInvalidSeconds", verror.NoRetry, "{1:}{2:} invalid number of seconds{:_}")
)
// NewPProfService returns a new pprof service implementation.
@@ -43,10 +51,10 @@
func (pprofService) Profile(ctx spprof.PProfProfileContext, name string, debug int32) error {
profile := pprof.Lookup(name)
if profile == nil {
- return verror.NoExistf("profile does not exist")
+ return verror.Make(errNoProfile, ctx, name)
}
if err := profile.WriteTo(&streamWriter{ctx.SendStream()}, int(debug)); err != nil {
- return verror.Convert(err)
+ return verror.Convert(verror.Unknown, ctx, err)
}
return nil
}
@@ -55,10 +63,10 @@
// streams the profile data.
func (pprofService) CPUProfile(ctx spprof.PProfCPUProfileContext, seconds int32) error {
if seconds <= 0 || seconds > 3600 {
- return verror.BadArgf("invalid number of seconds: %d", seconds)
+ return verror.Make(errInvalidSeconds, ctx, seconds)
}
if err := pprof.StartCPUProfile(&streamWriter{ctx.SendStream()}); err != nil {
- return verror.Convert(err)
+ return verror.Convert(verror.Unknown, ctx, err)
}
time.Sleep(time.Duration(seconds) * time.Second)
pprof.StopCPUProfile()
diff --git a/services/mgmt/stats/impl/stats.go b/services/mgmt/stats/impl/stats.go
index f51b12b..be098d5 100644
--- a/services/mgmt/stats/impl/stats.go
+++ b/services/mgmt/stats/impl/stats.go
@@ -14,7 +14,7 @@
"veyron.io/veyron/veyron2/services/watch"
watchtypes "veyron.io/veyron/veyron2/services/watch/types"
"veyron.io/veyron/veyron2/vdl/vdlutil"
- "veyron.io/veyron/veyron2/verror"
+ verror "veyron.io/veyron/veyron2/verror2"
"veyron.io/veyron/veyron2/vlog"
)
@@ -23,10 +23,11 @@
watchFreq time.Duration
}
+const pkgPath = "veyron.io/veyron/veyron/services/mgmt/stats/impl"
+
var (
- errNotFound = verror.NoExistf("object not found")
- errNoValue = verror.Make(types.NoValue, "object has no value")
- errOperationFailed = verror.Internalf("operation failed")
+ errNoValue = verror.Register(types.NoValue, verror.NoRetry, "{1:}{2:} object has no value{:_}")
+ errOperationFailed = verror.Register(pkgPath+".errOperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
)
// NewStatsService returns a stats server implementation. The value of watchFreq
@@ -76,9 +77,9 @@
}
if err := it.Err(); err != nil {
if err == libstats.ErrNotFound {
- return errNotFound
+ return verror.Make(verror.NoExist, ctx, i.suffix)
}
- return errOperationFailed
+ return verror.Make(errOperationFailed, ctx, i.suffix)
}
for _, change := range changes {
if err := ctx.SendStream().Send(change); err != nil {
@@ -101,12 +102,12 @@
v, err := libstats.Value(i.suffix)
switch err {
case libstats.ErrNotFound:
- return nil, errNotFound
+ return nil, verror.Make(verror.NoExist, ctx, i.suffix)
case libstats.ErrNoValue:
- return nil, errNoValue
+ return nil, verror.Make(errNoValue, ctx, i.suffix)
case nil:
return v, nil
default:
- return nil, errOperationFailed
+ return nil, verror.Make(errOperationFailed, ctx, i.suffix)
}
}
diff --git a/tools/debug/testdata/integration_test.go b/tools/debug/testdata/integration_test.go
new file mode 100644
index 0000000..86be0c9
--- /dev/null
+++ b/tools/debug/testdata/integration_test.go
@@ -0,0 +1,107 @@
+package testdata
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "testing"
+
+ "veyron.io/veyron/veyron/lib/modules"
+ "veyron.io/veyron/veyron/lib/testutil/integration"
+
+ _ "veyron.io/veyron/veyron/profiles/static"
+)
+
+func TestHelperProcess(t *testing.T) {
+ modules.DispatchInTest()
+}
+
+func TestDebugGlob(t *testing.T) {
+ env := integration.NewTestEnvironment(t)
+ defer env.Cleanup()
+
+ binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
+ inv := binary.Start("glob", env.RootMT()+"/__debug/*")
+
+ var want string
+ for _, entry := range []string{"logs", "pprof", "stats", "vtrace"} {
+ want += env.RootMT() + "/__debug/" + entry + "\n"
+ }
+ if got := inv.Output(); got != want {
+ t.Fatalf("unexpected output, want %s, got %s", want, got)
+ }
+}
+
+func TestDebugGlobLogs(t *testing.T) {
+ env := integration.NewTestEnvironment(t)
+ defer env.Cleanup()
+
+ fileName := filepath.Base(env.TempFile().Name())
+ binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
+ output := binary.Start("glob", env.RootMT()+"/__debug/logs/*").Output()
+
+ // The output should contain the filename.
+ want := "/logs/" + fileName
+ if !strings.Contains(output, want) {
+ t.Fatalf("output should contain %s but did not\n%s", want, output)
+ }
+}
+
+func TestReadHostname(t *testing.T) {
+ env := integration.NewTestEnvironment(t)
+ defer env.Cleanup()
+
+ path := env.RootMT() + "/__debug/stats/system/hostname"
+ binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
+ got := binary.Start("stats", "read", path).Output()
+ hostname, err := os.Hostname()
+ if err != nil {
+ t.Fatalf("Hostname() failed: %v", err)
+ }
+ if want := path + ": " + hostname + "\n"; got != want {
+ t.Fatalf("unexpected output, want %s, got %s", want, got)
+ }
+}
+
+func TestLogSize(t *testing.T) {
+ env := integration.NewTestEnvironment(t)
+ defer env.Cleanup()
+
+ binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
+ f := env.TempFile()
+ testLogData := []byte("This is a test log file")
+ f.Write(testLogData)
+
+ // Check to ensure the file size is accurate
+ str := strings.TrimSpace(binary.Start("logs", "size", env.RootMT()+"/__debug/logs/"+filepath.Base(f.Name())).Output())
+ got, err := strconv.Atoi(str)
+ if err != nil {
+ t.Fatalf("Atoi(\"%q\") failed", str)
+ }
+ want := len(testLogData)
+ if got != want {
+ t.Fatalf("unexpected output, want %d, got %d", got, want)
+ }
+}
+
+func TestStatsRead(t *testing.T) {
+ env := integration.NewTestEnvironment(t)
+ defer env.Cleanup()
+
+ binary := env.BuildGoPkg("veyron.io/veyron/veyron/tools/debug")
+ file := env.TempFile()
+ testLogData := []byte("This is a test log file\n")
+ file.Write(testLogData)
+ logName := filepath.Base(file.Name())
+ runCount := 12
+ for i := 0; i < runCount; i++ {
+ binary.Start("logs", "read", env.RootMT()+"/__debug/logs/"+logName).Wait(nil, nil)
+ }
+ got := binary.Start("stats", "read", env.RootMT()+"/__debug/stats/ipc/server/routing-id/*/methods/ReadLog/latency-ms").Output()
+ want := fmt.Sprintf("Count: %d", runCount)
+ if !strings.Contains(got, want) {
+ t.Fatalf("expected output to contain %s, but did not\n", want, got)
+ }
+}
diff --git a/tools/principal/main.go b/tools/principal/main.go
index dfbfd1a..62b4f61 100644
--- a/tools/principal/main.go
+++ b/tools/principal/main.go
@@ -39,11 +39,9 @@
flagSeekBlessingsSetDefault bool
flagSeekBlessingsForPeer string
- // Flag for the create command
- flagCreateOverwrite bool
-
// Flags common to many commands
- flagAddToRoots bool
+ flagAddToRoots bool
+ flagCreateOverwrite bool
// Flags for the "recvblessings" command
flagRecvBlessingsSetDefault bool
@@ -172,7 +170,7 @@
Long: `
Bless another principal.
-The blesser is obtained from the runtime this tool is using. The blessing that
+The blesser is obtained from the runtime this tool is using. The blessing that
will be extended is the default one from the blesser's store, or specified by
the --with flag. Caveats on the blessing are controlled via the --for flag.
@@ -456,16 +454,16 @@
Short: "Create a new principal and persist it into a directory",
Long: `
Creates a new principal with a single self-blessed blessing and writes it out
-to the provided directory. The same directory can be used to set the VEYRON_CREDENTIALS
-environment variables for other veyron applications.
+to the provided directory. The same directory can then be used to set the
+VEYRON_CREDENTIALS environment variable for other veyron applications.
The operation fails if the directory already contains a principal. In this case
-the --overwrite flag can be provided to clear the directory and write out a
+the --overwrite flag can be provided to clear the directory and write out the
new principal.
`,
ArgsName: "<directory> <blessing>",
ArgsLong: `
- <directory> is the directory to which the principal will be persisted.
+ <directory> is the directory to which the new principal will be persisted.
<blessing> is the self-blessed blessing that the principal will be setup to use by default.
`,
Run: func(cmd *cmdline.Command, args []string) error {
@@ -474,18 +472,12 @@
}
dir, name := args[0], args[1]
// TODO(suharshs,ashankar,ataly): How should we make an ecrypted pk... or is that up to the agent?
- var (
- p security.Principal
- err error
- )
if flagCreateOverwrite {
- if err = os.RemoveAll(dir); err != nil {
+ if err := os.RemoveAll(dir); err != nil {
return err
}
- p, err = vsecurity.CreatePersistentPrincipal(dir, nil)
- } else {
- p, err = vsecurity.CreatePersistentPrincipal(dir, nil)
}
+ p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
if err != nil {
return err
}
@@ -493,14 +485,81 @@
if err != nil {
return fmt.Errorf("BlessSelf(%q) failed: %v", name, err)
}
- if err := p.BlessingStore().SetDefault(blessings); err != nil {
- return fmt.Errorf("BlessingStore.SetDefault(%v) failed: %v", blessings, err)
+ if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
+ return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
}
- if _, err := p.BlessingStore().Set(blessings, security.AllPrincipals); err != nil {
- return fmt.Errorf("BlessingStore.Set(%v, %q) failed: %v", blessings, security.AllPrincipals, err)
+ return nil
+ },
+ }
+
+ cmdFork = &cmdline.Command{
+ Name: "fork",
+ Short: "Fork a new principal from the principal that this tool is running as and persist it into a directory",
+ Long: `
+Creates a new principal with a blessing from the principal specified by the
+environment that this tool is running in, and writes it out to the provided
+directory. The blessing that will be extended is the default one from the
+blesser's store, or specified by the --with flag. Caveats on the blessing
+are controlled via the --for flag. The blessing is marked as default and
+shareable with all peers on the new principal's blessing store.
+
+The operation fails if the directory already contains a principal. In this case
+the --overwrite flag can be provided to clear the directory and write out the
+forked principal.
+`,
+ ArgsName: "<directory> <extension>",
+ ArgsLong: `
+ <directory> is the directory to which the forked principal will be persisted.
+ <extension> is the extension under which the forked principal is blessed.
+ `,
+ Run: func(cmd *cmdline.Command, args []string) error {
+ if len(args) != 2 {
+ return fmt.Errorf("requires exactly two arguments: <directory> and <extension>, provided %d", len(args))
}
- if err := p.AddToRoots(blessings); err != nil {
- return fmt.Errorf("AddToRoots(%v) failed: %v", blessings, err)
+ dir, extension := args[0], args[1]
+
+ if flagCreateOverwrite {
+ if err := os.RemoveAll(dir); err != nil {
+ return err
+ }
+ }
+ p, err := vsecurity.CreatePersistentPrincipal(dir, nil)
+ if err != nil {
+ return err
+ }
+
+ runtime, err := rt.New()
+ if err != nil {
+ return err
+ }
+ defer runtime.Cleanup()
+
+ var (
+ with security.Blessings
+ caveats []security.Caveat
+ )
+ if len(flagBlessWith) > 0 {
+ if with, err = decodeBlessings(flagBlessWith); err != nil {
+ return fmt.Errorf("failed to read blessings from --with=%q: %v", flagBlessWith, err)
+ }
+ } else {
+ with = runtime.Principal().BlessingStore().Default()
+ }
+ if c, err := security.ExpiryCaveat(time.Now().Add(flagBlessFor)); err != nil {
+ return fmt.Errorf("failed to create ExpiryCaveat: %v", err)
+ } else {
+ caveats = append(caveats, c)
+ }
+ // TODO(ashankar,ataly,suharshs): Work out how to add additional caveats, like maybe
+ // revocation, method etc.
+
+ key := p.PublicKey()
+ blessings, err := runtime.Principal().Bless(key, with, extension, caveats[0], caveats[1:]...)
+ if err != nil {
+ return fmt.Errorf("Bless(%v, %v, %q, ...) failed: %v", key, with, extension, err)
+ }
+ if err := vsecurity.SetDefaultBlessings(p, blessings); err != nil {
+ return fmt.Errorf("could not set blessings %v as default: %v", blessings, err)
}
return nil
},
@@ -671,6 +730,9 @@
cmdStoreSetDefault.Flags.BoolVar(&flagAddToRoots, "add_to_roots", true, "If true, the root certificate of the blessing will be added to the principal's set of recognized root certificates")
cmdCreate.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
+ cmdFork.Flags.BoolVar(&flagCreateOverwrite, "overwrite", false, "If true, any existing principal data in the directory will be overwritten")
+ cmdFork.Flags.DurationVar(&flagBlessFor, "for", time.Minute, "Duration of blessing validity")
+ cmdFork.Flags.StringVar(&flagBlessWith, "with", "", "Path to file containing blessing to extend")
cmdRecvBlessings.Flags.BoolVar(&flagRecvBlessingsSetDefault, "set_default", true, "If true, the blessings received will be set as the default blessing in the store")
cmdRecvBlessings.Flags.StringVar(&flagRecvBlessingsForPeer, "for_peer", string(security.AllPrincipals), "If non-empty, the blessings received will be marked for peers matching this pattern in the store")
@@ -695,7 +757,7 @@
All objects are printed using base64-VOM-encoding.
`,
- Children: []*cmdline.Command{cmdCreate, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
+ Children: []*cmdline.Command{cmdCreate, cmdFork, cmdSeekBlessings, cmdRecvBlessings, cmdDump, cmdDumpBlessings, cmdBlessSelf, cmdBless, cmdStore},
}).Main()
}
diff --git a/tools/principal/test.sh b/tools/principal/test.sh
index 9761be0..b6404df 100755
--- a/tools/principal/test.sh
+++ b/tools/principal/test.sh
@@ -84,11 +84,21 @@
SEND_BLESSINGS_CMD="${PRINCIPAL_BIN_DIR}/${SEND_BLESSINGS_CMD}"
$(${SEND_BLESSINGS_CMD} 2>error) && shell_test::fail "line ${LINENO}: ${SEND_BLESSINGS_CMD} should have failed"
grep "blessings received from unexpected sender" error >/dev/null || shell_test::fail "line ${LINENO}: unexpected sender error not printed"
+ kill -9 "${RECV_BLESSINGS_PID}"
# Dump carol out, the only blessing that survives should be from the first
# "bless" command. (alice/friend/carol).
- kill -9 "${RECV_BLESSINGS_PID}"
"${PRINCIPAL_BIN}" --veyron.credentials=./carol dump >carol.dump || shell_test::fail "line ${LINENO}: dump failed"
+ # Run fork to setup up credentials for alice-phone that are blessed by alice under the extension "phone".
+ "${PRINCIPAL_BIN}" --veyron.credentials=./alice fork ./alice-phone "phone" >/dev/null || shell_test::fail "line ${LINENO}: fork failed"
+ # Dump alice-phone out, the only blessings it has must be from alice (alice/phone).
+ "${PRINCIPAL_BIN}" --veyron.credentials=./alice-phone dump >alice-phone.dump || shell_test::fail "line ${LINENO}: dump failed"
+
+ # Run fork to setup up credentials for alice-phone-calendar that are blessed by alice-phone under the extension "calendar".
+ "${PRINCIPAL_BIN}" --veyron.credentials=./alice-phone fork ./alice-phone-calendar "calendar" >/dev/null || shell_test::fail "line ${LINENO}: fork failed"
+ # Dump alice-phone-calendar out, the only blessings it has must be from alice-phone (alice/phone/calendar).
+ "${PRINCIPAL_BIN}" --veyron.credentials=./alice-phone-calendar dump >alice-phone-calendar.dump || shell_test::fail "line ${LINENO}: dump failed"
+
# Any other commands to be run without VEYRON_CREDENTIALS set.
unset VEYRON_CREDENTIALS
@@ -166,6 +176,36 @@
if ! diff -C 5 got want; then
shell_test::fail "line ${LINENO}"
fi
+
+ cat alice-phone.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice-phone.dump | rmpublickey failed"
+ cat >want <<EOF
+Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
+---------------- BlessingStore ----------------
+Default blessings: alice/phone
+Peer pattern : Blessings
+... : alice/phone
+---------------- BlessingRoots ----------------
+Public key : Pattern
+XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice/...]
+EOF
+ if ! diff -C 5 got want; then
+ shell_test::fail "line ${LINENO}"
+ fi
+
+ cat alice-phone-calendar.dump | rmpublickey >got || shell_test::fail "line ${LINENO}: cat alice-phone-calendar.dump | rmpublickey failed"
+ cat >want <<EOF
+Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
+---------------- BlessingStore ----------------
+Default blessings: alice/phone/calendar
+Peer pattern : Blessings
+... : alice/phone/calendar
+---------------- BlessingRoots ----------------
+Public key : Pattern
+XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice/...]
+EOF
+ if ! diff -C 5 got want; then
+ shell_test::fail "line ${LINENO}"
+ fi
shell_test::pass
}