-
Notifications
You must be signed in to change notification settings - Fork 0
/
backend.go
144 lines (124 loc) · 4.34 KB
/
backend.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
/*
Copyright 2015 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package backend
import (
"time"
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
)
// Forever means that object TTL will not expire unless deleted
const (
Forever time.Duration = 0
MaxLockDuration time.Duration = time.Minute
)
// Backend implements abstraction over local or remote storage backend
//
// Storage is modeled after BoltDB:
// * bucket is a slice []string{"a", "b"}
// * buckets contain key value pairs
//
type Backend interface {
// GetKeys returns a list of keys for a given path
GetKeys(bucket []string) ([]string, error)
// CreateVal creates value with a given TTL and key in the bucket
// if the value already exists, it must return trace.AlreadyExistsError
CreateVal(bucket []string, key string, val []byte, ttl time.Duration) error
// UpsertVal updates or inserts value with a given TTL into a bucket
// ForeverTTL for no TTL
UpsertVal(bucket []string, key string, val []byte, ttl time.Duration) error
// GetVal return a value for a given key in the bucket
GetVal(path []string, key string) ([]byte, error)
// DeleteKey deletes a key in a bucket
DeleteKey(bucket []string, key string) error
// DeleteBucket deletes the bucket by a given path
DeleteBucket(path []string, bkt string) error
// AcquireLock grabs a lock that will be released automatically in TTL
AcquireLock(token string, ttl time.Duration) error
// ReleaseLock forces lock release before TTL
ReleaseLock(token string) error
// Close releases the resources taken up by this backend
Close() error
// Clock returns clock used by this backend
Clock() clockwork.Clock
}
// Item is a pair of key and value
type Item struct {
// Key is an item key
Key string
// Value is an item value
Value []byte
}
// ItemsGetter is an interface that allows gettings all
// items in the bucket at once
type ItemsGetter interface {
// GetItems returns a list of items - key value pairs
GetItems(bucket []string) ([]Item, error)
}
// backend.Params type defines a flexible unified back-end configuration API.
// It is just a map of key/value pairs which gets populated by `storage` section
// in Teleport YAML config.
type Params map[string]interface{}
// NewFunc type defines a function type which every backend must implement to
// instantiate itself
type NewFunc func(Params) (Backend, error)
// NameFunc type defines a function type which every backend must implement
// to return its name
type NameFunc func() string
// Config is used for 'storage' config section. It's a combination of
// values for various backends: 'boltdb', 'etcd', 'filesystem' and 'dynamodb'
type Config struct {
// Type can be "bolt" or "etcd" or "dynamodb"
Type string `yaml:"type,omitempty"`
// Params is a generic key/value property bag which allows arbitrary
// falues to be passed to backend
Params Params `yaml:",inline"`
}
// ValidateLockTTL helper allows all backends to validate lock TTL parameter
func ValidateLockTTL(ttl time.Duration) error {
if ttl == Forever || ttl > MaxLockDuration {
return trace.BadParameter("locks cannot exceed %v", MaxLockDuration)
}
return nil
}
// GetString returns a string value stored in Params map, or an empty string
// if nothing is found
func (p Params) GetString(key string) string {
v, ok := p[key]
if !ok {
return ""
}
s, _ := v.(string)
return s
}
// TTL converts time to TTL from current time supplied
// by provider, if t is zero, returns forever
func TTL(clock clockwork.Clock, t time.Time) time.Duration {
if t.IsZero() {
return Forever
}
diff := t.UTC().Sub(clock.Now().UTC())
if diff < 0 {
return Forever
}
return diff
}
// AnyTTL returns TTL if any of the suplied times pass expiry time
// otherwise returns forever
func AnyTTL(clock clockwork.Clock, times ...time.Time) time.Duration {
for _, t := range times {
if !t.IsZero() {
return TTL(clock, t)
}
}
return Forever
}