diff --git a/helper/backend/backend.go b/helper/backend/backend.go index 2b35caa91d..4706ba892a 100644 --- a/helper/backend/backend.go +++ b/helper/backend/backend.go @@ -52,6 +52,37 @@ type Path struct { Callback func(*vault.Request, *FieldData) (*vault.Response, error) } +// vault.LogicalBackend impl. +func (b *Backend) HandleRequest(req *vault.Request) (*vault.Response, error) { + // Find the matching route + path, captures := b.route(req.Path) + if path == nil { + return nil, vault.ErrUnsupportedPath + } + + // Build up the data for the route, with the URL taking priority + // for the fields over the PUT data. + raw := make(map[string]interface{}, len(path.Fields)) + for k, v := range req.Data { + raw[k] = v + } + for k, v := range captures { + raw[k] = v + } + + // Call the callback with the request and the data + return path.Callback(req, &FieldData{ + Raw: raw, + Schema: path.Fields, + }) +} + +// vault.LogicalBackend impl. +func (b *Backend) RootPaths() []string { + // TODO + return nil +} + // Route looks up the path that would be used for a given path string. func (b *Backend) Route(path string) *Path { result, _ := b.route(path) diff --git a/helper/backend/backend_test.go b/helper/backend/backend_test.go index 77cf350302..00c6087f79 100644 --- a/helper/backend/backend_test.go +++ b/helper/backend/backend_test.go @@ -3,6 +3,8 @@ package backend import ( "reflect" "testing" + + "github.com/hashicorp/vault/vault" ) func BenchmarkBackendRoute(b *testing.B) { @@ -33,6 +35,106 @@ func BenchmarkBackendRoute(b *testing.B) { } } +func TestBackend_impl(t *testing.T) { + var _ vault.LogicalBackend = new(Backend) +} + +func TestBackendHandleRequest(t *testing.T) { + callback := func(req *vault.Request, data *FieldData) (*vault.Response, error) { + return &vault.Response{ + Data: map[string]interface{}{ + "value": data.Get("value"), + }, + }, nil + } + + b := &Backend{ + Paths: []*Path{ + &Path{ + Pattern: "foo/bar", + Fields: map[string]*FieldSchema{ + "value": &FieldSchema{Type: TypeInt}, + }, + Callback: callback, + }, + }, + } + + resp, err := b.HandleRequest(&vault.Request{ + Path: "foo/bar", + Data: map[string]interface{}{"value": "42"}, + }) + if err != nil { + t.Fatalf("err: %s", err) + } + if resp.Data["value"] != 42 { + t.Fatalf("bad: %#v", resp) + } +} + +func TestBackendHandleRequest_404(t *testing.T) { + callback := func(req *vault.Request, data *FieldData) (*vault.Response, error) { + return &vault.Response{ + Data: map[string]interface{}{ + "value": data.Get("value"), + }, + }, nil + } + + b := &Backend{ + Paths: []*Path{ + &Path{ + Pattern: `foo/bar`, + Fields: map[string]*FieldSchema{ + "value": &FieldSchema{Type: TypeInt}, + }, + Callback: callback, + }, + }, + } + + _, err := b.HandleRequest(&vault.Request{ + Path: "foo/baz", + Data: map[string]interface{}{"value": "84"}, + }) + if err != vault.ErrUnsupportedPath { + t.Fatalf("err: %s", err) + } +} + +func TestBackendHandleRequest_urlPriority(t *testing.T) { + callback := func(req *vault.Request, data *FieldData) (*vault.Response, error) { + return &vault.Response{ + Data: map[string]interface{}{ + "value": data.Get("value"), + }, + }, nil + } + + b := &Backend{ + Paths: []*Path{ + &Path{ + Pattern: `foo/(?P\d+)`, + Fields: map[string]*FieldSchema{ + "value": &FieldSchema{Type: TypeInt}, + }, + Callback: callback, + }, + }, + } + + resp, err := b.HandleRequest(&vault.Request{ + Path: "foo/42", + Data: map[string]interface{}{"value": "84"}, + }) + if err != nil { + t.Fatalf("err: %s", err) + } + if resp.Data["value"] != 42 { + t.Fatalf("bad: %#v", resp) + } +} + func TestBackendRoute(t *testing.T) { cases := map[string]struct { Patterns []string