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 }