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

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package dbplugin
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/hashicorp/errwrap"
    11  	log "github.com/hashicorp/go-hclog"
    12  	"github.com/hashicorp/vault/sdk/helper/consts"
    13  	"github.com/hashicorp/vault/sdk/helper/pluginutil"
    14  )
    15  
    16  // PluginFactory is used to build plugin database types. It wraps the database
    17  // object in a logging and metrics middleware.
    18  func PluginFactory(ctx context.Context, pluginName string, sys pluginutil.LookRunnerUtil, logger log.Logger) (Database, error) {
    19  	return PluginFactoryVersion(ctx, pluginName, "", sys, logger)
    20  }
    21  
    22  // PluginFactoryVersion is used to build plugin database types with a version specified.
    23  // It wraps the database object in a logging and metrics middleware.
    24  func PluginFactoryVersion(ctx context.Context, pluginName string, pluginVersion string, sys pluginutil.LookRunnerUtil, logger log.Logger) (Database, error) {
    25  	// Look for plugin in the plugin catalog
    26  	pluginRunner, err := sys.LookupPluginVersion(ctx, pluginName, consts.PluginTypeDatabase, pluginVersion)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	namedLogger := logger.Named(pluginName)
    32  
    33  	var transport string
    34  	var db Database
    35  	if pluginRunner.Builtin {
    36  		// Plugin is builtin so we can retrieve an instance of the interface
    37  		// from the pluginRunner. Then cast it to a Database.
    38  		dbRaw, err := pluginRunner.BuiltinFactory()
    39  		if err != nil {
    40  			return nil, errwrap.Wrapf("error initializing plugin: {{err}}", err)
    41  		}
    42  
    43  		var ok bool
    44  		db, ok = dbRaw.(Database)
    45  		if !ok {
    46  			return nil, fmt.Errorf("unsupported database type: %q", pluginName)
    47  		}
    48  
    49  		transport = "builtin"
    50  
    51  	} else {
    52  		config := pluginutil.PluginClientConfig{
    53  			Name:            pluginName,
    54  			PluginType:      consts.PluginTypeDatabase,
    55  			Version:         pluginVersion,
    56  			PluginSets:      PluginSets,
    57  			HandshakeConfig: HandshakeConfig,
    58  			Logger:          namedLogger,
    59  			IsMetadataMode:  false,
    60  			AutoMTLS:        true,
    61  			Wrapper:         sys,
    62  		}
    63  		// create a DatabasePluginClient instance
    64  		db, err = NewPluginClient(ctx, sys, config)
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  
    69  		// Switch on the underlying database client type to get the transport
    70  		// method.
    71  		switch db.(*DatabasePluginClient).Database.(type) {
    72  		case *gRPCClient:
    73  			transport = "gRPC"
    74  		}
    75  
    76  	}
    77  
    78  	typeStr, err := db.Type()
    79  	if err != nil {
    80  		return nil, errwrap.Wrapf("error getting plugin type: {{err}}", err)
    81  	}
    82  	logger.Debug("got database plugin instance", "type", typeStr)
    83  
    84  	// Wrap with metrics middleware
    85  	db = &databaseMetricsMiddleware{
    86  		next:    db,
    87  		typeStr: typeStr,
    88  	}
    89  
    90  	// Wrap with tracing middleware
    91  	if namedLogger.IsTrace() {
    92  		db = &databaseTracingMiddleware{
    93  			next:   db,
    94  			logger: namedLogger.With("transport", transport),
    95  		}
    96  	}
    97  
    98  	return db, nil
    99  }