fix(install): guard against nil CRD data and empty resource slice

Backport nil-pointer crash fix from main (PR #31578) to dev-v3.

Add nil checks for obj.File and obj.File.Data before building CRD
resources, and return a descriptive error instead of dereferencing nil.
Add empty slice check for res after Build() to prevent
res[0] panic on empty resource lists.
Add nil check for RESTClientGetter before invalidating discovery
and REST mapper caches.

Fixes #31552

Signed-off-by: texasich <texasich@users.noreply.github.com>
pull/32106/head
texasich 4 days ago
parent 3033a778b6
commit 69753a690c

@ -162,12 +162,24 @@ func (i *Install) installCRDs(crds []chart.CRD) error {
// We do these one file at a time in the order they were read.
totalItems := []*resource.Info{}
for _, obj := range crds {
if obj.File == nil {
return errors.Errorf("failed to install CRD %s: file is empty", obj.Name)
}
if obj.File.Data == nil {
return errors.Errorf("failed to install CRD %s: file data is empty", obj.Name)
}
// Read in the resources
res, err := i.cfg.KubeClient.Build(bytes.NewBuffer(obj.File.Data), false)
if err != nil {
return errors.Wrapf(err, "failed to install CRD %s", obj.Name)
}
if len(res) == 0 {
return errors.Errorf("failed to install CRD %s: resources are empty", obj.Name)
}
// Send them to Kube
if _, err := i.cfg.KubeClient.Create(res); err != nil {
// If the error is CRD already exists, continue.
@ -191,27 +203,29 @@ func (i *Install) installCRDs(crds []chart.CRD) error {
// the case when an action configuration is reused for multiple actions,
// as otherwise it is later loaded by ourselves when getCapabilities
// is called later on in the installation process.
if i.cfg.Capabilities != nil {
discoveryClient, err := i.cfg.RESTClientGetter.ToDiscoveryClient()
if err != nil {
return err
}
if i.cfg.RESTClientGetter != nil {
if i.cfg.Capabilities != nil {
discoveryClient, err := i.cfg.RESTClientGetter.ToDiscoveryClient()
if err != nil {
return err
}
i.cfg.Log("Clearing discovery cache")
discoveryClient.Invalidate()
i.cfg.Log("Clearing discovery cache")
discoveryClient.Invalidate()
_, _ = discoveryClient.ServerGroups()
}
_, _ = discoveryClient.ServerGroups()
}
// Invalidate the REST mapper, since it will not have the new CRDs
// present.
restMapper, err := i.cfg.RESTClientGetter.ToRESTMapper()
if err != nil {
return err
}
if resettable, ok := restMapper.(meta.ResettableRESTMapper); ok {
i.cfg.Log("Clearing REST mapper cache")
resettable.Reset()
// Invalidate the REST mapper, since it will not have the new CRDs
// present.
restMapper, err := i.cfg.RESTClientGetter.ToRESTMapper()
if err != nil {
return err
}
if resettable, ok := restMapper.(meta.ResettableRESTMapper); ok {
i.cfg.Log("Clearing REST mapper cache")
resettable.Reset()
}
}
}
return nil

Loading…
Cancel
Save