Add basic support for go-plugin
This commit is contained in:
parent
b28e6d95a6
commit
b11c86528a
|
@ -48,5 +48,8 @@ doc/
|
|||
.ruby-version
|
||||
.rvmrc
|
||||
|
||||
*.so
|
||||
*.bundle
|
||||
|
||||
# Box storage for spec
|
||||
test/vagrant-spec/boxes/*.box
|
||||
|
|
5
Rakefile
5
Rakefile
|
@ -1,5 +1,10 @@
|
|||
require 'rubygems'
|
||||
require 'bundler/setup'
|
||||
require 'rake/extensiontask'
|
||||
|
||||
Rake::ExtensionTask.new "go-plugin" do |ext|
|
||||
ext.lib_dir = "lib/vagrant/go_plugin"
|
||||
end
|
||||
|
||||
# Immediately sync all stdout so that tools like buildbot can
|
||||
# immediately load in the output.
|
||||
|
|
|
@ -14,6 +14,10 @@ Vagrant.configure("2") do |config|
|
|||
end
|
||||
end
|
||||
|
||||
config.vm.provider :vmware_desktop do |v, override|
|
||||
v.foobar = 'hi'
|
||||
end
|
||||
|
||||
config.vm.provision "shell", inline: $shell
|
||||
|
||||
config.push.define "www", strategy: "local-exec" do |push|
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||
)
|
||||
|
||||
//export GuestCapabilities
|
||||
func GuestCapabilities(pluginName, pluginType *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getGuestCapsPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.GuestCapabilities.GuestCapabilities()
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export GuestCapability
|
||||
func GuestCapability(pluginName, pluginType, cname, cplatform, cargs, cmachine *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getGuestCapsPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
machine, err := vagrant.LoadMachine(C.GoString(cmachine), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var args interface{}
|
||||
err = json.Unmarshal([]byte(C.GoString(cargs)), &args)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
cap := &vagrant.SystemCapability{
|
||||
Name: C.GoString(cname),
|
||||
Platform: C.GoString(cplatform)}
|
||||
r.Result, r.Error = p.GuestCapabilities.GuestCapability(cap, args, machine)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export HostCapabilities
|
||||
func HostCapabilities(pluginName, pluginType *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getHostCapsPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.HostCapabilities.HostCapabilities()
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export HostCapability
|
||||
func HostCapability(pluginName, pluginType, cname, cplatform, cargs, cenv *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getHostCapsPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
env, err := vagrant.LoadEnvironment(C.GoString(cenv), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var args interface{}
|
||||
err = json.Unmarshal([]byte(C.GoString(cargs)), &args)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
cap := &vagrant.SystemCapability{
|
||||
Name: C.GoString(cname),
|
||||
Platform: C.GoString(cplatform)}
|
||||
r.Result, r.Error = p.HostCapabilities.HostCapability(cap, args, env)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderCapabilities
|
||||
func ProviderCapabilities(pluginName, pluginType *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getProviderCapsPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.ProviderCapabilities.ProviderCapabilities()
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderCapability
|
||||
func ProviderCapability(pluginName, pluginType, cname, cprovider, cargs, cmach *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getProviderCapsPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, err := vagrant.LoadMachine(C.GoString(cmach), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var args interface{}
|
||||
err = json.Unmarshal([]byte(C.GoString(cargs)), &args)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
cap := &vagrant.ProviderCapability{
|
||||
Name: C.GoString(cname),
|
||||
Provider: C.GoString(cprovider)}
|
||||
r.Result, r.Error = p.ProviderCapabilities.ProviderCapability(cap, args, m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
func getProviderCapsPlugin(pluginName, pluginType *C.char) (c *plugin.RemoteProviderCapabilities, err error) {
|
||||
pname := C.GoString(pluginName)
|
||||
ptype := C.GoString(pluginType)
|
||||
|
||||
if ptype == "provider" {
|
||||
p, ok := Plugins.Providers[pname]
|
||||
if ok {
|
||||
c = &plugin.RemoteProviderCapabilities{
|
||||
Client: p.Client,
|
||||
ProviderCapabilities: p.Provider}
|
||||
}
|
||||
}
|
||||
if c == nil {
|
||||
err = errors.New("Failed to locate requested plugin")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getGuestCapsPlugin(pluginName, pluginType *C.char) (c *plugin.RemoteGuestCapabilities, err error) {
|
||||
pname := C.GoString(pluginName)
|
||||
ptype := C.GoString(pluginType)
|
||||
|
||||
if ptype == "provider" {
|
||||
p, ok := Plugins.Providers[pname]
|
||||
if ok {
|
||||
c = &plugin.RemoteGuestCapabilities{
|
||||
Client: p.Client,
|
||||
GuestCapabilities: p.Provider}
|
||||
}
|
||||
}
|
||||
if c == nil {
|
||||
err = errors.New("Failed to locate requested plugin")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getHostCapsPlugin(pluginName, pluginType *C.char) (c *plugin.RemoteHostCapabilities, err error) {
|
||||
pname := C.GoString(pluginName)
|
||||
ptype := C.GoString(pluginType)
|
||||
|
||||
if ptype == "provider" {
|
||||
p, ok := Plugins.Providers[pname]
|
||||
if ok {
|
||||
c = &plugin.RemoteHostCapabilities{
|
||||
Client: p.Client,
|
||||
HostCapabilities: p.Provider}
|
||||
}
|
||||
}
|
||||
if c == nil {
|
||||
err = errors.New("Failed to locate requested plugin")
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||
)
|
||||
|
||||
//export ConfigLoad
|
||||
func ConfigLoad(pluginName, pluginType, data *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getConfigPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var cdata map[string]interface{}
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(data)), &cdata)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.Config.ConfigLoad(cdata)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ConfigAttributes
|
||||
func ConfigAttributes(pluginName, pluginType *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getConfigPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.Config.ConfigAttributes()
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ConfigValidate
|
||||
func ConfigValidate(pluginName, pluginType, data, machData *C.char) *C.char {
|
||||
var m *vagrant.Machine
|
||||
r := vagrant.Response{}
|
||||
p, err := getConfigPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var cdata map[string]interface{}
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(data)), &cdata)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.Config.ConfigValidate(cdata, m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ConfigFinalize
|
||||
func ConfigFinalize(pluginName, pluginType, data *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getConfigPlugin(pluginName, pluginType)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var cdata map[string]interface{}
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(data)), &cdata)
|
||||
if r.Error == nil {
|
||||
println("FINALIZE HAS VALID CONFIG")
|
||||
r.Result, r.Error = p.Config.ConfigFinalize(cdata)
|
||||
}
|
||||
fmt.Printf("Full result: %s\n", r.Dump())
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
func getConfigPlugin(pluginName, pluginType *C.char) (c *plugin.RemoteConfig, err error) {
|
||||
pname := C.GoString(pluginName)
|
||||
ptype := C.GoString(pluginType)
|
||||
|
||||
if ptype == "provider" {
|
||||
p, ok := Plugins.Providers[pname]
|
||||
if ok {
|
||||
c = &plugin.RemoteConfig{
|
||||
Client: p.Client,
|
||||
Config: p.Provider}
|
||||
}
|
||||
}
|
||||
if c == nil {
|
||||
err = errors.New("Failed to locate requested plugin")
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
lib = File.expand_path('./../../../lib', File.expand_path(__FILE__))
|
||||
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||
|
||||
require 'mkmf'
|
||||
require 'time'
|
||||
|
||||
find_executable('go')
|
||||
|
||||
go_version = /go version go(\d+\.\d+)/.match(`go version`).captures.first
|
||||
raise "'go' version >=1.5.0 is required, found go #{go_version}" unless Gem::Dependency.new('', '>=1.5.0').match?('', go_version)
|
||||
|
||||
makefile = "Makefile"
|
||||
makefile_content = <<MFEND
|
||||
NAME := #{File.basename(File.dirname(File.expand_path(__FILE__)))}
|
||||
BINARY := ${NAME}.so
|
||||
|
||||
V = 0
|
||||
Q1 = $(V:1=)
|
||||
Q = $(Q1:0=@)
|
||||
ECHO1 = $(V:1=@:)
|
||||
ECHO = $(ECHO1:0=@echo)
|
||||
|
||||
SOURCEDIR=.
|
||||
SOURCES := $(shell find $(SOURCEDIR) -maxdepth 0 -name '*.go')
|
||||
|
||||
VERSION=1.0
|
||||
BUILD_DATE=#{Time.now.iso8601}
|
||||
|
||||
cflags= $(optflags) $(warnflags)
|
||||
optflags= -O3 -fno-fast-math
|
||||
warnflags= -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wimplicit-function-declaration -Wdiv-by-zero -Wdeprecated-declarations
|
||||
CCDLFLAGS= -fno-common
|
||||
INCFLAGS= -I#{RbConfig::CONFIG['rubyhdrdir']}/ -I#{RbConfig::CONFIG['rubyarchhdrdir']}/ -I$(SOURCEDIR)
|
||||
CFLAGS= $(CCDLFLAGS) $(cflags) -fno-common -pipe $(INCFLAGS)
|
||||
|
||||
LDFLAGS=-L#{RbConfig::CONFIG['libdir']} #{RbConfig::CONFIG['LIBRUBYARG']}
|
||||
|
||||
.DEFAULT_GOAL := $(BINARY)
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
${ECHO} ${VERSION}
|
||||
${ECHO} ${BUILD_DATE}
|
||||
|
||||
all:
|
||||
make clean
|
||||
$(BINARY)
|
||||
|
||||
$(BINARY): $(SOURCES)
|
||||
CGO_CFLAGS="${CFLAGS}" CGO_LDFLAGS="${LDFLAGS}" go build -buildmode=c-shared -o ${BINARY} #{File.dirname(__FILE__)}/../../ext/${NAME}/
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
# go install ${LDFLAGS} ./...
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
if [ -f ${BINARY} ] ; then rm ${BINARY} ; fi
|
||||
if [ -f lib/${BINARY} ] ; then rm lib/${BINARY} ; fi
|
||||
MFEND
|
||||
|
||||
puts "creating Makefile"
|
||||
File.open(makefile, 'w') do |f|
|
||||
f.write(makefile_content.gsub!(/(?:^|\G) {2}/m,"\t"))
|
||||
end
|
||||
|
||||
|
||||
$makefile_created = true
|
|
@ -0,0 +1,88 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||
)
|
||||
|
||||
var Plugins *plugin.VagrantPlugin
|
||||
|
||||
//export Setup
|
||||
func Setup(enableLogger, timestamps bool, logLevel *C.char) bool {
|
||||
lvl := C.GoString(logLevel)
|
||||
lopts := &hclog.LoggerOptions{Name: "vagrant"}
|
||||
if enableLogger {
|
||||
lopts.Output = os.Stderr
|
||||
} else {
|
||||
lopts.Output = ioutil.Discard
|
||||
}
|
||||
if !timestamps {
|
||||
lopts.TimeFormat = " "
|
||||
}
|
||||
lopts.Level = hclog.LevelFromString(lvl)
|
||||
vagrant.SetDefaultLogger(hclog.New(lopts))
|
||||
|
||||
if Plugins != nil {
|
||||
Plugins.Logger.Error("plugins setup failure", "error", "already setup")
|
||||
return false
|
||||
}
|
||||
|
||||
Plugins = &plugin.VagrantPlugin{
|
||||
PluginDirectories: []string{},
|
||||
Providers: map[string]*plugin.RemoteProvider{},
|
||||
Logger: vagrant.DefaultLogger().Named("go-plugin")}
|
||||
return true
|
||||
}
|
||||
|
||||
//export LoadPlugins
|
||||
func LoadPlugins(plgpath *C.char) bool {
|
||||
if Plugins == nil {
|
||||
vagrant.DefaultLogger().Error("cannot load plugins", "error", "not setup")
|
||||
return false
|
||||
}
|
||||
|
||||
p := C.GoString(plgpath)
|
||||
err := Plugins.LoadPlugins(p)
|
||||
if err != nil {
|
||||
Plugins.Logger.Error("failed loading plugins",
|
||||
"path", p, "error", err)
|
||||
return false
|
||||
}
|
||||
Plugins.Logger.Info("plugins successfully loaded", "path", p)
|
||||
return true
|
||||
}
|
||||
|
||||
//export Reset
|
||||
func Reset() {
|
||||
if Plugins != nil {
|
||||
Plugins.Logger.Info("resetting loaded plugins")
|
||||
Teardown()
|
||||
dirs := Plugins.PluginDirectories
|
||||
Plugins.PluginDirectories = []string{}
|
||||
for _, p := range dirs {
|
||||
Plugins.LoadPlugins(p)
|
||||
}
|
||||
} else {
|
||||
Plugins.Logger.Warn("plugin reset failure", "error", "not setup")
|
||||
}
|
||||
}
|
||||
|
||||
//export Teardown
|
||||
func Teardown() {
|
||||
// only teardown if setup
|
||||
if Plugins == nil {
|
||||
vagrant.DefaultLogger().Error("cannot teardown plugins", "error", "not setup")
|
||||
return
|
||||
}
|
||||
Plugins.Logger.Debug("tearing down any active plugins")
|
||||
Plugins.Kill()
|
||||
Plugins.Logger.Info("plugins have been halted")
|
||||
}
|
||||
|
||||
// stub required for build
|
||||
func main() {}
|
|
@ -0,0 +1,181 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||
)
|
||||
|
||||
//export ListProviders
|
||||
func ListProviders() *C.char {
|
||||
list := map[string]interface{}{}
|
||||
r := vagrant.Response{Result: list}
|
||||
if Plugins == nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
for n, p := range Plugins.Providers {
|
||||
list[n] = p.Provider.Info()
|
||||
}
|
||||
r.Result = list
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderAction
|
||||
func ProviderAction(providerName *C.char, actionName *C.char, machData *C.char) *C.char {
|
||||
var p *plugin.RemoteProvider
|
||||
var m *vagrant.Machine
|
||||
|
||||
r := vagrant.Response{}
|
||||
p, r.Error = getProvider(providerName)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
aName := C.GoString(actionName)
|
||||
r.Result, r.Error = p.Provider.Action(aName, m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderIsInstalled
|
||||
func ProviderIsInstalled(providerName *C.char, machData *C.char) *C.char {
|
||||
var p *plugin.RemoteProvider
|
||||
var m *vagrant.Machine
|
||||
|
||||
r := vagrant.Response{}
|
||||
p, r.Error = getProvider(providerName)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.Provider.IsInstalled(m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderIsUsable
|
||||
func ProviderIsUsable(providerName *C.char, machData *C.char) *C.char {
|
||||
var p *plugin.RemoteProvider
|
||||
var m *vagrant.Machine
|
||||
|
||||
r := vagrant.Response{}
|
||||
p, r.Error = getProvider(providerName)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.Provider.IsUsable(m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderMachineIdChanged
|
||||
func ProviderMachineIdChanged(providerName *C.char, machData *C.char) *C.char {
|
||||
var p *plugin.RemoteProvider
|
||||
var m *vagrant.Machine
|
||||
|
||||
r := vagrant.Response{}
|
||||
p, r.Error = getProvider(providerName)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Error = p.Provider.MachineIdChanged(m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderRunAction
|
||||
func ProviderRunAction(providerName *C.char, actName *C.char, runData *C.char, machData *C.char) *C.char {
|
||||
var p *plugin.RemoteProvider
|
||||
var m *vagrant.Machine
|
||||
|
||||
r := vagrant.Response{}
|
||||
p, r.Error = getProvider(providerName)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
aName := C.GoString(actName)
|
||||
rData := C.GoString(runData)
|
||||
r.Result, r.Error = p.Provider.RunAction(aName, rData, m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderSshInfo
|
||||
func ProviderSshInfo(providerName *C.char, machData *C.char) *C.char {
|
||||
var p *plugin.RemoteProvider
|
||||
var m *vagrant.Machine
|
||||
|
||||
r := vagrant.Response{}
|
||||
p, r.Error = getProvider(providerName)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.Provider.SshInfo(m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export ProviderState
|
||||
func ProviderState(providerName *C.char, machData *C.char) *C.char {
|
||||
var p *plugin.RemoteProvider
|
||||
var m *vagrant.Machine
|
||||
|
||||
r := vagrant.Response{}
|
||||
p, r.Error = getProvider(providerName)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.Provider.State(m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
func getProvider(pName *C.char) (*plugin.RemoteProvider, error) {
|
||||
providerName := C.GoString(pName)
|
||||
p, ok := Plugins.Providers[providerName]
|
||||
if !ok {
|
||||
Plugins.Logger.Error("error fetching plugin", "type", "provider",
|
||||
"name", providerName, "reason", "not found")
|
||||
return nil, errors.New(fmt.Sprintf(
|
||||
"failed to locate provider plugin `%s`", providerName))
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Loads the machine data JSON string to ensure that it is
|
||||
// valid JSON. Returns the converted GoString to be used
|
||||
// internally
|
||||
func validateMachine(machineData *C.char) (string, error) {
|
||||
mData := C.GoString(machineData)
|
||||
Plugins.Logger.Debug("received machine info", "data", mData)
|
||||
err := json.Unmarshal([]byte(mData), &vagrant.Machine{})
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %s\n", err)
|
||||
err = errors.New(fmt.Sprintf(
|
||||
"failed to load vagrant environment information - %s", err))
|
||||
}
|
||||
return mData, err
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||
)
|
||||
|
||||
//export ListSyncedFolders
|
||||
func ListSyncedFolders() *C.char {
|
||||
list := map[string]interface{}{}
|
||||
r := vagrant.Response{Result: list}
|
||||
if Plugins == nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
for n, p := range Plugins.SyncedFolders {
|
||||
list[n] = p.SyncedFolder.Info()
|
||||
}
|
||||
r.Result = list
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export SyncedFolderCleanup
|
||||
func SyncedFolderCleanup(pluginName, machine, opts *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getSyncedFolderPlugin(pluginName)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var o vagrant.FolderOptions
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Error = p.SyncedFolder.Cleanup(m, &o)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export SyncedFolderDisable
|
||||
func SyncedFolderDisable(pluginName, machine, folders, opts *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getSyncedFolderPlugin(pluginName)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var f vagrant.FolderList
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var o vagrant.FolderOptions
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Error = p.SyncedFolder.Disable(m, &f, &o)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export SyncedFolderEnable
|
||||
func SyncedFolderEnable(pluginName, machine, folders, opts *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getSyncedFolderPlugin(pluginName)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var f vagrant.FolderList
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var o vagrant.FolderOptions
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Error = p.SyncedFolder.Enable(m, &f, &o)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export SyncedFolderIsUsable
|
||||
func SyncedFolderIsUsable(pluginName, machine *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getSyncedFolderPlugin(pluginName)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Result, r.Error = p.SyncedFolder.IsUsable(m)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
//export SyncedFolderPrepare
|
||||
func SyncedFolderPrepare(pluginName, machine, folders, opts *C.char) *C.char {
|
||||
r := vagrant.Response{}
|
||||
p, err := getSyncedFolderPlugin(pluginName)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||
if err != nil {
|
||||
r.Error = err
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var f vagrant.FolderList
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
var o vagrant.FolderOptions
|
||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||
if r.Error != nil {
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
r.Error = p.SyncedFolder.Prepare(m, &f, &o)
|
||||
return C.CString(r.Dump())
|
||||
}
|
||||
|
||||
func getSyncedFolderPlugin(pluginName *C.char) (c *plugin.RemoteSyncedFolder, err error) {
|
||||
pname := C.GoString(pluginName)
|
||||
p, ok := Plugins.SyncedFolders[pname]
|
||||
if !ok {
|
||||
err = errors.New("Failed to locate requested plugin")
|
||||
return
|
||||
}
|
||||
c = &plugin.RemoteSyncedFolder{
|
||||
Client: p.Client,
|
||||
SyncedFolder: p.SyncedFolder}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package vagrant
|
||||
|
||||
type Box struct {
|
||||
Name string `json:"name"`
|
||||
Provider string `json:"provider"`
|
||||
Version string `json:"version"`
|
||||
Directory string `json:"directory"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
MetadataURL string `json:"metadata_url"`
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package vagrant
|
||||
|
||||
type SystemCapability struct {
|
||||
Name string `json:"name"`
|
||||
Platform string `json:"platform"`
|
||||
}
|
||||
|
||||
type ProviderCapability struct {
|
||||
Name string `json:"name"`
|
||||
Provider string `json:"name"`
|
||||
}
|
||||
|
||||
type GuestCapabilities interface {
|
||||
GuestCapabilities() (caps []SystemCapability, err error)
|
||||
GuestCapability(cap *SystemCapability, args interface{}, machine *Machine) (result interface{}, err error)
|
||||
}
|
||||
|
||||
type HostCapabilities interface {
|
||||
HostCapabilities() (caps []SystemCapability, err error)
|
||||
HostCapability(cap *SystemCapability, args interface{}, env *Environment) (result interface{}, err error)
|
||||
}
|
||||
|
||||
type ProviderCapabilities interface {
|
||||
ProviderCapabilities() (caps []ProviderCapability, err error)
|
||||
ProviderCapability(cap *ProviderCapability, args interface{}, machine *Machine) (result interface{}, err error)
|
||||
}
|
||||
|
||||
type NoGuestCapabilities struct{}
|
||||
type NoHostCapabilities struct{}
|
||||
type NoProviderCapabilities struct{}
|
||||
|
||||
func (g *NoGuestCapabilities) GuestCapabilities() (caps []SystemCapability, err error) {
|
||||
caps = make([]SystemCapability, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func (g *NoGuestCapabilities) GuestCapability(c *SystemCapability, a interface{}, m *Machine) (r interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (h *NoHostCapabilities) HostCapabilities() (caps []SystemCapability, err error) {
|
||||
caps = make([]SystemCapability, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func (h *NoHostCapabilities) HostCapability(c *SystemCapability, a interface{}, e *Environment) (r interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (p *NoProviderCapabilities) ProviderCapabilities() (caps []ProviderCapability, err error) {
|
||||
caps = make([]ProviderCapability, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func (p *NoProviderCapabilities) ProviderCapability(cap *ProviderCapability, args interface{}, machine *Machine) (result interface{}, err error) {
|
||||
return
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNoGuestCapabilities(t *testing.T) {
|
||||
g := NoGuestCapabilities{}
|
||||
caps, err := g.GuestCapabilities()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if len(caps) != 0 {
|
||||
t.Fatalf("guest capabilities should be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoGuestCapability(t *testing.T) {
|
||||
g := NoGuestCapabilities{}
|
||||
m := &Machine{}
|
||||
cap := &SystemCapability{"Test", "Test"}
|
||||
r, err := g.GuestCapability(cap, "args", m)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if r != nil {
|
||||
t.Fatalf("capability returned unexpected result")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoHostCapabilities(t *testing.T) {
|
||||
h := NoHostCapabilities{}
|
||||
caps, err := h.HostCapabilities()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if len(caps) != 0 {
|
||||
t.Fatalf("host capabilities should be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoHostCapability(t *testing.T) {
|
||||
h := NoHostCapabilities{}
|
||||
e := &Environment{}
|
||||
cap := &SystemCapability{"Test", "Test"}
|
||||
r, err := h.HostCapability(cap, "args", e)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if r != nil {
|
||||
t.Fatalf("capability returned unexpected result")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoProviderCapabilities(t *testing.T) {
|
||||
p := NoProviderCapabilities{}
|
||||
caps, err := p.ProviderCapabilities()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if len(caps) != 0 {
|
||||
t.Fatalf("provider capabilities should be empty")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoProviderCapability(t *testing.T) {
|
||||
p := NoProviderCapabilities{}
|
||||
m := &Machine{}
|
||||
cap := &ProviderCapability{"Test", "Test"}
|
||||
r, err := p.ProviderCapability(cap, "args", m)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
if r != nil {
|
||||
t.Fatalf("capability returned unexpected result")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
package communicator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
"unicode"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/mitchellh/iochan"
|
||||
)
|
||||
|
||||
// CmdDisconnect is a sentinel value to indicate a RemoteCmd
|
||||
// exited because the remote side disconnected us.
|
||||
const CmdDisconnect int = 2300218
|
||||
|
||||
// Cmd represents a remote command being prepared or run.
|
||||
type Cmd struct {
|
||||
// Command is the command to run remotely. This is executed as if
|
||||
// it were a shell command, so you are expected to do any shell escaping
|
||||
// necessary.
|
||||
Command string
|
||||
|
||||
// Stdin specifies the process's standard input. If Stdin is
|
||||
// nil, the process reads from an empty bytes.Buffer.
|
||||
Stdin io.Reader
|
||||
|
||||
// Stdout and Stderr represent the process's standard output and
|
||||
// error.
|
||||
//
|
||||
// If either is nil, it will be set to ioutil.Discard.
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
|
||||
// Once Wait returns, his will contain the exit code of the process.
|
||||
exitStatus int
|
||||
|
||||
// Internal fields
|
||||
exitCh chan struct{}
|
||||
|
||||
// err is used to store any error reported by the Communicator during
|
||||
// execution.
|
||||
err error
|
||||
|
||||
// This thing is a mutex, lock when making modifications concurrently
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// Init must be called by the Communicator before executing the command.
|
||||
func (c *Cmd) Init() {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.exitCh = make(chan struct{})
|
||||
}
|
||||
|
||||
// SetExitStatus stores the exit status of the remote command as well as any
|
||||
// communicator related error. SetExitStatus then unblocks any pending calls
|
||||
// to Wait.
|
||||
// This should only be called by communicators executing the remote.Cmd.
|
||||
func (c *Cmd) SetExitStatus(status int, err error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.exitStatus = status
|
||||
c.err = err
|
||||
|
||||
close(c.exitCh)
|
||||
}
|
||||
|
||||
// StartWithUi runs the remote command and streams the output to any
|
||||
// configured Writers for stdout/stderr, while also writing each line
|
||||
// as it comes to a Ui.
|
||||
func (r *Cmd) StartWithUi(c Communicator, ui vagrant.Ui) error {
|
||||
stdout_r, stdout_w := io.Pipe()
|
||||
stderr_r, stderr_w := io.Pipe()
|
||||
defer stdout_w.Close()
|
||||
defer stderr_w.Close()
|
||||
|
||||
// Retain the original stdout/stderr that we can replace back in.
|
||||
originalStdout := r.Stdout
|
||||
originalStderr := r.Stderr
|
||||
defer func() {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
|
||||
r.Stdout = originalStdout
|
||||
r.Stderr = originalStderr
|
||||
}()
|
||||
|
||||
// Set the writers for the output so that we get it streamed to us
|
||||
if r.Stdout == nil {
|
||||
r.Stdout = stdout_w
|
||||
} else {
|
||||
r.Stdout = io.MultiWriter(r.Stdout, stdout_w)
|
||||
}
|
||||
|
||||
if r.Stderr == nil {
|
||||
r.Stderr = stderr_w
|
||||
} else {
|
||||
r.Stderr = io.MultiWriter(r.Stderr, stderr_w)
|
||||
}
|
||||
|
||||
// Start the command
|
||||
if err := c.Start(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create the channels we'll use for data
|
||||
exitCh := make(chan struct{})
|
||||
stdoutCh := iochan.DelimReader(stdout_r, '\n')
|
||||
stderrCh := iochan.DelimReader(stderr_r, '\n')
|
||||
|
||||
// Start the goroutine to watch for the exit
|
||||
go func() {
|
||||
defer close(exitCh)
|
||||
defer stdout_w.Close()
|
||||
defer stderr_w.Close()
|
||||
r.Wait()
|
||||
}()
|
||||
|
||||
// Loop and get all our output
|
||||
OutputLoop:
|
||||
for {
|
||||
select {
|
||||
case output := <-stderrCh:
|
||||
if output != "" {
|
||||
ui.Say(r.cleanOutputLine(output))
|
||||
}
|
||||
case output := <-stdoutCh:
|
||||
if output != "" {
|
||||
ui.Say(r.cleanOutputLine(output))
|
||||
}
|
||||
case <-exitCh:
|
||||
break OutputLoop
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we finish off stdout/stderr because we may have gotten
|
||||
// a message from the exit channel before finishing these first.
|
||||
for output := range stdoutCh {
|
||||
ui.Say(r.cleanOutputLine(output))
|
||||
}
|
||||
|
||||
for output := range stderrCh {
|
||||
ui.Say(r.cleanOutputLine(output))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wait waits for the remote command to complete.
|
||||
// Wait may return an error from the communicator, or an ExitError if the
|
||||
// process exits with a non-zero exit status.
|
||||
func (c *Cmd) Wait() error {
|
||||
<-c.exitCh
|
||||
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
if c.err != nil || c.exitStatus != 0 {
|
||||
return &ExitError{
|
||||
Command: c.Command,
|
||||
ExitStatus: c.exitStatus,
|
||||
Err: c.err,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// cleanOutputLine cleans up a line so that '\r' don't muck up the
|
||||
// UI output when we're reading from a remote command.
|
||||
func (r *Cmd) cleanOutputLine(line string) string {
|
||||
// Trim surrounding whitespace
|
||||
line = strings.TrimRightFunc(line, unicode.IsSpace)
|
||||
|
||||
// Trim up to the first carriage return, since that text would be
|
||||
// lost anyways.
|
||||
idx := strings.LastIndex(line, "\r")
|
||||
if idx > -1 {
|
||||
line = line[idx+1:]
|
||||
}
|
||||
|
||||
return line
|
||||
}
|
||||
|
||||
// ExitError is returned by Wait to indicate and error executing the remote
|
||||
// command, or a non-zero exit status.
|
||||
type ExitError struct {
|
||||
Command string
|
||||
ExitStatus int
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *ExitError) Error() string {
|
||||
if e.Err != nil {
|
||||
return fmt.Sprintf("error executing %q: %v", e.Command, e.Err)
|
||||
}
|
||||
return fmt.Sprintf("%q exit status: %d", e.Command, e.ExitStatus)
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package communicator
|
|
@ -0,0 +1,117 @@
|
|||
package communicator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
)
|
||||
|
||||
type Communicator interface {
|
||||
Connect() error
|
||||
Disconnect() error
|
||||
Timeout() time.Duration
|
||||
Start(*Cmd) error
|
||||
Download(path string, output io.Writer) error
|
||||
DownloadDir(dst, src string, excludes []string) error
|
||||
Upload(dst string, src io.Reader, srcinfo *os.FileInfo) error
|
||||
UploadDir(dst, src string, excludes []string) error
|
||||
}
|
||||
|
||||
// maxBackoffDelay is the maximum delay between retry attempts
|
||||
var maxBackoffDelay = 20 * time.Second
|
||||
var initialBackoffDelay = time.Second
|
||||
var logger = vagrant.DefaultLogger().Named("communicator")
|
||||
|
||||
// Fatal is an interface that error values can return to halt Retry
|
||||
type Fatal interface {
|
||||
FatalError() error
|
||||
}
|
||||
|
||||
// Retry retries the function f until it returns a nil error, a Fatal error, or
|
||||
// the context expires.
|
||||
func Retry(ctx context.Context, f func() error) error {
|
||||
// container for atomic error value
|
||||
type errWrap struct {
|
||||
E error
|
||||
}
|
||||
|
||||
// Try the function in a goroutine
|
||||
var errVal atomic.Value
|
||||
doneCh := make(chan struct{})
|
||||
go func() {
|
||||
defer close(doneCh)
|
||||
|
||||
delay := time.Duration(0)
|
||||
for {
|
||||
// If our context ended, we want to exit right away.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-time.After(delay):
|
||||
}
|
||||
|
||||
// Try the function call
|
||||
err := f()
|
||||
|
||||
// return if we have no error, or a FatalError
|
||||
done := false
|
||||
switch e := err.(type) {
|
||||
case nil:
|
||||
done = true
|
||||
case Fatal:
|
||||
err = e.FatalError()
|
||||
done = true
|
||||
}
|
||||
|
||||
errVal.Store(errWrap{err})
|
||||
|
||||
if done {
|
||||
return
|
||||
}
|
||||
|
||||
logger.Warn("retryable error", "error", err)
|
||||
|
||||
delay *= 2
|
||||
|
||||
if delay == 0 {
|
||||
delay = initialBackoffDelay
|
||||
}
|
||||
|
||||
if delay > maxBackoffDelay {
|
||||
delay = maxBackoffDelay
|
||||
}
|
||||
|
||||
logger.Info("sleeping for retry", "duration", delay)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for completion
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-doneCh:
|
||||
}
|
||||
|
||||
var lastErr error
|
||||
// Check if we got an error executing
|
||||
if ev, ok := errVal.Load().(errWrap); ok {
|
||||
lastErr = ev.E
|
||||
}
|
||||
|
||||
// Check if we have a context error to check if we're interrupted or timeout
|
||||
switch ctx.Err() {
|
||||
case context.Canceled:
|
||||
return fmt.Errorf("interrupted - last error: %v", lastErr)
|
||||
case context.DeadlineExceeded:
|
||||
return fmt.Errorf("timeout - last error: %v", lastErr)
|
||||
}
|
||||
|
||||
if lastErr != nil {
|
||||
return lastErr
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package none
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/communicator"
|
||||
)
|
||||
|
||||
type Communicator struct {
|
||||
config string
|
||||
}
|
||||
|
||||
// Creates a null vagrant.Communicator implementation. This takes
|
||||
// an already existing configuration.
|
||||
func New(config string) (result *Communicator, err error) {
|
||||
// Establish an initial connection and connect
|
||||
result = &Communicator{
|
||||
config: config,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) Connect() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) Disconnect() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) Start(cmd *communicator.Cmd) (err error) {
|
||||
cmd.Init()
|
||||
cmd.SetExitStatus(0, nil)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) Upload(path string, input io.Reader, fi *os.FileInfo) error {
|
||||
return errors.New("Upload is not implemented when communicator = 'none'")
|
||||
}
|
||||
|
||||
func (c *Communicator) UploadDir(dst string, src string, excl []string) error {
|
||||
return errors.New("UploadDir is not implemented when communicator = 'none'")
|
||||
}
|
||||
|
||||
func (c *Communicator) Download(path string, output io.Writer) error {
|
||||
return errors.New("Download is not implemented when communicator = 'none'")
|
||||
}
|
||||
|
||||
func (c *Communicator) DownloadDir(dst string, src string, excl []string) error {
|
||||
return errors.New("DownloadDir is not implemented when communicator = 'none'")
|
||||
}
|
||||
|
||||
func (c *Communicator) Timeout() time.Duration {
|
||||
return 0
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package none
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/communicator"
|
||||
)
|
||||
|
||||
func TestCommIsCommunicator(t *testing.T) {
|
||||
// Force failure with explanation of why it's not valid
|
||||
var _ communicator.Communicator = new(Communicator)
|
||||
}
|
|
@ -0,0 +1,949 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/communicator"
|
||||
"github.com/pkg/sftp"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
// ErrHandshakeTimeout is returned from New() whenever we're unable to establish
|
||||
// an ssh connection within a certain timeframe. By default the handshake time-
|
||||
// out period is 1 minute. You can change it with Config.HandshakeTimeout.
|
||||
var ErrHandshakeTimeout = fmt.Errorf("Timeout during SSH handshake")
|
||||
|
||||
var logger = vagrant.DefaultLogger().Named("communicator.ssh")
|
||||
|
||||
type Communicator struct {
|
||||
client *ssh.Client
|
||||
config *Config
|
||||
conn net.Conn
|
||||
address string
|
||||
}
|
||||
|
||||
// Config is the structure used to configure the SSH communicator.
|
||||
type Config struct {
|
||||
// The configuration of the Go SSH connection
|
||||
SSHConfig *ssh.ClientConfig
|
||||
|
||||
// Connection returns a new connection. The current connection
|
||||
// in use will be closed as part of the Close method, or in the
|
||||
// case an error occurs.
|
||||
Connection func() (net.Conn, error)
|
||||
|
||||
// Pty, if true, will request a pty from the remote end.
|
||||
Pty bool
|
||||
|
||||
// DisableAgentForwarding, if true, will not forward the SSH agent.
|
||||
DisableAgentForwarding bool
|
||||
|
||||
// HandshakeTimeout limits the amount of time we'll wait to handshake before
|
||||
// saying the connection failed.
|
||||
HandshakeTimeout time.Duration
|
||||
|
||||
// UseSftp, if true, sftp will be used instead of scp for file transfers
|
||||
UseSftp bool
|
||||
|
||||
// KeepAliveInterval sets how often we send a channel request to the
|
||||
// server. A value < 0 disables.
|
||||
KeepAliveInterval time.Duration
|
||||
|
||||
// Timeout is how long to wait for a read or write to succeed.
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// Creates a new vagrant.Communicator implementation over SSH. This takes
|
||||
// an already existing TCP connection and SSH configuration.
|
||||
func New(address string, config *Config) (result *Communicator, err error) {
|
||||
// Establish an initial connection and connect
|
||||
result = &Communicator{
|
||||
config: config,
|
||||
address: address,
|
||||
}
|
||||
|
||||
// reset the logger in case custom default has been set
|
||||
logger = vagrant.DefaultLogger().Named("communicator.ssh")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) Connect() error {
|
||||
return c.reconnect()
|
||||
}
|
||||
|
||||
func (c *Communicator) Disconnect() (err error) {
|
||||
if c.conn != nil {
|
||||
logger.Info("closing connection")
|
||||
err = c.conn.Close()
|
||||
} else {
|
||||
err = errors.New("No connection currently established to close")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) Timeout() time.Duration {
|
||||
return c.config.Timeout
|
||||
}
|
||||
|
||||
func (c *Communicator) Start(cmd *communicator.Cmd) (err error) {
|
||||
session, err := c.newSession()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Setup our session
|
||||
session.Stdin = cmd.Stdin
|
||||
session.Stdout = cmd.Stdout
|
||||
session.Stderr = cmd.Stderr
|
||||
|
||||
if c.config.Pty {
|
||||
// Request a PTY
|
||||
termModes := ssh.TerminalModes{
|
||||
ssh.ECHO: 0, // do not echo
|
||||
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
|
||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
||||
}
|
||||
|
||||
if err = session.RequestPty("xterm", 40, 80, termModes); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
logger.Debug("starting remote command", "command", cmd.Command)
|
||||
err = session.Start(cmd.Command + "\n")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
if c.config.KeepAliveInterval <= 0 {
|
||||
return
|
||||
}
|
||||
c := time.NewTicker(c.config.KeepAliveInterval)
|
||||
defer c.Stop()
|
||||
for range c.C {
|
||||
_, err := session.SendRequest("keepalive@vagrantup.com", true, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Start a goroutine to wait for the session to end and set the
|
||||
// exit boolean and status.
|
||||
go func() {
|
||||
defer session.Close()
|
||||
|
||||
err := session.Wait()
|
||||
exitStatus := 0
|
||||
if err != nil {
|
||||
switch err.(type) {
|
||||
case *ssh.ExitError:
|
||||
exitStatus = err.(*ssh.ExitError).ExitStatus()
|
||||
logger.Error("remote command exited non-zero",
|
||||
"exitcode", exitStatus, "command", cmd.Command)
|
||||
case *ssh.ExitMissingError:
|
||||
logger.Error("remote command exited without exit status or exit signal",
|
||||
"command", cmd.Command)
|
||||
exitStatus = communicator.CmdDisconnect
|
||||
default:
|
||||
logger.Error("error waiting for ssh session", "error", err)
|
||||
}
|
||||
}
|
||||
cmd.SetExitStatus(exitStatus, err)
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) Upload(path string, input io.Reader, fi *os.FileInfo) error {
|
||||
if c.config.UseSftp {
|
||||
return c.sftpUploadSession(path, input, fi)
|
||||
} else {
|
||||
return c.scpUploadSession(path, input, fi)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Communicator) UploadDir(dst string, src string, excl []string) error {
|
||||
logger.Debug("uploading directory", "source", src, "destination", dst)
|
||||
if c.config.UseSftp {
|
||||
return c.sftpUploadDirSession(dst, src, excl)
|
||||
} else {
|
||||
return c.scpUploadDirSession(dst, src, excl)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Communicator) DownloadDir(src string, dst string, excl []string) error {
|
||||
logger.Debug("downloading directory", "source", src, "destination", dst)
|
||||
scpFunc := func(w io.Writer, stdoutR *bufio.Reader) error {
|
||||
dirStack := []string{dst}
|
||||
for {
|
||||
fmt.Fprint(w, "\x00")
|
||||
|
||||
// read file info
|
||||
fi, err := stdoutR.ReadString('\n')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(fi) < 0 {
|
||||
return fmt.Errorf("empty response from server")
|
||||
}
|
||||
|
||||
switch fi[0] {
|
||||
case '\x01', '\x02':
|
||||
return fmt.Errorf("%s", fi[1:])
|
||||
case 'C', 'D':
|
||||
break
|
||||
case 'E':
|
||||
dirStack = dirStack[:len(dirStack)-1]
|
||||
if len(dirStack) == 0 {
|
||||
fmt.Fprint(w, "\x00")
|
||||
return nil
|
||||
}
|
||||
continue
|
||||
default:
|
||||
return fmt.Errorf("unexpected server response (%x)", fi[0])
|
||||
}
|
||||
|
||||
var mode int64
|
||||
var size int64
|
||||
var name string
|
||||
logger.Debug("download directory", "str", fi)
|
||||
n, err := fmt.Sscanf(fi[1:], "%o %d %s", &mode, &size, &name)
|
||||
if err != nil || n != 3 {
|
||||
return fmt.Errorf("can't parse server response (%s)", fi)
|
||||
}
|
||||
if size < 0 {
|
||||
return fmt.Errorf("negative file size")
|
||||
}
|
||||
|
||||
logger.Debug("download directory", "mode", mode, "size", size, "name", name)
|
||||
|
||||
dst = filepath.Join(dirStack...)
|
||||
switch fi[0] {
|
||||
case 'D':
|
||||
err = os.MkdirAll(filepath.Join(dst, name), os.FileMode(mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dirStack = append(dirStack, name)
|
||||
continue
|
||||
case 'C':
|
||||
fmt.Fprint(w, "\x00")
|
||||
err = scpDownloadFile(filepath.Join(dst, name), stdoutR, size, os.FileMode(mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := checkSCPStatus(stdoutR); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return c.scpSession("scp -vrf "+src, scpFunc)
|
||||
}
|
||||
|
||||
func (c *Communicator) Download(path string, output io.Writer) error {
|
||||
if c.config.UseSftp {
|
||||
return c.sftpDownloadSession(path, output)
|
||||
}
|
||||
return c.scpDownloadSession(path, output)
|
||||
}
|
||||
|
||||
func (c *Communicator) newSession() (session *ssh.Session, err error) {
|
||||
logger.Debug("opening new ssh session")
|
||||
if c.client == nil {
|
||||
err = errors.New("client not available")
|
||||
} else {
|
||||
session, err = c.client.NewSession()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logger.Error("ssh session open failure", "error", err)
|
||||
if err := c.reconnect(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, errors.New("client not available")
|
||||
} else {
|
||||
return c.client.NewSession()
|
||||
}
|
||||
}
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (c *Communicator) reconnect() (err error) {
|
||||
// Ignore errors here because we don't care if it fails
|
||||
c.Disconnect()
|
||||
// Set the conn and client to nil since we'll recreate it
|
||||
c.conn = nil
|
||||
c.client = nil
|
||||
|
||||
logger.Debug("reconnection to tcp connection for ssh")
|
||||
c.conn, err = c.config.Connection()
|
||||
if err != nil {
|
||||
// Explicitly set this to the REAL nil. Connection() can return
|
||||
// a nil implementation of net.Conn which will make the
|
||||
// "if c.conn == nil" check fail above. Read here for more information
|
||||
// on this psychotic language feature:
|
||||
//
|
||||
// http://golang.org/doc/faq#nil_error
|
||||
c.conn = nil
|
||||
|
||||
logger.Error("reconnection failure", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
if c.config.Timeout > 0 {
|
||||
c.conn = &timeoutConn{c.conn, c.config.Timeout, c.config.Timeout}
|
||||
}
|
||||
|
||||
logger.Debug("handshaking with ssh")
|
||||
|
||||
// Default timeout to 1 minute if it wasn't specified (zero value). For
|
||||
// when you need to handshake from low orbit.
|
||||
var duration time.Duration
|
||||
if c.config.HandshakeTimeout == 0 {
|
||||
duration = 1 * time.Minute
|
||||
} else {
|
||||
duration = c.config.HandshakeTimeout
|
||||
}
|
||||
|
||||
connectionEstablished := make(chan struct{}, 1)
|
||||
|
||||
var sshConn ssh.Conn
|
||||
var sshChan <-chan ssh.NewChannel
|
||||
var req <-chan *ssh.Request
|
||||
|
||||
go func() {
|
||||
sshConn, sshChan, req, err = ssh.NewClientConn(c.conn, c.address, c.config.SSHConfig)
|
||||
close(connectionEstablished)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-connectionEstablished:
|
||||
// We don't need to do anything here. We just want select to block until
|
||||
// we connect or timeout.
|
||||
case <-time.After(duration):
|
||||
if c.conn != nil {
|
||||
c.conn.Close()
|
||||
}
|
||||
if sshConn != nil {
|
||||
sshConn.Close()
|
||||
}
|
||||
return ErrHandshakeTimeout
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
logger.Debug("handshake complete")
|
||||
if sshConn != nil {
|
||||
c.client = ssh.NewClient(sshConn, sshChan, req)
|
||||
}
|
||||
c.connectToAgent()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) connectToAgent() {
|
||||
if c.client == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.config.DisableAgentForwarding {
|
||||
logger.Info("SSH agent forwarding is disabled")
|
||||
return
|
||||
}
|
||||
|
||||
// open connection to the local agent
|
||||
socketLocation := os.Getenv("SSH_AUTH_SOCK")
|
||||
if socketLocation == "" {
|
||||
logger.Info("no local agent socket, will not connect agent")
|
||||
return
|
||||
}
|
||||
agentConn, err := net.Dial("unix", socketLocation)
|
||||
if err != nil {
|
||||
logger.Error("could not connect to local agent socket", "path", socketLocation)
|
||||
return
|
||||
}
|
||||
|
||||
// create agent and add in auth
|
||||
forwardingAgent := agent.NewClient(agentConn)
|
||||
if forwardingAgent == nil {
|
||||
logger.Error("could not create agent client")
|
||||
agentConn.Close()
|
||||
return
|
||||
}
|
||||
|
||||
// add callback for forwarding agent to SSH config
|
||||
// XXX - might want to handle reconnects appending multiple callbacks
|
||||
auth := ssh.PublicKeysCallback(forwardingAgent.Signers)
|
||||
c.config.SSHConfig.Auth = append(c.config.SSHConfig.Auth, auth)
|
||||
agent.ForwardToAgent(c.client, forwardingAgent)
|
||||
|
||||
// Setup a session to request agent forwarding
|
||||
session, err := c.newSession()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
err = agent.RequestAgentForwarding(session)
|
||||
if err != nil {
|
||||
logger.Error("request agent forwarding failed", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Info("agent forwarding enabled")
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Communicator) sftpUploadSession(path string, input io.Reader, fi *os.FileInfo) error {
|
||||
sftpFunc := func(client *sftp.Client) error {
|
||||
return c.sftpUploadFile(path, input, client, fi)
|
||||
}
|
||||
|
||||
return c.sftpSession(sftpFunc)
|
||||
}
|
||||
|
||||
func (c *Communicator) sftpUploadFile(path string, input io.Reader, client *sftp.Client, fi *os.FileInfo) error {
|
||||
logger.Debug("sftp uploading", "path", path)
|
||||
f, err := client.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err = io.Copy(f, input); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi != nil && (*fi).Mode().IsRegular() {
|
||||
mode := (*fi).Mode().Perm()
|
||||
err = client.Chmod(path, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Communicator) sftpUploadDirSession(dst string, src string, excl []string) error {
|
||||
sftpFunc := func(client *sftp.Client) error {
|
||||
rootDst := dst
|
||||
if src[len(src)-1] != '/' {
|
||||
logger.Debug("no trailing slash, creating the source directory name")
|
||||
rootDst = filepath.Join(dst, filepath.Base(src))
|
||||
}
|
||||
walkFunc := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Calculate the final destination using the
|
||||
// base source and root destination
|
||||
relSrc, err := filepath.Rel(src, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
finalDst := filepath.Join(rootDst, relSrc)
|
||||
|
||||
// In Windows, Join uses backslashes which we don't want to get
|
||||
// to the sftp server
|
||||
finalDst = filepath.ToSlash(finalDst)
|
||||
|
||||
// Skip the creation of the target destination directory since
|
||||
// it should exist and we might not even own it
|
||||
if finalDst == dst {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.sftpVisitFile(finalDst, path, info, client)
|
||||
}
|
||||
|
||||
return filepath.Walk(src, walkFunc)
|
||||
}
|
||||
|
||||
return c.sftpSession(sftpFunc)
|
||||
}
|
||||
|
||||
func (c *Communicator) sftpMkdir(path string, client *sftp.Client, fi os.FileInfo) error {
|
||||
logger.Debug("sftp create directory", "path", path)
|
||||
|
||||
if err := client.Mkdir(path); err != nil {
|
||||
// Do not consider it an error if the directory existed
|
||||
remoteFi, fiErr := client.Lstat(path)
|
||||
if fiErr != nil || !remoteFi.IsDir() {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
mode := fi.Mode().Perm()
|
||||
if err := client.Chmod(path, mode); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Communicator) sftpVisitFile(dst string, src string, fi os.FileInfo, client *sftp.Client) error {
|
||||
if !fi.IsDir() {
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
return c.sftpUploadFile(dst, f, client, &fi)
|
||||
} else {
|
||||
err := c.sftpMkdir(dst, client, fi)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Communicator) sftpDownloadSession(path string, output io.Writer) error {
|
||||
sftpFunc := func(client *sftp.Client) error {
|
||||
f, err := client.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if _, err = io.Copy(output, f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.sftpSession(sftpFunc)
|
||||
}
|
||||
|
||||
func (c *Communicator) sftpSession(f func(*sftp.Client) error) error {
|
||||
client, err := c.newSftpClient()
|
||||
if err != nil {
|
||||
return fmt.Errorf("sftpSession error: %s", err.Error())
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
return f(client)
|
||||
}
|
||||
|
||||
func (c *Communicator) newSftpClient() (*sftp.Client, error) {
|
||||
session, err := c.newSession()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := session.RequestSubsystem("sftp"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pw, err := session.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pr, err := session.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Capture stdout so we can return errors to the user
|
||||
var stdout bytes.Buffer
|
||||
tee := io.TeeReader(pr, &stdout)
|
||||
client, err := sftp.NewClientPipe(tee, pw)
|
||||
if err != nil && stdout.Len() > 0 {
|
||||
logger.Error("upload failed", "error", stdout.Bytes())
|
||||
}
|
||||
|
||||
return client, err
|
||||
}
|
||||
|
||||
func (c *Communicator) scpUploadSession(path string, input io.Reader, fi *os.FileInfo) error {
|
||||
|
||||
// The target directory and file for talking the SCP protocol
|
||||
target_dir := filepath.Dir(path)
|
||||
target_file := filepath.Base(path)
|
||||
|
||||
// On windows, filepath.Dir uses backslash separators (ie. "\tmp").
|
||||
// This does not work when the target host is unix. Switch to forward slash
|
||||
// which works for unix and windows
|
||||
target_dir = filepath.ToSlash(target_dir)
|
||||
|
||||
// Escape spaces in remote directory
|
||||
target_dir = strings.Replace(target_dir, " ", "\\ ", -1)
|
||||
|
||||
scpFunc := func(w io.Writer, stdoutR *bufio.Reader) error {
|
||||
return scpUploadFile(target_file, input, w, stdoutR, fi)
|
||||
}
|
||||
|
||||
return c.scpSession("scp -vt "+target_dir, scpFunc)
|
||||
}
|
||||
|
||||
func (c *Communicator) scpUploadDirSession(dst string, src string, excl []string) error {
|
||||
scpFunc := func(w io.Writer, r *bufio.Reader) error {
|
||||
uploadEntries := func() error {
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
entries, err := f.Readdir(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return scpUploadDir(src, entries, w, r)
|
||||
}
|
||||
|
||||
if src[len(src)-1] != '/' {
|
||||
logger.Debug("no trailing slash, creating the source directory name")
|
||||
fi, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return scpUploadDirProtocol(filepath.Base(src), w, r, uploadEntries, fi)
|
||||
} else {
|
||||
// Trailing slash, so only upload the contents
|
||||
return uploadEntries()
|
||||
}
|
||||
}
|
||||
|
||||
return c.scpSession("scp -rvt "+dst, scpFunc)
|
||||
}
|
||||
|
||||
func (c *Communicator) scpDownloadSession(path string, output io.Writer) error {
|
||||
scpFunc := func(w io.Writer, stdoutR *bufio.Reader) error {
|
||||
fmt.Fprint(w, "\x00")
|
||||
|
||||
// read file info
|
||||
fi, err := stdoutR.ReadString('\n')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(fi) < 0 {
|
||||
return fmt.Errorf("empty response from server")
|
||||
}
|
||||
|
||||
switch fi[0] {
|
||||
case '\x01', '\x02':
|
||||
return fmt.Errorf("%s", fi[1:])
|
||||
case 'C':
|
||||
case 'D':
|
||||
return fmt.Errorf("remote file is directory")
|
||||
default:
|
||||
return fmt.Errorf("unexpected server response (%x)", fi[0])
|
||||
}
|
||||
|
||||
var mode string
|
||||
var size int64
|
||||
|
||||
n, err := fmt.Sscanf(fi, "%6s %d ", &mode, &size)
|
||||
if err != nil || n != 2 {
|
||||
return fmt.Errorf("can't parse server response (%s)", fi)
|
||||
}
|
||||
if size < 0 {
|
||||
return fmt.Errorf("negative file size")
|
||||
}
|
||||
|
||||
fmt.Fprint(w, "\x00")
|
||||
|
||||
if _, err := io.CopyN(output, stdoutR, size); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(w, "\x00")
|
||||
|
||||
return checkSCPStatus(stdoutR)
|
||||
}
|
||||
|
||||
if !strings.Contains(path, " ") {
|
||||
return c.scpSession("scp -vf "+path, scpFunc)
|
||||
}
|
||||
return c.scpSession("scp -vf "+strconv.Quote(path), scpFunc)
|
||||
}
|
||||
|
||||
func (c *Communicator) scpSession(scpCommand string, f func(io.Writer, *bufio.Reader) error) error {
|
||||
session, err := c.newSession()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
// Get a pipe to stdin so that we can send data down
|
||||
stdinW, err := session.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We only want to close once, so we nil w after we close it,
|
||||
// and only close in the defer if it hasn't been closed already.
|
||||
defer func() {
|
||||
if stdinW != nil {
|
||||
stdinW.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// Get a pipe to stdout so that we can get responses back
|
||||
stdoutPipe, err := session.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stdoutR := bufio.NewReader(stdoutPipe)
|
||||
|
||||
// Set stderr to a bytes buffer
|
||||
stderr := new(bytes.Buffer)
|
||||
session.Stderr = stderr
|
||||
|
||||
// Start the sink mode on the other side
|
||||
// TODO(mitchellh): There are probably issues with shell escaping the path
|
||||
logger.Debug("starting remote scp process", "command", scpCommand)
|
||||
if err := session.Start(scpCommand); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Call our callback that executes in the context of SCP. We ignore
|
||||
// EOF errors if they occur because it usually means that SCP prematurely
|
||||
// ended on the other side.
|
||||
logger.Debug("started scp session, beginning transfers")
|
||||
if err := f(stdinW, stdoutR); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
// Close the stdin, which sends an EOF, and then set w to nil so that
|
||||
// our defer func doesn't close it again since that is unsafe with
|
||||
// the Go SSH package.
|
||||
logger.Debug("scp sessiono complete, closing stdin pipe")
|
||||
stdinW.Close()
|
||||
stdinW = nil
|
||||
|
||||
// Wait for the SCP connection to close, meaning it has consumed all
|
||||
// our data and has completed. Or has errored.
|
||||
logger.Debug("waiting for ssh session to complete")
|
||||
err = session.Wait()
|
||||
if err != nil {
|
||||
if exitErr, ok := err.(*ssh.ExitError); ok {
|
||||
// Otherwise, we have an ExitError, meaning we can just read
|
||||
// the exit status
|
||||
logger.Debug("non-zero exit status", "exitcode", exitErr.ExitStatus())
|
||||
stdoutB, err := ioutil.ReadAll(stdoutR)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Debug("scp output", "output", stdoutB)
|
||||
|
||||
// If we exited with status 127, it means SCP isn't available.
|
||||
// Return a more descriptive error for that.
|
||||
if exitErr.ExitStatus() == 127 {
|
||||
return errors.New(
|
||||
"SCP failed to start. This usually means that SCP is not\n" +
|
||||
"properly installed on the remote system.")
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Debug("scp stderr", "length", stderr.Len(), "content", stderr.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkSCPStatus checks that a prior command sent to SCP completed
|
||||
// successfully. If it did not complete successfully, an error will
|
||||
// be returned.
|
||||
func checkSCPStatus(r *bufio.Reader) error {
|
||||
code, err := r.ReadByte()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if code != 0 {
|
||||
// Treat any non-zero (really 1 and 2) as fatal errors
|
||||
message, _, err := r.ReadLine()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading error message: %s", err)
|
||||
}
|
||||
|
||||
return errors.New(string(message))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func scpDownloadFile(dst string, src io.Reader, size int64, mode os.FileMode) error {
|
||||
f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := io.CopyN(f, src, size); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scpUploadFile(dst string, src io.Reader, w io.Writer, r *bufio.Reader, fi *os.FileInfo) error {
|
||||
var mode os.FileMode
|
||||
var size int64
|
||||
|
||||
if fi != nil && (*fi).Mode().IsRegular() {
|
||||
mode = (*fi).Mode().Perm()
|
||||
size = (*fi).Size()
|
||||
} else {
|
||||
// Create a temporary file where we can copy the contents of the src
|
||||
// so that we can determine the length, since SCP is length-prefixed.
|
||||
tf, err := ioutil.TempFile("", "vagrant-upload")
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating temporary file for upload: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
defer tf.Close()
|
||||
|
||||
mode = 0644
|
||||
|
||||
logger.Debug("copying input data to temporary file to read length")
|
||||
if _, err := io.Copy(tf, src); err != nil {
|
||||
return fmt.Errorf("Error copying input data into local temporary "+
|
||||
"file. Check that TEMPDIR has enough space. Error: %s", err)
|
||||
}
|
||||
|
||||
// Sync the file so that the contents are definitely on disk, then
|
||||
// read the length of it.
|
||||
if err := tf.Sync(); err != nil {
|
||||
return fmt.Errorf("Error creating temporary file for upload: %s", err)
|
||||
}
|
||||
|
||||
// Seek the file to the beginning so we can re-read all of it
|
||||
if _, err := tf.Seek(0, 0); err != nil {
|
||||
return fmt.Errorf("Error creating temporary file for upload: %s", err)
|
||||
}
|
||||
|
||||
tfi, err := tf.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating temporary file for upload: %s", err)
|
||||
}
|
||||
|
||||
size = tfi.Size()
|
||||
src = tf
|
||||
}
|
||||
|
||||
// Start the protocol
|
||||
perms := fmt.Sprintf("C%04o", mode)
|
||||
logger.Debug("scp uploading", "path", dst, "perms", perms, "size", size)
|
||||
|
||||
fmt.Fprintln(w, perms, size, dst)
|
||||
if err := checkSCPStatus(r); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.CopyN(w, src, size); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(w, "\x00")
|
||||
return checkSCPStatus(r)
|
||||
}
|
||||
|
||||
func scpUploadDirProtocol(name string, w io.Writer, r *bufio.Reader, f func() error, fi os.FileInfo) error {
|
||||
logger.Debug("scp directory upload", "path", name)
|
||||
|
||||
mode := fi.Mode().Perm()
|
||||
|
||||
perms := fmt.Sprintf("D%04o 0", mode)
|
||||
|
||||
fmt.Fprintln(w, perms, name)
|
||||
err := checkSCPStatus(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, "E")
|
||||
return err
|
||||
}
|
||||
|
||||
func scpUploadDir(root string, fs []os.FileInfo, w io.Writer, r *bufio.Reader) error {
|
||||
for _, fi := range fs {
|
||||
realPath := filepath.Join(root, fi.Name())
|
||||
|
||||
// Track if this is actually a symlink to a directory. If it is
|
||||
// a symlink to a file we don't do any special behavior because uploading
|
||||
// a file just works. If it is a directory, we need to know so we
|
||||
// treat it as such.
|
||||
isSymlinkToDir := false
|
||||
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
symPath, err := filepath.EvalSymlinks(realPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
symFi, err := os.Lstat(symPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isSymlinkToDir = symFi.IsDir()
|
||||
}
|
||||
|
||||
if !fi.IsDir() && !isSymlinkToDir {
|
||||
// It is a regular file (or symlink to a file), just upload it
|
||||
f, err := os.Open(realPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = func() error {
|
||||
defer f.Close()
|
||||
return scpUploadFile(fi.Name(), f, w, r, &fi)
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// It is a directory, recursively upload
|
||||
err := scpUploadDirProtocol(fi.Name(), w, r, func() error {
|
||||
f, err := os.Open(realPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
entries, err := f.Readdir(-1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return scpUploadDir(realPath, entries, w, r)
|
||||
}, fi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
// +build !race
|
||||
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/communicator"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// private key for mock server
|
||||
const testServerPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU
|
||||
70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx
|
||||
9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF
|
||||
tupdMODN064vd3gyMKTwrlQ8tZM6aYuyOPsutLlUY7M5x5FwMDYvnPDSeyT/Iw0z
|
||||
s3B+NCyqeeMd2T7YzQFnRATj0M7rM5LoSs7DVqVriOEABssFyLj31PboaoLhOKgc
|
||||
qoM9khkNzr7FHVvi+DhYM2jD0DwvqZLN6NmnLwIDAQABAoIBAQCGVj+kuSFOV1lT
|
||||
+IclQYA6bM6uY5mroqcSBNegVxCNhWU03BxlW//BE9tA/+kq53vWylMeN9mpGZea
|
||||
riEMIh25KFGWXqXlOOioH8bkMsqA8S7sBmc7jljyv+0toQ9vCCtJ+sueNPhxQQxH
|
||||
D2YvUjfzBQ04I9+wn30BByDJ1QA/FoPsunxIOUCcRBE/7jxuLYcpR+JvEF68yYIh
|
||||
atXRld4W4in7T65YDR8jK1Uj9XAcNeDYNpT/M6oFLx1aPIlkG86aCWRO19S1jLPT
|
||||
b1ZAKHHxPMCVkSYW0RqvIgLXQOR62D0Zne6/2wtzJkk5UCjkSQ2z7ZzJpMkWgDgN
|
||||
ifCULFPBAoGBAPoMZ5q1w+zB+knXUD33n1J+niN6TZHJulpf2w5zsW+m2K6Zn62M
|
||||
MXndXlVAHtk6p02q9kxHdgov34Uo8VpuNjbS1+abGFTI8NZgFo+bsDxJdItemwC4
|
||||
KJ7L1iz39hRN/ZylMRLz5uTYRGddCkeIHhiG2h7zohH/MaYzUacXEEy3AoGBANz8
|
||||
e/msleB+iXC0cXKwds26N4hyMdAFE5qAqJXvV3S2W8JZnmU+sS7vPAWMYPlERPk1
|
||||
D8Q2eXqdPIkAWBhrx4RxD7rNc5qFNcQWEhCIxC9fccluH1y5g2M+4jpMX2CT8Uv+
|
||||
3z+NoJ5uDTXZTnLCfoZzgZ4nCZVZ+6iU5U1+YXFJAoGBANLPpIV920n/nJmmquMj
|
||||
orI1R/QXR9Cy56cMC65agezlGOfTYxk5Cfl5Ve+/2IJCfgzwJyjWUsFx7RviEeGw
|
||||
64o7JoUom1HX+5xxdHPsyZ96OoTJ5RqtKKoApnhRMamau0fWydH1yeOEJd+TRHhc
|
||||
XStGfhz8QNa1dVFvENczja1vAoGABGWhsd4VPVpHMc7lUvrf4kgKQtTC2PjA4xoc
|
||||
QJ96hf/642sVE76jl+N6tkGMzGjnVm4P2j+bOy1VvwQavKGoXqJBRd5Apppv727g
|
||||
/SM7hBXKFc/zH80xKBBgP/i1DR7kdjakCoeu4ngeGywvu2jTS6mQsqzkK+yWbUxJ
|
||||
I7mYBsECgYB/KNXlTEpXtz/kwWCHFSYA8U74l7zZbVD8ul0e56JDK+lLcJ0tJffk
|
||||
gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl
|
||||
NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw==
|
||||
-----END RSA PRIVATE KEY-----`
|
||||
|
||||
var serverConfig = &ssh.ServerConfig{
|
||||
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
||||
if c.User() == "user" && string(pass) == "pass" {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("password rejected for %q", c.User())
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Parse and set the private key of the server, required to accept connections
|
||||
signer, err := ssh.ParsePrivateKey([]byte(testServerPrivateKey))
|
||||
if err != nil {
|
||||
panic("unable to parse private key: " + err.Error())
|
||||
}
|
||||
serverConfig.AddHostKey(signer)
|
||||
}
|
||||
|
||||
func newMockLineServer(t *testing.T) string {
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to listen for connection: %s", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer l.Close()
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
t.Errorf("Unable to accept incoming connection: %s", err)
|
||||
}
|
||||
defer c.Close()
|
||||
conn, chans, _, err := ssh.NewServerConn(c, serverConfig)
|
||||
if err != nil {
|
||||
t.Logf("Handshaking error: %v", err)
|
||||
}
|
||||
t.Log("Accepted SSH connection")
|
||||
for newChannel := range chans {
|
||||
channel, _, err := newChannel.Accept()
|
||||
if err != nil {
|
||||
t.Errorf("Unable to accept channel.")
|
||||
}
|
||||
t.Log("Accepted channel")
|
||||
|
||||
go func(channelType string) {
|
||||
defer channel.Close()
|
||||
conn.OpenChannel(channelType, nil)
|
||||
}(newChannel.ChannelType())
|
||||
}
|
||||
conn.Close()
|
||||
}()
|
||||
|
||||
return l.Addr().String()
|
||||
}
|
||||
|
||||
func newMockBrokenServer(t *testing.T) string {
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable tp listen for connection: %s", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer l.Close()
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
t.Errorf("Unable to accept incoming connection: %s", err)
|
||||
}
|
||||
defer c.Close()
|
||||
// This should block for a period of time longer than our timeout in
|
||||
// the test case. That way we invoke a failure scenario.
|
||||
t.Log("Block on handshaking for SSH connection")
|
||||
time.Sleep(5 * time.Second)
|
||||
}()
|
||||
|
||||
return l.Addr().String()
|
||||
}
|
||||
|
||||
func TestCommIsCommunicator(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Communicator{}
|
||||
if _, ok := raw.(communicator.Communicator); !ok {
|
||||
t.Fatalf("Communicator must be a communicator")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNew_Invalid(t *testing.T) {
|
||||
clientConfig := &ssh.ClientConfig{
|
||||
User: "user",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("i-am-invalid"),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
address := newMockLineServer(t)
|
||||
conn := func() (net.Conn, error) {
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to accept incoming connection: %v", err)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
config := &Config{
|
||||
Connection: conn,
|
||||
SSHConfig: clientConfig,
|
||||
}
|
||||
|
||||
comm, err := New(address, config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to setup communicator: %s", err)
|
||||
}
|
||||
err = comm.Connect()
|
||||
if err == nil {
|
||||
t.Fatal("should have had an error connecting")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
clientConfig := &ssh.ClientConfig{
|
||||
User: "user",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("pass"),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
address := newMockLineServer(t)
|
||||
conn := func() (net.Conn, error) {
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to dial to remote side: %s", err)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
config := &Config{
|
||||
Connection: conn,
|
||||
SSHConfig: clientConfig,
|
||||
}
|
||||
|
||||
client, err := New(address, config)
|
||||
if err != nil {
|
||||
t.Fatalf("error connecting to SSH: %s", err)
|
||||
}
|
||||
|
||||
cmd := &communicator.Cmd{
|
||||
Command: "echo foo",
|
||||
Stdout: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
client.Start(cmd)
|
||||
}
|
||||
|
||||
func TestHandshakeTimeout(t *testing.T) {
|
||||
clientConfig := &ssh.ClientConfig{
|
||||
User: "user",
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password("pass"),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
address := newMockBrokenServer(t)
|
||||
conn := func() (net.Conn, error) {
|
||||
conn, err := net.Dial("tcp", address)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to dial to remote side: %s", err)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
config := &Config{
|
||||
Connection: conn,
|
||||
SSHConfig: clientConfig,
|
||||
HandshakeTimeout: 50 * time.Millisecond,
|
||||
}
|
||||
|
||||
comm, err := New(address, config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to setup communicator: %s", err)
|
||||
}
|
||||
err = comm.Connect()
|
||||
if err != ErrHandshakeTimeout {
|
||||
// Note: there's another error that can come back from this call:
|
||||
// ssh: handshake failed: EOF
|
||||
// This should appear in cases where the handshake fails because of
|
||||
// malformed (or no) data sent back by the server, but should not happen
|
||||
// in a timeout scenario.
|
||||
t.Fatalf("Expected handshake timeout, got: %s", err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
// ConnectFunc is a convenience method for returning a function
|
||||
// that just uses net.Dial to communicate with the remote end that
|
||||
// is suitable for use with the SSH communicator configuration.
|
||||
func ConnectFunc(network, addr string) func() (net.Conn, error) {
|
||||
return func() (net.Conn, error) {
|
||||
c, err := net.DialTimeout(network, addr, 15*time.Second)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tcpConn, ok := c.(*net.TCPConn); ok {
|
||||
tcpConn.SetKeepAlive(true)
|
||||
tcpConn.SetKeepAlivePeriod(5 * time.Second)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ProxyConnectFunc is a convenience method for returning a function
|
||||
// that connects to a host using SOCKS5 proxy
|
||||
func ProxyConnectFunc(socksProxy string, socksAuth *proxy.Auth, network, addr string) func() (net.Conn, error) {
|
||||
return func() (net.Conn, error) {
|
||||
// create a socks5 dialer
|
||||
dialer, err := proxy.SOCKS5("tcp", socksProxy, socksAuth, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can't connect to the proxy: %s", err)
|
||||
}
|
||||
|
||||
c, err := dialer.Dial(network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
|
||||
// BastionConnectFunc is a convenience method for returning a function
|
||||
// that connects to a host over a bastion connection.
|
||||
func BastionConnectFunc(
|
||||
bProto string,
|
||||
bAddr string,
|
||||
bConf *ssh.ClientConfig,
|
||||
proto string,
|
||||
addr string) func() (net.Conn, error) {
|
||||
return func() (net.Conn, error) {
|
||||
// Connect to the bastion
|
||||
bastion, err := ssh.Dial(bProto, bAddr, bConf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error connecting to bastion: %s", err)
|
||||
}
|
||||
|
||||
// Connect through to the end host
|
||||
conn, err := bastion.Dial(proto, addr)
|
||||
if err != nil {
|
||||
bastion.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Wrap it up so we close both things properly
|
||||
return &bastionConn{
|
||||
Conn: conn,
|
||||
Bastion: bastion,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
type bastionConn struct {
|
||||
net.Conn
|
||||
Bastion *ssh.Client
|
||||
}
|
||||
|
||||
func (c *bastionConn) Close() error {
|
||||
c.Conn.Close()
|
||||
return c.Bastion.Close()
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// timeoutConn wraps a net.Conn, and sets a deadline for every read
|
||||
// and write operation.
|
||||
type timeoutConn struct {
|
||||
net.Conn
|
||||
ReadTimeout time.Duration
|
||||
WriteTimeout time.Duration
|
||||
}
|
||||
|
||||
func (c *timeoutConn) Read(b []byte) (int, error) {
|
||||
err := c.Conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return c.Conn.Read(b)
|
||||
}
|
||||
|
||||
func (c *timeoutConn) Write(b []byte) (int, error) {
|
||||
err := c.Conn.SetWriteDeadline(time.Now().Add(c.WriteTimeout))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return c.Conn.Write(b)
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// An implementation of ssh.KeyboardInteractiveChallenge that simply sends
|
||||
// back the password for all questions. The questions are logged.
|
||||
func PasswordKeyboardInteractive(password string) ssh.KeyboardInteractiveChallenge {
|
||||
return func(user, instruction string, questions []string, echos []bool) ([]string, error) {
|
||||
logger.Info("keyboard interactive challenge", "user", user,
|
||||
"instructions", instruction)
|
||||
for i, question := range questions {
|
||||
logger.Info("challenge question", "number", i+1, "question", question)
|
||||
}
|
||||
|
||||
// Just send the password back for all questions
|
||||
answers := make([]string, len(questions))
|
||||
for i := range answers {
|
||||
answers[i] = password
|
||||
}
|
||||
|
||||
return answers, nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func TestPasswordKeyboardInteractive_Impl(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = PasswordKeyboardInteractive("foo")
|
||||
if _, ok := raw.(ssh.KeyboardInteractiveChallenge); !ok {
|
||||
t.Fatal("PasswordKeyboardInteractive must implement KeyboardInteractiveChallenge")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPasswordKeyboardInteractive_Challenge(t *testing.T) {
|
||||
p := PasswordKeyboardInteractive("foo")
|
||||
result, err := p("foo", "bar", []string{"one", "two"}, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err not nil: %s", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(result, []string{"foo", "foo"}) {
|
||||
t.Fatalf("invalid password: %#v", result)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,257 @@
|
|||
package winrm
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/communicator"
|
||||
"github.com/masterzen/winrm"
|
||||
"github.com/packer-community/winrmcp/winrmcp"
|
||||
)
|
||||
|
||||
var logger = vagrant.DefaultLogger().Named("communicator.winrm")
|
||||
|
||||
// Communicator represents the WinRM communicator
|
||||
type Communicator struct {
|
||||
config *Config
|
||||
client *winrm.Client
|
||||
endpoint *winrm.Endpoint
|
||||
}
|
||||
|
||||
// New creates a new communicator implementation over WinRM.
|
||||
func New(config *Config) (*Communicator, error) {
|
||||
endpoint := &winrm.Endpoint{
|
||||
Host: config.Host,
|
||||
Port: config.Port,
|
||||
HTTPS: config.Https,
|
||||
Insecure: config.Insecure,
|
||||
|
||||
/*
|
||||
TODO
|
||||
HTTPS: connInfo.HTTPS,
|
||||
Insecure: connInfo.Insecure,
|
||||
CACert: connInfo.CACert,
|
||||
*/
|
||||
}
|
||||
|
||||
// Create the client
|
||||
params := *winrm.DefaultParameters
|
||||
|
||||
if config.TransportDecorator != nil {
|
||||
params.TransportDecorator = config.TransportDecorator
|
||||
}
|
||||
|
||||
params.Timeout = formatDuration(config.Timeout)
|
||||
client, err := winrm.NewClientWithParameters(
|
||||
endpoint, config.Username, config.Password, ¶ms)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Communicator{
|
||||
config: config,
|
||||
client: client,
|
||||
endpoint: endpoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Communicator) Connect() (err error) {
|
||||
// Create the shell to verify the connection
|
||||
logger.Debug("connecting to remote shell")
|
||||
shell, err := c.client.CreateShell()
|
||||
if err != nil {
|
||||
logger.Error("connection failure", "error", err)
|
||||
return
|
||||
}
|
||||
if err = shell.Close(); err != nil {
|
||||
logger.Error("connection close failure", "error", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Start implementation of communicator.Communicator interface
|
||||
func (c *Communicator) Start(rc *communicator.Cmd) error {
|
||||
shell, err := c.client.CreateShell()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info("starting remote command", "commmand", rc.Command)
|
||||
|
||||
rc.Init()
|
||||
cmd, err := shell.Execute(rc.Command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go runCommand(shell, cmd, rc)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCommand(shell *winrm.Shell, cmd *winrm.Command, rc *communicator.Cmd) {
|
||||
defer shell.Close()
|
||||
var wg sync.WaitGroup
|
||||
|
||||
copyFunc := func(w io.Writer, r io.Reader) {
|
||||
defer wg.Done()
|
||||
io.Copy(w, r)
|
||||
}
|
||||
|
||||
if rc.Stdout != nil && cmd.Stdout != nil {
|
||||
wg.Add(1)
|
||||
go copyFunc(rc.Stdout, cmd.Stdout)
|
||||
} else {
|
||||
logger.Warn("failed to read stdout", "command", rc.Command)
|
||||
}
|
||||
|
||||
if rc.Stderr != nil && cmd.Stderr != nil {
|
||||
wg.Add(1)
|
||||
go copyFunc(rc.Stderr, cmd.Stderr)
|
||||
} else {
|
||||
logger.Warn("failed to read stderr", "command", rc.Command)
|
||||
}
|
||||
|
||||
cmd.Wait()
|
||||
wg.Wait()
|
||||
|
||||
code := cmd.ExitCode()
|
||||
logger.Info("command complete", "exitcode", code, "command", rc.Command)
|
||||
rc.SetExitStatus(code, nil)
|
||||
}
|
||||
|
||||
// Upload implementation of communicator.Communicator interface
|
||||
func (c *Communicator) Upload(path string, input io.Reader, fi *os.FileInfo) error {
|
||||
wcp, err := c.newCopyClient()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Was unable to create winrm client: %s", err)
|
||||
}
|
||||
if strings.HasSuffix(path, `\`) {
|
||||
// path is a directory
|
||||
path += filepath.Base((*fi).Name())
|
||||
}
|
||||
logger.Info("uploading file", "path", path)
|
||||
return wcp.Write(path, input)
|
||||
}
|
||||
|
||||
// UploadDir implementation of communicator.Communicator interface
|
||||
func (c *Communicator) UploadDir(dst string, src string, exclude []string) error {
|
||||
if !strings.HasSuffix(src, "/") {
|
||||
dst = fmt.Sprintf("%s\\%s", dst, filepath.Base(src))
|
||||
}
|
||||
logger.Info("uploading directory", "source", src, "destination", dst)
|
||||
wcp, err := c.newCopyClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return wcp.Copy(src, dst)
|
||||
}
|
||||
|
||||
func (c *Communicator) Download(src string, dst io.Writer) error {
|
||||
client, err := c.newWinRMClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
encodeScript := `$file=[System.IO.File]::ReadAllBytes("%s"); Write-Output $([System.Convert]::ToBase64String($file))`
|
||||
|
||||
base64DecodePipe := &Base64Pipe{w: dst}
|
||||
|
||||
cmd := winrm.Powershell(fmt.Sprintf(encodeScript, src))
|
||||
_, err = client.Run(cmd, base64DecodePipe, ioutil.Discard)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Communicator) DownloadDir(src string, dst string, exclude []string) error {
|
||||
return fmt.Errorf("WinRM doesn't support download dir.")
|
||||
}
|
||||
|
||||
func (c *Communicator) getClientConfig() *winrmcp.Config {
|
||||
return &winrmcp.Config{
|
||||
Auth: winrmcp.Auth{
|
||||
User: c.config.Username,
|
||||
Password: c.config.Password,
|
||||
},
|
||||
Https: c.config.Https,
|
||||
Insecure: c.config.Insecure,
|
||||
OperationTimeout: c.config.Timeout,
|
||||
MaxOperationsPerShell: 15, // lowest common denominator
|
||||
TransportDecorator: c.config.TransportDecorator,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Communicator) newCopyClient() (*winrmcp.Winrmcp, error) {
|
||||
addr := fmt.Sprintf("%s:%d", c.endpoint.Host, c.endpoint.Port)
|
||||
clientConfig := c.getClientConfig()
|
||||
return winrmcp.New(addr, clientConfig)
|
||||
}
|
||||
|
||||
func (c *Communicator) newWinRMClient() (*winrm.Client, error) {
|
||||
conf := c.getClientConfig()
|
||||
|
||||
// Shamelessly borrowed from the winrmcp client to ensure
|
||||
// that the client is configured using the same defaulting behaviors that
|
||||
// winrmcp uses even we we aren't using winrmcp. This ensures similar
|
||||
// behavior between upload, download, and copy functions. We can't use the
|
||||
// one generated by winrmcp because it isn't exported.
|
||||
var endpoint *winrm.Endpoint
|
||||
endpoint = &winrm.Endpoint{
|
||||
Host: c.endpoint.Host,
|
||||
Port: c.endpoint.Port,
|
||||
HTTPS: conf.Https,
|
||||
Insecure: conf.Insecure,
|
||||
TLSServerName: conf.TLSServerName,
|
||||
CACert: conf.CACertBytes,
|
||||
Timeout: conf.ConnectTimeout,
|
||||
}
|
||||
params := winrm.NewParameters(
|
||||
winrm.DefaultParameters.Timeout,
|
||||
winrm.DefaultParameters.Locale,
|
||||
winrm.DefaultParameters.EnvelopeSize,
|
||||
)
|
||||
|
||||
params.TransportDecorator = conf.TransportDecorator
|
||||
params.Timeout = "PT3M"
|
||||
|
||||
client, err := winrm.NewClientWithParameters(
|
||||
endpoint, conf.Auth.User, conf.Auth.Password, params)
|
||||
return client, err
|
||||
}
|
||||
|
||||
type Base64Pipe struct {
|
||||
w io.Writer // underlying writer (file, buffer)
|
||||
}
|
||||
|
||||
func (d *Base64Pipe) ReadFrom(r io.Reader) (int64, error) {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var i int
|
||||
i, err = d.Write(b)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int64(i), err
|
||||
}
|
||||
|
||||
func (d *Base64Pipe) Write(p []byte) (int, error) {
|
||||
dst := make([]byte, base64.StdEncoding.DecodedLen(len(p)))
|
||||
|
||||
decodedBytes, err := base64.StdEncoding.Decode(dst, p)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return d.w.Write(dst[0:decodedBytes])
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package winrm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/dylanmei/winrmtest"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/communicator"
|
||||
)
|
||||
|
||||
const PAYLOAD = "stuff"
|
||||
const BASE64_ENCODED_PAYLOAD = "c3R1ZmY="
|
||||
|
||||
func newMockWinRMServer(t *testing.T) *winrmtest.Remote {
|
||||
wrm := winrmtest.NewRemote()
|
||||
|
||||
wrm.CommandFunc(
|
||||
winrmtest.MatchText("echo foo"),
|
||||
func(out, err io.Writer) int {
|
||||
out.Write([]byte("foo"))
|
||||
return 0
|
||||
})
|
||||
|
||||
wrm.CommandFunc(
|
||||
winrmtest.MatchPattern(`^echo c29tZXRoaW5n >> ".*"$`),
|
||||
func(out, err io.Writer) int {
|
||||
return 0
|
||||
})
|
||||
|
||||
wrm.CommandFunc(
|
||||
winrmtest.MatchPattern(`^echo `+BASE64_ENCODED_PAYLOAD+` >> ".*"$`),
|
||||
func(out, err io.Writer) int {
|
||||
return 0
|
||||
})
|
||||
|
||||
wrm.CommandFunc(
|
||||
winrmtest.MatchPattern(`^powershell.exe -EncodedCommand .*$`),
|
||||
func(out, err io.Writer) int {
|
||||
out.Write([]byte(BASE64_ENCODED_PAYLOAD))
|
||||
return 0
|
||||
})
|
||||
|
||||
wrm.CommandFunc(
|
||||
winrmtest.MatchText("powershell"),
|
||||
func(out, err io.Writer) int {
|
||||
return 0
|
||||
})
|
||||
wrm.CommandFunc(
|
||||
winrmtest.MatchText(`powershell -Command "(Get-Item C:/Temp/vagrant.cmd) -is [System.IO.DirectoryInfo]"`),
|
||||
func(out, err io.Writer) int {
|
||||
out.Write([]byte("False"))
|
||||
return 0
|
||||
})
|
||||
|
||||
return wrm
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
wrm := newMockWinRMServer(t)
|
||||
defer wrm.Close()
|
||||
|
||||
c, err := New(&Config{
|
||||
Host: wrm.Host,
|
||||
Port: wrm.Port,
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
Timeout: 30 * time.Second,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("error creating communicator: %s", err)
|
||||
}
|
||||
|
||||
var cmd communicator.Cmd
|
||||
stdout := new(bytes.Buffer)
|
||||
cmd.Command = "echo foo"
|
||||
cmd.Stdout = stdout
|
||||
|
||||
err = c.Start(&cmd)
|
||||
if err != nil {
|
||||
t.Fatalf("error executing remote command: %s", err)
|
||||
}
|
||||
cmd.Wait()
|
||||
|
||||
if stdout.String() != "foo" {
|
||||
t.Fatalf("bad command response: expected %q, got %q", "foo", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpload(t *testing.T) {
|
||||
wrm := newMockWinRMServer(t)
|
||||
defer wrm.Close()
|
||||
|
||||
c, err := New(&Config{
|
||||
Host: wrm.Host,
|
||||
Port: wrm.Port,
|
||||
Username: "user",
|
||||
Password: "pass",
|
||||
Timeout: 30 * time.Second,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("error creating communicator: %s", err)
|
||||
}
|
||||
file := "C:/Temp/vagrant.cmd"
|
||||
err = c.Upload(file, strings.NewReader(PAYLOAD), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("error uploading file: %s", err)
|
||||
}
|
||||
|
||||
dest := new(bytes.Buffer)
|
||||
err = c.Download(file, dest)
|
||||
if err != nil {
|
||||
t.Fatalf("error downloading file: %s", err)
|
||||
}
|
||||
downloadedPayload := dest.String()
|
||||
|
||||
if downloadedPayload != PAYLOAD {
|
||||
t.Fatalf("files are not equal: expected [%s] length: %v, got [%s] length %v", PAYLOAD, len(PAYLOAD), downloadedPayload, len(downloadedPayload))
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package winrm
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/masterzen/winrm"
|
||||
)
|
||||
|
||||
// Config is used to configure the WinRM connection
|
||||
type Config struct {
|
||||
Host string
|
||||
Port int
|
||||
Username string
|
||||
Password string
|
||||
Timeout time.Duration
|
||||
Https bool
|
||||
Insecure bool
|
||||
TransportDecorator func() winrm.Transporter
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package winrm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// formatDuration formats the given time.Duration into an ISO8601
|
||||
// duration string.
|
||||
func formatDuration(duration time.Duration) string {
|
||||
// We're not supporting negative durations
|
||||
if duration.Seconds() <= 0 {
|
||||
return "PT0S"
|
||||
}
|
||||
|
||||
h := int(duration.Hours())
|
||||
m := int(duration.Minutes()) - (h * 60)
|
||||
s := int(duration.Seconds()) - (h*3600 + m*60)
|
||||
|
||||
res := "PT"
|
||||
if h > 0 {
|
||||
res = fmt.Sprintf("%s%dH", res, h)
|
||||
}
|
||||
if m > 0 {
|
||||
res = fmt.Sprintf("%s%dM", res, m)
|
||||
}
|
||||
if s > 0 {
|
||||
res = fmt.Sprintf("%s%dS", res, s)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package winrm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFormatDuration(t *testing.T) {
|
||||
// Test complex duration with hours, minutes, seconds
|
||||
d := time.Duration(3701) * time.Second
|
||||
s := formatDuration(d)
|
||||
if s != "PT1H1M41S" {
|
||||
t.Fatalf("bad ISO 8601 duration string: %s", s)
|
||||
}
|
||||
|
||||
// Test only minutes duration
|
||||
d = time.Duration(20) * time.Minute
|
||||
s = formatDuration(d)
|
||||
if s != "PT20M" {
|
||||
t.Fatalf("bad ISO 8601 duration string for 20M: %s", s)
|
||||
}
|
||||
|
||||
// Test only seconds
|
||||
d = time.Duration(1) * time.Second
|
||||
s = formatDuration(d)
|
||||
if s != "PT1S" {
|
||||
t.Fatalf("bad ISO 8601 duration string for 1S: %s", s)
|
||||
}
|
||||
|
||||
// Test negative duration (unsupported)
|
||||
d = time.Duration(-1) * time.Second
|
||||
s = formatDuration(d)
|
||||
if s != "PT0S" {
|
||||
t.Fatalf("bad ISO 8601 duration string for negative: %s", s)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package vagrant
|
||||
|
||||
type Config interface {
|
||||
ConfigAttributes() (attrs []string, err error)
|
||||
ConfigLoad(data map[string]interface{}) (loaddata map[string]interface{}, err error)
|
||||
ConfigValidate(data map[string]interface{}, m *Machine) (errors []string, err error)
|
||||
ConfigFinalize(data map[string]interface{}) (finaldata map[string]interface{}, err error)
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Environment struct {
|
||||
ActiveMachines map[string]string `json:"active_machines,omitempty"`
|
||||
AliasesPath string `json:"aliases_path,omitempty"`
|
||||
BoxesPath string `json:"boxes_path,omitempty"`
|
||||
CWD string `json:"cwd,omitempty"`
|
||||
DataDir string `json:"data_dir,omitempty"`
|
||||
DefaultPrivateKeyPath string `json:"default_private_key_path,omitempty"`
|
||||
GemsPath string `json:"gems_path,omitempty"`
|
||||
HomePath string `json:"home_path,omitempty"`
|
||||
LocalDataPath string `json:"local_data_path,omitempty"`
|
||||
MachineNames []string `json:"machine_names,omitempty"`
|
||||
PrimaryMachineName string `json:"primary_machine_name,omitempty"`
|
||||
RootPath string `json:"root_path,omitempty"`
|
||||
TmpPath string `json:"tmp_path,omitempty"`
|
||||
VagrantfileName string `json:"vagrantfile_name,omitempty"`
|
||||
UI Ui `json:"-"`
|
||||
}
|
||||
|
||||
func DumpEnvironment(e *Environment) (s string, err error) {
|
||||
DefaultLogger().Debug("dumping environment to serialized data")
|
||||
b, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
DefaultLogger().Error("environment dump failure", "error", err)
|
||||
return
|
||||
}
|
||||
s = string(b)
|
||||
return
|
||||
}
|
||||
|
||||
func LoadEnvironment(edata string, ios IOServer) (e *Environment, err error) {
|
||||
DefaultLogger().Debug("loading environment from serialized data")
|
||||
e = &Environment{}
|
||||
err = json.Unmarshal([]byte(edata), e)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var stdout io.Writer
|
||||
var stderr io.Writer
|
||||
if ios == nil {
|
||||
stdout = os.Stdout
|
||||
stderr = os.Stderr
|
||||
} else {
|
||||
stdout = &IOWriter{target: "stdout", srv: ios}
|
||||
stderr = &IOWriter{target: "stderr", srv: ios}
|
||||
}
|
||||
e.UI = &TargetedUi{
|
||||
Target: "vagrant",
|
||||
Ui: &ColoredUi{
|
||||
ErrorColor: UiColorRed,
|
||||
Ui: &BasicUi{
|
||||
Reader: os.Stdin,
|
||||
Writer: stdout,
|
||||
ErrorWriter: stderr},
|
||||
}}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadEnvironment(t *testing.T) {
|
||||
env, err := LoadEnvironment("{}", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %s", err)
|
||||
}
|
||||
if env.UI == nil {
|
||||
t.Fatalf("no UI configured for environment")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadLoadEnvironment(t *testing.T) {
|
||||
_, err := LoadEnvironment("ack", nil)
|
||||
if err == nil {
|
||||
t.Fatalf("expected load error but none provided")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadEnvironmentUIStdout(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
env, err := LoadEnvironment("{}", iosrv)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %s", err)
|
||||
}
|
||||
go func() { env.UI.Info("test string") }()
|
||||
str := <-iosrv.Streams()["stdout"]
|
||||
if !strings.Contains(str, "test string") {
|
||||
t.Fatalf("unexpected output: %s", str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadEnvironmentUIStderr(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
env, err := LoadEnvironment("{}", iosrv)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %s", err)
|
||||
}
|
||||
go func() { env.UI.Error("test string") }()
|
||||
str, err := iosrv.Read("stderr")
|
||||
if !strings.Contains(str, "test string") {
|
||||
t.Fatalf("unexpected output: %s", str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDumpEnvironment(t *testing.T) {
|
||||
env, err := LoadEnvironment("{}", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %s", err)
|
||||
}
|
||||
d, err := DumpEnvironment(env)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected dump error: %s", err)
|
||||
}
|
||||
if d != "{}" {
|
||||
t.Fatalf("unexpected dump information: %s", d)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
)
|
||||
|
||||
var GlobalIOServer *IOServer
|
||||
|
||||
var defaultLogger = hclog.Default().Named("vagrant")
|
||||
|
||||
func DefaultLogger() hclog.Logger {
|
||||
return defaultLogger
|
||||
}
|
||||
|
||||
func SetDefaultLogger(l hclog.Logger) {
|
||||
defaultLogger = l
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type StreamIO interface {
|
||||
Read(target string) (content string, err error)
|
||||
Write(content, target string) (n int, err error)
|
||||
}
|
||||
|
||||
type IOServer interface {
|
||||
Streams() map[string]chan (string)
|
||||
StreamIO
|
||||
}
|
||||
|
||||
type IOSrv struct {
|
||||
Targets map[string]chan (string)
|
||||
}
|
||||
|
||||
func (i *IOSrv) Streams() map[string]chan (string) {
|
||||
return i.Targets
|
||||
}
|
||||
|
||||
type IOWriter struct {
|
||||
target string
|
||||
srv IOServer
|
||||
}
|
||||
|
||||
func (i *IOWriter) Write(b []byte) (n int, err error) {
|
||||
content := string(b)
|
||||
n, err = i.srv.Write(content, i.target)
|
||||
return
|
||||
}
|
||||
|
||||
func (i *IOSrv) Read(target string) (content string, err error) {
|
||||
if _, ok := i.Streams()[target]; !ok {
|
||||
err = errors.New("Unknown target defined")
|
||||
return
|
||||
}
|
||||
content = <-i.Streams()[target]
|
||||
return
|
||||
}
|
||||
|
||||
func (i *IOSrv) Write(content, target string) (n int, err error) {
|
||||
if _, ok := i.Streams()[target]; !ok {
|
||||
err = errors.New("Unknown target defined")
|
||||
return
|
||||
}
|
||||
i.Streams()[target] <- content
|
||||
n = len(content)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func buildio() IOServer {
|
||||
return &IOSrv{
|
||||
Targets: map[string]chan (string){
|
||||
"stdout": make(chan string),
|
||||
"stderr": make(chan string)}}
|
||||
}
|
||||
|
||||
func TestIOSrvWrite(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
var i int
|
||||
go func() { i, _ = iosrv.Write("test string", "stdout") }()
|
||||
_, _ = iosrv.Read("stdout")
|
||||
if i != len("test string") {
|
||||
t.Fatalf("unexpected write bytes %d != %d",
|
||||
len("test string"), i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIOSrvRead(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
go func() { _, _ = iosrv.Write("test string", "stdout") }()
|
||||
r, _ := iosrv.Read("stdout")
|
||||
if r != "test string" {
|
||||
t.Fatalf("unexpected read result: %s", r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIOSrvWriteBadTarget(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
_, err := iosrv.Write("test string", "stdno")
|
||||
if err == nil {
|
||||
t.Fatalf("expected error on write")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIOSrvReadBadTarget(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
_, err := iosrv.Read("stdno")
|
||||
if err == nil {
|
||||
t.Fatalf("expected error on read")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Machine struct {
|
||||
Box Box `json:"box"`
|
||||
Config map[string]interface{} `json:"config"`
|
||||
DataDir string `json:"data_dir,omitempty"`
|
||||
Env Environment `json:"environment"`
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ProviderConfig map[string]interface{} `json:"provider_config"`
|
||||
ProviderName string `json:"provider_name,omitempty"`
|
||||
ProviderOptions map[string]string `json:"provider_options"`
|
||||
UI Ui `json:"-"`
|
||||
}
|
||||
|
||||
func DumpMachine(m *Machine) (s string, err error) {
|
||||
DefaultLogger().Debug("dumping machine to serialized data")
|
||||
b, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
DefaultLogger().Debug("machine dump failure", "error", err)
|
||||
return
|
||||
}
|
||||
s = string(b)
|
||||
return
|
||||
}
|
||||
|
||||
func LoadMachine(mdata string, ios IOServer) (m *Machine, err error) {
|
||||
DefaultLogger().Debug("loading machine from serialized data")
|
||||
m = &Machine{}
|
||||
err = json.Unmarshal([]byte(mdata), m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var stdout io.Writer
|
||||
var stderr io.Writer
|
||||
if ios == nil {
|
||||
stdout = os.Stdout
|
||||
stderr = os.Stderr
|
||||
} else {
|
||||
stdout = &IOWriter{target: "stdout", srv: ios}
|
||||
stderr = &IOWriter{target: "stderr", srv: ios}
|
||||
}
|
||||
m.UI = &TargetedUi{
|
||||
Target: m.Name,
|
||||
Ui: &ColoredUi{
|
||||
ErrorColor: UiColorRed,
|
||||
Ui: &BasicUi{
|
||||
Reader: os.Stdin,
|
||||
Writer: stdout,
|
||||
ErrorWriter: stderr},
|
||||
}}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package vagrant
|
||||
|
||||
type MachineState struct {
|
||||
Id string `json:"id"`
|
||||
ShortDesc string `json:"short_description"`
|
||||
LongDesc string `json:"long_description"`
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMachineLoad(t *testing.T) {
|
||||
_, err := LoadMachine("{}", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to load machine: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMachineDump(t *testing.T) {
|
||||
m, err := LoadMachine("{}", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %s", err)
|
||||
}
|
||||
_, err = DumpMachine(m)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to dump machine: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMachineUI(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
m, err := LoadMachine("{}", iosrv)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %s", err)
|
||||
}
|
||||
go func() { m.UI.Info("test string") }()
|
||||
r, _ := iosrv.Read("stdout")
|
||||
if !strings.Contains(r, "test string") {
|
||||
t.Fatalf("unexpected read result: %s", r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMachineUINamed(t *testing.T) {
|
||||
iosrv := buildio()
|
||||
m, err := LoadMachine("{\"name\":\"plugintest\"}", iosrv)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected load error: %s", err)
|
||||
}
|
||||
go func() { m.UI.Info("test string") }()
|
||||
r, _ := iosrv.Read("stdout")
|
||||
if !strings.Contains(r, "test string") {
|
||||
t.Fatalf("unexpected read result: %s", r)
|
||||
}
|
||||
if !strings.Contains(r, "plugintest") {
|
||||
t.Fatalf("output does not contain name: %s", r)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
go_plugin "github.com/hashicorp/go-plugin"
|
||||
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
)
|
||||
|
||||
type RemoteConfig struct {
|
||||
Client *go_plugin.Client
|
||||
Config vagrant.Config
|
||||
}
|
||||
|
||||
type RemoteProvider struct {
|
||||
Client *go_plugin.Client
|
||||
Provider Provider
|
||||
}
|
||||
|
||||
type RemoteGuestCapabilities struct {
|
||||
Client *go_plugin.Client
|
||||
GuestCapabilities vagrant.GuestCapabilities
|
||||
}
|
||||
|
||||
type RemoteHostCapabilities struct {
|
||||
Client *go_plugin.Client
|
||||
HostCapabilities vagrant.HostCapabilities
|
||||
}
|
||||
|
||||
type RemoteProviderCapabilities struct {
|
||||
Client *go_plugin.Client
|
||||
ProviderCapabilities vagrant.ProviderCapabilities
|
||||
}
|
||||
|
||||
type RemoteSyncedFolder struct {
|
||||
Client *go_plugin.Client
|
||||
SyncedFolder vagrant.SyncedFolder
|
||||
}
|
||||
|
||||
type VagrantPlugin struct {
|
||||
Providers map[string]*RemoteProvider
|
||||
SyncedFolders map[string]*RemoteSyncedFolder
|
||||
PluginDirectories []string
|
||||
Logger hclog.Logger
|
||||
}
|
||||
|
||||
func (v *VagrantPlugin) LoadPlugins(pluginPath string) error {
|
||||
for _, p := range v.PluginDirectories {
|
||||
if p == pluginPath {
|
||||
v.Logger.Error("plugin directory path already loaded", "path", pluginPath)
|
||||
return errors.New("plugin directory already loaded")
|
||||
}
|
||||
}
|
||||
v.PluginDirectories = append(v.PluginDirectories, pluginPath)
|
||||
if err := v.LoadProviders(pluginPath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := v.LoadSyncedFolders(pluginPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VagrantPlugin) LoadProviders(pluginPath string) error {
|
||||
providerPaths, err := go_plugin.Discover("*_provider", pluginPath)
|
||||
if err != nil {
|
||||
v.Logger.Error("error during plugin discovery", "type", "provider",
|
||||
"error", err, "path", pluginPath)
|
||||
return err
|
||||
}
|
||||
for _, providerPath := range providerPaths {
|
||||
v.Logger.Info("loading provider plugin", "path", providerPath)
|
||||
|
||||
client := go_plugin.NewClient(&go_plugin.ClientConfig{
|
||||
AllowedProtocols: []go_plugin.Protocol{go_plugin.ProtocolGRPC},
|
||||
Logger: v.Logger,
|
||||
HandshakeConfig: go_plugin.HandshakeConfig{
|
||||
MagicCookieKey: "BASIC_PLUGIN",
|
||||
MagicCookieValue: "hello",
|
||||
ProtocolVersion: 1,
|
||||
},
|
||||
Cmd: exec.Command(providerPath),
|
||||
VersionedPlugins: map[int]go_plugin.PluginSet{
|
||||
2: {"provider": &ProviderPlugin{}}}})
|
||||
gclient, err := client.Client()
|
||||
if err != nil {
|
||||
v.Logger.Error("error loading provider client", "error", err, "path", providerPath)
|
||||
return err
|
||||
}
|
||||
raw, err := gclient.Dispense("provider")
|
||||
if err != nil {
|
||||
v.Logger.Error("error loading provider plugin", "error", err, "path", providerPath)
|
||||
return err
|
||||
}
|
||||
prov := raw.(Provider)
|
||||
n := prov.Name()
|
||||
v.Providers[n] = &RemoteProvider{
|
||||
Client: client,
|
||||
Provider: prov}
|
||||
v.Logger.Info("plugin loaded", "type", "provider", "name", n, "path", providerPath)
|
||||
go v.StreamIO("stdout", prov, n, "provider")
|
||||
go v.StreamIO("stderr", prov, n, "provider")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VagrantPlugin) LoadSyncedFolders(pluginPath string) error {
|
||||
folderPaths, err := go_plugin.Discover("*_synced_folder", pluginPath)
|
||||
if err != nil {
|
||||
v.Logger.Error("error during plugin discovery", "type", "synced_folder",
|
||||
"error", err, "path", pluginPath)
|
||||
return err
|
||||
}
|
||||
for _, folderPath := range folderPaths {
|
||||
v.Logger.Info("loading synced_folder plugin", "path", folderPath)
|
||||
|
||||
client := go_plugin.NewClient(&go_plugin.ClientConfig{
|
||||
AllowedProtocols: []go_plugin.Protocol{go_plugin.ProtocolGRPC},
|
||||
Logger: v.Logger,
|
||||
HandshakeConfig: go_plugin.HandshakeConfig{
|
||||
MagicCookieKey: "BASIC_PLUGIN",
|
||||
MagicCookieValue: "hello",
|
||||
ProtocolVersion: 1,
|
||||
},
|
||||
Cmd: exec.Command(folderPath),
|
||||
VersionedPlugins: map[int]go_plugin.PluginSet{
|
||||
2: {"synced_folders": &SyncedFolderPlugin{}}}})
|
||||
gclient, err := client.Client()
|
||||
if err != nil {
|
||||
v.Logger.Error("error loading synced_folder client", "error", err, "path", folderPath)
|
||||
return err
|
||||
}
|
||||
raw, err := gclient.Dispense("synced_folder")
|
||||
if err != nil {
|
||||
v.Logger.Error("error loading synced_folder plugin", "error", err, "path", folderPath)
|
||||
return err
|
||||
}
|
||||
fold := raw.(SyncedFolder)
|
||||
n := fold.Name()
|
||||
v.SyncedFolders[n] = &RemoteSyncedFolder{
|
||||
Client: client,
|
||||
SyncedFolder: fold}
|
||||
v.Logger.Info("plugin loaded", "type", "synced_folder", "name", n, "path", folderPath)
|
||||
go v.StreamIO("stdout", fold, n, "synced_folder")
|
||||
go v.StreamIO("stderr", fold, n, "synced_folder")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *VagrantPlugin) StreamIO(target string, i vagrant.IOServer, name, kind string) {
|
||||
v.Logger.Info("starting plugin IO streaming", "target", target, "plugin", name, "type", kind)
|
||||
for {
|
||||
str, err := i.Read(target)
|
||||
if err != nil {
|
||||
v.Logger.Error("plugin IO streaming failure", "target", target, "plugin", name,
|
||||
"type", kind, "error", err)
|
||||
break
|
||||
}
|
||||
v.Logger.Debug("received plugin IO content", "target", target, "plugin", name,
|
||||
"type", kind, "content", str)
|
||||
if target == "stdout" {
|
||||
os.Stdout.Write([]byte(str))
|
||||
} else if target == "stderr" {
|
||||
os.Stderr.Write([]byte(str))
|
||||
}
|
||||
}
|
||||
v.Logger.Info("completed plugin IO streaming", "target", target, "plugin", name, "type", kind)
|
||||
}
|
||||
|
||||
func (v *VagrantPlugin) Kill() {
|
||||
v.Logger.Debug("killing all running plugins")
|
||||
for n, p := range v.Providers {
|
||||
v.Logger.Debug("killing plugin", "name", n, "type", "provider")
|
||||
p.Client.Kill()
|
||||
v.Logger.Info("plugin killed", "name", n, "type", "provider")
|
||||
}
|
||||
for n, p := range v.SyncedFolders {
|
||||
v.Logger.Debug("killing plugin", "name", n, "type", "synced_folder")
|
||||
p.Client.Kill()
|
||||
v.Logger.Info("plugin killed", "name", n, "type", "synced_folder")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,291 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
go_plugin "github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_caps"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
||||
)
|
||||
|
||||
type GuestCapabilities interface {
|
||||
vagrant.GuestCapabilities
|
||||
Meta
|
||||
}
|
||||
|
||||
type GuestCapabilitiesPlugin struct {
|
||||
go_plugin.NetRPCUnsupportedPlugin
|
||||
Impl GuestCapabilities
|
||||
}
|
||||
|
||||
type GRPCGuestCapabilitiesServer struct {
|
||||
GRPCIOServer
|
||||
Impl GuestCapabilities
|
||||
}
|
||||
|
||||
func (s *GRPCGuestCapabilitiesServer) GuestCapabilities(ctx context.Context, req *vagrant_common.NullRequest) (resp *vagrant_caps.CapabilitiesResponse, err error) {
|
||||
resp = &vagrant_caps.CapabilitiesResponse{}
|
||||
r, e := s.Impl.GuestCapabilities()
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
for _, cap := range r {
|
||||
rcap := &vagrant_caps.Capability{Name: cap.Name, Platform: cap.Platform}
|
||||
resp.Capabilities = append(resp.Capabilities, rcap)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCGuestCapabilitiesServer) GuestCapability(ctx context.Context, req *vagrant_caps.GuestCapabilityRequest) (resp *vagrant_caps.GuestCapabilityResponse, err error) {
|
||||
resp = &vagrant_caps.GuestCapabilityResponse{}
|
||||
var args interface{}
|
||||
err = json.Unmarshal([]byte(req.Arguments), args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cap := &vagrant.SystemCapability{
|
||||
Name: req.Capability.Name,
|
||||
Platform: req.Capability.Platform}
|
||||
r, err := s.Impl.GuestCapability(cap, args, machine)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
result, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp.Result = string(result)
|
||||
return
|
||||
}
|
||||
|
||||
type GRPCGuestCapabilitiesClient struct {
|
||||
client vagrant_caps.GuestCapabilitiesClient
|
||||
}
|
||||
|
||||
func (c *GRPCGuestCapabilitiesClient) GuestCapabilities() (caps []vagrant.SystemCapability, err error) {
|
||||
resp, err := c.client.GuestCapabilities(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
return
|
||||
}
|
||||
caps = make([]vagrant.SystemCapability, len(resp.Capabilities))
|
||||
for i := 0; i < len(resp.Capabilities); i++ {
|
||||
cap := vagrant.SystemCapability{
|
||||
Name: resp.Capabilities[i].Name,
|
||||
Platform: resp.Capabilities[i].Platform}
|
||||
caps[i] = cap
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCGuestCapabilitiesClient) GuestCapability(cap *vagrant.SystemCapability, args interface{}, machine *vagrant.Machine) (result interface{}, err error) {
|
||||
a, err := json.Marshal(args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m, err := vagrant.DumpMachine(machine)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.GuestCapability(context.Background(), &vagrant_caps.GuestCapabilityRequest{
|
||||
Capability: &vagrant_caps.Capability{Name: cap.Name, Platform: cap.Platform},
|
||||
Machine: m,
|
||||
Arguments: string(a)})
|
||||
err = json.Unmarshal([]byte(resp.Result), &result)
|
||||
return
|
||||
}
|
||||
|
||||
type HostCapabilities interface {
|
||||
vagrant.HostCapabilities
|
||||
Meta
|
||||
}
|
||||
|
||||
type GRPCHostCapabilitiesServer struct {
|
||||
GRPCIOServer
|
||||
Impl HostCapabilities
|
||||
}
|
||||
|
||||
func (s *GRPCHostCapabilitiesServer) HostCapabilities(ctx context.Context, req *vagrant_common.NullRequest) (resp *vagrant_caps.CapabilitiesResponse, err error) {
|
||||
resp = &vagrant_caps.CapabilitiesResponse{}
|
||||
r, e := s.Impl.HostCapabilities()
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
for _, cap := range r {
|
||||
rcap := &vagrant_caps.Capability{Name: cap.Name, Platform: cap.Platform}
|
||||
resp.Capabilities = append(resp.Capabilities, rcap)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCHostCapabilitiesServer) HostCapability(ctx context.Context, req *vagrant_caps.HostCapabilityRequest) (resp *vagrant_caps.HostCapabilityResponse, err error) {
|
||||
resp = &vagrant_caps.HostCapabilityResponse{}
|
||||
var args interface{}
|
||||
err = json.Unmarshal([]byte(req.Arguments), args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
env, err := vagrant.LoadEnvironment(req.Environment, s.Impl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cap := &vagrant.SystemCapability{
|
||||
Name: req.Capability.Name,
|
||||
Platform: req.Capability.Platform}
|
||||
r, err := s.Impl.HostCapability(cap, args, env)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
result, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp.Result = string(result)
|
||||
return
|
||||
}
|
||||
|
||||
type GRPCHostCapabilitiesClient struct {
|
||||
client vagrant_caps.HostCapabilitiesClient
|
||||
}
|
||||
|
||||
func (c *GRPCHostCapabilitiesClient) HostCapabilities() (caps []vagrant.SystemCapability, err error) {
|
||||
resp, err := c.client.HostCapabilities(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
return
|
||||
}
|
||||
caps = make([]vagrant.SystemCapability, len(resp.Capabilities))
|
||||
for i := 0; i < len(resp.Capabilities); i++ {
|
||||
cap := vagrant.SystemCapability{
|
||||
Name: resp.Capabilities[i].Name,
|
||||
Platform: resp.Capabilities[i].Platform}
|
||||
caps[i] = cap
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCHostCapabilitiesClient) HostCapability(cap *vagrant.SystemCapability, args interface{}, env *vagrant.Environment) (result interface{}, err error) {
|
||||
a, err := json.Marshal(args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e, err := vagrant.DumpEnvironment(env)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.HostCapability(context.Background(), &vagrant_caps.HostCapabilityRequest{
|
||||
Capability: &vagrant_caps.Capability{
|
||||
Name: cap.Name,
|
||||
Platform: cap.Platform},
|
||||
Environment: e,
|
||||
Arguments: string(a)})
|
||||
err = json.Unmarshal([]byte(resp.Result), &result)
|
||||
return
|
||||
}
|
||||
|
||||
type ProviderCapabilities interface {
|
||||
vagrant.ProviderCapabilities
|
||||
Meta
|
||||
}
|
||||
|
||||
type GRPCProviderCapabilitiesServer struct {
|
||||
GRPCIOServer
|
||||
Impl ProviderCapabilities
|
||||
}
|
||||
|
||||
func (s *GRPCProviderCapabilitiesServer) ProviderCapabilities(ctx context.Context, req *vagrant_common.NullRequest) (resp *vagrant_caps.ProviderCapabilitiesResponse, err error) {
|
||||
resp = &vagrant_caps.ProviderCapabilitiesResponse{}
|
||||
r, e := s.Impl.ProviderCapabilities()
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
for _, cap := range r {
|
||||
rcap := &vagrant_caps.ProviderCapability{Name: cap.Name, Provider: cap.Provider}
|
||||
resp.Capabilities = append(resp.Capabilities, rcap)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderCapabilitiesServer) ProviderCapability(ctx context.Context, req *vagrant_caps.ProviderCapabilityRequest) (resp *vagrant_caps.ProviderCapabilityResponse, err error) {
|
||||
resp = &vagrant_caps.ProviderCapabilityResponse{}
|
||||
var args interface{}
|
||||
err = json.Unmarshal([]byte(req.Arguments), args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cap := &vagrant.ProviderCapability{
|
||||
Name: req.Capability.Name,
|
||||
Provider: req.Capability.Provider}
|
||||
r, err := s.Impl.ProviderCapability(cap, args, m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
result, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp.Result = string(result)
|
||||
return
|
||||
}
|
||||
|
||||
type GRPCProviderCapabilitiesClient struct {
|
||||
client vagrant_caps.ProviderCapabilitiesClient
|
||||
}
|
||||
|
||||
func (c *GRPCProviderCapabilitiesClient) ProviderCapabilities() (caps []vagrant.ProviderCapability, err error) {
|
||||
resp, err := c.client.ProviderCapabilities(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
return
|
||||
}
|
||||
caps = make([]vagrant.ProviderCapability, len(resp.Capabilities))
|
||||
for i := 0; i < len(resp.Capabilities); i++ {
|
||||
cap := vagrant.ProviderCapability{
|
||||
Name: resp.Capabilities[i].Name,
|
||||
Provider: resp.Capabilities[i].Provider}
|
||||
caps[i] = cap
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderCapabilitiesClient) ProviderCapability(cap *vagrant.ProviderCapability, args interface{}, machine *vagrant.Machine) (result interface{}, err error) {
|
||||
a, err := json.Marshal(args)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m, err := vagrant.DumpMachine(machine)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.ProviderCapability(context.Background(), &vagrant_caps.ProviderCapabilityRequest{
|
||||
Capability: &vagrant_caps.ProviderCapability{
|
||||
Name: cap.Name,
|
||||
Provider: cap.Provider},
|
||||
Machine: m,
|
||||
Arguments: string(a)})
|
||||
err = json.Unmarshal([]byte(resp.Result), &result)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
go_plugin "github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_config"
|
||||
)
|
||||
|
||||
type Config interface {
|
||||
vagrant.Config
|
||||
Meta
|
||||
}
|
||||
|
||||
type ConfigPlugin struct {
|
||||
go_plugin.NetRPCUnsupportedPlugin
|
||||
Impl Config
|
||||
}
|
||||
|
||||
type GRPCConfigServer struct {
|
||||
GRPCIOServer
|
||||
Impl Config
|
||||
}
|
||||
|
||||
func (s *GRPCConfigServer) ConfigAttributes(ctx context.Context, req *vagrant_common.NullRequest) (resp *vagrant_config.AttributesResponse, err error) {
|
||||
resp = &vagrant_config.AttributesResponse{}
|
||||
r, e := s.Impl.ConfigAttributes()
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
resp.Attributes = r
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCConfigServer) ConfigLoad(ctx context.Context, req *vagrant_config.LoadRequest) (resp *vagrant_config.LoadResponse, err error) {
|
||||
resp = &vagrant_config.LoadResponse{}
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal([]byte(req.Data), &data)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
r, err := s.Impl.ConfigLoad(data)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
mdata, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
resp.Data = string(mdata)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCConfigServer) ConfigValidate(ctx context.Context, req *vagrant_config.ValidateRequest) (resp *vagrant_config.ValidateResponse, err error) {
|
||||
resp = &vagrant_config.ValidateResponse{}
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal([]byte(req.Data), &data)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
m, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
r, err := s.Impl.ConfigValidate(data, m)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
resp.Errors = r
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCConfigServer) ConfigFinalize(ctx context.Context, req *vagrant_config.FinalizeRequest) (resp *vagrant_config.FinalizeResponse, err error) {
|
||||
resp = &vagrant_config.FinalizeResponse{}
|
||||
var data map[string]interface{}
|
||||
err = json.Unmarshal([]byte(req.Data), &data)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
r, err := s.Impl.ConfigFinalize(data)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
mdata, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
resp.Error = err.Error()
|
||||
return
|
||||
}
|
||||
resp.Data = string(mdata)
|
||||
return
|
||||
}
|
||||
|
||||
type GRPCConfigClient struct {
|
||||
client vagrant_config.ConfigClient
|
||||
}
|
||||
|
||||
func (c *GRPCConfigClient) ConfigAttributes() (attrs []string, err error) {
|
||||
resp, err := c.client.ConfigAttributes(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
attrs = resp.Attributes
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCConfigClient) ConfigLoad(data map[string]interface{}) (loaddata map[string]interface{}, err error) {
|
||||
mdata, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.ConfigLoad(context.Background(), &vagrant_config.LoadRequest{
|
||||
Data: string(mdata)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal([]byte(resp.Data), &loaddata)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCConfigClient) ConfigValidate(data map[string]interface{}, m *vagrant.Machine) (errs []string, err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
mdata, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.ConfigValidate(context.Background(), &vagrant_config.ValidateRequest{
|
||||
Data: string(mdata),
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
return
|
||||
}
|
||||
errs = resp.Errors
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCConfigClient) ConfigFinalize(data map[string]interface{}) (finaldata map[string]interface{}, err error) {
|
||||
mdata, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.ConfigFinalize(context.Background(), &vagrant_config.FinalizeRequest{
|
||||
Data: string(mdata)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal([]byte(resp.Data), &finaldata)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
go_plugin "github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io"
|
||||
)
|
||||
|
||||
type IOPlugin struct {
|
||||
go_plugin.NetRPCUnsupportedPlugin
|
||||
Impl vagrant.StreamIO
|
||||
}
|
||||
|
||||
type GRPCIOServer struct {
|
||||
Impl vagrant.StreamIO
|
||||
}
|
||||
|
||||
func (s *GRPCIOServer) Read(ctx context.Context, req *vagrant_io.ReadRequest) (*vagrant_io.ReadResponse, error) {
|
||||
r, e := s.Impl.Read(req.Target)
|
||||
result := &vagrant_io.ReadResponse{Content: r}
|
||||
if e != nil {
|
||||
result.Error = e.Error()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *GRPCIOServer) Write(ctx context.Context, req *vagrant_io.WriteRequest) (*vagrant_io.WriteResponse, error) {
|
||||
n, e := s.Impl.Write(req.Content, req.Target)
|
||||
result := &vagrant_io.WriteResponse{Length: int32(n)}
|
||||
if e != nil {
|
||||
result.Error = e.Error()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type GRPCIOClient struct {
|
||||
client vagrant_io.IOClient
|
||||
}
|
||||
|
||||
func (c *GRPCIOClient) Read(target string) (content string, err error) {
|
||||
resp, err := c.client.Read(context.Background(), &vagrant_io.ReadRequest{
|
||||
Target: target})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
content = resp.Content
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCIOClient) Write(content, target string) (length int, err error) {
|
||||
resp, err := c.client.Write(context.Background(), &vagrant_io.WriteRequest{
|
||||
Content: content,
|
||||
Target: target})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
length = int(resp.Length)
|
||||
return
|
||||
}
|
||||
|
||||
func (i *IOPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||
vagrant_io.RegisterIOServer(s, &GRPCIOServer{Impl: i.Impl})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *IOPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||
return &GRPCIOClient{client: vagrant_io.NewIOClient(c)}, nil
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
)
|
||||
|
||||
type Meta interface {
|
||||
Init()
|
||||
vagrant.IOServer
|
||||
}
|
||||
|
||||
type GRPCCoreClient struct{}
|
||||
|
||||
func (c *GRPCCoreClient) Init() {}
|
||||
func (c *GRPCCoreClient) Streams() (s map[string]chan (string)) { return }
|
||||
|
||||
type Core struct {
|
||||
vagrant.IOServer
|
||||
io vagrant.StreamIO
|
||||
}
|
||||
|
||||
func (c *Core) Init() {
|
||||
if c.io == nil {
|
||||
c.io = &vagrant.IOSrv{
|
||||
map[string]chan (string){
|
||||
"stdout": make(chan string),
|
||||
"stderr": make(chan string),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Core) Read(target string) (string, error) {
|
||||
return c.io.Read(target)
|
||||
}
|
||||
|
||||
func (c *Core) Write(content, target string) (int, error) {
|
||||
return c.io.Write(content, target)
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
echo -n "Parsing proto files and generating go output... "
|
||||
|
||||
for i in *
|
||||
do
|
||||
if [ -d "${i}" ]; then
|
||||
protoc --proto_path=/home/spox/.go/src --proto_path=. --go_out=plugins=grpc:. "${i}"/*.proto;
|
||||
fi
|
||||
done
|
||||
|
||||
echo "done!"
|
|
@ -0,0 +1,859 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: vagrant_caps/capabilities.proto
|
||||
|
||||
package vagrant_caps
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import vagrant_common "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Capability struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Platform string `protobuf:"bytes,2,opt,name=platform,proto3" json:"platform,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Capability) Reset() { *m = Capability{} }
|
||||
func (m *Capability) String() string { return proto.CompactTextString(m) }
|
||||
func (*Capability) ProtoMessage() {}
|
||||
func (*Capability) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{0}
|
||||
}
|
||||
func (m *Capability) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Capability.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Capability) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Capability.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Capability) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Capability.Merge(m, src)
|
||||
}
|
||||
func (m *Capability) XXX_Size() int {
|
||||
return xxx_messageInfo_Capability.Size(m)
|
||||
}
|
||||
func (m *Capability) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Capability.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Capability proto.InternalMessageInfo
|
||||
|
||||
func (m *Capability) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Capability) GetPlatform() string {
|
||||
if m != nil {
|
||||
return m.Platform
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ProviderCapability struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Provider string `protobuf:"bytes,2,opt,name=provider,proto3" json:"provider,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ProviderCapability) Reset() { *m = ProviderCapability{} }
|
||||
func (m *ProviderCapability) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProviderCapability) ProtoMessage() {}
|
||||
func (*ProviderCapability) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{1}
|
||||
}
|
||||
func (m *ProviderCapability) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ProviderCapability.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ProviderCapability) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ProviderCapability.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ProviderCapability) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ProviderCapability.Merge(m, src)
|
||||
}
|
||||
func (m *ProviderCapability) XXX_Size() int {
|
||||
return xxx_messageInfo_ProviderCapability.Size(m)
|
||||
}
|
||||
func (m *ProviderCapability) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ProviderCapability.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ProviderCapability proto.InternalMessageInfo
|
||||
|
||||
func (m *ProviderCapability) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ProviderCapability) GetProvider() string {
|
||||
if m != nil {
|
||||
return m.Provider
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ProviderCapabilitiesResponse struct {
|
||||
Capabilities []*ProviderCapability `protobuf:"bytes,1,rep,name=capabilities,proto3" json:"capabilities,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ProviderCapabilitiesResponse) Reset() { *m = ProviderCapabilitiesResponse{} }
|
||||
func (m *ProviderCapabilitiesResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProviderCapabilitiesResponse) ProtoMessage() {}
|
||||
func (*ProviderCapabilitiesResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{2}
|
||||
}
|
||||
func (m *ProviderCapabilitiesResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ProviderCapabilitiesResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ProviderCapabilitiesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ProviderCapabilitiesResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ProviderCapabilitiesResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ProviderCapabilitiesResponse.Merge(m, src)
|
||||
}
|
||||
func (m *ProviderCapabilitiesResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_ProviderCapabilitiesResponse.Size(m)
|
||||
}
|
||||
func (m *ProviderCapabilitiesResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ProviderCapabilitiesResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ProviderCapabilitiesResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *ProviderCapabilitiesResponse) GetCapabilities() []*ProviderCapability {
|
||||
if m != nil {
|
||||
return m.Capabilities
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ProviderCapabilitiesResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ProviderCapabilityRequest struct {
|
||||
Capability *ProviderCapability `protobuf:"bytes,1,opt,name=capability,proto3" json:"capability,omitempty"`
|
||||
Machine string `protobuf:"bytes,2,opt,name=machine,proto3" json:"machine,omitempty"`
|
||||
Arguments string `protobuf:"bytes,3,opt,name=arguments,proto3" json:"arguments,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ProviderCapabilityRequest) Reset() { *m = ProviderCapabilityRequest{} }
|
||||
func (m *ProviderCapabilityRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProviderCapabilityRequest) ProtoMessage() {}
|
||||
func (*ProviderCapabilityRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{3}
|
||||
}
|
||||
func (m *ProviderCapabilityRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ProviderCapabilityRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ProviderCapabilityRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ProviderCapabilityRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ProviderCapabilityRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ProviderCapabilityRequest.Merge(m, src)
|
||||
}
|
||||
func (m *ProviderCapabilityRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_ProviderCapabilityRequest.Size(m)
|
||||
}
|
||||
func (m *ProviderCapabilityRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ProviderCapabilityRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ProviderCapabilityRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *ProviderCapabilityRequest) GetCapability() *ProviderCapability {
|
||||
if m != nil {
|
||||
return m.Capability
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ProviderCapabilityRequest) GetMachine() string {
|
||||
if m != nil {
|
||||
return m.Machine
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ProviderCapabilityRequest) GetArguments() string {
|
||||
if m != nil {
|
||||
return m.Arguments
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ProviderCapabilityResponse struct {
|
||||
Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ProviderCapabilityResponse) Reset() { *m = ProviderCapabilityResponse{} }
|
||||
func (m *ProviderCapabilityResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ProviderCapabilityResponse) ProtoMessage() {}
|
||||
func (*ProviderCapabilityResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{4}
|
||||
}
|
||||
func (m *ProviderCapabilityResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ProviderCapabilityResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ProviderCapabilityResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ProviderCapabilityResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ProviderCapabilityResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ProviderCapabilityResponse.Merge(m, src)
|
||||
}
|
||||
func (m *ProviderCapabilityResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_ProviderCapabilityResponse.Size(m)
|
||||
}
|
||||
func (m *ProviderCapabilityResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ProviderCapabilityResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ProviderCapabilityResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *ProviderCapabilityResponse) GetResult() string {
|
||||
if m != nil {
|
||||
return m.Result
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ProviderCapabilityResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CapabilitiesResponse struct {
|
||||
Capabilities []*Capability `protobuf:"bytes,1,rep,name=capabilities,proto3" json:"capabilities,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CapabilitiesResponse) Reset() { *m = CapabilitiesResponse{} }
|
||||
func (m *CapabilitiesResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*CapabilitiesResponse) ProtoMessage() {}
|
||||
func (*CapabilitiesResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{5}
|
||||
}
|
||||
func (m *CapabilitiesResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CapabilitiesResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *CapabilitiesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_CapabilitiesResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *CapabilitiesResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CapabilitiesResponse.Merge(m, src)
|
||||
}
|
||||
func (m *CapabilitiesResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_CapabilitiesResponse.Size(m)
|
||||
}
|
||||
func (m *CapabilitiesResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CapabilitiesResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CapabilitiesResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *CapabilitiesResponse) GetCapabilities() []*Capability {
|
||||
if m != nil {
|
||||
return m.Capabilities
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *CapabilitiesResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GuestCapabilityRequest struct {
|
||||
Capability *Capability `protobuf:"bytes,1,opt,name=capability,proto3" json:"capability,omitempty"`
|
||||
Machine string `protobuf:"bytes,2,opt,name=machine,proto3" json:"machine,omitempty"`
|
||||
Arguments string `protobuf:"bytes,3,opt,name=arguments,proto3" json:"arguments,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GuestCapabilityRequest) Reset() { *m = GuestCapabilityRequest{} }
|
||||
func (m *GuestCapabilityRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GuestCapabilityRequest) ProtoMessage() {}
|
||||
func (*GuestCapabilityRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{6}
|
||||
}
|
||||
func (m *GuestCapabilityRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GuestCapabilityRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GuestCapabilityRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GuestCapabilityRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GuestCapabilityRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GuestCapabilityRequest.Merge(m, src)
|
||||
}
|
||||
func (m *GuestCapabilityRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_GuestCapabilityRequest.Size(m)
|
||||
}
|
||||
func (m *GuestCapabilityRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GuestCapabilityRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GuestCapabilityRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *GuestCapabilityRequest) GetCapability() *Capability {
|
||||
if m != nil {
|
||||
return m.Capability
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *GuestCapabilityRequest) GetMachine() string {
|
||||
if m != nil {
|
||||
return m.Machine
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GuestCapabilityRequest) GetArguments() string {
|
||||
if m != nil {
|
||||
return m.Arguments
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GuestCapabilityResponse struct {
|
||||
Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *GuestCapabilityResponse) Reset() { *m = GuestCapabilityResponse{} }
|
||||
func (m *GuestCapabilityResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GuestCapabilityResponse) ProtoMessage() {}
|
||||
func (*GuestCapabilityResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{7}
|
||||
}
|
||||
func (m *GuestCapabilityResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_GuestCapabilityResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *GuestCapabilityResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_GuestCapabilityResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *GuestCapabilityResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GuestCapabilityResponse.Merge(m, src)
|
||||
}
|
||||
func (m *GuestCapabilityResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_GuestCapabilityResponse.Size(m)
|
||||
}
|
||||
func (m *GuestCapabilityResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GuestCapabilityResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GuestCapabilityResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *GuestCapabilityResponse) GetResult() string {
|
||||
if m != nil {
|
||||
return m.Result
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *GuestCapabilityResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type HostCapabilityRequest struct {
|
||||
Capability *Capability `protobuf:"bytes,1,opt,name=capability,proto3" json:"capability,omitempty"`
|
||||
Environment string `protobuf:"bytes,2,opt,name=environment,proto3" json:"environment,omitempty"`
|
||||
Arguments string `protobuf:"bytes,3,opt,name=arguments,proto3" json:"arguments,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *HostCapabilityRequest) Reset() { *m = HostCapabilityRequest{} }
|
||||
func (m *HostCapabilityRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*HostCapabilityRequest) ProtoMessage() {}
|
||||
func (*HostCapabilityRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{8}
|
||||
}
|
||||
func (m *HostCapabilityRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_HostCapabilityRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *HostCapabilityRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_HostCapabilityRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *HostCapabilityRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_HostCapabilityRequest.Merge(m, src)
|
||||
}
|
||||
func (m *HostCapabilityRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_HostCapabilityRequest.Size(m)
|
||||
}
|
||||
func (m *HostCapabilityRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_HostCapabilityRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_HostCapabilityRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *HostCapabilityRequest) GetCapability() *Capability {
|
||||
if m != nil {
|
||||
return m.Capability
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *HostCapabilityRequest) GetEnvironment() string {
|
||||
if m != nil {
|
||||
return m.Environment
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *HostCapabilityRequest) GetArguments() string {
|
||||
if m != nil {
|
||||
return m.Arguments
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type HostCapabilityResponse struct {
|
||||
Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *HostCapabilityResponse) Reset() { *m = HostCapabilityResponse{} }
|
||||
func (m *HostCapabilityResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*HostCapabilityResponse) ProtoMessage() {}
|
||||
func (*HostCapabilityResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_591a3013bd09a9cb, []int{9}
|
||||
}
|
||||
func (m *HostCapabilityResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_HostCapabilityResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *HostCapabilityResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_HostCapabilityResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *HostCapabilityResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_HostCapabilityResponse.Merge(m, src)
|
||||
}
|
||||
func (m *HostCapabilityResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_HostCapabilityResponse.Size(m)
|
||||
}
|
||||
func (m *HostCapabilityResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_HostCapabilityResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_HostCapabilityResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *HostCapabilityResponse) GetResult() string {
|
||||
if m != nil {
|
||||
return m.Result
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *HostCapabilityResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Capability)(nil), "vagrant.caps.Capability")
|
||||
proto.RegisterType((*ProviderCapability)(nil), "vagrant.caps.ProviderCapability")
|
||||
proto.RegisterType((*ProviderCapabilitiesResponse)(nil), "vagrant.caps.ProviderCapabilitiesResponse")
|
||||
proto.RegisterType((*ProviderCapabilityRequest)(nil), "vagrant.caps.ProviderCapabilityRequest")
|
||||
proto.RegisterType((*ProviderCapabilityResponse)(nil), "vagrant.caps.ProviderCapabilityResponse")
|
||||
proto.RegisterType((*CapabilitiesResponse)(nil), "vagrant.caps.CapabilitiesResponse")
|
||||
proto.RegisterType((*GuestCapabilityRequest)(nil), "vagrant.caps.GuestCapabilityRequest")
|
||||
proto.RegisterType((*GuestCapabilityResponse)(nil), "vagrant.caps.GuestCapabilityResponse")
|
||||
proto.RegisterType((*HostCapabilityRequest)(nil), "vagrant.caps.HostCapabilityRequest")
|
||||
proto.RegisterType((*HostCapabilityResponse)(nil), "vagrant.caps.HostCapabilityResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// GuestCapabilitiesClient is the client API for GuestCapabilities service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type GuestCapabilitiesClient interface {
|
||||
GuestCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error)
|
||||
GuestCapability(ctx context.Context, in *GuestCapabilityRequest, opts ...grpc.CallOption) (*GuestCapabilityResponse, error)
|
||||
}
|
||||
|
||||
type guestCapabilitiesClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewGuestCapabilitiesClient(cc *grpc.ClientConn) GuestCapabilitiesClient {
|
||||
return &guestCapabilitiesClient{cc}
|
||||
}
|
||||
|
||||
func (c *guestCapabilitiesClient) GuestCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error) {
|
||||
out := new(CapabilitiesResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.caps.GuestCapabilities/GuestCapabilities", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *guestCapabilitiesClient) GuestCapability(ctx context.Context, in *GuestCapabilityRequest, opts ...grpc.CallOption) (*GuestCapabilityResponse, error) {
|
||||
out := new(GuestCapabilityResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.caps.GuestCapabilities/GuestCapability", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// GuestCapabilitiesServer is the server API for GuestCapabilities service.
|
||||
type GuestCapabilitiesServer interface {
|
||||
GuestCapabilities(context.Context, *vagrant_common.NullRequest) (*CapabilitiesResponse, error)
|
||||
GuestCapability(context.Context, *GuestCapabilityRequest) (*GuestCapabilityResponse, error)
|
||||
}
|
||||
|
||||
func RegisterGuestCapabilitiesServer(s *grpc.Server, srv GuestCapabilitiesServer) {
|
||||
s.RegisterService(&_GuestCapabilities_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _GuestCapabilities_GuestCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(GuestCapabilitiesServer).GuestCapabilities(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.caps.GuestCapabilities/GuestCapabilities",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(GuestCapabilitiesServer).GuestCapabilities(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _GuestCapabilities_GuestCapability_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GuestCapabilityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(GuestCapabilitiesServer).GuestCapability(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.caps.GuestCapabilities/GuestCapability",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(GuestCapabilitiesServer).GuestCapability(ctx, req.(*GuestCapabilityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _GuestCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "vagrant.caps.GuestCapabilities",
|
||||
HandlerType: (*GuestCapabilitiesServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GuestCapabilities",
|
||||
Handler: _GuestCapabilities_GuestCapabilities_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GuestCapability",
|
||||
Handler: _GuestCapabilities_GuestCapability_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "vagrant_caps/capabilities.proto",
|
||||
}
|
||||
|
||||
// HostCapabilitiesClient is the client API for HostCapabilities service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type HostCapabilitiesClient interface {
|
||||
HostCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error)
|
||||
HostCapability(ctx context.Context, in *HostCapabilityRequest, opts ...grpc.CallOption) (*HostCapabilityResponse, error)
|
||||
}
|
||||
|
||||
type hostCapabilitiesClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewHostCapabilitiesClient(cc *grpc.ClientConn) HostCapabilitiesClient {
|
||||
return &hostCapabilitiesClient{cc}
|
||||
}
|
||||
|
||||
func (c *hostCapabilitiesClient) HostCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error) {
|
||||
out := new(CapabilitiesResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.caps.HostCapabilities/HostCapabilities", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *hostCapabilitiesClient) HostCapability(ctx context.Context, in *HostCapabilityRequest, opts ...grpc.CallOption) (*HostCapabilityResponse, error) {
|
||||
out := new(HostCapabilityResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.caps.HostCapabilities/HostCapability", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// HostCapabilitiesServer is the server API for HostCapabilities service.
|
||||
type HostCapabilitiesServer interface {
|
||||
HostCapabilities(context.Context, *vagrant_common.NullRequest) (*CapabilitiesResponse, error)
|
||||
HostCapability(context.Context, *HostCapabilityRequest) (*HostCapabilityResponse, error)
|
||||
}
|
||||
|
||||
func RegisterHostCapabilitiesServer(s *grpc.Server, srv HostCapabilitiesServer) {
|
||||
s.RegisterService(&_HostCapabilities_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _HostCapabilities_HostCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HostCapabilitiesServer).HostCapabilities(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.caps.HostCapabilities/HostCapabilities",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HostCapabilitiesServer).HostCapabilities(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _HostCapabilities_HostCapability_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(HostCapabilityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(HostCapabilitiesServer).HostCapability(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.caps.HostCapabilities/HostCapability",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(HostCapabilitiesServer).HostCapability(ctx, req.(*HostCapabilityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _HostCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "vagrant.caps.HostCapabilities",
|
||||
HandlerType: (*HostCapabilitiesServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "HostCapabilities",
|
||||
Handler: _HostCapabilities_HostCapabilities_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "HostCapability",
|
||||
Handler: _HostCapabilities_HostCapability_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "vagrant_caps/capabilities.proto",
|
||||
}
|
||||
|
||||
// ProviderCapabilitiesClient is the client API for ProviderCapabilities service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type ProviderCapabilitiesClient interface {
|
||||
ProviderCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*ProviderCapabilitiesResponse, error)
|
||||
ProviderCapability(ctx context.Context, in *ProviderCapabilityRequest, opts ...grpc.CallOption) (*ProviderCapabilityResponse, error)
|
||||
}
|
||||
|
||||
type providerCapabilitiesClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewProviderCapabilitiesClient(cc *grpc.ClientConn) ProviderCapabilitiesClient {
|
||||
return &providerCapabilitiesClient{cc}
|
||||
}
|
||||
|
||||
func (c *providerCapabilitiesClient) ProviderCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*ProviderCapabilitiesResponse, error) {
|
||||
out := new(ProviderCapabilitiesResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.caps.ProviderCapabilities/ProviderCapabilities", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *providerCapabilitiesClient) ProviderCapability(ctx context.Context, in *ProviderCapabilityRequest, opts ...grpc.CallOption) (*ProviderCapabilityResponse, error) {
|
||||
out := new(ProviderCapabilityResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.caps.ProviderCapabilities/ProviderCapability", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ProviderCapabilitiesServer is the server API for ProviderCapabilities service.
|
||||
type ProviderCapabilitiesServer interface {
|
||||
ProviderCapabilities(context.Context, *vagrant_common.NullRequest) (*ProviderCapabilitiesResponse, error)
|
||||
ProviderCapability(context.Context, *ProviderCapabilityRequest) (*ProviderCapabilityResponse, error)
|
||||
}
|
||||
|
||||
func RegisterProviderCapabilitiesServer(s *grpc.Server, srv ProviderCapabilitiesServer) {
|
||||
s.RegisterService(&_ProviderCapabilities_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _ProviderCapabilities_ProviderCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProviderCapabilitiesServer).ProviderCapabilities(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.caps.ProviderCapabilities/ProviderCapabilities",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProviderCapabilitiesServer).ProviderCapabilities(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ProviderCapabilities_ProviderCapability_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ProviderCapabilityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ProviderCapabilitiesServer).ProviderCapability(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.caps.ProviderCapabilities/ProviderCapability",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ProviderCapabilitiesServer).ProviderCapability(ctx, req.(*ProviderCapabilityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _ProviderCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "vagrant.caps.ProviderCapabilities",
|
||||
HandlerType: (*ProviderCapabilitiesServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "ProviderCapabilities",
|
||||
Handler: _ProviderCapabilities_ProviderCapabilities_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ProviderCapability",
|
||||
Handler: _ProviderCapabilities_ProviderCapability_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "vagrant_caps/capabilities.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("vagrant_caps/capabilities.proto", fileDescriptor_591a3013bd09a9cb) }
|
||||
|
||||
var fileDescriptor_591a3013bd09a9cb = []byte{
|
||||
// 510 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xcf, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0xc6, 0xb5, 0x14, 0x0a, 0x9d, 0x56, 0xfc, 0x59, 0x85, 0x60, 0x4c, 0x25, 0x22, 0x53, 0x44,
|
||||
0x84, 0x84, 0x2d, 0x85, 0x0b, 0x87, 0x1e, 0x90, 0xa8, 0x28, 0xe2, 0x80, 0x50, 0xe0, 0x56, 0x89,
|
||||
0x6a, 0x63, 0x16, 0x7b, 0x91, 0xbd, 0x6b, 0x76, 0xd7, 0x11, 0xe5, 0x11, 0xb8, 0x71, 0xe0, 0x8d,
|
||||
0xb8, 0xf0, 0x16, 0x3c, 0x0a, 0xb2, 0xbd, 0x71, 0xed, 0x7a, 0x5d, 0x97, 0xd2, 0x53, 0x32, 0x93,
|
||||
0x99, 0xf9, 0xe6, 0xfb, 0xd9, 0x9a, 0xc0, 0xfd, 0x25, 0x89, 0x24, 0xe1, 0xfa, 0x30, 0x24, 0x99,
|
||||
0x0a, 0x42, 0x92, 0x91, 0x05, 0x4b, 0x98, 0x66, 0x54, 0xf9, 0x99, 0x14, 0x5a, 0xe0, 0x2d, 0x53,
|
||||
0xe0, 0x17, 0x05, 0xee, 0x41, 0xc4, 0x74, 0x9c, 0x2f, 0xfc, 0x50, 0xa4, 0x41, 0x4c, 0x54, 0xcc,
|
||||
0x42, 0x21, 0xb3, 0xc0, 0x94, 0x04, 0xf4, 0xab, 0x0e, 0x22, 0xf1, 0x24, 0x4b, 0xf2, 0x88, 0xf1,
|
||||
0x3a, 0x6b, 0xc2, 0x72, 0x5c, 0x50, 0xcb, 0x89, 0x34, 0x15, 0x3c, 0xa8, 0x3e, 0x2a, 0x29, 0x6f,
|
||||
0x17, 0xe0, 0xc5, 0x6a, 0x81, 0x23, 0x8c, 0xe1, 0x32, 0x27, 0x29, 0x75, 0xd0, 0x04, 0x4d, 0x37,
|
||||
0xe6, 0xe5, 0x77, 0xec, 0xc2, 0xb5, 0x2c, 0x21, 0xfa, 0x93, 0x90, 0xa9, 0x73, 0xa9, 0xcc, 0xd7,
|
||||
0xb1, 0xb7, 0x07, 0xf8, 0xad, 0x14, 0x4b, 0xf6, 0x91, 0xca, 0x33, 0x4c, 0x31, 0x95, 0xf5, 0x14,
|
||||
0x13, 0x7b, 0xdf, 0x60, 0xbb, 0x33, 0x85, 0x51, 0x35, 0xa7, 0x2a, 0x13, 0x5c, 0x51, 0xbc, 0x07,
|
||||
0x5b, 0x4d, 0x48, 0x0e, 0x9a, 0xac, 0x4d, 0x37, 0x67, 0x13, 0xbf, 0x49, 0xc9, 0xef, 0xee, 0x31,
|
||||
0x6f, 0x75, 0xe1, 0x11, 0x5c, 0xa1, 0x52, 0x8a, 0x95, 0x7c, 0x15, 0x78, 0x3f, 0x11, 0xdc, 0xb5,
|
||||
0xb4, 0xd2, 0x2f, 0x39, 0x55, 0x1a, 0x3f, 0x07, 0xa8, 0x67, 0x1c, 0x95, 0x7e, 0xce, 0xa2, 0xdb,
|
||||
0xe8, 0xc1, 0x0e, 0x5c, 0x4d, 0x49, 0x18, 0x33, 0x4e, 0x8d, 0xee, 0x2a, 0xc4, 0xdb, 0xb0, 0x41,
|
||||
0x64, 0x94, 0xa7, 0x94, 0x6b, 0xe5, 0xac, 0x95, 0xbf, 0x1d, 0x27, 0xbc, 0xd7, 0xe0, 0xda, 0xd6,
|
||||
0x32, 0x44, 0xc6, 0xb0, 0x2e, 0xa9, 0xca, 0x13, 0x6d, 0x18, 0x9b, 0xa8, 0xc7, 0xe3, 0x67, 0x18,
|
||||
0x59, 0xb9, 0xee, 0x5a, 0xb9, 0x3a, 0x6d, 0x7f, 0xff, 0xc8, 0xf3, 0x3b, 0x82, 0xf1, 0x7e, 0xc1,
|
||||
0xae, 0x0b, 0xf3, 0x99, 0x05, 0x66, 0xbf, 0xd8, 0x45, 0x40, 0xdc, 0x87, 0x3b, 0x9d, 0x5d, 0xce,
|
||||
0x45, 0xf0, 0x07, 0x82, 0xdb, 0xaf, 0xc4, 0xc5, 0x9a, 0x9a, 0xc0, 0x26, 0xe5, 0x4b, 0x26, 0x05,
|
||||
0x2f, 0x96, 0x35, 0x7a, 0xcd, 0xd4, 0x80, 0xb9, 0x97, 0x30, 0x3e, 0xb9, 0xd2, 0x79, 0xbc, 0xcd,
|
||||
0x7e, 0x23, 0xb8, 0xd5, 0xa6, 0x54, 0x3c, 0xdd, 0xf7, 0xb6, 0xe4, 0xbd, 0x63, 0x63, 0xd5, 0x0d,
|
||||
0x79, 0x93, 0x27, 0x89, 0x21, 0xe1, 0x7a, 0x3d, 0xae, 0x9b, 0x6f, 0xdc, 0x07, 0xb8, 0x71, 0xe2,
|
||||
0x81, 0xe0, 0x9d, 0x76, 0x9b, 0xfd, 0xdd, 0x71, 0x1f, 0x0e, 0x54, 0x55, 0xf3, 0x67, 0xbf, 0x10,
|
||||
0xdc, 0x6c, 0x41, 0x29, 0xb6, 0x7e, 0x67, 0xc9, 0xfd, 0xb7, 0x93, 0x03, 0xb8, 0xde, 0xa6, 0x8f,
|
||||
0x1f, 0xb4, 0xbb, 0xac, 0xaf, 0x8b, 0xbb, 0x73, 0x7a, 0x91, 0xb1, 0xf1, 0x07, 0xc1, 0xc8, 0x76,
|
||||
0x11, 0xf1, 0x61, 0x4f, 0xfe, 0x54, 0x3b, 0x8f, 0x07, 0x0e, 0x56, 0xd3, 0x56, 0x64, 0x3d, 0xe8,
|
||||
0x8f, 0x06, 0x4f, 0x9e, 0x91, 0x9a, 0x0e, 0x17, 0x56, 0x42, 0x8b, 0xf5, 0xf2, 0xef, 0xe7, 0xe9,
|
||||
0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0xfc, 0x96, 0xa9, 0x0c, 0x07, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
syntax = "proto3";
|
||||
package vagrant.caps;
|
||||
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common/common.proto";
|
||||
|
||||
message Capability {
|
||||
string name = 1;
|
||||
string platform = 2;
|
||||
}
|
||||
|
||||
message ProviderCapability {
|
||||
string name = 1;
|
||||
string provider = 2;
|
||||
}
|
||||
|
||||
message ProviderCapabilitiesResponse {
|
||||
repeated ProviderCapability capabilities = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message ProviderCapabilityRequest {
|
||||
ProviderCapability capability = 1;
|
||||
string machine = 2;
|
||||
string arguments = 3;
|
||||
}
|
||||
|
||||
message ProviderCapabilityResponse {
|
||||
string result = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message CapabilitiesResponse {
|
||||
repeated Capability capabilities = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message GuestCapabilityRequest {
|
||||
Capability capability = 1;
|
||||
string machine = 2;
|
||||
string arguments = 3;
|
||||
}
|
||||
|
||||
message GuestCapabilityResponse {
|
||||
string result = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message HostCapabilityRequest {
|
||||
Capability capability = 1;
|
||||
string environment = 2;
|
||||
string arguments = 3;
|
||||
}
|
||||
|
||||
message HostCapabilityResponse {
|
||||
string result = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
service GuestCapabilities {
|
||||
rpc GuestCapabilities(vagrant.common.NullRequest) returns (CapabilitiesResponse);
|
||||
rpc GuestCapability(GuestCapabilityRequest) returns (GuestCapabilityResponse);
|
||||
}
|
||||
|
||||
service HostCapabilities {
|
||||
rpc HostCapabilities(vagrant.common.NullRequest) returns (CapabilitiesResponse);
|
||||
rpc HostCapability(HostCapabilityRequest) returns (HostCapabilityResponse);
|
||||
}
|
||||
|
||||
service ProviderCapabilities {
|
||||
rpc ProviderCapabilities(vagrant.common.NullRequest) returns (ProviderCapabilitiesResponse);
|
||||
rpc ProviderCapability(ProviderCapabilityRequest) returns (ProviderCapabilityResponse);
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: vagrant_common/common.proto
|
||||
|
||||
package vagrant_common
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type NullRequest struct {
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *NullRequest) Reset() { *m = NullRequest{} }
|
||||
func (m *NullRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*NullRequest) ProtoMessage() {}
|
||||
func (*NullRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_86eb89499a7c6603, []int{0}
|
||||
}
|
||||
func (m *NullRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NullRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *NullRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_NullRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *NullRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_NullRequest.Merge(m, src)
|
||||
}
|
||||
func (m *NullRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_NullRequest.Size(m)
|
||||
}
|
||||
func (m *NullRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_NullRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_NullRequest proto.InternalMessageInfo
|
||||
|
||||
type EmptyRequest struct {
|
||||
Machine string `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *EmptyRequest) Reset() { *m = EmptyRequest{} }
|
||||
func (m *EmptyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyRequest) ProtoMessage() {}
|
||||
func (*EmptyRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_86eb89499a7c6603, []int{1}
|
||||
}
|
||||
func (m *EmptyRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EmptyRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_EmptyRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_EmptyRequest.Merge(m, src)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_EmptyRequest.Size(m)
|
||||
}
|
||||
func (m *EmptyRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_EmptyRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_EmptyRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *EmptyRequest) GetMachine() string {
|
||||
if m != nil {
|
||||
return m.Machine
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type EmptyResponse struct {
|
||||
Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *EmptyResponse) Reset() { *m = EmptyResponse{} }
|
||||
func (m *EmptyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*EmptyResponse) ProtoMessage() {}
|
||||
func (*EmptyResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_86eb89499a7c6603, []int{2}
|
||||
}
|
||||
func (m *EmptyResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_EmptyResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_EmptyResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_EmptyResponse.Merge(m, src)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_EmptyResponse.Size(m)
|
||||
}
|
||||
func (m *EmptyResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_EmptyResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_EmptyResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *EmptyResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type IsResponse struct {
|
||||
Result bool `protobuf:"varint,1,opt,name=result,proto3" json:"result,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IsResponse) Reset() { *m = IsResponse{} }
|
||||
func (m *IsResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*IsResponse) ProtoMessage() {}
|
||||
func (*IsResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_86eb89499a7c6603, []int{3}
|
||||
}
|
||||
func (m *IsResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_IsResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *IsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_IsResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *IsResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_IsResponse.Merge(m, src)
|
||||
}
|
||||
func (m *IsResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_IsResponse.Size(m)
|
||||
}
|
||||
func (m *IsResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_IsResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_IsResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *IsResponse) GetResult() bool {
|
||||
if m != nil {
|
||||
return m.Result
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *IsResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type NameResponse struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *NameResponse) Reset() { *m = NameResponse{} }
|
||||
func (m *NameResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*NameResponse) ProtoMessage() {}
|
||||
func (*NameResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_86eb89499a7c6603, []int{4}
|
||||
}
|
||||
func (m *NameResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_NameResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *NameResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_NameResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *NameResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_NameResponse.Merge(m, src)
|
||||
}
|
||||
func (m *NameResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_NameResponse.Size(m)
|
||||
}
|
||||
func (m *NameResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_NameResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_NameResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *NameResponse) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*NullRequest)(nil), "vagrant.common.NullRequest")
|
||||
proto.RegisterType((*EmptyRequest)(nil), "vagrant.common.EmptyRequest")
|
||||
proto.RegisterType((*EmptyResponse)(nil), "vagrant.common.EmptyResponse")
|
||||
proto.RegisterType((*IsResponse)(nil), "vagrant.common.IsResponse")
|
||||
proto.RegisterType((*NameResponse)(nil), "vagrant.common.NameResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("vagrant_common/common.proto", fileDescriptor_86eb89499a7c6603) }
|
||||
|
||||
var fileDescriptor_86eb89499a7c6603 = []byte{
|
||||
// 178 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2e, 0x4b, 0x4c, 0x2f,
|
||||
0x4a, 0xcc, 0x2b, 0x89, 0x4f, 0xce, 0xcf, 0xcd, 0xcd, 0xcf, 0xd3, 0x87, 0x50, 0x7a, 0x05, 0x45,
|
||||
0xf9, 0x25, 0xf9, 0x42, 0x7c, 0x50, 0x49, 0x3d, 0x88, 0xa8, 0x12, 0x2f, 0x17, 0xb7, 0x5f, 0x69,
|
||||
0x4e, 0x4e, 0x50, 0x6a, 0x61, 0x69, 0x6a, 0x71, 0x89, 0x92, 0x06, 0x17, 0x8f, 0x6b, 0x6e, 0x41,
|
||||
0x49, 0x25, 0x94, 0x2f, 0x24, 0xc1, 0xc5, 0x9e, 0x9b, 0x98, 0x9c, 0x91, 0x99, 0x97, 0x2a, 0xc1,
|
||||
0xa8, 0xc0, 0xa8, 0xc1, 0x19, 0x04, 0xe3, 0x2a, 0xa9, 0x72, 0xf1, 0x42, 0x55, 0x16, 0x17, 0xe4,
|
||||
0xe7, 0x15, 0xa7, 0x0a, 0x89, 0x70, 0xb1, 0xa6, 0x16, 0x15, 0xe5, 0x17, 0x41, 0x15, 0x42, 0x38,
|
||||
0x4a, 0x56, 0x5c, 0x5c, 0x9e, 0xc5, 0x70, 0x35, 0x62, 0x5c, 0x6c, 0x45, 0xa9, 0xc5, 0xa5, 0x39,
|
||||
0x25, 0x60, 0x45, 0x1c, 0x41, 0x50, 0x1e, 0x42, 0x2f, 0x13, 0xb2, 0x5e, 0x25, 0x2e, 0x1e, 0xbf,
|
||||
0xc4, 0xdc, 0x54, 0xb8, 0x6e, 0x21, 0x2e, 0x96, 0xbc, 0xc4, 0x5c, 0x98, 0x4b, 0xc0, 0xec, 0x24,
|
||||
0x36, 0xb0, 0xb7, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x02, 0xed, 0x61, 0x90, 0xf5, 0x00,
|
||||
0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
syntax = "proto3";
|
||||
package vagrant.common;
|
||||
|
||||
message NullRequest {}
|
||||
|
||||
message EmptyRequest {
|
||||
string machine = 1;
|
||||
}
|
||||
|
||||
message EmptyResponse {
|
||||
string error = 1;
|
||||
}
|
||||
|
||||
message IsResponse {
|
||||
bool result = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message NameResponse { string name = 1; }
|
|
@ -0,0 +1,541 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: vagrant_config/config.proto
|
||||
|
||||
package vagrant_config
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import vagrant_common "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type AttributesResponse struct {
|
||||
Attributes []string `protobuf:"bytes,1,rep,name=attributes,proto3" json:"attributes,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *AttributesResponse) Reset() { *m = AttributesResponse{} }
|
||||
func (m *AttributesResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*AttributesResponse) ProtoMessage() {}
|
||||
func (*AttributesResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_952629f1a9a7438c, []int{0}
|
||||
}
|
||||
func (m *AttributesResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_AttributesResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *AttributesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_AttributesResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *AttributesResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_AttributesResponse.Merge(m, src)
|
||||
}
|
||||
func (m *AttributesResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_AttributesResponse.Size(m)
|
||||
}
|
||||
func (m *AttributesResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_AttributesResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_AttributesResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *AttributesResponse) GetAttributes() []string {
|
||||
if m != nil {
|
||||
return m.Attributes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AttributesResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type LoadRequest struct {
|
||||
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *LoadRequest) Reset() { *m = LoadRequest{} }
|
||||
func (m *LoadRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*LoadRequest) ProtoMessage() {}
|
||||
func (*LoadRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_952629f1a9a7438c, []int{1}
|
||||
}
|
||||
func (m *LoadRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LoadRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *LoadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_LoadRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *LoadRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_LoadRequest.Merge(m, src)
|
||||
}
|
||||
func (m *LoadRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_LoadRequest.Size(m)
|
||||
}
|
||||
func (m *LoadRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_LoadRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_LoadRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *LoadRequest) GetData() string {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type LoadResponse struct {
|
||||
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *LoadResponse) Reset() { *m = LoadResponse{} }
|
||||
func (m *LoadResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*LoadResponse) ProtoMessage() {}
|
||||
func (*LoadResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_952629f1a9a7438c, []int{2}
|
||||
}
|
||||
func (m *LoadResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_LoadResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *LoadResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_LoadResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *LoadResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_LoadResponse.Merge(m, src)
|
||||
}
|
||||
func (m *LoadResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_LoadResponse.Size(m)
|
||||
}
|
||||
func (m *LoadResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_LoadResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_LoadResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *LoadResponse) GetData() string {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *LoadResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ValidateRequest struct {
|
||||
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
Machine string `protobuf:"bytes,2,opt,name=machine,proto3" json:"machine,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ValidateRequest) Reset() { *m = ValidateRequest{} }
|
||||
func (m *ValidateRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ValidateRequest) ProtoMessage() {}
|
||||
func (*ValidateRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_952629f1a9a7438c, []int{3}
|
||||
}
|
||||
func (m *ValidateRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ValidateRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ValidateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ValidateRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ValidateRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ValidateRequest.Merge(m, src)
|
||||
}
|
||||
func (m *ValidateRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_ValidateRequest.Size(m)
|
||||
}
|
||||
func (m *ValidateRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ValidateRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ValidateRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *ValidateRequest) GetData() string {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ValidateRequest) GetMachine() string {
|
||||
if m != nil {
|
||||
return m.Machine
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ValidateResponse struct {
|
||||
Errors []string `protobuf:"bytes,1,rep,name=errors,proto3" json:"errors,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ValidateResponse) Reset() { *m = ValidateResponse{} }
|
||||
func (m *ValidateResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ValidateResponse) ProtoMessage() {}
|
||||
func (*ValidateResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_952629f1a9a7438c, []int{4}
|
||||
}
|
||||
func (m *ValidateResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ValidateResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ValidateResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ValidateResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ValidateResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ValidateResponse.Merge(m, src)
|
||||
}
|
||||
func (m *ValidateResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_ValidateResponse.Size(m)
|
||||
}
|
||||
func (m *ValidateResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ValidateResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ValidateResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *ValidateResponse) GetErrors() []string {
|
||||
if m != nil {
|
||||
return m.Errors
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *ValidateResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type FinalizeRequest struct {
|
||||
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *FinalizeRequest) Reset() { *m = FinalizeRequest{} }
|
||||
func (m *FinalizeRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*FinalizeRequest) ProtoMessage() {}
|
||||
func (*FinalizeRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_952629f1a9a7438c, []int{5}
|
||||
}
|
||||
func (m *FinalizeRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FinalizeRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *FinalizeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_FinalizeRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *FinalizeRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_FinalizeRequest.Merge(m, src)
|
||||
}
|
||||
func (m *FinalizeRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_FinalizeRequest.Size(m)
|
||||
}
|
||||
func (m *FinalizeRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_FinalizeRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_FinalizeRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *FinalizeRequest) GetData() string {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type FinalizeResponse struct {
|
||||
Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *FinalizeResponse) Reset() { *m = FinalizeResponse{} }
|
||||
func (m *FinalizeResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*FinalizeResponse) ProtoMessage() {}
|
||||
func (*FinalizeResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_952629f1a9a7438c, []int{6}
|
||||
}
|
||||
func (m *FinalizeResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_FinalizeResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *FinalizeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_FinalizeResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *FinalizeResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_FinalizeResponse.Merge(m, src)
|
||||
}
|
||||
func (m *FinalizeResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_FinalizeResponse.Size(m)
|
||||
}
|
||||
func (m *FinalizeResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_FinalizeResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_FinalizeResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *FinalizeResponse) GetData() string {
|
||||
if m != nil {
|
||||
return m.Data
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *FinalizeResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*AttributesResponse)(nil), "vagrant.config.AttributesResponse")
|
||||
proto.RegisterType((*LoadRequest)(nil), "vagrant.config.LoadRequest")
|
||||
proto.RegisterType((*LoadResponse)(nil), "vagrant.config.LoadResponse")
|
||||
proto.RegisterType((*ValidateRequest)(nil), "vagrant.config.ValidateRequest")
|
||||
proto.RegisterType((*ValidateResponse)(nil), "vagrant.config.ValidateResponse")
|
||||
proto.RegisterType((*FinalizeRequest)(nil), "vagrant.config.FinalizeRequest")
|
||||
proto.RegisterType((*FinalizeResponse)(nil), "vagrant.config.FinalizeResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// ConfigClient is the client API for Config service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type ConfigClient interface {
|
||||
ConfigAttributes(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*AttributesResponse, error)
|
||||
ConfigLoad(ctx context.Context, in *LoadRequest, opts ...grpc.CallOption) (*LoadResponse, error)
|
||||
ConfigValidate(ctx context.Context, in *ValidateRequest, opts ...grpc.CallOption) (*ValidateResponse, error)
|
||||
ConfigFinalize(ctx context.Context, in *FinalizeRequest, opts ...grpc.CallOption) (*FinalizeResponse, error)
|
||||
}
|
||||
|
||||
type configClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewConfigClient(cc *grpc.ClientConn) ConfigClient {
|
||||
return &configClient{cc}
|
||||
}
|
||||
|
||||
func (c *configClient) ConfigAttributes(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*AttributesResponse, error) {
|
||||
out := new(AttributesResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.config.Config/ConfigAttributes", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) ConfigLoad(ctx context.Context, in *LoadRequest, opts ...grpc.CallOption) (*LoadResponse, error) {
|
||||
out := new(LoadResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.config.Config/ConfigLoad", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) ConfigValidate(ctx context.Context, in *ValidateRequest, opts ...grpc.CallOption) (*ValidateResponse, error) {
|
||||
out := new(ValidateResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.config.Config/ConfigValidate", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *configClient) ConfigFinalize(ctx context.Context, in *FinalizeRequest, opts ...grpc.CallOption) (*FinalizeResponse, error) {
|
||||
out := new(FinalizeResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.config.Config/ConfigFinalize", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ConfigServer is the server API for Config service.
|
||||
type ConfigServer interface {
|
||||
ConfigAttributes(context.Context, *vagrant_common.NullRequest) (*AttributesResponse, error)
|
||||
ConfigLoad(context.Context, *LoadRequest) (*LoadResponse, error)
|
||||
ConfigValidate(context.Context, *ValidateRequest) (*ValidateResponse, error)
|
||||
ConfigFinalize(context.Context, *FinalizeRequest) (*FinalizeResponse, error)
|
||||
}
|
||||
|
||||
func RegisterConfigServer(s *grpc.Server, srv ConfigServer) {
|
||||
s.RegisterService(&_Config_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Config_ConfigAttributes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).ConfigAttributes(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.config.Config/ConfigAttributes",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).ConfigAttributes(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_ConfigLoad_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(LoadRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).ConfigLoad(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.config.Config/ConfigLoad",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).ConfigLoad(ctx, req.(*LoadRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_ConfigValidate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ValidateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).ConfigValidate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.config.Config/ConfigValidate",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).ConfigValidate(ctx, req.(*ValidateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Config_ConfigFinalize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(FinalizeRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ConfigServer).ConfigFinalize(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.config.Config/ConfigFinalize",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ConfigServer).ConfigFinalize(ctx, req.(*FinalizeRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Config_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "vagrant.config.Config",
|
||||
HandlerType: (*ConfigServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "ConfigAttributes",
|
||||
Handler: _Config_ConfigAttributes_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ConfigLoad",
|
||||
Handler: _Config_ConfigLoad_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ConfigValidate",
|
||||
Handler: _Config_ConfigValidate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ConfigFinalize",
|
||||
Handler: _Config_ConfigFinalize_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "vagrant_config/config.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("vagrant_config/config.proto", fileDescriptor_952629f1a9a7438c) }
|
||||
|
||||
var fileDescriptor_952629f1a9a7438c = []byte{
|
||||
// 363 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xc1, 0x4b, 0xfb, 0x30,
|
||||
0x14, 0xc7, 0xd9, 0x7e, 0x3f, 0x27, 0x7b, 0xca, 0x36, 0x82, 0x48, 0xe9, 0x44, 0x67, 0x41, 0xd8,
|
||||
0xc5, 0x06, 0xf4, 0xe2, 0x41, 0x50, 0x11, 0x14, 0x44, 0x3c, 0x74, 0xe0, 0xc5, 0x83, 0x64, 0x5d,
|
||||
0x6c, 0x03, 0x6d, 0x52, 0xd3, 0x54, 0xc4, 0xbf, 0xd2, 0x3f, 0x49, 0x4c, 0xd2, 0x75, 0xeb, 0xd6,
|
||||
0x81, 0xa7, 0xe4, 0xbd, 0x7c, 0xf3, 0x79, 0xc9, 0xfb, 0x3e, 0x18, 0x7e, 0x90, 0x48, 0x12, 0xae,
|
||||
0x5e, 0x43, 0xc1, 0xdf, 0x58, 0x84, 0xcd, 0xe2, 0x67, 0x52, 0x28, 0x81, 0x7a, 0xf6, 0xd0, 0x37,
|
||||
0x59, 0xf7, 0x25, 0x62, 0x2a, 0x2e, 0xa6, 0x7e, 0x28, 0x52, 0x1c, 0x93, 0x3c, 0x66, 0xa1, 0x90,
|
||||
0x19, 0xb6, 0x22, 0x4c, 0x3f, 0x15, 0x8e, 0xc4, 0x69, 0x96, 0x14, 0x11, 0xe3, 0xf3, 0xac, 0x0d,
|
||||
0x35, 0x10, 0x57, 0xc5, 0xd2, 0x54, 0x70, 0x6c, 0x16, 0x53, 0xcc, 0x7b, 0x00, 0x74, 0xa3, 0x94,
|
||||
0x64, 0xd3, 0x42, 0xd1, 0x3c, 0xa0, 0x79, 0x26, 0x78, 0x4e, 0xd1, 0x21, 0x00, 0x99, 0x67, 0x9d,
|
||||
0xd6, 0xe8, 0xdf, 0xb8, 0x1b, 0x2c, 0x64, 0xd0, 0x1e, 0x6c, 0x51, 0x29, 0x85, 0x74, 0xda, 0xa3,
|
||||
0xd6, 0xb8, 0x1b, 0x98, 0xc0, 0x3b, 0x86, 0x9d, 0x47, 0x41, 0x66, 0x01, 0x7d, 0x2f, 0x68, 0xae,
|
||||
0x10, 0x82, 0xff, 0x33, 0xa2, 0x88, 0xd3, 0xd2, 0x1a, 0xbd, 0xf7, 0x2e, 0x60, 0xd7, 0x48, 0x6c,
|
||||
0xa1, 0x35, 0x9a, 0x06, 0xf8, 0x15, 0xf4, 0x9f, 0x49, 0xc2, 0x66, 0x44, 0xd1, 0x0d, 0x05, 0x90,
|
||||
0x03, 0xdb, 0x29, 0x09, 0x63, 0xc6, 0xa9, 0xbd, 0x5e, 0x86, 0xde, 0x35, 0x0c, 0x2a, 0x80, 0x2d,
|
||||
0xbf, 0x0f, 0x1d, 0x4d, 0x2f, 0xff, 0x68, 0xa3, 0x86, 0x27, 0x9c, 0x40, 0xff, 0x8e, 0x71, 0x92,
|
||||
0xb0, 0xaf, 0x4d, 0x4f, 0xf0, 0x2e, 0x61, 0x50, 0xc9, 0xfe, 0xfa, 0xcf, 0xb3, 0xef, 0x36, 0x74,
|
||||
0x6e, 0xb5, 0xf1, 0x68, 0x02, 0x03, 0xb3, 0xab, 0x1c, 0x42, 0x43, 0xbf, 0x9a, 0x0e, 0x6d, 0xe3,
|
||||
0x53, 0x91, 0x24, 0xf6, 0x35, 0xae, 0xe7, 0x2f, 0x8f, 0x8e, 0xbf, 0xc6, 0xda, 0x7b, 0x00, 0x03,
|
||||
0xfd, 0xf5, 0x61, 0x09, 0xa7, 0x6f, 0x2c, 0x18, 0xe8, 0x1e, 0xac, 0x3f, 0xb4, 0xa0, 0x09, 0xf4,
|
||||
0x0c, 0xa8, 0xec, 0x2a, 0x3a, 0xaa, 0xeb, 0x6b, 0x86, 0xb9, 0xa3, 0x66, 0x41, 0x1d, 0x5a, 0x76,
|
||||
0x70, 0x15, 0x5a, 0xb3, 0x60, 0x15, 0x5a, 0x6f, 0xfe, 0xb4, 0xa3, 0x47, 0xfd, 0xfc, 0x27, 0x00,
|
||||
0x00, 0xff, 0xff, 0xe0, 0x00, 0xbf, 0x51, 0x76, 0x03, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
syntax = "proto3";
|
||||
package vagrant.config;
|
||||
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common/common.proto";
|
||||
|
||||
message AttributesResponse {
|
||||
repeated string attributes = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message LoadRequest {
|
||||
string data = 1;
|
||||
}
|
||||
|
||||
message LoadResponse {
|
||||
string data = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message ValidateRequest {
|
||||
string data = 1;
|
||||
string machine = 2;
|
||||
}
|
||||
|
||||
message ValidateResponse {
|
||||
repeated string errors = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message FinalizeRequest {
|
||||
string data = 1;
|
||||
}
|
||||
|
||||
message FinalizeResponse {
|
||||
string data = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
service Config {
|
||||
rpc ConfigAttributes(vagrant.common.NullRequest) returns (AttributesResponse);
|
||||
rpc ConfigLoad(LoadRequest) returns (LoadResponse);
|
||||
rpc ConfigValidate(ValidateRequest) returns (ValidateResponse);
|
||||
rpc ConfigFinalize(FinalizeRequest) returns (FinalizeResponse);
|
||||
}
|
|
@ -0,0 +1,688 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: vagrant_folder/synced_folder.proto
|
||||
|
||||
package vagrant_folder
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import vagrant_caps "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_caps"
|
||||
import vagrant_common "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
||||
import vagrant_io "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type Request struct {
|
||||
Machine string `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"`
|
||||
Folders string `protobuf:"bytes,2,opt,name=folders,proto3" json:"folders,omitempty"`
|
||||
Options string `protobuf:"bytes,3,opt,name=options,proto3" json:"options,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Request) Reset() { *m = Request{} }
|
||||
func (m *Request) String() string { return proto.CompactTextString(m) }
|
||||
func (*Request) ProtoMessage() {}
|
||||
func (*Request) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a01e482b349ecb1, []int{0}
|
||||
}
|
||||
func (m *Request) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Request.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Request.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *Request) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Request.Merge(m, src)
|
||||
}
|
||||
func (m *Request) XXX_Size() int {
|
||||
return xxx_messageInfo_Request.Size(m)
|
||||
}
|
||||
func (m *Request) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_Request.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_Request proto.InternalMessageInfo
|
||||
|
||||
func (m *Request) GetMachine() string {
|
||||
if m != nil {
|
||||
return m.Machine
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Request) GetFolders() string {
|
||||
if m != nil {
|
||||
return m.Folders
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *Request) GetOptions() string {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CleanupRequest struct {
|
||||
Machine string `protobuf:"bytes,1,opt,name=machine,proto3" json:"machine,omitempty"`
|
||||
Options string `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *CleanupRequest) Reset() { *m = CleanupRequest{} }
|
||||
func (m *CleanupRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*CleanupRequest) ProtoMessage() {}
|
||||
func (*CleanupRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a01e482b349ecb1, []int{1}
|
||||
}
|
||||
func (m *CleanupRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_CleanupRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *CleanupRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_CleanupRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *CleanupRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_CleanupRequest.Merge(m, src)
|
||||
}
|
||||
func (m *CleanupRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_CleanupRequest.Size(m)
|
||||
}
|
||||
func (m *CleanupRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_CleanupRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_CleanupRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *CleanupRequest) GetMachine() string {
|
||||
if m != nil {
|
||||
return m.Machine
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *CleanupRequest) GetOptions() string {
|
||||
if m != nil {
|
||||
return m.Options
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type InfoResponse struct {
|
||||
Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"`
|
||||
Priority int64 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *InfoResponse) Reset() { *m = InfoResponse{} }
|
||||
func (m *InfoResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*InfoResponse) ProtoMessage() {}
|
||||
func (*InfoResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_8a01e482b349ecb1, []int{2}
|
||||
}
|
||||
func (m *InfoResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_InfoResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *InfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_InfoResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *InfoResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_InfoResponse.Merge(m, src)
|
||||
}
|
||||
func (m *InfoResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_InfoResponse.Size(m)
|
||||
}
|
||||
func (m *InfoResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_InfoResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_InfoResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *InfoResponse) GetDescription() string {
|
||||
if m != nil {
|
||||
return m.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *InfoResponse) GetPriority() int64 {
|
||||
if m != nil {
|
||||
return m.Priority
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*Request)(nil), "vagrant.folder.Request")
|
||||
proto.RegisterType((*CleanupRequest)(nil), "vagrant.folder.CleanupRequest")
|
||||
proto.RegisterType((*InfoResponse)(nil), "vagrant.folder.InfoResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// SyncedFolderClient is the client API for SyncedFolder service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type SyncedFolderClient interface {
|
||||
Cleanup(ctx context.Context, in *CleanupRequest, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error)
|
||||
Disable(ctx context.Context, in *Request, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error)
|
||||
Enable(ctx context.Context, in *Request, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error)
|
||||
Info(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*InfoResponse, error)
|
||||
IsUsable(ctx context.Context, in *vagrant_common.EmptyRequest, opts ...grpc.CallOption) (*vagrant_common.IsResponse, error)
|
||||
Name(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*vagrant_common.NameResponse, error)
|
||||
Prepare(ctx context.Context, in *Request, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error)
|
||||
// These are IO helpers for streaming
|
||||
Read(ctx context.Context, in *vagrant_io.ReadRequest, opts ...grpc.CallOption) (*vagrant_io.ReadResponse, error)
|
||||
Write(ctx context.Context, in *vagrant_io.WriteRequest, opts ...grpc.CallOption) (*vagrant_io.WriteResponse, error)
|
||||
// Capabilities
|
||||
GuestCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*vagrant_caps.CapabilitiesResponse, error)
|
||||
GuestCapability(ctx context.Context, in *vagrant_caps.GuestCapabilityRequest, opts ...grpc.CallOption) (*vagrant_caps.GuestCapabilityResponse, error)
|
||||
HostCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*vagrant_caps.CapabilitiesResponse, error)
|
||||
HostCapability(ctx context.Context, in *vagrant_caps.HostCapabilityRequest, opts ...grpc.CallOption) (*vagrant_caps.HostCapabilityResponse, error)
|
||||
}
|
||||
|
||||
type syncedFolderClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewSyncedFolderClient(cc *grpc.ClientConn) SyncedFolderClient {
|
||||
return &syncedFolderClient{cc}
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Cleanup(ctx context.Context, in *CleanupRequest, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error) {
|
||||
out := new(vagrant_common.EmptyResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Cleanup", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Disable(ctx context.Context, in *Request, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error) {
|
||||
out := new(vagrant_common.EmptyResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Disable", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Enable(ctx context.Context, in *Request, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error) {
|
||||
out := new(vagrant_common.EmptyResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Enable", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Info(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*InfoResponse, error) {
|
||||
out := new(InfoResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Info", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) IsUsable(ctx context.Context, in *vagrant_common.EmptyRequest, opts ...grpc.CallOption) (*vagrant_common.IsResponse, error) {
|
||||
out := new(vagrant_common.IsResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/IsUsable", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Name(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*vagrant_common.NameResponse, error) {
|
||||
out := new(vagrant_common.NameResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Name", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Prepare(ctx context.Context, in *Request, opts ...grpc.CallOption) (*vagrant_common.EmptyResponse, error) {
|
||||
out := new(vagrant_common.EmptyResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Prepare", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Read(ctx context.Context, in *vagrant_io.ReadRequest, opts ...grpc.CallOption) (*vagrant_io.ReadResponse, error) {
|
||||
out := new(vagrant_io.ReadResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Read", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) Write(ctx context.Context, in *vagrant_io.WriteRequest, opts ...grpc.CallOption) (*vagrant_io.WriteResponse, error) {
|
||||
out := new(vagrant_io.WriteResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/Write", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) GuestCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*vagrant_caps.CapabilitiesResponse, error) {
|
||||
out := new(vagrant_caps.CapabilitiesResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/GuestCapabilities", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) GuestCapability(ctx context.Context, in *vagrant_caps.GuestCapabilityRequest, opts ...grpc.CallOption) (*vagrant_caps.GuestCapabilityResponse, error) {
|
||||
out := new(vagrant_caps.GuestCapabilityResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/GuestCapability", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) HostCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*vagrant_caps.CapabilitiesResponse, error) {
|
||||
out := new(vagrant_caps.CapabilitiesResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/HostCapabilities", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *syncedFolderClient) HostCapability(ctx context.Context, in *vagrant_caps.HostCapabilityRequest, opts ...grpc.CallOption) (*vagrant_caps.HostCapabilityResponse, error) {
|
||||
out := new(vagrant_caps.HostCapabilityResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.folder.SyncedFolder/HostCapability", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SyncedFolderServer is the server API for SyncedFolder service.
|
||||
type SyncedFolderServer interface {
|
||||
Cleanup(context.Context, *CleanupRequest) (*vagrant_common.EmptyResponse, error)
|
||||
Disable(context.Context, *Request) (*vagrant_common.EmptyResponse, error)
|
||||
Enable(context.Context, *Request) (*vagrant_common.EmptyResponse, error)
|
||||
Info(context.Context, *vagrant_common.NullRequest) (*InfoResponse, error)
|
||||
IsUsable(context.Context, *vagrant_common.EmptyRequest) (*vagrant_common.IsResponse, error)
|
||||
Name(context.Context, *vagrant_common.NullRequest) (*vagrant_common.NameResponse, error)
|
||||
Prepare(context.Context, *Request) (*vagrant_common.EmptyResponse, error)
|
||||
// These are IO helpers for streaming
|
||||
Read(context.Context, *vagrant_io.ReadRequest) (*vagrant_io.ReadResponse, error)
|
||||
Write(context.Context, *vagrant_io.WriteRequest) (*vagrant_io.WriteResponse, error)
|
||||
// Capabilities
|
||||
GuestCapabilities(context.Context, *vagrant_common.NullRequest) (*vagrant_caps.CapabilitiesResponse, error)
|
||||
GuestCapability(context.Context, *vagrant_caps.GuestCapabilityRequest) (*vagrant_caps.GuestCapabilityResponse, error)
|
||||
HostCapabilities(context.Context, *vagrant_common.NullRequest) (*vagrant_caps.CapabilitiesResponse, error)
|
||||
HostCapability(context.Context, *vagrant_caps.HostCapabilityRequest) (*vagrant_caps.HostCapabilityResponse, error)
|
||||
}
|
||||
|
||||
func RegisterSyncedFolderServer(s *grpc.Server, srv SyncedFolderServer) {
|
||||
s.RegisterService(&_SyncedFolder_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Cleanup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CleanupRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Cleanup(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Cleanup",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Cleanup(ctx, req.(*CleanupRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Disable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Disable(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Disable",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Disable(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Enable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Enable(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Enable",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Enable(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Info(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Info",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Info(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_IsUsable_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.EmptyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).IsUsable(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/IsUsable",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).IsUsable(ctx, req.(*vagrant_common.EmptyRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Name_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Name(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Name",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Name(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Prepare_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Request)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Prepare(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Prepare",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Prepare(ctx, req.(*Request))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_io.ReadRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Read(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Read",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Read(ctx, req.(*vagrant_io.ReadRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_io.WriteRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).Write(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/Write",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).Write(ctx, req.(*vagrant_io.WriteRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_GuestCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).GuestCapabilities(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/GuestCapabilities",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).GuestCapabilities(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_GuestCapability_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_caps.GuestCapabilityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).GuestCapability(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/GuestCapability",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).GuestCapability(ctx, req.(*vagrant_caps.GuestCapabilityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_HostCapabilities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_common.NullRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).HostCapabilities(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/HostCapabilities",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).HostCapabilities(ctx, req.(*vagrant_common.NullRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _SyncedFolder_HostCapability_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(vagrant_caps.HostCapabilityRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SyncedFolderServer).HostCapability(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.folder.SyncedFolder/HostCapability",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SyncedFolderServer).HostCapability(ctx, req.(*vagrant_caps.HostCapabilityRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _SyncedFolder_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "vagrant.folder.SyncedFolder",
|
||||
HandlerType: (*SyncedFolderServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Cleanup",
|
||||
Handler: _SyncedFolder_Cleanup_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Disable",
|
||||
Handler: _SyncedFolder_Disable_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Enable",
|
||||
Handler: _SyncedFolder_Enable_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Info",
|
||||
Handler: _SyncedFolder_Info_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "IsUsable",
|
||||
Handler: _SyncedFolder_IsUsable_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Name",
|
||||
Handler: _SyncedFolder_Name_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Prepare",
|
||||
Handler: _SyncedFolder_Prepare_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Read",
|
||||
Handler: _SyncedFolder_Read_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Write",
|
||||
Handler: _SyncedFolder_Write_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GuestCapabilities",
|
||||
Handler: _SyncedFolder_GuestCapabilities_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GuestCapability",
|
||||
Handler: _SyncedFolder_GuestCapability_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "HostCapabilities",
|
||||
Handler: _SyncedFolder_HostCapabilities_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "HostCapability",
|
||||
Handler: _SyncedFolder_HostCapability_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "vagrant_folder/synced_folder.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("vagrant_folder/synced_folder.proto", fileDescriptor_8a01e482b349ecb1) }
|
||||
|
||||
var fileDescriptor_8a01e482b349ecb1 = []byte{
|
||||
// 488 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x5f, 0x6f, 0xd3, 0x30,
|
||||
0x14, 0xc5, 0xb5, 0x3f, 0x2c, 0xe3, 0x32, 0x15, 0xf0, 0x0b, 0x21, 0x0c, 0x34, 0x95, 0x21, 0xf1,
|
||||
0x42, 0x22, 0xc1, 0x13, 0x12, 0x0f, 0x4c, 0xeb, 0x60, 0x95, 0xd0, 0x84, 0x52, 0xd0, 0x1e, 0x26,
|
||||
0x51, 0xb9, 0xa9, 0xd7, 0x5a, 0x4a, 0x6c, 0x63, 0x3b, 0x88, 0x7c, 0x48, 0xbe, 0x13, 0x4a, 0x6c,
|
||||
0x87, 0x38, 0x40, 0xa9, 0x58, 0x9f, 0xaa, 0x7b, 0xcf, 0x3d, 0x3f, 0x9f, 0xde, 0x38, 0x81, 0xe1,
|
||||
0x37, 0xbc, 0x90, 0x98, 0xe9, 0xe9, 0x35, 0xcf, 0xe7, 0x44, 0x26, 0xaa, 0x62, 0x19, 0x99, 0xdb,
|
||||
0x2a, 0x16, 0x92, 0x6b, 0x8e, 0x06, 0x76, 0x26, 0x36, 0xdd, 0xe8, 0x6a, 0x41, 0xf5, 0xb2, 0x9c,
|
||||
0xc5, 0x19, 0x2f, 0x92, 0x25, 0x56, 0x4b, 0x9a, 0x71, 0x29, 0x12, 0x3b, 0x94, 0x90, 0xef, 0x3a,
|
||||
0x59, 0xf0, 0x17, 0x22, 0x2f, 0x17, 0x94, 0xb5, 0x5d, 0x5b, 0x36, 0x40, 0xd7, 0x9c, 0x66, 0xbc,
|
||||
0x28, 0x38, 0x4b, 0xcc, 0x8f, 0x39, 0x2c, 0x9a, 0x6c, 0x0a, 0x4e, 0x79, 0x42, 0xb9, 0x85, 0x4e,
|
||||
0x37, 0x96, 0x18, 0x0b, 0x95, 0x64, 0x58, 0xe0, 0x19, 0xcd, 0xa9, 0xa6, 0x44, 0x99, 0x03, 0x86,
|
||||
0x97, 0x10, 0xa4, 0xe4, 0x6b, 0x49, 0x94, 0x46, 0x21, 0x04, 0x05, 0xce, 0x96, 0x94, 0x91, 0x70,
|
||||
0xeb, 0x68, 0xeb, 0xf9, 0xed, 0xd4, 0x95, 0xb5, 0x62, 0x36, 0xa8, 0xc2, 0x6d, 0xa3, 0xd8, 0xb2,
|
||||
0x56, 0xb8, 0xd0, 0x94, 0x33, 0x15, 0xee, 0x18, 0xc5, 0x96, 0xc3, 0x11, 0x0c, 0x4e, 0x73, 0x82,
|
||||
0x59, 0x29, 0xd6, 0xe2, 0x3b, 0xca, 0xb6, 0x4f, 0xf9, 0x00, 0x07, 0x63, 0x76, 0xcd, 0x53, 0xa2,
|
||||
0x04, 0x67, 0x8a, 0xa0, 0x23, 0xb8, 0x33, 0x27, 0x2a, 0x93, 0xb4, 0xd1, 0x2d, 0xa7, 0xdb, 0x42,
|
||||
0x11, 0xec, 0x0b, 0x49, 0xb9, 0xa4, 0xba, 0x6a, 0x60, 0x3b, 0x69, 0x5b, 0xbf, 0xfc, 0x11, 0xc0,
|
||||
0xc1, 0xa4, 0xb9, 0x27, 0xef, 0x9a, 0xfc, 0xe8, 0x1c, 0x02, 0x1b, 0x12, 0x3d, 0x89, 0xfd, 0xcb,
|
||||
0x12, 0xfb, 0xe9, 0xa3, 0xc7, 0xad, 0x6e, 0x9f, 0xfa, 0x59, 0x21, 0x74, 0xd5, 0x06, 0x3b, 0x81,
|
||||
0x60, 0x44, 0x15, 0x9e, 0xe5, 0x04, 0x3d, 0xe8, 0x93, 0xd6, 0x44, 0xbc, 0x85, 0xbd, 0x33, 0x76,
|
||||
0x23, 0xc2, 0x09, 0xec, 0xd6, 0xdb, 0x42, 0x8f, 0xfa, 0x63, 0x17, 0x65, 0x9e, 0x3b, 0xc6, 0x61,
|
||||
0x1f, 0xee, 0x2d, 0x78, 0x04, 0xfb, 0x63, 0xf5, 0xd9, 0xfc, 0x91, 0xc3, 0xbf, 0x9c, 0x66, 0x38,
|
||||
0x51, 0x5f, 0x1d, 0xab, 0x6e, 0x90, 0x0b, 0x5c, 0x90, 0x75, 0x83, 0x38, 0x11, 0x17, 0xa4, 0xbb,
|
||||
0xd0, 0x8f, 0x92, 0x08, 0x2c, 0xff, 0x7f, 0x1d, 0xaf, 0x61, 0x37, 0x25, 0x78, 0xde, 0xf1, 0x53,
|
||||
0x1e, 0xd7, 0x1d, 0xe7, 0x0f, 0x7f, 0x17, 0xac, 0xf5, 0x0d, 0xdc, 0xba, 0x94, 0x54, 0x13, 0xe4,
|
||||
0x8d, 0x34, 0x2d, 0x67, 0x7e, 0xf8, 0x07, 0xc5, 0xba, 0x3f, 0xc1, 0xfd, 0xf7, 0xf5, 0xcc, 0x69,
|
||||
0xe7, 0x7d, 0x5b, 0xbd, 0x8b, 0xe1, 0x2f, 0x11, 0x0b, 0x15, 0x77, 0x8d, 0x2d, 0xf5, 0x0b, 0xdc,
|
||||
0xf5, 0xa9, 0x15, 0x3a, 0xf6, 0x6d, 0x3d, 0xd9, 0xc1, 0x9f, 0xfd, 0x63, 0xca, 0xf2, 0x27, 0x70,
|
||||
0xef, 0x9c, 0x6f, 0x3a, 0xf4, 0x15, 0x0c, 0x3c, 0x68, 0x85, 0x9e, 0xfa, 0x2e, 0x5f, 0x75, 0xe8,
|
||||
0xe3, 0xd5, 0x43, 0x06, 0x3e, 0xdb, 0x6b, 0xbe, 0x61, 0xaf, 0x7e, 0x06, 0x00, 0x00, 0xff, 0xff,
|
||||
0x89, 0x36, 0xb1, 0x5c, 0x0c, 0x06, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
syntax = "proto3";
|
||||
package vagrant.folder;
|
||||
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common/common.proto";
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io/io.proto";
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_caps/capabilities.proto";
|
||||
|
||||
message Request {
|
||||
string machine = 1;
|
||||
string folders = 2;
|
||||
string options = 3;
|
||||
}
|
||||
|
||||
message CleanupRequest {
|
||||
string machine = 1;
|
||||
string options = 2;
|
||||
}
|
||||
|
||||
message InfoResponse {
|
||||
string description = 1;
|
||||
int64 priority = 2;
|
||||
}
|
||||
|
||||
service SyncedFolder {
|
||||
rpc Cleanup(CleanupRequest) returns (vagrant.common.EmptyResponse);
|
||||
rpc Disable(Request) returns (vagrant.common.EmptyResponse);
|
||||
rpc Enable(Request) returns (vagrant.common.EmptyResponse);
|
||||
rpc Info(vagrant.common.NullRequest) returns (InfoResponse);
|
||||
rpc IsUsable(vagrant.common.EmptyRequest) returns (vagrant.common.IsResponse);
|
||||
rpc Name(vagrant.common.NullRequest) returns (vagrant.common.NameResponse);
|
||||
rpc Prepare(Request) returns (vagrant.common.EmptyResponse);
|
||||
// These are IO helpers for streaming
|
||||
rpc Read(vagrant.io.ReadRequest) returns (vagrant.io.ReadResponse);
|
||||
rpc Write(vagrant.io.WriteRequest) returns (vagrant.io.WriteResponse);
|
||||
// Capabilities
|
||||
rpc GuestCapabilities(vagrant.common.NullRequest) returns (vagrant.caps.CapabilitiesResponse);
|
||||
rpc GuestCapability(vagrant.caps.GuestCapabilityRequest) returns (vagrant.caps.GuestCapabilityResponse);
|
||||
rpc HostCapabilities(vagrant.common.NullRequest) returns (vagrant.caps.CapabilitiesResponse);
|
||||
rpc HostCapability(vagrant.caps.HostCapabilityRequest) returns (vagrant.caps.HostCapabilityResponse);
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: vagrant_io/io.proto
|
||||
|
||||
package vagrant_io
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
type ReadRequest struct {
|
||||
Target string `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ReadRequest) Reset() { *m = ReadRequest{} }
|
||||
func (m *ReadRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReadRequest) ProtoMessage() {}
|
||||
func (*ReadRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d46affeac7affd9e, []int{0}
|
||||
}
|
||||
func (m *ReadRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ReadRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ReadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ReadRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ReadRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ReadRequest.Merge(m, src)
|
||||
}
|
||||
func (m *ReadRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_ReadRequest.Size(m)
|
||||
}
|
||||
func (m *ReadRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ReadRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ReadRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *ReadRequest) GetTarget() string {
|
||||
if m != nil {
|
||||
return m.Target
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ReadResponse struct {
|
||||
Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *ReadResponse) Reset() { *m = ReadResponse{} }
|
||||
func (m *ReadResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ReadResponse) ProtoMessage() {}
|
||||
func (*ReadResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d46affeac7affd9e, []int{1}
|
||||
}
|
||||
func (m *ReadResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_ReadResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *ReadResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_ReadResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *ReadResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_ReadResponse.Merge(m, src)
|
||||
}
|
||||
func (m *ReadResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_ReadResponse.Size(m)
|
||||
}
|
||||
func (m *ReadResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_ReadResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_ReadResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *ReadResponse) GetContent() string {
|
||||
if m != nil {
|
||||
return m.Content
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *ReadResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type WriteRequest struct {
|
||||
Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"`
|
||||
Target string `protobuf:"bytes,2,opt,name=target,proto3" json:"target,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *WriteRequest) Reset() { *m = WriteRequest{} }
|
||||
func (m *WriteRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*WriteRequest) ProtoMessage() {}
|
||||
func (*WriteRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d46affeac7affd9e, []int{2}
|
||||
}
|
||||
func (m *WriteRequest) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_WriteRequest.Unmarshal(m, b)
|
||||
}
|
||||
func (m *WriteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_WriteRequest.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *WriteRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_WriteRequest.Merge(m, src)
|
||||
}
|
||||
func (m *WriteRequest) XXX_Size() int {
|
||||
return xxx_messageInfo_WriteRequest.Size(m)
|
||||
}
|
||||
func (m *WriteRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_WriteRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_WriteRequest proto.InternalMessageInfo
|
||||
|
||||
func (m *WriteRequest) GetContent() string {
|
||||
if m != nil {
|
||||
return m.Content
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *WriteRequest) GetTarget() string {
|
||||
if m != nil {
|
||||
return m.Target
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type WriteResponse struct {
|
||||
Length int32 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"`
|
||||
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *WriteResponse) Reset() { *m = WriteResponse{} }
|
||||
func (m *WriteResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*WriteResponse) ProtoMessage() {}
|
||||
func (*WriteResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_d46affeac7affd9e, []int{3}
|
||||
}
|
||||
func (m *WriteResponse) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_WriteResponse.Unmarshal(m, b)
|
||||
}
|
||||
func (m *WriteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_WriteResponse.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (m *WriteResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_WriteResponse.Merge(m, src)
|
||||
}
|
||||
func (m *WriteResponse) XXX_Size() int {
|
||||
return xxx_messageInfo_WriteResponse.Size(m)
|
||||
}
|
||||
func (m *WriteResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_WriteResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_WriteResponse proto.InternalMessageInfo
|
||||
|
||||
func (m *WriteResponse) GetLength() int32 {
|
||||
if m != nil {
|
||||
return m.Length
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *WriteResponse) GetError() string {
|
||||
if m != nil {
|
||||
return m.Error
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*ReadRequest)(nil), "vagrant.io.ReadRequest")
|
||||
proto.RegisterType((*ReadResponse)(nil), "vagrant.io.ReadResponse")
|
||||
proto.RegisterType((*WriteRequest)(nil), "vagrant.io.WriteRequest")
|
||||
proto.RegisterType((*WriteResponse)(nil), "vagrant.io.WriteResponse")
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// IOClient is the client API for IO service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type IOClient interface {
|
||||
Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error)
|
||||
Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error)
|
||||
}
|
||||
|
||||
type iOClient struct {
|
||||
cc *grpc.ClientConn
|
||||
}
|
||||
|
||||
func NewIOClient(cc *grpc.ClientConn) IOClient {
|
||||
return &iOClient{cc}
|
||||
}
|
||||
|
||||
func (c *iOClient) Read(ctx context.Context, in *ReadRequest, opts ...grpc.CallOption) (*ReadResponse, error) {
|
||||
out := new(ReadResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.io.IO/Read", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *iOClient) Write(ctx context.Context, in *WriteRequest, opts ...grpc.CallOption) (*WriteResponse, error) {
|
||||
out := new(WriteResponse)
|
||||
err := c.cc.Invoke(ctx, "/vagrant.io.IO/Write", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// IOServer is the server API for IO service.
|
||||
type IOServer interface {
|
||||
Read(context.Context, *ReadRequest) (*ReadResponse, error)
|
||||
Write(context.Context, *WriteRequest) (*WriteResponse, error)
|
||||
}
|
||||
|
||||
func RegisterIOServer(s *grpc.Server, srv IOServer) {
|
||||
s.RegisterService(&_IO_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _IO_Read_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ReadRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IOServer).Read(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.io.IO/Read",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IOServer).Read(ctx, req.(*ReadRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _IO_Write_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(WriteRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IOServer).Write(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/vagrant.io.IO/Write",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IOServer).Write(ctx, req.(*WriteRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _IO_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "vagrant.io.IO",
|
||||
HandlerType: (*IOServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Read",
|
||||
Handler: _IO_Read_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Write",
|
||||
Handler: _IO_Write_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "vagrant_io/io.proto",
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("vagrant_io/io.proto", fileDescriptor_d46affeac7affd9e) }
|
||||
|
||||
var fileDescriptor_d46affeac7affd9e = []byte{
|
||||
// 219 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2e, 0x4b, 0x4c, 0x2f,
|
||||
0x4a, 0xcc, 0x2b, 0x89, 0xcf, 0xcc, 0xd7, 0xcf, 0xcc, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
|
||||
0xe2, 0x82, 0x0a, 0xea, 0x65, 0xe6, 0x2b, 0xa9, 0x72, 0x71, 0x07, 0xa5, 0x26, 0xa6, 0x04, 0xa5,
|
||||
0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x89, 0x71, 0xb1, 0x95, 0x24, 0x16, 0xa5, 0xa7, 0x96, 0x48,
|
||||
0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x41, 0x79, 0x4a, 0x76, 0x5c, 0x3c, 0x10, 0x65, 0xc5, 0x05,
|
||||
0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x12, 0x5c, 0xec, 0xc9, 0xf9, 0x79, 0x25, 0xa9, 0x79, 0x30, 0x85,
|
||||
0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, 0x6a, 0x51, 0x51, 0x7e, 0x91, 0x04, 0x13, 0x58, 0x1c, 0xc2,
|
||||
0x51, 0x72, 0xe0, 0xe2, 0x09, 0x2f, 0xca, 0x2c, 0x49, 0x85, 0xd9, 0x83, 0x5b, 0x3f, 0xc2, 0x05,
|
||||
0x4c, 0x28, 0x2e, 0xb0, 0xe5, 0xe2, 0x85, 0x9a, 0x00, 0x75, 0x82, 0x18, 0x17, 0x5b, 0x4e, 0x6a,
|
||||
0x5e, 0x7a, 0x49, 0x06, 0xd8, 0x04, 0xd6, 0x20, 0x28, 0x0f, 0xbb, 0x03, 0x8c, 0x6a, 0xb9, 0x98,
|
||||
0x3c, 0xfd, 0x85, 0x2c, 0xb9, 0x58, 0x40, 0xde, 0x10, 0x12, 0xd7, 0x43, 0x04, 0x81, 0x1e, 0x92,
|
||||
0xff, 0xa5, 0x24, 0x30, 0x25, 0xa0, 0xd6, 0xd9, 0x70, 0xb1, 0x82, 0xed, 0x17, 0x42, 0x51, 0x82,
|
||||
0xec, 0x29, 0x29, 0x49, 0x2c, 0x32, 0x10, 0xdd, 0x49, 0x6c, 0xe0, 0x90, 0x37, 0x06, 0x04, 0x00,
|
||||
0x00, 0xff, 0xff, 0x47, 0x7e, 0x0b, 0xe4, 0x90, 0x01, 0x00, 0x00,
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
syntax = "proto3";
|
||||
package vagrant.io;
|
||||
|
||||
message ReadRequest {
|
||||
string target = 1;
|
||||
}
|
||||
|
||||
message ReadResponse {
|
||||
string content = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message WriteRequest {
|
||||
string content = 1;
|
||||
string target = 2;
|
||||
}
|
||||
|
||||
message WriteResponse {
|
||||
int32 length = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
service IO {
|
||||
rpc Read(ReadRequest) returns (ReadResponse);
|
||||
rpc Write(WriteRequest) returns (WriteResponse);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,74 @@
|
|||
syntax = "proto3";
|
||||
package vagrant.provider;
|
||||
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_caps/capabilities.proto";
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common/common.proto";
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_config/config.proto";
|
||||
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io/io.proto";
|
||||
|
||||
message ActionRequest {
|
||||
string name = 1;
|
||||
string machine = 2;
|
||||
}
|
||||
message ActionResponse {
|
||||
repeated string result = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message InfoResponse {
|
||||
repeated string capabilities = 1;
|
||||
string description = 2;
|
||||
int64 priority = 3;
|
||||
}
|
||||
|
||||
message RunActionRequest {
|
||||
string name = 1;
|
||||
string data = 2;
|
||||
string machine = 3;
|
||||
}
|
||||
|
||||
message RunActionResponse {
|
||||
string data = 1;
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
message SshInfoResponse {
|
||||
string host = 1;
|
||||
int64 port = 2;
|
||||
string private_key_path = 3;
|
||||
string username = 4;
|
||||
string error = 5;
|
||||
}
|
||||
message StateResponse {
|
||||
string id = 1;
|
||||
string short_description = 2;
|
||||
string long_description = 3;
|
||||
string error = 4;
|
||||
}
|
||||
|
||||
service Provider {
|
||||
rpc Action(ActionRequest) returns (ActionResponse);
|
||||
rpc Info(vagrant.common.NullRequest) returns (InfoResponse);
|
||||
rpc IsInstalled(vagrant.common.EmptyRequest) returns (vagrant.common.IsResponse);
|
||||
rpc IsUsable(vagrant.common.EmptyRequest) returns (vagrant.common.IsResponse);
|
||||
rpc MachineIdChanged(vagrant.common.EmptyRequest) returns (vagrant.common.EmptyResponse);
|
||||
rpc Name(vagrant.common.NullRequest) returns (vagrant.common.NameResponse);
|
||||
rpc RunAction(RunActionRequest) returns (RunActionResponse);
|
||||
rpc SshInfo(vagrant.common.EmptyRequest) returns (SshInfoResponse);
|
||||
rpc State(vagrant.common.EmptyRequest) returns (StateResponse);
|
||||
// These are IO helpers for streaming
|
||||
rpc Read(vagrant.io.ReadRequest) returns (vagrant.io.ReadResponse);
|
||||
rpc Write(vagrant.io.WriteRequest) returns (vagrant.io.WriteResponse);
|
||||
// These are Config helpers
|
||||
rpc ConfigAttributes(vagrant.common.NullRequest) returns (vagrant.config.AttributesResponse);
|
||||
rpc ConfigLoad(vagrant.config.LoadRequest) returns (vagrant.config.LoadResponse);
|
||||
rpc ConfigValidate(vagrant.config.ValidateRequest) returns (vagrant.config.ValidateResponse);
|
||||
rpc ConfigFinalize(vagrant.config.FinalizeRequest) returns (vagrant.config.FinalizeResponse);
|
||||
// Capabilities
|
||||
rpc GuestCapabilities(vagrant.common.NullRequest) returns (vagrant.caps.CapabilitiesResponse);
|
||||
rpc GuestCapability(vagrant.caps.GuestCapabilityRequest) returns (vagrant.caps.GuestCapabilityResponse);
|
||||
rpc HostCapabilities(vagrant.common.NullRequest) returns (vagrant.caps.CapabilitiesResponse);
|
||||
rpc HostCapability(vagrant.caps.HostCapabilityRequest) returns (vagrant.caps.HostCapabilityResponse);
|
||||
rpc ProviderCapabilities(vagrant.common.NullRequest) returns (vagrant.caps.ProviderCapabilitiesResponse);
|
||||
rpc ProviderCapability(vagrant.caps.ProviderCapabilityRequest) returns (vagrant.caps.ProviderCapabilityResponse);
|
||||
}
|
|
@ -0,0 +1,363 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
go_plugin "github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_provider"
|
||||
)
|
||||
|
||||
type Provider interface {
|
||||
vagrant.Provider
|
||||
Meta
|
||||
}
|
||||
|
||||
type ProviderPlugin struct {
|
||||
go_plugin.NetRPCUnsupportedPlugin
|
||||
Impl Provider
|
||||
}
|
||||
|
||||
type GRPCProviderClient struct {
|
||||
GRPCCoreClient
|
||||
GRPCConfigClient
|
||||
GRPCGuestCapabilitiesClient
|
||||
GRPCHostCapabilitiesClient
|
||||
GRPCProviderCapabilitiesClient
|
||||
GRPCIOClient
|
||||
client vagrant_provider.ProviderClient
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) Action(actionName string, m *vagrant.Machine) (r []string, err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.Action(context.Background(), &vagrant_provider.ActionRequest{
|
||||
Name: actionName,
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = resp.Result
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) Info() *vagrant.ProviderInfo {
|
||||
resp, err := c.client.Info(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return &vagrant.ProviderInfo{}
|
||||
}
|
||||
return &vagrant.ProviderInfo{
|
||||
Description: resp.Description,
|
||||
Priority: resp.Priority}
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) IsInstalled(m *vagrant.Machine) (r bool, err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.IsInstalled(context.Background(), &vagrant_common.EmptyRequest{
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = resp.Result
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) IsUsable(m *vagrant.Machine) (r bool, err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.IsUsable(context.Background(), &vagrant_common.EmptyRequest{
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = resp.Result
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) MachineIdChanged(m *vagrant.Machine) (err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.MachineIdChanged(context.Background(), &vagrant_common.EmptyRequest{
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) RunAction(actName string, runData string, m *vagrant.Machine) (r string, err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.RunAction(context.Background(), &vagrant_provider.RunActionRequest{
|
||||
Name: actName,
|
||||
Data: runData,
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = resp.Data
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) SshInfo(m *vagrant.Machine) (r *vagrant.SshInfo, err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.SshInfo(context.Background(), &vagrant_common.EmptyRequest{
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
r = &vagrant.SshInfo{
|
||||
Host: resp.Host,
|
||||
Port: resp.Port,
|
||||
PrivateKeyPath: resp.PrivateKeyPath,
|
||||
Username: resp.Username}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) State(m *vagrant.Machine) (r *vagrant.MachineState, err error) {
|
||||
machData, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.State(context.Background(), &vagrant_common.EmptyRequest{
|
||||
Machine: machData})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
r = &vagrant.MachineState{
|
||||
Id: resp.Id,
|
||||
ShortDesc: resp.ShortDescription,
|
||||
LongDesc: resp.LongDescription}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCProviderClient) Name() string {
|
||||
resp, err := c.client.Name(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return resp.Name
|
||||
}
|
||||
|
||||
func (p *ProviderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProviderPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||
client := vagrant_provider.NewProviderClient(c)
|
||||
return &GRPCProviderClient{
|
||||
GRPCConfigClient: GRPCConfigClient{
|
||||
client: client},
|
||||
GRPCGuestCapabilitiesClient: GRPCGuestCapabilitiesClient{
|
||||
client: client},
|
||||
GRPCHostCapabilitiesClient: GRPCHostCapabilitiesClient{
|
||||
client: client},
|
||||
GRPCProviderCapabilitiesClient: GRPCProviderCapabilitiesClient{
|
||||
client: client},
|
||||
GRPCIOClient: GRPCIOClient{
|
||||
client: client},
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type GRPCProviderPlugin struct {
|
||||
ProviderPlugin
|
||||
Impl Provider
|
||||
}
|
||||
|
||||
func (p *GRPCProviderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||
p.Impl.Init()
|
||||
vagrant_provider.RegisterProviderServer(s, &GRPCProviderServer{
|
||||
Impl: p.Impl,
|
||||
GRPCConfigServer: GRPCConfigServer{
|
||||
Impl: p.Impl},
|
||||
GRPCGuestCapabilitiesServer: GRPCGuestCapabilitiesServer{
|
||||
Impl: p.Impl},
|
||||
GRPCHostCapabilitiesServer: GRPCHostCapabilitiesServer{
|
||||
Impl: p.Impl},
|
||||
GRPCProviderCapabilitiesServer: GRPCProviderCapabilitiesServer{
|
||||
Impl: p.Impl},
|
||||
GRPCIOServer: GRPCIOServer{
|
||||
Impl: p.Impl}})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *GRPCProviderPlugin) GRPCClient(context.Context, *go_plugin.GRPCBroker, *grpc.ClientConn) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type GRPCProviderServer struct {
|
||||
GRPCIOServer
|
||||
GRPCConfigServer
|
||||
GRPCGuestCapabilitiesServer
|
||||
GRPCHostCapabilitiesServer
|
||||
GRPCProviderCapabilitiesServer
|
||||
Impl Provider
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) Action(ctx context.Context, req *vagrant_provider.ActionRequest) (resp *vagrant_provider.ActionResponse, err error) {
|
||||
resp = &vagrant_provider.ActionResponse{}
|
||||
m, e := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
r, e := s.Impl.Action(req.Name, m)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
resp.Result = r
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) RunAction(ctx context.Context, req *vagrant_provider.RunActionRequest) (resp *vagrant_provider.RunActionResponse, err error) {
|
||||
resp = &vagrant_provider.RunActionResponse{}
|
||||
m, e := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
r, e := s.Impl.RunAction(req.Name, req.Data, m)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
resp.Data = r
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) Info(ctx context.Context, req *vagrant_common.NullRequest) (*vagrant_provider.InfoResponse, error) {
|
||||
r := s.Impl.Info()
|
||||
return &vagrant_provider.InfoResponse{
|
||||
Description: r.Description,
|
||||
Priority: r.Priority}, nil
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) IsInstalled(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_common.IsResponse, err error) {
|
||||
resp = &vagrant_common.IsResponse{}
|
||||
m, e := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
r, e := s.Impl.IsInstalled(m)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
resp.Result = r
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) IsUsable(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_common.IsResponse, err error) {
|
||||
resp = &vagrant_common.IsResponse{}
|
||||
m, e := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
r, e := s.Impl.IsUsable(m)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
resp.Result = r
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) SshInfo(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_provider.SshInfoResponse, err error) {
|
||||
resp = &vagrant_provider.SshInfoResponse{}
|
||||
m, e := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
r, e := s.Impl.SshInfo(m)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
resp = &vagrant_provider.SshInfoResponse{
|
||||
Host: r.Host,
|
||||
Port: r.Port,
|
||||
Username: r.Username,
|
||||
PrivateKeyPath: r.PrivateKeyPath}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) State(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_provider.StateResponse, err error) {
|
||||
resp = &vagrant_provider.StateResponse{}
|
||||
m, e := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
r, e := s.Impl.State(m)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
resp = &vagrant_provider.StateResponse{
|
||||
Id: r.Id,
|
||||
ShortDescription: r.ShortDesc,
|
||||
LongDescription: r.LongDesc}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) MachineIdChanged(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_common.EmptyResponse, err error) {
|
||||
resp = &vagrant_common.EmptyResponse{}
|
||||
m, e := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
return
|
||||
}
|
||||
e = s.Impl.MachineIdChanged(m)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCProviderServer) Name(ctx context.Context, req *vagrant_common.NullRequest) (*vagrant_common.NameResponse, error) {
|
||||
return &vagrant_common.NameResponse{Name: s.Impl.Name()}, nil
|
||||
}
|
|
@ -0,0 +1,291 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
|
||||
go_plugin "github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_folder"
|
||||
)
|
||||
|
||||
type SyncedFolder interface {
|
||||
vagrant.SyncedFolder
|
||||
Meta
|
||||
}
|
||||
|
||||
type SyncedFolderPlugin struct {
|
||||
go_plugin.NetRPCUnsupportedPlugin
|
||||
Impl SyncedFolder
|
||||
}
|
||||
|
||||
type GRPCSyncedFolderClient struct {
|
||||
GRPCCoreClient
|
||||
GRPCGuestCapabilitiesClient
|
||||
GRPCHostCapabilitiesClient
|
||||
GRPCIOClient
|
||||
client vagrant_folder.SyncedFolderClient
|
||||
}
|
||||
|
||||
func (c *GRPCSyncedFolderClient) Cleanup(m *vagrant.Machine, o *vagrant.FolderOptions) (err error) {
|
||||
machine, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
opts, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.Cleanup(context.Background(), &vagrant_folder.CleanupRequest{
|
||||
Machine: machine,
|
||||
Options: string(opts)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCSyncedFolderClient) Disable(m *vagrant.Machine, f *vagrant.FolderList, o *vagrant.FolderOptions) (err error) {
|
||||
machine, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
folders, err := json.Marshal(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
opts, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.Disable(context.Background(), &vagrant_folder.Request{
|
||||
Machine: machine,
|
||||
Folders: string(folders),
|
||||
Options: string(opts)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCSyncedFolderClient) Enable(m *vagrant.Machine, f *vagrant.FolderList, o *vagrant.FolderOptions) (err error) {
|
||||
machine, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
folders, err := json.Marshal(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
opts, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.Enable(context.Background(), &vagrant_folder.Request{
|
||||
Machine: machine,
|
||||
Folders: string(folders),
|
||||
Options: string(opts)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCSyncedFolderClient) Info() *vagrant.SyncedFolderInfo {
|
||||
resp, err := c.client.Info(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return &vagrant.SyncedFolderInfo{}
|
||||
}
|
||||
return &vagrant.SyncedFolderInfo{
|
||||
Description: resp.Description,
|
||||
Priority: resp.Priority}
|
||||
}
|
||||
|
||||
func (c *GRPCSyncedFolderClient) IsUsable(m *vagrant.Machine) (u bool, err error) {
|
||||
machine, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.IsUsable(context.Background(), &vagrant_common.EmptyRequest{
|
||||
Machine: machine})
|
||||
u = resp.Result
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *GRPCSyncedFolderClient) Name() string {
|
||||
resp, err := c.client.Name(context.Background(), &vagrant_common.NullRequest{})
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return resp.Name
|
||||
}
|
||||
|
||||
func (c *GRPCSyncedFolderClient) Prepare(m *vagrant.Machine, f *vagrant.FolderList, o *vagrant.FolderOptions) (err error) {
|
||||
machine, err := vagrant.DumpMachine(m)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
folders, err := json.Marshal(f)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
opts, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := c.client.Prepare(context.Background(), &vagrant_folder.Request{
|
||||
Machine: machine,
|
||||
Folders: string(folders),
|
||||
Options: string(opts)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if resp.Error != "" {
|
||||
err = errors.New(resp.Error)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type GRPCSyncedFolderServer struct {
|
||||
GRPCGuestCapabilitiesServer
|
||||
GRPCHostCapabilitiesServer
|
||||
GRPCIOServer
|
||||
Impl SyncedFolder
|
||||
}
|
||||
|
||||
func (s *GRPCSyncedFolderServer) Cleanup(ctx context.Context, req *vagrant_folder.CleanupRequest) (resp *vagrant_common.EmptyResponse, err error) {
|
||||
resp = &vagrant_common.EmptyResponse{}
|
||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var options vagrant.FolderOptions
|
||||
err = json.Unmarshal([]byte(req.Options), &options)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e := s.Impl.Cleanup(machine, &options)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCSyncedFolderServer) Disable(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
||||
resp = &vagrant_common.EmptyResponse{}
|
||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var folders vagrant.FolderList
|
||||
err = json.Unmarshal([]byte(req.Folders), &folders)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var options vagrant.FolderOptions
|
||||
err = json.Unmarshal([]byte(req.Options), &options)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e := s.Impl.Disable(machine, &folders, &options)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCSyncedFolderServer) Enable(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
||||
resp = &vagrant_common.EmptyResponse{}
|
||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var folders vagrant.FolderList
|
||||
err = json.Unmarshal([]byte(req.Folders), &folders)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var options vagrant.FolderOptions
|
||||
err = json.Unmarshal([]byte(req.Options), &options)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e := s.Impl.Enable(machine, &folders, &options)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCSyncedFolderServer) Info(ctx context.Context, req *vagrant_common.NullRequest) (*vagrant_folder.InfoResponse, error) {
|
||||
r := s.Impl.Info()
|
||||
return &vagrant_folder.InfoResponse{
|
||||
Description: r.Description,
|
||||
Priority: r.Priority}, nil
|
||||
}
|
||||
|
||||
func (s *GRPCSyncedFolderServer) IsUsable(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_common.IsResponse, err error) {
|
||||
resp = &vagrant_common.IsResponse{}
|
||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r, e := s.Impl.IsUsable(machine)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
}
|
||||
resp.Result = r
|
||||
return
|
||||
}
|
||||
|
||||
func (s *GRPCSyncedFolderServer) Name(ctx context.Context, req *vagrant_common.NullRequest) (*vagrant_common.NameResponse, error) {
|
||||
return &vagrant_common.NameResponse{Name: s.Impl.Name()}, nil
|
||||
}
|
||||
|
||||
func (s *GRPCSyncedFolderServer) Prepare(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
||||
resp = &vagrant_common.EmptyResponse{}
|
||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var folders vagrant.FolderList
|
||||
err = json.Unmarshal([]byte(req.Folders), &folders)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var options vagrant.FolderOptions
|
||||
err = json.Unmarshal([]byte(req.Options), &options)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
e := s.Impl.Prepare(machine, &folders, &options)
|
||||
if e != nil {
|
||||
resp.Error = e.Error()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (f *SyncedFolderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||
vagrant_folder.RegisterSyncedFolderServer(s, &GRPCSyncedFolderServer{Impl: f.Impl})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *SyncedFolderPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||
return &GRPCSyncedFolderClient{client: vagrant_folder.NewSyncedFolderClient(c)}, nil
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package vagrant
|
||||
|
||||
type Provider interface {
|
||||
Info() *ProviderInfo
|
||||
Action(actionName string, machData *Machine) ([]string, error)
|
||||
IsInstalled(machData *Machine) (bool, error)
|
||||
IsUsable(machData *Machine) (bool, error)
|
||||
MachineIdChanged(machData *Machine) error
|
||||
Name() string
|
||||
RunAction(actionName string, data string, machData *Machine) (string, error)
|
||||
SshInfo(machData *Machine) (*SshInfo, error)
|
||||
State(machData *Machine) (*MachineState, error)
|
||||
|
||||
Config
|
||||
GuestCapabilities
|
||||
HostCapabilities
|
||||
ProviderCapabilities
|
||||
}
|
||||
|
||||
type ProviderInfo struct {
|
||||
Description string `json:"description"`
|
||||
Priority int64 `json:"priority"`
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Error error `json:"error"`
|
||||
Result interface{} `json:"result"`
|
||||
}
|
||||
|
||||
// Serialize the response into a JSON string
|
||||
func (r Response) Dump() string {
|
||||
result, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return fmt.Sprintf(`{"error": "failed to encode response - %s"}`, err)
|
||||
}
|
||||
return string(result[:])
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package vagrant
|
||||
|
||||
type SshInfo struct {
|
||||
Host string `json:"host"`
|
||||
Port int64 `json:"port"`
|
||||
Username string `json:"username"`
|
||||
PrivateKeyPath string `json:"private_key_path"`
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package vagrant
|
||||
|
||||
type FolderList map[string]interface{}
|
||||
type FolderOptions map[string]interface{}
|
||||
|
||||
type SyncedFolderInfo struct {
|
||||
Description string `json:"description"`
|
||||
Priority int64 `json:"priority"`
|
||||
}
|
||||
|
||||
type SyncedFolder interface {
|
||||
Cleanup(m *Machine, opts *FolderOptions) error
|
||||
Disable(m *Machine, f *FolderList, opts *FolderOptions) error
|
||||
Enable(m *Machine, f *FolderList, opts *FolderOptions) error
|
||||
Info() *SyncedFolderInfo
|
||||
IsUsable(m *Machine) (bool, error)
|
||||
Name() string
|
||||
Prepare(m *Machine, f *FolderList, opts *FolderOptions) error
|
||||
|
||||
GuestCapabilities
|
||||
HostCapabilities
|
||||
}
|
|
@ -0,0 +1,472 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type UiColor uint
|
||||
|
||||
const (
|
||||
UiColorRed UiColor = 31
|
||||
UiColorGreen = 32
|
||||
UiColorYellow = 33
|
||||
UiColorBlue = 34
|
||||
UiColorMagenta = 35
|
||||
UiColorCyan = 36
|
||||
)
|
||||
|
||||
type UiChannel uint
|
||||
|
||||
const (
|
||||
UiOutput UiChannel = 1
|
||||
UiError = 2
|
||||
)
|
||||
|
||||
var logger = DefaultLogger().Named("ui")
|
||||
|
||||
type Options struct {
|
||||
Channel UiChannel
|
||||
NewLine bool
|
||||
}
|
||||
|
||||
var defaultOptions = &Options{
|
||||
Channel: UiOutput,
|
||||
NewLine: true,
|
||||
}
|
||||
|
||||
// The Ui interface handles all communication for Vagrant with the outside
|
||||
// world. This sort of control allows us to strictly control how output
|
||||
// is formatted and various levels of output.
|
||||
type Ui interface {
|
||||
Ask(string) (string, error)
|
||||
Detail(string)
|
||||
Info(string)
|
||||
Error(string)
|
||||
Machine(string, ...string)
|
||||
Message(string, *Options)
|
||||
Output(string)
|
||||
Say(string)
|
||||
Success(string)
|
||||
Warn(string)
|
||||
}
|
||||
|
||||
// The BasicUI is a UI that reads and writes from a standard Go reader
|
||||
// and writer. It is safe to be called from multiple goroutines. Machine
|
||||
// readable output is simply logged for this UI.
|
||||
type BasicUi struct {
|
||||
Reader io.Reader
|
||||
Writer io.Writer
|
||||
ErrorWriter io.Writer
|
||||
l sync.Mutex
|
||||
interrupted bool
|
||||
scanner *bufio.Scanner
|
||||
}
|
||||
|
||||
var _ Ui = new(BasicUi)
|
||||
|
||||
func (rw *BasicUi) Ask(query string) (string, error) {
|
||||
rw.l.Lock()
|
||||
defer rw.l.Unlock()
|
||||
|
||||
if rw.interrupted {
|
||||
return "", errors.New("interrupted")
|
||||
}
|
||||
|
||||
if rw.scanner == nil {
|
||||
rw.scanner = bufio.NewScanner(rw.Reader)
|
||||
}
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
|
||||
defer signal.Stop(sigCh)
|
||||
|
||||
logger.Info("ask", query)
|
||||
if query != "" {
|
||||
if _, err := fmt.Fprint(rw.Writer, query+" "); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
result := make(chan string, 1)
|
||||
go func() {
|
||||
var line string
|
||||
if rw.scanner.Scan() {
|
||||
line = rw.scanner.Text()
|
||||
}
|
||||
if err := rw.scanner.Err(); err != nil {
|
||||
logger.Error("scan failure", "error", err)
|
||||
return
|
||||
}
|
||||
result <- line
|
||||
}()
|
||||
|
||||
select {
|
||||
case line := <-result:
|
||||
return line, nil
|
||||
case <-sigCh:
|
||||
// Print a newline so that any further output starts properly
|
||||
// on a new line.
|
||||
fmt.Fprintln(rw.Writer)
|
||||
|
||||
// Mark that we were interrupted so future Ask calls fail.
|
||||
rw.interrupted = true
|
||||
|
||||
return "", errors.New("interrupted")
|
||||
}
|
||||
}
|
||||
|
||||
func (rw *BasicUi) Detail(message string) { rw.Say(message) }
|
||||
func (rw *BasicUi) Info(message string) { rw.Say(message) }
|
||||
func (rw *BasicUi) Output(message string) { rw.Say(message) }
|
||||
func (rw *BasicUi) Success(message string) { rw.Say(message) }
|
||||
func (rw *BasicUi) Warn(message string) { rw.Say(message) }
|
||||
|
||||
func (rw *BasicUi) Say(message string) {
|
||||
rw.Message(message, nil)
|
||||
}
|
||||
|
||||
func (rw *BasicUi) Message(message string, opts *Options) {
|
||||
rw.l.Lock()
|
||||
defer rw.l.Unlock()
|
||||
|
||||
if opts == nil {
|
||||
opts = &Options{Channel: UiOutput, NewLine: true}
|
||||
}
|
||||
|
||||
logger.Debug("write message", "content", message, "options", opts)
|
||||
target := rw.Writer
|
||||
if opts.Channel == UiError {
|
||||
if rw.ErrorWriter == nil {
|
||||
logger.Error("error writer unset using writer")
|
||||
} else {
|
||||
target = rw.ErrorWriter
|
||||
}
|
||||
}
|
||||
suffix := ""
|
||||
if opts.NewLine {
|
||||
suffix = "\n"
|
||||
}
|
||||
|
||||
_, err := fmt.Fprint(target, message+suffix)
|
||||
if err != nil {
|
||||
logger.Error("write failure", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (rw *BasicUi) Error(message string) {
|
||||
rw.Message(message, &Options{Channel: UiError, NewLine: true})
|
||||
}
|
||||
|
||||
func (rw *BasicUi) Machine(t string, args ...string) {
|
||||
logger.Info("machine readable", "category", t, "args", args)
|
||||
}
|
||||
|
||||
// MachineReadableUi is a UI that only outputs machine-readable output
|
||||
// to the given Writer.
|
||||
type MachineReadableUi struct {
|
||||
Writer io.Writer
|
||||
}
|
||||
|
||||
var _ Ui = new(MachineReadableUi)
|
||||
|
||||
func (u *MachineReadableUi) Ask(query string) (string, error) {
|
||||
return "", errors.New("machine-readable UI can't ask")
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Detail(message string) {
|
||||
u.Machine("ui", "detail", message)
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Info(message string) {
|
||||
u.Machine("ui", "info", message)
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Output(message string) {
|
||||
u.Machine("ui", "output", message)
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Success(message string) {
|
||||
u.Machine("ui", "success", message)
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Warn(message string) {
|
||||
u.Machine("ui", "warn", message)
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Say(message string) {
|
||||
u.Machine("ui", "say", message)
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Message(message string, opts *Options) {
|
||||
u.Machine("ui", "message", message)
|
||||
}
|
||||
|
||||
func (u *MachineReadableUi) Error(message string) {
|
||||
u.Machine("ui", "error", message)
|
||||
}
|
||||
|
||||
// TODO: Do we want to update this to match Vagrant machine style?
|
||||
func (u *MachineReadableUi) Machine(category string, args ...string) {
|
||||
now := time.Now().UTC()
|
||||
|
||||
// Determine if we have a target, and set it
|
||||
target := ""
|
||||
commaIdx := strings.Index(category, ",")
|
||||
if commaIdx > -1 {
|
||||
target = category[0:commaIdx]
|
||||
category = category[commaIdx+1:]
|
||||
}
|
||||
|
||||
// Prepare the args
|
||||
for i, v := range args {
|
||||
args[i] = strings.Replace(v, ",", "%!(VAGRANT_COMMA)", -1)
|
||||
args[i] = strings.Replace(args[i], "\r", "\\r", -1)
|
||||
args[i] = strings.Replace(args[i], "\n", "\\n", -1)
|
||||
}
|
||||
argsString := strings.Join(args, ",")
|
||||
|
||||
_, err := fmt.Fprintf(u.Writer, "%d,%s,%s,%s\n", now.Unix(), target, category, argsString)
|
||||
if err != nil {
|
||||
if err == syscall.EPIPE || strings.Contains(err.Error(), "broken pipe") {
|
||||
// Ignore epipe errors because that just means that the file
|
||||
// is probably closed or going to /dev/null or something.
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type NoopUi struct{}
|
||||
|
||||
var _ Ui = new(NoopUi)
|
||||
|
||||
func (*NoopUi) Ask(string) (string, error) { return "", errors.New("this is a noop ui") }
|
||||
func (*NoopUi) Detail(string) { return }
|
||||
func (*NoopUi) Info(string) { return }
|
||||
func (*NoopUi) Error(string) { return }
|
||||
func (*NoopUi) Machine(string, ...string) { return }
|
||||
func (*NoopUi) Message(string, *Options) { return }
|
||||
func (*NoopUi) Output(string) { return }
|
||||
func (*NoopUi) Say(string) { return }
|
||||
func (*NoopUi) Success(string) { return }
|
||||
func (*NoopUi) Warn(string) { return }
|
||||
|
||||
// ColoredUi is a UI that is colored using terminal colors.
|
||||
type ColoredUi struct {
|
||||
Color UiColor
|
||||
ErrorColor UiColor
|
||||
SuccessColor UiColor
|
||||
WarnColor UiColor
|
||||
Ui Ui
|
||||
}
|
||||
|
||||
var _ Ui = new(ColoredUi)
|
||||
|
||||
func (u *ColoredUi) Ask(query string) (string, error) {
|
||||
return u.Ui.Ask(u.colorize(query, u.Color, true))
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Detail(message string) {
|
||||
u.Say(message)
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Info(message string) {
|
||||
u.Say(message)
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Error(message string) {
|
||||
color := u.ErrorColor
|
||||
if color == 0 {
|
||||
color = UiColorRed
|
||||
}
|
||||
|
||||
u.Ui.Error(u.colorize(message, color, true))
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Machine(t string, args ...string) {
|
||||
// Don't colorize machine-readable output
|
||||
u.Ui.Machine(t, args...)
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Message(message string, opts *Options) {
|
||||
u.Ui.Message(u.colorize(message, u.Color, false), opts)
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Output(message string) {
|
||||
u.Say(message)
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Say(message string) {
|
||||
u.Ui.Say(u.colorize(message, u.Color, true))
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Success(message string) {
|
||||
u.Ui.Say(u.colorize(message, u.SuccessColor, true))
|
||||
}
|
||||
|
||||
func (u *ColoredUi) Warn(message string) {
|
||||
u.Ui.Say(u.colorize(message, u.WarnColor, true))
|
||||
}
|
||||
|
||||
func (u *ColoredUi) colorize(message string, color UiColor, bold bool) string {
|
||||
if !u.supportsColors() {
|
||||
return message
|
||||
}
|
||||
|
||||
attr := 0
|
||||
if bold {
|
||||
attr = 1
|
||||
}
|
||||
|
||||
return fmt.Sprintf("\033[%d;%dm%s\033[0m", attr, color, message)
|
||||
}
|
||||
|
||||
func (u *ColoredUi) supportsColors() bool {
|
||||
// Never use colors if we have this environmental variable
|
||||
if os.Getenv("VAGRANT_NO_COLOR") != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// For now, on non-Windows machine, just assume it does
|
||||
if runtime.GOOS != "windows" {
|
||||
return true
|
||||
}
|
||||
|
||||
// On Windows, if we appear to be in Cygwin, then it does
|
||||
cygwin := os.Getenv("CYGWIN") != "" ||
|
||||
os.Getenv("OSTYPE") == "cygwin" ||
|
||||
os.Getenv("TERM") == "cygwin"
|
||||
|
||||
return cygwin
|
||||
}
|
||||
|
||||
// TargetedUi is a UI that wraps another UI implementation and modifies
|
||||
// the output to indicate a specific target. Specifically, all Say output
|
||||
// is prefixed with the target name. Message output is not prefixed but
|
||||
// is offset by the length of the target so that output is lined up properly
|
||||
// with Say output. Machine-readable output has the proper target set.
|
||||
type TargetedUi struct {
|
||||
Target string
|
||||
Ui Ui
|
||||
}
|
||||
|
||||
var _ Ui = new(TargetedUi)
|
||||
|
||||
func (u *TargetedUi) Ask(query string) (string, error) {
|
||||
return u.Ui.Ask(u.prefixLines(true, query))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Detail(message string) {
|
||||
u.Ui.Detail(u.prefixLines(true, message))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Info(message string) {
|
||||
u.Ui.Info(u.prefixLines(true, message))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Output(message string) {
|
||||
u.Ui.Output(u.prefixLines(true, message))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Success(message string) {
|
||||
u.Ui.Success(u.prefixLines(true, message))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Warn(message string) {
|
||||
u.Ui.Warn(u.prefixLines(true, message))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Say(message string) {
|
||||
u.Ui.Say(u.prefixLines(true, message))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Message(message string, opts *Options) {
|
||||
u.Ui.Message(u.prefixLines(false, message), opts)
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Error(message string) {
|
||||
u.Ui.Error(u.prefixLines(true, message))
|
||||
}
|
||||
|
||||
func (u *TargetedUi) Machine(t string, args ...string) {
|
||||
// Prefix in the target, then pass through
|
||||
u.Ui.Machine(fmt.Sprintf("%s,%s", u.Target, t), args...)
|
||||
}
|
||||
|
||||
func (u *TargetedUi) prefixLines(arrow bool, message string) string {
|
||||
arrowText := "==>"
|
||||
if !arrow {
|
||||
arrowText = strings.Repeat(" ", len(arrowText))
|
||||
}
|
||||
|
||||
var result bytes.Buffer
|
||||
|
||||
for _, line := range strings.Split(message, "\n") {
|
||||
result.WriteString(fmt.Sprintf("%s %s: %s\n", arrowText, u.Target, line))
|
||||
}
|
||||
|
||||
return strings.TrimRightFunc(result.String(), unicode.IsSpace)
|
||||
}
|
||||
|
||||
// TimestampedUi is a UI that wraps another UI implementation and prefixes
|
||||
// prefixes each message with an RFC3339 timestamp
|
||||
type TimestampedUi struct {
|
||||
Ui Ui
|
||||
}
|
||||
|
||||
var _ Ui = new(TimestampedUi)
|
||||
|
||||
func (u *TimestampedUi) Ask(query string) (string, error) {
|
||||
return u.Ui.Ask(query)
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Detail(message string) {
|
||||
u.Ui.Detail(u.timestampLine(message))
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Info(message string) {
|
||||
u.Ui.Info(u.timestampLine(message))
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Output(message string) {
|
||||
u.Ui.Output(u.timestampLine(message))
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Success(message string) {
|
||||
u.Ui.Success(u.timestampLine(message))
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Warn(message string) {
|
||||
u.Ui.Warn(u.timestampLine(message))
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Say(message string) {
|
||||
u.Ui.Say(u.timestampLine(message))
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Message(message string, opts *Options) {
|
||||
u.Ui.Message(u.timestampLine(message), opts)
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Error(message string) {
|
||||
u.Ui.Error(u.timestampLine(message))
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) Machine(message string, args ...string) {
|
||||
u.Ui.Machine(message, args...)
|
||||
}
|
||||
|
||||
func (u *TimestampedUi) timestampLine(string string) string {
|
||||
return fmt.Sprintf("%v: %v", time.Now().Format(time.RFC3339), string)
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// This reads the output from the bytes.Buffer in our test object
|
||||
// and then resets the buffer.
|
||||
func readWriter(ui *BasicUi) (result string) {
|
||||
buffer := ui.Writer.(*bytes.Buffer)
|
||||
result = buffer.String()
|
||||
buffer.Reset()
|
||||
return
|
||||
}
|
||||
|
||||
// Reset the input Reader then add some input to it.
|
||||
func writeReader(ui *BasicUi, input string) {
|
||||
buffer := ui.Reader.(*bytes.Buffer)
|
||||
buffer.WriteString(input)
|
||||
}
|
||||
|
||||
func readErrorWriter(ui *BasicUi) (result string) {
|
||||
buffer := ui.ErrorWriter.(*bytes.Buffer)
|
||||
result = buffer.String()
|
||||
buffer.Reset()
|
||||
return
|
||||
}
|
||||
|
||||
func testUi() *BasicUi {
|
||||
return &BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
ErrorWriter: new(bytes.Buffer),
|
||||
}
|
||||
}
|
||||
|
||||
func TestColoredUi(t *testing.T) {
|
||||
bufferUi := testUi()
|
||||
ui := &ColoredUi{UiColorBlue, UiColorRed, UiColorGreen,
|
||||
UiColorYellow, bufferUi}
|
||||
|
||||
if !ui.supportsColors() {
|
||||
t.Skip("skipping for ui without color support")
|
||||
}
|
||||
|
||||
ui.Say("foo")
|
||||
result := readWriter(bufferUi)
|
||||
if result != "\033[1;34mfoo\033[0m\n" {
|
||||
t.Fatalf("invalid output: %s", result)
|
||||
}
|
||||
|
||||
ui.Message("foo", nil)
|
||||
result = readWriter(bufferUi)
|
||||
if result != "\033[0;34mfoo\033[0m\n" {
|
||||
t.Fatalf("invalid output: %s", result)
|
||||
}
|
||||
|
||||
ui.Error("foo")
|
||||
result = readWriter(bufferUi)
|
||||
if result != "" {
|
||||
t.Fatalf("invalid output: %s", result)
|
||||
}
|
||||
|
||||
result = readErrorWriter(bufferUi)
|
||||
if result != "\033[1;31mfoo\033[0m\n" {
|
||||
t.Fatalf("invalid output: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestColoredUi_noColorEnv(t *testing.T) {
|
||||
bufferUi := testUi()
|
||||
ui := &ColoredUi{UiColorBlue, UiColorRed, UiColorGreen,
|
||||
UiColorYellow, bufferUi}
|
||||
|
||||
// Set the env var to get rid of the color
|
||||
oldenv := os.Getenv("VAGRANT_NO_COLOR")
|
||||
os.Setenv("VAGRANT_NO_COLOR", "1")
|
||||
defer os.Setenv("VAGRANT_NO_COLOR", oldenv)
|
||||
|
||||
ui.Say("foo")
|
||||
result := readWriter(bufferUi)
|
||||
if result != "foo\n" {
|
||||
t.Fatalf("invalid output: %s", result)
|
||||
}
|
||||
|
||||
ui.Message("foo", nil)
|
||||
result = readWriter(bufferUi)
|
||||
if result != "foo\n" {
|
||||
t.Fatalf("invalid output: %s", result)
|
||||
}
|
||||
|
||||
ui.Error("foo")
|
||||
result = readErrorWriter(bufferUi)
|
||||
if result != "foo\n" {
|
||||
t.Fatalf("invalid output: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTargetedUi(t *testing.T) {
|
||||
bufferUi := testUi()
|
||||
targetedUi := &TargetedUi{
|
||||
Target: "foo",
|
||||
Ui: bufferUi,
|
||||
}
|
||||
|
||||
var actual, expected string
|
||||
targetedUi.Say("foo")
|
||||
actual = readWriter(bufferUi)
|
||||
expected = "==> foo: foo\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
|
||||
targetedUi.Message("foo", nil)
|
||||
actual = readWriter(bufferUi)
|
||||
expected = " foo: foo\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
|
||||
targetedUi.Error("bar")
|
||||
actual = readErrorWriter(bufferUi)
|
||||
expected = "==> foo: bar\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
|
||||
targetedUi.Say("foo\nbar")
|
||||
actual = readWriter(bufferUi)
|
||||
expected = "==> foo: foo\n==> foo: bar\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestColoredUi_ImplUi(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &ColoredUi{}
|
||||
if _, ok := raw.(Ui); !ok {
|
||||
t.Fatalf("ColoredUi must implement Ui")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTargetedUi_ImplUi(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &TargetedUi{}
|
||||
if _, ok := raw.(Ui); !ok {
|
||||
t.Fatalf("TargetedUi must implement Ui")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicUi_ImplUi(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &BasicUi{}
|
||||
if _, ok := raw.(Ui); !ok {
|
||||
t.Fatalf("BasicUi must implement Ui")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicUi_Error(t *testing.T) {
|
||||
bufferUi := testUi()
|
||||
|
||||
var actual, expected string
|
||||
bufferUi.Error("foo")
|
||||
actual = readErrorWriter(bufferUi)
|
||||
expected = "foo\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
|
||||
bufferUi.ErrorWriter = nil
|
||||
bufferUi.Error("5")
|
||||
actual = readWriter(bufferUi)
|
||||
expected = "5\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicUi_Say(t *testing.T) {
|
||||
bufferUi := testUi()
|
||||
|
||||
var actual, expected string
|
||||
|
||||
bufferUi.Say("foo")
|
||||
actual = readWriter(bufferUi)
|
||||
expected = "foo\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
|
||||
bufferUi.Say("5")
|
||||
actual = readWriter(bufferUi)
|
||||
expected = "5\n"
|
||||
if actual != expected {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicUi_Ask(t *testing.T) {
|
||||
|
||||
var actual, expected string
|
||||
var err error
|
||||
|
||||
var testCases = []struct {
|
||||
Prompt, Input, Answer string
|
||||
}{
|
||||
{"[c]ontinue or [a]bort", "c\n", "c"},
|
||||
{"[c]ontinue or [a]bort", "c", "c"},
|
||||
// Empty input shouldn't give an error
|
||||
{"Name", "Joe Bloggs\n", "Joe Bloggs"},
|
||||
{"Name", "Joe Bloggs", "Joe Bloggs"},
|
||||
{"Name", "\n", ""},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
// Because of the internal bufio we can't easily reset the input, so create a new one each time
|
||||
bufferUi := testUi()
|
||||
writeReader(bufferUi, testCase.Input)
|
||||
|
||||
actual, err = bufferUi.Ask(testCase.Prompt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if actual != testCase.Answer {
|
||||
t.Fatalf("bad answer: %#v", actual)
|
||||
}
|
||||
|
||||
actual = readWriter(bufferUi)
|
||||
expected = testCase.Prompt + " "
|
||||
if actual != expected {
|
||||
t.Fatalf("bad prompt: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMachineReadableUi_ImplUi(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &MachineReadableUi{}
|
||||
if _, ok := raw.(Ui); !ok {
|
||||
t.Fatalf("MachineReadableUi must implement Ui")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMachineReadableUi(t *testing.T) {
|
||||
var data, expected string
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
ui := &MachineReadableUi{Writer: buf}
|
||||
|
||||
// No target
|
||||
ui.Machine("foo", "bar", "baz")
|
||||
data = strings.SplitN(buf.String(), ",", 2)[1]
|
||||
expected = ",foo,bar,baz\n"
|
||||
if data != expected {
|
||||
t.Fatalf("bad: %s", data)
|
||||
}
|
||||
|
||||
// Target
|
||||
buf.Reset()
|
||||
ui.Machine("mitchellh,foo", "bar", "baz")
|
||||
data = strings.SplitN(buf.String(), ",", 2)[1]
|
||||
expected = "mitchellh,foo,bar,baz\n"
|
||||
if data != expected {
|
||||
t.Fatalf("bad: %s", data)
|
||||
}
|
||||
|
||||
// Commas
|
||||
buf.Reset()
|
||||
ui.Machine("foo", "foo,bar")
|
||||
data = strings.SplitN(buf.String(), ",", 2)[1]
|
||||
expected = ",foo,foo%!(VAGRANT_COMMA)bar\n"
|
||||
if data != expected {
|
||||
t.Fatalf("bad: %s", data)
|
||||
}
|
||||
|
||||
// New lines
|
||||
buf.Reset()
|
||||
ui.Machine("foo", "foo\n")
|
||||
data = strings.SplitN(buf.String(), ",", 2)[1]
|
||||
expected = ",foo,foo\\n\n"
|
||||
if data != expected {
|
||||
t.Fatalf("bad: %#v", data)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
require "log4r"
|
||||
require "log4r/logger"
|
||||
require "vagrant/util/credential_scrubber"
|
||||
# Update the default formatter within the log4r library to ensure
|
||||
# sensitive values are being properly scrubbed from logger data
|
||||
|
@ -53,6 +54,8 @@ if ENV["VAGRANT_LOG"] && ENV["VAGRANT_LOG"] != ""
|
|||
# rest-client to write using the `<<` operator.
|
||||
# See https://github.com/rest-client/rest-client/issues/34#issuecomment-290858
|
||||
# for more information
|
||||
Log4r::PatternFormatter::DirectiveTable["l"] =
|
||||
'"[" + ' + Log4r::PatternFormatter::DirectiveTable["l"] + ' + "]"'
|
||||
class VagrantLogger < Log4r::Logger
|
||||
def << (msg)
|
||||
debug(msg.strip)
|
||||
|
@ -61,13 +64,10 @@ if ENV["VAGRANT_LOG"] && ENV["VAGRANT_LOG"] != ""
|
|||
logger = VagrantLogger.new("vagrant")
|
||||
logger.outputters = Log4r::Outputter.stderr
|
||||
logger.level = level
|
||||
base_formatter = Log4r::BasicFormatter.new
|
||||
if ENV["VAGRANT_LOG_TIMESTAMP"]
|
||||
base_formatter = Log4r::PatternFormatter.new(
|
||||
pattern: "%d [%5l] %m",
|
||||
date_pattern: "%F %T"
|
||||
)
|
||||
end
|
||||
base_formatter = Log4r::PatternFormatter.new(
|
||||
pattern: "%d %-7l %C: %m",
|
||||
date_pattern: ENV["VAGRANT_LOG_TIMESTAMP"] ? "%FT%T.%L%z" : " "
|
||||
)
|
||||
# Vagrant Cloud gem uses RestClient to make HTTP requests, so
|
||||
# log them if debug is enabled and use Vagrants logger
|
||||
require 'rest_client'
|
||||
|
@ -118,6 +118,7 @@ module Vagrant
|
|||
autoload :Driver, 'vagrant/driver'
|
||||
autoload :Environment, 'vagrant/environment'
|
||||
autoload :Errors, 'vagrant/errors'
|
||||
autoload :GoPlugin, 'vagrant/go_plugin'
|
||||
autoload :Guest, 'vagrant/guest'
|
||||
autoload :Host, 'vagrant/host'
|
||||
autoload :Machine, 'vagrant/machine'
|
||||
|
|
|
@ -7,6 +7,10 @@ module Vagrant
|
|||
def method_missing(name, *args, &block)
|
||||
DummyConfig.new
|
||||
end
|
||||
|
||||
def to_json(*_)
|
||||
"null"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -112,6 +112,14 @@ module Vagrant
|
|||
@keys = state["keys"] if state.key?("keys")
|
||||
@missing_key_calls = state["missing_key_calls"] if state.key?("missing_key_calls")
|
||||
end
|
||||
|
||||
def to_json(*args)
|
||||
Hash[
|
||||
@keys.find_all { |k,v|
|
||||
!k.to_s.start_with?("_")
|
||||
}
|
||||
].to_json(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -175,6 +175,15 @@ module Vagrant
|
|||
# Load any global plugins
|
||||
Vagrant::Plugin::Manager.instance.load_plugins(plugins)
|
||||
|
||||
# Load any available go-plugins
|
||||
Util::Experimental.guard_with(:go_plugin) do
|
||||
begin
|
||||
Vagrant::GoPlugin::Manager.instance.globalize!
|
||||
rescue LoadError => err
|
||||
@logger.warn("go plugin support is not available: #{err}")
|
||||
end
|
||||
end
|
||||
|
||||
plugins = process_configured_plugins
|
||||
|
||||
# Call the hooks that does not require configurations to be loaded
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
module Vagrant
|
||||
module GoPlugin
|
||||
|
||||
# @return [String]
|
||||
INSTALL_DIRECTORY = Vagrant.user_data_path.join("go-plugins").to_s.freeze
|
||||
|
||||
autoload :CapabilityPlugin, "vagrant/go_plugin/capability_plugin"
|
||||
autoload :ConfigPlugin, "vagrant/go_plugin/config_plugin"
|
||||
autoload :Core, "vagrant/go_plugin/core"
|
||||
autoload :Interface, "vagrant/go_plugin/interface"
|
||||
autoload :Manager, "vagrant/go_plugin/manager"
|
||||
autoload :ProviderPlugin, "vagrant/go_plugin/provider_plugin"
|
||||
autoload :SyncedFolderPlugin, "vagrant/go_plugin/synced_folder_plugin"
|
||||
|
||||
# @return [Interface]
|
||||
def self.interface
|
||||
unless @_interface
|
||||
@_interface = Interface.new
|
||||
end
|
||||
@_interface
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,179 @@
|
|||
require "vagrant/go_plugin/core"
|
||||
|
||||
module Vagrant
|
||||
module GoPlugin
|
||||
# Contains all capability functionality for go-plugin
|
||||
module CapabilityPlugin
|
||||
# Wrapper class for go-plugin defined capabilities
|
||||
class Capability
|
||||
extend TypedGoPlugin
|
||||
end
|
||||
|
||||
# @return [Interface]
|
||||
def self.interface
|
||||
unless @_interface
|
||||
@_interface = Interface.new
|
||||
end
|
||||
@_interface
|
||||
end
|
||||
|
||||
# Capability interface to access go-plugin
|
||||
class Interface
|
||||
include GoPlugin::Core
|
||||
|
||||
typedef :string, :capability_args
|
||||
typedef :string, :capability_name
|
||||
typedef :string, :capability_platform
|
||||
typedef :string, :capability_provider
|
||||
|
||||
attach_function :_guest_capabilities, :GuestCapabilities,
|
||||
[:plugin_name, :plugin_type], :plugin_result
|
||||
attach_function :_guest_capability, :GuestCapability,
|
||||
[:plugin_name, :plugin_type, :capability_name, :capability_platform,
|
||||
:capability_args, :vagrant_machine], :plugin_result
|
||||
attach_function :_host_capabilities, :HostCapabilities,
|
||||
[:plugin_name, :plugin_type], :plugin_result
|
||||
attach_function :_host_capability, :HostCapability,
|
||||
[:plugin_name, :plugin_type, :capability_name, :capability_platform,
|
||||
:capability_args, :vagrant_environment], :plugin_result
|
||||
attach_function :_provider_capabilities, :ProviderCapabilities,
|
||||
[:plugin_name, :plugin_type], :plugin_result
|
||||
attach_function :_provider_capability, :ProviderCapability,
|
||||
[:plugin_name, :plugin_type, :capability_name, :capability_provider,
|
||||
:capability_args, :vagrant_machine], :plugin_result
|
||||
|
||||
# List of supported guest capabilities
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @return [Array<Hash>] List of guest capabilities
|
||||
def guest_capabilities(plugin_name, plugin_type)
|
||||
load_result { _guest_capabilities(plugin_name.to_s, plugin_type.to_s) }
|
||||
end
|
||||
|
||||
# Execute guest capability
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [String] cap_name Name of capability
|
||||
# @param [String] cap_plat Guest platform of capability
|
||||
# @param [Array<Object>] cap_args Arguments for the capability
|
||||
# @param [Vagrant::Machine] machine Guest machine
|
||||
def guest_capability(plugin_name, plugin_type, cap_name, cap_plat, cap_args, machine)
|
||||
load_result {
|
||||
_guest_capability(plugin_name.to_s, plugin_type.to_s, cap_name.to_s, cap_plat.to_s,
|
||||
JSON.dump(cap_args), dump_machine(machine))
|
||||
}
|
||||
end
|
||||
|
||||
# List of supported host capabilities
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @return [Array<Hash>] List of host capabilities
|
||||
def host_capabilities(plugin_name, plugin_type)
|
||||
load_result { _host_capabilities(plugin_name.to_s, plugin_type.to_s) }
|
||||
end
|
||||
|
||||
# Execute host capability
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [String] cap_name Name of capability
|
||||
# @param [String] cap_plat Host platform of capability
|
||||
# @param [Array<Object>] cap_args Arguments for the capability
|
||||
# @param [Vagrant::Environment] env Vagrant environment
|
||||
def host_capability(plugin_name, plugin_type, cap_name, cap_plat, cap_args, env)
|
||||
load_result {
|
||||
_host_capability(plugin_name.to_s, plugin_type.to_s, cap_name.to_s, cap_plat.to_s,
|
||||
JSON.dump(cap_args), dump_environment(env))
|
||||
}
|
||||
end
|
||||
|
||||
# List of supported provider capabilities
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @return [Array<Hash>] List of provider capabilities
|
||||
def provider_capabilities(plugin_name, plugin_type)
|
||||
load_result { _provider_capabilities(plugin_name.to_s, plugin_type.to_s) }
|
||||
end
|
||||
|
||||
# Execute provider capability
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [String] cap_name Name of capability
|
||||
# @param [String] cap_prov Provider of capability
|
||||
# @param [Array<Object>] cap_args Arguments for the capability
|
||||
# @param [Vagrant::Machine] machine Guest machine
|
||||
def provider_capability(plugin_name, plugin_type, cap_name, cap_prov, cap_args, machine)
|
||||
load_result {
|
||||
_provider_capability(plugin_name.to_s, plugin_type.to_s, cap_name.to_s, cap_prov.to_s,
|
||||
JSON.dump(cap_args), dump_machine(machine))
|
||||
}
|
||||
end
|
||||
|
||||
# Fetch any defined guest capabilites for given plugin and register
|
||||
# capabilities within given plugin class
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [Class] plugin_klass Plugin class to register capabilities
|
||||
def generate_guest_capabilities(plugin_name, plugin_type, plugin_klass)
|
||||
logger.debug("checking for guest capabilities in #{plugin_type} plugin #{plugin_name}")
|
||||
caps = guest_capabilities(plugin_name.to_s, plugin_type.to_s)
|
||||
return if !caps || caps.empty?
|
||||
logger.debug("guest capabilities support detected in #{plugin_type} plugin #{plugin_name}")
|
||||
caps.each do |cap|
|
||||
cap_klass = Class.new(Capability).tap do |k|
|
||||
k.class_eval("def self.#{k[:name]}(machine, *args){ CapabilityPlugin.interface.guest_capability(" \
|
||||
"plugin_name, plugin_type, '#{k[:name]}', '#{k[:platform]}', args, machine) }")
|
||||
end
|
||||
plugin_klass.guest_capability(k[:platform], k[:name])
|
||||
end
|
||||
end
|
||||
|
||||
# Fetch any defined host capabilites for given plugin and register
|
||||
# capabilities within given plugin class
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [Class] plugin_klass Plugin class to register capabilities
|
||||
def generate_host_capabilities(plugin_name, plugin_type, plugin_klass)
|
||||
logger.debug("checking for host capabilities in #{plugin_type} plugin #{plugin_name}")
|
||||
caps = host_capabilities(plugin_name.to_s, plugin_type.to_s)
|
||||
return if !caps || caps.empty?
|
||||
logger.debug("host capabilities support detected in #{plugin_type} plugin #{plugin_name}")
|
||||
caps.each do |cap|
|
||||
cap_klass = Class.new(Capability).tap do |k|
|
||||
k.class_eval("def self.#{k[:name]}(env, *args){ CapabilityPlugin.interface.host_capability(" \
|
||||
"plugin_name, plugin_type, '#{k[:name]}', '#{k[:platform]}', args, env) }")
|
||||
end
|
||||
plugin_klass.host_capability(k[:platform], k[:name])
|
||||
end
|
||||
end
|
||||
|
||||
# Fetch any defined provider capabilites for given plugin and register
|
||||
# capabilities within given plugin class
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [Class] plugin_klass Plugin class to register capabilities
|
||||
def generate_provider_capabilities(plugin_name, plugin_type, plugin_klass)
|
||||
logger.debug("checking for provider capabilities in #{plugin_type} plugin #{plugin_name}")
|
||||
caps = provider_capabilities(plugin_name.to_s, plugin_type.to_s)
|
||||
return if !caps || caps.empty?
|
||||
logger.debug("provider capabilities support detected in #{plugin_type} plugin #{plugin_name}")
|
||||
caps.each do |cap|
|
||||
cap_klass = Class.new(Capability).tap do |k|
|
||||
k.class_eval("def self.#{k[:name]}(machine, *args){ CapabilityPlugin.interface.provider_capability(" \
|
||||
"plugin_name, plugin_type, '#{k[:name]}', '#{k[:provider]}', args, machine) }")
|
||||
end
|
||||
plugin_klass.provider_capability(k[:provider], k[:name])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,133 @@
|
|||
require "vagrant/go_plugin/core"
|
||||
|
||||
module Vagrant
|
||||
module GoPlugin
|
||||
# Contains all configuration functionality for go-plugin
|
||||
module ConfigPlugin
|
||||
# Config plugin class used with go-plugin
|
||||
class Config < Vagrant.plugin("2", :config)
|
||||
include TypedGoPlugin
|
||||
|
||||
def finalize!
|
||||
data = local_data
|
||||
result = ConfigPlugin.interface.finalize(plugin_name, plugin_type, data)
|
||||
result.each do |key, value|
|
||||
next if data[key] == value
|
||||
instance_variable_set("@#{key}", value)
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
def validate(machine)
|
||||
ConfigPlugin.interface.validate(plugin_name, plugin_type, local_data, machine)
|
||||
end
|
||||
|
||||
# @return [Hash] currently defined instance variables
|
||||
def local_data
|
||||
data = Vagrant::Util::HashWithIndifferentAccess.
|
||||
new(instance_variables_hash)
|
||||
data.delete_if { |k,v|
|
||||
k.start_with?("_")
|
||||
}
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Interface]
|
||||
def self.interface
|
||||
unless @_interface
|
||||
@_interface = Interface.new
|
||||
end
|
||||
@_interface
|
||||
end
|
||||
|
||||
# Config interface to access go-plugin
|
||||
class Interface
|
||||
include GoPlugin::Core
|
||||
|
||||
typedef :string, :config_name
|
||||
typedef :string, :config_data
|
||||
typedef :string, :plugin_type
|
||||
|
||||
attach_function :_config_attributes, :ConfigAttributes,
|
||||
[:plugin_name, :plugin_type], :plugin_result
|
||||
attach_function :_config_load, :ConfigLoad,
|
||||
[:plugin_name, :plugin_type, :config_data], :plugin_result
|
||||
attach_function :_config_validate, :ConfigValidate,
|
||||
[:plugin_name, :plugin_type, :config_data, :vagrant_machine], :plugin_result
|
||||
attach_function :_config_finalize, :ConfigFinalize,
|
||||
[:plugin_name, :plugin_type, :config_data], :plugin_result
|
||||
|
||||
# List of all supported configuration attribute names
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @return [Array<String>] List of attribute names
|
||||
def attributes(plugin_name, plugin_type)
|
||||
load_result { _config_attributes(plugin_name, plugin_type.to_s) }
|
||||
end
|
||||
|
||||
# Load configuration data
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [Hash] data Configuration data
|
||||
# @return [Hash] Configuration data
|
||||
def load(plugin_name, plugin_type, data)
|
||||
load_result { _config_load(plugin_name, plugin_type, JSON.dump(data)) }
|
||||
end
|
||||
|
||||
# Validate configuration data
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [Hash] data Configuration data
|
||||
# @param [Vagrant::Machine] machine Guest machine
|
||||
# @return [Hash] Any validation errors
|
||||
def validate(plugin_name, plugin_type, data, machine)
|
||||
load_result { _config_validate(plugin_name, plugin_type, dump_config(data), dump_machine(machine)) }
|
||||
end
|
||||
|
||||
# Finalize the configuration data
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [Hash] data Configuration data
|
||||
# @return [Hash] Configuration data
|
||||
def finalize(plugin_name, plugin_type, data)
|
||||
load_result { _config_finalize(plugin_name, plugin_type, dump_config(data)) }
|
||||
end
|
||||
|
||||
# Serialize configuration data
|
||||
#
|
||||
# @param [Hash] d Configuration data
|
||||
# @return [String]
|
||||
def dump_config(d)
|
||||
JSON.dump(d)
|
||||
end
|
||||
|
||||
# Fetch any defined configuration support from the given plugin
|
||||
# and register it within the given plugin class
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] plugin_type Type of plugin
|
||||
# @param [Class] plugin_klass Plugin class to register configuration
|
||||
def generate_config(plugin_name, plugin_type, plugin_klass)
|
||||
logger.debug("checking for configuration support in #{plugin_type} plugin #{plugin_name}")
|
||||
cattrs = attributes(plugin_name, plugin_type)
|
||||
return nil if !cattrs || cattrs.empty?
|
||||
logger.debug("configuration support detected in #{plugin_type} plugin #{plugin_name}")
|
||||
config_klass = Class.new(Config)
|
||||
cattrs.each { |att|
|
||||
config_klass.instance_eval("attr_accessor :#{att}")
|
||||
}
|
||||
config_klass.go_plugin_name = plugin_name
|
||||
config_klass.go_plugin_type = plugin_type
|
||||
plugin_klass.config(plugin_name.to_sym, plugin_type.to_sym) do
|
||||
config_klass
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,198 @@
|
|||
require "ffi"
|
||||
|
||||
module Vagrant
|
||||
module GoPlugin
|
||||
# Base module for generic setup of module/class
|
||||
module Core
|
||||
# Loads FFI and core helpers into given module/class
|
||||
def self.included(const)
|
||||
const.class_eval do
|
||||
include Vagrant::Util::Logger
|
||||
extend FFI::Library
|
||||
|
||||
ffi_lib FFI::Platform::LIBC
|
||||
# TODO: Update this to include OS/ARCH details
|
||||
ffi_lib File.expand_path("./go-plugin.so", File.dirname(__FILE__))
|
||||
|
||||
typedef :string, :vagrant_environment
|
||||
typedef :string, :vagrant_machine
|
||||
typedef :string, :plugin_name
|
||||
typedef :string, :plugin_type
|
||||
typedef :strptr, :plugin_result
|
||||
|
||||
# stdlib functions
|
||||
if FFI::Platform.windows?
|
||||
attach_function :free, :_free, [:pointer], :void
|
||||
else
|
||||
attach_function :free, [:pointer], :void
|
||||
end
|
||||
|
||||
# Generate a Hash representation of the given machine
|
||||
# which can be serialized and sent to go-plugin
|
||||
#
|
||||
# @param [Vagrant::Machine] machine
|
||||
# @return [String] JSON serialized Hash
|
||||
def dump_machine(machine)
|
||||
if !machine.is_a?(Vagrant::Machine)
|
||||
raise TypeError,
|
||||
"Expected `Vagrant::Machine` but received `#{machine.class}`"
|
||||
end
|
||||
m = {
|
||||
box: {},
|
||||
config: machine.config,
|
||||
data_dir: machine.data_dir,
|
||||
environment: dump_environment(machine.env),
|
||||
id: machine.id,
|
||||
name: machine.name,
|
||||
provider_config: machine.provider_config,
|
||||
provider_name: machine.provider_name
|
||||
}
|
||||
if machine.box
|
||||
m[:box] = {
|
||||
name: machine.box.name,
|
||||
provider: machine.box.provider,
|
||||
version: machine.box.version,
|
||||
directory: machine.box.directory.to_s,
|
||||
metadata: machine.box.metadata,
|
||||
metadata_url: machine.box.metadata_url
|
||||
}
|
||||
end
|
||||
m.to_json
|
||||
end
|
||||
|
||||
# Generate a Hash representation of the given environment
|
||||
# which can be serialized and sent to a go-plugin
|
||||
#
|
||||
# @param [Vagrant::Environmment] environment
|
||||
# @return [Hash] Hash
|
||||
def dump_environment(environment)
|
||||
if !environment.is_a?(Vagrant::Environment)
|
||||
raise TypeError,
|
||||
"Expected `Vagrant::Environment` but received `#{environment.class}`"
|
||||
end
|
||||
e = {
|
||||
cwd: environment.cwd,
|
||||
data_dir: environment.data_dir,
|
||||
vagrantfile_name: environment.vagrantfile_name,
|
||||
home_path: environment.home_path,
|
||||
local_data_path: environment.local_data_path,
|
||||
tmp_path: environment.tmp_path,
|
||||
aliases_path: environment.aliases_path,
|
||||
boxes_path: environment.boxes_path,
|
||||
gems_path: environment.gems_path,
|
||||
default_private_key_path: environment.default_private_key_path,
|
||||
root_path: environment.root_path,
|
||||
primary_machine_name: environment.primary_machine_name,
|
||||
machine_names: environment.machine_names,
|
||||
active_machines: Hash[environment.active_machines]
|
||||
}
|
||||
end
|
||||
|
||||
# Load given data into the provided machine. This is
|
||||
# used to update the machine with data received from
|
||||
# go-plugins
|
||||
#
|
||||
# @param [Hash] data Machine data from go-plugin
|
||||
# @param [Vagrant::Machine] machine
|
||||
# @return [Vagrant::Machine]
|
||||
def load_machine(data, machine)
|
||||
machine
|
||||
end
|
||||
|
||||
# Load the result received from the extension. This will load
|
||||
# the JSON result, raise an error if detected, and properly
|
||||
# free the memory associated with the result.
|
||||
def load_result(*args)
|
||||
val, ptr = block_given? ? yield : args
|
||||
FFI::AutoPointer.new(ptr, self.method(:free))
|
||||
begin
|
||||
result = JSON.load(val)
|
||||
if !result.is_a?(Hash)
|
||||
raise TypeError.new "Expected Hash but received `#{result.class}`"
|
||||
end
|
||||
if !result["error"].to_s.empty?
|
||||
raise ArgumentError.new result["error"].to_s
|
||||
end
|
||||
result = result["result"]
|
||||
if result.is_a?(Hash)
|
||||
result = Vagrant::Util::HashWithIndifferentAccess.new(result)
|
||||
end
|
||||
result
|
||||
rescue => e
|
||||
# TODO: Customize to provide formatted output on error
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module DirectGoPlugin
|
||||
def self.included(klass)
|
||||
klass.extend(ClassMethods)
|
||||
klass.include(InstanceMethods)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
# @return [String] plugin name associated to this class
|
||||
def go_plugin_name
|
||||
@go_plugin_name
|
||||
end
|
||||
|
||||
def plugin_name
|
||||
go_plugin_name
|
||||
end
|
||||
|
||||
# Set the plugin name for this class
|
||||
#
|
||||
# @param [String] n plugin name
|
||||
# @return [String]
|
||||
# @note can only be set once
|
||||
def go_plugin_name=(n)
|
||||
if @go_plugin_name
|
||||
raise ArgumentError.new("Class plugin name has already been set")
|
||||
end
|
||||
@go_plugin_name = n
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def name
|
||||
go_plugin_name.to_s.capitalize.tr("_", "")
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def plugin_name
|
||||
self.class.go_plugin_name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module TypedGoPlugin
|
||||
def self.included(klass)
|
||||
klass.extend(ClassMethods)
|
||||
klass.include(InstanceMethods)
|
||||
klass.include(DirectGoPlugin)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def go_plugin_type
|
||||
@go_plugin_type
|
||||
end
|
||||
|
||||
def go_plugin_type=(t)
|
||||
if @go_plugin_type
|
||||
raise ArgumentError.new("Class plugin type has already been set")
|
||||
end
|
||||
@go_plugin_type = t.to_s
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
def plugin_type
|
||||
self.class.go_plugin_type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,72 @@
|
|||
require "log4r"
|
||||
require "vagrant/go_plugin/core"
|
||||
|
||||
module Vagrant
|
||||
module GoPlugin
|
||||
# Interface for go-plugin integration
|
||||
class Interface
|
||||
include Core
|
||||
|
||||
# go plugin functions
|
||||
typedef :bool, :enable_logger
|
||||
typedef :bool, :timestamps
|
||||
typedef :string, :log_level
|
||||
typedef :string, :plugin_directory
|
||||
|
||||
attach_function :_setup, :Setup, [:enable_logger, :timestamps, :log_level], :bool
|
||||
attach_function :_teardown, :Teardown, [], :void
|
||||
attach_function :_load_plugins, :LoadPlugins, [:plugin_directory], :bool
|
||||
|
||||
def initialize
|
||||
setup
|
||||
end
|
||||
|
||||
# Load any plugins found at the given directory
|
||||
#
|
||||
# @param [String, Pathname] path Directory to load
|
||||
def load_plugins(path)
|
||||
logger.debug("loading plugins from path: #{path}")
|
||||
if !File.directory?(path.to_s)
|
||||
raise ArgumentError, "Directory expected for plugin loading"
|
||||
end
|
||||
_load_plugins(path.to_s)
|
||||
end
|
||||
|
||||
# Register all available plugins
|
||||
def register_plugins
|
||||
logger.debug("registering provider plugins")
|
||||
ProviderPlugin.interface.load!
|
||||
logger.debug("registering synced folder plugins")
|
||||
SyncedFolderPlugin.interface.load!
|
||||
end
|
||||
|
||||
# Load the plugins found at the given directory
|
||||
#
|
||||
# @param [String] plugin_directory Directory containing go-plugins
|
||||
def setup
|
||||
if !@setup
|
||||
@setup = true
|
||||
Kernel.at_exit { Vagrant::GoPlugin.interface.teardown }
|
||||
logger.debug("running go-plugin interface setup")
|
||||
_setup(!Vagrant.log_level.to_s.empty?,
|
||||
!!ENV["VAGRANT_LOG_TIMESTAMP"],
|
||||
Vagrant.log_level.to_s)
|
||||
else
|
||||
logger.warn("go-plugin interface already setup")
|
||||
end
|
||||
end
|
||||
|
||||
# Teardown any plugins that may be currently active
|
||||
def teardown
|
||||
logger.debug("starting teardown of go-plugin interface")
|
||||
_teardown
|
||||
logger.debug("teardown of go-plugin interface complete")
|
||||
end
|
||||
|
||||
# @return [Boolean] go plugins have been setup
|
||||
def configured?
|
||||
!!@setup
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,88 @@
|
|||
require "zip"
|
||||
require "vagrant/plugin/state_file"
|
||||
|
||||
module Vagrant
|
||||
module GoPlugin
|
||||
class Manager
|
||||
include Util::Logger
|
||||
|
||||
# @return [Manager]
|
||||
def self.instance(env=nil)
|
||||
@instance ||= self.new
|
||||
if env
|
||||
@instance.envirnoment = env
|
||||
end
|
||||
@instance
|
||||
end
|
||||
|
||||
# @return [StateFile] user defined plugins
|
||||
attr_reader :user_file
|
||||
# @return [StateFile, nil] project local defined plugins
|
||||
attr_reader :local_file
|
||||
|
||||
def initialize
|
||||
FileUtils.mkdir_p(INSTALL_DIRECTORY)
|
||||
FileUtils.mkdir_p(Vagrant.user_data_path.join("tmp").to_s)
|
||||
@user_file = Plugin::StateFile.new(Vagrant.user_data_path.join("plugins.json"))
|
||||
end
|
||||
|
||||
# Load global plugins
|
||||
def globalize!
|
||||
Dir.glob(File.join(INSTALL_DIRECTORY, "*")).each do |entry|
|
||||
next if !File.directory?(entry)
|
||||
logger.debug("loading go plugins from directory: #{entry}")
|
||||
GoPlugin.interface.load_plugins(entry)
|
||||
end
|
||||
GoPlugin.interface.register_plugins
|
||||
end
|
||||
|
||||
# Load local plugins
|
||||
def localize!
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Install a go plugin
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [String] remote_source Location of plugin for download
|
||||
# @param [Hash] options Currently unused
|
||||
def install_plugin(plugin_name, remote_source, options={})
|
||||
install_dir = File.join(INSTALL_DIRECTORY, plugin_name)
|
||||
FileUtils.mkdir_p(install_dir)
|
||||
Dir.mktmpdir("go-plugin", Vagrant.user_data_path.join("tmp").to_s) do |dir|
|
||||
dest_file = File.join(dir, "plugin.zip")
|
||||
logger.debug("downloading go plugin #{plugin_name} from #{remote_source}")
|
||||
Util::Downloader.new(remote_source, dest_file).download!
|
||||
logger.debug("extracting go plugin #{plugin_name} from #{dest_file}")
|
||||
Zip::File.open(dest_file) do |zfile|
|
||||
zfile.each do |entry|
|
||||
install_path = File.join(install_dir, entry.name)
|
||||
if File.file?(install_path)
|
||||
logger.warn("removing existing plugin path for unpacking - #{install_path}")
|
||||
File.delete(install_path)
|
||||
end
|
||||
entry.extract(install_path)
|
||||
FileUtils.chmod(0755, install_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
user_file.add_go_plugin(plugin_name, source: remote_source)
|
||||
end
|
||||
|
||||
# Uninstall a go plugin
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [Hash] options Currently unused
|
||||
def uninstall_plugin(plugin_name, options={})
|
||||
plugin_path = File.join(INSTALL_DIRECTORY, plugin_name)
|
||||
if !File.directory?(plugin_path)
|
||||
logger.warn("Plugin directory does not exist for #{plugin_name} - #{plugin_path}")
|
||||
else
|
||||
logger.debug("deleting go plugin from path #{plugin_path}")
|
||||
FileUtils.rm_rf(plugin_path)
|
||||
end
|
||||
user_file.remove_go_plugin(plugin_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,341 @@
|
|||
require "vagrant/go_plugin/core"
|
||||
|
||||
module Vagrant
|
||||
module GoPlugin
|
||||
module ProviderPlugin
|
||||
# Helper class for wrapping actions in a go-plugin into
|
||||
# something which can be used by Vagrant::Action::Builder
|
||||
class Action
|
||||
# @return [String] provider name associated to this class
|
||||
def self.provider_name
|
||||
@provider_name
|
||||
end
|
||||
|
||||
# Set the provider name for this class
|
||||
#
|
||||
# @param [String] n provider name
|
||||
# @return [String]
|
||||
# @note can only be set once
|
||||
def self.provider_name=(n)
|
||||
if @provider_name
|
||||
raise ArgumentError.new("Class provider name has already been set")
|
||||
end
|
||||
@provider_name = n.to_s.dup.freeze
|
||||
end
|
||||
|
||||
# @return [String] action name associated to this class
|
||||
def self.action_name
|
||||
@action_name
|
||||
end
|
||||
|
||||
# Set the action name for this class
|
||||
#
|
||||
# @param [String] n action name
|
||||
# @return [String]
|
||||
# @note can only be set once
|
||||
def self.action_name=(n)
|
||||
if @action_name
|
||||
raise ArgumentError.new("Class action name has already been set")
|
||||
end
|
||||
@action_name = n.to_s.dup.freeze
|
||||
end
|
||||
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env_data = env_dump(env)
|
||||
result = VagrantGoPlugin._provider_run_action(
|
||||
self.class.go_plugin_name, self.class.go_action_name,
|
||||
env_data, env[:machine].environment.dump)
|
||||
result.each_pair do |k, v|
|
||||
env[k] = v
|
||||
end
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
# Helper class used to provide a wrapper around a go-plugin
|
||||
# provider so that it can be interacted with normally within
|
||||
# Vagrant
|
||||
class Provider < Vagrant.plugin("2", :provider)
|
||||
# @return [Vagrant::Machine]
|
||||
attr_reader :machine
|
||||
|
||||
# @return [String] plugin name associated to this class
|
||||
def self.go_plugin_name
|
||||
@go_plugin_name
|
||||
end
|
||||
|
||||
# Set the plugin name for this class
|
||||
#
|
||||
# @param [String] n plugin name
|
||||
# @return [String]
|
||||
# @note can only be set once
|
||||
def self.go_plugin_name=(n)
|
||||
if @go_plugin_name
|
||||
raise ArgumentError.new("Class plugin name has already been set")
|
||||
end
|
||||
@go_plugin_name = n
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def self.name
|
||||
go_plugin_name.to_s.capitalize.tr("_", "")
|
||||
end
|
||||
|
||||
def initialize(machine)
|
||||
@machine = machine
|
||||
end
|
||||
|
||||
# @return [String] name of the provider plugin for this class
|
||||
def provider_name
|
||||
self.class.go_plugin_name
|
||||
end
|
||||
|
||||
# Get callable action by name
|
||||
#
|
||||
# @param [Symbol] name name of the action
|
||||
# @return [Class] callable action class
|
||||
def action(name)
|
||||
ProviderPlugin.interface.action(provider_name, name.to_s, machine)
|
||||
end
|
||||
|
||||
# Execute capability with given name
|
||||
#
|
||||
# @param [Symbol] name Name of the capability
|
||||
# @return [Object]
|
||||
def capability(name, *args)
|
||||
args = args.map do |arg|
|
||||
arg.response_to(:to_json) ? arg.to_json : arg.to_s
|
||||
end
|
||||
result = ProviderPlugin.interface.capability(provider_name, args.to_json, machine)
|
||||
begin
|
||||
JSON.load(result)
|
||||
rescue
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Boolean] provider is installed
|
||||
def is_installed?
|
||||
ProviderPlugin.interface.is_installed(provider_name, machine)
|
||||
end
|
||||
|
||||
# @return [Boolean] provider is usable
|
||||
def is_usable?
|
||||
ProviderPlugin.interface.is_usable(provider_name, machine)
|
||||
end
|
||||
|
||||
# @return [nil]
|
||||
def machine_id_changed
|
||||
ProviderPlugin.interface.machine_id_changed(provider_name, machine)
|
||||
nil
|
||||
end
|
||||
|
||||
# @return [Hash] SSH information
|
||||
def ssh_info
|
||||
ProviderPlugin.interface.ssh_info(provider_name, machine)
|
||||
end
|
||||
|
||||
# @return [Vagrant::MachineState]
|
||||
def state
|
||||
ProviderPlugin.interface.state(provider_name, machine)
|
||||
end
|
||||
end
|
||||
|
||||
def self.interface
|
||||
unless @_interface
|
||||
@_interface = Interface.new
|
||||
end
|
||||
@_interface
|
||||
end
|
||||
|
||||
class Interface
|
||||
include GoPlugin::Core
|
||||
|
||||
typedef :string, :action_name
|
||||
typedef :string, :action_data
|
||||
typedef :string, :capability_name
|
||||
typedef :string, :capability_data
|
||||
typedef :string, :provider_name
|
||||
|
||||
# provider plugin functions
|
||||
attach_function :_provider_action, :ProviderAction,
|
||||
[:provider_name, :action_name, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_provider_capability, :ProviderCapability,
|
||||
[:provider_name, :capability_name, :capability_data, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_provider_is_installed, :ProviderIsInstalled,
|
||||
[:provider_name, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_provider_is_usable, :ProviderIsUsable,
|
||||
[:provider_name, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_provider_machine_id_changed, :ProviderMachineIdChanged,
|
||||
[:provider_name, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_provider_run_action, :ProviderRunAction,
|
||||
[:provider_name, :action_name, :action_data, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_provider_ssh_info, :ProviderSshInfo,
|
||||
[:provider_name, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_provider_state, :ProviderState,
|
||||
[:provider_name, :vagrant_machine], :plugin_result
|
||||
|
||||
attach_function :_list_providers, :ListProviders, [], :plugin_result
|
||||
|
||||
# List of provider plugins currently available
|
||||
#
|
||||
# @return [Array<String>]
|
||||
def list_providers
|
||||
result, ptr = _list_providers
|
||||
load_result(result, ptr) || []
|
||||
end
|
||||
|
||||
# Get callable action from a provider plugin
|
||||
#
|
||||
# @param [String] provider_name provider name for action
|
||||
# @param [String] action_name name of requested action
|
||||
# @param [Vagrant::Machine] machine instance of guest
|
||||
# @return [Action]
|
||||
def action(provider_name, action_name, machine)
|
||||
result = load_result { _provider_action(provider_name,
|
||||
action_name, dump_machine(machine)) }
|
||||
klasses = result.map do |klass_name|
|
||||
if klass_name.start_with?("self::")
|
||||
action_name = klass_name.split("::", 2).last
|
||||
klass = Class.new(Action)
|
||||
klass.go_provider_name = provider_name
|
||||
klass.go_action_name = action_name
|
||||
klass.class_eval do
|
||||
def self.name
|
||||
"#{provider_name.capitalize}#{action_name.capitalize}".tr("_", "")
|
||||
end
|
||||
end
|
||||
klass
|
||||
else
|
||||
klass_name.split("::").inject(Object) do |memo, const|
|
||||
if memo.const_defined?(const)
|
||||
memo.const_get(const)
|
||||
else
|
||||
raise NameError.new "Unknown action class `#{klass_name}`"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Vagrant::Action::Builder.new.tap do |builder|
|
||||
klasses.each do |action_class|
|
||||
builder.use action_class
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def capability
|
||||
end
|
||||
|
||||
# Check if provider has requested capability
|
||||
#
|
||||
# @param [String] provider_name provider name for request
|
||||
# @param [String] capability_name name of the capability
|
||||
# @param [Vagrant::Machine] machine instance of guest
|
||||
# @return [Boolean]
|
||||
def has_capability(provider_name, capability_name, machine)
|
||||
result = load_result { _provider_has_capability(provider_name,
|
||||
capability_name, dump_machine(machine)) }
|
||||
result
|
||||
end
|
||||
|
||||
# Check if provider is installed
|
||||
#
|
||||
# @param [String] provider_name provider name for request
|
||||
# @param [Vagrant::Machine] machine instance of guest
|
||||
# @return [Boolean]
|
||||
def is_installed(provider_name, machine)
|
||||
result = load_result { _provider_is_installed(provider_name,
|
||||
dump_machine(machine)) }
|
||||
result
|
||||
end
|
||||
|
||||
# Check if provider is usable
|
||||
#
|
||||
# @param [String] provider_name provider name for request
|
||||
# @param [Vagrant::Machine] machine instance of guest
|
||||
# @return [Boolean]
|
||||
def is_usable(provider_name, machine)
|
||||
result = load_result { _provider_is_usable(provider_name,
|
||||
dump_machine(machine)) }
|
||||
result
|
||||
end
|
||||
|
||||
# Called when the ID of a machine has changed
|
||||
#
|
||||
# @param [String] provider_name provider name for request
|
||||
# @param [Vagrant::Machine] machine instance of guest
|
||||
def machine_id_changed(provider_name, machine)
|
||||
load_result { _provider_machine_id_changed(provider_name, dump_machine(machine)) }
|
||||
end
|
||||
|
||||
# Get SSH info for guest
|
||||
#
|
||||
# @param [String] provider_name provider name for request
|
||||
# @param [Vagrant::Machine] machine instance of guest
|
||||
# @return [Hash] SSH information
|
||||
def ssh_info(provider_name, machine)
|
||||
load_result { _provider_ssh_info(provider_name, dump_machine(machine)) }
|
||||
end
|
||||
|
||||
# Get state of machine
|
||||
#
|
||||
# @param [String] provider_name provider name for request
|
||||
# @param [Vagrant::Machine] machine instance of guest
|
||||
# @return [Vagrant::MachineState]
|
||||
def state(provider_name, machine)
|
||||
result = load_result { _provider_state(provider_name, dump_machine(machine)) }
|
||||
Vagrant::MachineState.new(result[:id],
|
||||
result[:short_description], result[:long_description])
|
||||
end
|
||||
|
||||
# Load any detected provider plugins
|
||||
def load!
|
||||
if !@loaded
|
||||
@loaded = true
|
||||
logger.debug("provider go-plugins have not been loaded... loading")
|
||||
list_providers.each do |p_name, p_details|
|
||||
logger.debug("loading go-plugin provider #{p_name}. details - #{p_details}")
|
||||
# Create new provider class wrapper
|
||||
provider_klass = Class.new(Provider)
|
||||
provider_klass.go_plugin_name = p_name
|
||||
# Create new plugin to register the provider
|
||||
plugin_klass = Class.new(Vagrant.plugin("2"))
|
||||
# Define the plugin
|
||||
plugin_klass.class_eval do
|
||||
name "#{p_name} Provider"
|
||||
description p_details[:description]
|
||||
end
|
||||
# Register the provider
|
||||
plugin_klass.provider(p_name.to_sym, priority: p_details.fetch(:priority, 0)) do
|
||||
provider_klass
|
||||
end
|
||||
# Register any configuration support
|
||||
ConfigPlugin.interface.generate_config(p_name, :provider, plugin_klass)
|
||||
# Register any guest capabilities
|
||||
CapabilityPlugin.interface.generate_guest_capabilities(p_name, :provider, plugin_klass)
|
||||
# Register any host capabilities
|
||||
CapabilityPlugin.interface.generate_host_capabilities(p_name, :provider, plugin_klass)
|
||||
# Register any provider capabilities
|
||||
CapabilityPlugin.interface.generate_provider_capabilities(p_name, :provider, plugin_klass)
|
||||
logger.debug("completed loading provider go-plugin #{p_name}")
|
||||
logger.info("loaded go-plugin provider - #{p_name}")
|
||||
end
|
||||
else
|
||||
logger.warn("provider go-plugins have already been loaded. ignoring load request.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,170 @@
|
|||
require "vagrant/go_plugin/core"
|
||||
|
||||
module Vagrant
|
||||
module GoPlugin
|
||||
# Contains all synced folder functionality for go-plugin
|
||||
module SyncedFolderPlugin
|
||||
|
||||
# Helper class used to provide a wrapper around a go-plugin
|
||||
# synced folder so that it can be interacted with normally
|
||||
# within Vagrant
|
||||
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
|
||||
include DirectGoPlugin
|
||||
|
||||
# Cleanup synced folders
|
||||
#
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @param [Hash] opts Folder options
|
||||
def cleanup(machine, opts)
|
||||
SyncedFolderPlugin.interface.cleanup(plugin_name, machine, opts)
|
||||
end
|
||||
|
||||
# Disable synced folders
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @param [Hash] folders Folders to enable
|
||||
# @param [Hash] opts Folder options
|
||||
def disable(machine, folder, opts)
|
||||
SyncedFolderPlugin.interface.disable(plugin_name, machine, folder, opts)
|
||||
end
|
||||
|
||||
# Enable synced folders
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @param [Hash] folders Folders to enable
|
||||
# @param [Hash] opts Folder options
|
||||
def enable(machine, folder, opts)
|
||||
SyncedFolderPlugin.interface.enable(plugin_name, machine, folder, opts)
|
||||
end
|
||||
|
||||
# Check if plugin is usable
|
||||
#
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @return [Boolean]
|
||||
def usable?(machine, raise_error=false)
|
||||
SyncedFolderPlugin.interface.usable?(plugin_name, machine)
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Interface]
|
||||
def self.interface
|
||||
unless @_interface
|
||||
@_interface = Interface.new
|
||||
end
|
||||
@_interface
|
||||
end
|
||||
|
||||
# Synced folder interface to go-plugin
|
||||
class Interface
|
||||
include GoPlugin::Core
|
||||
|
||||
typedef :string, :folders
|
||||
typedef :string, :folder_options
|
||||
|
||||
# synced folder plugin functions
|
||||
attach_function :_cleanup, :SyncedFolderCleanup,
|
||||
[:plugin_name, :vagrant_machine, :folder_options], :plugin_result
|
||||
attach_function :_disable, :SyncedFolderDisable,
|
||||
[:plugin_name, :vagrant_machine, :folders, :folder_options], :plugin_result
|
||||
attach_function :_enable, :SyncedFolderEnable,
|
||||
[:plugin_name, :vagrant_machine, :folders, :folder_options], :plugin_result
|
||||
attach_function :_list_synced_folders, :ListSyncedFolders,
|
||||
[], :plugin_result
|
||||
attach_function :_usable, :SyncedFolderIsUsable,
|
||||
[:plugin_name, :vagrant_machine], :plugin_result
|
||||
|
||||
# Cleanup synced folders
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @param [Hash] opts Folder options
|
||||
def cleanup(plugin_name, machine, opts)
|
||||
load_result {
|
||||
_cleanup(plugin_name, dump_machine(machine), JSON.dump(opts))
|
||||
}
|
||||
end
|
||||
|
||||
# Disable synced folders
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @param [Hash] folders Folders to enable
|
||||
# @param [Hash] opts Folder options
|
||||
def disable(plugin_name, machine, folders, opts)
|
||||
load_result {
|
||||
_disable(plugin_name, dump_machine(machine),
|
||||
JSON.dump(folders), JSON.dump(opts))
|
||||
}
|
||||
end
|
||||
|
||||
# Enable synced folders
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @param [Hash] folders Folders to enable
|
||||
# @param [Hash] opts Folder options
|
||||
def enable(plugin_name, machine, folders, opts)
|
||||
load_result {
|
||||
_enable(plugin_name, dump_machine(machine),
|
||||
JSON.dump(folders), JSON.dump(opts))
|
||||
}
|
||||
end
|
||||
|
||||
# List of available synced folder plugins
|
||||
#
|
||||
# @return [Array]
|
||||
def list_synced_folders
|
||||
load_result { _list_synced_folders }
|
||||
end
|
||||
|
||||
# Check if plugin is usable
|
||||
#
|
||||
# @param [String] plugin_name Name of plugin
|
||||
# @param [Vagrant::Machine] machine Vagrant guest
|
||||
# @return [Boolean]
|
||||
def usable?(plugin_name, machine)
|
||||
load_result {
|
||||
_usable(plugin_name, dump_machine(machine))
|
||||
}
|
||||
end
|
||||
|
||||
# Load any detected synced folder plugins
|
||||
def load!
|
||||
if !@loaded
|
||||
@loaded = true
|
||||
logger.debug("synced folder go-plugins have not been loaded... loading")
|
||||
list_synced_folders.each do |f_name, f_details|
|
||||
logger.debug("loading go-plugin synced folder #{f_name}. details - #{f_details}")
|
||||
# Create new synced folder class wrapper
|
||||
folder_klass = Class.new(SyncedFolder)
|
||||
folder_klass.go_plugin_name = f_name
|
||||
# Create new plugin to register the synced folder
|
||||
plugin_klass = Class.new(Vagrant.plugin("2"))
|
||||
# Define the plugin
|
||||
plugin_klass.class_eval do
|
||||
name "#{f_name} Synced Folder"
|
||||
description f_details[:description]
|
||||
end
|
||||
# Register the synced folder
|
||||
plugin_klass.synced_folder(f_name.to_sym, f_details.fetch(:priority, 10)) do
|
||||
folder_klass
|
||||
end
|
||||
# Register any guest capabilities
|
||||
CapabilityPlugin.interface.generate_guest_capabilities(f_name, :synced_folder, plugin_klass)
|
||||
# Register any host capabilities
|
||||
CapabilityPlugin.interface.generate_host_capabilities(f_name, :synced_folder, plugin_klass)
|
||||
# Register any provider capabilities
|
||||
CapabilityPlugin.interface.generate_provider_capabilities(f_name, :synced_folder, plugin_klass)
|
||||
logger.debug("completed loading synced folder go-plugin #{f_name}")
|
||||
logger.info("loaded go-plugin synced folder - #{f_name}")
|
||||
end
|
||||
else
|
||||
logger.warn("synced folder go-plugins have already been loaded. ignoring load request.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -24,17 +24,53 @@ module Vagrant
|
|||
end
|
||||
|
||||
upgrade_v0! if !@data["version"]
|
||||
upgrade_v1! if @data["version"].to_s == "1"
|
||||
end
|
||||
|
||||
@data["version"] ||= "1"
|
||||
@data["installed"] ||= {}
|
||||
@data["version"] ||= "2"
|
||||
@data["ruby"] ||= {"installed" => {}}
|
||||
@data["go_plugin"] ||= {}
|
||||
end
|
||||
|
||||
# Add a go plugin that is installed to the state file.
|
||||
#
|
||||
# @param [String] name The name of the plugin
|
||||
def add_go_plugin(name, **opts)
|
||||
@data["go_plugin"][name] = {
|
||||
"source" => opts[:source]
|
||||
}
|
||||
|
||||
save!
|
||||
end
|
||||
|
||||
# Remove a plugin that is installed from the state file.
|
||||
#
|
||||
# @param [String] name The name of the plugin
|
||||
def remove_go_plugin(name)
|
||||
@data["go_plugin"].delete(name)
|
||||
|
||||
save!
|
||||
end
|
||||
|
||||
# @return [Boolean] go plugin is present in this state file
|
||||
def has_go_plugin?(name)
|
||||
@data["go_plugin"].key?(name)
|
||||
end
|
||||
|
||||
# This returns a hash of installed go plugins according to the state
|
||||
# file. Note that this may _not_ directly match over to actually
|
||||
# installed plugins.
|
||||
#
|
||||
# @return [Hash]
|
||||
def installed_go_plugins
|
||||
@data["go_plugin"]
|
||||
end
|
||||
|
||||
# Add a plugin that is installed to the state file.
|
||||
#
|
||||
# @param [String] name The name of the plugin
|
||||
def add_plugin(name, **opts)
|
||||
@data["installed"][name] = {
|
||||
@data["ruby"]["installed"][name] = {
|
||||
"ruby_version" => RUBY_VERSION,
|
||||
"vagrant_version" => Vagrant::VERSION,
|
||||
"gem_version" => opts[:version] || "",
|
||||
|
@ -51,8 +87,8 @@ module Vagrant
|
|||
#
|
||||
# @param [String] url URL of the source.
|
||||
def add_source(url)
|
||||
@data["sources"] ||= []
|
||||
@data["sources"] << url if !@data["sources"].include?(url)
|
||||
@data["ruby"]["sources"] ||= []
|
||||
@data["ruby"]["sources"] |= [url]
|
||||
save!
|
||||
end
|
||||
|
||||
|
@ -62,21 +98,21 @@ module Vagrant
|
|||
#
|
||||
# @return [Hash]
|
||||
def installed_plugins
|
||||
@data["installed"]
|
||||
@data["ruby"]["installed"]
|
||||
end
|
||||
|
||||
# Returns true/false if the plugin is present in this state file.
|
||||
#
|
||||
# @return [Boolean]
|
||||
def has_plugin?(name)
|
||||
@data["installed"].key?(name)
|
||||
@data["ruby"]["installed"].key?(name)
|
||||
end
|
||||
|
||||
# Remove a plugin that is installed from the state file.
|
||||
#
|
||||
# @param [String] name The name of the plugin.
|
||||
def remove_plugin(name)
|
||||
@data["installed"].delete(name)
|
||||
@data["ruby"]["installed"].delete(name)
|
||||
save!
|
||||
end
|
||||
|
||||
|
@ -84,8 +120,8 @@ module Vagrant
|
|||
#
|
||||
# @param [String] url URL of the source
|
||||
def remove_source(url)
|
||||
@data["sources"] ||= []
|
||||
@data["sources"].delete(url)
|
||||
@data["ruby"]["sources"] ||= []
|
||||
@data["ruby"]["sources"].delete(url)
|
||||
save!
|
||||
end
|
||||
|
||||
|
@ -94,7 +130,7 @@ module Vagrant
|
|||
#
|
||||
# @return [Array<String>]
|
||||
def sources
|
||||
@data["sources"] || []
|
||||
@data["ruby"]["sources"] || []
|
||||
end
|
||||
|
||||
# This saves the state back into the state file.
|
||||
|
@ -128,6 +164,18 @@ module Vagrant
|
|||
|
||||
save!
|
||||
end
|
||||
|
||||
# This upgrades the internal data representation from V1 to V2
|
||||
def upgrade_v1!
|
||||
@data.delete("version")
|
||||
new_data = {
|
||||
"version" => "2",
|
||||
"ruby" => @data,
|
||||
"go_plugin" => {}
|
||||
}
|
||||
|
||||
save!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,6 +9,7 @@ module Vagrant
|
|||
autoload :Env, 'vagrant/util/env'
|
||||
autoload :HashWithIndifferentAccess, 'vagrant/util/hash_with_indifferent_access'
|
||||
autoload :GuestInspection, 'vagrant/util/guest_inspection'
|
||||
autoload :Logger, 'vagrant/util/logger'
|
||||
autoload :LoggingFormatter, 'vagrant/util/logging_formatter'
|
||||
autoload :Platform, 'vagrant/util/platform'
|
||||
autoload :Retryable, 'vagrant/util/retryable'
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
require "log4r"
|
||||
|
||||
module Vagrant
|
||||
module Util
|
||||
# Adds a logger method which provides automatically
|
||||
# namespaced logger instance
|
||||
module Logger
|
||||
|
||||
# @return [Log4r::Logger]
|
||||
def logger
|
||||
if !@_logger
|
||||
@_logger = Log4r::Logger.new(self.class.name.downcase)
|
||||
end
|
||||
@_logger
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -74,6 +74,23 @@ module VagrantPlugins
|
|||
autoload :RepairPluginsLocal, action_root.join("repair_plugins")
|
||||
autoload :UninstallPlugin, action_root.join("uninstall_plugin")
|
||||
autoload :UpdateGems, action_root.join("update_gems")
|
||||
|
||||
Vagrant::Util::Experimental.guard_with(:go_plugin) do
|
||||
autoload :UninstallGoPlugin, action_root.join("uninstall_go_plugin")
|
||||
autoload :InstallGoPlugin, action_root.join("install_go_plugin")
|
||||
|
||||
def self.action_go_install
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use InstallGoPlugin
|
||||
end
|
||||
end
|
||||
|
||||
def self.action_go_uninstall
|
||||
Vagrant::Action::Builder.new.tap do |b|
|
||||
b.use UninstallGoPlugin
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
require "log4r"
|
||||
require "vagrant/go_plugin/manager"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPlugin
|
||||
module Action
|
||||
class InstallGoPlugin
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
@logger = Log4r::Logger.new("vagrant::plugins::plugincommand::installgoplugin")
|
||||
end
|
||||
|
||||
def call(env)
|
||||
plugin_name = env[:plugin_name]
|
||||
plugin_source = env[:plugin_source]
|
||||
|
||||
manager = Vagrant::GoPlugin::Manager.instance
|
||||
|
||||
env[:ui].info(I18n.t("vagrant.commands.plugin.installing",
|
||||
name: plugin_name))
|
||||
|
||||
manager.install_plugin(plugin_name, plugin_source)
|
||||
|
||||
# Tell the user
|
||||
env[:ui].success(I18n.t("vagrant.commands.plugin.installed",
|
||||
name: plugin_name,
|
||||
version: plugin_source))
|
||||
|
||||
# Continue
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
module VagrantPlugins
|
||||
module CommandPlugin
|
||||
module Action
|
||||
class UninstallGoPlugin
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
# Remove it!
|
||||
env[:ui].info(I18n.t("vagrant.commands.plugin.uninstalling",
|
||||
name: env[:plugin_name]))
|
||||
|
||||
manager = Vagrant::GoPlugin::Manager.instance
|
||||
manager.uninstall_plugin(env[:plugin_name])
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
require 'optparse'
|
||||
|
||||
require_relative "base"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPlugin
|
||||
module Command
|
||||
class GoInstall < Base
|
||||
|
||||
def execute
|
||||
options = { verbose: false }
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant plugin goinstall <name> <source>"
|
||||
o.separator ""
|
||||
|
||||
o.on("--verbose", "Enable verbose output for plugin installation") do |v|
|
||||
options[:verbose] = v
|
||||
end
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
if argv.length != 2
|
||||
raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp
|
||||
end
|
||||
|
||||
plugin_name, plugin_source = argv
|
||||
|
||||
action(Action.action_go_install,
|
||||
plugin_name: plugin_name,
|
||||
plugin_source: plugin_source
|
||||
)
|
||||
|
||||
# Success, exit status 0
|
||||
0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
require 'optparse'
|
||||
|
||||
require_relative "base"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPlugin
|
||||
module Command
|
||||
class GoUninstall < Base
|
||||
def execute
|
||||
options = {}
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant plugin gouninstall <name> [<name2> <name3> ...] [-h]"
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp if argv.length < 1
|
||||
|
||||
# Uninstall the plugins
|
||||
argv.each do |entry|
|
||||
action(Action.action_go_uninstall, plugin_name: entry)
|
||||
end
|
||||
|
||||
# Success, exit status 0
|
||||
0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -48,6 +48,18 @@ module VagrantPlugins
|
|||
require_relative "uninstall"
|
||||
Uninstall
|
||||
end
|
||||
|
||||
Vagrant::Util::Experimental.guard_with(:go_plugin) do
|
||||
@subcommands.register(:goinstall) do
|
||||
require_relative "go_install"
|
||||
GoInstall
|
||||
end
|
||||
|
||||
@subcommands.register(:gouninstall) do
|
||||
require_relative "go_uninstall"
|
||||
GoUninstall
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def execute
|
||||
|
|
|
@ -13,6 +13,7 @@ Gem::Specification.new do |s|
|
|||
s.description = "Vagrant is a tool for building and distributing virtualized development environments."
|
||||
|
||||
s.required_ruby_version = "~> 2.2", "< 2.7"
|
||||
|
||||
s.required_rubygems_version = ">= 1.3.6"
|
||||
s.rubyforge_project = "vagrant"
|
||||
|
||||
|
@ -49,6 +50,7 @@ Gem::Specification.new do |s|
|
|||
s.add_development_dependency "rspec-its", "~> 1.2.0"
|
||||
s.add_development_dependency "webmock", "~> 2.3.1"
|
||||
s.add_development_dependency "fake_ftp", "~> 0.1.1"
|
||||
s.add_development_dependency "rake-compiler"
|
||||
|
||||
# The following block of code determines the files that should be included
|
||||
# in the gem. It does this by reading all the files in the directory where
|
||||
|
|
|
@ -54,3 +54,7 @@ Enabling this feature allows all provisioners to specify `before` and `after`
|
|||
options. These options allow provisioners to be configured to run before or after
|
||||
any given "root" provisioner. more information about these options can be found
|
||||
on the [base provisioner documentation page](/docs/provisioning/basic_usage.html)
|
||||
|
||||
### `go_plugin`
|
||||
|
||||
Enabling this feature turns on support for [go-plugin](https://github.com/hashicorp/go-plugin) based plugin for Vagrant.
|
||||
|
|
Loading…
Reference in New Issue