update to start a new process for each plugin
Modify the plugin factories to create a new plugin process for each individual plugin.
This commit is contained in:
parent
35b375d3ee
commit
795161f615
|
@ -84,8 +84,7 @@ func (r *multiVersionProviderResolver) ResolveProviders(
|
|||
continue
|
||||
}
|
||||
|
||||
client := tfplugin.Client(newest)
|
||||
factories[name] = providerFactory(client)
|
||||
factories[name] = providerFactory(newest)
|
||||
} else {
|
||||
msg := fmt.Sprintf("provider.%s: no suitable version installed", name)
|
||||
|
||||
|
@ -332,7 +331,7 @@ func (m *Meta) provisionerFactories() map[string]terraform.ProvisionerFactory {
|
|||
log.Printf("[WARN] failed to build command line for internal plugin %q: %s", name, err)
|
||||
continue
|
||||
}
|
||||
factories[name] = provisionerFactory(client)
|
||||
factories[name] = internalProvisionerFactory(client)
|
||||
}
|
||||
|
||||
byName := plugins.ByName()
|
||||
|
@ -341,8 +340,8 @@ func (m *Meta) provisionerFactories() map[string]terraform.ProvisionerFactory {
|
|||
// by name, we're guaranteed that the metas in our set all have
|
||||
// valid versions and that there's at least one meta.
|
||||
newest := metas.Newest()
|
||||
client := tfplugin.Client(newest)
|
||||
factories[name] = provisionerFactory(client)
|
||||
|
||||
factories[name] = provisionerFactory(newest)
|
||||
}
|
||||
|
||||
return factories
|
||||
|
@ -369,8 +368,9 @@ func internalPluginClient(kind, name string) (*plugin.Client, error) {
|
|||
return plugin.NewClient(cfg), nil
|
||||
}
|
||||
|
||||
func providerFactory(client *plugin.Client) providers.Factory {
|
||||
func providerFactory(meta discovery.PluginMeta) providers.Factory {
|
||||
return func() (providers.Interface, error) {
|
||||
client := tfplugin.Client(meta)
|
||||
// Request the RPC client so we can get the provider
|
||||
// so we can build the actual RPC-implemented provider.
|
||||
rpcClient, err := client.Client()
|
||||
|
@ -383,24 +383,41 @@ func providerFactory(client *plugin.Client) providers.Factory {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return raw.(providers.Interface), nil
|
||||
// store the client so that the plugin can kill the child process
|
||||
p := raw.(*tfplugin.GRPCProvider)
|
||||
p.PluginClient = client
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
|
||||
func provisionerFactory(client *plugin.Client) terraform.ProvisionerFactory {
|
||||
func provisionerFactory(meta discovery.PluginMeta) terraform.ProvisionerFactory {
|
||||
return func() (provisioners.Interface, error) {
|
||||
// Request the RPC client so we can get the provisioner
|
||||
// so we can build the actual RPC-implemented provisioner.
|
||||
rpcClient, err := client.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw, err := rpcClient.Dispense(tfplugin.ProvisionerPluginName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return raw.(provisioners.Interface), nil
|
||||
client := tfplugin.Client(meta)
|
||||
return newProvisionerClient(client)
|
||||
}
|
||||
}
|
||||
|
||||
func internalProvisionerFactory(client *plugin.Client) terraform.ProvisionerFactory {
|
||||
return func() (provisioners.Interface, error) {
|
||||
return newProvisionerClient(client)
|
||||
}
|
||||
}
|
||||
|
||||
func newProvisionerClient(client *plugin.Client) (provisioners.Interface, error) {
|
||||
// Request the RPC client so we can get the provisioner
|
||||
// so we can build the actual RPC-implemented provisioner.
|
||||
rpcClient, err := client.Client()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
raw, err := rpcClient.Dispense(tfplugin.ProvisionerPluginName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// store the client so that the plugin can kill the child process
|
||||
p := raw.(*tfplugin.GRPCProvisioner)
|
||||
p.PluginClient = client
|
||||
return p, nil
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ type GRPCProviderPlugin struct {
|
|||
|
||||
func (p *GRPCProviderPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||
return &GRPCProvider{
|
||||
conn: c,
|
||||
client: proto.NewProviderClient(c),
|
||||
ctx: ctx,
|
||||
}, nil
|
||||
|
@ -41,7 +40,11 @@ func (p *GRPCProviderPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Serve
|
|||
// terraform provioders types and the grpc proto types, directly converting
|
||||
// between the two.
|
||||
type GRPCProvider struct {
|
||||
conn *grpc.ClientConn
|
||||
// PluginClient provides a reference to the plugin.Client which controls the plugin process.
|
||||
// This allows the GRPCProvider a way to shutdown the plugin process.
|
||||
PluginClient *plugin.Client
|
||||
|
||||
// Proto client use to make the grpc service calls.
|
||||
client proto.ProviderClient
|
||||
|
||||
// this context is created by the plugin package, and is canceled when the
|
||||
|
@ -495,8 +498,13 @@ func (p *GRPCProvider) ReadDataSource(r providers.ReadDataSourceRequest) (resp p
|
|||
}
|
||||
|
||||
// closing the grpc connection is final, and terraform will call it at the end of every phase.
|
||||
// FIXME: do we need this, and if so, how do we fix it?
|
||||
func (p *GRPCProvider) Close() error {
|
||||
log.Printf("[TRACE] GRPCProvider: Close")
|
||||
// check this since it's not automatically inserted during plugin creation
|
||||
if p.PluginClient == nil {
|
||||
log.Println("[DEBUG] provider has no plugin.Client")
|
||||
return nil
|
||||
}
|
||||
|
||||
p.PluginClient.Kill()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
plugin "github.com/hashicorp/go-plugin"
|
||||
|
@ -24,7 +25,6 @@ type GRPCProvisionerPlugin struct {
|
|||
|
||||
func (p *GRPCProvisionerPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||
return &GRPCProvisioner{
|
||||
conn: c,
|
||||
client: proto.NewProvisionerClient(c),
|
||||
ctx: ctx,
|
||||
}, nil
|
||||
|
@ -37,7 +37,10 @@ func (p *GRPCProvisionerPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Se
|
|||
|
||||
// provisioners.Interface grpc implementation
|
||||
type GRPCProvisioner struct {
|
||||
conn *grpc.ClientConn
|
||||
// PluginClient provides a reference to the plugin.Client which controls the plugin process.
|
||||
// This allows the GRPCProvider a way to shutdown the plugin process.
|
||||
PluginClient *plugin.Client
|
||||
|
||||
client proto.ProvisionerClient
|
||||
ctx context.Context
|
||||
|
||||
|
@ -163,5 +166,12 @@ func (p *GRPCProvisioner) Stop() error {
|
|||
}
|
||||
|
||||
func (p *GRPCProvisioner) Close() error {
|
||||
// check this since it's not automatically inserted during plugin creation
|
||||
if p.PluginClient == nil {
|
||||
log.Println("[DEBUG] provider has no plugin.Client")
|
||||
return nil
|
||||
}
|
||||
|
||||
p.PluginClient.Kill()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ type basicComponentFactory struct {
|
|||
|
||||
func (c *basicComponentFactory) ResourceProviders() []string {
|
||||
result := make([]string, len(c.providers))
|
||||
for k, _ := range c.providers {
|
||||
for k := range c.providers {
|
||||
result = append(result, k)
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ func (c *basicComponentFactory) ResourceProviders() []string {
|
|||
|
||||
func (c *basicComponentFactory) ResourceProvisioners() []string {
|
||||
result := make([]string, len(c.provisioners))
|
||||
for k, _ := range c.provisioners {
|
||||
for k := range c.provisioners {
|
||||
result = append(result, k)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue