// GetSubresourcesForVersion returns the subresources for given version or nil.
func GetSubresourcesForVersion(crd *apiextensionsv1.CustomResourceDefinition, version string) (*apiextensionsv1.CustomResourceSubresources, error) {
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return v.Subresources, nil
		}
	}
	return nil, fmt.Errorf("version %s not found in apiextensionsv1.CustomResourceDefinition: %v", version, crd.Name)
}


// HasPerVersionSchema returns true if a CRD uses per-version schema.
func HasPerVersionSchema(versions []apiextensionsv1.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Schema != nil {
			return true
		}
	}
	return false
}


// HasPerVersionSubresources returns true if a CRD uses per-version subresources.
func HasPerVersionSubresources(versions []apiextensionsv1.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Subresources != nil {
			return true
		}
	}
	return false
}


// HasPerVersionColumns returns true if a CRD uses per-version columns.
func HasPerVersionColumns(versions []apiextensionsv1.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if len(v.AdditionalPrinterColumns) > 0 {
			return true
		}
	}
	return false
}


// HasVersionServed returns true if given CRD has given version served.
func HasVersionServed(crd *apiextensionsv1.CustomResourceDefinition, version string) bool {
	for _, v := range crd.Spec.Versions {
		if !v.Served || v.Name != version {
			continue
		}
		return true
	}
	return false
}


