forked from hashicorp/vault
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathphysical.go
182 lines (153 loc) · 5.5 KB
/
physical.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package physical
import (
"fmt"
"sync"
log "github.com/mgutz/logxi/v1"
)
const DefaultParallelOperations = 128
// The operation type
type Operation string
const (
DeleteOperation Operation = "delete"
GetOperation = "get"
ListOperation = "list"
PutOperation = "put"
)
// ShutdownSignal
type ShutdownChannel chan struct{}
// Backend is the interface required for a physical
// backend. A physical backend is used to durably store
// data outside of Vault. As such, it is completely untrusted,
// and is only accessed via a security barrier. The backends
// must represent keys in a hierarchical manner. All methods
// are expected to be thread safe.
type Backend interface {
// Put is used to insert or update an entry
Put(entry *Entry) error
// Get is used to fetch an entry
Get(key string) (*Entry, error)
// Delete is used to permanently delete an entry
Delete(key string) error
// List is used ot list all the keys under a given
// prefix, up to the next prefix.
List(prefix string) ([]string, error)
}
// HABackend is an extensions to the standard physical
// backend to support high-availability. Vault only expects to
// use mutual exclusion to allow multiple instances to act as a
// hot standby for a leader that services all requests.
type HABackend interface {
// LockWith is used for mutual exclusion based on the given key.
LockWith(key, value string) (Lock, error)
// Whether or not HA functionality is enabled
HAEnabled() bool
}
// Purgable is an optional interface for backends that support
// purging of their caches.
type Purgable interface {
Purge()
}
// RedirectDetect is an optional interface that an HABackend
// can implement. If they do, a redirect address can be automatically
// detected.
type RedirectDetect interface {
// DetectHostAddr is used to detect the host address
DetectHostAddr() (string, error)
}
// Callback signatures for RunServiceDiscovery
type activeFunction func() bool
type sealedFunction func() bool
// ServiceDiscovery is an optional interface that an HABackend can implement.
// If they do, the state of a backend is advertised to the service discovery
// network.
type ServiceDiscovery interface {
// NotifyActiveStateChange is used by Core to notify a backend
// capable of ServiceDiscovery that this Vault instance has changed
// its status to active or standby.
NotifyActiveStateChange() error
// NotifySealedStateChange is used by Core to notify a backend
// capable of ServiceDiscovery that Vault has changed its Sealed
// status to sealed or unsealed.
NotifySealedStateChange() error
// Run executes any background service discovery tasks until the
// shutdown channel is closed.
RunServiceDiscovery(waitGroup *sync.WaitGroup, shutdownCh ShutdownChannel, redirectAddr string, activeFunc activeFunction, sealedFunc sealedFunction) error
}
type Lock interface {
// Lock is used to acquire the given lock
// The stopCh is optional and if closed should interrupt the lock
// acquisition attempt. The return struct should be closed when
// leadership is lost.
Lock(stopCh <-chan struct{}) (<-chan struct{}, error)
// Unlock is used to release the lock
Unlock() error
// Returns the value of the lock and if it is held
Value() (bool, string, error)
}
// Entry is used to represent data stored by the physical backend
type Entry struct {
Key string
Value []byte
}
// Factory is the factory function to create a physical backend.
type Factory func(config map[string]string, logger log.Logger) (Backend, error)
// NewBackend returns a new backend with the given type and configuration.
// The backend is looked up in the builtinBackends variable.
func NewBackend(t string, logger log.Logger, conf map[string]string) (Backend, error) {
f, ok := builtinBackends[t]
if !ok {
return nil, fmt.Errorf("unknown physical backend type: %s", t)
}
return f(conf, logger)
}
// BuiltinBackends is the list of built-in physical backends that can
// be used with NewBackend.
var builtinBackends = map[string]Factory{
"inmem": func(_ map[string]string, logger log.Logger) (Backend, error) {
return NewInmem(logger), nil
},
"inmem_transactional": func(_ map[string]string, logger log.Logger) (Backend, error) {
return NewTransactionalInmem(logger), nil
},
"inmem_ha": func(_ map[string]string, logger log.Logger) (Backend, error) {
return NewInmemHA(logger), nil
},
"inmem_transactional_ha": func(_ map[string]string, logger log.Logger) (Backend, error) {
return NewTransactionalInmemHA(logger), nil
},
"file_transactional": newTransactionalFileBackend,
"consul": newConsulBackend,
"zookeeper": newZookeeperBackend,
"file": newFileBackend,
"s3": newS3Backend,
"azure": newAzureBackend,
"dynamodb": newDynamoDBBackend,
"etcd": newEtcdBackend,
"mssql": newMsSQLBackend,
"mysql": newMySQLBackend,
"postgresql": newPostgreSQLBackend,
"swift": newSwiftBackend,
"gcs": newGCSBackend,
}
// PermitPool is used to limit maximum outstanding requests
type PermitPool struct {
sem chan int
}
// NewPermitPool returns a new permit pool with the provided
// number of permits
func NewPermitPool(permits int) *PermitPool {
if permits < 1 {
permits = DefaultParallelOperations
}
return &PermitPool{
sem: make(chan int, permits),
}
}
// Acquire returns when a permit has been acquired
func (c *PermitPool) Acquire() {
c.sem <- 1
}
// Release returns a permit to the pool
func (c *PermitPool) Release() {
<-c.sem
}