remove netrpc plugins

Provisioner plugins were the last remaining use of the legacy netrpc
plugin interface (even though it was wrapped in shimmed into the grpc
protocol). Now that these types are no longer being used, we can remove
the old code from the plugin package entirely.
This commit is contained in:
James Bardin 2020-11-27 10:05:59 -05:00
parent 85b7027048
commit 6aae0a94bd
7 changed files with 1 additions and 1942 deletions

View File

@ -4,8 +4,6 @@ import (
"github.com/hashicorp/go-plugin"
)
// See serve.go for serving plugins
var VersionedPlugins = map[int]plugin.PluginSet{
5: {
"provider": &GRPCProviderPlugin{},

View File

@ -1,17 +0,0 @@
package plugin
import (
"github.com/hashicorp/terraform/internal/legacy/terraform"
)
func testProviderFixed(p terraform.ResourceProvider) ProviderFunc {
return func() terraform.ResourceProvider {
return p
}
}
func testProvisionerFixed(p terraform.ResourceProvisioner) ProvisionerFunc {
return func() terraform.ResourceProvisioner {
return p
}
}

View File

@ -1,620 +0,0 @@
package plugin
import (
"net/rpc"
plugin "github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/internal/legacy/terraform"
)
// ResourceProviderPlugin is the plugin.Plugin implementation.
type ResourceProviderPlugin struct {
ResourceProvider func() terraform.ResourceProvider
}
func (p *ResourceProviderPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
return &ResourceProviderServer{
Broker: b,
Provider: p.ResourceProvider(),
}, nil
}
func (p *ResourceProviderPlugin) Client(
b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
return &ResourceProvider{Broker: b, Client: c}, nil
}
// ResourceProvider is an implementation of terraform.ResourceProvider
// that communicates over RPC.
type ResourceProvider struct {
Broker *plugin.MuxBroker
Client *rpc.Client
}
func (p *ResourceProvider) Stop() error {
var resp ResourceProviderStopResponse
err := p.Client.Call("Plugin.Stop", new(interface{}), &resp)
if err != nil {
return err
}
if resp.Error != nil {
err = resp.Error
}
return err
}
func (p *ResourceProvider) GetSchema(req *terraform.ProviderSchemaRequest) (*terraform.ProviderSchema, error) {
var result ResourceProviderGetSchemaResponse
args := &ResourceProviderGetSchemaArgs{
Req: req,
}
err := p.Client.Call("Plugin.GetSchema", args, &result)
if err != nil {
return nil, err
}
if result.Error != nil {
err = result.Error
}
return result.Schema, err
}
func (p *ResourceProvider) Input(
input terraform.UIInput,
c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
id := p.Broker.NextId()
go p.Broker.AcceptAndServe(id, &UIInputServer{
UIInput: input,
})
var resp ResourceProviderInputResponse
args := ResourceProviderInputArgs{
InputId: id,
Config: c,
}
err := p.Client.Call("Plugin.Input", &args, &resp)
if err != nil {
return nil, err
}
if resp.Error != nil {
err = resp.Error
return nil, err
}
return resp.Config, nil
}
func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
var resp ResourceProviderValidateResponse
args := ResourceProviderValidateArgs{
Config: c,
}
err := p.Client.Call("Plugin.Validate", &args, &resp)
if err != nil {
return nil, []error{err}
}
var errs []error
if len(resp.Errors) > 0 {
errs = make([]error, len(resp.Errors))
for i, err := range resp.Errors {
errs[i] = err
}
}
return resp.Warnings, errs
}
func (p *ResourceProvider) ValidateResource(
t string, c *terraform.ResourceConfig) ([]string, []error) {
var resp ResourceProviderValidateResourceResponse
args := ResourceProviderValidateResourceArgs{
Config: c,
Type: t,
}
err := p.Client.Call("Plugin.ValidateResource", &args, &resp)
if err != nil {
return nil, []error{err}
}
var errs []error
if len(resp.Errors) > 0 {
errs = make([]error, len(resp.Errors))
for i, err := range resp.Errors {
errs[i] = err
}
}
return resp.Warnings, errs
}
func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
var resp ResourceProviderConfigureResponse
err := p.Client.Call("Plugin.Configure", c, &resp)
if err != nil {
return err
}
if resp.Error != nil {
err = resp.Error
}
return err
}
func (p *ResourceProvider) Apply(
info *terraform.InstanceInfo,
s *terraform.InstanceState,
d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
var resp ResourceProviderApplyResponse
args := &ResourceProviderApplyArgs{
Info: info,
State: s,
Diff: d,
}
err := p.Client.Call("Plugin.Apply", args, &resp)
if err != nil {
return nil, err
}
if resp.Error != nil {
err = resp.Error
}
return resp.State, err
}
func (p *ResourceProvider) Diff(
info *terraform.InstanceInfo,
s *terraform.InstanceState,
c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
var resp ResourceProviderDiffResponse
args := &ResourceProviderDiffArgs{
Info: info,
State: s,
Config: c,
}
err := p.Client.Call("Plugin.Diff", args, &resp)
if err != nil {
return nil, err
}
if resp.Error != nil {
err = resp.Error
}
return resp.Diff, err
}
func (p *ResourceProvider) ValidateDataSource(
t string, c *terraform.ResourceConfig) ([]string, []error) {
var resp ResourceProviderValidateResourceResponse
args := ResourceProviderValidateResourceArgs{
Config: c,
Type: t,
}
err := p.Client.Call("Plugin.ValidateDataSource", &args, &resp)
if err != nil {
return nil, []error{err}
}
var errs []error
if len(resp.Errors) > 0 {
errs = make([]error, len(resp.Errors))
for i, err := range resp.Errors {
errs[i] = err
}
}
return resp.Warnings, errs
}
func (p *ResourceProvider) Refresh(
info *terraform.InstanceInfo,
s *terraform.InstanceState) (*terraform.InstanceState, error) {
var resp ResourceProviderRefreshResponse
args := &ResourceProviderRefreshArgs{
Info: info,
State: s,
}
err := p.Client.Call("Plugin.Refresh", args, &resp)
if err != nil {
return nil, err
}
if resp.Error != nil {
err = resp.Error
}
return resp.State, err
}
func (p *ResourceProvider) ImportState(
info *terraform.InstanceInfo,
id string) ([]*terraform.InstanceState, error) {
var resp ResourceProviderImportStateResponse
args := &ResourceProviderImportStateArgs{
Info: info,
Id: id,
}
err := p.Client.Call("Plugin.ImportState", args, &resp)
if err != nil {
return nil, err
}
if resp.Error != nil {
err = resp.Error
}
return resp.State, err
}
func (p *ResourceProvider) Resources() []terraform.ResourceType {
var result []terraform.ResourceType
err := p.Client.Call("Plugin.Resources", new(interface{}), &result)
if err != nil {
// TODO: panic, log, what?
return nil
}
return result
}
func (p *ResourceProvider) ReadDataDiff(
info *terraform.InstanceInfo,
c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
var resp ResourceProviderReadDataDiffResponse
args := &ResourceProviderReadDataDiffArgs{
Info: info,
Config: c,
}
err := p.Client.Call("Plugin.ReadDataDiff", args, &resp)
if err != nil {
return nil, err
}
if resp.Error != nil {
err = resp.Error
}
return resp.Diff, err
}
func (p *ResourceProvider) ReadDataApply(
info *terraform.InstanceInfo,
d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
var resp ResourceProviderReadDataApplyResponse
args := &ResourceProviderReadDataApplyArgs{
Info: info,
Diff: d,
}
err := p.Client.Call("Plugin.ReadDataApply", args, &resp)
if err != nil {
return nil, err
}
if resp.Error != nil {
err = resp.Error
}
return resp.State, err
}
func (p *ResourceProvider) DataSources() []terraform.DataSource {
var result []terraform.DataSource
err := p.Client.Call("Plugin.DataSources", new(interface{}), &result)
if err != nil {
// TODO: panic, log, what?
return nil
}
return result
}
func (p *ResourceProvider) Close() error {
return p.Client.Close()
}
// ResourceProviderServer is a net/rpc compatible structure for serving
// a ResourceProvider. This should not be used directly.
type ResourceProviderServer struct {
Broker *plugin.MuxBroker
Provider terraform.ResourceProvider
}
type ResourceProviderStopResponse struct {
Error *plugin.BasicError
}
type ResourceProviderGetSchemaArgs struct {
Req *terraform.ProviderSchemaRequest
}
type ResourceProviderGetSchemaResponse struct {
Schema *terraform.ProviderSchema
Error *plugin.BasicError
}
type ResourceProviderConfigureResponse struct {
Error *plugin.BasicError
}
type ResourceProviderInputArgs struct {
InputId uint32
Config *terraform.ResourceConfig
}
type ResourceProviderInputResponse struct {
Config *terraform.ResourceConfig
Error *plugin.BasicError
}
type ResourceProviderApplyArgs struct {
Info *terraform.InstanceInfo
State *terraform.InstanceState
Diff *terraform.InstanceDiff
}
type ResourceProviderApplyResponse struct {
State *terraform.InstanceState
Error *plugin.BasicError
}
type ResourceProviderDiffArgs struct {
Info *terraform.InstanceInfo
State *terraform.InstanceState
Config *terraform.ResourceConfig
}
type ResourceProviderDiffResponse struct {
Diff *terraform.InstanceDiff
Error *plugin.BasicError
}
type ResourceProviderRefreshArgs struct {
Info *terraform.InstanceInfo
State *terraform.InstanceState
}
type ResourceProviderRefreshResponse struct {
State *terraform.InstanceState
Error *plugin.BasicError
}
type ResourceProviderImportStateArgs struct {
Info *terraform.InstanceInfo
Id string
}
type ResourceProviderImportStateResponse struct {
State []*terraform.InstanceState
Error *plugin.BasicError
}
type ResourceProviderReadDataApplyArgs struct {
Info *terraform.InstanceInfo
Diff *terraform.InstanceDiff
}
type ResourceProviderReadDataApplyResponse struct {
State *terraform.InstanceState
Error *plugin.BasicError
}
type ResourceProviderReadDataDiffArgs struct {
Info *terraform.InstanceInfo
Config *terraform.ResourceConfig
}
type ResourceProviderReadDataDiffResponse struct {
Diff *terraform.InstanceDiff
Error *plugin.BasicError
}
type ResourceProviderValidateArgs struct {
Config *terraform.ResourceConfig
}
type ResourceProviderValidateResponse struct {
Warnings []string
Errors []*plugin.BasicError
}
type ResourceProviderValidateResourceArgs struct {
Config *terraform.ResourceConfig
Type string
}
type ResourceProviderValidateResourceResponse struct {
Warnings []string
Errors []*plugin.BasicError
}
func (s *ResourceProviderServer) Stop(
_ interface{},
reply *ResourceProviderStopResponse) error {
err := s.Provider.Stop()
*reply = ResourceProviderStopResponse{
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) GetSchema(
args *ResourceProviderGetSchemaArgs,
result *ResourceProviderGetSchemaResponse,
) error {
schema, err := s.Provider.GetSchema(args.Req)
result.Schema = schema
if err != nil {
result.Error = plugin.NewBasicError(err)
}
return nil
}
func (s *ResourceProviderServer) Input(
args *ResourceProviderInputArgs,
reply *ResourceProviderInputResponse) error {
conn, err := s.Broker.Dial(args.InputId)
if err != nil {
*reply = ResourceProviderInputResponse{
Error: plugin.NewBasicError(err),
}
return nil
}
client := rpc.NewClient(conn)
defer client.Close()
input := &UIInput{Client: client}
config, err := s.Provider.Input(input, args.Config)
*reply = ResourceProviderInputResponse{
Config: config,
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) Validate(
args *ResourceProviderValidateArgs,
reply *ResourceProviderValidateResponse) error {
warns, errs := s.Provider.Validate(args.Config)
berrs := make([]*plugin.BasicError, len(errs))
for i, err := range errs {
berrs[i] = plugin.NewBasicError(err)
}
*reply = ResourceProviderValidateResponse{
Warnings: warns,
Errors: berrs,
}
return nil
}
func (s *ResourceProviderServer) ValidateResource(
args *ResourceProviderValidateResourceArgs,
reply *ResourceProviderValidateResourceResponse) error {
warns, errs := s.Provider.ValidateResource(args.Type, args.Config)
berrs := make([]*plugin.BasicError, len(errs))
for i, err := range errs {
berrs[i] = plugin.NewBasicError(err)
}
*reply = ResourceProviderValidateResourceResponse{
Warnings: warns,
Errors: berrs,
}
return nil
}
func (s *ResourceProviderServer) Configure(
config *terraform.ResourceConfig,
reply *ResourceProviderConfigureResponse) error {
err := s.Provider.Configure(config)
*reply = ResourceProviderConfigureResponse{
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) Apply(
args *ResourceProviderApplyArgs,
result *ResourceProviderApplyResponse) error {
state, err := s.Provider.Apply(args.Info, args.State, args.Diff)
*result = ResourceProviderApplyResponse{
State: state,
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) Diff(
args *ResourceProviderDiffArgs,
result *ResourceProviderDiffResponse) error {
diff, err := s.Provider.Diff(args.Info, args.State, args.Config)
*result = ResourceProviderDiffResponse{
Diff: diff,
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) Refresh(
args *ResourceProviderRefreshArgs,
result *ResourceProviderRefreshResponse) error {
newState, err := s.Provider.Refresh(args.Info, args.State)
*result = ResourceProviderRefreshResponse{
State: newState,
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) ImportState(
args *ResourceProviderImportStateArgs,
result *ResourceProviderImportStateResponse) error {
states, err := s.Provider.ImportState(args.Info, args.Id)
*result = ResourceProviderImportStateResponse{
State: states,
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) Resources(
nothing interface{},
result *[]terraform.ResourceType) error {
*result = s.Provider.Resources()
return nil
}
func (s *ResourceProviderServer) ValidateDataSource(
args *ResourceProviderValidateResourceArgs,
reply *ResourceProviderValidateResourceResponse) error {
warns, errs := s.Provider.ValidateDataSource(args.Type, args.Config)
berrs := make([]*plugin.BasicError, len(errs))
for i, err := range errs {
berrs[i] = plugin.NewBasicError(err)
}
*reply = ResourceProviderValidateResourceResponse{
Warnings: warns,
Errors: berrs,
}
return nil
}
func (s *ResourceProviderServer) ReadDataDiff(
args *ResourceProviderReadDataDiffArgs,
result *ResourceProviderReadDataDiffResponse) error {
diff, err := s.Provider.ReadDataDiff(args.Info, args.Config)
*result = ResourceProviderReadDataDiffResponse{
Diff: diff,
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) ReadDataApply(
args *ResourceProviderReadDataApplyArgs,
result *ResourceProviderReadDataApplyResponse) error {
newState, err := s.Provider.ReadDataApply(args.Info, args.Diff)
*result = ResourceProviderReadDataApplyResponse{
State: newState,
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProviderServer) DataSources(
nothing interface{},
result *[]terraform.DataSource) error {
*result = s.Provider.DataSources()
return nil
}

View File

@ -1,827 +0,0 @@
package plugin
import (
"errors"
"reflect"
"testing"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/internal/legacy/terraform"
)
func TestResourceProvider_impl(t *testing.T) {
var _ plugin.Plugin = new(ResourceProviderPlugin)
var _ terraform.ResourceProvider = new(ResourceProvider)
}
func TestResourceProvider_stop(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvider)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Stop
e := provider.Stop()
if !p.StopCalled {
t.Fatal("stop should be called")
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_stopErrors(t *testing.T) {
p := new(terraform.MockResourceProvider)
p.StopReturnError = errors.New("foo")
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Stop
e := provider.Stop()
if !p.StopCalled {
t.Fatal("stop should be called")
}
if e == nil {
t.Fatal("should have error")
}
if e.Error() != "foo" {
t.Fatalf("bad: %s", e)
}
}
func TestResourceProvider_input(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvider)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
input := new(terraform.MockUIInput)
expected := &terraform.ResourceConfig{
Raw: map[string]interface{}{"bar": "baz"},
}
p.InputReturnConfig = expected
// Input
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
actual, err := provider.Input(input, config)
if !p.InputCalled {
t.Fatal("input should be called")
}
if !reflect.DeepEqual(p.InputConfig, config) {
t.Fatalf("bad: %#v", p.InputConfig)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("bad: %#v", actual)
}
}
func TestResourceProvider_configure(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvider)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
e := provider.Configure(config)
if !p.ConfigureCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ConfigureConfig, config) {
t.Fatalf("bad: %#v", p.ConfigureConfig)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_configure_errors(t *testing.T) {
p := new(terraform.MockResourceProvider)
p.ConfigureReturnError = errors.New("foo")
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
e := provider.Configure(config)
if !p.ConfigureCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ConfigureConfig, config) {
t.Fatalf("bad: %#v", p.ConfigureConfig)
}
if e == nil {
t.Fatal("should have error")
}
if e.Error() != "foo" {
t.Fatalf("bad: %s", e)
}
}
func TestResourceProvider_configure_warnings(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
e := provider.Configure(config)
if !p.ConfigureCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ConfigureConfig, config) {
t.Fatalf("bad: %#v", p.ConfigureConfig)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_apply(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.ApplyReturn = &terraform.InstanceState{
ID: "bob",
}
// Apply
info := &terraform.InstanceInfo{}
state := &terraform.InstanceState{}
diff := &terraform.InstanceDiff{}
newState, err := provider.Apply(info, state, diff)
if !p.ApplyCalled {
t.Fatal("apply should be called")
}
if !reflect.DeepEqual(p.ApplyDiff, diff) {
t.Fatalf("bad: %#v", p.ApplyDiff)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
if !reflect.DeepEqual(p.ApplyReturn, newState) {
t.Fatalf("bad: %#v", newState)
}
}
func TestResourceProvider_diff(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.DiffReturn = &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"foo": &terraform.ResourceAttrDiff{
Old: "",
New: "bar",
},
},
}
// Diff
info := &terraform.InstanceInfo{}
state := &terraform.InstanceState{}
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
diff, err := provider.Diff(info, state, config)
if !p.DiffCalled {
t.Fatal("diff should be called")
}
if !reflect.DeepEqual(p.DiffDesired, config) {
t.Fatalf("bad: %#v", p.DiffDesired)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
if !reflect.DeepEqual(p.DiffReturn, diff) {
t.Fatalf("bad: %#v", diff)
}
}
func TestResourceProvider_diff_error(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.DiffReturnError = errors.New("foo")
// Diff
info := &terraform.InstanceInfo{}
state := &terraform.InstanceState{}
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
diff, err := provider.Diff(info, state, config)
if !p.DiffCalled {
t.Fatal("diff should be called")
}
if !reflect.DeepEqual(p.DiffDesired, config) {
t.Fatalf("bad: %#v", p.DiffDesired)
}
if err == nil {
t.Fatal("should have error")
}
if diff != nil {
t.Fatal("should not have diff")
}
}
func TestResourceProvider_refresh(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.RefreshReturn = &terraform.InstanceState{
ID: "bob",
}
// Refresh
info := &terraform.InstanceInfo{}
state := &terraform.InstanceState{}
newState, err := provider.Refresh(info, state)
if !p.RefreshCalled {
t.Fatal("refresh should be called")
}
if !reflect.DeepEqual(p.RefreshState, state) {
t.Fatalf("bad: %#v", p.RefreshState)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
if !reflect.DeepEqual(p.RefreshReturn, newState) {
t.Fatalf("bad: %#v", newState)
}
}
func TestResourceProvider_importState(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.ImportStateReturn = []*terraform.InstanceState{
&terraform.InstanceState{
ID: "bob",
},
}
// ImportState
info := &terraform.InstanceInfo{}
states, err := provider.ImportState(info, "foo")
if !p.ImportStateCalled {
t.Fatal("ImportState should be called")
}
if !reflect.DeepEqual(p.ImportStateInfo, info) {
t.Fatalf("bad: %#v", p.ImportStateInfo)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
if !reflect.DeepEqual(p.ImportStateReturn, states) {
t.Fatalf("bad: %#v", states)
}
}
func TestResourceProvider_resources(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
expected := []terraform.ResourceType{
terraform.ResourceType{Name: "foo"},
terraform.ResourceType{Name: "bar", Importable: true},
}
p.ResourcesReturn = expected
// Resources
result := provider.Resources()
if !p.ResourcesCalled {
t.Fatal("resources should be called")
}
if !reflect.DeepEqual(result, expected) {
t.Fatalf("bad: %#v", result)
}
}
func TestResourceProvider_readdataapply(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.ReadDataApplyReturn = &terraform.InstanceState{
ID: "bob",
}
// ReadDataApply
info := &terraform.InstanceInfo{}
diff := &terraform.InstanceDiff{}
newState, err := provider.ReadDataApply(info, diff)
if !p.ReadDataApplyCalled {
t.Fatal("ReadDataApply should be called")
}
if !reflect.DeepEqual(p.ReadDataApplyDiff, diff) {
t.Fatalf("bad: %#v", p.ReadDataApplyDiff)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
if !reflect.DeepEqual(p.ReadDataApplyReturn, newState) {
t.Fatalf("bad: %#v", newState)
}
}
func TestResourceProvider_datasources(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
expected := []terraform.DataSource{
{Name: "foo"},
{Name: "bar"},
}
p.DataSourcesReturn = expected
// DataSources
result := provider.DataSources()
if !p.DataSourcesCalled {
t.Fatal("DataSources should be called")
}
if !reflect.DeepEqual(result, expected) {
t.Fatalf("bad: %#v", result)
}
}
func TestResourceProvider_validate(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provider.Validate(config)
if !p.ValidateCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ValidateConfig, config) {
t.Fatalf("bad: %#v", p.ValidateConfig)
}
if w != nil {
t.Fatalf("bad: %#v", w)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_validate_errors(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.ValidateReturnErrors = []error{errors.New("foo")}
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provider.Validate(config)
if !p.ValidateCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ValidateConfig, config) {
t.Fatalf("bad: %#v", p.ValidateConfig)
}
if w != nil {
t.Fatalf("bad: %#v", w)
}
if len(e) != 1 {
t.Fatalf("bad: %#v", e)
}
if e[0].Error() != "foo" {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_validate_warns(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.ValidateReturnWarns = []string{"foo"}
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provider.Validate(config)
if !p.ValidateCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ValidateConfig, config) {
t.Fatalf("bad: %#v", p.ValidateConfig)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
expected := []string{"foo"}
if !reflect.DeepEqual(w, expected) {
t.Fatalf("bad: %#v", w)
}
}
func TestResourceProvider_validateResource(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provider.ValidateResource("foo", config)
if !p.ValidateResourceCalled {
t.Fatal("configure should be called")
}
if p.ValidateResourceType != "foo" {
t.Fatalf("bad: %#v", p.ValidateResourceType)
}
if !reflect.DeepEqual(p.ValidateResourceConfig, config) {
t.Fatalf("bad: %#v", p.ValidateResourceConfig)
}
if w != nil {
t.Fatalf("bad: %#v", w)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_validateResource_errors(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.ValidateResourceReturnErrors = []error{errors.New("foo")}
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provider.ValidateResource("foo", config)
if !p.ValidateResourceCalled {
t.Fatal("configure should be called")
}
if p.ValidateResourceType != "foo" {
t.Fatalf("bad: %#v", p.ValidateResourceType)
}
if !reflect.DeepEqual(p.ValidateResourceConfig, config) {
t.Fatalf("bad: %#v", p.ValidateResourceConfig)
}
if w != nil {
t.Fatalf("bad: %#v", w)
}
if len(e) != 1 {
t.Fatalf("bad: %#v", e)
}
if e[0].Error() != "foo" {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_validateResource_warns(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
p.ValidateResourceReturnWarns = []string{"foo"}
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provider.ValidateResource("foo", config)
if !p.ValidateResourceCalled {
t.Fatal("configure should be called")
}
if p.ValidateResourceType != "foo" {
t.Fatalf("bad: %#v", p.ValidateResourceType)
}
if !reflect.DeepEqual(p.ValidateResourceConfig, config) {
t.Fatalf("bad: %#v", p.ValidateResourceConfig)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
expected := []string{"foo"}
if !reflect.DeepEqual(w, expected) {
t.Fatalf("bad: %#v", w)
}
}
func TestResourceProvider_validateDataSource(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provider.ValidateDataSource("foo", config)
if !p.ValidateDataSourceCalled {
t.Fatal("configure should be called")
}
if p.ValidateDataSourceType != "foo" {
t.Fatalf("bad: %#v", p.ValidateDataSourceType)
}
if !reflect.DeepEqual(p.ValidateDataSourceConfig, config) {
t.Fatalf("bad: %#v", p.ValidateDataSourceConfig)
}
if w != nil {
t.Fatalf("bad: %#v", w)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvider_close(t *testing.T) {
p := new(terraform.MockResourceProvider)
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProviderFunc: testProviderFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProviderPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvider)
var iface interface{} = provider
pCloser, ok := iface.(terraform.ResourceProviderCloser)
if !ok {
t.Fatal("should be a ResourceProviderCloser")
}
if err := pCloser.Close(); err != nil {
t.Fatalf("failed to close provider: %s", err)
}
// The connection should be closed now, so if we to make a
// new call we should get an error.
err = provider.Configure(&terraform.ResourceConfig{})
if err == nil {
t.Fatal("should have error")
}
}

View File

@ -1,181 +0,0 @@
package plugin
import (
"net/rpc"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/internal/legacy/terraform"
)
// ResourceProvisionerPlugin is the plugin.Plugin implementation.
type ResourceProvisionerPlugin struct {
ResourceProvisioner func() terraform.ResourceProvisioner
}
func (p *ResourceProvisionerPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
return &ResourceProvisionerServer{
Broker: b,
Provisioner: p.ResourceProvisioner(),
}, nil
}
func (p *ResourceProvisionerPlugin) Client(
b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
return &ResourceProvisioner{Broker: b, Client: c}, nil
}
// ResourceProvisioner is an implementation of terraform.ResourceProvisioner
// that communicates over RPC.
type ResourceProvisioner struct {
Broker *plugin.MuxBroker
Client *rpc.Client
}
func (p *ResourceProvisioner) GetConfigSchema() (*configschema.Block, error) {
panic("not implemented")
}
func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) {
var resp ResourceProvisionerValidateResponse
args := ResourceProvisionerValidateArgs{
Config: c,
}
err := p.Client.Call("Plugin.Validate", &args, &resp)
if err != nil {
return nil, []error{err}
}
var errs []error
if len(resp.Errors) > 0 {
errs = make([]error, len(resp.Errors))
for i, err := range resp.Errors {
errs[i] = err
}
}
return resp.Warnings, errs
}
func (p *ResourceProvisioner) Apply(
output terraform.UIOutput,
s *terraform.InstanceState,
c *terraform.ResourceConfig) error {
id := p.Broker.NextId()
go p.Broker.AcceptAndServe(id, &UIOutputServer{
UIOutput: output,
})
var resp ResourceProvisionerApplyResponse
args := &ResourceProvisionerApplyArgs{
OutputId: id,
State: s,
Config: c,
}
err := p.Client.Call("Plugin.Apply", args, &resp)
if err != nil {
return err
}
if resp.Error != nil {
err = resp.Error
}
return err
}
func (p *ResourceProvisioner) Stop() error {
var resp ResourceProvisionerStopResponse
err := p.Client.Call("Plugin.Stop", new(interface{}), &resp)
if err != nil {
return err
}
if resp.Error != nil {
err = resp.Error
}
return err
}
func (p *ResourceProvisioner) Close() error {
return p.Client.Close()
}
type ResourceProvisionerValidateArgs struct {
Config *terraform.ResourceConfig
}
type ResourceProvisionerValidateResponse struct {
Warnings []string
Errors []*plugin.BasicError
}
type ResourceProvisionerApplyArgs struct {
OutputId uint32
State *terraform.InstanceState
Config *terraform.ResourceConfig
}
type ResourceProvisionerApplyResponse struct {
Error *plugin.BasicError
}
type ResourceProvisionerStopResponse struct {
Error *plugin.BasicError
}
// ResourceProvisionerServer is a net/rpc compatible structure for serving
// a ResourceProvisioner. This should not be used directly.
type ResourceProvisionerServer struct {
Broker *plugin.MuxBroker
Provisioner terraform.ResourceProvisioner
}
func (s *ResourceProvisionerServer) Apply(
args *ResourceProvisionerApplyArgs,
result *ResourceProvisionerApplyResponse) error {
conn, err := s.Broker.Dial(args.OutputId)
if err != nil {
*result = ResourceProvisionerApplyResponse{
Error: plugin.NewBasicError(err),
}
return nil
}
client := rpc.NewClient(conn)
defer client.Close()
output := &UIOutput{Client: client}
err = s.Provisioner.Apply(output, args.State, args.Config)
*result = ResourceProvisionerApplyResponse{
Error: plugin.NewBasicError(err),
}
return nil
}
func (s *ResourceProvisionerServer) Validate(
args *ResourceProvisionerValidateArgs,
reply *ResourceProvisionerValidateResponse) error {
warns, errs := s.Provisioner.Validate(args.Config)
berrs := make([]*plugin.BasicError, len(errs))
for i, err := range errs {
berrs[i] = plugin.NewBasicError(err)
}
*reply = ResourceProvisionerValidateResponse{
Warnings: warns,
Errors: berrs,
}
return nil
}
func (s *ResourceProvisionerServer) Stop(
_ interface{},
reply *ResourceProvisionerStopResponse) error {
err := s.Provisioner.Stop()
*reply = ResourceProvisionerStopResponse{
Error: plugin.NewBasicError(err),
}
return nil
}

View File

@ -1,248 +0,0 @@
package plugin
import (
"errors"
"reflect"
"testing"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/internal/legacy/terraform"
)
func TestResourceProvisioner_impl(t *testing.T) {
var _ plugin.Plugin = new(ResourceProvisionerPlugin)
var _ terraform.ResourceProvisioner = new(ResourceProvisioner)
}
func TestResourceProvisioner_stop(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvisioner)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProvisionerFunc: testProvisionerFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProvisionerPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvisioner)
// Stop
e := provider.Stop()
if !p.StopCalled {
t.Fatal("stop should be called")
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvisioner_stopErrors(t *testing.T) {
p := new(terraform.MockResourceProvisioner)
p.StopReturnError = errors.New("foo")
// Create a mock provider
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProvisionerFunc: testProvisionerFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProvisionerPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provider := raw.(terraform.ResourceProvisioner)
// Stop
e := provider.Stop()
if !p.StopCalled {
t.Fatal("stop should be called")
}
if e == nil {
t.Fatal("should have error")
}
if e.Error() != "foo" {
t.Fatalf("bad: %s", e)
}
}
func TestResourceProvisioner_apply(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvisioner)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProvisionerFunc: testProvisionerFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProvisionerPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provisioner := raw.(terraform.ResourceProvisioner)
// Apply
output := &terraform.MockUIOutput{}
state := &terraform.InstanceState{}
conf := &terraform.ResourceConfig{}
err = provisioner.Apply(output, state, conf)
if !p.ApplyCalled {
t.Fatal("apply should be called")
}
if !reflect.DeepEqual(p.ApplyConfig, conf) {
t.Fatalf("bad: %#v", p.ApplyConfig)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
}
func TestResourceProvisioner_validate(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvisioner)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProvisionerFunc: testProvisionerFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProvisionerPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provisioner := raw.(terraform.ResourceProvisioner)
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provisioner.Validate(config)
if !p.ValidateCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ValidateConfig, config) {
t.Fatalf("bad: %#v", p.ValidateConfig)
}
if w != nil {
t.Fatalf("bad: %#v", w)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvisioner_validate_errors(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvisioner)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProvisionerFunc: testProvisionerFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProvisionerPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provisioner := raw.(terraform.ResourceProvisioner)
p.ValidateReturnErrors = []error{errors.New("foo")}
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provisioner.Validate(config)
if !p.ValidateCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ValidateConfig, config) {
t.Fatalf("bad: %#v", p.ValidateConfig)
}
if w != nil {
t.Fatalf("bad: %#v", w)
}
if len(e) != 1 {
t.Fatalf("bad: %#v", e)
}
if e[0].Error() != "foo" {
t.Fatalf("bad: %#v", e)
}
}
func TestResourceProvisioner_validate_warns(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvisioner)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProvisionerFunc: testProvisionerFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProvisionerPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provisioner := raw.(terraform.ResourceProvisioner)
p.ValidateReturnWarns = []string{"foo"}
// Configure
config := &terraform.ResourceConfig{
Raw: map[string]interface{}{"foo": "bar"},
}
w, e := provisioner.Validate(config)
if !p.ValidateCalled {
t.Fatal("configure should be called")
}
if !reflect.DeepEqual(p.ValidateConfig, config) {
t.Fatalf("bad: %#v", p.ValidateConfig)
}
if e != nil {
t.Fatalf("bad: %#v", e)
}
expected := []string{"foo"}
if !reflect.DeepEqual(w, expected) {
t.Fatalf("bad: %#v", w)
}
}
func TestResourceProvisioner_close(t *testing.T) {
// Create a mock provider
p := new(terraform.MockResourceProvisioner)
client, _ := plugin.TestPluginRPCConn(t, legacyPluginMap(&ServeOpts{
ProvisionerFunc: testProvisionerFixed(p),
}), nil)
defer client.Close()
// Request the provider
raw, err := client.Dispense(ProvisionerPluginName)
if err != nil {
t.Fatalf("err: %s", err)
}
provisioner := raw.(terraform.ResourceProvisioner)
pCloser, ok := raw.(terraform.ResourceProvisionerCloser)
if !ok {
t.Fatal("should be a ResourceProvisionerCloser")
}
if err := pCloser.Close(); err != nil {
t.Fatalf("failed to close provisioner: %s", err)
}
// The connection should be closed now, so if we to make a
// new call we should get an error.
o := &terraform.MockUIOutput{}
s := &terraform.InstanceState{}
c := &terraform.ResourceConfig{}
err = provisioner.Apply(o, s, c)
if err == nil {
t.Fatal("should have error")
}
}

View File

@ -2,8 +2,6 @@ package plugin
import (
"github.com/hashicorp/go-plugin"
grpcplugin "github.com/hashicorp/terraform/internal/legacy/helper/plugin"
"github.com/hashicorp/terraform/internal/legacy/terraform"
proto "github.com/hashicorp/terraform/internal/tfplugin5"
)
@ -35,16 +33,11 @@ var Handshake = plugin.HandshakeConfig{
MagicCookieValue: "d602bf8f470bc67ca7faa0386276bbdd4330efaf76d1a219cb4d6991ca9872b2",
}
type ProviderFunc func() terraform.ResourceProvider
type ProvisionerFunc func() terraform.ResourceProvisioner
type GRPCProviderFunc func() proto.ProviderServer
type GRPCProvisionerFunc func() proto.ProvisionerServer
// ServeOpts are the configurations to serve a plugin.
type ServeOpts struct {
ProviderFunc ProviderFunc
ProvisionerFunc ProvisionerFunc
// Wrapped versions of the above plugins will automatically shimmed and
// added to the GRPC functions when possible.
GRPCProviderFunc GRPCProviderFunc
@ -54,27 +47,6 @@ type ServeOpts struct {
// Serve serves a plugin. This function never returns and should be the final
// function called in the main function of the plugin.
func Serve(opts *ServeOpts) {
// since the plugins may not yet be aware of the new protocol, we
// automatically wrap the plugins in the grpc shims.
if opts.GRPCProviderFunc == nil && opts.ProviderFunc != nil {
provider := grpcplugin.NewGRPCProviderServerShim(opts.ProviderFunc())
// this is almost always going to be a *schema.Provider, but check that
// we got back a valid provider just in case.
if provider != nil {
opts.GRPCProviderFunc = func() proto.ProviderServer {
return provider
}
}
}
if opts.GRPCProvisionerFunc == nil && opts.ProvisionerFunc != nil {
provisioner := grpcplugin.NewGRPCProvisionerServerShim(opts.ProvisionerFunc())
if provisioner != nil {
opts.GRPCProvisionerFunc = func() proto.ProvisionerServer {
return provisioner
}
}
}
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: Handshake,
VersionedPlugins: pluginSet(opts),
@ -82,26 +54,8 @@ func Serve(opts *ServeOpts) {
})
}
// pluginMap returns the legacy map[string]plugin.Plugin to use for configuring
// a plugin server or client.
func legacyPluginMap(opts *ServeOpts) map[string]plugin.Plugin {
return map[string]plugin.Plugin{
"provider": &ResourceProviderPlugin{
ResourceProvider: opts.ProviderFunc,
},
"provisioner": &ResourceProvisionerPlugin{
ResourceProvisioner: opts.ProvisionerFunc,
},
}
}
func pluginSet(opts *ServeOpts) map[int]plugin.PluginSet {
// Set the legacy netrpc plugins at version 4.
// The oldest version is returned in when executed by a legacy go-plugin
// client.
plugins := map[int]plugin.PluginSet{
4: legacyPluginMap(opts),
}
plugins := map[int]plugin.PluginSet{}
// add the new protocol versions if they're configured
if opts.GRPCProviderFunc != nil || opts.GRPCProvisionerFunc != nil {