// TODO: Update this after a tag is created for interface fields in DeepCopy
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
	if in == nil {
		return nil
	}
	out := new(JSONSchemaProps)

	*out = *in

	if in.Default != nil {
		defaultJSON := JSON(runtime.DeepCopyJSONValue(*(in.Default)))
		out.Default = &(defaultJSON)
	} else {
		out.Default = nil
	}

	if in.Example != nil {
		exampleJSON := JSON(runtime.DeepCopyJSONValue(*(in.Example)))
		out.Example = &(exampleJSON)
	} else {
		out.Example = nil
	}

	if in.Ref != nil {
		in, out := &in.Ref, &out.Ref
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.Maximum != nil {
		in, out := &in.Maximum, &out.Maximum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.Minimum != nil {
		in, out := &in.Minimum, &out.Minimum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxLength != nil {
		in, out := &in.MaxLength, &out.MaxLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinLength != nil {
		in, out := &in.MinLength, &out.MinLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}
	if in.MaxItems != nil {
		in, out := &in.MaxItems, &out.MaxItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinItems != nil {
		in, out := &in.MinItems, &out.MinItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MultipleOf != nil {
		in, out := &in.MultipleOf, &out.MultipleOf
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.Enum != nil {
		out.Enum = make([]JSON, len(in.Enum))
		for i := range in.Enum {
			out.Enum[i] = runtime.DeepCopyJSONValue(in.Enum[i])
		}
	}

	if in.MaxProperties != nil {
		in, out := &in.MaxProperties, &out.MaxProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinProperties != nil {
		in, out := &in.MinProperties, &out.MinProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.Required != nil {
		in, out := &in.Required, &out.Required
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.Items != nil {
		in, out := &in.Items, &out.Items
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrArray)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.AllOf != nil {
		in, out := &in.AllOf, &out.AllOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.OneOf != nil {
		in, out := &in.OneOf, &out.OneOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.AnyOf != nil {
		in, out := &in.AnyOf, &out.AnyOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.Not != nil {
		in, out := &in.Not, &out.Not
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaProps)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Properties != nil {
		in, out := &in.Properties, &out.Properties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalProperties != nil {
		in, out := &in.AdditionalProperties, &out.AdditionalProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.PatternProperties != nil {
		in, out := &in.PatternProperties, &out.PatternProperties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.Dependencies != nil {
		in, out := &in.Dependencies, &out.Dependencies
		*out = make(JSONSchemaDependencies, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalItems != nil {
		in, out := &in.AdditionalItems, &out.AdditionalItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Definitions != nil {
		in, out := &in.Definitions, &out.Definitions
		*out = make(JSONSchemaDefinitions, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.ExternalDocs != nil {
		in, out := &in.ExternalDocs, &out.ExternalDocs
		if *in == nil {
			*out = nil
		} else {
			*out = new(ExternalDocumentation)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.XPreserveUnknownFields != nil {
		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
		if *in == nil {
			*out = nil
		} else {
			*out = new(bool)
			**out = **in
		}
	}

	if in.XListMapKeys != nil {
		in, out := &in.XListMapKeys, &out.XListMapKeys
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.XListType != nil {
		in, out := &in.XListType, &out.XListType
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.XMapType != nil {
		in, out := &in.XMapType, &out.XMapType
		*out = new(string)
		**out = **in
	}

	if in.XValidations != nil {
		in, out := &in.XValidations, &out.XValidations
		*out = make([]ValidationRule, len(*in))
		copy(*out, *in)
	}

	return out
}


// Funcs returns the fuzzer functions for the apiextensions apis.
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
	return []interface{}{
		func(obj *apiextensions.CustomResourceDefinitionSpec, c fuzz.Continue) {
			c.FuzzNoCustom(obj)

			// match our defaulter
			if len(obj.Scope) == 0 {
				obj.Scope = apiextensions.NamespaceScoped
			}
			if len(obj.Names.Singular) == 0 {
				obj.Names.Singular = strings.ToLower(obj.Names.Kind)
			}
			if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
				obj.Names.ListKind = obj.Names.Kind + "List"
			}
			if len(obj.Versions) == 0 && len(obj.Version) == 0 {
				// internal object must have a version to roundtrip all fields
				obj.Version = "v1"
			}
			if len(obj.Versions) == 0 && len(obj.Version) != 0 {
				obj.Versions = []apiextensions.CustomResourceDefinitionVersion{
					{
						Name:    obj.Version,
						Served:  true,
						Storage: true,
					},
				}
			} else if len(obj.Versions) != 0 {
				obj.Version = obj.Versions[0].Name
			}
			if len(obj.AdditionalPrinterColumns) == 0 {
				obj.AdditionalPrinterColumns = []apiextensions.CustomResourceColumnDefinition{
					{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
				}
			}
			if obj.Conversion == nil {
				obj.Conversion = &apiextensions.CustomResourceConversion{
					Strategy: apiextensions.NoneConverter,
				}
			}
			if obj.Conversion.Strategy == apiextensions.WebhookConverter && len(obj.Conversion.ConversionReviewVersions) == 0 {
				obj.Conversion.ConversionReviewVersions = []string{"v1beta1"}
			}
			if obj.PreserveUnknownFields == nil {
				obj.PreserveUnknownFields = pointer.BoolPtr(true)
			}

			// Move per-version schema, subresources, additionalPrinterColumns to the top-level.
			// This is required by validation in v1beta1, and by round-tripping in v1.
			if len(obj.Versions) == 1 {
				if obj.Versions[0].Schema != nil {
					obj.Validation = obj.Versions[0].Schema
					obj.Versions[0].Schema = nil
				}
				if obj.Versions[0].AdditionalPrinterColumns != nil {
					obj.AdditionalPrinterColumns = obj.Versions[0].AdditionalPrinterColumns
					obj.Versions[0].AdditionalPrinterColumns = nil
				}
				if obj.Versions[0].Subresources != nil {
					obj.Subresources = obj.Versions[0].Subresources
					obj.Versions[0].Subresources = nil
				}
			}
		},
		func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) {
			c.FuzzNoCustom(obj)

			if len(obj.Status.StoredVersions) == 0 {
				for _, v := range obj.Spec.Versions {
					if v.Storage && !apiextensions.IsStoredVersion(obj, v.Name) {
						obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
					}
				}
			}
		},
		func(obj *apiextensions.JSONSchemaProps, c fuzz.Continue) {
			// we cannot use c.FuzzNoCustom because of the interface{} fields. So let's loop with reflection.
			vobj := reflect.ValueOf(obj).Elem()
			tobj := reflect.TypeOf(obj).Elem()
			for i := 0; i < tobj.NumField(); i++ {
				field := tobj.Field(i)
				switch field.Name {
				case "Default", "Enum", "Example", "Ref":
					continue
				default:
					isValue := true
					switch field.Type.Kind() {
					case reflect.Interface, reflect.Map, reflect.Slice, reflect.Pointer:
						isValue = false
					}
					if isValue || c.Intn(10) == 0 {
						c.Fuzz(vobj.Field(i).Addr().Interface())
					}
				}
			}
			if c.RandBool() {
				validJSON := apiextensions.JSON(`{"some": {"json": "test"}, "string": 42}`)
				obj.Default = &validJSON
			}
			if c.RandBool() {
				obj.Enum = []apiextensions.JSON{c.Float64(), c.RandString(), c.RandBool()}
			}
			if c.RandBool() {
				validJSON := apiextensions.JSON(`"foobarbaz"`)
				obj.Example = &validJSON
			}
			if c.RandBool() {
				validRef := "validRef"
				obj.Ref = &validRef
			}
			if len(obj.Type) == 0 {
				obj.Nullable = false // because this does not roundtrip through go-openapi
			}
			if obj.XIntOrString {
				obj.Type = ""
			}
		},
		func(obj *apiextensions.JSONSchemaPropsOrBool, c fuzz.Continue) {
			if c.RandBool() {
				obj.Allows = true
				obj.Schema = &apiextensions.JSONSchemaProps{}
				c.Fuzz(obj.Schema)
			} else {
				obj.Allows = c.RandBool()
			}
		},
		func(obj *apiextensions.JSONSchemaPropsOrArray, c fuzz.Continue) {
			// disallow both Schema and JSONSchemas to be nil.
			if c.RandBool() {
				obj.Schema = &apiextensions.JSONSchemaProps{}
				c.Fuzz(obj.Schema)
			} else {
				obj.JSONSchemas = make([]apiextensions.JSONSchemaProps, c.Intn(3)+1)
				for i := range obj.JSONSchemas {
					c.Fuzz(&obj.JSONSchemas[i])
				}
			}
		},
		func(obj *apiextensions.JSONSchemaPropsOrStringArray, c fuzz.Continue) {
			if c.RandBool() {
				obj.Schema = &apiextensions.JSONSchemaProps{}
				c.Fuzz(obj.Schema)
			} else {
				c.Fuzz(&obj.Property)
			}
		},
		func(obj *int64, c fuzz.Continue) {
			// JSON only supports 53 bits because everything is a float
			*obj = int64(c.Uint64()) & ((int64(1) << 53) - 1)
		},
	}
}


// SetCRDCondition sets the status condition. It either overwrites the existing one or creates a new one.
func SetCRDCondition(crd *CustomResourceDefinition, newCondition CustomResourceDefinitionCondition) {
	newCondition.LastTransitionTime = metav1.NewTime(time.Now())

	existingCondition := FindCRDCondition(crd, newCondition.Type)
	if existingCondition == nil {
		crd.Status.Conditions = append(crd.Status.Conditions, newCondition)
		return
	}

	if existingCondition.Status != newCondition.Status || existingCondition.LastTransitionTime.IsZero() {
		existingCondition.LastTransitionTime = newCondition.LastTransitionTime
	}

	existingCondition.Status = newCondition.Status
	existingCondition.Reason = newCondition.Reason
	existingCondition.Message = newCondition.Message
}


// RemoveCRDCondition removes the status condition.
func RemoveCRDCondition(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) {
	newConditions := []CustomResourceDefinitionCondition{}
	for _, condition := range crd.Status.Conditions {
		if condition.Type != conditionType {
			newConditions = append(newConditions, condition)
		}
	}
	crd.Status.Conditions = newConditions
}


// FindCRDCondition returns the condition you're looking for or nil.
func FindCRDCondition(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) *CustomResourceDefinitionCondition {
	for i := range crd.Status.Conditions {
		if crd.Status.Conditions[i].Type == conditionType {
			return &crd.Status.Conditions[i]
		}
	}

	return nil
}


// IsCRDConditionTrue indicates if the condition is present and strictly true.
func IsCRDConditionTrue(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) bool {
	return IsCRDConditionPresentAndEqual(crd, conditionType, ConditionTrue)
}


// IsCRDConditionFalse indicates if the condition is present and false.
func IsCRDConditionFalse(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) bool {
	return IsCRDConditionPresentAndEqual(crd, conditionType, ConditionFalse)
}


// IsCRDConditionPresentAndEqual indicates if the condition is present and equal to the given status.
func IsCRDConditionPresentAndEqual(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType, status ConditionStatus) bool {
	for _, condition := range crd.Status.Conditions {
		if condition.Type == conditionType {
			return condition.Status == status
		}
	}
	return false
}


// IsCRDConditionEquivalent returns true if the lhs and rhs are equivalent except for times.
func IsCRDConditionEquivalent(lhs, rhs *CustomResourceDefinitionCondition) bool {
	if lhs == nil && rhs == nil {
		return true
	}
	if lhs == nil || rhs == nil {
		return false
	}

	return lhs.Message == rhs.Message && lhs.Reason == rhs.Reason && lhs.Status == rhs.Status && lhs.Type == rhs.Type
}


// CRDHasFinalizer returns true if the finalizer is in the list.
func CRDHasFinalizer(crd *CustomResourceDefinition, needle string) bool {
	for _, finalizer := range crd.Finalizers {
		if finalizer == needle {
			return true
		}
	}

	return false
}


// CRDRemoveFinalizer removes the finalizer if present.
func CRDRemoveFinalizer(crd *CustomResourceDefinition, needle string) {
	newFinalizers := []string{}
	for _, finalizer := range crd.Finalizers {
		if finalizer != needle {
			newFinalizers = append(newFinalizers, finalizer)
		}
	}
	crd.Finalizers = newFinalizers
}


// HasServedCRDVersion returns true if the given version is in the list of CRD's versions and the Served flag is set.
func HasServedCRDVersion(crd *CustomResourceDefinition, version string) bool {
	for _, v := range crd.Spec.Versions {
		if v.Name == version {
			return v.Served
		}
	}
	return false
}


// GetCRDStorageVersion returns the storage version for given CRD.
func GetCRDStorageVersion(crd *CustomResourceDefinition) (string, error) {
	for _, v := range crd.Spec.Versions {
		if v.Storage {
			return v.Name, nil
		}
	}
	// This should not happened if crd is valid
	return "", fmt.Errorf("invalid CustomResourceDefinition, no storage version")
}


// IsStoredVersion returns whether the given version is the storage version of the CRD.
func IsStoredVersion(crd *CustomResourceDefinition, version string) bool {
	for _, v := range crd.Status.StoredVersions {
		if version == v {
			return true
		}
	}
	return false
}


// GetSchemaForVersion returns the validation schema for the given version or nil.
func GetSchemaForVersion(crd *CustomResourceDefinition, version string) (*CustomResourceValidation, error) {
	if !HasPerVersionSchema(crd.Spec.Versions) {
		return crd.Spec.Validation, nil
	}
	if crd.Spec.Validation != nil {
		return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version schemas must be mutual exclusive", crd.Name, version)
	}
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return v.Schema, nil
		}
	}
	return nil, fmt.Errorf("version %s not found in CustomResourceDefinition: %v", version, crd.Name)
}


// GetSubresourcesForVersion returns the subresources for given version or nil.
func GetSubresourcesForVersion(crd *CustomResourceDefinition, version string) (*CustomResourceSubresources, error) {
	if !HasPerVersionSubresources(crd.Spec.Versions) {
		return crd.Spec.Subresources, nil
	}
	if crd.Spec.Subresources != nil {
		return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version subresources must be mutual exclusive", crd.Name, version)
	}
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return v.Subresources, nil
		}
	}
	return nil, fmt.Errorf("version %s not found in CustomResourceDefinition: %v", version, crd.Name)
}


// GetColumnsForVersion returns the columns for given version or nil.
// NOTE: the newly logically-defaulted columns is not pointing to the original CRD object.
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
// the original CRD object instead.
func GetColumnsForVersion(crd *CustomResourceDefinition, version string) ([]CustomResourceColumnDefinition, error) {
	if !HasPerVersionColumns(crd.Spec.Versions) {
		return serveDefaultColumnsIfEmpty(crd.Spec.AdditionalPrinterColumns), nil
	}
	if len(crd.Spec.AdditionalPrinterColumns) > 0 {
		return nil, fmt.Errorf("malformed CustomResourceDefinition %s version %s: top-level and per-version additionalPrinterColumns must be mutual exclusive", crd.Name, version)
	}
	for _, v := range crd.Spec.Versions {
		if version == v.Name {
			return serveDefaultColumnsIfEmpty(v.AdditionalPrinterColumns), nil
		}
	}
	return nil, fmt.Errorf("version %s not found in CustomResourceDefinition: %v", version, crd.Name)
}


// HasPerVersionSchema returns true if a CRD uses per-version schema.
func HasPerVersionSchema(versions []CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Schema != nil {
			return true
		}
	}
	return false
}


// HasPerVersionSubresources returns true if a CRD uses per-version subresources.
func HasPerVersionSubresources(versions []CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Subresources != nil {
			return true
		}
	}
	return false
}


// HasPerVersionColumns returns true if a CRD uses per-version columns.
func HasPerVersionColumns(versions []CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if len(v.AdditionalPrinterColumns) > 0 {
			return true
		}
	}
	return false
}


// serveDefaultColumnsIfEmpty applies logically defaulting to columns, if the input columns is empty.
// NOTE: in this way, the newly logically-defaulted columns is not pointing to the original CRD object.
// One cannot mutate the original CRD columns using the logically-defaulted columns. Please iterate through
// the original CRD object instead.
func serveDefaultColumnsIfEmpty(columns []CustomResourceColumnDefinition) []CustomResourceColumnDefinition {
	if len(columns) > 0 {
		return columns
	}
	return []CustomResourceColumnDefinition{
		{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
	}
}


// HasVersionServed returns true if given CRD has given version served.
func HasVersionServed(crd *CustomResourceDefinition, version string) bool {
	for _, v := range crd.Spec.Versions {
		if !v.Served || v.Name != version {
			continue
		}
		return true
	}
	return false
}


func Install(scheme *runtime.Scheme)

// Install registers the API group and adds types to a scheme
func Install(scheme *runtime.Scheme) {
	utilruntime.Must(apiextensions.AddToScheme(scheme))
	utilruntime.Must(v1beta1.AddToScheme(scheme))
	utilruntime.Must(v1.AddToScheme(scheme))
	utilruntime.Must(scheme.SetVersionPriority(v1.SchemeGroupVersion, v1beta1.SchemeGroupVersion))
}


func Kind(kind string) schema.GroupKind

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&CustomResourceDefinition{},
		&CustomResourceDefinitionList{},
	)
	return nil
}


func Convert_apiextensions_JSONSchemaProps_To_v1_JSONSchemaProps(in *apiextensions.JSONSchemaProps, out *JSONSchemaProps, s conversion.Scope) error {
	if err := autoConvert_apiextensions_JSONSchemaProps_To_v1_JSONSchemaProps(in, out, s); err != nil {
		return err
	}
	if in.Default != nil && *(in.Default) == nil {
		out.Default = nil
	}
	if in.Example != nil && *(in.Example) == nil {
		out.Example = nil
	}
	return nil
}


func Convert_apiextensions_JSON_To_v1_JSON(in *apiextensions.JSON, out *JSON, s conversion.Scope) error {
	raw, err := json.Marshal(*in)
	if err != nil {
		return err
	}
	if len(raw) == 0 || bytes.Equal(raw, nullLiteral) {
		// match JSON#UnmarshalJSON treatment of literal nulls
		out.Raw = nil
	} else {
		out.Raw = raw
	}
	return nil
}


func Convert_v1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s conversion.Scope) error {
	if in != nil {
		var i interface{}
		if len(in.Raw) > 0 && !bytes.Equal(in.Raw, nullLiteral) {
			if err := json.Unmarshal(in.Raw, &i); err != nil {
				return err
			}
		}
		*out = i
	} else {
		out = nil
	}
	return nil
}


func Convert_apiextensions_CustomResourceDefinitionSpec_To_v1_CustomResourceDefinitionSpec(in *apiextensions.CustomResourceDefinitionSpec, out *CustomResourceDefinitionSpec, s conversion.Scope) error {
	if err := autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1_CustomResourceDefinitionSpec(in, out, s); err != nil {
		return err
	}

	if len(out.Versions) == 0 && len(in.Version) > 0 {
		// no versions were specified, and a version name was specified
		out.Versions = []CustomResourceDefinitionVersion{{Name: in.Version, Served: true, Storage: true}}
	}

	// If spec.{subresources,validation,additionalPrinterColumns} exists, move to versions
	if in.Subresources != nil {
		subresources := &CustomResourceSubresources{}
		if err := Convert_apiextensions_CustomResourceSubresources_To_v1_CustomResourceSubresources(in.Subresources, subresources, s); err != nil {
			return err
		}
		for i := range out.Versions {
			out.Versions[i].Subresources = subresources
		}
	}
	if in.Validation != nil {
		schema := &CustomResourceValidation{}
		if err := Convert_apiextensions_CustomResourceValidation_To_v1_CustomResourceValidation(in.Validation, schema, s); err != nil {
			return err
		}
		for i := range out.Versions {
			out.Versions[i].Schema = schema
		}
	}
	if in.AdditionalPrinterColumns != nil {
		additionalPrinterColumns := make([]CustomResourceColumnDefinition, len(in.AdditionalPrinterColumns))
		for i := range in.AdditionalPrinterColumns {
			if err := Convert_apiextensions_CustomResourceColumnDefinition_To_v1_CustomResourceColumnDefinition(&in.AdditionalPrinterColumns[i], &additionalPrinterColumns[i], s); err != nil {
				return err
			}
		}
		for i := range out.Versions {
			out.Versions[i].AdditionalPrinterColumns = additionalPrinterColumns
		}
	}
	return nil
}


func Convert_v1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in *CustomResourceDefinitionSpec, out *apiextensions.CustomResourceDefinitionSpec, s conversion.Scope) error {
	if err := autoConvert_v1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in, out, s); err != nil {
		return err
	}

	if len(out.Versions) == 0 {
		return nil
	}

	// Copy versions[0] to version
	out.Version = out.Versions[0].Name

	// If versions[*].{subresources,schema,additionalPrinterColumns} are identical, move to spec
	subresources := out.Versions[0].Subresources
	subresourcesIdentical := true
	validation := out.Versions[0].Schema
	validationIdentical := true
	additionalPrinterColumns := out.Versions[0].AdditionalPrinterColumns
	additionalPrinterColumnsIdentical := true

	// Detect if per-version fields are identical
	for _, v := range out.Versions {
		if subresourcesIdentical && !apiequality.Semantic.DeepEqual(v.Subresources, subresources) {
			subresourcesIdentical = false
		}
		if validationIdentical && !apiequality.Semantic.DeepEqual(v.Schema, validation) {
			validationIdentical = false
		}
		if additionalPrinterColumnsIdentical && !apiequality.Semantic.DeepEqual(v.AdditionalPrinterColumns, additionalPrinterColumns) {
			additionalPrinterColumnsIdentical = false
		}
	}

	// If they are, set the top-level fields and clear the per-version fields
	if subresourcesIdentical {
		out.Subresources = subresources
	}
	if validationIdentical {
		out.Validation = validation
	}
	if additionalPrinterColumnsIdentical {
		out.AdditionalPrinterColumns = additionalPrinterColumns
	}
	for i := range out.Versions {
		if subresourcesIdentical {
			out.Versions[i].Subresources = nil
		}
		if validationIdentical {
			out.Versions[i].Schema = nil
		}
		if additionalPrinterColumnsIdentical {
			out.Versions[i].AdditionalPrinterColumns = nil
		}
	}

	return nil
}


func Convert_v1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in *CustomResourceConversion, out *apiextensions.CustomResourceConversion, s conversion.Scope) error {
	if err := autoConvert_v1_CustomResourceConversion_To_apiextensions_CustomResourceConversion(in, out, s); err != nil {
		return err
	}

	out.WebhookClientConfig = nil
	out.ConversionReviewVersions = nil
	if in.Webhook != nil {
		out.ConversionReviewVersions = in.Webhook.ConversionReviewVersions
		if in.Webhook.ClientConfig != nil {
			out.WebhookClientConfig = &apiextensions.WebhookClientConfig{}
			if err := Convert_v1_WebhookClientConfig_To_apiextensions_WebhookClientConfig(in.Webhook.ClientConfig, out.WebhookClientConfig, s); err != nil {
				return err
			}
		}
	}
	return nil
}


func Convert_apiextensions_CustomResourceConversion_To_v1_CustomResourceConversion(in *apiextensions.CustomResourceConversion, out *CustomResourceConversion, s conversion.Scope) error {
	if err := autoConvert_apiextensions_CustomResourceConversion_To_v1_CustomResourceConversion(in, out, s); err != nil {
		return err
	}

	out.Webhook = nil
	if in.WebhookClientConfig != nil || in.ConversionReviewVersions != nil {
		out.Webhook = &WebhookConversion{}
		out.Webhook.ConversionReviewVersions = in.ConversionReviewVersions
		if in.WebhookClientConfig != nil {
			out.Webhook.ClientConfig = &WebhookClientConfig{}
			if err := Convert_apiextensions_WebhookClientConfig_To_v1_WebhookClientConfig(in.WebhookClientConfig, out.Webhook.ClientConfig, s); err != nil {
				return err
			}
		}
	}
	return nil
}


func Convert_apiextensions_ValidationRules_To_v1_ValidationRules(in *apiextensions.ValidationRules, out *ValidationRules, s conversion.Scope) error {
	*out = *(*ValidationRules)(unsafe.Pointer(in))
	return nil
}


// TODO: Update this after a tag is created for interface fields in DeepCopy
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
	if in == nil {
		return nil
	}
	out := new(JSONSchemaProps)
	*out = *in

	if in.Ref != nil {
		in, out := &in.Ref, &out.Ref
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.Maximum != nil {
		in, out := &in.Maximum, &out.Maximum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.Minimum != nil {
		in, out := &in.Minimum, &out.Minimum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxLength != nil {
		in, out := &in.MaxLength, &out.MaxLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinLength != nil {
		in, out := &in.MinLength, &out.MinLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}
	if in.MaxItems != nil {
		in, out := &in.MaxItems, &out.MaxItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinItems != nil {
		in, out := &in.MinItems, &out.MinItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MultipleOf != nil {
		in, out := &in.MultipleOf, &out.MultipleOf
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxProperties != nil {
		in, out := &in.MaxProperties, &out.MaxProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinProperties != nil {
		in, out := &in.MinProperties, &out.MinProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.Required != nil {
		in, out := &in.Required, &out.Required
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.Items != nil {
		in, out := &in.Items, &out.Items
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrArray)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.AllOf != nil {
		in, out := &in.AllOf, &out.AllOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.OneOf != nil {
		in, out := &in.OneOf, &out.OneOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.AnyOf != nil {
		in, out := &in.AnyOf, &out.AnyOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.Not != nil {
		in, out := &in.Not, &out.Not
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaProps)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Properties != nil {
		in, out := &in.Properties, &out.Properties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalProperties != nil {
		in, out := &in.AdditionalProperties, &out.AdditionalProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.PatternProperties != nil {
		in, out := &in.PatternProperties, &out.PatternProperties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.Dependencies != nil {
		in, out := &in.Dependencies, &out.Dependencies
		*out = make(JSONSchemaDependencies, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalItems != nil {
		in, out := &in.AdditionalItems, &out.AdditionalItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Definitions != nil {
		in, out := &in.Definitions, &out.Definitions
		*out = make(JSONSchemaDefinitions, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.ExternalDocs != nil {
		in, out := &in.ExternalDocs, &out.ExternalDocs
		if *in == nil {
			*out = nil
		} else {
			*out = new(ExternalDocumentation)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.XPreserveUnknownFields != nil {
		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
		if *in == nil {
			*out = nil
		} else {
			*out = new(bool)
			**out = **in
		}
	}

	if in.XMapType != nil {
		in, out := &in.XMapType, &out.XMapType
		*out = new(string)
		**out = **in
	}

	if in.XValidations != nil {
		in, out := &in.XValidations, &out.XValidations
		*out = make([]ValidationRule, len(*in))
		copy(*out, *in)
	}

	return out
}


func addDefaultingFuncs(scheme *runtime.Scheme) error {
	return RegisterDefaults(scheme)
}


func SetDefaults_CustomResourceDefinition(obj *CustomResourceDefinition) {
	SetDefaults_CustomResourceDefinitionSpec(&obj.Spec)
	if len(obj.Status.StoredVersions) == 0 {
		for _, v := range obj.Spec.Versions {
			if v.Storage {
				obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
				break
			}
		}
	}
}


func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) {
	if len(obj.Names.Singular) == 0 {
		obj.Names.Singular = strings.ToLower(obj.Names.Kind)
	}
	if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
		obj.Names.ListKind = obj.Names.Kind + "List"
	}
	if obj.Conversion == nil {
		obj.Conversion = &CustomResourceConversion{
			Strategy: NoneConverter,
		}
	}
}


// SetDefaults_ServiceReference sets defaults for Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *ServiceReference) {
	if obj.Port == nil {
		obj.Port = utilpointer.Int32Ptr(443)
	}
}


func (s JSONSchemaPropsOrBool) MarshalJSON() ([]byte, error) {
	if s.Schema != nil {
		return json.Marshal(s.Schema)
	}

	if s.Schema == nil && !s.Allows {
		return jsFalse, nil
	}
	return jsTrue, nil
}


func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
	var nw JSONSchemaPropsOrBool
	switch {
	case len(data) == 0:
	case data[0] == '{':
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Allows = true
		nw.Schema = &sch
	case len(data) == 4 && string(data) == "true":
		nw.Allows = true
	case len(data) == 5 && string(data) == "false":
		nw.Allows = false
	default:
		return errors.New("boolean or JSON schema expected")
	}
	*s = nw
	return nil
}


func (s JSONSchemaPropsOrStringArray) MarshalJSON() ([]byte, error) {
	if len(s.Property) > 0 {
		return json.Marshal(s.Property)
	}
	if s.Schema != nil {
		return json.Marshal(s.Schema)
	}
	return []byte("null"), nil
}


func (s *JSONSchemaPropsOrStringArray) UnmarshalJSON(data []byte) error {
	var first byte
	if len(data) > 1 {
		first = data[0]
	}
	var nw JSONSchemaPropsOrStringArray
	if first == '{' {
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Schema = &sch
	}
	if first == '[' {
		if err := json.Unmarshal(data, &nw.Property); err != nil {
			return err
		}
	}
	*s = nw
	return nil
}


func (s JSONSchemaPropsOrArray) MarshalJSON() ([]byte, error) {
	if len(s.JSONSchemas) > 0 {
		return json.Marshal(s.JSONSchemas)
	}
	return json.Marshal(s.Schema)
}


func (s *JSONSchemaPropsOrArray) UnmarshalJSON(data []byte) error {
	var nw JSONSchemaPropsOrArray
	var first byte
	if len(data) > 1 {
		first = data[0]
	}
	if first == '{' {
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Schema = &sch
	}
	if first == '[' {
		if err := json.Unmarshal(data, &nw.JSONSchemas); err != nil {
			return err
		}
	}
	*s = nw
	return nil
}


func (s JSON) MarshalJSON() ([]byte, error) {
	if len(s.Raw) > 0 {
		return s.Raw, nil
	}
	return []byte("null"), nil

}


func (s *JSON) UnmarshalJSON(data []byte) error {
	if len(data) > 0 && !bytes.Equal(data, nullLiteral) {
		s.Raw = data
	}
	return nil
}


// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&CustomResourceDefinition{},
		&CustomResourceDefinitionList{},
		&ConversionReview{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


func init()

func init() {
	// We only register manually written functions here. The registration of the
	// generated functions takes place in the generated files. The separation
	// makes the code compile even when the generated files are missing.
	localSchemeBuilder.Register(addDefaultingFuncs)
}


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSON) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSON) OpenAPISchemaFormat() string { return "" }


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" }


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" }


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" }


func Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(in *apiextensions.JSONSchemaProps, out *JSONSchemaProps, s conversion.Scope) error {
	if err := autoConvert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(in, out, s); err != nil {
		return err
	}
	if in.Default != nil && *(in.Default) == nil {
		out.Default = nil
	}
	if in.Example != nil && *(in.Example) == nil {
		out.Example = nil
	}
	return nil
}


func Convert_apiextensions_JSON_To_v1beta1_JSON(in *apiextensions.JSON, out *JSON, s conversion.Scope) error {
	raw, err := json.Marshal(*in)
	if err != nil {
		return err
	}
	if len(raw) == 0 || bytes.Equal(raw, nullLiteral) {
		// match JSON#UnmarshalJSON treatment of literal nulls
		out.Raw = nil
	} else {
		out.Raw = raw
	}
	return nil
}


func Convert_v1beta1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s conversion.Scope) error {
	if in != nil {
		var i interface{}
		if len(in.Raw) > 0 && !bytes.Equal(in.Raw, nullLiteral) {
			if err := json.Unmarshal(in.Raw, &i); err != nil {
				return err
			}
		}
		*out = i
	} else {
		out = nil
	}
	return nil
}


// TODO: Update this after a tag is created for interface fields in DeepCopy
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
	if in == nil {
		return nil
	}
	out := new(JSONSchemaProps)
	*out = *in

	if in.Ref != nil {
		in, out := &in.Ref, &out.Ref
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.Maximum != nil {
		in, out := &in.Maximum, &out.Maximum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.Minimum != nil {
		in, out := &in.Minimum, &out.Minimum
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxLength != nil {
		in, out := &in.MaxLength, &out.MaxLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinLength != nil {
		in, out := &in.MinLength, &out.MinLength
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}
	if in.MaxItems != nil {
		in, out := &in.MaxItems, &out.MaxItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinItems != nil {
		in, out := &in.MinItems, &out.MinItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MultipleOf != nil {
		in, out := &in.MultipleOf, &out.MultipleOf
		if *in == nil {
			*out = nil
		} else {
			*out = new(float64)
			**out = **in
		}
	}

	if in.MaxProperties != nil {
		in, out := &in.MaxProperties, &out.MaxProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.MinProperties != nil {
		in, out := &in.MinProperties, &out.MinProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(int64)
			**out = **in
		}
	}

	if in.Required != nil {
		in, out := &in.Required, &out.Required
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.Items != nil {
		in, out := &in.Items, &out.Items
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrArray)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.AllOf != nil {
		in, out := &in.AllOf, &out.AllOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.OneOf != nil {
		in, out := &in.OneOf, &out.OneOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}
	if in.AnyOf != nil {
		in, out := &in.AnyOf, &out.AnyOf
		*out = make([]JSONSchemaProps, len(*in))
		for i := range *in {
			(*in)[i].DeepCopyInto(&(*out)[i])
		}
	}

	if in.Not != nil {
		in, out := &in.Not, &out.Not
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaProps)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Properties != nil {
		in, out := &in.Properties, &out.Properties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalProperties != nil {
		in, out := &in.AdditionalProperties, &out.AdditionalProperties
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.PatternProperties != nil {
		in, out := &in.PatternProperties, &out.PatternProperties
		*out = make(map[string]JSONSchemaProps, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.Dependencies != nil {
		in, out := &in.Dependencies, &out.Dependencies
		*out = make(JSONSchemaDependencies, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.AdditionalItems != nil {
		in, out := &in.AdditionalItems, &out.AdditionalItems
		if *in == nil {
			*out = nil
		} else {
			*out = new(JSONSchemaPropsOrBool)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.Definitions != nil {
		in, out := &in.Definitions, &out.Definitions
		*out = make(JSONSchemaDefinitions, len(*in))
		for key, val := range *in {
			(*out)[key] = *val.DeepCopy()
		}
	}

	if in.ExternalDocs != nil {
		in, out := &in.ExternalDocs, &out.ExternalDocs
		if *in == nil {
			*out = nil
		} else {
			*out = new(ExternalDocumentation)
			(*in).DeepCopyInto(*out)
		}
	}

	if in.XPreserveUnknownFields != nil {
		in, out := &in.XPreserveUnknownFields, &out.XPreserveUnknownFields
		if *in == nil {
			*out = nil
		} else {
			*out = new(bool)
			**out = **in
		}
	}

	if in.XListMapKeys != nil {
		in, out := &in.XListMapKeys, &out.XListMapKeys
		*out = make([]string, len(*in))
		copy(*out, *in)
	}

	if in.XListType != nil {
		in, out := &in.XListType, &out.XListType
		if *in == nil {
			*out = nil
		} else {
			*out = new(string)
			**out = **in
		}
	}

	if in.XMapType != nil {
		in, out := &in.XMapType, &out.XMapType
		*out = new(string)
		**out = **in
	}

	if in.XValidations != nil {
		in, out := &in.XValidations, &out.XValidations
		*out = make([]ValidationRule, len(*in))
		copy(*out, *in)
	}

	return out
}


func addDefaultingFuncs(scheme *runtime.Scheme) error {
	return RegisterDefaults(scheme)
}


func SetDefaults_CustomResourceDefinition(obj *CustomResourceDefinition) {
	SetDefaults_CustomResourceDefinitionSpec(&obj.Spec)
	if len(obj.Status.StoredVersions) == 0 {
		for _, v := range obj.Spec.Versions {
			if v.Storage {
				obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
				break
			}
		}
	}
}


func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) {
	if len(obj.Scope) == 0 {
		obj.Scope = NamespaceScoped
	}
	if len(obj.Names.Singular) == 0 {
		obj.Names.Singular = strings.ToLower(obj.Names.Kind)
	}
	if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
		obj.Names.ListKind = obj.Names.Kind + "List"
	}
	// If there is no list of versions, create on using deprecated Version field.
	if len(obj.Versions) == 0 && len(obj.Version) != 0 {
		obj.Versions = []CustomResourceDefinitionVersion{{
			Name:    obj.Version,
			Storage: true,
			Served:  true,
		}}
	}
	// For backward compatibility set the version field to the first item in versions list.
	if len(obj.Version) == 0 && len(obj.Versions) != 0 {
		obj.Version = obj.Versions[0].Name
	}
	if obj.Conversion == nil {
		obj.Conversion = &CustomResourceConversion{
			Strategy: NoneConverter,
		}
	}
	if obj.Conversion.Strategy == WebhookConverter && len(obj.Conversion.ConversionReviewVersions) == 0 {
		obj.Conversion.ConversionReviewVersions = []string{SchemeGroupVersion.Version}
	}
	if obj.PreserveUnknownFields == nil {
		obj.PreserveUnknownFields = utilpointer.BoolPtr(true)
	}
}


// SetDefaults_ServiceReference sets defaults for Webhook's ServiceReference
func SetDefaults_ServiceReference(obj *ServiceReference) {
	if obj.Port == nil {
		obj.Port = utilpointer.Int32Ptr(443)
	}
}


func (s JSONSchemaPropsOrBool) MarshalJSON() ([]byte, error) {
	if s.Schema != nil {
		return json.Marshal(s.Schema)
	}

	if s.Schema == nil && !s.Allows {
		return jsFalse, nil
	}
	return jsTrue, nil
}


func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
	var nw JSONSchemaPropsOrBool
	switch {
	case len(data) == 0:
	case data[0] == '{':
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Allows = true
		nw.Schema = &sch
	case len(data) == 4 && string(data) == "true":
		nw.Allows = true
	case len(data) == 5 && string(data) == "false":
		nw.Allows = false
	default:
		return errors.New("boolean or JSON schema expected")
	}
	*s = nw
	return nil
}


func (s JSONSchemaPropsOrStringArray) MarshalJSON() ([]byte, error) {
	if len(s.Property) > 0 {
		return json.Marshal(s.Property)
	}
	if s.Schema != nil {
		return json.Marshal(s.Schema)
	}
	return []byte("null"), nil
}


func (s *JSONSchemaPropsOrStringArray) UnmarshalJSON(data []byte) error {
	var first byte
	if len(data) > 1 {
		first = data[0]
	}
	var nw JSONSchemaPropsOrStringArray
	if first == '{' {
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Schema = &sch
	}
	if first == '[' {
		if err := json.Unmarshal(data, &nw.Property); err != nil {
			return err
		}
	}
	*s = nw
	return nil
}


func (s JSONSchemaPropsOrArray) MarshalJSON() ([]byte, error) {
	if len(s.JSONSchemas) > 0 {
		return json.Marshal(s.JSONSchemas)
	}
	return json.Marshal(s.Schema)
}


func (s *JSONSchemaPropsOrArray) UnmarshalJSON(data []byte) error {
	var nw JSONSchemaPropsOrArray
	var first byte
	if len(data) > 1 {
		first = data[0]
	}
	if first == '{' {
		var sch JSONSchemaProps
		if err := json.Unmarshal(data, &sch); err != nil {
			return err
		}
		nw.Schema = &sch
	}
	if first == '[' {
		if err := json.Unmarshal(data, &nw.JSONSchemas); err != nil {
			return err
		}
	}
	*s = nw
	return nil
}


func (s JSON) MarshalJSON() ([]byte, error) {
	if len(s.Raw) > 0 {
		return s.Raw, nil
	}
	return []byte("null"), nil

}


func (s *JSON) UnmarshalJSON(data []byte) error {
	if len(data) > 0 && !bytes.Equal(data, nullLiteral) {
		s.Raw = data
	}
	return nil
}


func Kind(kind string) schema.GroupKind

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}


// Resource takes an unqualified resource and returns back a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}


// Adds the list of known types to the given scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
	scheme.AddKnownTypes(SchemeGroupVersion,
		&CustomResourceDefinition{},
		&CustomResourceDefinitionList{},
		&ConversionReview{},
	)
	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
	return nil
}


func init()

func init() {
	// We only register manually written functions here. The registration of the
	// generated functions takes place in the generated files. The separation
	// makes the code compile even when the generated files are missing.
	localSchemeBuilder.Register(addDefaultingFuncs)
}


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSON) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSON) OpenAPISchemaFormat() string { return "" }


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" }


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" }


// OpenAPISchemaType is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
//
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string {
	// TODO: return actual types when anyOf is supported
	return nil
}


// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
// the OpenAPI spec of this type.
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" }


// TypeInfo returns the CELTypeInfo for this CELSchemaContext node.  Returns nil, nil if this CELSchemaContext is nil,
// or if current level or above does not have x-kubernetes-validations rules. The returned type info is shared and
// should not be modified by the caller.
func (c *CELSchemaContext) TypeInfo() (*CELTypeInfo, error) {
	if c == nil || !c.withinValidationRuleScope {
		return nil, nil
	}
	if c.typeInfo != nil || c.typeInfoErr != nil {
		return c.typeInfo, c.typeInfoErr // return already computed result if available
	}

	// If able to get the type info from the parent's type info, prefer this approach
	// since it is more efficient.
	if c.parent != nil {
		parentTypeInfo, parentErr := c.parent.TypeInfo()
		if parentErr != nil {
			c.typeInfoErr = parentErr
			return nil, parentErr
		}
		if parentTypeInfo != nil && c.typeInfoAccessor != nil {
			c.typeInfo = c.typeInfoAccessor.accessTypeInfo(parentTypeInfo)
			if c.typeInfo != nil {
				return c.typeInfo, nil
			}
		}
	}
	// If unable to get the type info from the parent, convert the jsonSchema to type info.
	// This is expensive for large schemas.
	c.typeInfo, c.typeInfoErr = c.converter(c.jsonSchema, c.parent == nil || c.jsonSchema.XEmbeddedResource)
	return c.typeInfo, c.typeInfoErr
}


func defaultConverter(schema *apiextensions.JSONSchemaProps, isRoot bool) (*CELTypeInfo, error) {
	structural, err := structuralschema.NewStructural(schema)
	if err != nil {
		return nil, err
	}
	declType := model.SchemaDeclType(structural, isRoot)
	if declType == nil {
		return nil, fmt.Errorf("unable to convert structural schema to CEL declarations")
	}
	return &CELTypeInfo{structural, declType}, nil
}


// RootCELContext constructs CELSchemaContext for the given root schema.
func RootCELContext(schema *apiextensions.JSONSchemaProps) *CELSchemaContext {
	rootCardinality := uint64(1)
	r := &CELSchemaContext{
		jsonSchema:                schema,
		withinValidationRuleScope: len(schema.XValidations) > 0,
		MaxCardinality:            &rootCardinality,
		TotalCost:                 &TotalCost{},
		converter:                 defaultConverter,
	}
	return r
}


// ChildPropertyContext returns nil, nil if this CELSchemaContext is nil, otherwise constructs and returns a
// CELSchemaContext for propertyName.
func (c *CELSchemaContext) ChildPropertyContext(propSchema *apiextensions.JSONSchemaProps, propertyName string) *CELSchemaContext {
	if c == nil {
		return nil
	}
	return c.childContext(propSchema, propertyTypeInfoAccessor{propertyName: propertyName})
}


// ChildAdditionalPropertiesContext returns nil, nil if this CELSchemaContext is nil, otherwise it constructs and returns
// a CELSchemaContext for the properties of an object if this CELSchemaContext is an object.
// schema must be non-nil and have a non-nil schema.AdditionalProperties.
func (c *CELSchemaContext) ChildAdditionalPropertiesContext(propsSchema *apiextensions.JSONSchemaProps) *CELSchemaContext {
	if c == nil {
		return nil
	}
	return c.childContext(propsSchema, additionalItemsTypeInfoAccessor{})
}


// ChildItemsContext returns nil, nil if this CELSchemaContext is nil, otherwise it constructs and returns a CELSchemaContext
// for the items of an array if this CELSchemaContext is an array.
func (c *CELSchemaContext) ChildItemsContext(itemsSchema *apiextensions.JSONSchemaProps) *CELSchemaContext {
	if c == nil {
		return nil
	}
	return c.childContext(itemsSchema, itemsTypeInfoAccessor{})
}


// childContext returns nil, nil if this CELSchemaContext is nil, otherwise it constructs a new CELSchemaContext for the
// given child schema of the current schema context.
// accessor optionally provides a way to access CELTypeInfo of the child from the current schema context's CELTypeInfo.
// childContext returns a CELSchemaContext where the MaxCardinality is multiplied by the
// factor that the schema increases the cardinality of its children. If the CELSchemaContext's
// MaxCardinality is unbounded (nil) or the factor that the schema increase the cardinality
// is unbounded, the resulting CELSchemaContext's MaxCardinality is also unbounded.
func (c *CELSchemaContext) childContext(child *apiextensions.JSONSchemaProps, accessor typeInfoAccessor) *CELSchemaContext {
	result := &CELSchemaContext{
		parent:                    c,
		typeInfoAccessor:          accessor,
		withinValidationRuleScope: c.withinValidationRuleScope,
		TotalCost:                 c.TotalCost,
		MaxCardinality:            unbounded,
		converter:                 c.converter,
	}
	if child != nil {
		result.jsonSchema = child
		if len(child.XValidations) > 0 {
			result.withinValidationRuleScope = true
		}
	}
	if c.jsonSchema == nil {
		// nil schemas can be passed since we call ChildSchemaContext
		// before ValidateCustomResourceDefinitionOpenAPISchema performs its nil check
		return result
	}
	if c.MaxCardinality == unbounded {
		return result
	}
	maxElements := extractMaxElements(c.jsonSchema)
	if maxElements == unbounded {
		return result
	}
	result.MaxCardinality = uint64ptr(multiplyWithOverflowGuard(*c.MaxCardinality, *maxElements))
	return result
}


func (c propertyTypeInfoAccessor) accessTypeInfo(parentTypeInfo *CELTypeInfo) *CELTypeInfo {
	if parentTypeInfo.Schema.Properties != nil {
		propSchema := parentTypeInfo.Schema.Properties[c.propertyName]
		if escapedPropName, ok := cel.Escape(c.propertyName); ok {
			if fieldDeclType, ok := parentTypeInfo.DeclType.Fields[escapedPropName]; ok {
				return &CELTypeInfo{Schema: &propSchema, DeclType: fieldDeclType.Type}
			} // else fields with unknown types are omitted from CEL validation entirely
		} // fields with unescapable names are expected to be absent
	}
	return nil
}


func (c itemsTypeInfoAccessor) accessTypeInfo(parentTypeInfo *CELTypeInfo) *CELTypeInfo {
	if parentTypeInfo.Schema.Items != nil {
		itemsSchema := parentTypeInfo.Schema.Items
		itemsDeclType := parentTypeInfo.DeclType.ElemType
		return &CELTypeInfo{Schema: itemsSchema, DeclType: itemsDeclType}
	}
	return nil
}


func (c additionalItemsTypeInfoAccessor) accessTypeInfo(parentTypeInfo *CELTypeInfo) *CELTypeInfo {
	if parentTypeInfo.Schema.AdditionalProperties != nil {
		propsSchema := parentTypeInfo.Schema.AdditionalProperties.Structural
		valuesDeclType := parentTypeInfo.DeclType.ElemType
		return &CELTypeInfo{Schema: propsSchema, DeclType: valuesDeclType}
	}
	return nil
}


// ObserveExpressionCost accumulates the cost of evaluating a -kubernetes-validations rule.
func (c *TotalCost) ObserveExpressionCost(path *field.Path, cost uint64) {
	if math.MaxUint64-c.Total < cost {
		c.Total = math.MaxUint64
	} else {
		c.Total += cost
	}

	if cost < StaticEstimatedCRDCostLimit/100 { // ignore rules that contribute < 1% of total cost limit
		return
	}
	c.MostExpensive = append(c.MostExpensive, RuleCost{Path: path, Cost: cost})
	sort.Slice(c.MostExpensive, func(i, j int) bool {
		// sort in descending order so the most expensive rule is first
		return c.MostExpensive[i].Cost > c.MostExpensive[j].Cost
	})
	if len(c.MostExpensive) > 4 {
		c.MostExpensive = c.MostExpensive[:4]
	}
}


// extractMaxElements returns the factor by which the schema increases the cardinality
// (number of possible data elements) of its children.  If schema is a map and has
// MaxProperties or an array has MaxItems, the int pointer of the max value is returned.
// If schema is a map or array and does not have MaxProperties or MaxItems,
// unbounded (nil) is returned to indicate that there is no limit to the possible
// number of data elements imposed by the current schema.  If the schema is an object, 1 is
// returned to indicate that there is no increase to the number of possible data elements
// for its children.  Primitives do not have children, but 1 is returned for simplicity.
func extractMaxElements(schema *apiextensions.JSONSchemaProps) *uint64 {
	switch schema.Type {
	case "object":
		if schema.AdditionalProperties != nil {
			if schema.MaxProperties != nil {
				maxProps := uint64(zeroIfNegative(*schema.MaxProperties))
				return &maxProps
			}
			return unbounded
		}
		// return 1 to indicate that all fields of an object exist at most one for
		// each occurrence of the object they are fields of
		return uint64ptr(1)
	case "array":
		if schema.MaxItems != nil {
			maxItems := uint64(zeroIfNegative(*schema.MaxItems))
			return &maxItems
		}
		return unbounded
	default:
		return uint64ptr(1)
	}
}


func zeroIfNegative(v int64) int64

func zeroIfNegative(v int64) int64 {
	if v < 0 {
		return 0
	}
	return v
}


func uint64ptr(i uint64) *uint64

func uint64ptr(i uint64) *uint64 {
	return &i
}


// ValidateCustomResourceDefinition statically validates
// context is passed for supporting context cancellation during cel validation when validating defaults
func ValidateCustomResourceDefinition(ctx context.Context, obj *apiextensions.CustomResourceDefinition) field.ErrorList {
	nameValidationFn := func(name string, prefix bool) []string {
		ret := genericvalidation.NameIsDNSSubdomain(name, prefix)
		requiredName := obj.Spec.Names.Plural + "." + obj.Spec.Group
		if name != requiredName {
			ret = append(ret, fmt.Sprintf(`must be spec.names.plural+"."+spec.group`))
		}
		return ret
	}

	opts := validationOptions{
		allowDefaults:                            true,
		requireRecognizedConversionReviewVersion: true,
		requireImmutableNames:                    false,
		requireOpenAPISchema:                     true,
		requireValidPropertyType:                 true,
		requireStructuralSchema:                  true,
		requirePrunedDefaults:                    true,
		requireAtomicSetType:                     true,
		requireMapListKeysMapSetValidation:       true,
	}

	allErrs := genericvalidation.ValidateObjectMeta(&obj.ObjectMeta, false, nameValidationFn, field.NewPath("metadata"))
	allErrs = append(allErrs, validateCustomResourceDefinitionSpec(ctx, &obj.Spec, opts, field.NewPath("spec"))...)
	allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...)
	allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...)
	allErrs = append(allErrs, validateAPIApproval(obj, nil)...)
	allErrs = append(allErrs, validatePreserveUnknownFields(obj, nil)...)
	return allErrs
}


// ValidateCustomResourceDefinitionUpdate statically validates
// context is passed for supporting context cancellation during cel validation when validating defaults
func ValidateCustomResourceDefinitionUpdate(ctx context.Context, obj, oldObj *apiextensions.CustomResourceDefinition) field.ErrorList {
	opts := validationOptions{
		allowDefaults:                            true,
		requireRecognizedConversionReviewVersion: oldObj.Spec.Conversion == nil || hasValidConversionReviewVersionOrEmpty(oldObj.Spec.Conversion.ConversionReviewVersions),
		requireImmutableNames:                    apiextensions.IsCRDConditionTrue(oldObj, apiextensions.Established),
		requireOpenAPISchema:                     requireOpenAPISchema(&oldObj.Spec),
		requireValidPropertyType:                 requireValidPropertyType(&oldObj.Spec),
		requireStructuralSchema:                  requireStructuralSchema(&oldObj.Spec),
		requirePrunedDefaults:                    requirePrunedDefaults(&oldObj.Spec),
		requireAtomicSetType:                     requireAtomicSetType(&oldObj.Spec),
		requireMapListKeysMapSetValidation:       requireMapListKeysMapSetValidation(&oldObj.Spec),
	}

	allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata"))
	allErrs = append(allErrs, validateCustomResourceDefinitionSpecUpdate(ctx, &obj.Spec, &oldObj.Spec, opts, field.NewPath("spec"))...)
	allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...)
	allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...)
	allErrs = append(allErrs, validateAPIApproval(obj, oldObj)...)
	allErrs = append(allErrs, validatePreserveUnknownFields(obj, oldObj)...)
	return allErrs
}


// ValidateCustomResourceDefinitionStoredVersions statically validates
func ValidateCustomResourceDefinitionStoredVersions(storedVersions []string, versions []apiextensions.CustomResourceDefinitionVersion, fldPath *field.Path) field.ErrorList {
	if len(storedVersions) == 0 {
		return field.ErrorList{field.Invalid(fldPath, storedVersions, "must have at least one stored version")}
	}
	allErrs := field.ErrorList{}
	storedVersionsMap := map[string]int{}
	for i, v := range storedVersions {
		storedVersionsMap[v] = i
	}
	for _, v := range versions {
		_, ok := storedVersionsMap[v.Name]
		if v.Storage && !ok {
			allErrs = append(allErrs, field.Invalid(fldPath, v, "must have the storage version "+v.Name))
		}
		if ok {
			delete(storedVersionsMap, v.Name)
		}
	}

	for v, i := range storedVersionsMap {
		allErrs = append(allErrs, field.Invalid(fldPath.Index(i), v, "must appear in spec.versions"))
	}

	return allErrs
}


// ValidateUpdateCustomResourceDefinitionStatus statically validates
func ValidateUpdateCustomResourceDefinitionStatus(obj, oldObj *apiextensions.CustomResourceDefinition) field.ErrorList {
	allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata"))
	allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...)
	return allErrs
}


// validateCustomResourceDefinitionVersion statically validates.
// context is passed for supporting context cancellation during cel validation when validating defaults
func validateCustomResourceDefinitionVersion(ctx context.Context, version *apiextensions.CustomResourceDefinitionVersion, fldPath *field.Path, statusEnabled bool, opts validationOptions) field.ErrorList {
	allErrs := field.ErrorList{}
	for _, err := range validateDeprecationWarning(version.Deprecated, version.DeprecationWarning) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("deprecationWarning"), version.DeprecationWarning, err))
	}
	allErrs = append(allErrs, validateCustomResourceDefinitionValidation(ctx, version.Schema, statusEnabled, opts, fldPath.Child("schema"))...)
	allErrs = append(allErrs, ValidateCustomResourceDefinitionSubresources(version.Subresources, fldPath.Child("subresources"))...)
	for i := range version.AdditionalPrinterColumns {
		allErrs = append(allErrs, ValidateCustomResourceColumnDefinition(&version.AdditionalPrinterColumns[i], fldPath.Child("additionalPrinterColumns").Index(i))...)
	}
	return allErrs
}


func validateDeprecationWarning(deprecated bool, deprecationWarning *string) []string {
	if !deprecated && deprecationWarning != nil {
		return []string{"can only be set for deprecated versions"}
	}
	if deprecationWarning == nil {
		return nil
	}
	var errors []string
	if len(*deprecationWarning) > 256 {
		errors = append(errors, "must be <= 256 characters long")
	}
	if len(*deprecationWarning) == 0 {
		errors = append(errors, "must not be an empty string")
	}
	for i, r := range *deprecationWarning {
		if !unicode.IsPrint(r) {
			errors = append(errors, fmt.Sprintf("must only contain printable UTF-8 characters; non-printable character found at index %d", i))
			break
		}
		if unicode.IsControl(r) {
			errors = append(errors, fmt.Sprintf("must only contain printable UTF-8 characters; control character found at index %d", i))
			break
		}
	}
	if !utf8.ValidString(*deprecationWarning) {
		errors = append(errors, "must only contain printable UTF-8 characters")
	}
	return errors
}


// context is passed for supporting context cancellation during cel validation when validating defaults
func validateCustomResourceDefinitionSpec(ctx context.Context, spec *apiextensions.CustomResourceDefinitionSpec, opts validationOptions, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	if len(spec.Group) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("group"), ""))
	} else if errs := utilvalidation.IsDNS1123Subdomain(spec.Group); len(errs) > 0 {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), spec.Group, strings.Join(errs, ",")))
	} else if len(strings.Split(spec.Group, ".")) < 2 {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), spec.Group, "should be a domain with at least one dot"))
	}

	allErrs = append(allErrs, validateEnumStrings(fldPath.Child("scope"), string(spec.Scope), []string{string(apiextensions.ClusterScoped), string(apiextensions.NamespaceScoped)}, true)...)

	// enabling pruning requires structural schemas
	if spec.PreserveUnknownFields == nil || *spec.PreserveUnknownFields == false {
		opts.requireStructuralSchema = true
	}

	if opts.requireOpenAPISchema {
		// check that either a global schema or versioned schemas are set in all versions
		if spec.Validation == nil || spec.Validation.OpenAPIV3Schema == nil {
			for i, v := range spec.Versions {
				if v.Schema == nil || v.Schema.OpenAPIV3Schema == nil {
					allErrs = append(allErrs, field.Required(fldPath.Child("versions").Index(i).Child("schema").Child("openAPIV3Schema"), "schemas are required"))
				}
			}
		}
	} else if spec.PreserveUnknownFields == nil || *spec.PreserveUnknownFields == false {
		// check that either a global schema or versioned schemas are set in served versions
		if spec.Validation == nil || spec.Validation.OpenAPIV3Schema == nil {
			for i, v := range spec.Versions {
				schemaPath := fldPath.Child("versions").Index(i).Child("schema", "openAPIV3Schema")
				if v.Served && (v.Schema == nil || v.Schema.OpenAPIV3Schema == nil) {
					allErrs = append(allErrs, field.Required(schemaPath, "because otherwise all fields are pruned"))
				}
			}
		}
	}
	if opts.allowDefaults && specHasDefaults(spec) {
		opts.requireStructuralSchema = true
		if spec.PreserveUnknownFields == nil || *spec.PreserveUnknownFields == true {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("preserveUnknownFields"), true, "must be false in order to use defaults in the schema"))
		}
	}
	if specHasKubernetesExtensions(spec) {
		opts.requireStructuralSchema = true
	}

	storageFlagCount := 0
	versionsMap := map[string]bool{}
	uniqueNames := true
	for i, version := range spec.Versions {
		if version.Storage {
			storageFlagCount++
		}
		if versionsMap[version.Name] {
			uniqueNames = false
		} else {
			versionsMap[version.Name] = true
		}
		if errs := utilvalidation.IsDNS1035Label(version.Name); len(errs) > 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("versions").Index(i).Child("name"), spec.Versions[i].Name, strings.Join(errs, ",")))
		}
		subresources := getSubresourcesForVersion(spec, version.Name)
		allErrs = append(allErrs, validateCustomResourceDefinitionVersion(ctx, &version, fldPath.Child("versions").Index(i), hasStatusEnabled(subresources), opts)...)
	}

	// The top-level and per-version fields are mutual exclusive
	if spec.Validation != nil && hasPerVersionSchema(spec.Versions) {
		allErrs = append(allErrs, field.Forbidden(fldPath.Child("validation"), "top-level and per-version schemas are mutually exclusive"))
	}
	if spec.Subresources != nil && hasPerVersionSubresources(spec.Versions) {
		allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "top-level and per-version subresources are mutually exclusive"))
	}
	if len(spec.AdditionalPrinterColumns) > 0 && hasPerVersionColumns(spec.Versions) {
		allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalPrinterColumns"), "top-level and per-version additionalPrinterColumns are mutually exclusive"))
	}

	// Per-version fields may not all be set to identical values (top-level field should be used instead)
	if hasIdenticalPerVersionSchema(spec.Versions) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "per-version schemas may not all be set to identical values (top-level validation should be used instead)"))
	}
	if hasIdenticalPerVersionSubresources(spec.Versions) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "per-version subresources may not all be set to identical values (top-level subresources should be used instead)"))
	}
	if hasIdenticalPerVersionColumns(spec.Versions) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "per-version additionalPrinterColumns may not all be set to identical values (top-level additionalPrinterColumns should be used instead)"))
	}

	if !uniqueNames {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must contain unique version names"))
	}
	if storageFlagCount != 1 {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must have exactly one version marked as storage version"))
	}
	if len(spec.Version) != 0 {
		if errs := utilvalidation.IsDNS1035Label(spec.Version); len(errs) > 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, strings.Join(errs, ",")))
		}
		if len(spec.Versions) >= 1 && spec.Versions[0].Name != spec.Version {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, "must match the first version in spec.versions"))
		}
	}

	// in addition to the basic name restrictions, some names are required for spec, but not for status
	if len(spec.Names.Plural) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("names", "plural"), ""))
	}
	if len(spec.Names.Singular) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("names", "singular"), ""))
	}
	if len(spec.Names.Kind) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("names", "kind"), ""))
	}
	if len(spec.Names.ListKind) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("names", "listKind"), ""))
	}

	allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&spec.Names, fldPath.Child("names"))...)
	allErrs = append(allErrs, validateCustomResourceDefinitionValidation(ctx, spec.Validation, hasAnyStatusEnabled(spec), opts, fldPath.Child("validation"))...)
	allErrs = append(allErrs, ValidateCustomResourceDefinitionSubresources(spec.Subresources, fldPath.Child("subresources"))...)

	for i := range spec.AdditionalPrinterColumns {
		if errs := ValidateCustomResourceColumnDefinition(&spec.AdditionalPrinterColumns[i], fldPath.Child("additionalPrinterColumns").Index(i)); len(errs) > 0 {
			allErrs = append(allErrs, errs...)
		}
	}

	if (spec.Conversion != nil && spec.Conversion.Strategy != apiextensions.NoneConverter) && (spec.PreserveUnknownFields == nil || *spec.PreserveUnknownFields) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("conversion").Child("strategy"), spec.Conversion.Strategy, "must be None if spec.preserveUnknownFields is true"))
	}
	allErrs = append(allErrs, validateCustomResourceConversion(spec.Conversion, opts.requireRecognizedConversionReviewVersion, fldPath.Child("conversion"))...)

	return allErrs
}


func validateEnumStrings(fldPath *field.Path, value string, accepted []string, required bool) field.ErrorList {
	if value == "" {
		if required {
			return field.ErrorList{field.Required(fldPath, "")}
		}
		return field.ErrorList{}
	}
	for _, a := range accepted {
		if a == value {
			return field.ErrorList{}
		}
	}
	return field.ErrorList{field.NotSupported(fldPath, value, accepted)}
}


func isAcceptedConversionReviewVersion(v string) bool {
	return acceptedConversionReviewVersions.Has(v)
}


func validateConversionReviewVersions(versions []string, requireRecognizedVersion bool, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	if len(versions) < 1 {
		allErrs = append(allErrs, field.Required(fldPath, ""))
	} else {
		seen := map[string]bool{}
		hasAcceptedVersion := false
		for i, v := range versions {
			if seen[v] {
				allErrs = append(allErrs, field.Invalid(fldPath.Index(i), v, "duplicate version"))
				continue
			}
			seen[v] = true
			for _, errString := range utilvalidation.IsDNS1035Label(v) {
				allErrs = append(allErrs, field.Invalid(fldPath.Index(i), v, errString))
			}
			if isAcceptedConversionReviewVersion(v) {
				hasAcceptedVersion = true
			}
		}
		if requireRecognizedVersion && !hasAcceptedVersion {
			allErrs = append(allErrs, field.Invalid(
				fldPath, versions,
				fmt.Sprintf("must include at least one of %v",
					strings.Join(acceptedConversionReviewVersions.List(), ", "))))
		}
	}
	return allErrs
}


