mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-06-10 10:15:57 +00:00
vendor: revendor
This commit is contained in:
parent
269295a414
commit
9f0440be0f
669 changed files with 58447 additions and 20021 deletions
2
vendor/k8s.io/apiserver/pkg/storage/OWNERS
generated
vendored
2
vendor/k8s.io/apiserver/pkg/storage/OWNERS
generated
vendored
|
|
@ -23,6 +23,4 @@ reviewers:
|
|||
- ingvagabund
|
||||
- resouer
|
||||
- mbohlool
|
||||
- mqliang
|
||||
- rrati
|
||||
- enj
|
||||
|
|
|
|||
40
vendor/k8s.io/apiserver/pkg/storage/cacher/cacher.go
generated
vendored
40
vendor/k8s.io/apiserver/pkg/storage/cacher/cacher.go
generated
vendored
|
|
@ -158,8 +158,10 @@ func (i *indexedWatchers) terminateAll(objectType reflect.Type, done func(*cache
|
|||
// second in a bucket, and pop up them once at the timeout. To be more specific,
|
||||
// if you set fire time at X, you can get the bookmark within (X-1,X+1) period.
|
||||
type watcherBookmarkTimeBuckets struct {
|
||||
lock sync.Mutex
|
||||
lock sync.Mutex
|
||||
// the key of watcherBuckets is the number of seconds since createTime
|
||||
watchersBuckets map[int64][]*cacheWatcher
|
||||
createTime time.Time
|
||||
startBucketID int64
|
||||
clock clock.Clock
|
||||
bookmarkFrequency time.Duration
|
||||
|
|
@ -168,7 +170,8 @@ type watcherBookmarkTimeBuckets struct {
|
|||
func newTimeBucketWatchers(clock clock.Clock, bookmarkFrequency time.Duration) *watcherBookmarkTimeBuckets {
|
||||
return &watcherBookmarkTimeBuckets{
|
||||
watchersBuckets: make(map[int64][]*cacheWatcher),
|
||||
startBucketID: clock.Now().Unix(),
|
||||
createTime: clock.Now(),
|
||||
startBucketID: 0,
|
||||
clock: clock,
|
||||
bookmarkFrequency: bookmarkFrequency,
|
||||
}
|
||||
|
|
@ -181,7 +184,7 @@ func (t *watcherBookmarkTimeBuckets) addWatcher(w *cacheWatcher) bool {
|
|||
if !ok {
|
||||
return false
|
||||
}
|
||||
bucketID := nextTime.Unix()
|
||||
bucketID := int64(nextTime.Sub(t.createTime) / time.Second)
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
if bucketID < t.startBucketID {
|
||||
|
|
@ -193,7 +196,7 @@ func (t *watcherBookmarkTimeBuckets) addWatcher(w *cacheWatcher) bool {
|
|||
}
|
||||
|
||||
func (t *watcherBookmarkTimeBuckets) popExpiredWatchers() [][]*cacheWatcher {
|
||||
currentBucketID := t.clock.Now().Unix()
|
||||
currentBucketID := int64(t.clock.Since(t.createTime) / time.Second)
|
||||
// There should be one or two elements in almost all cases
|
||||
expiredWatchers := make([][]*cacheWatcher, 0, 2)
|
||||
t.lock.Lock()
|
||||
|
|
@ -263,7 +266,7 @@ type Cacher struct {
|
|||
|
||||
// Defines a time budget that can be spend on waiting for not-ready watchers
|
||||
// while dispatching event before shutting them down.
|
||||
dispatchTimeoutBudget *timeBudget
|
||||
dispatchTimeoutBudget timeBudget
|
||||
|
||||
// Handling graceful termination.
|
||||
stopLock sync.RWMutex
|
||||
|
|
@ -730,7 +733,7 @@ func (c *Cacher) List(ctx context.Context, key string, opts storage.ListOptions,
|
|||
// GuaranteedUpdate implements storage.Interface.
|
||||
func (c *Cacher) GuaranteedUpdate(
|
||||
ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool,
|
||||
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, _ ...runtime.Object) error {
|
||||
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, _ runtime.Object) error {
|
||||
// Ignore the suggestion and try to pass down the current version of the object
|
||||
// read from cache.
|
||||
if elem, exists, err := c.watchCache.GetByKey(key); err != nil {
|
||||
|
|
@ -740,7 +743,7 @@ func (c *Cacher) GuaranteedUpdate(
|
|||
return c.storage.GuaranteedUpdate(ctx, key, ptrToType, ignoreNotFound, preconditions, tryUpdate, currObj)
|
||||
}
|
||||
// If we couldn't get the object, fallback to no-suggestion.
|
||||
return c.storage.GuaranteedUpdate(ctx, key, ptrToType, ignoreNotFound, preconditions, tryUpdate)
|
||||
return c.storage.GuaranteedUpdate(ctx, key, ptrToType, ignoreNotFound, preconditions, tryUpdate, nil)
|
||||
}
|
||||
|
||||
// Count implements storage.Interface.
|
||||
|
|
@ -793,7 +796,19 @@ func (c *Cacher) dispatchEvents() {
|
|||
if !ok {
|
||||
return
|
||||
}
|
||||
c.dispatchEvent(&event)
|
||||
// Don't dispatch bookmarks coming from the storage layer.
|
||||
// They can be very frequent (even to the level of subseconds)
|
||||
// to allow efficient watch resumption on kube-apiserver restarts,
|
||||
// and propagating them down may overload the whole system.
|
||||
//
|
||||
// TODO: If at some point we decide the performance and scalability
|
||||
// footprint is acceptable, this is the place to hook them in.
|
||||
// However, we then need to check if this was called as a result
|
||||
// of a bookmark event or regular Add/Update/Delete operation by
|
||||
// checking if resourceVersion here has changed.
|
||||
if event.Type != watch.Bookmark {
|
||||
c.dispatchEvent(&event)
|
||||
}
|
||||
lastProcessedResourceVersion = event.ResourceVersion
|
||||
case <-bookmarkTimer.C():
|
||||
bookmarkTimer.Reset(wait.Jitter(time.Second, 0.25))
|
||||
|
|
@ -1098,7 +1113,14 @@ func (lw *cacherListerWatcher) List(options metav1.ListOptions) (runtime.Object,
|
|||
|
||||
// Implements cache.ListerWatcher interface.
|
||||
func (lw *cacherListerWatcher) Watch(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return lw.storage.WatchList(context.TODO(), lw.resourcePrefix, storage.ListOptions{ResourceVersion: options.ResourceVersion, Predicate: storage.Everything})
|
||||
opts := storage.ListOptions{
|
||||
ResourceVersion: options.ResourceVersion,
|
||||
Predicate: storage.Everything,
|
||||
}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.EfficientWatchResumption) {
|
||||
opts.ProgressNotify = true
|
||||
}
|
||||
return lw.storage.WatchList(context.TODO(), lw.resourcePrefix, opts)
|
||||
}
|
||||
|
||||
// errWatcher implements watch.Interface to return a single error
|
||||
|
|
|
|||
17
vendor/k8s.io/apiserver/pkg/storage/cacher/time_budget.go
generated
vendored
17
vendor/k8s.io/apiserver/pkg/storage/cacher/time_budget.go
generated
vendored
|
|
@ -39,7 +39,12 @@ const (
|
|||
// NOTE: It's not recommended to be used concurrently from multiple threads -
|
||||
// if first user takes the whole timeout, the second one will get 0 timeout
|
||||
// even though the first one may return something later.
|
||||
type timeBudget struct {
|
||||
type timeBudget interface {
|
||||
takeAvailable() time.Duration
|
||||
returnUnused(unused time.Duration)
|
||||
}
|
||||
|
||||
type timeBudgetImpl struct {
|
||||
sync.Mutex
|
||||
budget time.Duration
|
||||
|
||||
|
|
@ -47,8 +52,8 @@ type timeBudget struct {
|
|||
maxBudget time.Duration
|
||||
}
|
||||
|
||||
func newTimeBudget(stopCh <-chan struct{}) *timeBudget {
|
||||
result := &timeBudget{
|
||||
func newTimeBudget(stopCh <-chan struct{}) timeBudget {
|
||||
result := &timeBudgetImpl{
|
||||
budget: time.Duration(0),
|
||||
refresh: refreshPerSecond,
|
||||
maxBudget: maxBudget,
|
||||
|
|
@ -57,7 +62,7 @@ func newTimeBudget(stopCh <-chan struct{}) *timeBudget {
|
|||
return result
|
||||
}
|
||||
|
||||
func (t *timeBudget) periodicallyRefresh(stopCh <-chan struct{}) {
|
||||
func (t *timeBudgetImpl) periodicallyRefresh(stopCh <-chan struct{}) {
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
|
|
@ -74,7 +79,7 @@ func (t *timeBudget) periodicallyRefresh(stopCh <-chan struct{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func (t *timeBudget) takeAvailable() time.Duration {
|
||||
func (t *timeBudgetImpl) takeAvailable() time.Duration {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
result := t.budget
|
||||
|
|
@ -82,7 +87,7 @@ func (t *timeBudget) takeAvailable() time.Duration {
|
|||
return result
|
||||
}
|
||||
|
||||
func (t *timeBudget) returnUnused(unused time.Duration) {
|
||||
func (t *timeBudgetImpl) returnUnused(unused time.Duration) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
if unused < 0 {
|
||||
|
|
|
|||
31
vendor/k8s.io/apiserver/pkg/storage/cacher/watch_cache.go
generated
vendored
31
vendor/k8s.io/apiserver/pkg/storage/cacher/watch_cache.go
generated
vendored
|
|
@ -320,8 +320,9 @@ func (w *watchCache) processEvent(event watch.Event, resourceVersion uint64, upd
|
|||
}
|
||||
|
||||
// Avoid calling event handler under lock.
|
||||
// This is safe as long as there is at most one call to processEvent in flight
|
||||
// at any point in time.
|
||||
// This is safe as long as there is at most one call to Add/Update/Delete and
|
||||
// UpdateResourceVersion in flight at any point in time, which is true now,
|
||||
// because reflector calls them synchronously from its main thread.
|
||||
if w.eventHandler != nil {
|
||||
w.eventHandler(wcEvent)
|
||||
}
|
||||
|
|
@ -381,6 +382,32 @@ func (w *watchCache) doCacheResizeLocked(capacity int) {
|
|||
w.capacity = capacity
|
||||
}
|
||||
|
||||
func (w *watchCache) UpdateResourceVersion(resourceVersion string) {
|
||||
rv, err := w.versioner.ParseResourceVersion(resourceVersion)
|
||||
if err != nil {
|
||||
klog.Errorf("Couldn't parse resourceVersion: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
func() {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
w.resourceVersion = rv
|
||||
}()
|
||||
|
||||
// Avoid calling event handler under lock.
|
||||
// This is safe as long as there is at most one call to Add/Update/Delete and
|
||||
// UpdateResourceVersion in flight at any point in time, which is true now,
|
||||
// because reflector calls them synchronously from its main thread.
|
||||
if w.eventHandler != nil {
|
||||
wcEvent := &watchCacheEvent{
|
||||
Type: watch.Bookmark,
|
||||
ResourceVersion: rv,
|
||||
}
|
||||
w.eventHandler(wcEvent)
|
||||
}
|
||||
}
|
||||
|
||||
// List returns list of pointers to <storeElement> objects.
|
||||
func (w *watchCache) List() []interface{} {
|
||||
return w.store.List()
|
||||
|
|
|
|||
20
vendor/k8s.io/apiserver/pkg/storage/etcd3/event.go
generated
vendored
20
vendor/k8s.io/apiserver/pkg/storage/etcd3/event.go
generated
vendored
|
|
@ -23,12 +23,13 @@ import (
|
|||
)
|
||||
|
||||
type event struct {
|
||||
key string
|
||||
value []byte
|
||||
prevValue []byte
|
||||
rev int64
|
||||
isDeleted bool
|
||||
isCreated bool
|
||||
key string
|
||||
value []byte
|
||||
prevValue []byte
|
||||
rev int64
|
||||
isDeleted bool
|
||||
isCreated bool
|
||||
isProgressNotify bool
|
||||
}
|
||||
|
||||
// parseKV converts a KeyValue retrieved from an initial sync() listing to a synthetic isCreated event.
|
||||
|
|
@ -61,3 +62,10 @@ func parseEvent(e *clientv3.Event) (*event, error) {
|
|||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func progressNotifyEvent(rev int64) *event {
|
||||
return &event{
|
||||
rev: rev,
|
||||
isProgressNotify: true,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
vendor/k8s.io/apiserver/pkg/storage/etcd3/metrics/metrics.go
generated
vendored
22
vendor/k8s.io/apiserver/pkg/storage/etcd3/metrics/metrics.go
generated
vendored
|
|
@ -35,8 +35,12 @@ import (
|
|||
var (
|
||||
etcdRequestLatency = compbasemetrics.NewHistogramVec(
|
||||
&compbasemetrics.HistogramOpts{
|
||||
Name: "etcd_request_duration_seconds",
|
||||
Help: "Etcd request latency in seconds for each operation and object type.",
|
||||
Name: "etcd_request_duration_seconds",
|
||||
Help: "Etcd request latency in seconds for each operation and object type.",
|
||||
// Keeping it similar to the buckets used by the apiserver_request_duration_seconds metric so that
|
||||
// api latency and etcd latency can be more comparable side by side.
|
||||
Buckets: []float64{.005, .01, .025, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7,
|
||||
0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40, 50, 60},
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{"operation", "type"},
|
||||
|
|
@ -57,6 +61,14 @@ var (
|
|||
},
|
||||
[]string{"endpoint"},
|
||||
)
|
||||
etcdBookmarkCounts = compbasemetrics.NewGaugeVec(
|
||||
&compbasemetrics.GaugeOpts{
|
||||
Name: "etcd_bookmark_counts",
|
||||
Help: "Number of etcd bookmarks (progress notify events) split by kind.",
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
},
|
||||
[]string{"resource"},
|
||||
)
|
||||
)
|
||||
|
||||
var registerMetrics sync.Once
|
||||
|
|
@ -68,6 +80,7 @@ func Register() {
|
|||
legacyregistry.MustRegister(etcdRequestLatency)
|
||||
legacyregistry.MustRegister(objectCounts)
|
||||
legacyregistry.MustRegister(dbTotalSize)
|
||||
legacyregistry.MustRegister(etcdBookmarkCounts)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +94,11 @@ func RecordEtcdRequestLatency(verb, resource string, startTime time.Time) {
|
|||
etcdRequestLatency.WithLabelValues(verb, resource).Observe(sinceInSeconds(startTime))
|
||||
}
|
||||
|
||||
// RecordEtcdBookmark updates the etcd_bookmark_counts metric.
|
||||
func RecordEtcdBookmark(resource string) {
|
||||
etcdBookmarkCounts.WithLabelValues(resource).Inc()
|
||||
}
|
||||
|
||||
// Reset resets the etcd_request_duration_seconds metric.
|
||||
func Reset() {
|
||||
etcdRequestLatency.Reset()
|
||||
|
|
|
|||
16
vendor/k8s.io/apiserver/pkg/storage/etcd3/store.go
generated
vendored
16
vendor/k8s.io/apiserver/pkg/storage/etcd3/store.go
generated
vendored
|
|
@ -83,11 +83,11 @@ type objState struct {
|
|||
}
|
||||
|
||||
// New returns an etcd3 implementation of storage.Interface.
|
||||
func New(c *clientv3.Client, codec runtime.Codec, prefix string, transformer value.Transformer, pagingEnabled bool) storage.Interface {
|
||||
return newStore(c, pagingEnabled, codec, prefix, transformer)
|
||||
func New(c *clientv3.Client, codec runtime.Codec, newFunc func() runtime.Object, prefix string, transformer value.Transformer, pagingEnabled bool) storage.Interface {
|
||||
return newStore(c, newFunc, pagingEnabled, codec, prefix, transformer)
|
||||
}
|
||||
|
||||
func newStore(c *clientv3.Client, pagingEnabled bool, codec runtime.Codec, prefix string, transformer value.Transformer) *store {
|
||||
func newStore(c *clientv3.Client, newFunc func() runtime.Object, pagingEnabled bool, codec runtime.Codec, prefix string, transformer value.Transformer) *store {
|
||||
versioner := APIObjectVersioner{}
|
||||
result := &store{
|
||||
client: c,
|
||||
|
|
@ -99,7 +99,7 @@ func newStore(c *clientv3.Client, pagingEnabled bool, codec runtime.Codec, prefi
|
|||
// no-op for default prefix of '/registry'.
|
||||
// keeps compatibility with etcd2 impl for custom prefixes that don't start with '/'
|
||||
pathPrefix: path.Join("/", prefix),
|
||||
watcher: newWatcher(c, codec, versioner, transformer),
|
||||
watcher: newWatcher(c, codec, newFunc, versioner, transformer),
|
||||
leaseManager: newDefaultLeaseManager(c),
|
||||
}
|
||||
return result
|
||||
|
|
@ -238,7 +238,7 @@ func (s *store) conditionalDelete(ctx context.Context, key string, out runtime.O
|
|||
// GuaranteedUpdate implements storage.Interface.GuaranteedUpdate.
|
||||
func (s *store) GuaranteedUpdate(
|
||||
ctx context.Context, key string, out runtime.Object, ignoreNotFound bool,
|
||||
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, suggestion ...runtime.Object) error {
|
||||
preconditions *storage.Preconditions, tryUpdate storage.UpdateFunc, suggestion runtime.Object) error {
|
||||
trace := utiltrace.New("GuaranteedUpdate etcd3", utiltrace.Field{"type", getTypeName(out)})
|
||||
defer trace.LogIfLong(500 * time.Millisecond)
|
||||
|
||||
|
|
@ -260,8 +260,8 @@ func (s *store) GuaranteedUpdate(
|
|||
|
||||
var origState *objState
|
||||
var mustCheckData bool
|
||||
if len(suggestion) == 1 && suggestion[0] != nil {
|
||||
origState, err = s.getStateFromObject(suggestion[0])
|
||||
if suggestion != nil {
|
||||
origState, err = s.getStateFromObject(suggestion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -784,7 +784,7 @@ func (s *store) watch(ctx context.Context, key string, opts storage.ListOptions,
|
|||
return nil, err
|
||||
}
|
||||
key = path.Join(s.pathPrefix, key)
|
||||
return s.watcher.Watch(ctx, key, int64(rev), recursive, opts.Predicate)
|
||||
return s.watcher.Watch(ctx, key, int64(rev), recursive, opts.ProgressNotify, opts.Predicate)
|
||||
}
|
||||
|
||||
func (s *store) getState(getResp *clientv3.GetResponse, key string, v reflect.Value, ignoreNotFound bool) (*objState, error) {
|
||||
|
|
|
|||
50
vendor/k8s.io/apiserver/pkg/storage/etcd3/watcher.go
generated
vendored
50
vendor/k8s.io/apiserver/pkg/storage/etcd3/watcher.go
generated
vendored
|
|
@ -21,6 +21,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
|
@ -29,6 +30,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/etcd3/metrics"
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
|
||||
"go.etcd.io/etcd/clientv3"
|
||||
|
|
@ -68,6 +70,8 @@ func TestOnlySetFatalOnDecodeError(b bool) {
|
|||
type watcher struct {
|
||||
client *clientv3.Client
|
||||
codec runtime.Codec
|
||||
newFunc func() runtime.Object
|
||||
objectType string
|
||||
versioner storage.Versioner
|
||||
transformer value.Transformer
|
||||
}
|
||||
|
|
@ -78,6 +82,7 @@ type watchChan struct {
|
|||
key string
|
||||
initialRev int64
|
||||
recursive bool
|
||||
progressNotify bool
|
||||
internalPred storage.SelectionPredicate
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
|
|
@ -86,13 +91,20 @@ type watchChan struct {
|
|||
errChan chan error
|
||||
}
|
||||
|
||||
func newWatcher(client *clientv3.Client, codec runtime.Codec, versioner storage.Versioner, transformer value.Transformer) *watcher {
|
||||
return &watcher{
|
||||
func newWatcher(client *clientv3.Client, codec runtime.Codec, newFunc func() runtime.Object, versioner storage.Versioner, transformer value.Transformer) *watcher {
|
||||
res := &watcher{
|
||||
client: client,
|
||||
codec: codec,
|
||||
newFunc: newFunc,
|
||||
versioner: versioner,
|
||||
transformer: transformer,
|
||||
}
|
||||
if newFunc == nil {
|
||||
res.objectType = "<unknown>"
|
||||
} else {
|
||||
res.objectType = reflect.TypeOf(newFunc()).String()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Watch watches on a key and returns a watch.Interface that transfers relevant notifications.
|
||||
|
|
@ -102,21 +114,22 @@ func newWatcher(client *clientv3.Client, codec runtime.Codec, versioner storage.
|
|||
// If recursive is false, it watches on given key.
|
||||
// If recursive is true, it watches any children and directories under the key, excluding the root key itself.
|
||||
// pred must be non-nil. Only if pred matches the change, it will be returned.
|
||||
func (w *watcher) Watch(ctx context.Context, key string, rev int64, recursive bool, pred storage.SelectionPredicate) (watch.Interface, error) {
|
||||
func (w *watcher) Watch(ctx context.Context, key string, rev int64, recursive, progressNotify bool, pred storage.SelectionPredicate) (watch.Interface, error) {
|
||||
if recursive && !strings.HasSuffix(key, "/") {
|
||||
key += "/"
|
||||
}
|
||||
wc := w.createWatchChan(ctx, key, rev, recursive, pred)
|
||||
wc := w.createWatchChan(ctx, key, rev, recursive, progressNotify, pred)
|
||||
go wc.run()
|
||||
return wc, nil
|
||||
}
|
||||
|
||||
func (w *watcher) createWatchChan(ctx context.Context, key string, rev int64, recursive bool, pred storage.SelectionPredicate) *watchChan {
|
||||
func (w *watcher) createWatchChan(ctx context.Context, key string, rev int64, recursive, progressNotify bool, pred storage.SelectionPredicate) *watchChan {
|
||||
wc := &watchChan{
|
||||
watcher: w,
|
||||
key: key,
|
||||
initialRev: rev,
|
||||
recursive: recursive,
|
||||
progressNotify: progressNotify,
|
||||
internalPred: pred,
|
||||
incomingEventChan: make(chan *event, incomingBufSize),
|
||||
resultChan: make(chan watch.Event, outgoingBufSize),
|
||||
|
|
@ -223,6 +236,9 @@ func (wc *watchChan) startWatching(watchClosedCh chan struct{}) {
|
|||
if wc.recursive {
|
||||
opts = append(opts, clientv3.WithPrefix())
|
||||
}
|
||||
if wc.progressNotify {
|
||||
opts = append(opts, clientv3.WithProgressNotify())
|
||||
}
|
||||
wch := wc.watcher.client.Watch(wc.ctx, wc.key, opts...)
|
||||
for wres := range wch {
|
||||
if wres.Err() != nil {
|
||||
|
|
@ -232,6 +248,12 @@ func (wc *watchChan) startWatching(watchClosedCh chan struct{}) {
|
|||
wc.sendError(err)
|
||||
return
|
||||
}
|
||||
if wres.IsProgressNotify() {
|
||||
wc.sendEvent(progressNotifyEvent(wres.Header.GetRevision()))
|
||||
metrics.RecordEtcdBookmark(wc.watcher.objectType)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, e := range wres.Events {
|
||||
parsedEvent, err := parseEvent(e)
|
||||
if err != nil {
|
||||
|
|
@ -299,6 +321,19 @@ func (wc *watchChan) transform(e *event) (res *watch.Event) {
|
|||
}
|
||||
|
||||
switch {
|
||||
case e.isProgressNotify:
|
||||
if wc.watcher.newFunc == nil {
|
||||
return nil
|
||||
}
|
||||
object := wc.watcher.newFunc()
|
||||
if err := wc.watcher.versioner.UpdateObject(object, uint64(e.rev)); err != nil {
|
||||
klog.Errorf("failed to propagate object version: %v", err)
|
||||
return nil
|
||||
}
|
||||
res = &watch.Event{
|
||||
Type: watch.Bookmark,
|
||||
Object: object,
|
||||
}
|
||||
case e.isDeleted:
|
||||
if !wc.filter(oldObj) {
|
||||
return nil
|
||||
|
|
@ -376,6 +411,11 @@ func (wc *watchChan) sendEvent(e *event) {
|
|||
}
|
||||
|
||||
func (wc *watchChan) prepareObjs(e *event) (curObj runtime.Object, oldObj runtime.Object, err error) {
|
||||
if e.isProgressNotify {
|
||||
// progressNotify events doesn't contain neither current nor previous object version,
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
if !e.isDeleted {
|
||||
data, _, err := wc.watcher.transformer.TransformFromStorage(e.value, authenticatedDataString(e.key))
|
||||
if err != nil {
|
||||
|
|
|
|||
11
vendor/k8s.io/apiserver/pkg/storage/interfaces.go
generated
vendored
11
vendor/k8s.io/apiserver/pkg/storage/interfaces.go
generated
vendored
|
|
@ -215,9 +215,9 @@ type Interface interface {
|
|||
// or zero value in 'ptrToType' parameter otherwise.
|
||||
// If the object to update has the same value as previous, it won't do any update
|
||||
// but will return the object in 'ptrToType' parameter.
|
||||
// If 'suggestion' can contain zero or one element - in such case this can be used as
|
||||
// a suggestion about the current version of the object to avoid read operation from
|
||||
// storage to get it.
|
||||
// If 'suggestion' is non-nil, it can be used as a suggestion about the current version
|
||||
// of the object to avoid read operation from storage to get it. However, the
|
||||
// implementations have to retry in case suggestion is stale.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
|
|
@ -239,7 +239,7 @@ type Interface interface {
|
|||
// )
|
||||
GuaranteedUpdate(
|
||||
ctx context.Context, key string, ptrToType runtime.Object, ignoreNotFound bool,
|
||||
precondtions *Preconditions, tryUpdate UpdateFunc, suggestion ...runtime.Object) error
|
||||
precondtions *Preconditions, tryUpdate UpdateFunc, suggestion runtime.Object) error
|
||||
|
||||
// Count returns number of different entries under the key (generally being path prefix).
|
||||
Count(key string) (int64, error)
|
||||
|
|
@ -269,4 +269,7 @@ type ListOptions struct {
|
|||
ResourceVersionMatch metav1.ResourceVersionMatch
|
||||
// Predicate provides the selection rules for the list operation.
|
||||
Predicate SelectionPredicate
|
||||
// ProgressNotify determines whether storage-originated bookmark (progress notify) events should
|
||||
// be delivered to the users. The option is ignored for non-watch requests.
|
||||
ProgressNotify bool
|
||||
}
|
||||
|
|
|
|||
4
vendor/k8s.io/apiserver/pkg/storage/storagebackend/config.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/storage/storagebackend/config.go
generated
vendored
|
|
@ -30,6 +30,7 @@ const (
|
|||
|
||||
DefaultCompactInterval = 5 * time.Minute
|
||||
DefaultDBMetricPollInterval = 30 * time.Second
|
||||
DefaultHealthcheckTimeout = 2 * time.Second
|
||||
)
|
||||
|
||||
// TransportConfig holds all connection related info, i.e. equal TransportConfig means equal servers we talk to.
|
||||
|
|
@ -74,6 +75,8 @@ type Config struct {
|
|||
CountMetricPollPeriod time.Duration
|
||||
// DBMetricPollInterval specifies how often should storage backend metric be updated.
|
||||
DBMetricPollInterval time.Duration
|
||||
// HealthcheckTimeout specifies the timeout used when checking health
|
||||
HealthcheckTimeout time.Duration
|
||||
}
|
||||
|
||||
func NewDefaultConfig(prefix string, codec runtime.Codec) *Config {
|
||||
|
|
@ -83,5 +86,6 @@ func NewDefaultConfig(prefix string, codec runtime.Codec) *Config {
|
|||
Codec: codec,
|
||||
CompactionInterval: DefaultCompactInterval,
|
||||
DBMetricPollInterval: DefaultDBMetricPollInterval,
|
||||
HealthcheckTimeout: DefaultHealthcheckTimeout,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go
generated
vendored
11
vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/etcd3.go
generated
vendored
|
|
@ -31,6 +31,7 @@ import (
|
|||
"go.etcd.io/etcd/pkg/transport"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/server/egressselector"
|
||||
|
|
@ -91,7 +92,11 @@ func newETCD3HealthCheck(c storagebackend.Config) (func() error, error) {
|
|||
return fmt.Errorf(errMsg)
|
||||
}
|
||||
client := clientValue.Load().(*clientv3.Client)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
healthcheckTimeout := storagebackend.DefaultHealthcheckTimeout
|
||||
if c.HealthcheckTimeout != time.Duration(0) {
|
||||
healthcheckTimeout = c.HealthcheckTimeout
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), healthcheckTimeout)
|
||||
defer cancel()
|
||||
// See https://github.com/etcd-io/etcd/blob/c57f8b3af865d1b531b979889c602ba14377420e/etcdctl/ctlv3/command/ep_command.go#L118
|
||||
_, err := client.Get(ctx, path.Join("/", c.Prefix, "health"))
|
||||
|
|
@ -217,7 +222,7 @@ func startCompactorOnce(c storagebackend.TransportConfig, interval time.Duration
|
|||
}, nil
|
||||
}
|
||||
|
||||
func newETCD3Storage(c storagebackend.Config) (storage.Interface, DestroyFunc, error) {
|
||||
func newETCD3Storage(c storagebackend.Config, newFunc func() runtime.Object) (storage.Interface, DestroyFunc, error) {
|
||||
stopCompactor, err := startCompactorOnce(c.Transport, c.CompactionInterval)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
@ -249,7 +254,7 @@ func newETCD3Storage(c storagebackend.Config) (storage.Interface, DestroyFunc, e
|
|||
if transformer == nil {
|
||||
transformer = value.IdentityTransformer
|
||||
}
|
||||
return etcd3.New(client, c.Codec, c.Prefix, transformer, c.Paging), destroyFunc, nil
|
||||
return etcd3.New(client, c.Codec, newFunc, c.Prefix, transformer, c.Paging), destroyFunc, nil
|
||||
}
|
||||
|
||||
// startDBSizeMonitorPerEndpoint starts a loop to monitor etcd database size and update the
|
||||
|
|
|
|||
5
vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/factory.go
generated
vendored
5
vendor/k8s.io/apiserver/pkg/storage/storagebackend/factory/factory.go
generated
vendored
|
|
@ -19,6 +19,7 @@ package factory
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
)
|
||||
|
|
@ -27,12 +28,12 @@ import (
|
|||
type DestroyFunc func()
|
||||
|
||||
// Create creates a storage backend based on given config.
|
||||
func Create(c storagebackend.Config) (storage.Interface, DestroyFunc, error) {
|
||||
func Create(c storagebackend.Config, newFunc func() runtime.Object) (storage.Interface, DestroyFunc, error) {
|
||||
switch c.Type {
|
||||
case "etcd2":
|
||||
return nil, nil, fmt.Errorf("%v is no longer a supported storage backend", c.Type)
|
||||
case storagebackend.StorageTypeUnset, storagebackend.StorageTypeETCD3:
|
||||
return newETCD3Storage(c)
|
||||
return newETCD3Storage(c, newFunc)
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("unknown storage type: %s", c.Type)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue