Files
linuxkit/vendor/github.com/docker/infrakit/pkg/rpc/server/info.go
Rolf Neugebauer 48845bcfd9 infrakit: Move the hyperkit instance plugin into the source directory
- The tools directory ideally should not contain source code
- Removes double vendoring of packagages
- Makes it easer to hook the build into the top-level Makefile

Eventually, the plugin should be moved to the infrakit repo.

Signed-off-by: Rolf Neugebauer <rolf.neugebauer@docker.com>
2017-03-25 13:02:45 +01:00

135 lines
3.5 KiB
Go

package server
import (
"encoding/json"
"net/http"
"github.com/docker/infrakit/pkg/plugin"
"github.com/docker/infrakit/pkg/spi"
"github.com/docker/infrakit/pkg/template"
)
// TypedFunctionExporter is an interface implemented by plugins that supports multiple types in a single RPC endpoint.
// Each typed plugin can export some functions and this interface provides metadata about them.
type TypedFunctionExporter interface {
// Types returns a list of types in this plugin
Types() []string
// FuncsByType returns the template functions exported by each typed plugin
FuncsByType(string) []template.Function
}
// PluginInfo is the service object for the RPC metadata service
type PluginInfo struct {
vendor spi.Vendor
reflectors []*reflector
receiver interface{}
}
// NewPluginInfo returns an instance of the metadata service
func NewPluginInfo(receiver interface{}) (*PluginInfo, error) {
m := &PluginInfo{
reflectors: []*reflector{},
receiver: receiver,
}
if v, is := receiver.(spi.Vendor); is {
m.vendor = v
}
return m, m.Register(receiver)
}
// Register registers an rpc-capable object for introspection and metadata service
func (m *PluginInfo) Register(receiver interface{}) error {
r := &reflector{target: receiver}
m.reflectors = append(m.reflectors, r)
return nil
}
// ShowAPI responds by returning information about the plugin.
func (m *PluginInfo) ShowAPI(resp http.ResponseWriter, req *http.Request) {
meta := m.getInfo()
buff, err := json.Marshal(meta)
if err != nil {
resp.WriteHeader(http.StatusInternalServerError)
resp.Write([]byte(err.Error()))
return
}
resp.Write(buff)
return
}
// ShowTemplateFunctions responds by returning information about template functions the plugin expopses.
func (m *PluginInfo) ShowTemplateFunctions(resp http.ResponseWriter, req *http.Request) {
result := map[string][]template.Function{}
exporter, is := m.receiver.(template.FunctionExporter)
if is {
base := template.UpdateDocumentation(exporter.Funcs())
if len(base) > 0 {
result["base"] = base
}
}
texporter, is := m.receiver.(TypedFunctionExporter)
if is {
for _, t := range texporter.Types() {
typed := template.UpdateDocumentation(texporter.FuncsByType(t))
if len(typed) > 0 {
result[t] = typed
}
}
}
if t, err := template.NewTemplate("str://", template.Options{}); err == nil {
builtin := template.UpdateDocumentation(t.DefaultFuncs())
if len(builtin) > 0 {
result["builtin"] = builtin
}
}
buff, err := json.MarshalIndent(result, "", " ")
if err != nil {
resp.WriteHeader(http.StatusInternalServerError)
resp.Write([]byte(err.Error()))
return
}
resp.Write(buff)
return
}
func (m *PluginInfo) getInfo() *plugin.Info {
meta := &plugin.Info{}
myImplements := []spi.InterfaceSpec{}
myInterfaces := []plugin.InterfaceDescription{}
for _, r := range m.reflectors {
iface := r.Interface()
myImplements = append(myImplements, iface)
descriptions := []plugin.MethodDescription{}
for _, method := range r.pluginMethods() {
desc := r.toDescription(method)
descriptions = append(descriptions, desc)
// sets the example properties which are the custom types for the plugin
r.setExampleProperties(desc.Request.Params)
}
myInterfaces = append(myInterfaces,
plugin.InterfaceDescription{
InterfaceSpec: iface,
Methods: descriptions,
})
}
if m.vendor != nil {
meta.Vendor = m.vendor.VendorInfo()
}
meta.Implements = myImplements
meta.Interfaces = myInterfaces
return meta
}