// hasValidConversionReviewVersion return true if there is a valid version or if the list is empty.
func hasValidConversionReviewVersionOrEmpty(versions []string) bool {
	if len(versions) < 1 {
		return true
	}
	for _, v := range versions {
		if isAcceptedConversionReviewVersion(v) {
			return true
		}
	}
	return false
}


// ValidateCustomResourceConversion statically validates
func ValidateCustomResourceConversion(conversion *apiextensions.CustomResourceConversion, fldPath *field.Path) field.ErrorList {
	return validateCustomResourceConversion(conversion, true, fldPath)
}


func validateCustomResourceConversion(conversion *apiextensions.CustomResourceConversion, requireRecognizedVersion bool, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	if conversion == nil {
		return allErrs
	}
	allErrs = append(allErrs, validateEnumStrings(fldPath.Child("strategy"), string(conversion.Strategy), []string{string(apiextensions.NoneConverter), string(apiextensions.WebhookConverter)}, true)...)
	if conversion.Strategy == apiextensions.WebhookConverter {
		if conversion.WebhookClientConfig == nil {
			allErrs = append(allErrs, field.Required(fldPath.Child("webhookClientConfig"), "required when strategy is set to Webhook"))
		} else {
			cc := conversion.WebhookClientConfig
			switch {
			case (cc.URL == nil) == (cc.Service == nil):
				allErrs = append(allErrs, field.Required(fldPath.Child("webhookClientConfig"), "exactly one of url or service is required"))
			case cc.URL != nil:
				allErrs = append(allErrs, webhook.ValidateWebhookURL(fldPath.Child("webhookClientConfig").Child("url"), *cc.URL, true)...)
			case cc.Service != nil:
				allErrs = append(allErrs, webhook.ValidateWebhookService(fldPath.Child("webhookClientConfig").Child("service"), cc.Service.Name, cc.Service.Namespace, cc.Service.Path, cc.Service.Port)...)
			}
		}
		allErrs = append(allErrs, validateConversionReviewVersions(conversion.ConversionReviewVersions, requireRecognizedVersion, fldPath.Child("conversionReviewVersions"))...)
	} else {
		if conversion.WebhookClientConfig != nil {
			allErrs = append(allErrs, field.Forbidden(fldPath.Child("webhookClientConfig"), "should not be set when strategy is not set to Webhook"))
		}
		if len(conversion.ConversionReviewVersions) > 0 {
			allErrs = append(allErrs, field.Forbidden(fldPath.Child("conversionReviewVersions"), "should not be set when strategy is not set to Webhook"))
		}
	}
	return allErrs
}


