diff --git a/cache/cache.go b/cache/cache.go index 3e68f733..af5ba8d4 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -32,22 +32,17 @@ const ( defaultInterval = time.Minute ) -// Cache[T] is a thread-safe in-memory key/object store. -// It can be used to store objects with optional expiration. -// A function to extract the key from the object must be provided. -// Use the New function to create a new cache that is ready to use. +// Cache[T] is a thread-safe in-memory key/value store. +// It can be used to store items with optional expiration. type Cache[T any] struct { *cache[T] - // keyFunc is used to make the key for objects stored in and retrieved from index, and - // should be deterministic. - keyFunc KeyFunc[T] } // item is an item stored in the cache. type item[T any] struct { key string - // object is the item's object. - object T + // value is the item's value. + value T // expiresAt is the item's expiration time. expiresAt time.Time } @@ -61,11 +56,10 @@ type cache[T any] struct { // It is initially true, and set to false when the items are not sorted. sorted bool // capacity is the maximum number of index the cache can hold. - capacity int - metrics *cacheMetrics - labelsFunc GetLvsFunc[T] - janitor *janitor[T] - closed bool + capacity int + metrics *cacheMetrics + janitor *janitor[T] + closed bool mu sync.RWMutex } @@ -73,18 +67,17 @@ type cache[T any] struct { var _ Expirable[any] = &Cache[any]{} // New creates a new cache with the given configuration. -func New[T any](capacity int, keyFunc KeyFunc[T], opts ...Options[T]) (*Cache[T], error) { +func New[T any](capacity int, opts ...Options) (*Cache[T], error) { opt, err := makeOptions(opts...) if err != nil { return nil, fmt.Errorf("failed to apply options: %w", err) } c := &cache[T]{ - index: make(map[string]*item[T]), - items: make([]*item[T], 0, capacity), - sorted: true, - capacity: capacity, - labelsFunc: opt.labelsFunc, + index: make(map[string]*item[T]), + items: make([]*item[T], 0, capacity), + sorted: true, + capacity: capacity, janitor: &janitor[T]{ interval: opt.interval, stop: make(chan bool), @@ -92,10 +85,10 @@ func New[T any](capacity int, keyFunc KeyFunc[T], opts ...Options[T]) (*Cache[T] } if opt.registerer != nil { - c.metrics = newCacheMetrics(opt.registerer, opt.extraLabels...) + c.metrics = newCacheMetrics(opt.metricsPrefix, opt.registerer) } - C := &Cache[T]{cache: c, keyFunc: keyFunc} + C := &Cache[T]{cache: c} if opt.interval > 0 { go c.janitor.run(c) @@ -104,8 +97,8 @@ func New[T any](capacity int, keyFunc KeyFunc[T], opts ...Options[T]) (*Cache[T] return C, nil } -func makeOptions[T any](opts ...Options[T]) (*storeOptions[T], error) { - opt := storeOptions[T]{} +func makeOptions(opts ...Options) (*storeOptions, error) { + opt := storeOptions{} for _, o := range opts { err := o(&opt) if err != nil { @@ -131,14 +124,8 @@ func (c *Cache[T]) Close() error { } // Set an item in the cache, existing index will be overwritten. -// If the cache is full, Add will return an error. -func (c *Cache[T]) Set(object T) error { - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return &CacheError{Reason: ErrInvalidKey, Err: err} - } - +// If the cache is full, an error is returned. +func (c *Cache[T]) Set(key string, value T) error { c.mu.Lock() if c.closed { c.mu.Unlock() @@ -147,14 +134,14 @@ func (c *Cache[T]) Set(object T) error { } _, found := c.index[key] if found { - c.set(key, object) + c.set(key, value) c.mu.Unlock() recordRequest(c.metrics, StatusSuccess) return nil } if c.capacity > 0 && len(c.index) < c.capacity { - c.set(key, object) + c.set(key, value) c.mu.Unlock() recordRequest(c.metrics, StatusSuccess) recordItemIncrement(c.metrics) @@ -165,10 +152,10 @@ func (c *Cache[T]) Set(object T) error { return ErrCacheFull } -func (c *cache[T]) set(key string, object T) { +func (c *cache[T]) set(key string, value T) { item := item[T]{ key: key, - object: object, + value: value, expiresAt: time.Now().Add(noExpiration), } @@ -181,86 +168,40 @@ func (c *cache[T]) set(key string, object T) { c.items = append(c.items, &item) } -// Get an item from the cache. Returns the item or nil, and a bool indicating -// whether the key was found. -func (c *Cache[T]) Get(object T) (item T, exists bool, err error) { - var res T - lvs := []string{} - if c.labelsFunc != nil { - lvs, err = c.labelsFunc(object, len(c.metrics.getExtraLabels())) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return res, false, &CacheError{Reason: ErrInvalidLabels, Err: err} - } - } - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return res, false, &CacheError{Reason: ErrInvalidKey, Err: err} - } - item, found, err := c.get(key) - if err != nil { - return res, false, err - } - if !found { - recordEvent(c.metrics, CacheEventTypeMiss, lvs...) - return res, false, nil - } - recordEvent(c.metrics, CacheEventTypeHit, lvs...) - return item, true, nil -} - -// GetByKey returns the object for the given key. -func (c *Cache[T]) GetByKey(key string) (T, bool, error) { - var res T - index, found, err := c.get(key) - if err != nil { - return res, false, err - } - if !found { - recordEvent(c.metrics, CacheEventTypeMiss) - return res, false, nil - } - - recordEvent(c.metrics, CacheEventTypeHit) - return index, true, nil -} - -func (c *cache[T]) get(key string) (T, bool, error) { +// Get returns an item in the cache for the given key. If no item is found, an +// error is returned. +// The caller can record cache hit or miss based on the result with +// Cache.RecordCacheEvent(). +func (c *Cache[T]) Get(key string) (T, error) { var res T c.mu.RLock() if c.closed { c.mu.RUnlock() recordRequest(c.metrics, StatusFailure) - return res, false, ErrCacheClosed + return res, ErrCacheClosed } item, found := c.index[key] if !found { c.mu.RUnlock() recordRequest(c.metrics, StatusSuccess) - return res, false, nil + return res, ErrNotFound } if !item.expiresAt.IsZero() { if item.expiresAt.Compare(time.Now()) < 0 { c.mu.RUnlock() recordRequest(c.metrics, StatusSuccess) - return res, false, nil + return res, ErrNotFound } } c.mu.RUnlock() recordRequest(c.metrics, StatusSuccess) - return item.object, true, nil + return item.value, nil } // Delete an item from the cache. Does nothing if the key is not in the cache. // It actually sets the item expiration to `now“, so that it will be deleted at // the cleanup. -func (c *Cache[T]) Delete(object T) error { - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return &CacheError{Reason: ErrInvalidKey, Err: err} - } +func (c *Cache[T]) Delete(key string) error { c.mu.Lock() if c.closed { c.mu.Unlock() @@ -355,13 +296,7 @@ func (c *cache[T]) Resize(size int) (int, error) { } // HasExpired returns true if the item has expired. -func (c *Cache[T]) HasExpired(object T) (bool, error) { - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return false, &CacheError{Reason: ErrInvalidKey, Err: err} - } - +func (c *Cache[T]) HasExpired(key string) (bool, error) { c.mu.RLock() if c.closed { c.mu.RUnlock() @@ -387,13 +322,7 @@ func (c *Cache[T]) HasExpired(object T) (bool, error) { } // SetExpiration sets the expiration for the given key. -func (c *Cache[T]) SetExpiration(object T, expiration time.Time) error { - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return &CacheError{Reason: ErrInvalidKey, Err: err} - } - +func (c *Cache[T]) SetExpiration(key string, expiration time.Time) error { c.mu.Lock() if c.closed { c.mu.Unlock() @@ -417,12 +346,7 @@ func (c *Cache[T]) SetExpiration(object T, expiration time.Time) error { // GetExpiration returns the expiration for the given key. // Returns zero if the key is not in the cache or the item // has already expired. -func (c *Cache[T]) GetExpiration(object T) (time.Time, error) { - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return time.Time{}, &CacheError{Reason: ErrInvalidKey, Err: err} - } +func (c *Cache[T]) GetExpiration(key string) (time.Time, error) { c.mu.RLock() if c.closed { c.mu.RUnlock() @@ -481,6 +405,18 @@ func (c *cache[T]) deleteExpired() { c.mu.Unlock() } +// RecordCacheEvent records a cache event (cache_miss or cache_hit) with kind, +// name and namespace of the associated object being reconciled. +func (c *Cache[T]) RecordCacheEvent(event, kind, name, namespace string) { + recordCacheEvent(c.metrics, event, kind, name, namespace) +} + +// DeleteCacheEvent deletes the cache event (cache_miss or cache_hit) metric for +// the associated object being reconciled, given their kind, name and namespace. +func (c *Cache[T]) DeleteCacheEvent(event, kind, name, namespace string) { + deleteCacheEvent(c.metrics, event, kind, name, namespace) +} + type janitor[T any] struct { interval time.Duration stop chan bool diff --git a/cache/cache_test.go b/cache/cache_test.go index 62dfe393..509801b1 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -23,94 +23,68 @@ import ( "testing" "time" - "github.com/fluxcd/cli-utils/pkg/object" . "github.com/onsi/gomega" "github.com/prometheus/client_golang/prometheus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - kc "k8s.io/client-go/tools/cache" ) func TestCache(t *testing.T) { t.Run("Add and update keys", func(t *testing.T) { g := NewWithT(t) // create a cache that can hold 2 items and have no cleanup - cache, err := New(3, kc.MetaNamespaceKeyFunc, - WithMetricsRegisterer[any](prometheus.NewPedanticRegistry()), - WithCleanupInterval[any](1*time.Second)) + cache, err := New[string](3, + WithMetricsRegisterer(prometheus.NewPedanticRegistry()), + WithCleanupInterval(1*time.Second)) g.Expect(err).ToNot(HaveOccurred()) - obj := &metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test", - }, - } - // Get an Item from the cache - _, found, err := cache.Get(obj) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeFalse()) + key1 := "key1" + value1 := "val1" + got, err := cache.Get(key1) + g.Expect(err).To(Equal(ErrNotFound)) + g.Expect(got).To(BeEmpty()) // Add an item to the cache - err = cache.Set(obj) + err = cache.Set(key1, value1) g.Expect(err).ToNot(HaveOccurred()) // Get the item from the cache - item, found, err := cache.Get(obj) + got, err = cache.Get(key1) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue()) - g.Expect(item).To(Equal(obj)) + g.Expect(got).To(Equal(value1)) + + // Writing to the obtained value doesn't update the cache. + got = "val2" + got2, err := cache.Get(key1) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(got2).To(Equal(value1)) - obj2 := &metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test2", - }, - } // Add another item to the cache - err = cache.Set(obj2) + key2 := "key2" + value2 := "val2" + err = cache.Set(key2, value2) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns/test", "test-ns/test2")) + g.Expect(cache.ListKeys()).To(ConsistOf(key1, key2)) // Get the item from the cache - item, found, err = cache.GetByKey("test-ns/test2") + got, err = cache.Get(key2) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue()) - g.Expect(item).To(Equal(obj2)) - - //Update an item in the cache - obj3 := &metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test3", - }, - } - err = cache.Set(obj3) + g.Expect(got).To(Equal(value2)) + + // Update an item in the cache + key3 := "key3" + value3 := "val3" + value4 := "val4" + err = cache.Set(key3, value3) g.Expect(err).ToNot(HaveOccurred()) // Replace an item in the cache - obj3.Labels = map[string]string{"pp.kubernetes.io/created-by: ": "flux"} - err = cache.Set(obj3) + err = cache.Set(key3, value4) g.Expect(err).ToNot(HaveOccurred()) // Get the item from the cache - item, found, err = cache.Get(obj3) + got, err = cache.Get(key3) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue()) - g.Expect(item).To(Equal(obj3)) + g.Expect(got).To(Equal(value4)) // cleanup the cache cache.Clear() @@ -124,183 +98,135 @@ func TestCache(t *testing.T) { t.Run("Add expiring keys", func(t *testing.T) { g := NewWithT(t) // new cache with a cleanup interval of 1 second - cache, err := New(2, IdentifiableObjectKeyFunc, - WithCleanupInterval[IdentifiableObject](1*time.Second), - WithMetricsRegisterer[IdentifiableObject](prometheus.NewPedanticRegistry())) + + cache, err := New[string](2, + WithCleanupInterval(1*time.Second), + WithMetricsRegisterer(prometheus.NewPedanticRegistry())) g.Expect(err).ToNot(HaveOccurred()) // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: struct { - token string - }{ - token: "test-token", - }, - } + key := "key1" + value := "val1" - err = cache.Set(obj) + err = cache.Set(key, value) g.Expect(err).ToNot(HaveOccurred()) // set expiration time to 2 seconds - err = cache.SetExpiration(obj, time.Now().Add(2*time.Second)) + err = cache.SetExpiration(key, time.Now().Add(2*time.Second)) g.Expect(err).ToNot(HaveOccurred()) // Get the item from the cache - item, found, err := cache.Get(obj) + item, err := cache.Get(key) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue()) - g.Expect(item).To(Equal(obj)) + g.Expect(item).To(Equal(value)) // wait for the item to expire time.Sleep(3 * time.Second) // Get the item from the cache - item, found, err = cache.Get(obj) + item, err = cache.Get(key) + g.Expect(err).To(Equal(ErrNotFound)) + g.Expect(item).To(BeEmpty()) + }) + + t.Run("Cache of integer value", func(t *testing.T) { + g := NewWithT(t) + + cache, err := New[int](3, WithMetricsRegisterer(prometheus.NewPedanticRegistry())) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeFalse()) - g.Expect(item.Object).To(BeNil()) + + key := "key1" + g.Expect(cache.Set(key, 4)).To(Succeed()) + + got, err := cache.Get(key) + g.Expect(err).To(Succeed()) + g.Expect(got).To(Equal(4)) }) } -func Test_Cache_Add(t *testing.T) { +func Test_Cache_Set(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := New[IdentifiableObject](1, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg), - WithCleanupInterval[IdentifiableObject](10*time.Millisecond)) + cache, err := New[string](1, + WithMetricsRegisterer(reg), + WithMetricsPrefix("gotk_"), + WithCleanupInterval(10*time.Millisecond)) g.Expect(err).ToNot(HaveOccurred()) // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - err = cache.Set(obj) + key1 := "key1" + value1 := "val1" + err = cache.Set(key1, value1) g.Expect(err).ToNot(HaveOccurred()) - err = cache.SetExpiration(obj, time.Now().Add(10*time.Millisecond)) + err = cache.SetExpiration(key1, time.Now().Add(10*time.Millisecond)) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test_test-group_TestObject")) + g.Expect(cache.ListKeys()).To(ConsistOf(key1)) // try adding the same object again, it should overwrite the existing one - err = cache.Set(obj) + err = cache.Set(key1, value1) g.Expect(err).ToNot(HaveOccurred()) // wait for the item to expire time.Sleep(20 * time.Millisecond) - ok, err := cache.HasExpired(obj) + ok, err := cache.HasExpired(key1) g.Expect(err).ToNot(HaveOccurred()) g.Expect(ok).To(BeTrue()) // add another object - obj.Name = "test2" - err = cache.Set(obj) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test2_test-group_TestObject")) - - // validate metrics - validateMetrics(reg, ` - # HELP gotk_cache_evictions_total Total number of cache evictions. - # TYPE gotk_cache_evictions_total counter - gotk_cache_evictions_total 1 - # HELP gotk_cache_requests_total Total number of cache requests partioned by success or failure. - # TYPE gotk_cache_requests_total counter - gotk_cache_requests_total{status="success"} 7 - # HELP gotk_cached_items Total number of items in the cache. - # TYPE gotk_cached_items gauge - gotk_cached_items 1 -`, t) -} - -func Test_Cache_Update(t *testing.T) { - g := NewWithT(t) - reg := prometheus.NewPedanticRegistry() - cache, err := New[IdentifiableObject](1, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg)) - g.Expect(err).ToNot(HaveOccurred()) - - // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - err = cache.Set(obj) + key2 := "key2" + value2 := "val2" + err = cache.Set(key2, value2) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test_test-group_TestObject")) + g.Expect(cache.ListKeys()).To(ConsistOf(key2)) - obj.Object = "test-token2" - err = cache.Set(obj) + // Update the value of existing item. + value3 := "val3" + err = cache.Set(key2, value3) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test_test-group_TestObject")) - g.Expect(cache.index["test-ns_test_test-group_TestObject"].object.Object).To(Equal("test-token2")) + g.Expect(cache.ListKeys()).To(ConsistOf(key2)) + g.Expect(cache.index[key2].value).To(Equal(value3)) // validate metrics validateMetrics(reg, ` # HELP gotk_cache_evictions_total Total number of cache evictions. # TYPE gotk_cache_evictions_total counter - gotk_cache_evictions_total 0 + gotk_cache_evictions_total 1 # HELP gotk_cache_requests_total Total number of cache requests partioned by success or failure. # TYPE gotk_cache_requests_total counter - gotk_cache_requests_total{status="success"} 4 + gotk_cache_requests_total{status="success"} 9 # HELP gotk_cached_items Total number of items in the cache. # TYPE gotk_cached_items gauge gotk_cached_items 1 - `, t) +`, t) } func Test_Cache_Get(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := New[IdentifiableObject](5, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg), - WithMetricsLabels[IdentifiableObject](IdentifiableObjectLabels, IdentifiableObjectLVSFunc)) + cache, err := New[string](5, WithMetricsRegisterer(reg), WithMetricsPrefix("gotk_")) g.Expect(err).ToNot(HaveOccurred()) + // Reconciling object label values for cache event metric. + recObjKind := "TestObject" + recObjName := "test" + recObjNamespace := "test-ns" + // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } + key := "key1" + value := "val1" - _, found, err := cache.Get(obj) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeFalse()) + got, err := cache.Get(key) + g.Expect(err).To(Equal(ErrNotFound)) + g.Expect(got).To(BeEmpty()) + cache.RecordCacheEvent(CacheEventTypeMiss, recObjKind, recObjName, recObjNamespace) - err = cache.Set(obj) + err = cache.Set(key, value) g.Expect(err).ToNot(HaveOccurred()) - item, found, err := cache.Get(obj) + got, err = cache.Get(key) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue()) - g.Expect(item).To(Equal(obj)) + g.Expect(got).To(Equal(value)) + cache.RecordCacheEvent(CacheEventTypeHit, recObjKind, recObjName, recObjNamespace) validateMetrics(reg, ` # HELP gotk_cache_events_total Total number of cache retrieval events for a Gitops Toolkit resource reconciliation. @@ -317,34 +243,42 @@ func Test_Cache_Get(t *testing.T) { # TYPE gotk_cached_items gauge gotk_cached_items 1 `, t) + + cache.DeleteCacheEvent(CacheEventTypeHit, recObjKind, recObjName, recObjNamespace) + cache.DeleteCacheEvent(CacheEventTypeMiss, recObjKind, recObjName, recObjNamespace) + + validateMetrics(reg, ` + # HELP gotk_cache_evictions_total Total number of cache evictions. + # TYPE gotk_cache_evictions_total counter + gotk_cache_evictions_total 0 + # HELP gotk_cache_requests_total Total number of cache requests partioned by success or failure. + # TYPE gotk_cache_requests_total counter + gotk_cache_requests_total{status="success"} 3 + # HELP gotk_cached_items Total number of items in the cache. + # TYPE gotk_cached_items gauge + gotk_cached_items 1 +`, t) + } func Test_Cache_Delete(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := New[IdentifiableObject](5, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg), - WithCleanupInterval[IdentifiableObject](1*time.Millisecond)) + cache, err := New[string](5, + WithMetricsRegisterer(reg), + WithMetricsPrefix("gotk_"), + WithCleanupInterval(1*time.Millisecond)) g.Expect(err).ToNot(HaveOccurred()) // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } + key := "key1" + value := "value1" - err = cache.Set(obj) + err = cache.Set(key, value) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test_test-group_TestObject")) + g.Expect(cache.ListKeys()).To(ConsistOf(key)) - err = cache.Delete(obj) + err = cache.Delete(key) g.Expect(err).ToNot(HaveOccurred()) time.Sleep(5 * time.Millisecond) @@ -365,7 +299,8 @@ func Test_Cache_Delete(t *testing.T) { func Test_Cache_deleteExpired(t *testing.T) { type expiringItem struct { - object StoreObject[string] + key string + value string expiresAt time.Time expire bool } @@ -378,17 +313,13 @@ func Test_Cache_deleteExpired(t *testing.T) { name: "non expiring items", items: []expiringItem{ { - object: StoreObject[string]{ - Object: "test-token", - Key: "test", - }, + key: "test", + value: "test-token", expiresAt: time.Now().Add(noExpiration), }, { - object: StoreObject[string]{ - Object: "test-token2", - Key: "test2", - }, + key: "test2", + value: "test-token2", expiresAt: time.Now().Add(noExpiration), }, }, @@ -398,18 +329,14 @@ func Test_Cache_deleteExpired(t *testing.T) { name: "expiring items", items: []expiringItem{ { - object: StoreObject[string]{ - Object: "test-token", - Key: "test", - }, + key: "test", + value: "test-token", expiresAt: time.Now().Add(1 * time.Millisecond), expire: true, }, { - object: StoreObject[string]{ - Object: "test-token2", - Key: "test2", - }, + key: "test2", + value: "test-token2", expiresAt: time.Now().Add(1 * time.Millisecond), expire: true, }, @@ -420,25 +347,19 @@ func Test_Cache_deleteExpired(t *testing.T) { name: "mixed items", items: []expiringItem{ { - object: StoreObject[string]{ - Object: "test-token", - Key: "test", - }, + key: "test", + value: "test-token", expiresAt: time.Now().Add(1 * time.Millisecond), expire: true, }, { - object: StoreObject[string]{ - Object: "test-token2", - Key: "test2", - }, + key: "test2", + value: "test-token2", expiresAt: time.Now().Add(noExpiration), }, { - object: StoreObject[string]{ - Object: "test-token3", - Key: "test3", - }, + key: "test3", + value: "test-token3", expiresAt: time.Now().Add(1 * time.Minute), expire: true, }, @@ -451,16 +372,16 @@ func Test_Cache_deleteExpired(t *testing.T) { t.Run(tt.name, func(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := New[StoreObject[string]](5, StoreObjectKeyFunc, - WithMetricsRegisterer[StoreObject[string]](reg), - WithCleanupInterval[StoreObject[string]](1*time.Millisecond)) + cache, err := New[string](5, + WithMetricsRegisterer(reg), + WithCleanupInterval(1*time.Millisecond)) g.Expect(err).ToNot(HaveOccurred()) for _, item := range tt.items { - err := cache.Set(item.object) + err := cache.Set(item.key, item.value) g.Expect(err).ToNot(HaveOccurred()) if item.expire { - err = cache.SetExpiration(item.object, item.expiresAt) + err = cache.SetExpiration(item.key, item.expiresAt) g.Expect(err).ToNot(HaveOccurred()) } } @@ -477,26 +398,18 @@ func Test_Cache_Resize(t *testing.T) { n := 100 g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := New[IdentifiableObject](n, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg), - WithCleanupInterval[IdentifiableObject](10*time.Millisecond)) + + cache, err := New[string](n, + WithMetricsRegisterer(reg), + WithCleanupInterval(10*time.Millisecond)) g.Expect(err).ToNot(HaveOccurred()) for i := range n { - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: fmt.Sprintf("test-%d", i), - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - err = cache.Set(obj) + key := fmt.Sprintf("test-%d", i) + value := "test-token" + err = cache.Set(key, value) g.Expect(err).ToNot(HaveOccurred()) - err = cache.SetExpiration(obj, time.Now().Add(10*time.Minute)) + err = cache.SetExpiration(key, time.Now().Add(10*time.Minute)) g.Expect(err).ToNot(HaveOccurred()) } @@ -520,12 +433,16 @@ func TestCache_Concurrent(t *testing.T) { ) g := NewWithT(t) // create a cache that can hold 10 items and have no cleanup - cache, err := New(10, IdentifiableObjectKeyFunc, - WithCleanupInterval[IdentifiableObject](1*time.Second), - WithMetricsRegisterer[IdentifiableObject](prometheus.NewPedanticRegistry())) + cache, err := New[string](10, + WithCleanupInterval(1*time.Second), + WithMetricsRegisterer(prometheus.NewPedanticRegistry())) g.Expect(err).ToNot(HaveOccurred()) - objmap := createObjectMap(keysNum) + keymap := map[int]string{} + for i := 0; i < keysNum; i++ { + key := fmt.Sprintf("test-%d", i) + keymap[i] = key + } wg := sync.WaitGroup{} run := make(chan bool) @@ -536,13 +453,13 @@ func TestCache_Concurrent(t *testing.T) { wg.Add(2) go func() { defer wg.Done() - _ = cache.Set(objmap[key]) + _ = cache.Set(keymap[key], "test-token") }() go func() { defer wg.Done() <-run - _, _, _ = cache.Get(objmap[key]) - _ = cache.SetExpiration(objmap[key], time.Now().Add(noExpiration)) + _, _ = cache.Get(keymap[key]) + _ = cache.SetExpiration(keymap[key], time.Now().Add(noExpiration)) }() } close(run) @@ -550,35 +467,11 @@ func TestCache_Concurrent(t *testing.T) { keys, err := cache.ListKeys() g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(keys)).To(Equal(len(objmap))) + g.Expect(len(keys)).To(Equal(len(keymap))) - for _, obj := range objmap { - val, found, err := cache.Get(obj) + for _, key := range keymap { + val, err := cache.Get(key) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue(), "object %s not found", obj.Name) - g.Expect(val).To(Equal(obj)) - } -} - -func createObjectMap(num int) map[int]IdentifiableObject { - objMap := make(map[int]IdentifiableObject) - for i := 0; i < num; i++ { - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: fmt.Sprintf("test-%d", i), - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: struct { - token string - }{ - token: "test-token", - }, - } - objMap[i] = obj + g.Expect(val).To(Equal("test-token")) } - return objMap } diff --git a/cache/doc.go b/cache/doc.go new file mode 100644 index 00000000..f1456014 --- /dev/null +++ b/cache/doc.go @@ -0,0 +1,53 @@ +/* +Copyright 2024 The Flux authors + +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 cache provides a Store interface for a cache store, along with two +// implementations of this interface for expiring cache(Cache) and least +// recently used cache(LRU). Expirable defines an interface for cache with +// expiring items. This is also implemented by the expiring cache +// implementation, Cache. +// The Cache and LRU cache implementations are generic cache. The data type of +// the value stored in the cache has to be defined when creating the cache. For +// example, for storing string values in Cache create a string type Cache +// +// cache, err := New[string](10) +// +// The cache implementations are self-instrumenting and export metrics about the +// internal operations of the cache if it is configured with a metrics +// registerer. +// +// cache, err := New[string](10, WithMetricsRegisterer(reg)) +// +// For recording cache hit/miss metrics associated with a Flux object for which +// the cache is used, the caller must explicitly record the cache event based on +// the result of the operation along with the object in the context +// +// got, err := cache.Get("foo") +// // Handle any error. +// ... +// +// if err == ErrNotFound { +// cache.RecordCacheEvent(CacheEventTypeMiss, "GitRepository", "repoA", "testNS") +// } else { +// cache.RecordCacheEvent(CacheEventTypeHit, "GitRepository", "repoA", "testNS") +// } +// +// When the Flux object associated with the cache metrics is deleted, the +// metrics can be deleted as follows +// +// cache.DeleteCacheEvent(CacheEventTypeHit, "GitRepository", "repoA", "testNS") +// cache.DeleteCacheEvent(CacheEventTypeMiss, "GitRepository", "repoA", "testNS") +package cache diff --git a/cache/errors.go b/cache/errors.go index 2b69055b..b52af260 100644 --- a/cache/errors.go +++ b/cache/errors.go @@ -64,11 +64,8 @@ func (e *CacheError) Unwrap() error { } var ( - ErrNotFound = CacheErrorReason{"NotFound", "object not found"} - ErrAlreadyExists = CacheErrorReason{"AlreadyRxists", "object already exists"} - ErrCacheClosed = CacheErrorReason{"CacheClosed", "cache is closed"} - ErrCacheFull = CacheErrorReason{"CacheFull", "cache is full"} - ErrInvalidSize = CacheErrorReason{"InvalidSize", "invalid size"} - ErrInvalidKey = CacheErrorReason{"InvalidKey", "invalid key"} - ErrInvalidLabels = CacheErrorReason{"InvalidLabels", "invalid labels"} + ErrNotFound = CacheErrorReason{"NotFound", "object not found"} + ErrCacheClosed = CacheErrorReason{"CacheClosed", "cache is closed"} + ErrCacheFull = CacheErrorReason{"CacheFull", "cache is full"} + ErrInvalidSize = CacheErrorReason{"InvalidSize", "invalid size"} ) diff --git a/cache/go.mod b/cache/go.mod index 7870055e..e5aed37c 100644 --- a/cache/go.mod +++ b/cache/go.mod @@ -3,66 +3,24 @@ module github.com/fluxcd/pkg/cache go 1.22.7 require ( - github.com/fluxcd/cli-utils v0.36.0-flux.10 github.com/onsi/gomega v1.36.0 github.com/prometheus/client_golang v1.20.5 - k8s.io/apimachinery v0.31.3 - k8s.io/client-go v0.31.3 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-errors/errors v1.5.1 // indirect - github.com/go-logr/logr v1.4.2 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect + github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect - github.com/x448/float16 v0.8.4 // indirect - github.com/xlab/treeprint v1.2.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect golang.org/x/net v0.31.0 // indirect - golang.org/x/oauth2 v0.24.0 // indirect - golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.26.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/time v0.8.0 // indirect google.golang.org/protobuf v1.35.1 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.31.3 // indirect - k8s.io/cli-runtime v0.31.3 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.18.0 // indirect - sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/cache/go.sum b/cache/go.sum index ccc5765b..592688e3 100644 --- a/cache/go.sum +++ b/cache/go.sum @@ -1,118 +1,30 @@ -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= -github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fluxcd/cli-utils v0.36.0-flux.10 h1:kgoj1HP7KBFfIG9CHLFHpA2kCPNlfzCpbscCaAOSClE= -github.com/fluxcd/cli-utils v0.36.0-flux.10/go.mod h1:eWf+UVZmm51EmNmeGkdplVLVsFU4jETfCjoHZq7nUp4= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= -github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= -github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA= +github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= -github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo= +github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI= github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= @@ -123,115 +35,18 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= -github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= -golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= -k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= -k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= -k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/cli-runtime v0.31.3 h1:fEQD9Xokir78y7pVK/fCJN090/iYNrLHpFbGU4ul9TI= -k8s.io/cli-runtime v0.31.3/go.mod h1:Q2jkyTpl+f6AtodQvgDI8io3jrfr+Z0LyQBPJJ2Btq8= -k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= -k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= -k8s.io/component-base v0.31.3 h1:DMCXXVx546Rfvhj+3cOm2EUxhS+EyztH423j+8sOwhQ= -k8s.io/component-base v0.31.3/go.mod h1:xME6BHfUOafRgT0rGVBGl7TuSg8Z9/deT7qq6w7qjIU= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/kubectl v0.31.3 h1:3r111pCjPsvnR98oLLxDMwAeM6OPGmPty6gSKaLTQes= -k8s.io/kubectl v0.31.3/go.mod h1:lhMECDCbJN8He12qcKqs2QfmVo9Pue30geovBVpH5fs= -k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno= -k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= -sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= -sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= -sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/cache/lru.go b/cache/lru.go index 4f2337b1..61fc5801 100644 --- a/cache/lru.go +++ b/cache/lru.go @@ -24,10 +24,10 @@ import ( // node is a node in a doubly linked list // that is used to implement an LRU cache type node[T any] struct { - object T - key string - prev *node[T] - next *node[T] + value T + key string + prev *node[T] + next *node[T] } func (n *node[T]) addNext(node *node[T]) { @@ -38,7 +38,7 @@ func (n *node[T]) addPrev(node *node[T]) { n.prev = node } -// LRU is a thread-safe in-memory key/object store. +// LRU is a thread-safe in-memory key/value store. // All methods are safe for concurrent use. // All operations are O(1). The hash map lookup is O(1) and so is the doubly // linked list insertion/deletion. @@ -62,25 +62,20 @@ func (n *node[T]) addPrev(node *node[T]) { // │ │ // └───────────────────────────────────────────────────┘ // -// A function to extract the key from the object must be provided. // Use the NewLRU function to create a new cache that is ready to use. type LRU[T any] struct { cache map[string]*node[T] capacity int - // keyFunc is used to make the key for objects stored in and retrieved from items, and - // should be deterministic. - keyFunc KeyFunc[T] - metrics *cacheMetrics - labelsFunc GetLvsFunc[T] - head *node[T] - tail *node[T] - mu sync.RWMutex + metrics *cacheMetrics + head *node[T] + tail *node[T] + mu sync.RWMutex } var _ Store[any] = &LRU[any]{} -// NewLRU creates a new LRU cache with the given capacity and keyFunc. -func NewLRU[T any](capacity int, keyFunc KeyFunc[T], opts ...Options[T]) (*LRU[T], error) { +// NewLRU creates a new LRU cache with the given capacity. +func NewLRU[T any](capacity int, opts ...Options) (*LRU[T], error) { opt, err := makeOptions(opts...) if err != nil { return nil, fmt.Errorf("failed to apply options: %w", err) @@ -92,41 +87,33 @@ func NewLRU[T any](capacity int, keyFunc KeyFunc[T], opts ...Options[T]) (*LRU[T tail.addPrev(head) lru := &LRU[T]{ - cache: make(map[string]*node[T]), - keyFunc: keyFunc, - labelsFunc: opt.labelsFunc, - capacity: capacity, - head: head, - tail: tail, + cache: make(map[string]*node[T]), + capacity: capacity, + head: head, + tail: tail, } if opt.registerer != nil { - lru.metrics = newCacheMetrics(opt.registerer, opt.extraLabels...) + lru.metrics = newCacheMetrics(opt.metricsPrefix, opt.registerer) } return lru, nil } // Set an item in the cache, existing index will be overwritten. -func (c *LRU[T]) Set(object T) error { - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return &CacheError{Reason: ErrInvalidKey, Err: err} - } - +func (c *LRU[T]) Set(key string, value T) error { // if node is already in cache, return error c.mu.Lock() newNode, ok := c.cache[key] if ok { c.delete(newNode) - _ = c.add(&node[T]{key: key, object: object}) + _ = c.add(&node[T]{key: key, value: value}) c.mu.Unlock() recordRequest(c.metrics, StatusSuccess) return nil } - evicted := c.add(&node[T]{key: key, object: object}) + evicted := c.add(&node[T]{key: key, value: value}) c.mu.Unlock() recordRequest(c.metrics, StatusSuccess) if evicted { @@ -154,13 +141,7 @@ func (c *LRU[T]) add(node *node[T]) (evicted bool) { } // Delete removes a node from the list -func (c *LRU[T]) Delete(object T) error { - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return &CacheError{Reason: ErrInvalidKey, Err: err} - } - +func (c *LRU[T]) Delete(key string) error { // if node is head or tail, do nothing if key == c.head.key || key == c.tail.key { recordRequest(c.metrics, StatusSuccess) @@ -189,66 +170,24 @@ func (c *LRU[T]) delete(node *node[T]) { delete(c.cache, node.key) } -// Get returns the given object from the cache. -// If the object is not in the cache, it returns false. -func (c *LRU[T]) Get(object T) (item T, exists bool, err error) { - var res T - lvs := []string{} - if c.labelsFunc != nil { - lvs, err = c.labelsFunc(object, len(c.metrics.getExtraLabels())) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return res, false, &CacheError{Reason: ErrInvalidLabels, Err: err} - } - } - key, err := c.keyFunc(object) - if err != nil { - recordRequest(c.metrics, StatusFailure) - return item, false, &CacheError{Reason: ErrInvalidKey, Err: err} - } - - item, exists, err = c.get(key) - if err != nil { - return res, false, ErrInvalidKey - } - if !exists { - recordEvent(c.metrics, CacheEventTypeMiss, lvs...) - return res, false, nil - } - recordEvent(c.metrics, CacheEventTypeHit, lvs...) - return item, true, nil -} - -// GetByKey returns the object for the given key. -func (c *LRU[T]) GetByKey(key string) (T, bool, error) { - var res T - item, found, err := c.get(key) - if err != nil { - return res, false, err - } - if !found { - recordEvent(c.metrics, CacheEventTypeMiss) - return res, false, nil - } - - recordEvent(c.metrics, CacheEventTypeHit) - return item, true, nil -} - -func (c *LRU[T]) get(key string) (item T, exists bool, err error) { +// Get returns an item in the cache for the given key. If no item is found, an +// error is returned. +// The caller can record cache hit or miss based on the result with +// LRU.RecordCacheEvent(). +func (c *LRU[T]) Get(key string) (T, error) { var res T c.mu.Lock() node, ok := c.cache[key] if !ok { c.mu.Unlock() recordRequest(c.metrics, StatusSuccess) - return res, false, nil + return res, ErrNotFound } c.delete(node) _ = c.add(node) c.mu.Unlock() recordRequest(c.metrics, StatusSuccess) - return node.object, true, nil + return node.value, nil } // ListKeys returns a list of keys in the cache. @@ -288,3 +227,15 @@ func (c *LRU[T]) Resize(size int) (int, error) { recordRequest(c.metrics, StatusSuccess) return overflow, nil } + +// RecordCacheEvent records a cache event (cache_miss or cache_hit) with kind, +// name and namespace of the associated object being reconciled. +func (c *LRU[T]) RecordCacheEvent(event, kind, name, namespace string) { + recordCacheEvent(c.metrics, event, kind, name, namespace) +} + +// DeleteCacheEvent deletes the cache event (cache_miss or cache_hit) metric for +// the associated object being reconciled, given their kind, name and namespace. +func (c *LRU[T]) DeleteCacheEvent(event, kind, name, namespace string) { + deleteCacheEvent(c.metrics, event, kind, name, namespace) +} diff --git a/cache/lru_test.go b/cache/lru_test.go index e484171e..645f0fac 100644 --- a/cache/lru_test.go +++ b/cache/lru_test.go @@ -22,195 +22,57 @@ import ( "sync" "testing" - "github.com/fluxcd/cli-utils/pkg/object" . "github.com/onsi/gomega" "github.com/prometheus/client_golang/prometheus" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" - kc "k8s.io/client-go/tools/cache" ) func Test_LRU(t *testing.T) { + type keyVal struct { + key string + value string + } testCases := []struct { name string - inputs []*metav1.PartialObjectMetadata - expectedCache map[string]*node[metav1.PartialObjectMetadata] + inputs []keyVal + expectedCache map[string]*node[string] }{ { name: "empty cache", - inputs: []*metav1.PartialObjectMetadata{}, - expectedCache: map[string]*node[metav1.PartialObjectMetadata]{}, + inputs: []keyVal{}, + expectedCache: map[string]*node[string]{}, }, { name: "add one node", - inputs: []*metav1.PartialObjectMetadata{ + inputs: []keyVal{ { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test", - }, + key: "test", + value: "test-token", }, }, - expectedCache: map[string]*node[metav1.PartialObjectMetadata]{ - "test-ns/test": { - object: metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test", - }, - }, - key: "test-ns/test", + expectedCache: map[string]*node[string]{ + "test": { + key: "test", + value: "test-token", }, }, }, { name: "add seven nodes", - inputs: []*metav1.PartialObjectMetadata{ - { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test", - }, - }, - { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test2", - }, - }, - { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test3", - }, - }, - { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test4", - }, - }, - { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test5", - }, - }, - { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test6", - }, - }, - { - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test7", - }, - }, + inputs: []keyVal{ + {key: "test", value: "test-token"}, + {key: "test2", value: "test-token"}, + {key: "test3", value: "test-token"}, + {key: "test4", value: "test-token"}, + {key: "test5", value: "test-token"}, + {key: "test6", value: "test-token"}, + {key: "test7", value: "test-token"}, }, - expectedCache: map[string]*node[metav1.PartialObjectMetadata]{ - "test-ns/test3": { - object: metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test3", - }, - }, - key: "test-ns/test3", - }, - "test-ns/test4": { - object: metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test4", - }, - }, - key: "test-ns/test4", - }, - "test-ns/test5": { - object: metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test5", - }, - }, - key: "test-ns/test5", - }, - "test-ns/test6": { - object: metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test6", - }, - }, - key: "test-ns/test6", - }, - "test-ns/test7": { - object: metav1.PartialObjectMetadata{ - TypeMeta: metav1.TypeMeta{ - Kind: "TestObject", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Namespace: "test-ns", - Name: "test7", - }, - }, - key: "test-ns/test7", - }, + expectedCache: map[string]*node[string]{ + "test3": {key: "test3", value: "test-token"}, + "test4": {key: "test4", value: "test-token"}, + "test5": {key: "test5", value: "test-token"}, + "test6": {key: "test6", value: "test-token"}, + "test7": {key: "test7", value: "test-token"}, }, }, } @@ -218,11 +80,11 @@ func Test_LRU(t *testing.T) { for _, v := range testCases { t.Run(v.name, func(t *testing.T) { g := NewWithT(t) - cache, err := NewLRU(5, kc.MetaNamespaceKeyFunc, - WithMetricsRegisterer[any](prometheus.NewPedanticRegistry())) + cache, err := NewLRU[string](5, + WithMetricsRegisterer(prometheus.NewPedanticRegistry())) g.Expect(err).ToNot(HaveOccurred()) for _, input := range v.inputs { - err := cache.Set(input) + err := cache.Set(input.key, input.value) g.Expect(err).ToNot(HaveOccurred()) } @@ -237,38 +99,38 @@ func Test_LRU(t *testing.T) { } } -func Test_LRU_Add(t *testing.T) { +func Test_LRU_Set(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := NewLRU[IdentifiableObject](1, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg)) + cache, err := NewLRU[string](1, + WithMetricsRegisterer(reg), + WithMetricsPrefix("gotk_")) g.Expect(err).ToNot(HaveOccurred()) // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - err = cache.Set(obj) + key1 := "key1" + value1 := "val1" + err = cache.Set(key1, value1) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test_test-group_TestObject")) + g.Expect(cache.ListKeys()).To(ConsistOf(key1)) // try adding the same object again, it should overwrite the existing one - err = cache.Set(obj) + err = cache.Set(key1, value1) g.Expect(err).ToNot(HaveOccurred()) // add another object - obj.Name = "test2" - err = cache.Set(obj) + key2 := "key2" + value2 := "val2" + err = cache.Set(key2, value2) + g.Expect(err).ToNot(HaveOccurred()) + g.Expect(cache.ListKeys()).To(ConsistOf(key2)) + + // Update the value of existing item. + value3 := "val3" + err = cache.Set(key2, value3) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test2_test-group_TestObject")) + g.Expect(cache.ListKeys()).To(ConsistOf(key2)) + g.Expect(cache.cache[key2].value).To(Equal(value3)) // validate metrics validateMetrics(reg, ` @@ -277,88 +139,41 @@ func Test_LRU_Add(t *testing.T) { gotk_cache_evictions_total 1 # HELP gotk_cache_requests_total Total number of cache requests partioned by success or failure. # TYPE gotk_cache_requests_total counter - gotk_cache_requests_total{status="success"} 5 + gotk_cache_requests_total{status="success"} 7 # HELP gotk_cached_items Total number of items in the cache. # TYPE gotk_cached_items gauge gotk_cached_items 1 `, t) } -func Test_LRU_Update(t *testing.T) { - g := NewWithT(t) - reg := prometheus.NewPedanticRegistry() - cache, err := NewLRU[IdentifiableObject](1, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg)) - g.Expect(err).ToNot(HaveOccurred()) - - // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - err = cache.Set(obj) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test_test-group_TestObject")) - - obj.Object = "test-token2" - err = cache.Set(obj) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(cache.ListKeys()).To(ConsistOf("test-ns_test_test-group_TestObject")) - g.Expect(cache.cache["test-ns_test_test-group_TestObject"].object.Object).To(Equal("test-token2")) - - // validate metrics - validateMetrics(reg, ` - # HELP gotk_cache_evictions_total Total number of cache evictions. - # TYPE gotk_cache_evictions_total counter - gotk_cache_evictions_total 0 - # HELP gotk_cache_requests_total Total number of cache requests partioned by success or failure. - # TYPE gotk_cache_requests_total counter - gotk_cache_requests_total{status="success"} 4 - # HELP gotk_cached_items Total number of items in the cache. - # TYPE gotk_cached_items gauge - gotk_cached_items 1 - `, t) -} - func Test_LRU_Get(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := NewLRU[IdentifiableObject](5, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg), - WithMetricsLabels[IdentifiableObject](IdentifiableObjectLabels, IdentifiableObjectLVSFunc)) + cache, err := NewLRU[string](5, + WithMetricsRegisterer(reg), + WithMetricsPrefix("gotk_")) g.Expect(err).ToNot(HaveOccurred()) - // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - - _, found, err := cache.Get(obj) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeFalse()) + // Reconciling object label values for cache event metric. + recObjKind := "TestObject" + recObjName := "test" + recObjNamespace := "test-ns" - err = cache.Set(obj) + // Add an object representing an expiring token + key1 := "key1" + value1 := "val1" + got, err := cache.Get(key1) + g.Expect(err).To(Equal(ErrNotFound)) + g.Expect(got).To(BeEmpty()) + cache.RecordCacheEvent(CacheEventTypeMiss, recObjKind, recObjName, recObjNamespace) + + err = cache.Set(key1, value1) g.Expect(err).ToNot(HaveOccurred()) - item, found, err := cache.Get(obj) + got, err = cache.Get(key1) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue()) - g.Expect(item).To(Equal(obj)) + g.Expect(got).To(Equal(value1)) + cache.RecordCacheEvent(CacheEventTypeHit, recObjKind, recObjName, recObjNamespace) validateMetrics(reg, ` # HELP gotk_cache_events_total Total number of cache retrieval events for a Gitops Toolkit resource reconciliation. @@ -375,32 +190,38 @@ func Test_LRU_Get(t *testing.T) { # TYPE gotk_cached_items gauge gotk_cached_items 1 `, t) + + cache.DeleteCacheEvent(CacheEventTypeHit, recObjKind, recObjName, recObjNamespace) + cache.DeleteCacheEvent(CacheEventTypeMiss, recObjKind, recObjName, recObjNamespace) + + validateMetrics(reg, ` + # HELP gotk_cache_evictions_total Total number of cache evictions. + # TYPE gotk_cache_evictions_total counter + gotk_cache_evictions_total 0 + # HELP gotk_cache_requests_total Total number of cache requests partioned by success or failure. + # TYPE gotk_cache_requests_total counter + gotk_cache_requests_total{status="success"} 3 + # HELP gotk_cached_items Total number of items in the cache. + # TYPE gotk_cached_items gauge + gotk_cached_items 1 +`, t) } func Test_LRU_Delete(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := NewLRU[IdentifiableObject](5, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg)) + cache, err := NewLRU[string](5, + WithMetricsRegisterer(reg), + WithMetricsPrefix("gotk_")) g.Expect(err).ToNot(HaveOccurred()) // Add an object representing an expiring token - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: "test", - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - - err = cache.Set(obj) + key := "key1" + value := "val1" + err = cache.Set(key, value) g.Expect(err).ToNot(HaveOccurred()) - err = cache.Delete(obj) + err = cache.Delete(key) g.Expect(err).ToNot(HaveOccurred()) g.Expect(cache.ListKeys()).To(BeEmpty()) @@ -421,23 +242,13 @@ func Test_LRU_Resize(t *testing.T) { n := 100 g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - cache, err := NewLRU[IdentifiableObject](n, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](reg)) + cache, err := NewLRU[string](n, + WithMetricsRegisterer(reg)) g.Expect(err).ToNot(HaveOccurred()) for i := range n { - obj := IdentifiableObject{ - ObjMetadata: object.ObjMetadata{ - Namespace: "test-ns", - Name: fmt.Sprintf("test-%d", i), - GroupKind: schema.GroupKind{ - Group: "test-group", - Kind: "TestObject", - }, - }, - Object: "test-token", - } - err = cache.Set(obj) + key := fmt.Sprintf("test-%d", i) + err = cache.Set(key, "test-token") g.Expect(err).ToNot(HaveOccurred()) } @@ -461,11 +272,15 @@ func TestLRU_Concurrent(t *testing.T) { ) g := NewWithT(t) // create a cache that can hold 10 items and have no cleanup - cache, err := NewLRU(10, IdentifiableObjectKeyFunc, - WithMetricsRegisterer[IdentifiableObject](prometheus.NewPedanticRegistry())) + cache, err := NewLRU[string](10, + WithMetricsRegisterer(prometheus.NewPedanticRegistry())) g.Expect(err).ToNot(HaveOccurred()) - objmap := createObjectMap(keysNum) + keymap := map[int]string{} + for i := 0; i < keysNum; i++ { + key := fmt.Sprintf("test-%d", i) + keymap[i] = key + } wg := sync.WaitGroup{} run := make(chan bool) @@ -476,12 +291,12 @@ func TestLRU_Concurrent(t *testing.T) { wg.Add(2) go func() { defer wg.Done() - _ = cache.Set(objmap[key]) + _ = cache.Set(keymap[key], "test-token") }() go func() { defer wg.Done() <-run - _, _, _ = cache.Get(objmap[key]) + _, _ = cache.Get(keymap[key]) }() } close(run) @@ -489,12 +304,25 @@ func TestLRU_Concurrent(t *testing.T) { keys, err := cache.ListKeys() g.Expect(err).ToNot(HaveOccurred()) - g.Expect(len(keys)).To(Equal(len(objmap))) + g.Expect(len(keys)).To(Equal(len(keymap))) - for _, obj := range objmap { - val, found, err := cache.Get(obj) + for _, key := range keymap { + val, err := cache.Get(key) g.Expect(err).ToNot(HaveOccurred()) - g.Expect(found).To(BeTrue(), "object %s not found", obj.Name) - g.Expect(val).To(Equal(obj)) + g.Expect(val).To(Equal("test-token")) } } + +func TestLRU_int(t *testing.T) { + g := NewWithT(t) + + cache, err := NewLRU[int](3, WithMetricsRegisterer(prometheus.NewPedanticRegistry())) + g.Expect(err).ToNot(HaveOccurred()) + + key := "key1" + g.Expect(cache.Set(key, 4)).To(Succeed()) + + got, err := cache.Get(key) + g.Expect(err).To(Succeed()) + g.Expect(got).To(Equal(4)) +} diff --git a/cache/metrics.go b/cache/metrics.go index c6dd29ea..6ea0cfe1 100644 --- a/cache/metrics.go +++ b/cache/metrics.go @@ -40,47 +40,41 @@ type cacheMetrics struct { cacheItemsGauge prometheus.Gauge cacheRequestsCounter *prometheus.CounterVec cacheEvictionCounter prometheus.Counter - extraLabels []string } // newcacheMetrics returns a new cacheMetrics. -func newCacheMetrics(reg prometheus.Registerer, extraLabels ...string) *cacheMetrics { - labels := append([]string{"event_type"}, extraLabels...) +func newCacheMetrics(prefix string, reg prometheus.Registerer) *cacheMetrics { + labels := []string{"event_type", "kind", "name", "namespace"} return &cacheMetrics{ cacheEventsCounter: promauto.With(reg).NewCounterVec( prometheus.CounterOpts{ - Name: "gotk_cache_events_total", + Name: fmt.Sprintf("%scache_events_total", prefix), Help: "Total number of cache retrieval events for a Gitops Toolkit resource reconciliation.", }, labels, ), cacheItemsGauge: promauto.With(reg).NewGauge( prometheus.GaugeOpts{ - Name: "gotk_cached_items", + Name: fmt.Sprintf("%scached_items", prefix), Help: "Total number of items in the cache.", }, ), cacheRequestsCounter: promauto.With(reg).NewCounterVec( prometheus.CounterOpts{ - Name: "gotk_cache_requests_total", + Name: fmt.Sprintf("%scache_requests_total", prefix), Help: "Total number of cache requests partioned by success or failure.", }, []string{"status"}, ), cacheEvictionCounter: promauto.With(reg).NewCounter( prometheus.CounterOpts{ - Name: "gotk_cache_evictions_total", + Name: fmt.Sprintf("%scache_evictions_total", prefix), Help: "Total number of cache evictions.", }, ), - extraLabels: extraLabels, } } -func (m *cacheMetrics) getExtraLabels() []string { - return m.extraLabels -} - // collectors returns the metrics.Collector objects for the cacheMetrics. func (m *cacheMetrics) collectors() []prometheus.Collector { return []prometheus.Collector{ @@ -151,34 +145,20 @@ func recordDecrement(metrics *cacheMetrics) { } } -func recordEvent(metrics *cacheMetrics, event string, lvs ...string) { +func recordItemIncrement(metrics *cacheMetrics) { if metrics != nil { - metrics.incCacheEvents(event, lvs...) + metrics.incCacheItems() } } -func recordItemIncrement(metrics *cacheMetrics) { +func recordCacheEvent(metrics *cacheMetrics, event, kind, name, namespace string) { if metrics != nil { - metrics.incCacheItems() + metrics.incCacheEvents(event, kind, name, namespace) } } -// IdentifiableObjectLabels are the labels for an IdentifiableObject. -var IdentifiableObjectLabels []string = []string{"name", "namespace", "kind"} - -// GetLvsFunc is a function that returns the label's values for a metric. -type GetLvsFunc[T any] func(obj T, cardinality int) ([]string, error) - -// IdentifiableObjectLVSFunc returns the label's values for a metric for an IdentifiableObject. -func IdentifiableObjectLVSFunc[T any](object T, cardinality int) ([]string, error) { - n, ok := any(object).(IdentifiableObject) - if !ok { - return nil, fmt.Errorf("object is not an IdentifiableObject") - } - lvs := []string{n.Name, n.Namespace, n.GroupKind.Kind} - if len(lvs) != cardinality { - return nil, fmt.Errorf("expected cardinality %d, got %d", cardinality, len(lvs)) +func deleteCacheEvent(metrics *cacheMetrics, event, kind, name, namespace string) { + if metrics != nil { + metrics.deleteCacheEvent(event, kind, name, namespace) } - - return []string{n.Name, n.Namespace, n.GroupKind.Kind}, nil } diff --git a/cache/metrics_test.go b/cache/metrics_test.go index 5a2d90b8..76a4a5ba 100644 --- a/cache/metrics_test.go +++ b/cache/metrics_test.go @@ -28,12 +28,12 @@ import ( func TestCacheMetrics(t *testing.T) { g := NewWithT(t) reg := prometheus.NewPedanticRegistry() - m := newCacheMetrics(reg, IdentifiableObjectLabels...) + m := newCacheMetrics("gotk_", reg) g.Expect(m).ToNot(BeNil()) // CounterVec is a collection of counters and is not exported until it has counters in it. - m.incCacheEvents(CacheEventTypeHit, []string{"test", "test-ns", "TestObject"}...) - m.incCacheEvents(CacheEventTypeMiss, []string{"test", "test-ns", "TestObject"}...) + m.incCacheEvents(CacheEventTypeHit, []string{"TestObject", "test", "test-ns"}...) + m.incCacheEvents(CacheEventTypeMiss, []string{"TestObject", "test", "test-ns"}...) m.incCacheRequests("success") m.incCacheRequests("failure") diff --git a/cache/store.go b/cache/store.go index ba80e232..a5207bf9 100644 --- a/cache/store.go +++ b/cache/store.go @@ -17,122 +17,61 @@ limitations under the License. package cache import ( - "fmt" "time" - "github.com/fluxcd/cli-utils/pkg/object" "github.com/prometheus/client_golang/prometheus" ) // Store is an interface for a cache store. -// It is a generic version of the Kubernetes client-go cache.Store interface. -// See https://pkg.go.dev/k8s.io/client-go/tools/cache#Store -// The implementation should know how to extract a key from an object. type Store[T any] interface { - // Set adds an object to the store. - // It will overwrite the item if it already exists. - Set(object T) error - // Delete deletes an object from the store. - Delete(object T) error - // ListKeys returns a list of keys in the store. - ListKeys() ([]string, error) - // Get returns the object stored in the store. - Get(object T) (item T, exists bool, err error) - // GetByKey returns the object stored in the store by key. - GetByKey(key string) (item T, exists bool, err error) - // Resize resizes the store and returns the number of items removed. - Resize(int) (int, error) + // Set adds an item to the store for the given key. + Set(key string, value T) error + // Get returns an item stored in the store for the given key. + Get(key string) (T, error) + // Delete deletes an item in the store for the given key. + Delete(key string) error } // Expirable is an interface for a cache store that supports expiration. type Expirable[T any] interface { Store[T] - // SetExpiration sets the expiration time for the object. - SetExpiration(object T, expiresAt time.Time) error - // GetExpiration returns the expiration time for the object in unix time. - GetExpiration(object T) (time.Time, error) - // HasExpired returns true if the object has expired. - HasExpired(object T) (bool, error) + // SetExpiration sets the expiration time for a cached item. + SetExpiration(key string, expiresAt time.Time) error + // GetExpiration returns the expiration time of an item. + GetExpiration(key string) (time.Time, error) + // HasExpired returns if an item has expired. + HasExpired(key string) (bool, error) } -type storeOptions[T any] struct { - interval time.Duration - registerer prometheus.Registerer - extraLabels []string - labelsFunc GetLvsFunc[T] +type storeOptions struct { + interval time.Duration + registerer prometheus.Registerer + metricsPrefix string } // Options is a function that sets the store options. -type Options[T any] func(*storeOptions[T]) error - -// WithMetricsLabels sets the extra labels for the cache metrics. -func WithMetricsLabels[T any](labels []string, f GetLvsFunc[T]) Options[T] { - return func(o *storeOptions[T]) error { - if labels != nil && f == nil { - return fmt.Errorf("labelsFunc must be set if labels are provided") - } - o.extraLabels = labels - o.labelsFunc = f - return nil - } -} +type Options func(*storeOptions) error // WithCleanupInterval sets the interval for the cache cleanup. -func WithCleanupInterval[T any](interval time.Duration) Options[T] { - return func(o *storeOptions[T]) error { +func WithCleanupInterval(interval time.Duration) Options { + return func(o *storeOptions) error { o.interval = interval return nil } } // WithMetricsRegisterer sets the Prometheus registerer for the cache metrics. -func WithMetricsRegisterer[T any](r prometheus.Registerer) Options[T] { - return func(o *storeOptions[T]) error { +func WithMetricsRegisterer(r prometheus.Registerer) Options { + return func(o *storeOptions) error { o.registerer = r return nil } } -// KeyFunc knows how to make a key from an object. Implementations should be deterministic. -type KeyFunc[T any] func(object T) (string, error) - -// IdentifiableObject is a wrapper for an object with its identifying metadata. -type IdentifiableObject struct { - object.ObjMetadata - // Object is the object that is being stored. - Object any -} - -// ExplicitKey can be passed to IdentifiableObjectKeyFunc if you have the key for -// the objectec but not the object itself. -type ExplicitKey string - -// IdentifiableObjectKeyFunc is a convenient default KeyFunc which knows how to make -// keys from IdentifiableObject objects. -func IdentifiableObjectKeyFunc[T any](object T) (string, error) { - if key, ok := any(object).(ExplicitKey); ok { - return string(key), nil - } - n, ok := any(object).(IdentifiableObject) - if !ok { - return "", fmt.Errorf("object has no meta: %v", object) +// WithMetricsPrefix sets the metrics prefix for the cache metrics. +func WithMetricsPrefix(prefix string) Options { + return func(o *storeOptions) error { + o.metricsPrefix = prefix + return nil } - return n.String(), nil -} - -// StoreObject is a wrapper for an object with its identifying key. -// It is used to store objects in a Store. -// This helper is useful when the object does not have metadata to extract the key from. -// The supplied key can be retrieved with the StoreObjectKeyFunc. -// When the object has metadata, use IdentifiableObject instead if possible. -type StoreObject[T any] struct { - // Object is the object that is being stored. - Object T - // Key is the key for the object. - Key string -} - -// StoreObjectKeyFunc returns the key for a StoreObject. -func StoreObjectKeyFunc[T any](object StoreObject[T]) (string, error) { - return object.Key, nil } diff --git a/oci/auth/login/cache.go b/oci/auth/login/cache.go deleted file mode 100644 index 13180ff6..00000000 --- a/oci/auth/login/cache.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2024 The Flux authors - -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 login - -import ( - "time" - - "github.com/google/go-containerregistry/pkg/authn" - - "github.com/fluxcd/pkg/cache" -) - -func cacheObject[T authn.Authenticator](store cache.Expirable[cache.StoreObject[T]], auth T, key string, expiresAt time.Time) error { - obj := cache.StoreObject[T]{ - Object: auth, - Key: key, - } - - err := store.Set(obj) - if err != nil { - return err - } - - return store.SetExpiration(obj, expiresAt) -} - -func getObjectFromCache[T authn.Authenticator](cache cache.Expirable[cache.StoreObject[T]], key string) (T, bool, error) { - val, exists, err := cache.GetByKey(key) - return val.Object, exists, err -} diff --git a/oci/auth/login/login.go b/oci/auth/login/login.go index 9ffaef94..60f31968 100644 --- a/oci/auth/login/login.go +++ b/oci/auth/login/login.go @@ -21,12 +21,12 @@ import ( "fmt" "net/url" "strings" + "time" "github.com/go-logr/logr" "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/name" - "github.com/fluxcd/pkg/cache" "github.com/fluxcd/pkg/oci" "github.com/fluxcd/pkg/oci/auth/aws" "github.com/fluxcd/pkg/oci/auth/azure" @@ -70,8 +70,6 @@ type ProviderOptions struct { // AzureAutoLogin enables automatic attempt to get credentials for images in // ACR. AzureAutoLogin bool - // Cache is a cache for storing auth configurations. - Cache cache.Expirable[cache.StoreObject[authn.Authenticator]] } // Manager is a login manager for various registry providers. @@ -141,65 +139,24 @@ func (m *Manager) WithACRClient(c *azure.Client) *Manager { // Login performs authentication against a registry and returns the Authenticator. // For generic registry provider, it is no-op. func (m *Manager) Login(ctx context.Context, url string, ref name.Reference, opts ProviderOptions) (authn.Authenticator, error) { - provider := ImageRegistryProvider(url, ref) - var ( - key string - err error - ) - if opts.Cache != nil { - key, err = m.keyFromURL(url, provider) - if err != nil { - logr.FromContextOrDiscard(ctx).Error(err, "failed to get cache key") - } else { - auth, exists, err := getObjectFromCache(opts.Cache, key) - if err != nil { - logr.FromContextOrDiscard(ctx).Error(err, "failed to get auth object from cache") - } - if exists { - return auth, nil - } - } - } + auth, _, err := m.LoginWithExpiry(ctx, url, ref, opts) + return auth, err +} +// LoginWithExpiry performs authentication against a registry and returns the +// Authenticator along with the auth expiry time. +// For generic registry provider, it is no-op. +func (m *Manager) LoginWithExpiry(ctx context.Context, url string, ref name.Reference, opts ProviderOptions) (authn.Authenticator, time.Time, error) { + provider := ImageRegistryProvider(url, ref) switch provider { case oci.ProviderAWS: - auth, expiresAt, err := m.ecr.LoginWithExpiry(ctx, opts.AwsAutoLogin, url) - if err != nil { - return nil, err - } - if opts.Cache != nil { - err := cacheObject(opts.Cache, auth, key, expiresAt) - if err != nil { - logr.FromContextOrDiscard(ctx).Error(err, "failed to cache auth object") - } - } - return auth, nil + return m.ecr.LoginWithExpiry(ctx, opts.AwsAutoLogin, url) case oci.ProviderGCP: - auth, expiresAt, err := m.gcr.LoginWithExpiry(ctx, opts.GcpAutoLogin, url, ref) - if err != nil { - return nil, err - } - if opts.Cache != nil { - err := cacheObject(opts.Cache, auth, key, expiresAt) - if err != nil { - logr.FromContextOrDiscard(ctx).Error(err, "failed to cache auth object") - } - } - return auth, nil + return m.gcr.LoginWithExpiry(ctx, opts.GcpAutoLogin, url, ref) case oci.ProviderAzure: - auth, expiresAt, err := m.acr.LoginWithExpiry(ctx, opts.AzureAutoLogin, url, ref) - if err != nil { - return nil, err - } - if opts.Cache != nil { - err := cacheObject(opts.Cache, auth, key, expiresAt) - if err != nil { - logr.FromContextOrDiscard(ctx).Error(err, "failed to cache auth object") - } - } - return auth, nil + return m.acr.LoginWithExpiry(ctx, opts.AzureAutoLogin, url, ref) } - return nil, nil + return nil, time.Time{}, nil } // OIDCLogin attempts to get an Authenticator for the provided URL endpoint. @@ -236,28 +193,3 @@ func (m *Manager) OIDCLogin(ctx context.Context, registryURL string, opts Provid } return nil, nil } - -// keyFromURL returns a key for the cache based on the URL and provider. -// Use this when you don't want to cache the full URL, -// but instead want to cache based on the provider secific way of identifying -// the authentication principal, i.e. the Domain for AWS and Azure, Project for GCP. -func (m *Manager) keyFromURL(ref string, provider oci.Provider) (string, error) { - if !strings.Contains(ref, "://") { - ref = fmt.Sprintf("//%s", ref) - } - u, err := url.Parse(ref) - if err != nil { - return "", err - } - switch provider { - case oci.ProviderAWS, oci.ProviderAzure: - return u.Host, nil - case oci.ProviderGCP: - paths := strings.Split(u.Path, "/") - if len(paths) > 1 { - return fmt.Sprintf("%s/%s", u.Host, paths[1]), nil - } - return u.Host, nil - } - return "", nil -} diff --git a/oci/auth/login/login_test.go b/oci/auth/login/login_test.go index 2aebdfab..b23be1dc 100644 --- a/oci/auth/login/login_test.go +++ b/oci/auth/login/login_test.go @@ -18,20 +18,16 @@ package login import ( "context" - "fmt" "net/http" "net/http/httptest" "strings" "testing" - "time" awssdk "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/credentials" - "github.com/google/go-containerregistry/pkg/authn" "github.com/google/go-containerregistry/pkg/name" . "github.com/onsi/gomega" - "github.com/fluxcd/pkg/cache" "github.com/fluxcd/pkg/oci" "github.com/fluxcd/pkg/oci/auth/aws" "github.com/fluxcd/pkg/oci/auth/azure" @@ -165,146 +161,3 @@ func TestLogin(t *testing.T) { }) } } - -func TestLogin_WithCache(t *testing.T) { - timestamp := time.Now().Add(10 * time.Second).Unix() - tests := []struct { - name string - responseBody string - statusCode int - providerOpts ProviderOptions - beforeFunc func(serverURL string, mgr *Manager, image *string) - wantErr bool - }{ - { - name: "ecr", - responseBody: fmt.Sprintf(`{"authorizationData": [{"authorizationToken": "c29tZS1rZXk6c29tZS1zZWNyZXQ=","expiresAt": %d}]}`, timestamp), - providerOpts: ProviderOptions{AwsAutoLogin: true}, - beforeFunc: func(serverURL string, mgr *Manager, image *string) { - // Create ECR client and configure the manager. - ecrClient := aws.NewClient() - cfg := awssdk.NewConfig() - cfg.EndpointResolverWithOptions = awssdk.EndpointResolverWithOptionsFunc( - func(service, region string, options ...interface{}) (awssdk.Endpoint, error) { - return awssdk.Endpoint{URL: serverURL}, nil - }) - cfg.Credentials = credentials.NewStaticCredentialsProvider("x", "y", "z") - ecrClient.WithConfig(cfg) - - mgr.WithECRClient(ecrClient) - - *image = "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo:v1" - }, - }, - { - name: "gcr", - responseBody: `{"access_token": "some-token","expires_in": 10, "token_type": "foo"}`, - providerOpts: ProviderOptions{GcpAutoLogin: true}, - beforeFunc: func(serverURL string, mgr *Manager, image *string) { - // Create GCR client and configure the manager. - gcrClient := gcp.NewClient().WithTokenURL(serverURL) - mgr.WithGCRClient(gcrClient) - - *image = "gcr.io/foo/bar:v1" - }, - }, - { - name: "acr", - responseBody: `{"refresh_token": "bbbbb"}`, - providerOpts: ProviderOptions{AzureAutoLogin: true}, - beforeFunc: func(serverURL string, mgr *Manager, image *string) { - acrClient := azure.NewClient().WithTokenCredential(&azure.FakeTokenCredential{Token: "foo"}).WithScheme("http") - mgr.WithACRClient(acrClient) - - *image = "foo.azurecr.io/bar:v1" - }, - // NOTE: This fails because the azure exchanger uses the image host - // to exchange token which can't be modified here without - // interfering image name based categorization of the login - // provider, that's actually being tested here. This is tested in - // detail in the azure package. - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g := NewWithT(t) - - // Create test server. - handler := func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(tt.responseBody)) - } - srv := httptest.NewServer(http.HandlerFunc(handler)) - t.Cleanup(func() { - srv.Close() - }) - - mgr := NewManager() - var image string - - if tt.beforeFunc != nil { - tt.beforeFunc(srv.URL, mgr, &image) - } - - ref, err := name.ParseReference(image) - g.Expect(err).ToNot(HaveOccurred()) - - cache, err := cache.New(5, cache.StoreObjectKeyFunc, - cache.WithCleanupInterval[cache.StoreObject[authn.Authenticator]](1*time.Second)) - g.Expect(err).ToNot(HaveOccurred()) - - tt.providerOpts.Cache = cache - - _, err = mgr.Login(context.TODO(), image, ref, tt.providerOpts) - if tt.wantErr { - g.Expect(err).To(HaveOccurred()) - } else { - key, err := mgr.keyFromURL(image, ImageRegistryProvider(image, ref)) - g.Expect(err).ToNot(HaveOccurred()) - auth, exists, err := getObjectFromCache(cache, key) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(exists).To(BeTrue()) - g.Expect(auth).ToNot(BeNil()) - obj, _, err := cache.GetByKey(key) - g.Expect(err).ToNot(HaveOccurred()) - expiration, err := cache.GetExpiration(obj) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(expiration).ToNot(BeZero()) - g.Expect(expiration).To(BeTemporally("~", time.Unix(timestamp, 0), 1*time.Second)) - } - }) - } -} - -func Test_keyFromURL(t *testing.T) { - tests := []struct { - name string - image string - want string - }{ - {"gcr", "gcr.io/foo/bar:v1", "gcr.io/foo"}, - {"ecr", "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo:v1", "012345678901.dkr.ecr.us-east-1.amazonaws.com"}, - {"ecr-root", "012345678901.dkr.ecr.us-east-1.amazonaws.com", "012345678901.dkr.ecr.us-east-1.amazonaws.com"}, - {"ecr-root with slash", "012345678901.dkr.ecr.us-east-1.amazonaws.com/", "012345678901.dkr.ecr.us-east-1.amazonaws.com"}, - {"gcr", "gcr.io/foo/bar:v1", "gcr.io/foo"}, - {"gcr-root", "gcr.io", "gcr.io"}, - {"acr", "foo.azurecr.io/bar:v1", "foo.azurecr.io"}, - {"acr-root", "foo.azurecr.io", "foo.azurecr.io"}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g := NewWithT(t) - - // Trim suffix to allow parsing it as reference without modifying - // the given image address. - ref, err := name.ParseReference(strings.TrimSuffix(tt.image, "/")) - g.Expect(err).ToNot(HaveOccurred()) - key, err := NewManager().keyFromURL(tt.image, ImageRegistryProvider(tt.image, ref)) - g.Expect(err).ToNot(HaveOccurred()) - g.Expect(key).To(Equal(tt.want)) - }) - } -} diff --git a/oci/go.mod b/oci/go.mod index 0ea3af34..3f8f90b0 100644 --- a/oci/go.mod +++ b/oci/go.mod @@ -3,7 +3,6 @@ module github.com/fluxcd/pkg/oci go 1.22.7 replace ( - github.com/fluxcd/pkg/cache => ../cache github.com/fluxcd/pkg/sourceignore => ../sourceignore github.com/fluxcd/pkg/tar => ../tar github.com/fluxcd/pkg/version => ../version @@ -18,7 +17,6 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.17.32 github.com/aws/aws-sdk-go-v2/service/ecr v1.33.0 github.com/distribution/distribution/v3 v3.0.0-beta.1 - github.com/fluxcd/pkg/cache v0.0.4 github.com/fluxcd/pkg/sourceignore v0.8.1 github.com/fluxcd/pkg/tar v0.8.1 github.com/fluxcd/pkg/version v0.4.1 @@ -42,7 +40,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect github.com/aws/smithy-go v1.20.4 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -57,49 +54,32 @@ require ( github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect github.com/docker/go-metrics v0.0.1 // indirect - github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fluxcd/cli-utils v0.36.0-flux.10 // indirect - github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-errors/errors v1.5.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect github.com/go-git/go-git/v5 v5.12.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.4 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect - github.com/golang/protobuf v1.5.4 // indirect - github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/handlers v1.5.2 // indirect github.com/gorilla/mux v1.8.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect - github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.17.9 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/onsi/ginkgo/v2 v2.22.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect @@ -109,9 +89,8 @@ require ( github.com/redis/go-redis/v9 v9.1.0 // indirect github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.10.0 // indirect github.com/vbatts/tar-split v0.11.3 // indirect - github.com/x448/float16 v0.8.4 // indirect - github.com/xlab/treeprint v1.2.0 // indirect go.opentelemetry.io/contrib/bridges/prometheus v0.53.0 // indirect go.opentelemetry.io/contrib/exporters/autoexport v0.53.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect @@ -135,31 +114,15 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect golang.org/x/crypto v0.29.0 // indirect golang.org/x/net v0.31.0 // indirect - golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/sync v0.9.0 // indirect golang.org/x/sys v0.27.0 // indirect - golang.org/x/term v0.26.0 // indirect golang.org/x/text v0.20.0 // indirect - golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.27.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.35.1 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.31.3 // indirect - k8s.io/apimachinery v0.31.3 // indirect - k8s.io/cli-runtime v0.31.3 // indirect - k8s.io/client-go v0.31.3 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect - k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.18.0 // indirect - sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/oci/go.sum b/oci/go.sum index d6804816..dbf2d797 100644 --- a/oci/go.sum +++ b/oci/go.sum @@ -4,13 +4,9 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -47,8 +43,6 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= @@ -61,15 +55,12 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= -github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc= github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -92,18 +83,8 @@ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fluxcd/cli-utils v0.36.0-flux.10 h1:kgoj1HP7KBFfIG9CHLFHpA2kCPNlfzCpbscCaAOSClE= -github.com/fluxcd/cli-utils v0.36.0-flux.10/go.mod h1:eWf+UVZmm51EmNmeGkdplVLVsFU4jETfCjoHZq7nUp4= -github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= -github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= -github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= -github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= @@ -118,62 +99,36 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= -github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/golang-lru/arc/v2 v2.0.5 h1:l2zaLDubNhW4XO3LnliVj0GXO3+/CGNJAg1dcN2Fpfw= github.com/hashicorp/golang-lru/arc/v2 v2.0.5/go.mod h1:ny6zBSQZi2JxIeYcv7kt2sH2PXJtirBN7RDhRpxPkxU= github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= -github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= @@ -182,55 +137,29 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= @@ -239,8 +168,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -276,11 +203,7 @@ github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0Niuqvtf github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -293,8 +216,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -306,12 +227,6 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= -github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= -github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opentelemetry.io/contrib/bridges/prometheus v0.53.0 h1:BdkKDtcrHThgjcEia1737OUuFdP6xzBKAMx2sNZCkvE= go.opentelemetry.io/contrib/bridges/prometheus v0.53.0/go.mod h1:ZkhVxcJgeXlL/lVyT/vxNHVFiSG5qOaDwYaSgD8IfZo= go.opentelemetry.io/contrib/exporters/autoexport v0.53.0 h1:13K+tY7E8GJInkrvRiPAhC0gi/7vKjzDNhtmCf+QXG8= @@ -358,58 +273,30 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= -golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= -golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= -golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= -golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= -golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= @@ -422,10 +309,6 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= -gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -437,31 +320,3 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= -k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= -k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= -k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/cli-runtime v0.31.3 h1:fEQD9Xokir78y7pVK/fCJN090/iYNrLHpFbGU4ul9TI= -k8s.io/cli-runtime v0.31.3/go.mod h1:Q2jkyTpl+f6AtodQvgDI8io3jrfr+Z0LyQBPJJ2Btq8= -k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= -k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= -k8s.io/component-base v0.31.3 h1:DMCXXVx546Rfvhj+3cOm2EUxhS+EyztH423j+8sOwhQ= -k8s.io/component-base v0.31.3/go.mod h1:xME6BHfUOafRgT0rGVBGl7TuSg8Z9/deT7qq6w7qjIU= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= -k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/kubectl v0.31.3 h1:3r111pCjPsvnR98oLLxDMwAeM6OPGmPty6gSKaLTQes= -k8s.io/kubectl v0.31.3/go.mod h1:lhMECDCbJN8He12qcKqs2QfmVo9Pue30geovBVpH5fs= -k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno= -k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= -sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= -sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= -sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= -sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/oci/tests/integration/go.mod b/oci/tests/integration/go.mod index 3f8bc9d6..bff62839 100644 --- a/oci/tests/integration/go.mod +++ b/oci/tests/integration/go.mod @@ -4,7 +4,6 @@ go 1.22.7 replace ( github.com/fluxcd/pkg/auth => ../../../auth - github.com/fluxcd/pkg/cache => ../../../cache github.com/fluxcd/pkg/git => ../../../git github.com/fluxcd/pkg/git/gogit => ../../../git/gogit github.com/fluxcd/pkg/oci => ../../ @@ -12,7 +11,6 @@ replace ( require ( github.com/fluxcd/pkg/auth v0.0.1 - github.com/fluxcd/pkg/cache v0.0.4 github.com/fluxcd/pkg/git v0.21.0 github.com/fluxcd/pkg/git/gogit v0.19.0 github.com/fluxcd/pkg/oci v0.40.0 @@ -54,7 +52,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect github.com/aws/smithy-go v1.20.4 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver/v4 v4.0.0 // indirect github.com/bradleyfalzon/ghinstallation/v2 v2.12.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cloudflare/circl v1.5.0 // indirect @@ -66,12 +63,11 @@ require ( github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/evanphx/json-patch v5.7.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect - github.com/fluxcd/cli-utils v0.36.0-flux.10 // indirect github.com/fluxcd/pkg/ssh v0.14.1 // indirect github.com/fluxcd/pkg/version v0.4.1 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-errors/errors v1.5.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -89,7 +85,7 @@ require ( github.com/google/go-github/v66 v66.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -107,7 +103,6 @@ require ( github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect @@ -125,7 +120,6 @@ require ( github.com/vbatts/tar-split v0.11.3 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xlab/treeprint v1.2.0 // indirect github.com/zclconf/go-cty v1.14.4 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect @@ -142,20 +136,16 @@ require ( golang.org/x/tools v0.28.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/protobuf v1.35.1 // indirect - gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.31.3 // indirect - k8s.io/cli-runtime v0.31.3 // indirect k8s.io/client-go v0.31.3 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.18.0 // indirect - sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/oci/tests/integration/go.sum b/oci/tests/integration/go.sum index 80cd75ac..5dee6df6 100644 --- a/oci/tests/integration/go.sum +++ b/oci/tests/integration/go.sum @@ -8,15 +8,11 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0 h1:+m0M/LFxN43KvUL github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.0/go.mod h1:PwOyop78lveYMRs6oCxjiVyBdyCgIYH6XHIVZO9/SFQ= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM= github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= @@ -60,14 +56,10 @@ github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bradleyfalzon/ghinstallation/v2 v2.12.0 h1:k8oVjGhZel2qmCUsYwSE34jPNT9DL2wCBOtugsHv26g= github.com/bradleyfalzon/ghinstallation/v2 v2.12.0/go.mod h1:V4gJcNyAftH0rXpRp1SUVUuh+ACxOH1xOk/ZzkRHltg= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= -github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys= github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= @@ -98,10 +90,6 @@ github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fluxcd/cli-utils v0.36.0-flux.10 h1:kgoj1HP7KBFfIG9CHLFHpA2kCPNlfzCpbscCaAOSClE= -github.com/fluxcd/cli-utils v0.36.0-flux.10/go.mod h1:eWf+UVZmm51EmNmeGkdplVLVsFU4jETfCjoHZq7nUp4= github.com/fluxcd/gitkit v0.6.0 h1:iNg5LTx6ePo+Pl0ZwqHTAkhbUHxGVSY3YCxCdw7VIFg= github.com/fluxcd/gitkit v0.6.0/go.mod h1:svOHuKi0fO9HoawdK4HfHAJJseZDHHjk7I3ihnCIqNo= github.com/fluxcd/pkg/gittestserver v0.13.1 h1:5rXF8ANlk6wtAsvqH7tI7gaO2zhMySftf7ALh0AhfU4= @@ -116,8 +104,6 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= -github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= -github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8= @@ -151,8 +137,6 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -170,15 +154,9 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -195,8 +173,6 @@ github.com/hashicorp/terraform-json v0.22.1 h1:xft84GZR0QzjPVWs4lRUwvTcPnegqlyS7 github.com/hashicorp/terraform-json v0.22.1/go.mod h1:JbWSQCLFSXFFhg42T7l9iJwdGXBYV8fmmD6o/ML4p3A= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -225,31 +201,19 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/microsoft/azure-devops-go-api/azuredevops/v7 v7.1.0 h1:mmJCWLe63QvybxhW1iBmQWEaCKdc4SKgALfTNZ+OphU= github.com/microsoft/azure-devops-go-api/azuredevops/v7 v7.1.0/go.mod h1:mDunUZ1IUJdJIRHvFb+LPBUtxe3AYB5MI6BMXNg8194= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8= -github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= @@ -258,8 +222,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug= github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= -github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= @@ -281,8 +243,6 @@ github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0 github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= @@ -292,15 +252,11 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -317,8 +273,6 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= -github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zclconf/go-cty v1.14.4 h1:uXXczd9QDGsgu0i/QFR/hzI5NYCHLf6NQw/atrbnhq8= @@ -417,28 +371,18 @@ k8s.io/apiextensions-apiserver v0.31.3 h1:+GFGj2qFiU7rGCsA5o+p/rul1OQIq6oYpQw4+u k8s.io/apiextensions-apiserver v0.31.3/go.mod h1:2DSpFhUZZJmn/cr/RweH1cEVVbzFw9YBu4T+U3mf1e4= k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/cli-runtime v0.31.3 h1:fEQD9Xokir78y7pVK/fCJN090/iYNrLHpFbGU4ul9TI= -k8s.io/cli-runtime v0.31.3/go.mod h1:Q2jkyTpl+f6AtodQvgDI8io3jrfr+Z0LyQBPJJ2Btq8= k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= -k8s.io/component-base v0.31.3 h1:DMCXXVx546Rfvhj+3cOm2EUxhS+EyztH423j+8sOwhQ= -k8s.io/component-base v0.31.3/go.mod h1:xME6BHfUOafRgT0rGVBGl7TuSg8Z9/deT7qq6w7qjIU= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= -k8s.io/kubectl v0.31.3 h1:3r111pCjPsvnR98oLLxDMwAeM6OPGmPty6gSKaLTQes= -k8s.io/kubectl v0.31.3/go.mod h1:lhMECDCbJN8He12qcKqs2QfmVo9Pue30geovBVpH5fs= k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 h1:jGnCPejIetjiy2gqaJ5V0NLwTpF4wbQ6cZIItJCSHno= k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= -sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= -sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= -sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/oci/tests/integration/testapp/main.go b/oci/tests/integration/testapp/main.go index bf92cf9a..e970088e 100644 --- a/oci/tests/integration/testapp/main.go +++ b/oci/tests/integration/testapp/main.go @@ -34,7 +34,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" "github.com/fluxcd/pkg/auth/azure" - "github.com/fluxcd/pkg/cache" "github.com/fluxcd/pkg/git" "github.com/fluxcd/pkg/git/gogit" "github.com/fluxcd/pkg/git/repository" @@ -69,16 +68,10 @@ func main() { } func checkOci(ctx context.Context) { - cache, err := cache.New(5, cache.StoreObjectKeyFunc, - cache.WithCleanupInterval[cache.StoreObject[authn.Authenticator]](1*time.Second)) - if err != nil { - panic(err) - } opts := login.ProviderOptions{ AwsAutoLogin: true, GcpAutoLogin: true, AzureAutoLogin: true, - Cache: cache, } if *repo == "" { @@ -88,6 +81,7 @@ func checkOci(ctx context.Context) { var loginURL string var auth authn.Authenticator var ref name.Reference + var err error if *registry != "" { // Registry and repository are separate.