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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
client := tfplugin.Client(newest)
|
factories[name] = providerFactory(newest)
|
||||||
factories[name] = providerFactory(client)
|
|
||||||
} else {
|
} else {
|
||||||
msg := fmt.Sprintf("provider.%s: no suitable version installed", name)
|
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)
|
log.Printf("[WARN] failed to build command line for internal plugin %q: %s", name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
factories[name] = provisionerFactory(client)
|
factories[name] = internalProvisionerFactory(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
byName := plugins.ByName()
|
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
|
// by name, we're guaranteed that the metas in our set all have
|
||||||
// valid versions and that there's at least one meta.
|
// valid versions and that there's at least one meta.
|
||||||
newest := metas.Newest()
|
newest := metas.Newest()
|
||||||
client := tfplugin.Client(newest)
|
|
||||||
factories[name] = provisionerFactory(client)
|
factories[name] = provisionerFactory(newest)
|
||||||
}
|
}
|
||||||
|
|
||||||
return factories
|
return factories
|
||||||
|
@ -369,8 +368,9 @@ func internalPluginClient(kind, name string) (*plugin.Client, error) {
|
||||||
return plugin.NewClient(cfg), nil
|
return plugin.NewClient(cfg), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func providerFactory(client *plugin.Client) providers.Factory {
|
func providerFactory(meta discovery.PluginMeta) providers.Factory {
|
||||||
return func() (providers.Interface, error) {
|
return func() (providers.Interface, error) {
|
||||||
|
client := tfplugin.Client(meta)
|
||||||
// Request the RPC client so we can get the provider
|
// Request the RPC client so we can get the provider
|
||||||
// so we can build the actual RPC-implemented provider.
|
// so we can build the actual RPC-implemented provider.
|
||||||
rpcClient, err := client.Client()
|
rpcClient, err := client.Client()
|
||||||
|
@ -383,24 +383,41 @@ func providerFactory(client *plugin.Client) providers.Factory {
|
||||||
return nil, err
|
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) {
|
return func() (provisioners.Interface, error) {
|
||||||
// Request the RPC client so we can get the provisioner
|
client := tfplugin.Client(meta)
|
||||||
// so we can build the actual RPC-implemented provisioner.
|
return newProvisionerClient(client)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
func (p *GRPCProviderPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
return &GRPCProvider{
|
return &GRPCProvider{
|
||||||
conn: c,
|
|
||||||
client: proto.NewProviderClient(c),
|
client: proto.NewProviderClient(c),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}, nil
|
}, 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
|
// terraform provioders types and the grpc proto types, directly converting
|
||||||
// between the two.
|
// between the two.
|
||||||
type GRPCProvider struct {
|
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
|
client proto.ProviderClient
|
||||||
|
|
||||||
// this context is created by the plugin package, and is canceled when the
|
// 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.
|
// 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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
plugin "github.com/hashicorp/go-plugin"
|
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) {
|
func (p *GRPCProvisionerPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
return &GRPCProvisioner{
|
return &GRPCProvisioner{
|
||||||
conn: c,
|
|
||||||
client: proto.NewProvisionerClient(c),
|
client: proto.NewProvisionerClient(c),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -37,7 +37,10 @@ func (p *GRPCProvisionerPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Se
|
||||||
|
|
||||||
// provisioners.Interface grpc implementation
|
// provisioners.Interface grpc implementation
|
||||||
type GRPCProvisioner struct {
|
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
|
client proto.ProvisionerClient
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
|
||||||
|
@ -163,5 +166,12 @@ func (p *GRPCProvisioner) Stop() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *GRPCProvisioner) Close() 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ type basicComponentFactory struct {
|
||||||
|
|
||||||
func (c *basicComponentFactory) ResourceProviders() []string {
|
func (c *basicComponentFactory) ResourceProviders() []string {
|
||||||
result := make([]string, len(c.providers))
|
result := make([]string, len(c.providers))
|
||||||
for k, _ := range c.providers {
|
for k := range c.providers {
|
||||||
result = append(result, k)
|
result = append(result, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ func (c *basicComponentFactory) ResourceProviders() []string {
|
||||||
|
|
||||||
func (c *basicComponentFactory) ResourceProvisioners() []string {
|
func (c *basicComponentFactory) ResourceProvisioners() []string {
|
||||||
result := make([]string, len(c.provisioners))
|
result := make([]string, len(c.provisioners))
|
||||||
for k, _ := range c.provisioners {
|
for k := range c.provisioners {
|
||||||
result = append(result, k)
|
result = append(result, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue