mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-01 19:17:58 +00:00
New database plugin API to reload by plugin name (#24472)
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/hashicorp/go-uuid"
|
||||
@@ -94,13 +95,7 @@ func (b *databaseBackend) pathConnectionReset() framework.OperationFunc {
|
||||
return logical.ErrorResponse(respErrEmptyName), nil
|
||||
}
|
||||
|
||||
// Close plugin and delete the entry in the connections cache.
|
||||
if err := b.ClearConnection(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Execute plugin again, we don't need the object so throw away.
|
||||
if _, err := b.GetConnection(ctx, req.Storage, name); err != nil {
|
||||
if err := b.reloadConnection(ctx, req.Storage, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -108,6 +103,103 @@ func (b *databaseBackend) pathConnectionReset() framework.OperationFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *databaseBackend) reloadConnection(ctx context.Context, storage logical.Storage, name string) error {
|
||||
// Close plugin and delete the entry in the connections cache.
|
||||
if err := b.ClearConnection(name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Execute plugin again, we don't need the object so throw away.
|
||||
if _, err := b.GetConnection(ctx, storage, name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// pathReloadPlugin reloads all connections using a named plugin.
|
||||
func pathReloadPlugin(b *databaseBackend) *framework.Path {
|
||||
return &framework.Path{
|
||||
Pattern: fmt.Sprintf("reload/%s", framework.GenericNameRegex("plugin_name")),
|
||||
|
||||
DisplayAttrs: &framework.DisplayAttributes{
|
||||
OperationPrefix: operationPrefixDatabase,
|
||||
OperationVerb: "reload",
|
||||
OperationSuffix: "plugin",
|
||||
},
|
||||
|
||||
Fields: map[string]*framework.FieldSchema{
|
||||
"plugin_name": {
|
||||
Type: framework.TypeString,
|
||||
Description: "Name of the database plugin",
|
||||
},
|
||||
},
|
||||
|
||||
Callbacks: map[logical.Operation]framework.OperationFunc{
|
||||
logical.UpdateOperation: b.reloadPlugin(),
|
||||
},
|
||||
|
||||
HelpSynopsis: pathReloadPluginHelpSyn,
|
||||
HelpDescription: pathReloadPluginHelpDesc,
|
||||
}
|
||||
}
|
||||
|
||||
// reloadPlugin reloads all instances of a named plugin by closing the existing
|
||||
// instances and creating new ones.
|
||||
func (b *databaseBackend) reloadPlugin() framework.OperationFunc {
|
||||
return func(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
|
||||
pluginName := data.Get("plugin_name").(string)
|
||||
if pluginName == "" {
|
||||
return logical.ErrorResponse(respErrEmptyPluginName), nil
|
||||
}
|
||||
|
||||
connNames, err := req.Storage.List(ctx, "config/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reloaded := []string{}
|
||||
for _, connName := range connNames {
|
||||
entry, err := req.Storage.Get(ctx, fmt.Sprintf("config/%s", connName))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read connection configuration: %w", err)
|
||||
}
|
||||
if entry == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var config DatabaseConfig
|
||||
if err := entry.DecodeJSON(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if config.PluginName == pluginName {
|
||||
if err := b.reloadConnection(ctx, req.Storage, connName); err != nil {
|
||||
var successfullyReloaded string
|
||||
if len(reloaded) > 0 {
|
||||
successfullyReloaded = fmt.Sprintf("successfully reloaded %d connection(s): %s; ",
|
||||
len(reloaded),
|
||||
strings.Join(reloaded, ", "))
|
||||
}
|
||||
return nil, fmt.Errorf("%sfailed to reload connection %q: %w", successfullyReloaded, connName, err)
|
||||
}
|
||||
reloaded = append(reloaded, connName)
|
||||
}
|
||||
}
|
||||
|
||||
resp := &logical.Response{
|
||||
Data: map[string]interface{}{
|
||||
"connections": reloaded,
|
||||
"count": len(reloaded),
|
||||
},
|
||||
}
|
||||
|
||||
if len(reloaded) == 0 {
|
||||
resp.AddWarning(fmt.Sprintf("no connections were found with plugin_name %q", pluginName))
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
|
||||
// pathConfigurePluginConnection returns a configured framework.Path setup to
|
||||
// operate on plugins.
|
||||
func pathConfigurePluginConnection(b *databaseBackend) *framework.Path {
|
||||
@@ -551,3 +643,12 @@ const pathResetConnectionHelpDesc = `
|
||||
This path resets the database connection by closing the existing database plugin
|
||||
instance and running a new one.
|
||||
`
|
||||
|
||||
const pathReloadPluginHelpSyn = `
|
||||
Reloads all connections using a named database plugin.
|
||||
`
|
||||
|
||||
const pathReloadPluginHelpDesc = `
|
||||
This path resets each database connection using a named plugin by closing each
|
||||
existing database plugin instance and running a new one.
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user