Files
linuxkit/vendor/github.com/docker/infrakit/pkg/plugin/metadata/plugin.go
Rolf Neugebauer 6a29d153f5 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

91 lines
2.1 KiB
Go

package metadata
import (
log "github.com/Sirupsen/logrus"
"github.com/docker/infrakit/pkg/spi/metadata"
"github.com/docker/infrakit/pkg/types"
)
// NewPluginFromData creates a plugin out of a simple data map. Note the updates to the map
// is not guarded and synchronized with the reads.
func NewPluginFromData(data map[string]interface{}) metadata.Plugin {
return &plugin{data: data}
}
// NewPluginFromChannel returns a plugin implementation where reads and writes are serialized
// via channel of functions that have a view to the metadata. Closing the write channel stops
// the serialized read/writes and falls back to unserialized reads.
func NewPluginFromChannel(writes <-chan func(map[string]interface{})) metadata.Plugin {
readChan := make(chan func(map[string]interface{}))
p := &plugin{reads: readChan}
go func() {
defer func() {
if r := recover(); r != nil {
log.Warningln("Plugin stopped:", r)
}
}()
data := map[string]interface{}{}
for {
select {
case writer, open := <-writes:
if !open {
close(readChan)
p.reads = nil
return
}
writer(data)
case reader := <-p.reads:
copy := data
reader(copy)
}
}
}()
return p
}
type plugin struct {
data map[string]interface{}
reads chan func(data map[string]interface{})
}
// List returns a list of *child nodes* given a path, which is specified as a slice
// where for i > j path[i] is the parent of path[j]
func (p *plugin) List(path metadata.Path) ([]string, error) {
if p.reads == nil && p.data != nil {
return List(path, p.data), nil
}
children := make(chan []string)
p.reads <- func(data map[string]interface{}) {
children <- List(path, data)
return
}
return <-children, nil
}
// Get retrieves the value at path given.
func (p *plugin) Get(path metadata.Path) (*types.Any, error) {
if p.reads == nil && p.data != nil {
return types.AnyValue(Get(path, p.data))
}
value := make(chan *types.Any)
err := make(chan error)
p.reads <- func(data map[string]interface{}) {
v, e := types.AnyValue(Get(path, data))
value <- v
err <- e
return
}
return <-value, <-err
}