diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 32fac97d8..3133da730 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -708,11 +708,11 @@ }, { "ImportPath": "k8s.io/client-go", - "Rev": "1cfb136f9050" + "Rev": "9409f5796d38" }, { "ImportPath": "k8s.io/component-base", - "Rev": "a7be188c8339" + "Rev": "b6d06acb8460" }, { "ImportPath": "k8s.io/gengo", diff --git a/go.mod b/go.mod index a4d683a01..d6eb47329 100644 --- a/go.mod +++ b/go.mod @@ -43,8 +43,8 @@ require ( gopkg.in/yaml.v2 v2.2.8 k8s.io/api v0.0.0-20210304082812-0d975ab4576f k8s.io/apimachinery v0.0.0-20210303224021-086982076e5b - k8s.io/client-go v0.0.0-20210304012214-1cfb136f9050 - k8s.io/component-base v0.0.0-20210303075719-a7be188c8339 + k8s.io/client-go v0.0.0-20210304132206-9409f5796d38 + k8s.io/component-base v0.0.0-20210304092723-b6d06acb8460 k8s.io/klog/v2 v2.5.0 k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd k8s.io/utils v0.0.0-20201110183641-67b214c5f920 @@ -56,6 +56,6 @@ require ( replace ( k8s.io/api => k8s.io/api v0.0.0-20210304082812-0d975ab4576f k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20210303224021-086982076e5b - k8s.io/client-go => k8s.io/client-go v0.0.0-20210304012214-1cfb136f9050 - k8s.io/component-base => k8s.io/component-base v0.0.0-20210303075719-a7be188c8339 + k8s.io/client-go => k8s.io/client-go v0.0.0-20210304132206-9409f5796d38 + k8s.io/component-base => k8s.io/component-base v0.0.0-20210304092723-b6d06acb8460 ) diff --git a/go.sum b/go.sum index 40d601650..a75621884 100644 --- a/go.sum +++ b/go.sum @@ -586,8 +586,8 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.0.0-20210304082812-0d975ab4576f/go.mod h1:YspOqQmF4OXdACGAs03nGPxRrWe/nIKAS3Cwch9YyFk= k8s.io/apimachinery v0.0.0-20210303224021-086982076e5b/go.mod h1:+s3G/nGQJY9oe1CFOXRrb9QkXTIEgTnFtF8GeKZIgOg= -k8s.io/client-go v0.0.0-20210304012214-1cfb136f9050/go.mod h1:7+H6O1iSg25yn0iqW6klOnBY/wGJvd6FBq4Dj0g2trw= -k8s.io/component-base v0.0.0-20210303075719-a7be188c8339/go.mod h1:kjHrkAGnrWmx2fK+fwbJKP0ipZkno3KivH4Rke6Va60= +k8s.io/client-go v0.0.0-20210304132206-9409f5796d38/go.mod h1:8e1dQV5aiRbvDwbqMoJhxxW7nYgrs9iCGWjxHFJkuXo= +k8s.io/component-base v0.0.0-20210304092723-b6d06acb8460/go.mod h1:y2J5c34+m/mFnjMj5b/bma1BnxhJycBj9Z2VmzHUG50= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.5.0 h1:8mOnjf1RmUPW6KRqQCfYSZq/K20Unmp3IhuZUhxl8KI= diff --git a/pkg/server/deleted_kinds.go b/pkg/server/deleted_kinds.go index 931264a0d..e9aed99ed 100644 --- a/pkg/server/deleted_kinds.go +++ b/pkg/server/deleted_kinds.go @@ -21,6 +21,9 @@ import ( "strconv" "strings" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/sets" apimachineryversion "k8s.io/apimachinery/pkg/version" "k8s.io/apiserver/pkg/registry/rest" @@ -45,7 +48,7 @@ type resourceExpirationEvaluator struct { type ResourceExpirationEvaluator interface { // RemoveDeletedKinds inspects the storage map and modifies it in place by removing storage for kinds that have been deleted. // versionedResourcesStorageMap mirrors the field on APIGroupInfo, it's a map from version to resource to the storage. - RemoveDeletedKinds(groupName string, versionedResourcesStorageMap map[string]map[string]rest.Storage) + RemoveDeletedKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage) // ShouldServeForVersion returns true if a particular version cut off is after the current version ShouldServeForVersion(majorRemoved, minorRemoved int) bool } @@ -91,8 +94,21 @@ func NewResourceExpirationEvaluator(currentVersion apimachineryversion.Info) (Re return ret, nil } -func (e *resourceExpirationEvaluator) shouldServe(resourceServingInfo rest.Storage) bool { - versionedPtr := resourceServingInfo.New() +func (e *resourceExpirationEvaluator) shouldServe(gv schema.GroupVersion, versioner runtime.ObjectVersioner, resourceServingInfo rest.Storage) bool { + internalPtr := resourceServingInfo.New() + + target := gv + // honor storage that overrides group version (used for things like scale subresources) + if versionProvider, ok := resourceServingInfo.(rest.GroupVersionKindProvider); ok { + target = versionProvider.GroupVersionKind(target).GroupVersion() + } + + versionedPtr, err := versioner.ConvertToVersion(internalPtr, target) + if err != nil { + utilruntime.HandleError(err) + return false + } + removed, ok := versionedPtr.(removedInterface) if !ok { return true @@ -135,12 +151,13 @@ type removedInterface interface { // removeDeletedKinds inspects the storage map and modifies it in place by removing storage for kinds that have been deleted. // versionedResourcesStorageMap mirrors the field on APIGroupInfo, it's a map from version to resource to the storage. -func (e *resourceExpirationEvaluator) RemoveDeletedKinds(groupName string, versionedResourcesStorageMap map[string]map[string]rest.Storage) { +func (e *resourceExpirationEvaluator) RemoveDeletedKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage) { versionsToRemove := sets.NewString() - for apiVersion, versionToResource := range versionedResourcesStorageMap { + for apiVersion := range sets.StringKeySet(versionedResourcesStorageMap) { + versionToResource := versionedResourcesStorageMap[apiVersion] resourcesToRemove := sets.NewString() for resourceName, resourceServingInfo := range versionToResource { - if !e.shouldServe(resourceServingInfo) { + if !e.shouldServe(schema.GroupVersion{Group: groupName, Version: apiVersion}, versioner, resourceServingInfo) { resourcesToRemove.Insert(resourceName) } } @@ -151,8 +168,9 @@ func (e *resourceExpirationEvaluator) RemoveDeletedKinds(groupName string, versi } klog.V(1).Infof("Removing resource %v.%v.%v because it is time to stop serving it per APILifecycle.", resourceName, apiVersion, groupName) - delete(versionedResourcesStorageMap[apiVersion], resourceName) + delete(versionToResource, resourceName) } + versionedResourcesStorageMap[apiVersion] = versionToResource if len(versionedResourcesStorageMap[apiVersion]) == 0 { versionsToRemove.Insert(apiVersion) diff --git a/pkg/server/deleted_kinds_test.go b/pkg/server/deleted_kinds_test.go index 54ad13a4d..8cbcd2f59 100644 --- a/pkg/server/deleted_kinds_test.go +++ b/pkg/server/deleted_kinds_test.go @@ -221,13 +221,27 @@ func Test_resourceExpirationEvaluator_shouldServe(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if actual := tt.resourceExpirationEvaluator.shouldServe(tt.restStorage); actual != tt.expected { + gv := schema.GroupVersion{Group: "mygroup", Version: "myversion"} + convertor := &dummyConvertor{} + if actual := tt.resourceExpirationEvaluator.shouldServe(gv, convertor, tt.restStorage); actual != tt.expected { t.Errorf("shouldServe() = %v, want %v", actual, tt.expected) } + if !reflect.DeepEqual(convertor.called, gv) { + t.Errorf("expected converter to be called with %#v, got %#v", gv, convertor.called) + } }) } } +type dummyConvertor struct { + called runtime.GroupVersioner +} + +func (d *dummyConvertor) ConvertToVersion(in runtime.Object, gv runtime.GroupVersioner) (runtime.Object, error) { + d.called = gv + return in, nil +} + func checkErr(t *testing.T, actual error, expected string) { t.Helper() switch { @@ -309,7 +323,8 @@ func Test_removeDeletedKinds(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tt.resourceExpirationEvaluator.RemoveDeletedKinds("group.name", tt.versionedResourcesStorageMap) + convertor := &dummyConvertor{} + tt.resourceExpirationEvaluator.RemoveDeletedKinds("group.name", convertor, tt.versionedResourcesStorageMap) if !reflect.DeepEqual(tt.expectedStorage, tt.versionedResourcesStorageMap) { t.Fatal(spew.Sdump(tt.versionedResourcesStorageMap)) }