// validateCustomResourceDefinitionSpecUpdate statically validates
// context is passed for supporting context cancellation during cel validation when validating defaults
func validateCustomResourceDefinitionSpecUpdate(ctx context.Context, spec, oldSpec *apiextensions.CustomResourceDefinitionSpec, opts validationOptions, fldPath *field.Path) field.ErrorList {
	allErrs := validateCustomResourceDefinitionSpec(ctx, spec, opts, fldPath)

	if opts.requireImmutableNames {
		// these effect the storage and cannot be changed therefore
		allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Scope, oldSpec.Scope, fldPath.Child("scope"))...)
		allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Names.Kind, oldSpec.Names.Kind, fldPath.Child("names", "kind"))...)
	}

	// these affects the resource name, which is always immutable, so this can't be updated.
	allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Group, oldSpec.Group, fldPath.Child("group"))...)
	allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Names.Plural, oldSpec.Names.Plural, fldPath.Child("names", "plural"))...)

	return allErrs
}


// getSubresourcesForVersion returns the subresources for given version in given CRD spec.
// NOTE That this function assumes version always exist since it's used by the validation process
// that iterates through the existing versions.
func getSubresourcesForVersion(crd *apiextensions.CustomResourceDefinitionSpec, version string) *apiextensions.CustomResourceSubresources {
	if !hasPerVersionSubresources(crd.Versions) {
		return crd.Subresources
	}
	for _, v := range crd.Versions {
		if version == v.Name {
			return v.Subresources
		}
	}
	return nil
}


