Adding test coverage
This commit is contained in:
parent
8aa0fd9445
commit
9499553706
|
@ -11,168 +11,148 @@ import (
|
||||||
|
|
||||||
//export GuestCapabilities
|
//export GuestCapabilities
|
||||||
func GuestCapabilities(pluginName, pluginType *C.char) *C.char {
|
func GuestCapabilities(pluginName, pluginType *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getGuestCapsPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
|
}
|
||||||
|
p, ok := i.(*plugin.RemoteGuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.GuestCapabilities.GuestCapabilities()
|
r.Result, r.Error = p.GuestCapabilities.GuestCapabilities()
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export GuestCapability
|
//export GuestCapability
|
||||||
func GuestCapability(pluginName, pluginType, cname, cplatform, cargs, cmachine *C.char) *C.char {
|
func GuestCapability(pluginName, pluginType, cname, cplatform, cargs, cmachine *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getGuestCapsPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
machine, err := vagrant.LoadMachine(C.GoString(cmachine), nil)
|
p, ok := i.(*plugin.RemoteGuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("Failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
machine, err := vagrant.LoadMachine(to_gs(cmachine), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var args interface{}
|
var args interface{}
|
||||||
err = json.Unmarshal([]byte(C.GoString(cargs)), &args)
|
err = json.Unmarshal([]byte(to_gs(cargs)), &args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
cap := &vagrant.SystemCapability{
|
cap := &vagrant.SystemCapability{
|
||||||
Name: C.GoString(cname),
|
Name: to_gs(cname),
|
||||||
Platform: C.GoString(cplatform)}
|
Platform: to_gs(cplatform)}
|
||||||
r.Result, r.Error = p.GuestCapabilities.GuestCapability(cap, args, machine)
|
r.Result, r.Error = p.GuestCapabilities.GuestCapability(cap, args, machine)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export HostCapabilities
|
//export HostCapabilities
|
||||||
func HostCapabilities(pluginName, pluginType *C.char) *C.char {
|
func HostCapabilities(pluginName, pluginType *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getHostCapsPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
p, ok := i.(*plugin.RemoteHostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("Failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
|
||||||
r.Result, r.Error = p.HostCapabilities.HostCapabilities()
|
r.Result, r.Error = p.HostCapabilities.HostCapabilities()
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export HostCapability
|
//export HostCapability
|
||||||
func HostCapability(pluginName, pluginType, cname, cplatform, cargs, cenv *C.char) *C.char {
|
func HostCapability(pluginName, pluginType, cname, cplatform, cargs, cenv *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getHostCapsPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
env, err := vagrant.LoadEnvironment(C.GoString(cenv), nil)
|
p, ok := i.(*plugin.RemoteHostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("Failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
|
||||||
|
env, err := vagrant.LoadEnvironment(to_gs(cenv), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var args interface{}
|
var args interface{}
|
||||||
err = json.Unmarshal([]byte(C.GoString(cargs)), &args)
|
err = json.Unmarshal([]byte(to_gs(cargs)), &args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
cap := &vagrant.SystemCapability{
|
cap := &vagrant.SystemCapability{
|
||||||
Name: C.GoString(cname),
|
Name: to_gs(cname),
|
||||||
Platform: C.GoString(cplatform)}
|
Platform: to_gs(cplatform)}
|
||||||
r.Result, r.Error = p.HostCapabilities.HostCapability(cap, args, env)
|
r.Result, r.Error = p.HostCapabilities.HostCapability(cap, args, env)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderCapabilities
|
//export ProviderCapabilities
|
||||||
func ProviderCapabilities(pluginName, pluginType *C.char) *C.char {
|
func ProviderCapabilities(pluginName, pluginType *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getProviderCapsPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
p, ok := i.(*plugin.RemoteProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("Failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
|
||||||
r.Result, r.Error = p.ProviderCapabilities.ProviderCapabilities()
|
r.Result, r.Error = p.ProviderCapabilities.ProviderCapabilities()
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderCapability
|
//export ProviderCapability
|
||||||
func ProviderCapability(pluginName, pluginType, cname, cprovider, cargs, cmach *C.char) *C.char {
|
func ProviderCapability(pluginName, pluginType, cname, cprovider, cargs, cmach *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getProviderCapsPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
m, err := vagrant.LoadMachine(C.GoString(cmach), nil)
|
p, ok := i.(*plugin.RemoteProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("Failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := vagrant.LoadMachine(to_gs(cmach), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var args interface{}
|
var args interface{}
|
||||||
err = json.Unmarshal([]byte(C.GoString(cargs)), &args)
|
err = json.Unmarshal([]byte(to_gs(cargs)), &args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
cap := &vagrant.ProviderCapability{
|
cap := &vagrant.ProviderCapability{
|
||||||
Name: C.GoString(cname),
|
Name: to_gs(cname),
|
||||||
Provider: C.GoString(cprovider)}
|
Provider: to_gs(cprovider)}
|
||||||
r.Result, r.Error = p.ProviderCapabilities.ProviderCapability(cap, args, m)
|
r.Result, r.Error = p.ProviderCapabilities.ProviderCapability(cap, args, m)
|
||||||
return C.CString(r.Dump())
|
return 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,414 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
vplugin "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCapabilities_GuestCapabilities(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.GuestCapabilitiesPlugin{Impl: &vplugin.MockGuestCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.GuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteGuestCapabilities{
|
||||||
|
GuestCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := GuestCapabilities(nil, nil)
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
caps, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap, ok := caps[0].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", caps[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if cap["name"] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", cap["name"])
|
||||||
|
}
|
||||||
|
if cap["platform"] != "testOS" {
|
||||||
|
t.Errorf("%s != testOS", cap["platform"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_GuestCapability(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.GuestCapabilitiesPlugin{Impl: &vplugin.MockGuestCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.GuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteGuestCapabilities{
|
||||||
|
GuestCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := json.Marshal([]string{"test_arg", "other_arg"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
args := string(a)
|
||||||
|
result := GuestCapability(nil, nil, to_cs("test_cap"), to_cs("test_platform"), to_cs(args), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", r[0])
|
||||||
|
}
|
||||||
|
if r[1] != "test_arg" {
|
||||||
|
t.Errorf("%s != test_arg", r[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_GuestCapability_noargs(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.GuestCapabilitiesPlugin{Impl: &vplugin.MockGuestCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.GuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteGuestCapabilities{
|
||||||
|
GuestCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := GuestCapability(nil, nil, to_cs("test_cap"), to_cs("test_platform"), to_cs("null"), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s - %s", err, to_gs(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r) != 1 {
|
||||||
|
t.Errorf("%d != 1", len(r))
|
||||||
|
}
|
||||||
|
if r[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", r[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_HostCapabilities(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.HostCapabilitiesPlugin{Impl: &vplugin.MockHostCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.HostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteHostCapabilities{
|
||||||
|
HostCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := HostCapabilities(nil, nil)
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
caps, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap, ok := caps[0].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", caps[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if cap["name"] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", cap["name"])
|
||||||
|
}
|
||||||
|
if cap["platform"] != "testOS" {
|
||||||
|
t.Errorf("%s != testOS", cap["platform"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_HostCapability(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.HostCapabilitiesPlugin{Impl: &vplugin.MockHostCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.HostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteHostCapabilities{
|
||||||
|
HostCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := json.Marshal([]string{"test_arg", "other_arg"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
args := string(a)
|
||||||
|
result := HostCapability(nil, nil, to_cs("test_cap"), to_cs("test_platform"), to_cs(args), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", r[0])
|
||||||
|
}
|
||||||
|
if r[1] != "test_arg" {
|
||||||
|
t.Errorf("%s != test_arg", r[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_HostCapability_noargs(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.HostCapabilitiesPlugin{Impl: &vplugin.MockHostCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.HostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteHostCapabilities{
|
||||||
|
HostCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := HostCapability(nil, nil, to_cs("test_cap"), to_cs("test_platform"), to_cs("null"), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s - %s", err, to_gs(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r) != 1 {
|
||||||
|
t.Errorf("%d != 1", len(r))
|
||||||
|
}
|
||||||
|
if r[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", r[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_ProviderCapabilities(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.ProviderCapabilitiesPlugin{Impl: &vplugin.MockProviderCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.ProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProviderCapabilities{
|
||||||
|
ProviderCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderCapabilities(nil, nil)
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
caps, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap, ok := caps[0].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", caps[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if cap["name"] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", cap["name"])
|
||||||
|
}
|
||||||
|
if cap["provider"] != "testProvider" {
|
||||||
|
t.Errorf("%s != testProvider", cap["provider"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_ProviderCapability(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.ProviderCapabilitiesPlugin{Impl: &vplugin.MockProviderCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.ProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProviderCapabilities{
|
||||||
|
ProviderCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := json.Marshal([]string{"test_arg", "other_arg"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
args := string(a)
|
||||||
|
result := ProviderCapability(nil, nil, to_cs("test_cap"), to_cs("test_provider"), to_cs(args), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", r[0])
|
||||||
|
}
|
||||||
|
if r[1] != "test_arg" {
|
||||||
|
t.Errorf("%s != test_arg", r[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_ProviderCapability_noargs(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &vplugin.ProviderCapabilitiesPlugin{Impl: &vplugin.MockProviderCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.ProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProviderCapabilities{
|
||||||
|
ProviderCapabilities: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderCapability(nil, nil, to_cs("test_cap"), to_cs("test_provider"), to_cs("null"), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s - %s", err, to_gs(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r) != 1 {
|
||||||
|
t.Errorf("%d != 1", len(r))
|
||||||
|
}
|
||||||
|
if r[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", r[0])
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"C"
|
"C"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||||
|
@ -12,87 +11,87 @@ import (
|
||||||
|
|
||||||
//export ConfigLoad
|
//export ConfigLoad
|
||||||
func ConfigLoad(pluginName, pluginType, data *C.char) *C.char {
|
func ConfigLoad(pluginName, pluginType, data *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getConfigPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
|
}
|
||||||
|
p, ok := i.(*plugin.RemoteConfig)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var cdata map[string]interface{}
|
var cdata map[string]interface{}
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(data)), &cdata)
|
r.Error = json.Unmarshal([]byte(to_gs(data)), &cdata)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.Config.ConfigLoad(cdata)
|
r.Result, r.Error = p.Config.ConfigLoad(cdata)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ConfigAttributes
|
//export ConfigAttributes
|
||||||
func ConfigAttributes(pluginName, pluginType *C.char) *C.char {
|
func ConfigAttributes(pluginName, pluginType *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getConfigPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
|
}
|
||||||
|
p, ok := i.(*plugin.RemoteConfig)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.Config.ConfigAttributes()
|
r.Result, r.Error = p.Config.ConfigAttributes()
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ConfigValidate
|
//export ConfigValidate
|
||||||
func ConfigValidate(pluginName, pluginType, data, machData *C.char) *C.char {
|
func ConfigValidate(pluginName, pluginType, data, machData *C.char) *C.char {
|
||||||
var m *vagrant.Machine
|
var m *vagrant.Machine
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getConfigPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
|
}
|
||||||
|
p, ok := i.(*plugin.RemoteConfig)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var cdata map[string]interface{}
|
var cdata map[string]interface{}
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(data)), &cdata)
|
r.Error = json.Unmarshal([]byte(to_gs(data)), &cdata)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
m, r.Error = vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.Config.ConfigValidate(cdata, m)
|
r.Result, r.Error = p.Config.ConfigValidate(cdata, m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ConfigFinalize
|
//export ConfigFinalize
|
||||||
func ConfigFinalize(pluginName, pluginType, data *C.char) *C.char {
|
func ConfigFinalize(pluginName, pluginType, data *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getConfigPlugin(pluginName, pluginType)
|
i, err := Plugins.PluginLookup(to_gs(pluginName), to_gs(pluginType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
|
}
|
||||||
|
p, ok := i.(*plugin.RemoteConfig)
|
||||||
|
if !ok {
|
||||||
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var cdata map[string]interface{}
|
var cdata map[string]interface{}
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(data)), &cdata)
|
r.Error = json.Unmarshal([]byte(to_gs(data)), &cdata)
|
||||||
if r.Error == nil {
|
if r.Error == nil {
|
||||||
println("FINALIZE HAS VALID CONFIG")
|
|
||||||
r.Result, r.Error = p.Config.ConfigFinalize(cdata)
|
r.Result, r.Error = p.Config.ConfigFinalize(cdata)
|
||||||
}
|
}
|
||||||
fmt.Printf("Full result: %s\n", r.Dump())
|
return 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,203 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
vplugin "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfig_Load(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"config": &vplugin.ConfigPlugin{Impl: &vplugin.MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("config")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteConfig{
|
||||||
|
Config: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]string{"test_key": "custom_val"}
|
||||||
|
s, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ConfigLoad(nil, nil, to_cs(string(s)))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
config, ok := resp.Result.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config["test_key"] != "test_val" {
|
||||||
|
t.Errorf("%s != test_val", config["test_key"])
|
||||||
|
}
|
||||||
|
if config["sent_key"] != "custom_val" {
|
||||||
|
t.Errorf("%s != custom_val", config["sent_key"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_Attributes(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"config": &vplugin.ConfigPlugin{Impl: &vplugin.MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("config")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteConfig{
|
||||||
|
Config: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ConfigAttributes(nil, nil)
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
attrs, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(attrs) != 2 {
|
||||||
|
t.Fatalf("%d != 2", len(attrs))
|
||||||
|
}
|
||||||
|
if attrs[0] != "fubar" {
|
||||||
|
t.Errorf("%s != fubar", attrs[0])
|
||||||
|
}
|
||||||
|
if attrs[1] != "foobar" {
|
||||||
|
t.Errorf("%s != foobar", attrs[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_Validate(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"config": &vplugin.ConfigPlugin{Impl: &vplugin.MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("config")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteConfig{
|
||||||
|
Config: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]string{"test_key": "custom_val"}
|
||||||
|
s, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ConfigValidate(nil, nil, to_cs(string(s)), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
errs, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) != 1 {
|
||||||
|
t.Fatalf("%d != 1", len(errs))
|
||||||
|
}
|
||||||
|
if errs[0] != "test error" {
|
||||||
|
t.Errorf("%s != test error", errs[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfig_Finalize(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"config": &vplugin.ConfigPlugin{Impl: &vplugin.MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("config")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteConfig{
|
||||||
|
Config: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]string{"test_key": "custom_val"}
|
||||||
|
s, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ConfigFinalize(nil, nil, to_cs(string(s)))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
config, ok := resp.Result.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if config["test_key"] != "custom_val-updated" {
|
||||||
|
t.Errorf("%s != custom_val-updated", config["test_key"])
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ var Plugins *plugin.VagrantPlugin
|
||||||
|
|
||||||
//export Setup
|
//export Setup
|
||||||
func Setup(enableLogger, timestamps bool, logLevel *C.char) bool {
|
func Setup(enableLogger, timestamps bool, logLevel *C.char) bool {
|
||||||
lvl := C.GoString(logLevel)
|
lvl := to_gs(logLevel)
|
||||||
lopts := &hclog.LoggerOptions{Name: "vagrant"}
|
lopts := &hclog.LoggerOptions{Name: "vagrant"}
|
||||||
if enableLogger {
|
if enableLogger {
|
||||||
lopts.Output = os.Stderr
|
lopts.Output = os.Stderr
|
||||||
|
@ -32,10 +32,7 @@ func Setup(enableLogger, timestamps bool, logLevel *C.char) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugins = &plugin.VagrantPlugin{
|
Plugins = plugin.VagrantPluginInit()
|
||||||
PluginDirectories: []string{},
|
|
||||||
Providers: map[string]*plugin.RemoteProvider{},
|
|
||||||
Logger: vagrant.DefaultLogger().Named("go-plugin")}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +43,7 @@ func LoadPlugins(plgpath *C.char) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
p := C.GoString(plgpath)
|
p := to_gs(plgpath)
|
||||||
err := Plugins.LoadPlugins(p)
|
err := Plugins.LoadPlugins(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Plugins.Logger.Error("failed loading plugins",
|
Plugins.Logger.Error("failed loading plugins",
|
||||||
|
@ -86,3 +83,13 @@ func Teardown() {
|
||||||
|
|
||||||
// stub required for build
|
// stub required for build
|
||||||
func main() {}
|
func main() {}
|
||||||
|
|
||||||
|
// helper to convert c string to go string
|
||||||
|
func to_gs(s *C.char) string {
|
||||||
|
return C.GoString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper to convert go string to c string
|
||||||
|
func to_cs(s string) *C.char {
|
||||||
|
return C.CString(s)
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"C"
|
"C"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||||
|
@ -13,169 +12,176 @@ import (
|
||||||
//export ListProviders
|
//export ListProviders
|
||||||
func ListProviders() *C.char {
|
func ListProviders() *C.char {
|
||||||
list := map[string]interface{}{}
|
list := map[string]interface{}{}
|
||||||
r := vagrant.Response{Result: list}
|
r := &Response{Result: list}
|
||||||
if Plugins == nil {
|
if Plugins == nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
for n, p := range Plugins.Providers {
|
for n, p := range Plugins.Providers {
|
||||||
list[n] = p.Provider.Info()
|
list[n] = p.Provider.Info()
|
||||||
}
|
}
|
||||||
r.Result = list
|
r.Result = list
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderAction
|
//export ProviderAction
|
||||||
func ProviderAction(providerName *C.char, actionName *C.char, machData *C.char) *C.char {
|
func ProviderAction(providerName *C.char, actionName *C.char, machData *C.char) *C.char {
|
||||||
var p *plugin.RemoteProvider
|
r := &Response{}
|
||||||
var m *vagrant.Machine
|
i, err := Plugins.PluginLookup(to_gs(providerName), "provider")
|
||||||
|
if err != nil {
|
||||||
r := vagrant.Response{}
|
r.Error = err
|
||||||
p, r.Error = getProvider(providerName)
|
return r.Dump()
|
||||||
if r.Error != nil {
|
|
||||||
return C.CString(r.Dump())
|
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
p, ok := i.(*plugin.RemoteProvider)
|
||||||
if r.Error != nil {
|
if !ok {
|
||||||
return C.CString(r.Dump())
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
aName := C.GoString(actionName)
|
m, err := vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
aName := to_gs(actionName)
|
||||||
r.Result, r.Error = p.Provider.Action(aName, m)
|
r.Result, r.Error = p.Provider.Action(aName, m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderIsInstalled
|
//export ProviderIsInstalled
|
||||||
func ProviderIsInstalled(providerName *C.char, machData *C.char) *C.char {
|
func ProviderIsInstalled(providerName *C.char, machData *C.char) *C.char {
|
||||||
var p *plugin.RemoteProvider
|
r := &Response{}
|
||||||
var m *vagrant.Machine
|
i, err := Plugins.PluginLookup(to_gs(providerName), "provider")
|
||||||
|
if err != nil {
|
||||||
r := vagrant.Response{}
|
r.Error = err
|
||||||
p, r.Error = getProvider(providerName)
|
return r.Dump()
|
||||||
if r.Error != nil {
|
|
||||||
return C.CString(r.Dump())
|
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
p, ok := i.(*plugin.RemoteProvider)
|
||||||
if r.Error != nil {
|
if !ok {
|
||||||
return C.CString(r.Dump())
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
m, err := vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.Provider.IsInstalled(m)
|
r.Result, r.Error = p.Provider.IsInstalled(m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderIsUsable
|
//export ProviderIsUsable
|
||||||
func ProviderIsUsable(providerName *C.char, machData *C.char) *C.char {
|
func ProviderIsUsable(providerName *C.char, machData *C.char) *C.char {
|
||||||
var p *plugin.RemoteProvider
|
r := &Response{}
|
||||||
var m *vagrant.Machine
|
i, err := Plugins.PluginLookup(to_gs(providerName), "provider")
|
||||||
|
if err != nil {
|
||||||
r := vagrant.Response{}
|
r.Error = err
|
||||||
p, r.Error = getProvider(providerName)
|
return r.Dump()
|
||||||
if r.Error != nil {
|
|
||||||
return C.CString(r.Dump())
|
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
p, ok := i.(*plugin.RemoteProvider)
|
||||||
if r.Error != nil {
|
if !ok {
|
||||||
return C.CString(r.Dump())
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.Provider.IsUsable(m)
|
r.Result, r.Error = p.Provider.IsUsable(m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderMachineIdChanged
|
//export ProviderMachineIdChanged
|
||||||
func ProviderMachineIdChanged(providerName *C.char, machData *C.char) *C.char {
|
func ProviderMachineIdChanged(providerName *C.char, machData *C.char) *C.char {
|
||||||
var p *plugin.RemoteProvider
|
r := &Response{}
|
||||||
var m *vagrant.Machine
|
i, err := Plugins.PluginLookup(to_gs(providerName), "provider")
|
||||||
|
if err != nil {
|
||||||
r := vagrant.Response{}
|
r.Error = err
|
||||||
p, r.Error = getProvider(providerName)
|
return r.Dump()
|
||||||
if r.Error != nil {
|
|
||||||
return C.CString(r.Dump())
|
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
p, ok := i.(*plugin.RemoteProvider)
|
||||||
if r.Error != nil {
|
if !ok {
|
||||||
return C.CString(r.Dump())
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
m, err := vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Error = p.Provider.MachineIdChanged(m)
|
r.Error = p.Provider.MachineIdChanged(m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderRunAction
|
//export ProviderRunAction
|
||||||
func ProviderRunAction(providerName *C.char, actName *C.char, runData *C.char, machData *C.char) *C.char {
|
func ProviderRunAction(providerName *C.char, actName *C.char, runData *C.char, machData *C.char) *C.char {
|
||||||
var p *plugin.RemoteProvider
|
r := &Response{}
|
||||||
var m *vagrant.Machine
|
i, err := Plugins.PluginLookup(to_gs(providerName), "provider")
|
||||||
|
if err != nil {
|
||||||
r := vagrant.Response{}
|
r.Error = err
|
||||||
p, r.Error = getProvider(providerName)
|
return r.Dump()
|
||||||
if r.Error != nil {
|
|
||||||
return C.CString(r.Dump())
|
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
p, ok := i.(*plugin.RemoteProvider)
|
||||||
if r.Error != nil {
|
if !ok {
|
||||||
return C.CString(r.Dump())
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
m, err := vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
aName := to_gs(actName)
|
||||||
|
var rData interface{}
|
||||||
|
err = json.Unmarshal([]byte(to_gs(runData)), &rData)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
aName := C.GoString(actName)
|
|
||||||
rData := C.GoString(runData)
|
|
||||||
r.Result, r.Error = p.Provider.RunAction(aName, rData, m)
|
r.Result, r.Error = p.Provider.RunAction(aName, rData, m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderSshInfo
|
//export ProviderSshInfo
|
||||||
func ProviderSshInfo(providerName *C.char, machData *C.char) *C.char {
|
func ProviderSshInfo(providerName *C.char, machData *C.char) *C.char {
|
||||||
var p *plugin.RemoteProvider
|
r := &Response{}
|
||||||
var m *vagrant.Machine
|
i, err := Plugins.PluginLookup(to_gs(providerName), "provider")
|
||||||
|
if err != nil {
|
||||||
r := vagrant.Response{}
|
r.Error = err
|
||||||
p, r.Error = getProvider(providerName)
|
return r.Dump()
|
||||||
if r.Error != nil {
|
|
||||||
return C.CString(r.Dump())
|
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
p, ok := i.(*plugin.RemoteProvider)
|
||||||
if r.Error != nil {
|
if !ok {
|
||||||
return C.CString(r.Dump())
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
m, err := vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.Provider.SshInfo(m)
|
r.Result, r.Error = p.Provider.SshInfo(m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export ProviderState
|
//export ProviderState
|
||||||
func ProviderState(providerName *C.char, machData *C.char) *C.char {
|
func ProviderState(providerName *C.char, machData *C.char) *C.char {
|
||||||
var p *plugin.RemoteProvider
|
r := &Response{}
|
||||||
var m *vagrant.Machine
|
i, err := Plugins.PluginLookup(to_gs(providerName), "provider")
|
||||||
|
if err != nil {
|
||||||
r := vagrant.Response{}
|
r.Error = err
|
||||||
p, r.Error = getProvider(providerName)
|
return r.Dump()
|
||||||
if r.Error != nil {
|
|
||||||
return C.CString(r.Dump())
|
|
||||||
}
|
}
|
||||||
m, r.Error = vagrant.LoadMachine(C.GoString(machData), nil)
|
p, ok := i.(*plugin.RemoteProvider)
|
||||||
if r.Error != nil {
|
if !ok {
|
||||||
return C.CString(r.Dump())
|
r.Error = errors.New("failed to load requested plugin")
|
||||||
|
return r.Dump()
|
||||||
|
}
|
||||||
|
m, err := vagrant.LoadMachine(to_gs(machData), nil)
|
||||||
|
if err != nil {
|
||||||
|
r.Error = err
|
||||||
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.Provider.State(m)
|
r.Result, r.Error = p.Provider.State(m)
|
||||||
return C.CString(r.Dump())
|
return 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,320 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
vplugin "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProvider_ListProviders(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.Providers[impl.Name()] = p
|
||||||
|
|
||||||
|
result := ListProviders()
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r["mock_provider"] == nil {
|
||||||
|
t.Fatalf("bad result")
|
||||||
|
}
|
||||||
|
|
||||||
|
i, ok := r["mock_provider"].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", r["mock_provider"])
|
||||||
|
}
|
||||||
|
|
||||||
|
if i["description"] != "Custom" {
|
||||||
|
t.Errorf("%s != Custom", i["description"])
|
||||||
|
}
|
||||||
|
if i["priority"] != 10.0 {
|
||||||
|
t.Errorf("%d != 10", i["priority"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_ProviderAction(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderAction(nil, to_cs("valid"), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
r := resp.Result.([]interface{})
|
||||||
|
if r[0] != "self::DoTask" {
|
||||||
|
t.Errorf("%s != self::DoTask", r[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_ProviderIsInstalled(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderIsInstalled(nil, to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !resp.Result.(bool) {
|
||||||
|
t.Errorf("bad result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_ProviderIsUsable(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderIsUsable(nil, to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !resp.Result.(bool) {
|
||||||
|
t.Errorf("bad result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_ProviderMachineIdChanged(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderMachineIdChanged(nil, to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", resp.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_ProviderRunAction(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a, err := json.Marshal([]string{"test_arg"})
|
||||||
|
args := string(a)
|
||||||
|
|
||||||
|
result := ProviderRunAction(nil, to_cs("valid"), to_cs(args), to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
if r[0] != "valid" {
|
||||||
|
t.Errorf("%s != valid", r[0])
|
||||||
|
}
|
||||||
|
if r[1] != "test_arg" {
|
||||||
|
t.Errorf("%s != test_arg", r[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_ProviderSshInfo(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderSshInfo(nil, to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r["host"] != "localhost" {
|
||||||
|
t.Errorf("%s != localhost", r["host"])
|
||||||
|
}
|
||||||
|
if r["port"] != 2222.0 {
|
||||||
|
t.Errorf("%d != 2222", r["port"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_ProviderState(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &vplugin.ProviderPlugin{Impl: &vplugin.MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(vplugin.Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := &vplugin.RemoteProvider{
|
||||||
|
Provider: impl}
|
||||||
|
Plugins = vplugin.VagrantPluginInit()
|
||||||
|
Plugins.PluginLookup = func(_, _ string) (r interface{}, err error) {
|
||||||
|
r = p
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ProviderState(nil, to_cs("{}"))
|
||||||
|
resp, err := LoadResponse(result)
|
||||||
|
if resp.Error != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, ok := resp.Result.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", resp.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r["id"] != "default" {
|
||||||
|
t.Errorf("%s != default", r["id"])
|
||||||
|
}
|
||||||
|
if r["short_description"] != "running" {
|
||||||
|
t.Errorf("%s != running", r["short_description"])
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"C"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Error error `json:"error"`
|
||||||
|
Result interface{} `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize the response into a JSON C string
|
||||||
|
func (r *Response) Dump() *C.char {
|
||||||
|
tmp := map[string]interface{}{}
|
||||||
|
if r.Error != nil {
|
||||||
|
tmp["error"] = r.Error.Error()
|
||||||
|
} else {
|
||||||
|
tmp["error"] = nil
|
||||||
|
}
|
||||||
|
tmp["result"] = r.Result
|
||||||
|
result, err := json.Marshal(tmp)
|
||||||
|
if err != nil {
|
||||||
|
return to_cs(fmt.Sprintf(`{"error": "failed to encode response - %s"}`, err))
|
||||||
|
}
|
||||||
|
return to_cs(string(result[:]))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load a new response from a JSON C string
|
||||||
|
func LoadResponse(s *C.char) (r *Response, err error) {
|
||||||
|
tmp := map[string]interface{}{}
|
||||||
|
st := []byte(to_gs(s))
|
||||||
|
r = &Response{}
|
||||||
|
err = json.Unmarshal(st, &tmp)
|
||||||
|
if tmp["error"] != nil {
|
||||||
|
e, ok := tmp["error"].(string)
|
||||||
|
if !ok {
|
||||||
|
err = errors.New(
|
||||||
|
fmt.Sprintf("cannot load error content - %s", tmp["error"]))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.Error = errors.New(e)
|
||||||
|
}
|
||||||
|
r.Result = tmp["result"]
|
||||||
|
return
|
||||||
|
}
|
|
@ -12,135 +12,135 @@ import (
|
||||||
//export ListSyncedFolders
|
//export ListSyncedFolders
|
||||||
func ListSyncedFolders() *C.char {
|
func ListSyncedFolders() *C.char {
|
||||||
list := map[string]interface{}{}
|
list := map[string]interface{}{}
|
||||||
r := vagrant.Response{Result: list}
|
r := &Response{Result: list}
|
||||||
if Plugins == nil {
|
if Plugins == nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
for n, p := range Plugins.SyncedFolders {
|
for n, p := range Plugins.SyncedFolders {
|
||||||
list[n] = p.SyncedFolder.Info()
|
list[n] = p.SyncedFolder.Info()
|
||||||
}
|
}
|
||||||
r.Result = list
|
r.Result = list
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export SyncedFolderCleanup
|
//export SyncedFolderCleanup
|
||||||
func SyncedFolderCleanup(pluginName, machine, opts *C.char) *C.char {
|
func SyncedFolderCleanup(pluginName, machine, opts *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getSyncedFolderPlugin(pluginName)
|
p, err := getSyncedFolderPlugin(pluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var o vagrant.FolderOptions
|
var o vagrant.FolderOptions
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Error = p.SyncedFolder.Cleanup(m, &o)
|
r.Error = p.SyncedFolder.Cleanup(m, o)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export SyncedFolderDisable
|
//export SyncedFolderDisable
|
||||||
func SyncedFolderDisable(pluginName, machine, folders, opts *C.char) *C.char {
|
func SyncedFolderDisable(pluginName, machine, folders, opts *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getSyncedFolderPlugin(pluginName)
|
p, err := getSyncedFolderPlugin(pluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var f vagrant.FolderList
|
var f vagrant.FolderList
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var o vagrant.FolderOptions
|
var o vagrant.FolderOptions
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Error = p.SyncedFolder.Disable(m, &f, &o)
|
r.Error = p.SyncedFolder.Disable(m, f, o)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export SyncedFolderEnable
|
//export SyncedFolderEnable
|
||||||
func SyncedFolderEnable(pluginName, machine, folders, opts *C.char) *C.char {
|
func SyncedFolderEnable(pluginName, machine, folders, opts *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getSyncedFolderPlugin(pluginName)
|
p, err := getSyncedFolderPlugin(pluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var f vagrant.FolderList
|
var f vagrant.FolderList
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var o vagrant.FolderOptions
|
var o vagrant.FolderOptions
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Error = p.SyncedFolder.Enable(m, &f, &o)
|
r.Error = p.SyncedFolder.Enable(m, f, o)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export SyncedFolderIsUsable
|
//export SyncedFolderIsUsable
|
||||||
func SyncedFolderIsUsable(pluginName, machine *C.char) *C.char {
|
func SyncedFolderIsUsable(pluginName, machine *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getSyncedFolderPlugin(pluginName)
|
p, err := getSyncedFolderPlugin(pluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Result, r.Error = p.SyncedFolder.IsUsable(m)
|
r.Result, r.Error = p.SyncedFolder.IsUsable(m)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
//export SyncedFolderPrepare
|
//export SyncedFolderPrepare
|
||||||
func SyncedFolderPrepare(pluginName, machine, folders, opts *C.char) *C.char {
|
func SyncedFolderPrepare(pluginName, machine, folders, opts *C.char) *C.char {
|
||||||
r := vagrant.Response{}
|
r := &Response{}
|
||||||
p, err := getSyncedFolderPlugin(pluginName)
|
p, err := getSyncedFolderPlugin(pluginName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
m, err := vagrant.LoadMachine(C.GoString(machine), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Error = err
|
r.Error = err
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var f vagrant.FolderList
|
var f vagrant.FolderList
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
r.Error = json.Unmarshal([]byte(C.GoString(folders)), &f)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
var o vagrant.FolderOptions
|
var o vagrant.FolderOptions
|
||||||
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
r.Error = json.Unmarshal([]byte(C.GoString(opts)), &o)
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
r.Error = p.SyncedFolder.Prepare(m, &f, &o)
|
r.Error = p.SyncedFolder.Prepare(m, f, o)
|
||||||
return C.CString(r.Dump())
|
return r.Dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSyncedFolderPlugin(pluginName *C.char) (c *plugin.RemoteSyncedFolder, err error) {
|
func getSyncedFolderPlugin(pluginName *C.char) (c *plugin.RemoteSyncedFolder, err error) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ type SystemCapability struct {
|
||||||
|
|
||||||
type ProviderCapability struct {
|
type ProviderCapability struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Provider string `json:"name"`
|
Provider string `json:"provider"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GuestCapabilities interface {
|
type GuestCapabilities interface {
|
||||||
|
|
|
@ -6,3 +6,10 @@ type Config interface {
|
||||||
ConfigValidate(data map[string]interface{}, m *Machine) (errors []string, err error)
|
ConfigValidate(data map[string]interface{}, m *Machine) (errors []string, err error)
|
||||||
ConfigFinalize(data map[string]interface{}) (finaldata map[string]interface{}, err error)
|
ConfigFinalize(data map[string]interface{}) (finaldata map[string]interface{}, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NoConfig struct{}
|
||||||
|
|
||||||
|
func (c *NoConfig) ConfigAttributes() (a []string, e error) { return }
|
||||||
|
func (c *NoConfig) ConfigLoad(map[string]interface{}) (d map[string]interface{}, e error) { return }
|
||||||
|
func (c *NoConfig) ConfigValidate(map[string]interface{}, *Machine) (es []string, e error) { return }
|
||||||
|
func (c *NoConfig) ConfigFinalize(map[string]interface{}) (f map[string]interface{}, e error) { return }
|
||||||
|
|
|
@ -2,6 +2,7 @@ package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
|
@ -11,6 +12,13 @@ import (
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Handshake = go_plugin.HandshakeConfig{
|
||||||
|
MagicCookieKey: "VAGRANT_PLUGIN_MAGIC_COOKIE",
|
||||||
|
MagicCookieValue: "1561a662a76642f98df77ad025aa13a9b16225d93f90475e91090fbe577317ed",
|
||||||
|
ProtocolVersion: 1}
|
||||||
|
)
|
||||||
|
|
||||||
type RemoteConfig struct {
|
type RemoteConfig struct {
|
||||||
Client *go_plugin.Client
|
Client *go_plugin.Client
|
||||||
Config vagrant.Config
|
Config vagrant.Config
|
||||||
|
@ -45,9 +53,36 @@ type VagrantPlugin struct {
|
||||||
Providers map[string]*RemoteProvider
|
Providers map[string]*RemoteProvider
|
||||||
SyncedFolders map[string]*RemoteSyncedFolder
|
SyncedFolders map[string]*RemoteSyncedFolder
|
||||||
PluginDirectories []string
|
PluginDirectories []string
|
||||||
|
PluginLookup func(name, kind string) (p interface{}, err error)
|
||||||
Logger hclog.Logger
|
Logger hclog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func VagrantPluginInit() *VagrantPlugin {
|
||||||
|
v := &VagrantPlugin{
|
||||||
|
PluginDirectories: []string{},
|
||||||
|
Providers: map[string]*RemoteProvider{},
|
||||||
|
SyncedFolders: map[string]*RemoteSyncedFolder{},
|
||||||
|
Logger: vagrant.DefaultLogger().Named("go-plugin")}
|
||||||
|
v.PluginLookup = v.DefaultPluginLookup
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *VagrantPlugin) DefaultPluginLookup(name, kind string) (p interface{}, err error) {
|
||||||
|
switch kind {
|
||||||
|
case "provider":
|
||||||
|
p = v.Providers[name]
|
||||||
|
case "synced_folder":
|
||||||
|
p = v.SyncedFolders[name]
|
||||||
|
default:
|
||||||
|
err = errors.New("invalid plugin type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p == nil {
|
||||||
|
err = errors.New(fmt.Sprintf("Failed to locate %s plugin of type %s", name, kind))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (v *VagrantPlugin) LoadPlugins(pluginPath string) error {
|
func (v *VagrantPlugin) LoadPlugins(pluginPath string) error {
|
||||||
for _, p := range v.PluginDirectories {
|
for _, p := range v.PluginDirectories {
|
||||||
if p == pluginPath {
|
if p == pluginPath {
|
||||||
|
@ -78,11 +113,7 @@ func (v *VagrantPlugin) LoadProviders(pluginPath string) error {
|
||||||
client := go_plugin.NewClient(&go_plugin.ClientConfig{
|
client := go_plugin.NewClient(&go_plugin.ClientConfig{
|
||||||
AllowedProtocols: []go_plugin.Protocol{go_plugin.ProtocolGRPC},
|
AllowedProtocols: []go_plugin.Protocol{go_plugin.ProtocolGRPC},
|
||||||
Logger: v.Logger,
|
Logger: v.Logger,
|
||||||
HandshakeConfig: go_plugin.HandshakeConfig{
|
HandshakeConfig: Handshake,
|
||||||
MagicCookieKey: "BASIC_PLUGIN",
|
|
||||||
MagicCookieValue: "hello",
|
|
||||||
ProtocolVersion: 1,
|
|
||||||
},
|
|
||||||
Cmd: exec.Command(providerPath),
|
Cmd: exec.Command(providerPath),
|
||||||
VersionedPlugins: map[int]go_plugin.PluginSet{
|
VersionedPlugins: map[int]go_plugin.PluginSet{
|
||||||
2: {"provider": &ProviderPlugin{}}}})
|
2: {"provider": &ProviderPlugin{}}}})
|
||||||
|
@ -121,11 +152,7 @@ func (v *VagrantPlugin) LoadSyncedFolders(pluginPath string) error {
|
||||||
client := go_plugin.NewClient(&go_plugin.ClientConfig{
|
client := go_plugin.NewClient(&go_plugin.ClientConfig{
|
||||||
AllowedProtocols: []go_plugin.Protocol{go_plugin.ProtocolGRPC},
|
AllowedProtocols: []go_plugin.Protocol{go_plugin.ProtocolGRPC},
|
||||||
Logger: v.Logger,
|
Logger: v.Logger,
|
||||||
HandshakeConfig: go_plugin.HandshakeConfig{
|
HandshakeConfig: Handshake,
|
||||||
MagicCookieKey: "BASIC_PLUGIN",
|
|
||||||
MagicCookieValue: "hello",
|
|
||||||
ProtocolVersion: 1,
|
|
||||||
},
|
|
||||||
Cmd: exec.Command(folderPath),
|
Cmd: exec.Command(folderPath),
|
||||||
VersionedPlugins: map[int]go_plugin.PluginSet{
|
VersionedPlugins: map[int]go_plugin.PluginSet{
|
||||||
2: {"synced_folders": &SyncedFolderPlugin{}}}})
|
2: {"synced_folders": &SyncedFolderPlugin{}}}})
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
go_plugin "github.com/hashicorp/go-plugin"
|
go_plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
"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_caps"
|
||||||
|
@ -21,6 +23,23 @@ type GuestCapabilitiesPlugin struct {
|
||||||
Impl GuestCapabilities
|
Impl GuestCapabilities
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GuestCapabilitiesPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
g.Impl.Init()
|
||||||
|
vagrant_caps.RegisterGuestCapabilitiesServer(s, &GRPCGuestCapabilitiesServer{
|
||||||
|
Impl: g.Impl,
|
||||||
|
GRPCIOServer: GRPCIOServer{
|
||||||
|
Impl: g.Impl}})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GuestCapabilitiesPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
|
client := vagrant_caps.NewGuestCapabilitiesClient(c)
|
||||||
|
return &GRPCGuestCapabilitiesClient{
|
||||||
|
client: client,
|
||||||
|
GRPCIOClient: GRPCIOClient{
|
||||||
|
client: client}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type GRPCGuestCapabilitiesServer struct {
|
type GRPCGuestCapabilitiesServer struct {
|
||||||
GRPCIOServer
|
GRPCIOServer
|
||||||
Impl GuestCapabilities
|
Impl GuestCapabilities
|
||||||
|
@ -43,8 +62,7 @@ func (s *GRPCGuestCapabilitiesServer) GuestCapabilities(ctx context.Context, req
|
||||||
func (s *GRPCGuestCapabilitiesServer) GuestCapability(ctx context.Context, req *vagrant_caps.GuestCapabilityRequest) (resp *vagrant_caps.GuestCapabilityResponse, err error) {
|
func (s *GRPCGuestCapabilitiesServer) GuestCapability(ctx context.Context, req *vagrant_caps.GuestCapabilityRequest) (resp *vagrant_caps.GuestCapabilityResponse, err error) {
|
||||||
resp = &vagrant_caps.GuestCapabilityResponse{}
|
resp = &vagrant_caps.GuestCapabilityResponse{}
|
||||||
var args interface{}
|
var args interface{}
|
||||||
err = json.Unmarshal([]byte(req.Arguments), args)
|
if err = json.Unmarshal([]byte(req.Arguments), &args); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||||
|
@ -67,6 +85,8 @@ func (s *GRPCGuestCapabilitiesServer) GuestCapability(ctx context.Context, req *
|
||||||
}
|
}
|
||||||
|
|
||||||
type GRPCGuestCapabilitiesClient struct {
|
type GRPCGuestCapabilitiesClient struct {
|
||||||
|
GRPCCoreClient
|
||||||
|
GRPCIOClient
|
||||||
client vagrant_caps.GuestCapabilitiesClient
|
client vagrant_caps.GuestCapabilitiesClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +122,13 @@ func (c *GRPCGuestCapabilitiesClient) GuestCapability(cap *vagrant.SystemCapabil
|
||||||
Capability: &vagrant_caps.Capability{Name: cap.Name, Platform: cap.Platform},
|
Capability: &vagrant_caps.Capability{Name: cap.Name, Platform: cap.Platform},
|
||||||
Machine: m,
|
Machine: m,
|
||||||
Arguments: string(a)})
|
Arguments: string(a)})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp.Error != "" {
|
||||||
|
err = errors.New(resp.Error)
|
||||||
|
return
|
||||||
|
}
|
||||||
err = json.Unmarshal([]byte(resp.Result), &result)
|
err = json.Unmarshal([]byte(resp.Result), &result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -111,6 +138,28 @@ type HostCapabilities interface {
|
||||||
Meta
|
Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HostCapabilitiesPlugin struct {
|
||||||
|
go_plugin.NetRPCUnsupportedPlugin
|
||||||
|
Impl HostCapabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HostCapabilitiesPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
h.Impl.Init()
|
||||||
|
vagrant_caps.RegisterHostCapabilitiesServer(s, &GRPCHostCapabilitiesServer{
|
||||||
|
Impl: h.Impl,
|
||||||
|
GRPCIOServer: GRPCIOServer{
|
||||||
|
Impl: h.Impl}})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HostCapabilitiesPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
|
client := vagrant_caps.NewHostCapabilitiesClient(c)
|
||||||
|
return &GRPCHostCapabilitiesClient{
|
||||||
|
client: client,
|
||||||
|
GRPCIOClient: GRPCIOClient{
|
||||||
|
client: client}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type GRPCHostCapabilitiesServer struct {
|
type GRPCHostCapabilitiesServer struct {
|
||||||
GRPCIOServer
|
GRPCIOServer
|
||||||
Impl HostCapabilities
|
Impl HostCapabilities
|
||||||
|
@ -133,8 +182,7 @@ func (s *GRPCHostCapabilitiesServer) HostCapabilities(ctx context.Context, req *
|
||||||
func (s *GRPCHostCapabilitiesServer) HostCapability(ctx context.Context, req *vagrant_caps.HostCapabilityRequest) (resp *vagrant_caps.HostCapabilityResponse, err error) {
|
func (s *GRPCHostCapabilitiesServer) HostCapability(ctx context.Context, req *vagrant_caps.HostCapabilityRequest) (resp *vagrant_caps.HostCapabilityResponse, err error) {
|
||||||
resp = &vagrant_caps.HostCapabilityResponse{}
|
resp = &vagrant_caps.HostCapabilityResponse{}
|
||||||
var args interface{}
|
var args interface{}
|
||||||
err = json.Unmarshal([]byte(req.Arguments), args)
|
if err = json.Unmarshal([]byte(req.Arguments), &args); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
env, err := vagrant.LoadEnvironment(req.Environment, s.Impl)
|
env, err := vagrant.LoadEnvironment(req.Environment, s.Impl)
|
||||||
|
@ -157,6 +205,8 @@ func (s *GRPCHostCapabilitiesServer) HostCapability(ctx context.Context, req *va
|
||||||
}
|
}
|
||||||
|
|
||||||
type GRPCHostCapabilitiesClient struct {
|
type GRPCHostCapabilitiesClient struct {
|
||||||
|
GRPCCoreClient
|
||||||
|
GRPCIOClient
|
||||||
client vagrant_caps.HostCapabilitiesClient
|
client vagrant_caps.HostCapabilitiesClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +244,9 @@ func (c *GRPCHostCapabilitiesClient) HostCapability(cap *vagrant.SystemCapabilit
|
||||||
Platform: cap.Platform},
|
Platform: cap.Platform},
|
||||||
Environment: e,
|
Environment: e,
|
||||||
Arguments: string(a)})
|
Arguments: string(a)})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
err = json.Unmarshal([]byte(resp.Result), &result)
|
err = json.Unmarshal([]byte(resp.Result), &result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -203,6 +256,28 @@ type ProviderCapabilities interface {
|
||||||
Meta
|
Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProviderCapabilitiesPlugin struct {
|
||||||
|
go_plugin.NetRPCUnsupportedPlugin
|
||||||
|
Impl ProviderCapabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProviderCapabilitiesPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
p.Impl.Init()
|
||||||
|
vagrant_caps.RegisterProviderCapabilitiesServer(s, &GRPCProviderCapabilitiesServer{
|
||||||
|
Impl: p.Impl,
|
||||||
|
GRPCIOServer: GRPCIOServer{
|
||||||
|
Impl: p.Impl}})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProviderCapabilitiesPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
|
client := vagrant_caps.NewProviderCapabilitiesClient(c)
|
||||||
|
return &GRPCProviderCapabilitiesClient{
|
||||||
|
client: client,
|
||||||
|
GRPCIOClient: GRPCIOClient{
|
||||||
|
client: client}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type GRPCProviderCapabilitiesServer struct {
|
type GRPCProviderCapabilitiesServer struct {
|
||||||
GRPCIOServer
|
GRPCIOServer
|
||||||
Impl ProviderCapabilities
|
Impl ProviderCapabilities
|
||||||
|
@ -225,7 +300,7 @@ func (s *GRPCProviderCapabilitiesServer) ProviderCapabilities(ctx context.Contex
|
||||||
func (s *GRPCProviderCapabilitiesServer) ProviderCapability(ctx context.Context, req *vagrant_caps.ProviderCapabilityRequest) (resp *vagrant_caps.ProviderCapabilityResponse, err error) {
|
func (s *GRPCProviderCapabilitiesServer) ProviderCapability(ctx context.Context, req *vagrant_caps.ProviderCapabilityRequest) (resp *vagrant_caps.ProviderCapabilityResponse, err error) {
|
||||||
resp = &vagrant_caps.ProviderCapabilityResponse{}
|
resp = &vagrant_caps.ProviderCapabilityResponse{}
|
||||||
var args interface{}
|
var args interface{}
|
||||||
err = json.Unmarshal([]byte(req.Arguments), args)
|
err = json.Unmarshal([]byte(req.Arguments), &args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -249,6 +324,8 @@ func (s *GRPCProviderCapabilitiesServer) ProviderCapability(ctx context.Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
type GRPCProviderCapabilitiesClient struct {
|
type GRPCProviderCapabilitiesClient struct {
|
||||||
|
GRPCCoreClient
|
||||||
|
GRPCIOClient
|
||||||
client vagrant_caps.ProviderCapabilitiesClient
|
client vagrant_caps.ProviderCapabilitiesClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,6 +363,9 @@ func (c *GRPCProviderCapabilitiesClient) ProviderCapability(cap *vagrant.Provide
|
||||||
Provider: cap.Provider},
|
Provider: cap.Provider},
|
||||||
Machine: m,
|
Machine: m,
|
||||||
Arguments: string(a)})
|
Arguments: string(a)})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
err = json.Unmarshal([]byte(resp.Result), &result)
|
err = json.Unmarshal([]byte(resp.Result), &result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,311 @@
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCapabilities_GuestCapabilities(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &GuestCapabilitiesPlugin{Impl: &MockGuestCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(GuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
resp, err := impl.GuestCapabilities()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if len(resp) != 1 {
|
||||||
|
t.Fatalf("length %d != 1", len(resp))
|
||||||
|
}
|
||||||
|
if resp[0].Name != "test_cap" {
|
||||||
|
t.Errorf("name - %s != test_cap", resp[0].Name)
|
||||||
|
}
|
||||||
|
if resp[0].Platform != "testOS" {
|
||||||
|
t.Errorf("platform - %s != testOS", resp[0].Platform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_GuestCapability(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &GuestCapabilitiesPlugin{Impl: &MockGuestCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(GuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap := &vagrant.SystemCapability{
|
||||||
|
Name: "test_cap",
|
||||||
|
Platform: "TestOS"}
|
||||||
|
m := &vagrant.Machine{}
|
||||||
|
args := []string{"test_value", "next_test_value"}
|
||||||
|
|
||||||
|
resp, err := impl.GuestCapability(cap, args, m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
result, ok := resp.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", result)
|
||||||
|
}
|
||||||
|
if result[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", result[0])
|
||||||
|
}
|
||||||
|
if result[1] != "test_value" {
|
||||||
|
t.Errorf("%s != test_value", result[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_GuestCapability_noargs(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &GuestCapabilitiesPlugin{Impl: &MockGuestCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(GuestCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap := &vagrant.SystemCapability{
|
||||||
|
Name: "test_cap",
|
||||||
|
Platform: "TestOS"}
|
||||||
|
m := &vagrant.Machine{}
|
||||||
|
var args interface{}
|
||||||
|
args = nil
|
||||||
|
|
||||||
|
resp, err := impl.GuestCapability(cap, args, m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
result, ok := resp.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", result)
|
||||||
|
}
|
||||||
|
if result[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", result[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_HostCapabilities(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &HostCapabilitiesPlugin{Impl: &MockHostCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(HostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
resp, err := impl.HostCapabilities()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if len(resp) != 1 {
|
||||||
|
t.Fatalf("length %d != 1", len(resp))
|
||||||
|
}
|
||||||
|
if resp[0].Name != "test_cap" {
|
||||||
|
t.Errorf("name - %s != test_cap", resp[0].Name)
|
||||||
|
}
|
||||||
|
if resp[0].Platform != "testOS" {
|
||||||
|
t.Errorf("platform - %s != testOS", resp[0].Platform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_HostCapability(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &HostCapabilitiesPlugin{Impl: &MockHostCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(HostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap := &vagrant.SystemCapability{
|
||||||
|
Name: "test_cap",
|
||||||
|
Platform: "TestOS"}
|
||||||
|
e := &vagrant.Environment{}
|
||||||
|
args := []string{"test_value", "next_test_value"}
|
||||||
|
|
||||||
|
resp, err := impl.HostCapability(cap, args, e)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
result, ok := resp.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", result)
|
||||||
|
}
|
||||||
|
if result[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", result[0])
|
||||||
|
}
|
||||||
|
if result[1] != "test_value" {
|
||||||
|
t.Errorf("%s != test_value", result[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_HostCapability_noargs(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &HostCapabilitiesPlugin{Impl: &MockHostCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(HostCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap := &vagrant.SystemCapability{
|
||||||
|
Name: "test_cap",
|
||||||
|
Platform: "TestOS"}
|
||||||
|
e := &vagrant.Environment{}
|
||||||
|
var args interface{}
|
||||||
|
args = nil
|
||||||
|
|
||||||
|
resp, err := impl.HostCapability(cap, args, e)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
result, ok := resp.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", result)
|
||||||
|
}
|
||||||
|
if result[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", result[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_ProviderCapabilities(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &ProviderCapabilitiesPlugin{Impl: &MockProviderCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(ProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
resp, err := impl.ProviderCapabilities()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if len(resp) != 1 {
|
||||||
|
t.Fatalf("length %d != 1", len(resp))
|
||||||
|
}
|
||||||
|
if resp[0].Name != "test_cap" {
|
||||||
|
t.Errorf("name - %s != test_cap", resp[0].Name)
|
||||||
|
}
|
||||||
|
if resp[0].Provider != "testProvider" {
|
||||||
|
t.Errorf("provider - %s != testProvdier", resp[0].Provider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_ProviderCapability(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &ProviderCapabilitiesPlugin{Impl: &MockProviderCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(ProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap := &vagrant.ProviderCapability{
|
||||||
|
Name: "test_cap",
|
||||||
|
Provider: "test_provider"}
|
||||||
|
m := &vagrant.Machine{}
|
||||||
|
args := []string{"test_value", "next_test_value"}
|
||||||
|
|
||||||
|
resp, err := impl.ProviderCapability(cap, args, m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
result, ok := resp.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", result)
|
||||||
|
}
|
||||||
|
if result[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", result[0])
|
||||||
|
}
|
||||||
|
if result[1] != "test_value" {
|
||||||
|
t.Errorf("%s != test_value", result[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCapabilities_ProviderCapability_noargs(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"caps": &ProviderCapabilitiesPlugin{Impl: &MockProviderCapabilities{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("caps")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(ProviderCapabilities)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
cap := &vagrant.ProviderCapability{
|
||||||
|
Name: "test_cap",
|
||||||
|
Provider: "test_provider"}
|
||||||
|
m := &vagrant.Machine{}
|
||||||
|
var args interface{}
|
||||||
|
args = nil
|
||||||
|
|
||||||
|
resp, err := impl.ProviderCapability(cap, args, m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
result, ok := resp.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", result)
|
||||||
|
}
|
||||||
|
if result[0] != "test_cap" {
|
||||||
|
t.Errorf("%s != test_cap", result[0])
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
go_plugin "github.com/hashicorp/go-plugin"
|
go_plugin "github.com/hashicorp/go-plugin"
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
"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_common"
|
||||||
|
@ -21,6 +23,23 @@ type ConfigPlugin struct {
|
||||||
Impl Config
|
Impl Config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ConfigPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
c.Impl.Init()
|
||||||
|
vagrant_config.RegisterConfigServer(s, &GRPCConfigServer{
|
||||||
|
Impl: c.Impl,
|
||||||
|
GRPCIOServer: GRPCIOServer{
|
||||||
|
Impl: c.Impl}})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConfigPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, con *grpc.ClientConn) (interface{}, error) {
|
||||||
|
client := vagrant_config.NewConfigClient(con)
|
||||||
|
return &GRPCConfigClient{
|
||||||
|
client: client,
|
||||||
|
GRPCIOClient: GRPCIOClient{
|
||||||
|
client: client}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type GRPCConfigServer struct {
|
type GRPCConfigServer struct {
|
||||||
GRPCIOServer
|
GRPCIOServer
|
||||||
Impl Config
|
Impl Config
|
||||||
|
@ -104,6 +123,8 @@ func (s *GRPCConfigServer) ConfigFinalize(ctx context.Context, req *vagrant_conf
|
||||||
}
|
}
|
||||||
|
|
||||||
type GRPCConfigClient struct {
|
type GRPCConfigClient struct {
|
||||||
|
GRPCCoreClient
|
||||||
|
GRPCIOClient
|
||||||
client vagrant_config.ConfigClient
|
client vagrant_config.ConfigClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestConfigPlugin_Attributes(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"configs": &ConfigPlugin{Impl: &MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("configs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := impl.ConfigAttributes()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp %s", err)
|
||||||
|
}
|
||||||
|
if resp[0] != "fubar" {
|
||||||
|
t.Errorf("%s != fubar", resp[0])
|
||||||
|
}
|
||||||
|
if resp[1] != "foobar" {
|
||||||
|
t.Errorf("%s != foobar", resp[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigPlugin_Load(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"configs": &ConfigPlugin{Impl: &MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("configs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]interface{}{}
|
||||||
|
|
||||||
|
resp, err := impl.ConfigLoad(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if _, ok := resp["test_key"]; !ok {
|
||||||
|
t.Fatalf("bad resp content %#v", resp)
|
||||||
|
}
|
||||||
|
v := resp["test_key"].(string)
|
||||||
|
if v != "test_val" {
|
||||||
|
t.Errorf("%s != test_val", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigPlugin_Validate(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"configs": &ConfigPlugin{Impl: &MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("configs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]interface{}{}
|
||||||
|
machine := &vagrant.Machine{}
|
||||||
|
|
||||||
|
resp, err := impl.ConfigValidate(data, machine)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if len(resp) != 1 {
|
||||||
|
t.Fatalf("bad size %d != 1", len(resp))
|
||||||
|
}
|
||||||
|
if resp[0] != "test error" {
|
||||||
|
t.Errorf("%s != test error", resp[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigPlugin_Finalize(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"configs": &ConfigPlugin{Impl: &MockConfig{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("configs")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Config)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"test_key": "test_val",
|
||||||
|
"other_key": "other_val"}
|
||||||
|
|
||||||
|
resp, err := impl.ConfigFinalize(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if _, ok := resp["test_key"]; !ok {
|
||||||
|
t.Fatalf("bad resp content %#v", resp)
|
||||||
|
}
|
||||||
|
v := resp["test_key"].(string)
|
||||||
|
if v != "test_val-updated" {
|
||||||
|
t.Errorf("%s != test_val-updated", v)
|
||||||
|
}
|
||||||
|
v = resp["other_key"].(string)
|
||||||
|
if v != "other_val-updated" {
|
||||||
|
t.Errorf("%s != other_val-updated", v)
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,10 @@ import (
|
||||||
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io"
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type IO interface {
|
||||||
|
vagrant.StreamIO
|
||||||
|
}
|
||||||
|
|
||||||
type IOPlugin struct {
|
type IOPlugin struct {
|
||||||
go_plugin.NetRPCUnsupportedPlugin
|
go_plugin.NetRPCUnsupportedPlugin
|
||||||
Impl vagrant.StreamIO
|
Impl vagrant.StreamIO
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockIO struct {
|
||||||
|
Core
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIO_ReadWrite(t *testing.T) {
|
||||||
|
ioplugin := &MockIO{}
|
||||||
|
ioplugin.Init()
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"io": &IOPlugin{Impl: ioplugin}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("io")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(IO)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
length, err := impl.Write("test_message", "stdout")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad write: %s", err)
|
||||||
|
}
|
||||||
|
if length != len("test_message") {
|
||||||
|
t.Fatalf("bad length %d != %d", length, len("test_message"))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
resp, err := impl.Read("stdout")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad read: %s", err)
|
||||||
|
}
|
||||||
|
if resp != "test_message" {
|
||||||
|
t.Errorf("%s != test_message", resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIO_Write_bad(t *testing.T) {
|
||||||
|
ioplugin := &MockIO{}
|
||||||
|
ioplugin.Init()
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"io": &IOPlugin{Impl: ioplugin}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("io")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(IO)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
_, err = impl.Write("test_message", "bad-target")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("illegal write")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIO_Read_bad(t *testing.T) {
|
||||||
|
ioplugin := &MockIO{}
|
||||||
|
ioplugin.Init()
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"io": &IOPlugin{Impl: ioplugin}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("io")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(IO)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
_, err = impl.Read("bad-target")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("illegal read")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,176 @@
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockGuestCapabilities struct{ Core }
|
||||||
|
|
||||||
|
func (g *MockGuestCapabilities) GuestCapabilities() (caps []vagrant.SystemCapability, err error) {
|
||||||
|
caps = []vagrant.SystemCapability{
|
||||||
|
vagrant.SystemCapability{Name: "test_cap", Platform: "testOS"}}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *MockGuestCapabilities) GuestCapability(cap *vagrant.SystemCapability, args interface{}, m *vagrant.Machine) (result interface{}, err error) {
|
||||||
|
if args != nil {
|
||||||
|
arguments := args.([]interface{})
|
||||||
|
if len(arguments) > 0 {
|
||||||
|
result = []string{
|
||||||
|
cap.Name,
|
||||||
|
arguments[0].(string)}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = []string{cap.Name}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockHostCapabilities struct{ Core }
|
||||||
|
|
||||||
|
func (h *MockHostCapabilities) HostCapabilities() (caps []vagrant.SystemCapability, err error) {
|
||||||
|
caps = []vagrant.SystemCapability{
|
||||||
|
vagrant.SystemCapability{Name: "test_cap", Platform: "testOS"}}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *MockHostCapabilities) HostCapability(cap *vagrant.SystemCapability, args interface{}, e *vagrant.Environment) (result interface{}, err error) {
|
||||||
|
if args != nil {
|
||||||
|
arguments := args.([]interface{})
|
||||||
|
if len(arguments) > 0 {
|
||||||
|
result = []string{
|
||||||
|
cap.Name,
|
||||||
|
arguments[0].(string)}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = []string{cap.Name}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockProviderCapabilities struct{ Core }
|
||||||
|
|
||||||
|
func (p *MockProviderCapabilities) ProviderCapabilities() (caps []vagrant.ProviderCapability, err error) {
|
||||||
|
caps = []vagrant.ProviderCapability{
|
||||||
|
vagrant.ProviderCapability{Name: "test_cap", Provider: "testProvider"}}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MockProviderCapabilities) ProviderCapability(cap *vagrant.ProviderCapability, args interface{}, m *vagrant.Machine) (result interface{}, err error) {
|
||||||
|
if args != nil {
|
||||||
|
arguments := args.([]interface{})
|
||||||
|
if len(arguments) > 0 {
|
||||||
|
result = []string{
|
||||||
|
cap.Name,
|
||||||
|
arguments[0].(string)}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = []string{cap.Name}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockConfig struct {
|
||||||
|
Core
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockConfig) ConfigAttributes() (attrs []string, err error) {
|
||||||
|
attrs = []string{"fubar", "foobar"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockConfig) ConfigLoad(data map[string]interface{}) (loaddata map[string]interface{}, err error) {
|
||||||
|
loaddata = map[string]interface{}{
|
||||||
|
"test_key": "test_val"}
|
||||||
|
if data["test_key"] != nil {
|
||||||
|
loaddata["sent_key"] = data["test_key"]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockConfig) ConfigValidate(data map[string]interface{}, m *vagrant.Machine) (errors []string, err error) {
|
||||||
|
errors = []string{"test error"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockConfig) ConfigFinalize(data map[string]interface{}) (finaldata map[string]interface{}, err error) {
|
||||||
|
finaldata = make(map[string]interface{})
|
||||||
|
for key, tval := range data {
|
||||||
|
val := tval.(string)
|
||||||
|
finaldata[key] = val + "-updated"
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockProvider struct {
|
||||||
|
Core
|
||||||
|
vagrant.NoConfig
|
||||||
|
vagrant.NoGuestCapabilities
|
||||||
|
vagrant.NoHostCapabilities
|
||||||
|
vagrant.NoProviderCapabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) Action(actionName string, m *vagrant.Machine) (actions []string, err error) {
|
||||||
|
if actionName == "valid" {
|
||||||
|
actions = []string{"self::DoTask"}
|
||||||
|
} else {
|
||||||
|
err = errors.New("Unknown action requested")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) IsInstalled(m *vagrant.Machine) (bool, error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) IsUsable(m *vagrant.Machine) (bool, error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) MachineIdChanged(m *vagrant.Machine) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) Name() string {
|
||||||
|
return "mock_provider"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) RunAction(actionName string, args interface{}, m *vagrant.Machine) (r interface{}, err error) {
|
||||||
|
if actionName != "valid" && actionName != "send_output" {
|
||||||
|
err = errors.New("invalid action name")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if actionName == "send_output" {
|
||||||
|
m.UI.Say("test_output_p")
|
||||||
|
}
|
||||||
|
var arguments []interface{}
|
||||||
|
if args != nil {
|
||||||
|
arguments = args.([]interface{})
|
||||||
|
} else {
|
||||||
|
arguments = []interface{}{"unset"}
|
||||||
|
}
|
||||||
|
r = []string{
|
||||||
|
actionName,
|
||||||
|
arguments[0].(string)}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) SshInfo(m *vagrant.Machine) (*vagrant.SshInfo, error) {
|
||||||
|
return &vagrant.SshInfo{
|
||||||
|
Host: "localhost",
|
||||||
|
Port: 2222}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) State(m *vagrant.Machine) (*vagrant.MachineState, error) {
|
||||||
|
return &vagrant.MachineState{
|
||||||
|
Id: "default",
|
||||||
|
ShortDesc: "running"}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MockProvider) Info() *vagrant.ProviderInfo {
|
||||||
|
return &vagrant.ProviderInfo{
|
||||||
|
Description: "Custom",
|
||||||
|
Priority: 10}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import proto "github.com/golang/protobuf/proto"
|
||||||
import fmt "fmt"
|
import fmt "fmt"
|
||||||
import math "math"
|
import math "math"
|
||||||
import vagrant_common "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
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 (
|
import (
|
||||||
context "golang.org/x/net/context"
|
context "golang.org/x/net/context"
|
||||||
|
@ -535,6 +536,9 @@ const _ = grpc.SupportPackageIsVersion4
|
||||||
type GuestCapabilitiesClient interface {
|
type GuestCapabilitiesClient interface {
|
||||||
GuestCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error)
|
GuestCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error)
|
||||||
GuestCapability(ctx context.Context, in *GuestCapabilityRequest, opts ...grpc.CallOption) (*GuestCapabilityResponse, error)
|
GuestCapability(ctx context.Context, in *GuestCapabilityRequest, opts ...grpc.CallOption) (*GuestCapabilityResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
type guestCapabilitiesClient struct {
|
type guestCapabilitiesClient struct {
|
||||||
|
@ -563,10 +567,31 @@ func (c *guestCapabilitiesClient) GuestCapability(ctx context.Context, in *Guest
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *guestCapabilitiesClient) 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.caps.GuestCapabilities/Read", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *guestCapabilitiesClient) 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.caps.GuestCapabilities/Write", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GuestCapabilitiesServer is the server API for GuestCapabilities service.
|
// GuestCapabilitiesServer is the server API for GuestCapabilities service.
|
||||||
type GuestCapabilitiesServer interface {
|
type GuestCapabilitiesServer interface {
|
||||||
GuestCapabilities(context.Context, *vagrant_common.NullRequest) (*CapabilitiesResponse, error)
|
GuestCapabilities(context.Context, *vagrant_common.NullRequest) (*CapabilitiesResponse, error)
|
||||||
GuestCapability(context.Context, *GuestCapabilityRequest) (*GuestCapabilityResponse, error)
|
GuestCapability(context.Context, *GuestCapabilityRequest) (*GuestCapabilityResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterGuestCapabilitiesServer(s *grpc.Server, srv GuestCapabilitiesServer) {
|
func RegisterGuestCapabilitiesServer(s *grpc.Server, srv GuestCapabilitiesServer) {
|
||||||
|
@ -609,6 +634,42 @@ func _GuestCapabilities_GuestCapability_Handler(srv interface{}, ctx context.Con
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _GuestCapabilities_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.(GuestCapabilitiesServer).Read(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.caps.GuestCapabilities/Read",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(GuestCapabilitiesServer).Read(ctx, req.(*vagrant_io.ReadRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _GuestCapabilities_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.(GuestCapabilitiesServer).Write(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.caps.GuestCapabilities/Write",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(GuestCapabilitiesServer).Write(ctx, req.(*vagrant_io.WriteRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
var _GuestCapabilities_serviceDesc = grpc.ServiceDesc{
|
var _GuestCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
ServiceName: "vagrant.caps.GuestCapabilities",
|
ServiceName: "vagrant.caps.GuestCapabilities",
|
||||||
HandlerType: (*GuestCapabilitiesServer)(nil),
|
HandlerType: (*GuestCapabilitiesServer)(nil),
|
||||||
|
@ -621,6 +682,14 @@ var _GuestCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "GuestCapability",
|
MethodName: "GuestCapability",
|
||||||
Handler: _GuestCapabilities_GuestCapability_Handler,
|
Handler: _GuestCapabilities_GuestCapability_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Read",
|
||||||
|
Handler: _GuestCapabilities_Read_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Write",
|
||||||
|
Handler: _GuestCapabilities_Write_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "vagrant_caps/capabilities.proto",
|
Metadata: "vagrant_caps/capabilities.proto",
|
||||||
|
@ -632,6 +701,9 @@ var _GuestCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
type HostCapabilitiesClient interface {
|
type HostCapabilitiesClient interface {
|
||||||
HostCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error)
|
HostCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*CapabilitiesResponse, error)
|
||||||
HostCapability(ctx context.Context, in *HostCapabilityRequest, opts ...grpc.CallOption) (*HostCapabilityResponse, error)
|
HostCapability(ctx context.Context, in *HostCapabilityRequest, opts ...grpc.CallOption) (*HostCapabilityResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
type hostCapabilitiesClient struct {
|
type hostCapabilitiesClient struct {
|
||||||
|
@ -660,10 +732,31 @@ func (c *hostCapabilitiesClient) HostCapability(ctx context.Context, in *HostCap
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *hostCapabilitiesClient) 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.caps.HostCapabilities/Read", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *hostCapabilitiesClient) 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.caps.HostCapabilities/Write", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// HostCapabilitiesServer is the server API for HostCapabilities service.
|
// HostCapabilitiesServer is the server API for HostCapabilities service.
|
||||||
type HostCapabilitiesServer interface {
|
type HostCapabilitiesServer interface {
|
||||||
HostCapabilities(context.Context, *vagrant_common.NullRequest) (*CapabilitiesResponse, error)
|
HostCapabilities(context.Context, *vagrant_common.NullRequest) (*CapabilitiesResponse, error)
|
||||||
HostCapability(context.Context, *HostCapabilityRequest) (*HostCapabilityResponse, error)
|
HostCapability(context.Context, *HostCapabilityRequest) (*HostCapabilityResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterHostCapabilitiesServer(s *grpc.Server, srv HostCapabilitiesServer) {
|
func RegisterHostCapabilitiesServer(s *grpc.Server, srv HostCapabilitiesServer) {
|
||||||
|
@ -706,6 +799,42 @@ func _HostCapabilities_HostCapability_Handler(srv interface{}, ctx context.Conte
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _HostCapabilities_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.(HostCapabilitiesServer).Read(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.caps.HostCapabilities/Read",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HostCapabilitiesServer).Read(ctx, req.(*vagrant_io.ReadRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _HostCapabilities_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.(HostCapabilitiesServer).Write(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.caps.HostCapabilities/Write",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HostCapabilitiesServer).Write(ctx, req.(*vagrant_io.WriteRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
var _HostCapabilities_serviceDesc = grpc.ServiceDesc{
|
var _HostCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
ServiceName: "vagrant.caps.HostCapabilities",
|
ServiceName: "vagrant.caps.HostCapabilities",
|
||||||
HandlerType: (*HostCapabilitiesServer)(nil),
|
HandlerType: (*HostCapabilitiesServer)(nil),
|
||||||
|
@ -718,6 +847,14 @@ var _HostCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "HostCapability",
|
MethodName: "HostCapability",
|
||||||
Handler: _HostCapabilities_HostCapability_Handler,
|
Handler: _HostCapabilities_HostCapability_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Read",
|
||||||
|
Handler: _HostCapabilities_Read_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Write",
|
||||||
|
Handler: _HostCapabilities_Write_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "vagrant_caps/capabilities.proto",
|
Metadata: "vagrant_caps/capabilities.proto",
|
||||||
|
@ -729,6 +866,9 @@ var _HostCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
type ProviderCapabilitiesClient interface {
|
type ProviderCapabilitiesClient interface {
|
||||||
ProviderCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*ProviderCapabilitiesResponse, error)
|
ProviderCapabilities(ctx context.Context, in *vagrant_common.NullRequest, opts ...grpc.CallOption) (*ProviderCapabilitiesResponse, error)
|
||||||
ProviderCapability(ctx context.Context, in *ProviderCapabilityRequest, opts ...grpc.CallOption) (*ProviderCapabilityResponse, error)
|
ProviderCapability(ctx context.Context, in *ProviderCapabilityRequest, opts ...grpc.CallOption) (*ProviderCapabilityResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
type providerCapabilitiesClient struct {
|
type providerCapabilitiesClient struct {
|
||||||
|
@ -757,10 +897,31 @@ func (c *providerCapabilitiesClient) ProviderCapability(ctx context.Context, in
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *providerCapabilitiesClient) 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.caps.ProviderCapabilities/Read", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *providerCapabilitiesClient) 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.caps.ProviderCapabilities/Write", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ProviderCapabilitiesServer is the server API for ProviderCapabilities service.
|
// ProviderCapabilitiesServer is the server API for ProviderCapabilities service.
|
||||||
type ProviderCapabilitiesServer interface {
|
type ProviderCapabilitiesServer interface {
|
||||||
ProviderCapabilities(context.Context, *vagrant_common.NullRequest) (*ProviderCapabilitiesResponse, error)
|
ProviderCapabilities(context.Context, *vagrant_common.NullRequest) (*ProviderCapabilitiesResponse, error)
|
||||||
ProviderCapability(context.Context, *ProviderCapabilityRequest) (*ProviderCapabilityResponse, error)
|
ProviderCapability(context.Context, *ProviderCapabilityRequest) (*ProviderCapabilityResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterProviderCapabilitiesServer(s *grpc.Server, srv ProviderCapabilitiesServer) {
|
func RegisterProviderCapabilitiesServer(s *grpc.Server, srv ProviderCapabilitiesServer) {
|
||||||
|
@ -803,6 +964,42 @@ func _ProviderCapabilities_ProviderCapability_Handler(srv interface{}, ctx conte
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _ProviderCapabilities_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.(ProviderCapabilitiesServer).Read(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.caps.ProviderCapabilities/Read",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ProviderCapabilitiesServer).Read(ctx, req.(*vagrant_io.ReadRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _ProviderCapabilities_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.(ProviderCapabilitiesServer).Write(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.caps.ProviderCapabilities/Write",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ProviderCapabilitiesServer).Write(ctx, req.(*vagrant_io.WriteRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
var _ProviderCapabilities_serviceDesc = grpc.ServiceDesc{
|
var _ProviderCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
ServiceName: "vagrant.caps.ProviderCapabilities",
|
ServiceName: "vagrant.caps.ProviderCapabilities",
|
||||||
HandlerType: (*ProviderCapabilitiesServer)(nil),
|
HandlerType: (*ProviderCapabilitiesServer)(nil),
|
||||||
|
@ -815,6 +1012,14 @@ var _ProviderCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "ProviderCapability",
|
MethodName: "ProviderCapability",
|
||||||
Handler: _ProviderCapabilities_ProviderCapability_Handler,
|
Handler: _ProviderCapabilities_ProviderCapability_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Read",
|
||||||
|
Handler: _ProviderCapabilities_Read_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Write",
|
||||||
|
Handler: _ProviderCapabilities_Write_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "vagrant_caps/capabilities.proto",
|
Metadata: "vagrant_caps/capabilities.proto",
|
||||||
|
@ -823,37 +1028,40 @@ var _ProviderCapabilities_serviceDesc = grpc.ServiceDesc{
|
||||||
func init() { proto.RegisterFile("vagrant_caps/capabilities.proto", fileDescriptor_591a3013bd09a9cb) }
|
func init() { proto.RegisterFile("vagrant_caps/capabilities.proto", fileDescriptor_591a3013bd09a9cb) }
|
||||||
|
|
||||||
var fileDescriptor_591a3013bd09a9cb = []byte{
|
var fileDescriptor_591a3013bd09a9cb = []byte{
|
||||||
// 510 bytes of a gzipped FileDescriptorProto
|
// 560 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x95, 0xcf, 0x6e, 0xd3, 0x40,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x95, 0x4d, 0x6f, 0xd3, 0x30,
|
||||||
0x10, 0xc6, 0xb5, 0x14, 0x0a, 0x9d, 0x56, 0xfc, 0x59, 0x85, 0x60, 0x4c, 0x25, 0x22, 0x53, 0x44,
|
0x18, 0xc7, 0x95, 0xee, 0x05, 0xf6, 0x6c, 0xe2, 0xc5, 0x2a, 0x5d, 0x16, 0x26, 0x51, 0x85, 0x21,
|
||||||
0x84, 0x84, 0x2d, 0x85, 0x0b, 0x87, 0x1e, 0x90, 0xa8, 0x28, 0xe2, 0x80, 0x50, 0xe0, 0x56, 0x89,
|
0x2a, 0x24, 0x12, 0xa9, 0x5c, 0x40, 0xda, 0x01, 0x89, 0x89, 0x21, 0x0e, 0x08, 0x75, 0x48, 0x1c,
|
||||||
0x6a, 0x63, 0x16, 0x7b, 0x91, 0xbd, 0x6b, 0x76, 0xd7, 0x11, 0xe5, 0x11, 0xb8, 0x71, 0xe0, 0x8d,
|
0x26, 0x31, 0xb9, 0x9d, 0x49, 0x8d, 0x12, 0x3b, 0xd8, 0x4e, 0xc5, 0xf8, 0x08, 0xdc, 0x38, 0xf0,
|
||||||
0xb8, 0xf0, 0x16, 0x3c, 0x0a, 0xb2, 0xbd, 0x71, 0xed, 0x7a, 0x5d, 0x97, 0xd2, 0x53, 0x32, 0x93,
|
0x71, 0xb8, 0xf0, 0x2d, 0xf8, 0x36, 0x28, 0x89, 0x93, 0x25, 0x8b, 0xbb, 0x8c, 0xad, 0xd2, 0x4e,
|
||||||
0x99, 0xf9, 0xe6, 0xfb, 0xd9, 0x9a, 0xc0, 0xfd, 0x25, 0x89, 0x24, 0xe1, 0xfa, 0x30, 0x24, 0x99,
|
0xed, 0xf3, 0xf8, 0x79, 0xfb, 0xff, 0xec, 0xd8, 0xf0, 0x60, 0x86, 0x03, 0x81, 0x99, 0x3a, 0x9a,
|
||||||
0x0a, 0x42, 0x92, 0x91, 0x05, 0x4b, 0x98, 0x66, 0x54, 0xf9, 0x99, 0x14, 0x5a, 0xe0, 0x2d, 0x53,
|
0xe0, 0x58, 0xfa, 0x13, 0x1c, 0xe3, 0x31, 0x0d, 0xa9, 0xa2, 0x44, 0x7a, 0xb1, 0xe0, 0x8a, 0xa3,
|
||||||
0xe0, 0x17, 0x05, 0xee, 0x41, 0xc4, 0x74, 0x9c, 0x2f, 0xfc, 0x50, 0xa4, 0x41, 0x4c, 0x54, 0xcc,
|
0x0d, 0x1d, 0xe0, 0xa5, 0x01, 0xce, 0x61, 0x40, 0xd5, 0x34, 0x19, 0x7b, 0x13, 0x1e, 0xf9, 0x53,
|
||||||
0x42, 0x21, 0xb3, 0xc0, 0x94, 0x04, 0xf4, 0xab, 0x0e, 0x22, 0xf1, 0x24, 0x4b, 0xf2, 0x88, 0xf1,
|
0x2c, 0xa7, 0x74, 0xc2, 0x45, 0xec, 0xeb, 0x10, 0x9f, 0x7c, 0x53, 0x7e, 0xc0, 0x9f, 0xc6, 0x61,
|
||||||
0x3a, 0x6b, 0xc2, 0x72, 0x5c, 0x50, 0xcb, 0x89, 0x34, 0x15, 0x3c, 0xa8, 0x3e, 0x2a, 0x29, 0x6f,
|
0x12, 0x50, 0x56, 0x7a, 0xb5, 0x99, 0x95, 0xf3, 0xcb, 0x76, 0x3c, 0x8a, 0x38, 0xf3, 0xf3, 0x9f,
|
||||||
0x17, 0xe0, 0xc5, 0x6a, 0x81, 0x23, 0x8c, 0xe1, 0x32, 0x27, 0x29, 0x75, 0xd0, 0x04, 0x4d, 0x37,
|
0xbc, 0x95, 0x73, 0xb0, 0xa8, 0xe2, 0x94, 0xfb, 0x94, 0xe7, 0x45, 0xdd, 0x5d, 0x80, 0x57, 0x85,
|
||||||
0xe6, 0xe5, 0x77, 0xec, 0xc2, 0xb5, 0x2c, 0x21, 0xfa, 0x93, 0x90, 0xa9, 0x73, 0xa9, 0xcc, 0xd7,
|
0xaa, 0x13, 0x84, 0x60, 0x99, 0xe1, 0x88, 0xd8, 0x56, 0xdf, 0x1a, 0xac, 0x8d, 0xb2, 0xff, 0xc8,
|
||||||
0xb1, 0xb7, 0x07, 0xf8, 0xad, 0x14, 0x4b, 0xf6, 0x91, 0xca, 0x33, 0x4c, 0x31, 0x95, 0xf5, 0x14,
|
0x81, 0x9b, 0x71, 0x88, 0xd5, 0x67, 0x2e, 0x22, 0xbb, 0x93, 0xf9, 0x4b, 0xdb, 0xdd, 0x03, 0xf4,
|
||||||
0x13, 0x7b, 0xdf, 0x60, 0xbb, 0x33, 0x85, 0x51, 0x35, 0xa7, 0x2a, 0x13, 0x5c, 0x51, 0xbc, 0x07,
|
0x5e, 0xf0, 0x19, 0x3d, 0x26, 0xe2, 0x02, 0x55, 0x74, 0x64, 0x59, 0x45, 0xdb, 0xee, 0x77, 0xd8,
|
||||||
0x5b, 0x4d, 0x48, 0x0e, 0x9a, 0xac, 0x4d, 0x37, 0x67, 0x13, 0xbf, 0x49, 0xc9, 0xef, 0xee, 0x31,
|
0x6e, 0x54, 0xa1, 0x44, 0x8e, 0x88, 0x8c, 0x39, 0x93, 0x04, 0xed, 0xc1, 0x46, 0x95, 0xbc, 0x6d,
|
||||||
0x6f, 0x75, 0xe1, 0x11, 0x5c, 0xa1, 0x52, 0x8a, 0x95, 0x7c, 0x15, 0x78, 0x3f, 0x11, 0xdc, 0xb5,
|
0xf5, 0x97, 0x06, 0xeb, 0xc3, 0xbe, 0x57, 0x45, 0xef, 0x35, 0xe7, 0x18, 0xd5, 0xb2, 0x50, 0x17,
|
||||||
0xb4, 0xd2, 0x2f, 0x39, 0x55, 0x1a, 0x3f, 0x07, 0xa8, 0x67, 0x1c, 0x95, 0x7e, 0xce, 0xa2, 0xdb,
|
0x56, 0x88, 0x10, 0xbc, 0x68, 0x9f, 0x1b, 0xee, 0x2f, 0x0b, 0xb6, 0x0c, 0xa9, 0xe4, 0x6b, 0x42,
|
||||||
0xe8, 0xc1, 0x0e, 0x5c, 0x4d, 0x49, 0x18, 0x33, 0x4e, 0x8d, 0xee, 0x2a, 0xc4, 0xdb, 0xb0, 0x41,
|
0xa4, 0x42, 0x2f, 0x01, 0xca, 0x1a, 0x27, 0x99, 0x9e, 0x8b, 0xf4, 0xad, 0xe4, 0x20, 0x1b, 0x6e,
|
||||||
0x64, 0x94, 0xa7, 0x94, 0x6b, 0xe5, 0xac, 0x95, 0xbf, 0x1d, 0x27, 0xbc, 0xd7, 0xe0, 0xda, 0xd6,
|
0x44, 0x78, 0x32, 0xa5, 0x8c, 0xe8, 0xbe, 0x85, 0x89, 0xb6, 0x61, 0x0d, 0x8b, 0x20, 0x89, 0x08,
|
||||||
0x32, 0x44, 0xc6, 0xb0, 0x2e, 0xa9, 0xca, 0x13, 0x6d, 0x18, 0x9b, 0xa8, 0xc7, 0xe3, 0x67, 0x18,
|
0x53, 0xd2, 0x5e, 0xca, 0xd6, 0x4e, 0x1d, 0xee, 0x5b, 0x70, 0x4c, 0x63, 0x69, 0x22, 0x3d, 0x58,
|
||||||
0x59, 0xb9, 0xee, 0x5a, 0xb9, 0x3a, 0x6d, 0x7f, 0xff, 0xc8, 0xf3, 0x3b, 0x82, 0xf1, 0x7e, 0xc1,
|
0x15, 0x44, 0x26, 0xa1, 0xd2, 0x8c, 0xb5, 0x35, 0x47, 0xe3, 0x17, 0xe8, 0x1a, 0xb9, 0xee, 0x1a,
|
||||||
0xae, 0x0b, 0xf3, 0x99, 0x05, 0x66, 0xbf, 0xd8, 0x45, 0x40, 0xdc, 0x87, 0x3b, 0x9d, 0x5d, 0xce,
|
0xb9, 0xda, 0x75, 0x7d, 0xff, 0xc9, 0xf3, 0x87, 0x05, 0xbd, 0xfd, 0x94, 0x5d, 0x13, 0xe6, 0x73,
|
||||||
0x45, 0xf0, 0x07, 0x82, 0xdb, 0xaf, 0xc4, 0xc5, 0x9a, 0x9a, 0xc0, 0x26, 0xe5, 0x4b, 0x26, 0x05,
|
0x03, 0xcc, 0xf9, 0xcd, 0x16, 0x01, 0x71, 0x1f, 0x36, 0x1b, 0xb3, 0x5c, 0x8a, 0xe0, 0x4f, 0x0b,
|
||||||
0x2f, 0x96, 0x35, 0x7a, 0xcd, 0xd4, 0x80, 0xb9, 0x97, 0x30, 0x3e, 0xb9, 0xd2, 0x79, 0xbc, 0xcd,
|
0xee, 0xbd, 0xe1, 0x8b, 0x15, 0xd5, 0x87, 0x75, 0xc2, 0x66, 0x54, 0x70, 0x96, 0x0e, 0xab, 0xfb,
|
||||||
0x7e, 0x23, 0xb8, 0xd5, 0xa6, 0x54, 0x3c, 0xdd, 0xf7, 0xb6, 0xe4, 0xbd, 0x63, 0x63, 0xd5, 0x0d,
|
0x55, 0x5d, 0x2d, 0xe2, 0x5e, 0x43, 0xef, 0xec, 0x48, 0x97, 0xd1, 0x36, 0xfc, 0xd3, 0x81, 0xbb,
|
||||||
0x79, 0x93, 0x27, 0x89, 0x21, 0xe1, 0x7a, 0x3d, 0xae, 0x9b, 0x6f, 0xdc, 0x07, 0xb8, 0x71, 0xe2,
|
0x75, 0x4a, 0xe9, 0xee, 0x7e, 0x30, 0x39, 0xef, 0x9f, 0x0a, 0xcb, 0x2f, 0xa6, 0x77, 0x49, 0x18,
|
||||||
0x81, 0xe0, 0x9d, 0x76, 0x9b, 0xfd, 0xdd, 0x71, 0x1f, 0x0e, 0x54, 0x55, 0xf3, 0x67, 0xbf, 0x10,
|
0x6a, 0x12, 0x8e, 0x3b, 0x47, 0x75, 0xf5, 0xc4, 0x7d, 0x82, 0xdb, 0x67, 0x36, 0x04, 0xed, 0xd4,
|
||||||
0xdc, 0x6c, 0x41, 0x29, 0xb6, 0x7e, 0x67, 0xc9, 0xfd, 0xb7, 0x93, 0x03, 0xb8, 0xde, 0xa6, 0x8f,
|
0xd3, 0xcc, 0x67, 0xc7, 0x79, 0xd4, 0x12, 0xa5, 0xeb, 0xbf, 0x80, 0xe5, 0x11, 0xc1, 0xc7, 0x68,
|
||||||
0x1f, 0xb4, 0xbb, 0xac, 0xaf, 0x8b, 0xbb, 0x73, 0x7a, 0x91, 0xb1, 0xf1, 0x07, 0xc1, 0xc8, 0x76,
|
0xb3, 0x0c, 0xa7, 0xdc, 0x4b, 0x3d, 0x45, 0x1d, 0xbb, 0xb9, 0x50, 0x7e, 0x0c, 0x2b, 0x1f, 0x05,
|
||||||
0x11, 0xf1, 0x61, 0x4f, 0xfe, 0x54, 0x3b, 0x8f, 0x07, 0x0e, 0x56, 0xd3, 0x56, 0x64, 0x3d, 0xe8,
|
0x55, 0x04, 0xd5, 0x42, 0x32, 0x57, 0x91, 0xbc, 0x65, 0x58, 0xc9, 0xb3, 0x87, 0xbf, 0x3b, 0x70,
|
||||||
0x8f, 0x06, 0x4f, 0x9e, 0x91, 0x9a, 0x0e, 0x17, 0x56, 0x42, 0x8b, 0xf5, 0xf2, 0xef, 0xe7, 0xe9,
|
0xa7, 0xb6, 0x1b, 0x29, 0xae, 0x03, 0x83, 0xef, 0xca, 0x08, 0x0f, 0xe1, 0x56, 0x7d, 0xdb, 0xd1,
|
||||||
0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0xfc, 0x96, 0xa9, 0x0c, 0x07, 0x00, 0x00,
|
0xc3, 0x7a, 0x96, 0xf1, 0x9c, 0x3a, 0x3b, 0xe7, 0x07, 0x5d, 0x37, 0xbf, 0xbf, 0x1d, 0xe8, 0x9a,
|
||||||
|
0xde, 0x00, 0x74, 0x34, 0xc7, 0x7f, 0x2e, 0xc7, 0x27, 0x2d, 0x57, 0x74, 0x95, 0x67, 0x60, 0x7c,
|
||||||
|
0xc2, 0x1e, 0xb7, 0x5e, 0xf2, 0xba, 0xd5, 0xa0, 0x3d, 0xf0, 0x9a, 0xd9, 0x8e, 0x57, 0xb3, 0x97,
|
||||||
|
0xfe, 0xd9, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x37, 0xe6, 0x14, 0x9d, 0xcc, 0x08, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ syntax = "proto3";
|
||||||
package vagrant.caps;
|
package vagrant.caps;
|
||||||
|
|
||||||
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_common/common.proto";
|
||||||
|
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io/io.proto";
|
||||||
|
|
||||||
message Capability {
|
message Capability {
|
||||||
string name = 1;
|
string name = 1;
|
||||||
|
@ -59,14 +60,23 @@ message HostCapabilityResponse {
|
||||||
service GuestCapabilities {
|
service GuestCapabilities {
|
||||||
rpc GuestCapabilities(vagrant.common.NullRequest) returns (CapabilitiesResponse);
|
rpc GuestCapabilities(vagrant.common.NullRequest) returns (CapabilitiesResponse);
|
||||||
rpc GuestCapability(GuestCapabilityRequest) returns (GuestCapabilityResponse);
|
rpc GuestCapability(GuestCapabilityRequest) returns (GuestCapabilityResponse);
|
||||||
|
// These are IO helpers for streaming
|
||||||
|
rpc Read(vagrant.io.ReadRequest) returns (vagrant.io.ReadResponse);
|
||||||
|
rpc Write(vagrant.io.WriteRequest) returns (vagrant.io.WriteResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
service HostCapabilities {
|
service HostCapabilities {
|
||||||
rpc HostCapabilities(vagrant.common.NullRequest) returns (CapabilitiesResponse);
|
rpc HostCapabilities(vagrant.common.NullRequest) returns (CapabilitiesResponse);
|
||||||
rpc HostCapability(HostCapabilityRequest) returns (HostCapabilityResponse);
|
rpc HostCapability(HostCapabilityRequest) returns (HostCapabilityResponse);
|
||||||
|
// These are IO helpers for streaming
|
||||||
|
rpc Read(vagrant.io.ReadRequest) returns (vagrant.io.ReadResponse);
|
||||||
|
rpc Write(vagrant.io.WriteRequest) returns (vagrant.io.WriteResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
service ProviderCapabilities {
|
service ProviderCapabilities {
|
||||||
rpc ProviderCapabilities(vagrant.common.NullRequest) returns (ProviderCapabilitiesResponse);
|
rpc ProviderCapabilities(vagrant.common.NullRequest) returns (ProviderCapabilitiesResponse);
|
||||||
rpc ProviderCapability(ProviderCapabilityRequest) returns (ProviderCapabilityResponse);
|
rpc ProviderCapability(ProviderCapabilityRequest) returns (ProviderCapabilityResponse);
|
||||||
|
// These are IO helpers for streaming
|
||||||
|
rpc Read(vagrant.io.ReadRequest) returns (vagrant.io.ReadResponse);
|
||||||
|
rpc Write(vagrant.io.WriteRequest) returns (vagrant.io.WriteResponse);
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import proto "github.com/golang/protobuf/proto"
|
||||||
import fmt "fmt"
|
import fmt "fmt"
|
||||||
import math "math"
|
import math "math"
|
||||||
import vagrant_common "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_common"
|
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 (
|
import (
|
||||||
context "golang.org/x/net/context"
|
context "golang.org/x/net/context"
|
||||||
|
@ -356,6 +357,9 @@ type ConfigClient interface {
|
||||||
ConfigLoad(ctx context.Context, in *LoadRequest, opts ...grpc.CallOption) (*LoadResponse, error)
|
ConfigLoad(ctx context.Context, in *LoadRequest, opts ...grpc.CallOption) (*LoadResponse, error)
|
||||||
ConfigValidate(ctx context.Context, in *ValidateRequest, opts ...grpc.CallOption) (*ValidateResponse, error)
|
ConfigValidate(ctx context.Context, in *ValidateRequest, opts ...grpc.CallOption) (*ValidateResponse, error)
|
||||||
ConfigFinalize(ctx context.Context, in *FinalizeRequest, opts ...grpc.CallOption) (*FinalizeResponse, error)
|
ConfigFinalize(ctx context.Context, in *FinalizeRequest, opts ...grpc.CallOption) (*FinalizeResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
type configClient struct {
|
type configClient struct {
|
||||||
|
@ -402,12 +406,33 @@ func (c *configClient) ConfigFinalize(ctx context.Context, in *FinalizeRequest,
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *configClient) 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.config.Config/Read", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configClient) 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.config.Config/Write", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ConfigServer is the server API for Config service.
|
// ConfigServer is the server API for Config service.
|
||||||
type ConfigServer interface {
|
type ConfigServer interface {
|
||||||
ConfigAttributes(context.Context, *vagrant_common.NullRequest) (*AttributesResponse, error)
|
ConfigAttributes(context.Context, *vagrant_common.NullRequest) (*AttributesResponse, error)
|
||||||
ConfigLoad(context.Context, *LoadRequest) (*LoadResponse, error)
|
ConfigLoad(context.Context, *LoadRequest) (*LoadResponse, error)
|
||||||
ConfigValidate(context.Context, *ValidateRequest) (*ValidateResponse, error)
|
ConfigValidate(context.Context, *ValidateRequest) (*ValidateResponse, error)
|
||||||
ConfigFinalize(context.Context, *FinalizeRequest) (*FinalizeResponse, error)
|
ConfigFinalize(context.Context, *FinalizeRequest) (*FinalizeResponse, 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterConfigServer(s *grpc.Server, srv ConfigServer) {
|
func RegisterConfigServer(s *grpc.Server, srv ConfigServer) {
|
||||||
|
@ -486,6 +511,42 @@ func _Config_ConfigFinalize_Handler(srv interface{}, ctx context.Context, dec fu
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _Config_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.(ConfigServer).Read(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.config.Config/Read",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ConfigServer).Read(ctx, req.(*vagrant_io.ReadRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Config_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.(ConfigServer).Write(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/vagrant.config.Config/Write",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ConfigServer).Write(ctx, req.(*vagrant_io.WriteRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
var _Config_serviceDesc = grpc.ServiceDesc{
|
var _Config_serviceDesc = grpc.ServiceDesc{
|
||||||
ServiceName: "vagrant.config.Config",
|
ServiceName: "vagrant.config.Config",
|
||||||
HandlerType: (*ConfigServer)(nil),
|
HandlerType: (*ConfigServer)(nil),
|
||||||
|
@ -506,6 +567,14 @@ var _Config_serviceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "ConfigFinalize",
|
MethodName: "ConfigFinalize",
|
||||||
Handler: _Config_ConfigFinalize_Handler,
|
Handler: _Config_ConfigFinalize_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Read",
|
||||||
|
Handler: _Config_Read_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Write",
|
||||||
|
Handler: _Config_Write_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "vagrant_config/config.proto",
|
Metadata: "vagrant_config/config.proto",
|
||||||
|
@ -514,28 +583,31 @@ var _Config_serviceDesc = grpc.ServiceDesc{
|
||||||
func init() { proto.RegisterFile("vagrant_config/config.proto", fileDescriptor_952629f1a9a7438c) }
|
func init() { proto.RegisterFile("vagrant_config/config.proto", fileDescriptor_952629f1a9a7438c) }
|
||||||
|
|
||||||
var fileDescriptor_952629f1a9a7438c = []byte{
|
var fileDescriptor_952629f1a9a7438c = []byte{
|
||||||
// 363 bytes of a gzipped FileDescriptorProto
|
// 415 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xc1, 0x4b, 0xfb, 0x30,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0xdf, 0x6b, 0xdb, 0x30,
|
||||||
0x14, 0xc7, 0xd9, 0x7e, 0x3f, 0x27, 0x7b, 0xca, 0x36, 0x82, 0x48, 0xe9, 0x44, 0x67, 0x41, 0xd8,
|
0x10, 0xc7, 0xc9, 0xf2, 0x63, 0xe4, 0x36, 0x92, 0x20, 0xc6, 0xe6, 0x39, 0x63, 0xcb, 0x0c, 0x83,
|
||||||
0xc5, 0x06, 0xf4, 0xe2, 0x41, 0x50, 0x11, 0x14, 0x44, 0x3c, 0x74, 0xe0, 0xc5, 0x83, 0x64, 0x5d,
|
0xbc, 0xcc, 0x82, 0xed, 0x65, 0x83, 0xc0, 0x56, 0x0a, 0x2d, 0x94, 0xd2, 0x07, 0x07, 0xda, 0x87,
|
||||||
0x6c, 0x03, 0x6d, 0x52, 0xd3, 0x54, 0xc4, 0xbf, 0xd2, 0x3f, 0x49, 0x4c, 0xd2, 0x75, 0xeb, 0xd6,
|
0x3e, 0x14, 0xc5, 0x56, 0x6d, 0x81, 0x6d, 0xb9, 0xb2, 0x5c, 0x4a, 0xff, 0xc3, 0xfe, 0x57, 0x25,
|
||||||
0x81, 0xa7, 0xe4, 0xbd, 0x7c, 0xf3, 0x79, 0xc9, 0xfb, 0x3e, 0x18, 0x7e, 0x90, 0x48, 0x12, 0xae,
|
0x92, 0x1c, 0x27, 0xb6, 0x13, 0x28, 0xf4, 0xc9, 0xba, 0xbb, 0xef, 0x7d, 0x4e, 0xba, 0x3b, 0xc3,
|
||||||
0x5e, 0x43, 0xc1, 0xdf, 0x58, 0x84, 0xcd, 0xe2, 0x67, 0x52, 0x28, 0x81, 0x7a, 0xf6, 0xd0, 0x37,
|
0xf4, 0x9e, 0x84, 0x82, 0xa4, 0xf2, 0xc6, 0xe7, 0xe9, 0x2d, 0x0b, 0xb1, 0xfe, 0xb8, 0x99, 0xe0,
|
||||||
0x59, 0xf7, 0x25, 0x62, 0x2a, 0x2e, 0xa6, 0x7e, 0x28, 0x52, 0x1c, 0x93, 0x3c, 0x66, 0xa1, 0x90,
|
0x92, 0xa3, 0x91, 0x09, 0xba, 0xda, 0x6b, 0x5f, 0x87, 0x4c, 0x46, 0xc5, 0xca, 0xf5, 0x79, 0x82,
|
||||||
0x19, 0xb6, 0x22, 0x4c, 0x3f, 0x15, 0x8e, 0xc4, 0x69, 0x96, 0x14, 0x11, 0xe3, 0xf3, 0xac, 0x0d,
|
0x23, 0x92, 0x47, 0xcc, 0xe7, 0x22, 0xc3, 0x46, 0x84, 0xe9, 0x83, 0xc4, 0x21, 0xff, 0x99, 0xc5,
|
||||||
0x35, 0x10, 0x57, 0xc5, 0xd2, 0x54, 0x70, 0x6c, 0x16, 0x53, 0xcc, 0x7b, 0x00, 0x74, 0xa3, 0x94,
|
0x45, 0xc8, 0xd2, 0x8d, 0xd7, 0x98, 0x0a, 0x88, 0xab, 0x62, 0x49, 0xc2, 0x53, 0xac, 0x3f, 0xba,
|
||||||
0x64, 0xd3, 0x42, 0xd1, 0x3c, 0xa0, 0x79, 0x26, 0x78, 0x4e, 0xd1, 0x21, 0x00, 0x99, 0x67, 0x9d,
|
0x98, 0xbd, 0x7c, 0x2d, 0x38, 0xe3, 0x98, 0x71, 0x0d, 0x75, 0xce, 0x00, 0x1d, 0x49, 0x29, 0xd8,
|
||||||
0xd6, 0xe8, 0xdf, 0xb8, 0x1b, 0x2c, 0x64, 0xd0, 0x1e, 0x6c, 0x51, 0x29, 0x85, 0x74, 0xda, 0xa3,
|
0xaa, 0x90, 0x34, 0xf7, 0x68, 0x9e, 0xf1, 0x34, 0xa7, 0xe8, 0x2b, 0x00, 0xd9, 0x78, 0xad, 0xce,
|
||||||
0xd6, 0xb8, 0x1b, 0x98, 0xc0, 0x3b, 0x86, 0x9d, 0x47, 0x41, 0x66, 0x01, 0x7d, 0x2f, 0x68, 0xae,
|
0xac, 0x3b, 0x1f, 0x7a, 0x5b, 0x1e, 0xf4, 0x01, 0xfa, 0x54, 0x08, 0x2e, 0xac, 0x37, 0xb3, 0xce,
|
||||||
0x10, 0x82, 0xff, 0x33, 0xa2, 0x88, 0xd3, 0xd2, 0x1a, 0xbd, 0xf7, 0x2e, 0x60, 0xd7, 0x48, 0x6c,
|
0x7c, 0xe8, 0x69, 0xc3, 0xf9, 0x0e, 0xef, 0xce, 0x39, 0x09, 0x3c, 0x7a, 0x57, 0xd0, 0x5c, 0x22,
|
||||||
0xa1, 0x35, 0x9a, 0x06, 0xf8, 0x15, 0xf4, 0x9f, 0x49, 0xc2, 0x66, 0x44, 0xd1, 0x0d, 0x05, 0x90,
|
0x04, 0xbd, 0x80, 0x48, 0x62, 0x75, 0x94, 0x46, 0x9d, 0x9d, 0x3f, 0xf0, 0x5e, 0x4b, 0x4c, 0xa1,
|
||||||
0x03, 0xdb, 0x29, 0x09, 0x63, 0xc6, 0xa9, 0xbd, 0x5e, 0x86, 0xde, 0x35, 0x0c, 0x2a, 0x80, 0x2d,
|
0x16, 0xcd, 0x1e, 0xf8, 0x3f, 0x18, 0x5f, 0x92, 0x98, 0x05, 0x44, 0xd2, 0x03, 0x05, 0x90, 0x05,
|
||||||
0xbf, 0x0f, 0x1d, 0x4d, 0x2f, 0xff, 0x68, 0xa3, 0x86, 0x27, 0x9c, 0x40, 0xff, 0x8e, 0x71, 0x92,
|
0x6f, 0x13, 0xe2, 0x47, 0x2c, 0xa5, 0x26, 0xbd, 0x34, 0x9d, 0xff, 0x30, 0xa9, 0x00, 0xa6, 0xfc,
|
||||||
0xb0, 0xaf, 0x4d, 0x4f, 0xf0, 0x2e, 0x61, 0x50, 0xc9, 0xfe, 0xfa, 0xcf, 0xb3, 0xef, 0x36, 0x74,
|
0x47, 0x18, 0x28, 0x7a, 0xf9, 0x46, 0x63, 0xed, 0xb9, 0xc2, 0x0f, 0x18, 0x9f, 0xb0, 0x94, 0xc4,
|
||||||
0x6e, 0xb5, 0xf1, 0x68, 0x02, 0x03, 0xb3, 0xab, 0x1c, 0x42, 0x43, 0xbf, 0x9a, 0x0e, 0x6d, 0xe3,
|
0xec, 0xf1, 0xd0, 0x15, 0x9c, 0x05, 0x4c, 0x2a, 0xd9, 0x4b, 0xdf, 0xf9, 0xeb, 0xa9, 0x0b, 0x83,
|
||||||
0x53, 0x91, 0x24, 0xf6, 0x35, 0xae, 0xe7, 0x2f, 0x8f, 0x8e, 0xbf, 0xc6, 0xda, 0x7b, 0x00, 0x03,
|
0x63, 0xb5, 0x4d, 0x68, 0x09, 0x13, 0x7d, 0xaa, 0x26, 0x84, 0xa6, 0x6e, 0xb5, 0x72, 0x6a, 0x37,
|
||||||
0xfd, 0xf5, 0x61, 0x09, 0xa7, 0x6f, 0x2c, 0x18, 0xe8, 0x1e, 0xac, 0x3f, 0xb4, 0xa0, 0x09, 0xf4,
|
0x2e, 0x8a, 0x38, 0x36, 0xb7, 0xb1, 0x1d, 0x77, 0x77, 0x1f, 0xdd, 0x96, 0xd1, 0x9e, 0x02, 0x68,
|
||||||
0x0c, 0xa8, 0xec, 0x2a, 0x3a, 0xaa, 0xeb, 0x6b, 0x86, 0xb9, 0xa3, 0x66, 0x41, 0x1d, 0x5a, 0x76,
|
0xe8, 0x7a, 0x0e, 0x3b, 0x38, 0x95, 0xb1, 0x35, 0x40, 0xfb, 0x4b, 0x7b, 0xd0, 0x80, 0x96, 0x30,
|
||||||
0x70, 0x15, 0x5a, 0xb3, 0x60, 0x15, 0x5a, 0x6f, 0xfe, 0xb4, 0xa3, 0x47, 0xfd, 0xfc, 0x27, 0x00,
|
0xd2, 0xa0, 0xb2, 0xab, 0xe8, 0x5b, 0x5d, 0x5f, 0x1b, 0x98, 0x3d, 0xdb, 0x2f, 0xa8, 0x43, 0xcb,
|
||||||
0x00, 0xff, 0xff, 0xe0, 0x00, 0xbf, 0x51, 0x76, 0x03, 0x00, 0x00,
|
0x0e, 0x36, 0xa1, 0xb5, 0x11, 0x34, 0xa1, 0x8d, 0xe6, 0xff, 0x85, 0x9e, 0x47, 0x49, 0x80, 0x3e,
|
||||||
|
0x6d, 0x94, 0x8c, 0xbb, 0x6b, 0x4f, 0x89, 0xb0, 0x9a, 0x01, 0x93, 0xba, 0x80, 0xfe, 0x95, 0x60,
|
||||||
|
0x92, 0xa2, 0x1d, 0x89, 0x72, 0x95, 0xc9, 0x9f, 0x5b, 0x22, 0x3a, 0x7b, 0x35, 0x50, 0xff, 0xd8,
|
||||||
|
0xef, 0xe7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x44, 0xad, 0xc6, 0x44, 0x04, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ syntax = "proto3";
|
||||||
package vagrant.config;
|
package vagrant.config;
|
||||||
|
|
||||||
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_common/common.proto";
|
||||||
|
import "github.com/hashicorp/vagrant/ext/go-plugin/vagrant/plugin/proto/vagrant_io/io.proto";
|
||||||
|
|
||||||
message AttributesResponse {
|
message AttributesResponse {
|
||||||
repeated string attributes = 1;
|
repeated string attributes = 1;
|
||||||
|
@ -41,4 +42,7 @@ service Config {
|
||||||
rpc ConfigLoad(LoadRequest) returns (LoadResponse);
|
rpc ConfigLoad(LoadRequest) returns (LoadResponse);
|
||||||
rpc ConfigValidate(ValidateRequest) returns (ValidateResponse);
|
rpc ConfigValidate(ValidateRequest) returns (ValidateResponse);
|
||||||
rpc ConfigFinalize(FinalizeRequest) returns (FinalizeResponse);
|
rpc ConfigFinalize(FinalizeRequest) returns (FinalizeResponse);
|
||||||
|
// These are IO helpers for streaming
|
||||||
|
rpc Read(vagrant.io.ReadRequest) returns (vagrant.io.ReadResponse);
|
||||||
|
rpc Write(vagrant.io.WriteRequest) returns (vagrant.io.WriteResponse);
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ package plugin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
@ -110,19 +111,26 @@ func (c *GRPCProviderClient) MachineIdChanged(m *vagrant.Machine) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GRPCProviderClient) RunAction(actName string, runData string, m *vagrant.Machine) (r string, err error) {
|
func (c *GRPCProviderClient) RunAction(actName string, args interface{}, m *vagrant.Machine) (r interface{}, err error) {
|
||||||
machData, err := vagrant.DumpMachine(m)
|
machData, err := vagrant.DumpMachine(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
runData, err := json.Marshal(args)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
resp, err := c.client.RunAction(context.Background(), &vagrant_provider.RunActionRequest{
|
resp, err := c.client.RunAction(context.Background(), &vagrant_provider.RunActionRequest{
|
||||||
Name: actName,
|
Name: actName,
|
||||||
Data: runData,
|
Data: string(runData),
|
||||||
Machine: machData})
|
Machine: machData})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r = resp.Data
|
err = json.Unmarshal([]byte(resp.Data), &r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if resp.Error != "" {
|
if resp.Error != "" {
|
||||||
err = errors.New(resp.Error)
|
err = errors.New(resp.Error)
|
||||||
}
|
}
|
||||||
|
@ -178,10 +186,6 @@ func (c *GRPCProviderClient) Name() string {
|
||||||
return resp.Name
|
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) {
|
func (p *ProviderPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
client := vagrant_provider.NewProviderClient(c)
|
client := vagrant_provider.NewProviderClient(c)
|
||||||
return &GRPCProviderClient{
|
return &GRPCProviderClient{
|
||||||
|
@ -199,12 +203,7 @@ func (p *ProviderPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCB
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type GRPCProviderPlugin struct {
|
func (p *ProviderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
ProviderPlugin
|
|
||||||
Impl Provider
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *GRPCProviderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
|
||||||
p.Impl.Init()
|
p.Impl.Init()
|
||||||
vagrant_provider.RegisterProviderServer(s, &GRPCProviderServer{
|
vagrant_provider.RegisterProviderServer(s, &GRPCProviderServer{
|
||||||
Impl: p.Impl,
|
Impl: p.Impl,
|
||||||
|
@ -221,10 +220,6 @@ func (p *GRPCProviderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Se
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *GRPCProviderPlugin) GRPCClient(context.Context, *go_plugin.GRPCBroker, *grpc.ClientConn) (interface{}, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GRPCProviderServer struct {
|
type GRPCProviderServer struct {
|
||||||
GRPCIOServer
|
GRPCIOServer
|
||||||
GRPCConfigServer
|
GRPCConfigServer
|
||||||
|
@ -257,12 +252,21 @@ func (s *GRPCProviderServer) RunAction(ctx context.Context, req *vagrant_provide
|
||||||
resp.Error = e.Error()
|
resp.Error = e.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r, e := s.Impl.RunAction(req.Name, req.Data, m)
|
var args interface{}
|
||||||
|
err = json.Unmarshal([]byte(req.Data), &args)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r, e := s.Impl.RunAction(req.Name, args, m)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
resp.Error = e.Error()
|
resp.Error = e.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp.Data = r
|
result, err := json.Marshal(r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.Data = string(result)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestProvider_Action(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := impl.Action("valid", &vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if resp[0] != "self::DoTask" {
|
||||||
|
t.Errorf("%s != self::DoTask", resp[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_Action_invalid(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = impl.Action("invalid", &vagrant.Machine{})
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("illegal action")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_IsInstalled(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
installed, err := impl.IsInstalled(&vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if !installed {
|
||||||
|
t.Errorf("bad result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_IsUsable(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
usable, err := impl.IsUsable(&vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if !usable {
|
||||||
|
t.Errorf("bad result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_MachineIdChanged(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = impl.MachineIdChanged(&vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_Name(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := impl.Name()
|
||||||
|
if resp != "mock_provider" {
|
||||||
|
t.Errorf("%s != mock_provider", resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_RunAction(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{"test_arg", "other_arg"}
|
||||||
|
m := &vagrant.Machine{}
|
||||||
|
|
||||||
|
resp, err := impl.RunAction("valid", args, m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := resp.([]interface{})
|
||||||
|
if result[0] != "valid" {
|
||||||
|
t.Errorf("%s != valid", result[0])
|
||||||
|
}
|
||||||
|
if result[1] != "test_arg" {
|
||||||
|
t.Errorf("%s != test_arg", result[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_RunAction_invalid(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{"test_arg", "other_arg"}
|
||||||
|
m := &vagrant.Machine{}
|
||||||
|
|
||||||
|
_, err = impl.RunAction("invalid", args, m)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("illegal action run")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_SshInfo(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := impl.SshInfo(&vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("invalid resp: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Host != "localhost" {
|
||||||
|
t.Errorf("%s != localhost", resp.Host)
|
||||||
|
}
|
||||||
|
if resp.Port != 2222 {
|
||||||
|
t.Errorf("%d != 2222", resp.Port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_State(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := impl.State(&vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("invalid resp: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Id != "default" {
|
||||||
|
t.Errorf("%s != default", resp.Id)
|
||||||
|
}
|
||||||
|
if resp.ShortDesc != "running" {
|
||||||
|
t.Errorf("%s != running", resp.ShortDesc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_Info(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := impl.Info()
|
||||||
|
|
||||||
|
if resp.Description != "Custom" {
|
||||||
|
t.Errorf("%s != Custom", resp.Description)
|
||||||
|
}
|
||||||
|
if resp.Priority != 10 {
|
||||||
|
t.Errorf("%d != 10", resp.Priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_MachineUI_output(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"provider": &ProviderPlugin{Impl: &MockProvider{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("provider")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(Provider)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_, err = impl.RunAction("send_output", nil, &vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
resp, err := impl.Read("stdout")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(resp, "test_output_p") {
|
||||||
|
t.Errorf("%s !~ test_output_p", resp)
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,7 @@ type GRPCSyncedFolderClient struct {
|
||||||
client vagrant_folder.SyncedFolderClient
|
client vagrant_folder.SyncedFolderClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GRPCSyncedFolderClient) Cleanup(m *vagrant.Machine, o *vagrant.FolderOptions) (err error) {
|
func (c *GRPCSyncedFolderClient) Cleanup(m *vagrant.Machine, o vagrant.FolderOptions) (err error) {
|
||||||
machine, err := vagrant.DumpMachine(m)
|
machine, err := vagrant.DumpMachine(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -52,7 +52,7 @@ func (c *GRPCSyncedFolderClient) Cleanup(m *vagrant.Machine, o *vagrant.FolderOp
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GRPCSyncedFolderClient) Disable(m *vagrant.Machine, f *vagrant.FolderList, o *vagrant.FolderOptions) (err error) {
|
func (c *GRPCSyncedFolderClient) Disable(m *vagrant.Machine, f vagrant.FolderList, o vagrant.FolderOptions) (err error) {
|
||||||
machine, err := vagrant.DumpMachine(m)
|
machine, err := vagrant.DumpMachine(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -78,7 +78,7 @@ func (c *GRPCSyncedFolderClient) Disable(m *vagrant.Machine, f *vagrant.FolderLi
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GRPCSyncedFolderClient) Enable(m *vagrant.Machine, f *vagrant.FolderList, o *vagrant.FolderOptions) (err error) {
|
func (c *GRPCSyncedFolderClient) Enable(m *vagrant.Machine, f vagrant.FolderList, o vagrant.FolderOptions) (err error) {
|
||||||
machine, err := vagrant.DumpMachine(m)
|
machine, err := vagrant.DumpMachine(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -136,7 +136,7 @@ func (c *GRPCSyncedFolderClient) Name() string {
|
||||||
return resp.Name
|
return resp.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GRPCSyncedFolderClient) Prepare(m *vagrant.Machine, f *vagrant.FolderList, o *vagrant.FolderOptions) (err error) {
|
func (c *GRPCSyncedFolderClient) Prepare(m *vagrant.Machine, f vagrant.FolderList, o vagrant.FolderOptions) (err error) {
|
||||||
machine, err := vagrant.DumpMachine(m)
|
machine, err := vagrant.DumpMachine(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -171,7 +171,7 @@ type GRPCSyncedFolderServer struct {
|
||||||
|
|
||||||
func (s *GRPCSyncedFolderServer) Cleanup(ctx context.Context, req *vagrant_folder.CleanupRequest) (resp *vagrant_common.EmptyResponse, err error) {
|
func (s *GRPCSyncedFolderServer) Cleanup(ctx context.Context, req *vagrant_folder.CleanupRequest) (resp *vagrant_common.EmptyResponse, err error) {
|
||||||
resp = &vagrant_common.EmptyResponse{}
|
resp = &vagrant_common.EmptyResponse{}
|
||||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ func (s *GRPCSyncedFolderServer) Cleanup(ctx context.Context, req *vagrant_folde
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e := s.Impl.Cleanup(machine, &options)
|
e := s.Impl.Cleanup(machine, options)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
resp.Error = e.Error()
|
resp.Error = e.Error()
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ func (s *GRPCSyncedFolderServer) Cleanup(ctx context.Context, req *vagrant_folde
|
||||||
|
|
||||||
func (s *GRPCSyncedFolderServer) Disable(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
func (s *GRPCSyncedFolderServer) Disable(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
||||||
resp = &vagrant_common.EmptyResponse{}
|
resp = &vagrant_common.EmptyResponse{}
|
||||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,7 @@ func (s *GRPCSyncedFolderServer) Disable(ctx context.Context, req *vagrant_folde
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e := s.Impl.Disable(machine, &folders, &options)
|
e := s.Impl.Disable(machine, folders, options)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
resp.Error = e.Error()
|
resp.Error = e.Error()
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ func (s *GRPCSyncedFolderServer) Disable(ctx context.Context, req *vagrant_folde
|
||||||
|
|
||||||
func (s *GRPCSyncedFolderServer) Enable(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
func (s *GRPCSyncedFolderServer) Enable(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
||||||
resp = &vagrant_common.EmptyResponse{}
|
resp = &vagrant_common.EmptyResponse{}
|
||||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ func (s *GRPCSyncedFolderServer) Enable(ctx context.Context, req *vagrant_folder
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e := s.Impl.Enable(machine, &folders, &options)
|
e := s.Impl.Enable(machine, folders, options)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
resp.Error = e.Error()
|
resp.Error = e.Error()
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ func (s *GRPCSyncedFolderServer) Info(ctx context.Context, req *vagrant_common.N
|
||||||
|
|
||||||
func (s *GRPCSyncedFolderServer) IsUsable(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_common.IsResponse, err error) {
|
func (s *GRPCSyncedFolderServer) IsUsable(ctx context.Context, req *vagrant_common.EmptyRequest) (resp *vagrant_common.IsResponse, err error) {
|
||||||
resp = &vagrant_common.IsResponse{}
|
resp = &vagrant_common.IsResponse{}
|
||||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ func (s *GRPCSyncedFolderServer) Name(ctx context.Context, req *vagrant_common.N
|
||||||
|
|
||||||
func (s *GRPCSyncedFolderServer) Prepare(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
func (s *GRPCSyncedFolderServer) Prepare(ctx context.Context, req *vagrant_folder.Request) (resp *vagrant_common.EmptyResponse, err error) {
|
||||||
resp = &vagrant_common.EmptyResponse{}
|
resp = &vagrant_common.EmptyResponse{}
|
||||||
machine, err := vagrant.LoadMachine(req.Machine, nil)
|
machine, err := vagrant.LoadMachine(req.Machine, s.Impl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ func (s *GRPCSyncedFolderServer) Prepare(ctx context.Context, req *vagrant_folde
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
e := s.Impl.Prepare(machine, &folders, &options)
|
e := s.Impl.Prepare(machine, folders, options)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
resp.Error = e.Error()
|
resp.Error = e.Error()
|
||||||
}
|
}
|
||||||
|
@ -282,10 +282,27 @@ func (s *GRPCSyncedFolderServer) Prepare(ctx context.Context, req *vagrant_folde
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *SyncedFolderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
func (f *SyncedFolderPlugin) GRPCServer(broker *go_plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
vagrant_folder.RegisterSyncedFolderServer(s, &GRPCSyncedFolderServer{Impl: f.Impl})
|
f.Impl.Init()
|
||||||
|
vagrant_folder.RegisterSyncedFolderServer(s,
|
||||||
|
&GRPCSyncedFolderServer{
|
||||||
|
Impl: f.Impl,
|
||||||
|
GRPCIOServer: GRPCIOServer{
|
||||||
|
Impl: f.Impl},
|
||||||
|
GRPCGuestCapabilitiesServer: GRPCGuestCapabilitiesServer{
|
||||||
|
Impl: f.Impl},
|
||||||
|
GRPCHostCapabilitiesServer: GRPCHostCapabilitiesServer{
|
||||||
|
Impl: f.Impl}})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *SyncedFolderPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
func (f *SyncedFolderPlugin) GRPCClient(ctx context.Context, broker *go_plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
return &GRPCSyncedFolderClient{client: vagrant_folder.NewSyncedFolderClient(c)}, nil
|
client := vagrant_folder.NewSyncedFolderClient(c)
|
||||||
|
return &GRPCSyncedFolderClient{
|
||||||
|
GRPCIOClient: GRPCIOClient{
|
||||||
|
client: client},
|
||||||
|
GRPCGuestCapabilitiesClient: GRPCGuestCapabilitiesClient{
|
||||||
|
client: client},
|
||||||
|
GRPCHostCapabilitiesClient: GRPCHostCapabilitiesClient{
|
||||||
|
client: client},
|
||||||
|
client: client}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,368 @@
|
||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"github.com/hashicorp/vagrant/ext/go-plugin/vagrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockSyncedFolder struct {
|
||||||
|
Core
|
||||||
|
vagrant.NoGuestCapabilities
|
||||||
|
vagrant.NoHostCapabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MockSyncedFolder) Cleanup(m *vagrant.Machine, opts vagrant.FolderOptions) error {
|
||||||
|
if opts != nil {
|
||||||
|
err, _ := opts["error"].(bool)
|
||||||
|
ui, _ := opts["ui"].(bool)
|
||||||
|
if err {
|
||||||
|
return errors.New("cleanup error")
|
||||||
|
}
|
||||||
|
if ui {
|
||||||
|
m.UI.Say("test_output_sf")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MockSyncedFolder) Disable(m *vagrant.Machine, f vagrant.FolderList, opts vagrant.FolderOptions) error {
|
||||||
|
if opts != nil && opts["error"].(bool) {
|
||||||
|
return errors.New("disable error")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MockSyncedFolder) Enable(m *vagrant.Machine, f vagrant.FolderList, opts vagrant.FolderOptions) error {
|
||||||
|
if opts != nil && opts["error"].(bool) {
|
||||||
|
return errors.New("enable error")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MockSyncedFolder) Info() *vagrant.SyncedFolderInfo {
|
||||||
|
return &vagrant.SyncedFolderInfo{
|
||||||
|
Description: "mock_folder",
|
||||||
|
Priority: 100}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MockSyncedFolder) IsUsable(m *vagrant.Machine) (bool, error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MockSyncedFolder) Name() string {
|
||||||
|
return "mock_folder"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MockSyncedFolder) Prepare(m *vagrant.Machine, f vagrant.FolderList, opts vagrant.FolderOptions) error {
|
||||||
|
if opts != nil && opts["error"].(bool) {
|
||||||
|
return errors.New("prepare error")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Cleanup(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = impl.Cleanup(&vagrant.Machine{}, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Cleanup_error(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
args := map[string]interface{}{
|
||||||
|
"error": true}
|
||||||
|
|
||||||
|
err = impl.Cleanup(&vagrant.Machine{}, args)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("illegal cleanup")
|
||||||
|
}
|
||||||
|
if err.Error() != "cleanup error" {
|
||||||
|
t.Errorf("%s != cleanup error", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Disable(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = impl.Disable(&vagrant.Machine{}, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Disable_error(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
folders := map[string]interface{}{
|
||||||
|
"folder_name": "options"}
|
||||||
|
args := map[string]interface{}{
|
||||||
|
"error": true}
|
||||||
|
|
||||||
|
err = impl.Disable(&vagrant.Machine{}, folders, args)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("illegal disable")
|
||||||
|
}
|
||||||
|
if err.Error() != "disable error" {
|
||||||
|
t.Errorf("%s != disable error", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Enable(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = impl.Enable(&vagrant.Machine{}, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Enable_error(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
folders := map[string]interface{}{
|
||||||
|
"folder_name": "options"}
|
||||||
|
args := map[string]interface{}{
|
||||||
|
"error": true}
|
||||||
|
|
||||||
|
err = impl.Enable(&vagrant.Machine{}, folders, args)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("illegal enable")
|
||||||
|
}
|
||||||
|
if err.Error() != "enable error" {
|
||||||
|
t.Errorf("%s != enable error", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Prepare(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = impl.Prepare(&vagrant.Machine{}, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Prepare_error(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
folders := map[string]interface{}{
|
||||||
|
"folder_name": "options"}
|
||||||
|
args := map[string]interface{}{
|
||||||
|
"error": true}
|
||||||
|
|
||||||
|
err = impl.Prepare(&vagrant.Machine{}, folders, args)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("illegal prepare")
|
||||||
|
}
|
||||||
|
if err.Error() != "prepare error" {
|
||||||
|
t.Errorf("%s != prepare error", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Info(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := impl.Info()
|
||||||
|
if resp == nil {
|
||||||
|
t.Fatalf("bad resp")
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Description != "mock_folder" {
|
||||||
|
t.Errorf("%s != mock_folder", resp.Description)
|
||||||
|
}
|
||||||
|
if resp.Priority != 100 {
|
||||||
|
t.Errorf("%d != 100", resp.Priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_IsUsable(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := impl.IsUsable(&vagrant.Machine{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if !resp {
|
||||||
|
t.Errorf("bad result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_Name(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := impl.Name()
|
||||||
|
if resp != "mock_folder" {
|
||||||
|
t.Errorf("%s != mock_folder", resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncedFolder_MachineUI_output(t *testing.T) {
|
||||||
|
client, server := plugin.TestPluginGRPCConn(t, map[string]plugin.Plugin{
|
||||||
|
"folder": &SyncedFolderPlugin{Impl: &MockSyncedFolder{}}})
|
||||||
|
defer server.Stop()
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
raw, err := client.Dispense("folder")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
impl, ok := raw.(SyncedFolder)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("bad %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := impl.Cleanup(&vagrant.Machine{}, map[string]interface{}{"ui": true})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
resp, err := impl.Read("stdout")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("bad resp: %s", err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(resp, "test_output") {
|
||||||
|
t.Errorf("%s !~ test_output", resp)
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ type Provider interface {
|
||||||
IsUsable(machData *Machine) (bool, error)
|
IsUsable(machData *Machine) (bool, error)
|
||||||
MachineIdChanged(machData *Machine) error
|
MachineIdChanged(machData *Machine) error
|
||||||
Name() string
|
Name() string
|
||||||
RunAction(actionName string, data string, machData *Machine) (string, error)
|
RunAction(actionName string, args interface{}, machData *Machine) (interface{}, error)
|
||||||
SshInfo(machData *Machine) (*SshInfo, error)
|
SshInfo(machData *Machine) (*SshInfo, error)
|
||||||
State(machData *Machine) (*MachineState, error)
|
State(machData *Machine) (*MachineState, error)
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
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[:])
|
|
||||||
}
|
|
|
@ -9,13 +9,13 @@ type SyncedFolderInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SyncedFolder interface {
|
type SyncedFolder interface {
|
||||||
Cleanup(m *Machine, opts *FolderOptions) error
|
Cleanup(m *Machine, opts FolderOptions) error
|
||||||
Disable(m *Machine, f *FolderList, opts *FolderOptions) error
|
Disable(m *Machine, f FolderList, opts FolderOptions) error
|
||||||
Enable(m *Machine, f *FolderList, opts *FolderOptions) error
|
Enable(m *Machine, f FolderList, opts FolderOptions) error
|
||||||
Info() *SyncedFolderInfo
|
Info() *SyncedFolderInfo
|
||||||
IsUsable(m *Machine) (bool, error)
|
IsUsable(m *Machine) (bool, error)
|
||||||
Name() string
|
Name() string
|
||||||
Prepare(m *Machine, f *FolderList, opts *FolderOptions) error
|
Prepare(m *Machine, f FolderList, opts FolderOptions) error
|
||||||
|
|
||||||
GuestCapabilities
|
GuestCapabilities
|
||||||
HostCapabilities
|
HostCapabilities
|
||||||
|
|
|
@ -6,12 +6,12 @@ module Vagrant
|
||||||
module CapabilityPlugin
|
module CapabilityPlugin
|
||||||
# Wrapper class for go-plugin defined capabilities
|
# Wrapper class for go-plugin defined capabilities
|
||||||
class Capability
|
class Capability
|
||||||
extend TypedGoPlugin
|
include TypedGoPlugin
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Interface]
|
# @return [Interface]
|
||||||
def self.interface
|
def self.interface
|
||||||
unless @_interface
|
if !@_interface
|
||||||
@_interface = Interface.new
|
@_interface = Interface.new
|
||||||
end
|
end
|
||||||
@_interface
|
@_interface
|
||||||
|
|
|
@ -90,12 +90,16 @@ module Vagrant
|
||||||
|
|
||||||
# Load given data into the provided machine. This is
|
# Load given data into the provided machine. This is
|
||||||
# used to update the machine with data received from
|
# used to update the machine with data received from
|
||||||
# go-plugins
|
# go-plugins. Currently the only modification applied
|
||||||
|
# is an ID change.
|
||||||
#
|
#
|
||||||
# @param [Hash] data Machine data from go-plugin
|
# @param [Hash] data Machine data from go-plugin
|
||||||
# @param [Vagrant::Machine] machine
|
# @param [Vagrant::Machine] machine
|
||||||
# @return [Vagrant::Machine]
|
# @return [Vagrant::Machine]
|
||||||
def load_machine(data, machine)
|
def load_machine(data, machine)
|
||||||
|
if data[:id] != machine.id
|
||||||
|
machine.id = data[:id]
|
||||||
|
end
|
||||||
machine
|
machine
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -157,7 +161,7 @@ module Vagrant
|
||||||
|
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def name
|
def name
|
||||||
go_plugin_name.to_s.capitalize.tr("_", "")
|
go_plugin_name.to_s.split("_").map(&:capitalize).join
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,9 @@ module Vagrant
|
||||||
include Util::Logger
|
include Util::Logger
|
||||||
|
|
||||||
# @return [Manager]
|
# @return [Manager]
|
||||||
def self.instance(env=nil)
|
def self.instance
|
||||||
@instance ||= self.new
|
if !@instance
|
||||||
if env
|
@instance = self.new
|
||||||
@instance.envirnoment = env
|
|
||||||
end
|
end
|
||||||
@instance
|
@instance
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,31 +60,11 @@ module Vagrant
|
||||||
# provider so that it can be interacted with normally within
|
# provider so that it can be interacted with normally within
|
||||||
# Vagrant
|
# Vagrant
|
||||||
class Provider < Vagrant.plugin("2", :provider)
|
class Provider < Vagrant.plugin("2", :provider)
|
||||||
|
include DirectGoPlugin
|
||||||
|
|
||||||
# @return [Vagrant::Machine]
|
# @return [Vagrant::Machine]
|
||||||
attr_reader :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)
|
def initialize(machine)
|
||||||
@machine = machine
|
@machine = machine
|
||||||
end
|
end
|
||||||
|
@ -234,21 +214,6 @@ module Vagrant
|
||||||
end
|
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
|
# Check if provider is installed
|
||||||
#
|
#
|
||||||
# @param [String] provider_name provider name for request
|
# @param [String] provider_name provider name for request
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
require_relative "../../base"
|
||||||
|
|
||||||
|
describe Vagrant::GoPlugin::CapabilityPlugin do
|
||||||
|
describe Vagrant::GoPlugin::CapabilityPlugin::Capability do
|
||||||
|
it "should be a TypedGoPlugin" do
|
||||||
|
expect(described_class.ancestors).to include(Vagrant::GoPlugin::TypedGoPlugin)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".interface" do
|
||||||
|
it "should create an interface instance" do
|
||||||
|
expect(described_class.interface).to be_a(Vagrant::GoPlugin::CapabilityHost::Interface)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should cache generated interface" do
|
||||||
|
expect(described_class.interface).to be(described_class.interface)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,214 @@
|
||||||
|
require_relative "../../base"
|
||||||
|
|
||||||
|
describe Vagrant::GoPlugin::Core do
|
||||||
|
include_context "unit"
|
||||||
|
|
||||||
|
let(:subject_class) { Class.new.tap { |c| c.include(described_class) } }
|
||||||
|
let(:subject) { subject_class.new }
|
||||||
|
|
||||||
|
let(:name) { "foo" }
|
||||||
|
let(:provider) { new_provider_mock }
|
||||||
|
let(:provider_cls) do
|
||||||
|
obj = double("provider_cls")
|
||||||
|
allow(obj).to receive(:new).and_return(provider)
|
||||||
|
obj
|
||||||
|
end
|
||||||
|
let(:provider_config) { Object.new }
|
||||||
|
let(:provider_name) { :test }
|
||||||
|
let(:provider_options) { {} }
|
||||||
|
let(:base) { false }
|
||||||
|
let(:box) do
|
||||||
|
double("box",
|
||||||
|
name: "foo",
|
||||||
|
provider: :dummy,
|
||||||
|
version: "1.0",
|
||||||
|
directory: "box dir",
|
||||||
|
metadata: nil,
|
||||||
|
metadata_url: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:config) { env.vagrantfile.config }
|
||||||
|
let(:data_dir) { Pathname.new(Dir.mktmpdir("vagrant-machine-data-dir")) }
|
||||||
|
let(:env) do
|
||||||
|
# We need to create a Vagrantfile so that this test environment
|
||||||
|
# has a proper root path
|
||||||
|
test_env.vagrantfile("")
|
||||||
|
|
||||||
|
# Create the Vagrant::Environment instance
|
||||||
|
test_env.create_vagrant_env
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:test_env) { isolated_environment }
|
||||||
|
let(:machine) {
|
||||||
|
Vagrant::Machine.new(name, provider_name, provider_cls, provider_config,
|
||||||
|
provider_options, config, data_dir, box,
|
||||||
|
env, env.vagrantfile, base)
|
||||||
|
}
|
||||||
|
|
||||||
|
def new_provider_mock
|
||||||
|
double("provider").tap do |obj|
|
||||||
|
allow(obj).to receive(:_initialize)
|
||||||
|
.with(provider_name, anything).and_return(nil)
|
||||||
|
allow(obj).to receive(:machine_id_changed).and_return(nil)
|
||||||
|
allow(obj).to receive(:state).and_return(Vagrant::MachineState.new(
|
||||||
|
:created, "", ""))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#dump_machine" do
|
||||||
|
it "should raise error when argument is not a Vagrant Machine" do
|
||||||
|
expect { subject.dump_machine(:value) }.to raise_error(TypeError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should dump machine to JSON string" do
|
||||||
|
expect(subject.dump_machine(machine)).to be_a(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should dump machine information" do
|
||||||
|
val = subject.dump_machine(machine)
|
||||||
|
result = JSON.load(val)
|
||||||
|
expect(result["name"]).to eq(machine.name)
|
||||||
|
expect(result["provider_name"]).to eq(machine.provider_name.to_s)
|
||||||
|
expect(result["data_dir"]).to eq(machine.data_dir.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should dump box information" do
|
||||||
|
val = subject.dump_machine(machine)
|
||||||
|
result = JSON.load(val)
|
||||||
|
expect(result["box"]).to_not be_nil
|
||||||
|
expect(result["box"]["name"]).to eq("foo")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should dump environment information" do
|
||||||
|
val = subject.dump_machine(machine)
|
||||||
|
result = JSON.load(val)
|
||||||
|
expect(result["environment"]).to_not be_nil
|
||||||
|
expect(result["environment"]["cwd"]).to eq(machine.env.cwd.to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#dump_environment" do
|
||||||
|
it "should dump environment to Hash" do
|
||||||
|
expect(subject.dump_environment(env)).to be_a(Hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should include environment information" do
|
||||||
|
result = subject.dump_environment(env)
|
||||||
|
expect(result[:cwd]).to eq(env.cwd)
|
||||||
|
expect(result[:data_dir]).to eq(env.data_dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#load_machine" do
|
||||||
|
it "should set ID if ID has changed" do
|
||||||
|
expect(machine).to receive(:id=).with("newid")
|
||||||
|
subject.load_machine({id: "newid"}, machine)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not set ID if ID has not changed" do
|
||||||
|
expect(machine).not_to receive(:id=)
|
||||||
|
subject.load_machine({id: machine.id}, machine)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Vagrant::GoPlugin::DirectGoPlugin do
|
||||||
|
let(:subject_class) { Class.new.tap { |c| c.include(described_class) } }
|
||||||
|
let(:subject) { subject_class.new }
|
||||||
|
|
||||||
|
describe ".go_plugin_name" do
|
||||||
|
it "should return nil by default" do
|
||||||
|
expect(subject_class.go_plugin_name).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return assigned name when assigned" do
|
||||||
|
subject_class.go_plugin_name = :test
|
||||||
|
expect(subject_class.go_plugin_name).to eq(:test)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".go_plugin_name=" do
|
||||||
|
it "should allow for setting the plugin name" do
|
||||||
|
subject_class.go_plugin_name = :test_plugin
|
||||||
|
expect(subject_class.go_plugin_name).to eq(:test_plugin)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should raise error when name has already been set" do
|
||||||
|
subject_class.go_plugin_name = :test_plugin
|
||||||
|
expect {
|
||||||
|
subject_class.go_plugin_name = :different_plugin
|
||||||
|
}.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".plugin_name" do
|
||||||
|
it "should proxy to .go_plugin_name" do
|
||||||
|
expect(subject_class).to receive(:go_plugin_name)
|
||||||
|
subject_class.plugin_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".name" do
|
||||||
|
it "should default to empty string" do
|
||||||
|
expect(subject_class.name).to eq("")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should camel case the go_plugin_name" do
|
||||||
|
subject_class.go_plugin_name = "test_vagrant_plugin"
|
||||||
|
expect(subject_class.name).to eq("TestVagrantPlugin")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#plugin_name" do
|
||||||
|
it "should proxy to .go_plugin_name" do
|
||||||
|
expect(subject_class).to receive(:go_plugin_name)
|
||||||
|
subject.plugin_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe Vagrant::GoPlugin::TypedGoPlugin do
|
||||||
|
let(:subject_class) { Class.new.tap { |c| c.include(described_class) } }
|
||||||
|
let(:subject) { subject_class.new }
|
||||||
|
|
||||||
|
it "should include DirectGoPlugin" do
|
||||||
|
expect(subject_class.ancestors).to include(Vagrant::GoPlugin::DirectGoPlugin)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".go_plugin_type" do
|
||||||
|
it "should be nil by default" do
|
||||||
|
expect(subject_class.go_plugin_type).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should return assigned type when set" do
|
||||||
|
subject_class.go_plugin_type = "provider"
|
||||||
|
expect(subject_class.go_plugin_type).to eq("provider")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".go_plugin_type=" do
|
||||||
|
it "should allow setting plugin type" do
|
||||||
|
subject_class.go_plugin_type = "test_type"
|
||||||
|
expect(subject_class.go_plugin_type).to eq("test_type")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should convert plugin type value to string" do
|
||||||
|
subject_class.go_plugin_type = :test_type
|
||||||
|
expect(subject_class.go_plugin_type).to eq("test_type")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should raise an error when type has already been set" do
|
||||||
|
subject_class.go_plugin_type = :test_type
|
||||||
|
expect {
|
||||||
|
subject_class.go_plugin_type = :different_type
|
||||||
|
}.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#plugin_type" do
|
||||||
|
it "should proxy to .go_plugin_type" do
|
||||||
|
expect(subject_class).to receive(:go_plugin_type)
|
||||||
|
subject.plugin_type
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,56 @@
|
||||||
|
require_relative "../../base"
|
||||||
|
|
||||||
|
describe Vagrant::GoPlugin::Interface do
|
||||||
|
before do
|
||||||
|
allow_any_instance_of(described_class).to receive(:_setup)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#load_plugins" do
|
||||||
|
let(:path) { double("path", to_s: "path") }
|
||||||
|
|
||||||
|
it "should raise error if path is not a directory" do
|
||||||
|
expect(File).to receive(:directory?).with(path.to_s).and_return(false)
|
||||||
|
expect { subject.load_plugins(path) }.to raise_error(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should load plugins if path is a directory" do
|
||||||
|
expect(File).to receive(:directory?).with(path.to_s).and_return(true)
|
||||||
|
expect(subject).to receive(:_load_plugins).with(path.to_s)
|
||||||
|
subject.load_plugins(path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#register_plugins" do
|
||||||
|
it "should load Provider and SyncedFolder plugins" do
|
||||||
|
expect(Vagrant::GoPlugin::ProviderPlugin).to receive_message_chain(:interface, :load!)
|
||||||
|
expect(Vagrant::GoPlugin::SyncedFolderPlugin).to receive_message_chain(:interface, :load!)
|
||||||
|
subject.register_plugins
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#setup" do
|
||||||
|
after { subject }
|
||||||
|
|
||||||
|
it "should register at_exit action" do
|
||||||
|
expect(Kernel).to receive(:at_exit)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should run the setup action" do
|
||||||
|
expect_any_instance_of(described_class).to receive(:_setup)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should only run the setup process once" do
|
||||||
|
expect_any_instance_of(described_class).to receive(:_setup).once
|
||||||
|
expect(subject.logger).to receive(:warn)
|
||||||
|
subject.setup
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#teardown" do
|
||||||
|
it "should run the teardown action" do
|
||||||
|
expect(subject).to receive(:_teardown)
|
||||||
|
subject.teardown
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,148 @@
|
||||||
|
require_relative "../../base"
|
||||||
|
|
||||||
|
describe Vagrant::GoPlugin::Manager do
|
||||||
|
include_context "unit"
|
||||||
|
|
||||||
|
let(:env) do
|
||||||
|
test_env.vagrantfile("")
|
||||||
|
test_env.create_vagrant_env
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(FileUtils).to receive(:mkdir_p)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".instance" do
|
||||||
|
it "should return instance of manager" do
|
||||||
|
expect(described_class.instance).to be_a(described_class)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should cache instance" do
|
||||||
|
expect(described_class.instance).to be(described_class.instance)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".new" do
|
||||||
|
it "should create the installation directory" do
|
||||||
|
expect(FileUtils).to receive(:mkdir_p).with(Vagrant::GoPlugin::INSTALL_DIRECTORY)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should create installation temporary directory" do
|
||||||
|
expect(FileUtils).to receive(:mkdir_p).with(/tmp$/)
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should generate user state file" do
|
||||||
|
expect(subject.user_file).to be_a(Vagrant::Plugin::StateFile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#globalize!" do
|
||||||
|
let(:entries) { [double("entry1"), double("entry2")] }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(File).to receive(:directory?).and_return(false)
|
||||||
|
allow(Dir).to receive(:glob).and_return(entries)
|
||||||
|
allow(Vagrant::GoPlugin).to receive_message_chain(:interface, :register_plugins)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when entries are not directories" do
|
||||||
|
before { allow(File).to receive(:directory?).and_return(false) }
|
||||||
|
|
||||||
|
it "should not load any plugins" do
|
||||||
|
interface = double("interface", register_plugins: nil)
|
||||||
|
allow(Vagrant::GoPlugin).to receive(:interface).and_return(interface)
|
||||||
|
expect(interface).not_to receive(:load_plugins)
|
||||||
|
subject.globalize!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when entries are directories" do
|
||||||
|
before { allow(File).to receive(:directory?).and_return(true) }
|
||||||
|
|
||||||
|
it "should load all entries" do
|
||||||
|
expect(Vagrant::GoPlugin).to receive_message_chain(:interface, :load_plugins).with(entries.first)
|
||||||
|
expect(Vagrant::GoPlugin).to receive_message_chain(:interface, :load_plugins).with(entries.last)
|
||||||
|
subject.globalize!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should register plugins after loading" do
|
||||||
|
expect(Vagrant::GoPlugin).to receive_message_chain(:interface, :register_plugins)
|
||||||
|
subject.globalize!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#localize!" do
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#install_plugin" do
|
||||||
|
let(:plugin_name) { "test_plugin_name" }
|
||||||
|
let(:remote_source) { double("remote_source") }
|
||||||
|
let(:downloader) { double("downloader", download!: nil) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(FileUtils).to receive(:mkdir_p)
|
||||||
|
allow(Dir).to receive(:mktmpdir)
|
||||||
|
allow(Vagrant::Util::Downloader).to receive(:new).and_return(downloader)
|
||||||
|
allow(Zip::File).to receive(:open)
|
||||||
|
end
|
||||||
|
|
||||||
|
after { subject.install_plugin(plugin_name, remote_source) }
|
||||||
|
|
||||||
|
it "should create plugin directory for plugin name" do
|
||||||
|
expect(FileUtils).to receive(:mkdir_p).with(/test_plugin_name$/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should create a temporary directory to download and unpack" do
|
||||||
|
expect(Dir).to receive(:mktmpdir).with(/go-plugin/, any_args)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should download the remote file" do
|
||||||
|
expect(Dir).to receive(:mktmpdir).with(any_args).and_yield("tmpdir")
|
||||||
|
expect(downloader).to receive(:download!)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should unzip the downloaded file" do
|
||||||
|
expect(Dir).to receive(:mktmpdir).with(any_args).and_yield("tmpdir")
|
||||||
|
expect(Zip::File).to receive(:open).with(/plugin.zip/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should add the plugin to the user file" do
|
||||||
|
expect(subject.user_file).to receive(:add_go_plugin).and_call_original
|
||||||
|
expect(subject.user_file.has_go_plugin?("test_plugin_name")).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#uninstall_plugin" do
|
||||||
|
let(:plugin_name) { "test_plugin_name" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(File).to receive(:directory?).and_call_original
|
||||||
|
allow(FileUtils).to receive(:rm_rf)
|
||||||
|
end
|
||||||
|
|
||||||
|
after { subject.uninstall_plugin(plugin_name) }
|
||||||
|
|
||||||
|
it "should remove plugin path when installed" do
|
||||||
|
expect(File).to receive(:directory?).with(/test_plugin_name/).and_return(true)
|
||||||
|
expect(FileUtils).to receive(:rm_rf).with(/test_plugin_name/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not remove plugin path when not installed" do
|
||||||
|
expect(File).to receive(:directory?).with(/test_plugin_name/).and_return(false)
|
||||||
|
expect(FileUtils).not_to receive(:rm_rf).with(/test_plugin_name/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have plugin name removed from user file when installed" do
|
||||||
|
expect(File).to receive(:directory?).with(/test_plugin_name/).and_return(true)
|
||||||
|
expect(subject.user_file).to receive(:remove_go_plugin).with(plugin_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have plugin name removed from user file when not installed" do
|
||||||
|
expect(File).to receive(:directory?).with(/test_plugin_name/).and_return(false)
|
||||||
|
expect(subject.user_file).to receive(:remove_go_plugin).with(plugin_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,29 @@
|
||||||
|
require_relative "../base"
|
||||||
|
|
||||||
|
describe Vagrant::GoPlugin do
|
||||||
|
describe "INSTALL_DIRECTORY constant" do
|
||||||
|
let(:subject) { described_class.const_get(:INSTALL_DIRECTORY) }
|
||||||
|
|
||||||
|
it "should be a String" do
|
||||||
|
expect(subject).to be_a(String)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be frozen" do
|
||||||
|
expect(subject).to be_frozen
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should be within the user data path" do
|
||||||
|
expect(subject).to start_with(Vagrant.user_data_path.to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".interface" do
|
||||||
|
it "should return an interface instance" do
|
||||||
|
expect(described_class.interface).to be_a(Vagrant::GoPlugin::Interface)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should cache the interface instance" do
|
||||||
|
expect(described_class.interface).to be(described_class.interface)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue