Skip to content

Commit 0811bad

Browse files
g-gastonk8s-infra-cherrypick-robot
authored and
k8s-infra-cherrypick-robot
committed
Address review comments
1 parent 40b41df commit 0811bad

File tree

2 files changed

+56
-31
lines changed

2 files changed

+56
-31
lines changed

pkg/client/apiutil/restmapper.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ func (m *mapper) addKnownGroupAndReload(groupName string, versions ...string) er
185185

186186
// Update information for group resources about versioned resources.
187187
// The number of API calls is equal to the number of versions: /apis/<group>/<version>.
188-
groupVersionResources, err := m.fetchGroupVersionResources(groupName, versions...)
188+
// If we encounter a missing API version (NotFound error), we will remove the group from
189+
// the m.apiGroups and m.knownGroups caches.
190+
// If this happens, in the next call the group will be added back to apiGroups
191+
// and only the existing versions will be loaded in knownGroups.
192+
groupVersionResources, err := m.fetchGroupVersionResourcesLocked(groupName, versions...)
189193
if err != nil {
190194
return fmt.Errorf("failed to get API group resources: %w", err)
191195
}
@@ -194,14 +198,12 @@ func (m *mapper) addKnownGroupAndReload(groupName string, versions ...string) er
194198
groupResources = m.knownGroups[groupName]
195199
}
196200

197-
for version, resources := range groupVersionResources {
198-
groupResources.VersionedResources[version.Version] = resources.APIResources
199-
}
200-
201201
// Update information for group resources about the API group by adding new versions.
202202
// Ignore the versions that are already registered.
203-
for groupVersion := range groupVersionResources {
203+
for groupVersion, resources := range groupVersionResources {
204204
version := groupVersion.Version
205+
206+
groupResources.VersionedResources[version] = resources.APIResources
205207
found := false
206208
for _, v := range groupResources.Group.Versions {
207209
if v.Version == version {
@@ -268,9 +270,9 @@ func (m *mapper) findAPIGroupByName(groupName string) (*metav1.APIGroup, error)
268270
return m.apiGroups[groupName], nil
269271
}
270272

271-
// fetchGroupVersionResources fetches the resources for the specified group and its versions.
273+
// fetchGroupVersionResourcesLocked fetches the resources for the specified group and its versions.
272274
// This method might modify the cache so it needs to be called under the lock.
273-
func (m *mapper) fetchGroupVersionResources(groupName string, versions ...string) (map[schema.GroupVersion]*metav1.APIResourceList, error) {
275+
func (m *mapper) fetchGroupVersionResourcesLocked(groupName string, versions ...string) (map[schema.GroupVersion]*metav1.APIResourceList, error) {
274276
groupVersionResources := make(map[schema.GroupVersion]*metav1.APIResourceList)
275277
failedGroups := make(map[schema.GroupVersion]error)
276278

@@ -283,6 +285,7 @@ func (m *mapper) fetchGroupVersionResources(groupName string, versions ...string
283285
// so it gets refreshed on the next call.
284286
delete(m.apiGroups, groupName)
285287
delete(m.knownGroups, groupName)
288+
continue
286289
} else if err != nil {
287290
failedGroups[groupVersion] = err
288291
}

pkg/client/apiutil/restmapper_test.go

+45-23
Original file line numberDiff line numberDiff line change
@@ -571,12 +571,24 @@ func TestLazyRestMapperProvider(t *testing.T) {
571571
c, err := client.New(restCfg, client.Options{Scheme: s})
572572
g.Expect(err).NotTo(gmg.HaveOccurred())
573573

574-
// Register a new CRD ina new group to avoid collisions when deleting versions - "taxi.inventory.example.com".
574+
// Register a new CRD ina new group to avoid collisions when deleting versions - "taxis.inventory.example.com".
575575
group := "inventory.example.com"
576576
kind := "Taxi"
577577
plural := "taxis"
578578
crdName := plural + "." + group
579-
crd := createNewCRD(ctx, g, c, group, kind, plural)
579+
// Create a CRD with two versions: v1alpha1 and v1 where both are served and
580+
// v1 is the storage version so we can easily remove v1alpha1 later.
581+
crd := newCRD(ctx, g, c, group, kind, plural)
582+
v1alpha1 := crd.Spec.Versions[0]
583+
v1alpha1.Name = "v1alpha1"
584+
v1alpha1.Storage = false
585+
v1alpha1.Served = true
586+
v1 := crd.Spec.Versions[0]
587+
v1.Name = "v1"
588+
v1.Storage = true
589+
v1.Served = true
590+
crd.Spec.Versions = []apiextensionsv1.CustomResourceDefinitionVersion{v1alpha1, v1}
591+
g.Expect(c.Create(ctx, crd)).To(gmg.Succeed())
580592
t.Cleanup(func() {
581593
g.Expect(c.Delete(ctx, crd)).To(gmg.Succeed())
582594
})
@@ -599,63 +611,76 @@ func TestLazyRestMapperProvider(t *testing.T) {
599611
// #1: GET https://host/api
600612
// #2: GET https://host/apis
601613
// Then, for all available versions:
602-
// #3: GET https://host/apis/inventory.example.com/v1
603-
// #4: GET https://host/apis/inventory.example.com/v2
614+
// #3: GET https://host/apis/inventory.example.com/v1alpha1
615+
// #4: GET https://host/apis/inventory.example.com/v1
604616
// This should fill the cache for apiGroups and versions.
605617
mapping, err := lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind})
606618
g.Expect(err).NotTo(gmg.HaveOccurred())
607619
g.Expect(mapping.GroupVersionKind.Kind).To(gmg.Equal(kind))
608620
g.Expect(crt.GetRequestCount()).To(gmg.Equal(4))
609621
crt.Reset() // We reset the counter to check how many additional requests are made later.
610622

611-
// At this point v2 should be cached
612-
_, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind}, "v2")
623+
// At this point v1alpha1 should be cached
624+
_, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind}, "v1alpha1")
613625
g.Expect(err).NotTo(gmg.HaveOccurred())
614626
g.Expect(crt.GetRequestCount()).To(gmg.Equal(0))
615627

616628
// We update the CRD to only have v1 version.
617629
g.Expect(c.Get(ctx, types.NamespacedName{Name: crdName}, crd)).To(gmg.Succeed())
618-
var v1 apiextensionsv1.CustomResourceDefinitionVersion
619-
for i, version := range crd.Spec.Versions {
630+
for _, version := range crd.Spec.Versions {
620631
if version.Name == "v1" {
621-
crd.Spec.Versions[i].Storage = true
622632
v1 = version
623-
v1.Storage = true
633+
break
624634
}
625635
}
626636
crd.Spec.Versions = []apiextensionsv1.CustomResourceDefinitionVersion{v1}
627637
g.Expect(c.Update(ctx, crd)).To(gmg.Succeed())
628638

629-
// We wait until v2 is not available anymore.
639+
// We wait until v1alpha1 is not available anymore.
630640
g.Eventually(func(g gmg.Gomega) {
631-
_, err = discClient.ServerResourcesForGroupVersion(group + "/v2")
632-
g.Expect(apierrors.IsNotFound(err)).To(gmg.BeTrue(), "v2 should not be available anymore")
641+
_, err = discClient.ServerResourcesForGroupVersion(group + "/v1alpha1")
642+
g.Expect(apierrors.IsNotFound(err)).To(gmg.BeTrue(), "v1alpha1 should not be available anymore")
633643
}).Should(gmg.Succeed())
634644

635-
// Although v2 is not available anymore, the cache is not invalidated yet so it should return a mapping.
636-
_, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind}, "v2")
645+
// Although v1alpha1 is not available anymore, the cache is not invalidated yet so it should return a mapping.
646+
_, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind}, "v1alpha1")
637647
g.Expect(err).NotTo(gmg.HaveOccurred())
638648
g.Expect(crt.GetRequestCount()).To(gmg.Equal(0))
639649

