github.com/hashicorp/vault/sdk@v0.13.0/database/dbplugin/v5/plugin_client.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package dbplugin
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  
    10  	"github.com/hashicorp/go-plugin"
    11  	"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
    12  	"github.com/hashicorp/vault/sdk/helper/pluginutil"
    13  	"github.com/hashicorp/vault/sdk/logical"
    14  )
    15  
    16  var _ logical.PluginVersioner = (*DatabasePluginClient)(nil)
    17  
    18  type DatabasePluginClient struct {
    19  	client pluginutil.PluginClient
    20  	Database
    21  }
    22  
    23  func (dc *DatabasePluginClient) PluginVersion() logical.PluginVersion {
    24  	if versioner, ok := dc.Database.(logical.PluginVersioner); ok {
    25  		return versioner.PluginVersion()
    26  	}
    27  	return logical.EmptyPluginVersion
    28  }
    29  
    30  // This wraps the Close call and ensures we both close the database connection
    31  // and kill the plugin.
    32  func (dc *DatabasePluginClient) Close() error {
    33  	err := dc.Database.Close()
    34  	dc.client.Close()
    35  
    36  	return err
    37  }
    38  
    39  // pluginSets is the map of plugins we can dispense.
    40  var PluginSets = map[int]plugin.PluginSet{
    41  	5: {
    42  		"database": &GRPCDatabasePlugin{},
    43  	},
    44  	6: {
    45  		"database": &GRPCDatabasePlugin{},
    46  	},
    47  }
    48  
    49  // NewPluginClient returns a databaseRPCClient with a connection to a running
    50  // plugin.
    51  func NewPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, config pluginutil.PluginClientConfig) (Database, error) {
    52  	pluginClient, err := sys.NewPluginClient(ctx, config)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	// Request the plugin
    58  	raw, err := pluginClient.Dispense("database")
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	// We should have a database type now. This feels like a normal interface
    64  	// implementation but is in fact over an RPC connection.
    65  	var db Database
    66  	switch c := raw.(type) {
    67  	case gRPCClient:
    68  		// This is an abstraction leak from go-plugin but it is necessary in
    69  		// order to enable multiplexing on multiplexed plugins
    70  		c.client = proto.NewDatabaseClient(pluginClient.Conn())
    71  		c.versionClient = logical.NewPluginVersionClient(pluginClient.Conn())
    72  
    73  		db = c
    74  	default:
    75  		return nil, errors.New("unsupported client type")
    76  	}
    77  
    78  	return &DatabasePluginClient{
    79  		client:   pluginClient,
    80  		Database: db,
    81  	}, nil
    82  }