Host component related work
This commit is contained in:
parent
908b1e3449
commit
05d5634c83
@ -1,8 +1,10 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/hashicorp/vagrant-plugin-sdk/component"
|
||||
sdkcore "github.com/hashicorp/vagrant-plugin-sdk/core"
|
||||
"github.com/hashicorp/vagrant-plugin-sdk/terminal"
|
||||
"github.com/hashicorp/vagrant/builtin/myplugin/host/cap"
|
||||
)
|
||||
|
||||
@ -12,8 +14,6 @@ type HostConfig struct {
|
||||
// AlwaysTrueHost is a Host implementation for myplugin.
|
||||
type AlwaysTrueHost struct {
|
||||
config HostConfig
|
||||
|
||||
sdkcore.CapabilityHost
|
||||
}
|
||||
|
||||
// DetectFunc implements component.Host
|
||||
@ -22,16 +22,35 @@ func (h *AlwaysTrueHost) DetectFunc() interface{} {
|
||||
}
|
||||
|
||||
func (h *AlwaysTrueHost) Detect() bool {
|
||||
h.InitializeCapabilities()
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *AlwaysTrueHost) InitializeCapabilities() (err error) {
|
||||
err = h.RegisterCapability("write_hello", cap.WriteHello)
|
||||
return
|
||||
func (h *AlwaysTrueHost) HasCapabilityFunc() interface{} {
|
||||
return h.CheckCapability
|
||||
}
|
||||
|
||||
func (h *AlwaysTrueHost) CheckCapability(n *component.NamedCapability) bool {
|
||||
if n.Capability == "write_hello" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *AlwaysTrueHost) CapabilityFunc(name string) interface{} {
|
||||
if name == "write_hello" {
|
||||
return h.WriteHelloCap
|
||||
}
|
||||
return errors.New("Invalid capability requested")
|
||||
}
|
||||
|
||||
func (h *AlwaysTrueHost) WriteHelloCap(ui terminal.UI) error {
|
||||
return cap.WriteHello(ui)
|
||||
}
|
||||
|
||||
func (h *AlwaysTrueHost) WriteHelloCapNoUI() error {
|
||||
return cap.WriteHelloNoUI()
|
||||
}
|
||||
|
||||
var (
|
||||
_ component.Host = (*AlwaysTrueHost)(nil)
|
||||
_ sdkcore.Host = (*AlwaysTrueHost)(nil)
|
||||
)
|
||||
|
||||
@ -13,3 +13,10 @@ func WriteHello(ui terminal.UI) error {
|
||||
ioutil.WriteFile("/tmp/hello", data, 0644)
|
||||
return nil
|
||||
}
|
||||
|
||||
func WriteHelloNoUI() error {
|
||||
msg := "Hello from the write hello capability, compliments of the AlwaysTrue Host"
|
||||
data := []byte(msg)
|
||||
ioutil.WriteFile("/tmp/hello", data, 0644)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/DavidGamba/go-getoptions/option"
|
||||
"github.com/hashicorp/go-argmapper"
|
||||
"github.com/hashicorp/vagrant-plugin-sdk/component"
|
||||
plugincore "github.com/hashicorp/vagrant-plugin-sdk/core"
|
||||
|
||||
@ -157,18 +156,28 @@ func (c *Command) ExecuteOfni(trm terminal.UI) int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *Command) ExecuteUseHostPlugin(trm terminal.UI, host plugincore.Host) int64 {
|
||||
trm.Output("I'm going to use a the host plugin to do something!")
|
||||
ok := host.HasCapability("write_hello")
|
||||
func (c *Command) ExecuteUseHostPlugin(trm terminal.UI, basis plugincore.Basis) int64 {
|
||||
trm.Output("I'm going to use a the host plugin to do something!\n\n")
|
||||
host, err := basis.Host()
|
||||
if err != nil {
|
||||
trm.Output("Error: Failed to receive host plugin - " + err.Error() + "\n\n")
|
||||
return 1
|
||||
}
|
||||
ok, err := host.HasCapability("write_hello")
|
||||
if err != nil {
|
||||
trm.Output("ERROR: " + err.Error() + "\n\n")
|
||||
// return 1
|
||||
}
|
||||
if ok {
|
||||
trm.Output("Writing to file using `write_hello` capability")
|
||||
_, err := host.Capability("write_hello", argmapper.Typed(trm))
|
||||
trm.Output("Writing to file using `write_hello` capability\n\n")
|
||||
_, err = host.Capability("write_hello", trm)
|
||||
if err != nil {
|
||||
trm.Output("Error!")
|
||||
trm.Output("Error executing capability - " + err.Error() + "\n\n")
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
trm.Output("no `write_hello` capability found")
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ func BaseCommand(ctx context.Context, log hclog.Logger, logOutput io.Writer, opt
|
||||
|
||||
// Start building our client options
|
||||
basisOpts := []clientpkg.Option{
|
||||
clientpkg.WithLogger(bc.Log),
|
||||
clientpkg.WithLogger(bc.Log.ResetNamed("vagrant.client")),
|
||||
clientpkg.WithClientConnect(connectOpts...),
|
||||
clientpkg.WithBasis(
|
||||
&vagrant_server.Basis{
|
||||
@ -431,7 +431,7 @@ func (c *baseCommand) Do(ctx context.Context, f func(context.Context, Tasker) er
|
||||
// Start with checking if we are running in a machine based scope
|
||||
if len(c.targets) > 0 {
|
||||
for _, m := range c.targets {
|
||||
c.Log.Warn("running command on target", "target", m)
|
||||
c.Log.Debug("running command on target", "target", m)
|
||||
// If the context has been canceled, then bail
|
||||
if err := ctx.Err(); err != nil {
|
||||
return err
|
||||
|
||||
@ -228,7 +228,7 @@ func Commands(
|
||||
func logger(args []string) ([]string, hclog.Logger, io.Writer, error) {
|
||||
app := args[0]
|
||||
|
||||
// Determine our log level if we have any. First override we check if env var
|
||||
// Determine our log level if we have any. First override we check is env var
|
||||
level := hclog.NoLevel
|
||||
if v := os.Getenv(EnvLogLevel); v != "" {
|
||||
level = hclog.LevelFromString(v)
|
||||
|
||||
@ -38,7 +38,7 @@ type Basis struct {
|
||||
|
||||
func New(ctx context.Context, opts ...Option) (basis *Basis, err error) {
|
||||
basis = &Basis{
|
||||
logger: hclog.L().Named("basis"),
|
||||
logger: hclog.L(),
|
||||
runner: &vagrant_server.Ref_Runner{
|
||||
Target: &vagrant_server.Ref_Runner_Any{
|
||||
Any: &vagrant_server.Ref_RunnerAny{},
|
||||
@ -55,6 +55,8 @@ func New(ctx context.Context, opts ...Option) (basis *Basis, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
basis.logger = basis.logger.Named("basis")
|
||||
|
||||
// If no internal basis was provided, set it up now
|
||||
if basis.basis == nil {
|
||||
vh, err := paths.VagrantHome()
|
||||
|
||||
@ -11,7 +11,7 @@ func (b *Basis) startRunner() (*runner.Runner, error) {
|
||||
r, err := runner.New(
|
||||
runner.WithClient(b.client),
|
||||
runner.WithVagrantRubyRuntime(b.vagrantRubyRuntime),
|
||||
runner.WithLogger(b.logger.Named("runner")),
|
||||
runner.WithLogger(b.logger),
|
||||
runner.ByIdOnly(), // We'll direct target this
|
||||
runner.WithLocal(b.UI()), // Local mode
|
||||
)
|
||||
|
||||
@ -35,7 +35,7 @@ import (
|
||||
// found, this will spin up an in-memory server.
|
||||
//
|
||||
func (b *Basis) initServerClient(ctx context.Context, cfg *config) (*grpc.ClientConn, error) {
|
||||
log := b.logger.Named("server")
|
||||
log := b.logger.ResetNamed("vagrant.server")
|
||||
|
||||
// If we're local, then connection is optional.
|
||||
opts := cfg.connectOpts
|
||||
@ -73,7 +73,7 @@ func (b *Basis) initServerClient(ctx context.Context, cfg *config) (*grpc.Client
|
||||
// If this returns an error, all resources associated with this operation
|
||||
// will be closed, but the project can retry.
|
||||
func (b *Basis) initLocalServer(ctx context.Context) (_ *grpc.ClientConn, err error) {
|
||||
log := b.logger.Named("server")
|
||||
log := b.logger.ResetNamed("vagrant.server")
|
||||
b.localServer = true
|
||||
|
||||
// We use this pointer to accumulate things we need to clean up
|
||||
|
||||
@ -73,6 +73,12 @@ func NewBasis(ctx context.Context, opts ...BasisOption) (b *Basis, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if b.logger.IsTrace() {
|
||||
b.logger = b.logger.Named("basis")
|
||||
} else {
|
||||
b.logger = b.logger.ResetNamed("vagrant.core.basis")
|
||||
}
|
||||
|
||||
if b.basis == nil {
|
||||
return nil, errors.New("basis data was not properly loaded")
|
||||
}
|
||||
@ -96,8 +102,9 @@ func NewBasis(ctx context.Context, opts ...BasisOption) (b *Basis, err error) {
|
||||
// If the mappers aren't already set, load known mappers
|
||||
if len(b.mappers) == 0 {
|
||||
b.mappers, err = argmapper.NewFuncList(protomappers.All,
|
||||
argmapper.Logger(b.logger),
|
||||
argmapper.Logger(dynamicLogger),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -161,6 +168,15 @@ func (b *Basis) Client() *serverclient.VagrantClient {
|
||||
return b.client
|
||||
}
|
||||
|
||||
func (b *Basis) Host() (host core.Host, err error) {
|
||||
h, err := b.findHostPlugin(b.ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
host = h.Value.(core.Host)
|
||||
return
|
||||
}
|
||||
|
||||
func (b *Basis) Init() (result *vagrant_server.Job_InitResult, err error) {
|
||||
b.logger.Debug("running init for basis")
|
||||
f := b.factories[component.CommandType]
|
||||
@ -203,7 +219,6 @@ func (b *Basis) Init() (result *vagrant_server.Job_InitResult, err error) {
|
||||
b.convertCommandInfo(r, []string{})...)
|
||||
}
|
||||
|
||||
b.logger.Warn("resulting init commands", "commands", result.Commands)
|
||||
return
|
||||
}
|
||||
|
||||
@ -224,7 +239,7 @@ func (b *Basis) LoadProject(popts ...ProjectOption) (p *Project, err error) {
|
||||
p = &Project{
|
||||
ctx: b.ctx,
|
||||
basis: b,
|
||||
logger: b.logger.Named("project"),
|
||||
logger: b.logger,
|
||||
mappers: b.mappers,
|
||||
factories: b.factories,
|
||||
targets: map[string]*Target{},
|
||||
@ -237,6 +252,7 @@ func (b *Basis) LoadProject(popts ...ProjectOption) (p *Project, err error) {
|
||||
err = multierror.Append(err, oerr)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -249,6 +265,12 @@ func (b *Basis) LoadProject(popts ...ProjectOption) (p *Project, err error) {
|
||||
// Set our loaded project into the basis
|
||||
b.projects[p.project.ResourceId] = p
|
||||
|
||||
if p.logger.IsTrace() {
|
||||
p.logger = p.logger.Named("project")
|
||||
} else {
|
||||
p.logger = p.logger.ResetNamed("vagrant.core.project")
|
||||
}
|
||||
|
||||
// Ensure project directory is set
|
||||
if p.dir == nil {
|
||||
if p.dir, err = b.dir.Project(p.project.Name); err != nil {
|
||||
@ -399,6 +421,9 @@ func (b *Basis) findHostPlugin(ctx context.Context) (*Component, error) {
|
||||
h,
|
||||
h.Value.(component.Host).DetectFunc(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if detected != nil && detected.(bool) {
|
||||
return h, nil
|
||||
}
|
||||
@ -451,7 +476,7 @@ func (b *Basis) startPlugin(
|
||||
typ component.Type,
|
||||
n string,
|
||||
) (*plugin.Instance, error) {
|
||||
log := b.logger.Named(strings.ToLower(typ.String()))
|
||||
log := b.logger.ResetNamed(fmt.Sprintf("vagrant.plugin.%s.%s", strings.ToLower(typ.String()), n))
|
||||
|
||||
f, ok := b.factories[typ]
|
||||
if !ok {
|
||||
@ -465,11 +490,11 @@ func (b *Basis) startPlugin(
|
||||
}
|
||||
|
||||
// Call the factory to get our raw value (interface{} type)
|
||||
fnResult := fn.Call(argmapper.Typed(ctx, log))
|
||||
fnResult := fn.Call(argmapper.Typed(ctx, log), argmapper.Logger(dynamicLogger))
|
||||
if err := fnResult.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Info("initialized component", "type", typ.String())
|
||||
log.Info("initialized component", "type", typ.String(), "name", n)
|
||||
raw := fnResult.Out(0)
|
||||
|
||||
// If we have a plugin.Instance then we can extract other information
|
||||
@ -494,13 +519,14 @@ func (b *Basis) callDynamicFunc(
|
||||
f interface{}, // function
|
||||
args ...argmapper.Arg,
|
||||
) (interface{}, error) {
|
||||
// We allow f to be a *mapper.Func because our plugin system creates
|
||||
// a func directly due to special argument types.
|
||||
// TODO: test
|
||||
rawFunc, ok := f.(*argmapper.Func)
|
||||
if !ok {
|
||||
var rawFunc *argmapper.Func
|
||||
if fn, ok := f.(*argmapper.Func); ok {
|
||||
rawFunc = fn
|
||||
} else if fn, ok := f.(*component.SpicyFunc); ok {
|
||||
rawFunc = fn.Func
|
||||
} else {
|
||||
var err error
|
||||
rawFunc, err = argmapper.NewFunc(f, argmapper.Logger(log))
|
||||
rawFunc, err = argmapper.NewFunc(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -512,11 +538,12 @@ func (b *Basis) callDynamicFunc(
|
||||
|
||||
args = append(args,
|
||||
argmapper.ConverterFunc(b.mappers...),
|
||||
argmapper.Typed(b, b.ui, ctx, log),
|
||||
argmapper.Typed(b, b.ui, ctx, log.Named("plugin-call")),
|
||||
argmapper.Named("basis", b),
|
||||
argmapper.Logger(dynamicLogger),
|
||||
)
|
||||
|
||||
b.logger.Info("running dynamic call from basis", "basis", b)
|
||||
b.logger.Info("running dynamic call from basis", "basis", b, "func", rawFunc.Name())
|
||||
|
||||
// Build the chain and call it
|
||||
callResult := rawFunc.Call(args...)
|
||||
@ -690,3 +717,8 @@ func WithBasisResourceId(rid string) BasisOption {
|
||||
}
|
||||
|
||||
var _ core.Basis = (*Basis)(nil)
|
||||
|
||||
var dynamicLogger hclog.Logger = hclog.New(&hclog.LoggerOptions{
|
||||
Name: "vagrant.core.dynamic-function",
|
||||
Level: hclog.Error,
|
||||
})
|
||||
|
||||
@ -97,11 +97,7 @@ func (p *Project) DefaultPrivateKey() (path string, err error) {
|
||||
}
|
||||
|
||||
func (p *Project) Host() (host core.Host, err error) {
|
||||
hostComponent, err := p.basis.findHostPlugin(p.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hostComponent.Value.(core.Host), nil
|
||||
return p.basis.Host()
|
||||
}
|
||||
|
||||
func (p *Project) MachineNames() (names []string, err error) {
|
||||
@ -156,7 +152,7 @@ func (p *Project) LoadTarget(topts ...TargetOption) (t *Target, err error) {
|
||||
t = &Target{
|
||||
ctx: p.ctx,
|
||||
project: p,
|
||||
logger: p.logger.Named("target"),
|
||||
logger: p.logger,
|
||||
ui: p.ui,
|
||||
}
|
||||
|
||||
@ -178,6 +174,12 @@ func (p *Project) LoadTarget(topts ...TargetOption) (t *Target, err error) {
|
||||
|
||||
p.targets[t.target.ResourceId] = t
|
||||
|
||||
if t.logger.IsTrace() {
|
||||
t.logger = t.logger.Named("target")
|
||||
} else {
|
||||
t.logger = t.logger.ResetNamed("vagrant.core.target")
|
||||
}
|
||||
|
||||
if t.dir == nil {
|
||||
if t.dir, err = p.dir.Target(t.target.Name); err != nil {
|
||||
return
|
||||
|
||||
@ -166,22 +166,15 @@ func (t *Target) Run(ctx context.Context, task *vagrant_server.Task) (err error)
|
||||
return
|
||||
}
|
||||
|
||||
host, _ := t.project.Host()
|
||||
|
||||
// _, err = t.callDynamicFunc(
|
||||
// ctx,
|
||||
// t.logger,
|
||||
// (interface{})(nil),
|
||||
// nil,
|
||||
// host.(component.Host).CapabilityFunc("write_hello"),
|
||||
// argmapper.Typed(t.ui),
|
||||
// )
|
||||
// host.Capability("write_hello", argmapper.Typed(t.ui))
|
||||
host, err := t.project.Host()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result, err := t.callDynamicFunc(
|
||||
ctx,
|
||||
t.logger,
|
||||
(interface{})(nil),
|
||||
nil,
|
||||
cmd,
|
||||
cmd.Value.(component.Command).ExecuteFunc(strings.Split(task.CommandName, " ")),
|
||||
argmapper.Typed(task.CliArgs, t.jobInfo, t.dir, host),
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/go-plugin"
|
||||
@ -20,6 +21,7 @@ type Builtin struct {
|
||||
log hclog.Logger
|
||||
cancel context.CancelFunc
|
||||
ctx context.Context
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewBuiltins(ctx context.Context, log hclog.Logger) *Builtin {
|
||||
@ -33,6 +35,8 @@ func NewBuiltins(ctx context.Context, log hclog.Logger) *Builtin {
|
||||
}
|
||||
|
||||
func (b *Builtin) ConnectInfo(name string) (*plugin.ReattachConfig, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
r, ok := b.servers[name]
|
||||
if !ok {
|
||||
b.log.Error("failed to locate plugin", "name", name, "servers", b.servers)
|
||||
@ -54,7 +58,12 @@ func (b *Builtin) Add(name string, opts ...sdk.Option) (err error) {
|
||||
opts = append(opts, sdk.InProcess(cfg), sdk.WithLogger(b.log))
|
||||
|
||||
// Spin off a new go routine to get the reattach config
|
||||
go func() { b.servers[name] = <-reCh }()
|
||||
go func() {
|
||||
rc := <-reCh
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
b.servers[name] = rc
|
||||
}()
|
||||
|
||||
// Add the plugin server to our group
|
||||
b.group.Add(func() error {
|
||||
|
||||
@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// disable in process plugins by default for now
|
||||
const IN_PROCESS_PLUGINS = true
|
||||
const IN_PROCESS_PLUGINS = false
|
||||
|
||||
var (
|
||||
// Builtins is the map of all available builtin plugins and their
|
||||
|
||||
@ -106,6 +106,7 @@ func New(opts ...Option) (*Runner, error) {
|
||||
}
|
||||
}
|
||||
|
||||
runner.logger = runner.logger.ResetNamed("vagrant.runner")
|
||||
// Setup our runner components list
|
||||
for t, f := range runner.factories {
|
||||
for _, n := range f.Registered() {
|
||||
|
||||
@ -30,6 +30,7 @@ func Run(opts ...Option) error {
|
||||
if cfg.Logger == nil {
|
||||
cfg.Logger = hclog.L()
|
||||
}
|
||||
cfg.Logger = cfg.Logger.ResetNamed("vagrant.server")
|
||||
|
||||
// Setup our run group since we're going to be starting multiple
|
||||
// goroutines for all the servers that we want to live/die as a group.
|
||||
|
||||
@ -32,7 +32,7 @@ type RubyVagrantClient struct {
|
||||
}
|
||||
|
||||
func RubyVagrantPluginConfig(log hclog.Logger) *plugin.ClientConfig {
|
||||
log = log.Named("vagrant-ruby-runtime")
|
||||
log = log.ResetNamed("vagrant.client.ruby-runtime")
|
||||
config := pluginclient.ClientConfig(log)
|
||||
config.Logger = log
|
||||
config.VersionedPlugins[1]["vagrantrubyruntime"] = &RubyVagrantPlugin{}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user