Skip to content

Commit

Permalink
Update memcache code to match upstream changes
Browse files Browse the repository at this point in the history
We maintain a downstream copy of the memcache discovery client that uses a different logger. The upstream code changed some interfaces in v0.26.0. This change pulls in the latest code and reapplies the logging changes.
  • Loading branch information
lblackstone committed Jan 18, 2023
1 parent bccd18c commit 01de5fb
Showing 1 changed file with 68 additions and 13 deletions.
81 changes: 68 additions & 13 deletions provider/pkg/clients/memcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ limitations under the License.
// This bypasses Pulumi's logging mechanism, and causes unactionable error messages to appear in the CLI. This error
// logging was disabled.
//
// [1] https://github.com/kubernetes/client-go/blob/release-1.24/discovery/cached/memory/memcache.go
// [1] https://github.com/kubernetes/client-go/blob/release-1.26/discovery/cached/memory/memcache.go

package clients

Expand All @@ -32,9 +32,9 @@ import (

openapi_v2 "github.com/google/gnostic/openapiv2"
logger "github.com/pulumi/pulumi/sdk/v3/go/common/util/logging" // Added in place of upstream HandleError

errorsutil "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/discovery"
Expand All @@ -56,11 +56,12 @@ type cacheEntry struct {
type memCacheClient struct {
delegate discovery.DiscoveryInterface

lock sync.RWMutex
groupToServerResources map[string]*cacheEntry
groupList *metav1.APIGroupList
cacheValid bool
openapiClient openapi.Client
lock sync.RWMutex
groupToServerResources map[string]*cacheEntry
groupList *metav1.APIGroupList
cacheValid bool
openapiClient openapi.Client
receivedAggregatedDiscovery bool
}

// Error Constants
Expand Down Expand Up @@ -124,15 +125,39 @@ func (d *memCacheClient) ServerGroupsAndResources() ([]*metav1.APIGroup, []*meta
return discovery.ServerGroupsAndResources(d)
}

func (d *memCacheClient) ServerGroups() (*metav1.APIGroupList, error) {
// GroupsAndMaybeResources returns the list of APIGroups, and possibly the map of group/version
// to resources. The returned groups will never be nil, but the resources map can be nil
// if there are no cached resources.
func (d *memCacheClient) GroupsAndMaybeResources() (*metav1.APIGroupList, map[schema.GroupVersion]*metav1.APIResourceList, error) {
d.lock.Lock()
defer d.lock.Unlock()

if !d.cacheValid {
if err := d.refreshLocked(); err != nil {
return nil, err
return nil, nil, err
}
}
return d.groupList, nil
// Build the resourceList from the cache?
var resourcesMap map[schema.GroupVersion]*metav1.APIResourceList
if d.receivedAggregatedDiscovery && len(d.groupToServerResources) > 0 {
resourcesMap = map[schema.GroupVersion]*metav1.APIResourceList{}
for gv, cacheEntry := range d.groupToServerResources {
groupVersion, err := schema.ParseGroupVersion(gv)
if err != nil {
return nil, nil, fmt.Errorf("failed to parse group version (%v): %v", gv, err)
}
resourcesMap[groupVersion] = cacheEntry.resourceList
}
}
return d.groupList, resourcesMap, nil
}

func (d *memCacheClient) ServerGroups() (*metav1.APIGroupList, error) {
groups, _, err := d.GroupsAndMaybeResources()
if err != nil {
return nil, err
}
return groups, nil
}

func (d *memCacheClient) RESTClient() restclient.Interface {
Expand Down Expand Up @@ -185,6 +210,10 @@ func (d *memCacheClient) Invalidate() {
d.groupToServerResources = nil
d.groupList = nil
d.openapiClient = nil
d.receivedAggregatedDiscovery = false
if ad, ok := d.delegate.(discovery.CachedDiscoveryInterface); ok {
ad.Invalidate()
}
}

// refreshLocked refreshes the state of cache. The caller must hold d.lock for
Expand All @@ -193,7 +222,26 @@ func (d *memCacheClient) refreshLocked() error {
// TODO: Could this multiplicative set of calls be replaced by a single call
// to ServerResources? If it's possible for more than one resulting
// APIResourceList to have the same GroupVersion, the lists would need merged.
gl, err := d.delegate.ServerGroups()
var gl *metav1.APIGroupList
var err error

if ad, ok := d.delegate.(discovery.AggregatedDiscoveryInterface); ok {
var resources map[schema.GroupVersion]*metav1.APIResourceList
gl, resources, err = ad.GroupsAndMaybeResources()
if resources != nil && err == nil {
// Cache the resources.
d.groupToServerResources = map[string]*cacheEntry{}
d.groupList = gl
for gv, resources := range resources {
d.groupToServerResources[gv.String()] = &cacheEntry{resources, nil}
}
d.receivedAggregatedDiscovery = true
d.cacheValid = true
return nil
}
} else {
gl, err = d.delegate.ServerGroups()
}
if err != nil || len(gl.Groups) == 0 {
logger.V(9).Infof("couldn't get current server API group list: %v", err) // Updated by Pulumi
return err
Expand Down Expand Up @@ -239,14 +287,21 @@ func (d *memCacheClient) serverResourcesForGroupVersion(groupVersion string) (*m
return r, nil
}

// WithLegacy returns current memory-cached discovery client;
// current client does not support legacy-only discovery.
func (d *memCacheClient) WithLegacy() discovery.DiscoveryInterface {
return d
}

// NewMemCacheClient creates a new CachedDiscoveryInterface which caches
// discovery information in memory and will stay up-to-date if Invalidate is
// called with regularity.
//
// NOTE: The client will NOT resort to live lookups on cache misses.
func NewMemCacheClient(delegate discovery.DiscoveryInterface) discovery.CachedDiscoveryInterface {
return &memCacheClient{
delegate: delegate,
groupToServerResources: map[string]*cacheEntry{},
delegate: delegate,
groupToServerResources: map[string]*cacheEntry{},
receivedAggregatedDiscovery: false,
}
}

0 comments on commit 01de5fb

Please sign in to comment.