forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plugin_reload.go
135 lines (113 loc) · 3.43 KB
/
plugin_reload.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package vault
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/errwrap"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/logical"
)
// reloadPluginMounts reloads provided mounts, regardless of
// plugin name, as long as the backend type is plugin.
func (c *Core) reloadMatchingPluginMounts(ctx context.Context, mounts []string) error {
c.mountsLock.Lock()
defer c.mountsLock.Unlock()
var errors error
for _, mount := range mounts {
entry := c.router.MatchingMountEntry(mount)
if entry == nil {
errors = multierror.Append(errors, fmt.Errorf("cannot fetch mount entry on %q", mount))
continue
}
var isAuth bool
fullPath := c.router.MatchingMount(mount)
if strings.HasPrefix(fullPath, credentialRoutePrefix) {
isAuth = true
}
if entry.Type == "plugin" {
err := c.reloadBackendCommon(ctx, entry, isAuth)
if err != nil {
errors = multierror.Append(errors, errwrap.Wrapf(fmt.Sprintf("cannot reload plugin on %q: {{err}}", mount), err))
continue
}
c.logger.Info("successfully reloaded plugin", "plugin", entry.Config.PluginName, "path", entry.Path)
}
}
return errors
}
// reloadPlugin reloads all mounted backends that are of
// plugin pluginName (name of the plugin as registered in
// the plugin catalog).
func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) error {
c.mountsLock.Lock()
defer c.mountsLock.Unlock()
// Filter mount entries that only matches the plugin name
for _, entry := range c.mounts.Entries {
if entry.Config.PluginName == pluginName && entry.Type == "plugin" {
err := c.reloadBackendCommon(ctx, entry, false)
if err != nil {
return err
}
c.logger.Info("successfully reloaded plugin", "plugin", pluginName, "path", entry.Path)
}
}
// Filter auth mount entries that ony matches the plugin name
for _, entry := range c.auth.Entries {
if entry.Config.PluginName == pluginName && entry.Type == "plugin" {
err := c.reloadBackendCommon(ctx, entry, true)
if err != nil {
return err
}
c.logger.Info("successfully reloaded plugin", "plugin", pluginName, "path", entry.Path)
}
}
return nil
}
// reloadBackendCommon is a generic method to reload a backend provided a
// MountEntry.
func (c *Core) reloadBackendCommon(ctx context.Context, entry *MountEntry, isAuth bool) error {
path := entry.Path
if isAuth {
path = credentialRoutePrefix + path
}
// Fast-path out if the backend doesn't exist
raw, ok := c.router.root.Get(path)
if !ok {
return nil
}
re := raw.(*routeEntry)
// Grab the lock, this allows requests to drain before we cleanup the
// client.
re.l.Lock()
defer re.l.Unlock()
// Only call Cleanup if backend is initialized
if re.backend != nil {
// Call backend's Cleanup routine
re.backend.Cleanup(ctx)
}
view := re.storageView
sysView := c.mountEntrySysView(entry)
var backend logical.Backend
var err error
if !isAuth {
// Dispense a new backend
backend, err = c.newLogicalBackend(ctx, entry, sysView, view)
} else {
backend, err = c.newCredentialBackend(ctx, entry, sysView, view)
}
if err != nil {
return err
}
if backend == nil {
return fmt.Errorf("nil backend of type %q returned from creation function", entry.Type)
}
// Set the backend back
re.backend = backend
// Set paths as well
paths := backend.SpecialPaths()
if paths != nil {
re.rootPaths.Store(pathsToRadix(paths.Root))
re.loginPaths.Store(pathsToRadix(paths.Unauthenticated))
}
return nil
}