mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 18:31:15 +00:00
Allow CRD /scale labelSelectors to be under either status or spec (#78234)
* apiextensions API doc: allow labelSelectorPath to be under .status or .spec * apiextensions validation: allow labelSelectorPath to be under .status or .spec * test * generated
This commit is contained in:
parent
470916d32d
commit
6a5fa6ca5b
2
api/openapi-spec/swagger.json
generated
2
api/openapi-spec/swagger.json
generated
@ -16616,7 +16616,7 @@
|
|||||||
"description": "CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources.",
|
"description": "CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"labelSelectorPath": {
|
"labelSelectorPath": {
|
||||||
"description": "LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector. Only JSON paths without the array notation are allowed. Must be a JSON Path under .status. Must be set to work with HPA. If there is no value under the given path in the CustomResource, the status label selector value in the /scale subresource will default to the empty string.",
|
"description": "LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector. Only JSON paths without the array notation are allowed. Must be a JSON Path under .status or .spec. Must be set to work with HPA. The field pointed by this JSON path must be a string field (not a complex selector struct) which contains a serialized label selector in string form. More info: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions#scale-subresource If there is no value under the given path in the CustomResource, the status label selector value in the /scale subresource will default to the empty string.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"specReplicasPath": {
|
"specReplicasPath": {
|
||||||
|
@ -393,8 +393,11 @@ type CustomResourceSubresourceScale struct {
|
|||||||
StatusReplicasPath string
|
StatusReplicasPath string
|
||||||
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
||||||
// Only JSON paths without the array notation are allowed.
|
// Only JSON paths without the array notation are allowed.
|
||||||
// Must be a JSON Path under .status.
|
// Must be a JSON Path under .status or .spec.
|
||||||
// Must be set to work with HPA.
|
// Must be set to work with HPA.
|
||||||
|
// The field pointed by this JSON path must be a string field (not a complex selector struct)
|
||||||
|
// which contains a serialized label selector in string form.
|
||||||
|
// More info: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions#scale-subresource
|
||||||
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
||||||
// subresource will default to the empty string.
|
// subresource will default to the empty string.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -327,8 +327,11 @@ message CustomResourceSubresourceScale {
|
|||||||
|
|
||||||
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
||||||
// Only JSON paths without the array notation are allowed.
|
// Only JSON paths without the array notation are allowed.
|
||||||
// Must be a JSON Path under .status.
|
// Must be a JSON Path under .status or .spec.
|
||||||
// Must be set to work with HPA.
|
// Must be set to work with HPA.
|
||||||
|
// The field pointed by this JSON path must be a string field (not a complex selector struct)
|
||||||
|
// which contains a serialized label selector in string form.
|
||||||
|
// More info: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions#scale-subresource
|
||||||
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
||||||
// subresource will default to the empty string.
|
// subresource will default to the empty string.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -412,8 +412,11 @@ type CustomResourceSubresourceScale struct {
|
|||||||
StatusReplicasPath string `json:"statusReplicasPath" protobuf:"bytes,2,opt,name=statusReplicasPath"`
|
StatusReplicasPath string `json:"statusReplicasPath" protobuf:"bytes,2,opt,name=statusReplicasPath"`
|
||||||
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
||||||
// Only JSON paths without the array notation are allowed.
|
// Only JSON paths without the array notation are allowed.
|
||||||
// Must be a JSON Path under .status.
|
// Must be a JSON Path under .status or .spec.
|
||||||
// Must be set to work with HPA.
|
// Must be set to work with HPA.
|
||||||
|
// The field pointed by this JSON path must be a string field (not a complex selector struct)
|
||||||
|
// which contains a serialized label selector in string form.
|
||||||
|
// More info: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions#scale-subresource
|
||||||
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
||||||
// subresource will default to the empty string.
|
// subresource will default to the empty string.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -794,8 +794,8 @@ func ValidateCustomResourceDefinitionSubresources(subresources *apiextensions.Cu
|
|||||||
if subresources.Scale.LabelSelectorPath != nil && len(*subresources.Scale.LabelSelectorPath) > 0 {
|
if subresources.Scale.LabelSelectorPath != nil && len(*subresources.Scale.LabelSelectorPath) > 0 {
|
||||||
if errs := validateSimpleJSONPath(*subresources.Scale.LabelSelectorPath, fldPath.Child("scale.labelSelectorPath")); len(errs) > 0 {
|
if errs := validateSimpleJSONPath(*subresources.Scale.LabelSelectorPath, fldPath.Child("scale.labelSelectorPath")); len(errs) > 0 {
|
||||||
allErrs = append(allErrs, errs...)
|
allErrs = append(allErrs, errs...)
|
||||||
} else if !strings.HasPrefix(*subresources.Scale.LabelSelectorPath, ".status.") {
|
} else if !strings.HasPrefix(*subresources.Scale.LabelSelectorPath, ".spec.") && !strings.HasPrefix(*subresources.Scale.LabelSelectorPath, ".status.") {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("scale.labelSelectorPath"), subresources.Scale.LabelSelectorPath, "should be a json path under .status"))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("scale.labelSelectorPath"), subresources.Scale.LabelSelectorPath, "should be a json path under either .spec or .status"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1162,6 +1162,83 @@ func TestValidateCustomResourceDefinition(t *testing.T) {
|
|||||||
required("spec", "versions[1]", "schema", "openAPIV3Schema"),
|
required("spec", "versions[1]", "schema", "openAPIV3Schema"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "labelSelectorPath outside of .spec and .status",
|
||||||
|
resource: &apiextensions.CustomResourceDefinition{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||||
|
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||||
|
Group: "group.com",
|
||||||
|
Version: "version0",
|
||||||
|
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
// null labelSelectorPath
|
||||||
|
Name: "version0",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Subresources: &apiextensions.CustomResourceSubresources{
|
||||||
|
Scale: &apiextensions.CustomResourceSubresourceScale{
|
||||||
|
SpecReplicasPath: ".spec.replicas",
|
||||||
|
StatusReplicasPath: ".status.replicas",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// labelSelectorPath under .status
|
||||||
|
Name: "version1",
|
||||||
|
Served: true,
|
||||||
|
Storage: false,
|
||||||
|
Subresources: &apiextensions.CustomResourceSubresources{
|
||||||
|
Scale: &apiextensions.CustomResourceSubresourceScale{
|
||||||
|
SpecReplicasPath: ".spec.replicas",
|
||||||
|
StatusReplicasPath: ".status.replicas",
|
||||||
|
LabelSelectorPath: strPtr(".status.labelSelector"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// labelSelectorPath under .spec
|
||||||
|
Name: "version2",
|
||||||
|
Served: true,
|
||||||
|
Storage: false,
|
||||||
|
Subresources: &apiextensions.CustomResourceSubresources{
|
||||||
|
Scale: &apiextensions.CustomResourceSubresourceScale{
|
||||||
|
SpecReplicasPath: ".spec.replicas",
|
||||||
|
StatusReplicasPath: ".status.replicas",
|
||||||
|
LabelSelectorPath: strPtr(".spec.labelSelector"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// labelSelectorPath outside of .spec and .status
|
||||||
|
Name: "version3",
|
||||||
|
Served: true,
|
||||||
|
Storage: false,
|
||||||
|
Subresources: &apiextensions.CustomResourceSubresources{
|
||||||
|
Scale: &apiextensions.CustomResourceSubresourceScale{
|
||||||
|
SpecReplicasPath: ".spec.replicas",
|
||||||
|
StatusReplicasPath: ".status.replicas",
|
||||||
|
LabelSelectorPath: strPtr(".labelSelector"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Scope: apiextensions.NamespaceScoped,
|
||||||
|
Names: apiextensions.CustomResourceDefinitionNames{
|
||||||
|
Plural: "plural",
|
||||||
|
Singular: "singular",
|
||||||
|
Kind: "Plural",
|
||||||
|
ListKind: "PluralList",
|
||||||
|
},
|
||||||
|
PreserveUnknownFields: pointer.BoolPtr(true),
|
||||||
|
},
|
||||||
|
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||||
|
StoredVersions: []string{"version0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errors: []validationMatch{
|
||||||
|
invalid("spec", "versions[3]", "subresources", "scale", "labelSelectorPath"),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
Loading…
Reference in New Issue
Block a user