open-vault/logical/framework/path.go

134 lines
3.7 KiB
Go
Raw Normal View History

package framework
import (
"bytes"
"fmt"
"sort"
"text/template"
"github.com/hashicorp/vault/logical"
"github.com/mitchellh/go-wordwrap"
)
// Path is a single path that the backend responds to.
type Path struct {
// Pattern is the pattern of the URL that matches this path.
//
// This should be a valid regular expression. Named captures will be
// exposed as fields that should map to a schema in Fields. If a named
// capture is not a field in the Fields map, then it will be ignored.
Pattern string
// Fields is the mapping of data fields to a schema describing that
// field. Named captures in the Pattern also map to fields. If a named
// capture name matches a PUT body name, the named capture takes
// priority.
//
// Note that only named capture fields are available in every operation,
// whereas all fields are avaiable in the Write operation.
Fields map[string]*FieldSchema
// Callbacks are the set of callbacks that are called for a given
// operation. If a callback for a specific operation is not present,
// then logical.ErrUnsupportedOperation is automatically generated.
//
// The help operation is the only operation that the Path will
// automatically handle if the Help field is set. If both the Help
// field is set and there is a callback registered here, then the
// callback will be called.
Callbacks map[logical.Operation]OperationFunc
// Help is text describing how to use this path. This will be used
// to auto-generate the help operation. The Path will automatically
// generate a parameter listing and URL structure based on the
// regular expression, so the help text should just contain a description
// of what happens.
//
// HelpSynopsis is a one-sentence description of the path. This will
// be automatically line-wrapped at 80 characters.
//
// HelpDescription is a long-form description of the path. This will
// be automatically line-wrapped at 80 characters.
HelpSynopsis string
HelpDescription string
}
func (p *Path) helpCallback(req *Request) (*logical.Response, error) {
var tplData pathTemplateData
tplData.Request = req.LogicalRequest.Path
tplData.RoutePattern = p.Pattern
tplData.Synopsis = wordwrap.WrapString(p.HelpSynopsis, 80)
tplData.Description = wordwrap.WrapString(p.HelpDescription, 80)
// Alphabetize the fields
fieldKeys := make([]string, 0, len(p.Fields))
for k, _ := range p.Fields {
fieldKeys = append(fieldKeys, k)
}
sort.Strings(fieldKeys)
// Build the field help
tplData.Fields = make([]pathTemplateFieldData, len(fieldKeys))
for i, k := range fieldKeys {
schema := p.Fields[k]
description := wordwrap.WrapString(schema.Description, 60)
if description == "" {
description = "<no description>"
}
tplData.Fields[i] = pathTemplateFieldData{
Key: k,
Type: schema.Type.String(),
Description: description,
}
}
// Parse the help template
tpl, err := template.New("root").Parse(pathHelpTemplate)
if err != nil {
return nil, fmt.Errorf("error parsing template: %s", err)
}
// Execute the template and store the output
var buf bytes.Buffer
if err := tpl.Execute(&buf, &tplData); err != nil {
return nil, fmt.Errorf("error executing template: %s", err)
}
return logical.HelpResponse(buf.String(), nil), nil
}
type pathTemplateData struct {
Request string
RoutePattern string
Synopsis string
Description string
Fields []pathTemplateFieldData
}
type pathTemplateFieldData struct {
Key string
Type string
Description string
URL bool
}
const pathHelpTemplate = `
Request: {{.Request}}
Matching Route: {{.RoutePattern}}
{{.Synopsis}}
## Parameters
{{range .Fields}}
### {{.Key}} (type: {{.Type}})
{{.Description}}
{{end}}
## Description
{{.Description}}
`