mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 01:40:07 +00:00
CRD v1: require schema
This commit is contained in:
parent
15097a524f
commit
fec2d3717a
@ -65,6 +65,7 @@ func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinitio
|
|||||||
allowDefaults: allowDefaults(requestGV),
|
allowDefaults: allowDefaults(requestGV),
|
||||||
requireRecognizedConversionReviewVersion: true,
|
requireRecognizedConversionReviewVersion: true,
|
||||||
requireImmutableNames: false,
|
requireImmutableNames: false,
|
||||||
|
requireOpenAPISchema: requireOpenAPISchema(requestGV, nil),
|
||||||
}
|
}
|
||||||
|
|
||||||
allErrs := genericvalidation.ValidateObjectMeta(&obj.ObjectMeta, false, nameValidationFn, field.NewPath("metadata"))
|
allErrs := genericvalidation.ValidateObjectMeta(&obj.ObjectMeta, false, nameValidationFn, field.NewPath("metadata"))
|
||||||
@ -84,6 +85,8 @@ type validationOptions struct {
|
|||||||
requireRecognizedConversionReviewVersion bool
|
requireRecognizedConversionReviewVersion bool
|
||||||
// requireImmutableNames disables changing spec.names
|
// requireImmutableNames disables changing spec.names
|
||||||
requireImmutableNames bool
|
requireImmutableNames bool
|
||||||
|
// requireOpenAPISchema requires an openapi V3 schema be specified
|
||||||
|
requireOpenAPISchema bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateCustomResourceDefinitionUpdate statically validates
|
// ValidateCustomResourceDefinitionUpdate statically validates
|
||||||
@ -92,6 +95,7 @@ func ValidateCustomResourceDefinitionUpdate(obj, oldObj *apiextensions.CustomRes
|
|||||||
allowDefaults: allowDefaults(requestGV) || specHasDefaults(&oldObj.Spec),
|
allowDefaults: allowDefaults(requestGV) || specHasDefaults(&oldObj.Spec),
|
||||||
requireRecognizedConversionReviewVersion: oldObj.Spec.Conversion == nil || hasValidConversionReviewVersionOrEmpty(oldObj.Spec.Conversion.ConversionReviewVersions),
|
requireRecognizedConversionReviewVersion: oldObj.Spec.Conversion == nil || hasValidConversionReviewVersionOrEmpty(oldObj.Spec.Conversion.ConversionReviewVersions),
|
||||||
requireImmutableNames: apiextensions.IsCRDConditionTrue(oldObj, apiextensions.Established),
|
requireImmutableNames: apiextensions.IsCRDConditionTrue(oldObj, apiextensions.Established),
|
||||||
|
requireOpenAPISchema: requireOpenAPISchema(requestGV, &oldObj.Spec),
|
||||||
}
|
}
|
||||||
|
|
||||||
allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata"))
|
allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata"))
|
||||||
@ -161,10 +165,23 @@ func validateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi
|
|||||||
|
|
||||||
allErrs = append(allErrs, validateEnumStrings(fldPath.Child("scope"), string(spec.Scope), []string{string(apiextensions.ClusterScoped), string(apiextensions.NamespaceScoped)}, true)...)
|
allErrs = append(allErrs, validateEnumStrings(fldPath.Child("scope"), string(spec.Scope), []string{string(apiextensions.ClusterScoped), string(apiextensions.NamespaceScoped)}, true)...)
|
||||||
|
|
||||||
|
// enabling pruning requires structural schemas
|
||||||
mustBeStructural := false
|
mustBeStructural := false
|
||||||
if spec.PreserveUnknownFields == nil || *spec.PreserveUnknownFields == false {
|
if spec.PreserveUnknownFields == nil || *spec.PreserveUnknownFields == false {
|
||||||
mustBeStructural = true
|
mustBeStructural = true
|
||||||
// check that either a global schema or versioned schemas are set
|
}
|
||||||
|
|
||||||
|
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 {
|
if spec.Validation == nil || spec.Validation.OpenAPIV3Schema == nil {
|
||||||
for i, v := range spec.Versions {
|
for i, v := range spec.Versions {
|
||||||
schemaPath := fldPath.Child("versions").Index(i).Child("schema", "openAPIV3Schema")
|
schemaPath := fldPath.Child("versions").Index(i).Child("schema", "openAPIV3Schema")
|
||||||
@ -946,6 +963,30 @@ func allowedAtRootSchema(field string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// requireOpenAPISchema returns true if the request group version requires a schema
|
||||||
|
func requireOpenAPISchema(requestGV schema.GroupVersion, oldCRDSpec *apiextensions.CustomResourceDefinitionSpec) bool {
|
||||||
|
if requestGV == v1beta1.SchemeGroupVersion {
|
||||||
|
// for backwards compatibility
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if oldCRDSpec != nil && !allVersionsSpecifyOpenAPISchema(oldCRDSpec) {
|
||||||
|
// don't tighten validation on existing persisted data
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
func allVersionsSpecifyOpenAPISchema(spec *apiextensions.CustomResourceDefinitionSpec) bool {
|
||||||
|
if spec.Validation != nil && spec.Validation.OpenAPIV3Schema != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, v := range spec.Versions {
|
||||||
|
if v.Schema == nil || v.Schema.OpenAPIV3Schema == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// allowDefaults returns true if the defaulting feature is enabled and the request group version allows adding defaults
|
// allowDefaults returns true if the defaulting feature is enabled and the request group version allows adding defaults
|
||||||
func allowDefaults(requestGV schema.GroupVersion) bool {
|
func allowDefaults(requestGV schema.GroupVersion) bool {
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceDefaulting) {
|
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceDefaulting) {
|
||||||
|
@ -1320,6 +1320,7 @@ func TestValidateCustomResourceDefinition(t *testing.T) {
|
|||||||
StoredVersions: []string{"version"},
|
StoredVersions: []string{"version"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
requestGV: apiextensionsv1beta1.SchemeGroupVersion,
|
||||||
errors: []validationMatch{
|
errors: []validationMatch{
|
||||||
required("spec", "versions[1]", "schema", "openAPIV3Schema"),
|
required("spec", "versions[1]", "schema", "openAPIV3Schema"),
|
||||||
},
|
},
|
||||||
@ -1360,6 +1361,49 @@ func TestValidateCustomResourceDefinition(t *testing.T) {
|
|||||||
StoredVersions: []string{"version"},
|
StoredVersions: []string{"version"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
requestGV: apiextensionsv1beta1.SchemeGroupVersion,
|
||||||
|
errors: []validationMatch{
|
||||||
|
required("spec", "versions[0]", "schema", "openAPIV3Schema"),
|
||||||
|
required("spec", "versions[1]", "schema", "openAPIV3Schema"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no schema via v1",
|
||||||
|
resource: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "version",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "version2",
|
||||||
|
Served: true,
|
||||||
|
Storage: false,
|
||||||
|
Schema: &apiextensions.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{
|
||||||
|
Plural: "plural",
|
||||||
|
Singular: "singular",
|
||||||
|
Kind: "Plural",
|
||||||
|
ListKind: "PluralList",
|
||||||
|
},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(false),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||||
|
StoredVersions: []string{"version"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
requestGV: apiextensionsv1.SchemeGroupVersion,
|
||||||
errors: []validationMatch{
|
errors: []validationMatch{
|
||||||
required("spec", "versions[0]", "schema", "openAPIV3Schema"),
|
required("spec", "versions[0]", "schema", "openAPIV3Schema"),
|
||||||
required("spec", "versions[1]", "schema", "openAPIV3Schema"),
|
required("spec", "versions[1]", "schema", "openAPIV3Schema"),
|
||||||
@ -3489,6 +3533,169 @@ func TestValidateCustomResourceDefinitionUpdate(t *testing.T) {
|
|||||||
requestGV: apiextensionsv1.SchemeGroupVersion,
|
requestGV: apiextensionsv1.SchemeGroupVersion,
|
||||||
errors: []validationMatch{},
|
errors: []validationMatch{},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "schema not required via v1beta1",
|
||||||
|
old: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{{Name: "version", Served: true, Storage: true}},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
resource: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{{Name: "version", Served: true, Storage: true}},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
requestGV: apiextensionsv1beta1.SchemeGroupVersion,
|
||||||
|
errors: []validationMatch{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "schema not required via v1 if old object is missing schema",
|
||||||
|
old: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{{Name: "version", Served: true, Storage: true}},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
resource: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{{Name: "version", Served: true, Storage: true}},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
requestGV: apiextensionsv1.SchemeGroupVersion,
|
||||||
|
errors: []validationMatch{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "schema not required via v1 if old object is missing schema for some versions",
|
||||||
|
old: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||||
|
{Name: "version", Served: true, Storage: true, Schema: &apiextensions.CustomResourceValidation{OpenAPIV3Schema: &apiextensions.JSONSchemaProps{Type: "object"}}},
|
||||||
|
{Name: "version2", Served: true, Storage: false},
|
||||||
|
},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
resource: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||||
|
{Name: "version", Served: true, Storage: true},
|
||||||
|
{Name: "version2", Served: true, Storage: false},
|
||||||
|
},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
requestGV: apiextensionsv1.SchemeGroupVersion,
|
||||||
|
errors: []validationMatch{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "schema required via v1 if old object has top-level schema",
|
||||||
|
old: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{{Name: "version", Served: true, Storage: true}},
|
||||||
|
Validation: &apiextensions.CustomResourceValidation{OpenAPIV3Schema: &apiextensions.JSONSchemaProps{Type: "object"}},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
resource: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{{Name: "version", Served: true, Storage: true}},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
requestGV: apiextensionsv1.SchemeGroupVersion,
|
||||||
|
errors: []validationMatch{
|
||||||
|
required("spec.versions[0].schema.openAPIV3Schema"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "schema required via v1 if all versions of old object have schema",
|
||||||
|
old: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||||
|
{Name: "version", Served: true, Storage: true, Schema: &apiextensions.CustomResourceValidation{OpenAPIV3Schema: &apiextensions.JSONSchemaProps{Type: "object", Description: "1"}}},
|
||||||
|
{Name: "version2", Served: true, Storage: false, Schema: &apiextensions.CustomResourceValidation{OpenAPIV3Schema: &apiextensions.JSONSchemaProps{Type: "object", Description: "2"}}},
|
||||||
|
},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
resource: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com", ResourceVersion: "1"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||||
|
{Name: "version", Served: true, Storage: true},
|
||||||
|
{Name: "version2", Served: true, Storage: false},
|
||||||
|
},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{Plural: "plural", Singular: "singular", Kind: "Plural", ListKind: "PluralList"},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{StoredVersions: []string{"version"}},
|
||||||
|
},
|
||||||
|
requestGV: apiextensionsv1.SchemeGroupVersion,
|
||||||
|
errors: []validationMatch{
|
||||||
|
required("spec.versions[0].schema.openAPIV3Schema"),
|
||||||
|
required("spec.versions[1].schema.openAPIV3Schema"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "setting defaults with enabled feature gate",
|
name: "setting defaults with enabled feature gate",
|
||||||
old: &apiextensions.CustomResourceDefinition{
|
old: &apiextensions.CustomResourceDefinition{
|
||||||
|
@ -479,7 +479,10 @@ func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionRes
|
|||||||
|
|
||||||
// k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
|
// k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
|
||||||
gvr("apiextensions.k8s.io", "v1", "customresourcedefinitions"): {
|
gvr("apiextensions.k8s.io", "v1", "customresourcedefinitions"): {
|
||||||
Stub: `{"metadata": {"name": "openshiftwebconsoleconfigs.webconsole2.operator.openshift.io"},"spec": {"scope": "Cluster","group": "webconsole2.operator.openshift.io","versions": [{"name":"v1alpha1","storage":true,"served":true}],"names": {"kind": "OpenShiftWebConsoleConfig","plural": "openshiftwebconsoleconfigs","singular": "openshiftwebconsoleconfig"}}}`,
|
Stub: `{"metadata": {"name": "openshiftwebconsoleconfigs.webconsole2.operator.openshift.io"},"spec": {` +
|
||||||
|
`"scope": "Cluster","group": "webconsole2.operator.openshift.io",` +
|
||||||
|
`"versions": [{"name":"v1alpha1","storage":true,"served":true,"schema":{"openAPIV3Schema":{"type":"object"}}}],` +
|
||||||
|
`"names": {"kind": "OpenShiftWebConsoleConfig","plural": "openshiftwebconsoleconfigs","singular": "openshiftwebconsoleconfig"}}}`,
|
||||||
ExpectedEtcdPath: "/registry/apiextensions.k8s.io/customresourcedefinitions/openshiftwebconsoleconfigs.webconsole2.operator.openshift.io",
|
ExpectedEtcdPath: "/registry/apiextensions.k8s.io/customresourcedefinitions/openshiftwebconsoleconfigs.webconsole2.operator.openshift.io",
|
||||||
ExpectedGVK: gvkP("apiextensions.k8s.io", "v1beta1", "CustomResourceDefinition"),
|
ExpectedGVK: gvkP("apiextensions.k8s.io", "v1beta1", "CustomResourceDefinition"),
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user