640650
// We request Limo, which is not in the mapper because it doesn't exist.
641651
// This will trigger a reload of the lazy mapper cache.
642652
// Reloading the cache will read v2 again and since it's not available anymore, it should invalidate the cache.
643-
// #1: GET https://host/apis/inventory.example.com/v1
644-
// #2: GET https://host/apis/inventory.example.com/v2
653+
// #1: GET https://host/apis/inventory.example.com/v1alpha1
654+
// #2: GET https://host/apis/inventory.example.com/v1
645655
_, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: "Limo"})
646656
g.Expect(err).To(beNoMatchError())
647657
g.Expect(crt.GetRequestCount()).To(gmg.Equal(2))
648658
crt.Reset()
649659

650-
// Now we request v2 again and it should return an error since the cache was invalidated.
651-
// #1: GET https://host/apis/inventory.example.com/v2
652-
_, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind}, "v2")
660+
// Now we request v1alpha1 again and it should return an error since the cache was invalidated.
661+
// #1: GET https://host/apis/inventory.example.com/v1alpha1
662+
_, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind}, "v1alpha1")
653663
g.Expect(err).To(beNoMatchError())
654664
g.Expect(crt.GetRequestCount()).To(gmg.Equal(1))
665+
666+
// Verify that when requesting the mapping without a version, it doesn't error
667+
// and it returns v1.
668+
mapping, err = lazyRestMapper.RESTMapping(schema.GroupKind{Group: group, Kind: kind})
669+
g.Expect(err).NotTo(gmg.HaveOccurred())
670+
g.Expect(mapping.Resource.Version).To(gmg.Equal("v1"))
655671
})
656672
}
657673

674+
// createNewCRD creates a new CRD with the given group, kind, and plural and returns it.
658675
func createNewCRD(ctx context.Context, g gmg.Gomega, c client.Client, group, kind, plural string) *apiextensionsv1.CustomResourceDefinition {
676+
newCRD := newCRD(ctx, g, c, group, kind, plural)
677+
g.Expect(c.Create(ctx, newCRD)).To(gmg.Succeed())
678+
679+
return newCRD
680+
}
681+
682+
// newCRD returns a new CRD with the given group, kind, and plural.
683+
func newCRD(ctx context.Context, g gmg.Gomega, c client.Client, group, kind, plural string) *apiextensionsv1.CustomResourceDefinition {
659684
crd := &apiextensionsv1.CustomResourceDefinition{}
660685
err := c.Get(ctx, types.NamespacedName{Name: "drivers.crew.example.com"}, crd)
661686
g.Expect(err).NotTo(gmg.HaveOccurred())
@@ -671,9 +696,6 @@ func createNewCRD(ctx context.Context, g gmg.Gomega, c client.Client, group, kin
671696
}
672697
newCRD.ResourceVersion = ""
673698

674-
// Create the new CRD.
675-
g.Expect(c.Create(ctx, newCRD)).To(gmg.Succeed())
676-
677699
return newCRD
678700
}
679701

0 commit comments

Comments
 (0)