// hasAnyStatusEnabled returns true if given CRD spec has at least one Status Subresource set
// among the top-level and per-version Subresources.
func hasAnyStatusEnabled(crd *apiextensions.CustomResourceDefinitionSpec) bool {
	if hasStatusEnabled(crd.Subresources) {
		return true
	}
	for _, v := range crd.Versions {
		if hasStatusEnabled(v.Subresources) {
			return true
		}
	}
	return false
}


// hasStatusEnabled returns true if given CRD Subresources has non-nil Status set.
func hasStatusEnabled(subresources *apiextensions.CustomResourceSubresources) bool {
	if subresources != nil && subresources.Status != nil {
		return true
	}
	return false
}


// hasPerVersionSchema returns true if a CRD uses per-version schema.
func hasPerVersionSchema(versions []apiextensions.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Schema != nil {
			return true
		}
	}
	return false
}


// hasPerVersionSubresources returns true if a CRD uses per-version subresources.
func hasPerVersionSubresources(versions []apiextensions.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if v.Subresources != nil {
			return true
		}
	}
	return false
}


// hasPerVersionColumns returns true if a CRD uses per-version columns.
func hasPerVersionColumns(versions []apiextensions.CustomResourceDefinitionVersion) bool {
	for _, v := range versions {
		if len(v.AdditionalPrinterColumns) > 0 {
			return true
		}
	}
	return false
}


// hasIdenticalPerVersionSchema returns true if a CRD sets identical non-nil values
// to all per-version schemas
func hasIdenticalPerVersionSchema(versions []apiextensions.CustomResourceDefinitionVersion) bool {
	if len(versions) == 0 {
		return false
	}
	value := versions[0].Schema
	for _, v := range versions {
		if v.Schema == nil || !apiequality.Semantic.DeepEqual(v.Schema, value) {
			return false
		}
	}
	return true
}


// hasIdenticalPerVersionSubresources returns true if a CRD sets identical non-nil values
// to all per-version subresources
func hasIdenticalPerVersionSubresources(versions []apiextensions.CustomResourceDefinitionVersion) bool {
	if len(versions) == 0 {
		return false
	}
	value := versions[0].Subresources
	for _, v := range versions {
		if v.Subresources == nil || !apiequality.Semantic.DeepEqual(v.Subresources, value) {
			return false
		}
	}
	return true
}


// hasIdenticalPerVersionColumns returns true if a CRD sets identical non-nil values
// to all per-version columns
func hasIdenticalPerVersionColumns(versions []apiextensions.CustomResourceDefinitionVersion) bool {
	if len(versions) == 0 {
		return false
	}
	value := versions[0].AdditionalPrinterColumns
	for _, v := range versions {
		if len(v.AdditionalPrinterColumns) == 0 || !apiequality.Semantic.DeepEqual(v.AdditionalPrinterColumns, value) {
			return false
		}
	}
	return true
}


// ValidateCustomResourceDefinitionStatus statically validates
func ValidateCustomResourceDefinitionStatus(status *apiextensions.CustomResourceDefinitionStatus, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&status.AcceptedNames, fldPath.Child("acceptedNames"))...)
	return allErrs
}


// ValidateCustomResourceDefinitionNames statically validates
func ValidateCustomResourceDefinitionNames(names *apiextensions.CustomResourceDefinitionNames, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	if errs := utilvalidation.IsDNS1035Label(names.Plural); len(names.Plural) > 0 && len(errs) > 0 {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("plural"), names.Plural, strings.Join(errs, ",")))
	}
	if errs := utilvalidation.IsDNS1035Label(names.Singular); len(names.Singular) > 0 && len(errs) > 0 {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("singular"), names.Singular, strings.Join(errs, ",")))
	}
	if errs := utilvalidation.IsDNS1035Label(strings.ToLower(names.Kind)); len(names.Kind) > 0 && len(errs) > 0 {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), names.Kind, "may have mixed case, but should otherwise match: "+strings.Join(errs, ",")))
	}
	if errs := utilvalidation.IsDNS1035Label(strings.ToLower(names.ListKind)); len(names.ListKind) > 0 && len(errs) > 0 {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("listKind"), names.ListKind, "may have mixed case, but should otherwise match: "+strings.Join(errs, ",")))
	}

	for i, shortName := range names.ShortNames {
		if errs := utilvalidation.IsDNS1035Label(shortName); len(errs) > 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("shortNames").Index(i), shortName, strings.Join(errs, ",")))
		}
	}

	// kind and listKind may not be the same or parsing become ambiguous
	if len(names.Kind) > 0 && names.Kind == names.ListKind {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("listKind"), names.ListKind, "kind and listKind may not be the same"))
	}

	for i, category := range names.Categories {
		if errs := utilvalidation.IsDNS1035Label(category); len(errs) > 0 {
			allErrs = append(allErrs, field.Invalid(fldPath.Child("categories").Index(i), category, strings.Join(errs, ",")))
		}
	}

	return allErrs
}


// ValidateCustomResourceColumnDefinition statically validates a printer column.
func ValidateCustomResourceColumnDefinition(col *apiextensions.CustomResourceColumnDefinition, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	if len(col.Name) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
	}

	if len(col.Type) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("type"), fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ","))))
	} else if !printerColumnDatatypes.Has(col.Type) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), col.Type, fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ","))))
	}

	if len(col.Format) > 0 && !customResourceColumnDefinitionFormats.Has(col.Format) {
		allErrs = append(allErrs, field.Invalid(fldPath.Child("format"), col.Format, fmt.Sprintf("must be one of %s", strings.Join(customResourceColumnDefinitionFormats.List(), ","))))
	}

	if len(col.JSONPath) == 0 {
		allErrs = append(allErrs, field.Required(fldPath.Child("JSONPath"), ""))
	} else if errs := validateSimpleJSONPath(col.JSONPath, fldPath.Child("JSONPath")); len(errs) > 0 {
		allErrs = append(allErrs, errs...)
	}

	return allErrs
}


// validateCustomResourceDefinitionValidation statically validates
// context is passed for supporting context cancellation during cel validation when validating defaults
func validateCustomResourceDefinitionValidation(ctx context.Context, customResourceValidation *apiextensions.CustomResourceValidation, statusSubresourceEnabled bool, opts validationOptions, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	if customResourceValidation == nil {
		return allErrs
	}

	if schema := customResourceValidation.OpenAPIV3Schema; schema != nil {
		// if the status subresource is enabled, only certain fields are allowed inside the root schema.
		// these fields are chosen such that, if status is extracted as properties["status"], it's validation is not lost.
		if statusSubresourceEnabled {
			v := reflect.ValueOf(schema).Elem()
			for i := 0; i < v.NumField(); i++ {
				// skip zero values
				if value := v.Field(i).Interface(); reflect.DeepEqual(value, reflect.Zero(reflect.TypeOf(value)).Interface()) {
					continue
				}

				fieldName := v.Type().Field(i).Name

				// only "object" type is valid at root of the schema since validation schema for status is extracted as properties["status"]
				if fieldName == "Type" {
					if schema.Type != "object" {
						allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema.type"), schema.Type, fmt.Sprintf(`only "object" is allowed as the type at the root of the schema if the status subresource is enabled`)))
						break
					}
					continue
				}

				if !allowedAtRootSchema(fieldName) {
					allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf(`only %v fields are allowed at the root of the schema if the status subresource is enabled`, allowedFieldsAtRootSchema)))
					break
				}
			}
		}

		if schema.Nullable {
			allErrs = append(allErrs, field.Forbidden(fldPath.Child("openAPIV3Schema.nullable"), fmt.Sprintf(`nullable cannot be true at the root`)))
		}

		openAPIV3Schema := &specStandardValidatorV3{
			allowDefaults:            opts.allowDefaults,
			disallowDefaultsReason:   opts.disallowDefaultsReason,
			requireValidPropertyType: opts.requireValidPropertyType,
		}

		var celContext *CELSchemaContext
		var structuralSchemaInitErrs field.ErrorList
		if opts.requireStructuralSchema {
			if ss, err := structuralschema.NewStructural(schema); err != nil {
				// These validation errors overlap with  OpenAPISchema validation errors so we keep track of them
				// separately and only show them if OpenAPISchema validation does not report any errors.
				structuralSchemaInitErrs = append(structuralSchemaInitErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), "", err.Error()))
			} else if validationErrors := structuralschema.ValidateStructural(fldPath.Child("openAPIV3Schema"), ss); len(validationErrors) > 0 {
				allErrs = append(allErrs, validationErrors...)
			} else if validationErrors, err := structuraldefaulting.ValidateDefaults(ctx, fldPath.Child("openAPIV3Schema"), ss, true, opts.requirePrunedDefaults); err != nil {
				// this should never happen
				allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), "", err.Error()))
			} else if len(validationErrors) > 0 {
				allErrs = append(allErrs, validationErrors...)
			} else {
				// Only initialize CEL rule validation context if the structural schemas are valid.
				// A nil CELSchemaContext indicates that no CEL validation should be attempted.
				celContext = RootCELContext(schema)
			}
		}
		allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema, fldPath.Child("openAPIV3Schema"), openAPIV3Schema, true, &opts, celContext).AllErrors()...)

		if len(allErrs) == 0 && len(structuralSchemaInitErrs) > 0 {
			// Structural schema initialization errors overlap with OpenAPISchema validation errors so we only show them
			// if there are no OpenAPISchema validation errors.
			allErrs = append(allErrs, structuralSchemaInitErrs...)
		}

		if celContext != nil && celContext.TotalCost != nil {
			if celContext.TotalCost.Total > StaticEstimatedCRDCostLimit {
				for _, expensive := range celContext.TotalCost.MostExpensive {
					costErrorMsg := fmt.Sprintf("contributed to estimated rule cost total exceeding cost limit for entire OpenAPIv3 schema")
					allErrs = append(allErrs, field.Forbidden(expensive.Path, costErrorMsg))
				}

				costErrorMsg := getCostErrorMessage("x-kubernetes-validations estimated rule cost total for entire OpenAPIv3 schema", celContext.TotalCost.Total, StaticEstimatedCRDCostLimit)
				allErrs = append(allErrs, field.Forbidden(fldPath.Child("openAPIV3Schema"), costErrorMsg))
			}
		}
	}

	// 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, "", fmt.Sprintf("error building validator: %v", err)))
		}
	}
	return allErrs
}


// AppendErrors appends all errors in the provided list with the errors of this list.
func (o *OpenAPISchemaErrorList) AppendErrors(list *OpenAPISchemaErrorList) {
	if o == nil || list == nil {
		return
	}
	o.SchemaErrors = append(o.SchemaErrors, list.SchemaErrors...)
	o.CELErrors = append(o.CELErrors, list.CELErrors...)
}


// AllErrors returns a list containing both schema and CEL errors.
func (o *OpenAPISchemaErrorList) AllErrors() field.ErrorList {
	if o == nil {
		return field.ErrorList{}
	}
	return append(o.SchemaErrors, o.CELErrors...)
}