-
Notifications
You must be signed in to change notification settings - Fork 40k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix apiserver crash caused by nil pointer #58438
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -20,14 +20,13 @@ import ( | |||||||
"fmt" | ||||||||
"strings" | ||||||||
|
||||||||
"github.com/go-openapi/spec" | ||||||||
|
||||||||
genericvalidation "k8s.io/apimachinery/pkg/api/validation" | ||||||||
validationutil "k8s.io/apimachinery/pkg/util/validation" | ||||||||
"k8s.io/apimachinery/pkg/util/validation/field" | ||||||||
utilfeature "k8s.io/apiserver/pkg/util/feature" | ||||||||
|
||||||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" | ||||||||
apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation" | ||||||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" | ||||||||
) | ||||||||
|
||||||||
|
@@ -188,6 +187,12 @@ func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiext | |||||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(customResourceValidation.OpenAPIV3Schema, fldPath.Child("openAPIV3Schema"), openAPIV3Schema)...) | ||||||||
} | ||||||||
|
||||||||
// if validation passed otherwise, make sure we can actually construct a schema validator from this custom resource validation. | ||||||||
if len(allErrs) == 0 { | ||||||||
if _, err := apiservervalidation.NewSchemaValidator(customResourceValidation); err != nil { | ||||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("customResourceValidation"), "", fmt.Sprintf("error building validator: %v", err))) | ||||||||
} | ||||||||
} | ||||||||
return allErrs | ||||||||
} | ||||||||
|
||||||||
|
@@ -213,17 +218,6 @@ func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSch | |||||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalProperties.Schema, fldPath.Child("additionalProperties"), ssv)...) | ||||||||
} | ||||||||
|
||||||||
if schema.Ref != nil { | ||||||||
openapiRef, err := spec.NewRef(*schema.Ref) | ||||||||
if err != nil { | ||||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("ref"), *schema.Ref, err.Error())) | ||||||||
} | ||||||||
|
||||||||
if !openapiRef.IsValidURI() { | ||||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("ref"), *schema.Ref, "ref does not point to a valid URI")) | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
if schema.AdditionalItems != nil { | ||||||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalItems.Schema, fldPath.Child("additionalItems"), ssv)...) | ||||||||
} | ||||||||
|
@@ -318,6 +312,10 @@ func (v *specStandardValidatorV3) validate(schema *apiextensions.JSONSchemaProps | |||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("dependencies"), "dependencies is not supported")) | ||||||||
} | ||||||||
|
||||||||
if schema.Ref != nil { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean we forbid schemata like described in https://spacetelescope.github.io/understanding-json-schema/structuring.html with local definitions? Then I do not agree with this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To my understanding the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sttts We don't support definitions now: Lines 313 to 315 in 23226c2
because OpenAPI v3 does not support definitions (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject)
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright. Poor OpenAPI (again). Then, without definitions my concerns are gone. /unhold There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for your review |
||||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("ref"), "ref is not supported")) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should match the json field There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @liggitt ok |
||||||||
} | ||||||||
|
||||||||
if schema.Type == "null" { | ||||||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("type"), "type cannot be set to null")) | ||||||||
} | ||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,9 +24,6 @@ import ( | |
"sync/atomic" | ||
"time" | ||
|
||
openapispec "github.com/go-openapi/spec" | ||
"github.com/go-openapi/strfmt" | ||
"github.com/go-openapi/validate" | ||
"github.com/golang/glog" | ||
|
||
apiequality "k8s.io/apimachinery/pkg/api/equality" | ||
|
@@ -313,13 +310,13 @@ func (r *crdHandler) removeDeadStorage() { | |
} | ||
|
||
// GetCustomResourceListerCollectionDeleter returns the ListerCollectionDeleter for | ||
// the given uid, or nil if one does not exist. | ||
func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions.CustomResourceDefinition) finalizer.ListerCollectionDeleter { | ||
// the given uid, or nil if an error occurs. | ||
func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions.CustomResourceDefinition) (finalizer.ListerCollectionDeleter, error) { | ||
info, err := r.getOrCreateServingInfoFor(crd) | ||
if err != nil { | ||
utilruntime.HandleError(err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be better to make the caller handle the error? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's what this is doing now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for your review, but I think that an accurate description maybe better for k8s user to find the root cause. i.e. could not list instances: unable to find a custom resource client for xxx.yyy due to zzz |
||
return nil, err | ||
} | ||
return info.storage | ||
return info.storage, nil | ||
} | ||
|
||
func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResourceDefinition) (*crdInfo, error) { | ||
|
@@ -354,15 +351,10 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource | |
} | ||
creator := unstructuredCreator{} | ||
|
||
// convert CRD schema to openapi schema | ||
openapiSchema := &openapispec.Schema{} | ||
if err := apiservervalidation.ConvertToOpenAPITypes(crd, openapiSchema); err != nil { | ||
return nil, err | ||
} | ||
if err := openapispec.ExpandSchema(openapiSchema, nil, nil); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we sure this is only about expanding refs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sttts |
||
validator, err := apiservervalidation.NewSchemaValidator(crd.Spec.Validation) | ||
if err != nil { | ||
return nil, err | ||
} | ||
validator := validate.NewSchemaValidator(openapiSchema, nil, "", strfmt.Default) | ||
|
||
storage := customresource.NewREST( | ||
schema.GroupResource{Group: crd.Spec.Group, Resource: crd.Status.AcceptedNames.Plural}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,7 +65,7 @@ type ListerCollectionDeleter interface { | |
type CRClientGetter interface { | ||
// GetCustomResourceListerCollectionDeleter gets the ListerCollectionDeleter for the given CRD | ||
// UID. | ||
GetCustomResourceListerCollectionDeleter(crd *apiextensions.CustomResourceDefinition) ListerCollectionDeleter | ||
GetCustomResourceListerCollectionDeleter(crd *apiextensions.CustomResourceDefinition) (ListerCollectionDeleter, error) | ||
} | ||
|
||
// NewCRDFinalizer creates a new CRDFinalizer. | ||
|
@@ -155,9 +155,9 @@ func (c *CRDFinalizer) deleteInstances(crd *apiextensions.CustomResourceDefiniti | |
// Now we can start deleting items. While it would be ideal to use a REST API client, doing so | ||
// could incorrectly delete a ThirdPartyResource with the same URL as the CustomResource, so we go | ||
// directly to the storage instead. Since we control the storage, we know that delete collection works. | ||
crClient := c.crClientGetter.GetCustomResourceListerCollectionDeleter(crd) | ||
if crClient == nil { | ||
err := fmt.Errorf("unable to find a custom resource client for %s.%s", crd.Status.AcceptedNames.Plural, crd.Spec.Group) | ||
crClient, err := c.crClientGetter.GetCustomResourceListerCollectionDeleter(crd) | ||
if err != nil { | ||
err = fmt.Errorf("unable to find a custom resource client for %s.%s due to %v", crd.Status.AcceptedNames.Plural, crd.Spec.Group, err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are right. |
||
return apiextensions.CustomResourceDefinitionCondition{ | ||
Type: apiextensions.Terminating, | ||
Status: apiextensions.ConditionTrue, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong child string. I guess we do not need any child at all here.