Add servedVersions info in StorageVersion API

This commit is contained in:
Richa Banker 2023-06-01 18:07:56 -07:00
parent 1c7e87cff2
commit 1c48b7ec14
23 changed files with 295 additions and 61 deletions

View File

@ -843,6 +843,14 @@
"encodingVersion": { "encodingVersion": {
"description": "The API server encodes the object to this version when persisting it in the backend (e.g., etcd).", "description": "The API server encodes the object to this version when persisting it in the backend (e.g., etcd).",
"type": "string" "type": "string"
},
"servedVersions": {
"description": "The API server can serve these versions. DecodableVersions must include all ServedVersions.",
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "set"
} }
}, },
"type": "object" "type": "object"

View File

@ -20,6 +20,15 @@
"encodingVersion": { "encodingVersion": {
"description": "The API server encodes the object to this version when persisting it in the backend (e.g., etcd).", "description": "The API server encodes the object to this version when persisting it in the backend (e.g., etcd).",
"type": "string" "type": "string"
},
"servedVersions": {
"description": "The API server can serve these versions. DecodableVersions must include all ServedVersions.",
"items": {
"default": "",
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "set"
} }
}, },
"type": "object" "type": "object"

View File

@ -70,6 +70,10 @@ type ServerStorageVersion struct {
// The API server can decode objects encoded in these versions. // The API server can decode objects encoded in these versions.
// The encodingVersion must be included in the decodableVersions. // The encodingVersion must be included in the decodableVersions.
DecodableVersions []string DecodableVersions []string
// The API server can serve these versions.
// DecodableVersions must include all ServedVersions.
ServedVersions []string
} }
// StorageVersionConditionType Indicates the storage version condition type // StorageVersionConditionType Indicates the storage version condition type

View File

@ -104,6 +104,7 @@ func autoConvert_v1alpha1_ServerStorageVersion_To_apiserverinternal_ServerStorag
out.APIServerID = in.APIServerID out.APIServerID = in.APIServerID
out.EncodingVersion = in.EncodingVersion out.EncodingVersion = in.EncodingVersion
out.DecodableVersions = *(*[]string)(unsafe.Pointer(&in.DecodableVersions)) out.DecodableVersions = *(*[]string)(unsafe.Pointer(&in.DecodableVersions))
out.ServedVersions = *(*[]string)(unsafe.Pointer(&in.ServedVersions))
return nil return nil
} }
@ -116,6 +117,7 @@ func autoConvert_apiserverinternal_ServerStorageVersion_To_v1alpha1_ServerStorag
out.APIServerID = in.APIServerID out.APIServerID = in.APIServerID
out.EncodingVersion = in.EncodingVersion out.EncodingVersion = in.EncodingVersion
out.DecodableVersions = *(*[]string)(unsafe.Pointer(&in.DecodableVersions)) out.DecodableVersions = *(*[]string)(unsafe.Pointer(&in.DecodableVersions))
out.ServedVersions = *(*[]string)(unsafe.Pointer(&in.ServedVersions))
return nil return nil
} }

View File

@ -98,6 +98,22 @@ func validateServerStorageVersion(ssv apiserverinternal.ServerStorageVersion, fl
if !found { if !found {
allErrs = append(allErrs, field.Invalid(fldPath.Child("decodableVersions"), ssv.DecodableVersions, fmt.Sprintf("decodableVersions must include encodingVersion %s", ssv.EncodingVersion))) allErrs = append(allErrs, field.Invalid(fldPath.Child("decodableVersions"), ssv.DecodableVersions, fmt.Sprintf("decodableVersions must include encodingVersion %s", ssv.EncodingVersion)))
} }
for i, sv := range ssv.ServedVersions {
if errs := isValidAPIVersion(sv); len(errs) > 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("servedVersions").Index(i), sv, strings.Join(errs, ",")))
}
foundDecodableVersion := false
for _, dv := range ssv.DecodableVersions {
if sv == dv {
foundDecodableVersion = true
break
}
}
if !foundDecodableVersion {
allErrs = append(allErrs, field.Invalid(fldPath.Child("servedVersions").Index(i), sv, fmt.Sprintf("individual served version : %s must be included in decodableVersions : %s", sv, ssv.DecodableVersions)))
}
}
return allErrs return allErrs
} }

View File

@ -33,6 +33,7 @@ func TestValidateServerStorageVersion(t *testing.T) {
APIServerID: "-fea", APIServerID: "-fea",
EncodingVersion: "v1alpha1", EncodingVersion: "v1alpha1",
DecodableVersions: []string{"v1alpha1", "v1"}, DecodableVersions: []string{"v1alpha1", "v1"},
ServedVersions: []string{"v1alpha1", "v1"},
}, },
expectedErr: "apiServerID: Invalid value", expectedErr: "apiServerID: Invalid value",
}, { }, {
@ -40,6 +41,7 @@ func TestValidateServerStorageVersion(t *testing.T) {
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "v1alpha1", EncodingVersion: "v1alpha1",
DecodableVersions: []string{"v1beta1", "v1"}, DecodableVersions: []string{"v1beta1", "v1"},
ServedVersions: []string{"v1beta1", "v1"},
}, },
expectedErr: "decodableVersions must include encodingVersion", expectedErr: "decodableVersions must include encodingVersion",
}, { }, {
@ -47,6 +49,7 @@ func TestValidateServerStorageVersion(t *testing.T) {
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "v1alpha1", EncodingVersion: "v1alpha1",
DecodableVersions: []string{"v1alpha1", "v1", "-fea"}, DecodableVersions: []string{"v1alpha1", "v1", "-fea"},
ServedVersions: []string{"v1alpha1", "v1", "-fea"},
}, },
expectedErr: "decodableVersions[2]: Invalid value", expectedErr: "decodableVersions[2]: Invalid value",
}, { }, {
@ -54,6 +57,15 @@ func TestValidateServerStorageVersion(t *testing.T) {
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "v1alpha1", EncodingVersion: "v1alpha1",
DecodableVersions: []string{"v1alpha1", "v1"}, DecodableVersions: []string{"v1alpha1", "v1"},
ServedVersions: []string{"v1alpha1", "v1"},
},
expectedErr: "",
}, {
ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea",
EncodingVersion: "v1alpha1",
DecodableVersions: []string{"v1alpha1", "v1"},
ServedVersions: []string{"v1alpha1", "v1"},
}, },
expectedErr: "", expectedErr: "",
}, { }, {
@ -61,20 +73,39 @@ func TestValidateServerStorageVersion(t *testing.T) {
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "mygroup.com/v2", EncodingVersion: "mygroup.com/v2",
DecodableVersions: []string{"v1alpha1", "v1", "mygroup.com/v2"}, DecodableVersions: []string{"v1alpha1", "v1", "mygroup.com/v2"},
ServedVersions: []string{"v1alpha1", "v1", "mygroup.com/v2"},
}, },
expectedErr: "", expectedErr: "",
}, {
ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea",
EncodingVersion: "v1alpha1",
DecodableVersions: []string{"v1alpha1", "v1"},
ServedVersions: []string{"/v3"},
},
expectedErr: `[].servedVersions[0]: Invalid value: "/v3": group part: must be non-empty`,
}, { }, {
ssv: apiserverinternal.ServerStorageVersion{ ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "mygroup.com/v2", EncodingVersion: "mygroup.com/v2",
DecodableVersions: []string{"mygroup.com/v2", "/v3"}, DecodableVersions: []string{"mygroup.com/v2", "/v3"},
ServedVersions: []string{"mygroup.com/v2", "/v3"},
}, },
expectedErr: `[].decodableVersions[1]: Invalid value: "/v3": group part: must be non-empty`, expectedErr: `[].decodableVersions[1]: Invalid value: "/v3": group part: must be non-empty`,
}, {
ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea",
EncodingVersion: "mygroup.com/v2",
DecodableVersions: []string{"mygroup.com/v2", "/v3"},
ServedVersions: []string{"mygroup.com/"},
},
expectedErr: `[].servedVersions[0]: Invalid value: "mygroup.com/": version part: must be non-empty`,
}, { }, {
ssv: apiserverinternal.ServerStorageVersion{ ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "mygroup.com/v2", EncodingVersion: "mygroup.com/v2",
DecodableVersions: []string{"mygroup.com/v2", "mygroup.com/"}, DecodableVersions: []string{"mygroup.com/v2", "mygroup.com/"},
ServedVersions: []string{"mygroup.com/v2", "mygroup.com/"},
}, },
expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/": version part: must be non-empty`, expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/": version part: must be non-empty`,
}, { }, {
@ -82,6 +113,7 @@ func TestValidateServerStorageVersion(t *testing.T) {
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "/v3", EncodingVersion: "/v3",
DecodableVersions: []string{"mygroup.com/v2", "/v3"}, DecodableVersions: []string{"mygroup.com/v2", "/v3"},
ServedVersions: []string{"mygroup.com/v2", "/v3"},
}, },
expectedErr: `[].encodingVersion: Invalid value: "/v3": group part: must be non-empty`, expectedErr: `[].encodingVersion: Invalid value: "/v3": group part: must be non-empty`,
}, { }, {
@ -89,22 +121,57 @@ func TestValidateServerStorageVersion(t *testing.T) {
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "v1", EncodingVersion: "v1",
DecodableVersions: []string{"v1", "mygroup_com/v2"}, DecodableVersions: []string{"v1", "mygroup_com/v2"},
ServedVersions: []string{"v1", "mygroup_com/v2"},
}, },
expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup_com/v2": group part: a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`, expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup_com/v2": group part: a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`,
}, {
ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea",
EncodingVersion: "v1",
DecodableVersions: []string{"v1", "mygroup.com/v2"},
ServedVersions: []string{"v1", "mygroup_com/v2"},
},
expectedErr: `[].servedVersions[1]: Invalid value: "mygroup_com/v2": group part: a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')`,
}, { }, {
ssv: apiserverinternal.ServerStorageVersion{ ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "v1", EncodingVersion: "v1",
DecodableVersions: []string{"v1", "mygroup.com/v2_"}, DecodableVersions: []string{"v1", "mygroup.com/v2_"},
ServedVersions: []string{"v1", "mygroup.com/v2_"},
}, },
expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2_": version part: a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')`, expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2_": version part: a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')`,
}, {
ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea",
EncodingVersion: "v1",
DecodableVersions: []string{"v1", "mygroup.com/v2"},
ServedVersions: []string{"v1", "mygroup.com/v2_"},
},
expectedErr: `[].servedVersions[1]: Invalid value: "mygroup.com/v2_": version part: a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?')`,
}, { }, {
ssv: apiserverinternal.ServerStorageVersion{ ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea", APIServerID: "fea",
EncodingVersion: "v1", EncodingVersion: "v1",
DecodableVersions: []string{"v1", "mygroup.com/v2/myresource"}, DecodableVersions: []string{"v1", "mygroup.com/v2/myresource"},
ServedVersions: []string{"v1", "mygroup.com/v2/myresource"},
}, },
expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2/myresource": an apiVersion is a DNS-1035 label, which must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?') with an optional DNS subdomain prefix and '/' (e.g. 'example.com/MyVersion')`, expectedErr: `[].decodableVersions[1]: Invalid value: "mygroup.com/v2/myresource": an apiVersion is a DNS-1035 label, which must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?') with an optional DNS subdomain prefix and '/' (e.g. 'example.com/MyVersion')`,
}, {
ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea",
EncodingVersion: "v1",
DecodableVersions: []string{"v1", "mygroup.com/v2"},
ServedVersions: []string{"v1", "mygroup.com/v2/myresource"},
},
expectedErr: `[].servedVersions[1]: Invalid value: "mygroup.com/v2/myresource": an apiVersion is a DNS-1035 label, which must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123', regex used for validation is '[a-z]([-a-z0-9]*[a-z0-9])?') with an optional DNS subdomain prefix and '/' (e.g. 'example.com/MyVersion')`,
}, {
ssv: apiserverinternal.ServerStorageVersion{
APIServerID: "fea",
EncodingVersion: "v1alpha1",
DecodableVersions: []string{"v1alpha1", "v1"},
ServedVersions: []string{"v2"},
},
expectedErr: `[].servedVersions[0]: Invalid value: "v2": individual served version : v2 must be included in decodableVersions : [v1alpha1 v1]`,
}} }}
for _, tc := range cases { for _, tc := range cases {

View File

@ -33,6 +33,11 @@ func (in *ServerStorageVersion) DeepCopyInto(out *ServerStorageVersion) {
*out = make([]string, len(*in)) *out = make([]string, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.ServedVersions != nil {
in, out := &in.ServedVersions, &out.ServedVersions
*out = make([]string, len(*in))
copy(*out, *in)
}
return return
} }

View File

@ -3743,6 +3743,26 @@ func schema_k8sio_api_apiserverinternal_v1alpha1_ServerStorageVersion(ref common
}, },
}, },
}, },
"servedVersions": {
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-list-type": "set",
},
},
SchemaProps: spec.SchemaProps{
Description: "The API server can serve these versions. DecodableVersions must include all ServedVersions.",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
},
},
}, },
}, },
}, },

View File

@ -225,55 +225,57 @@ func init() {
} }
var fileDescriptor_a3903ff5e3cc7a03 = []byte{ var fileDescriptor_a3903ff5e3cc7a03 = []byte{
// 768 bytes of a gzipped FileDescriptorProto // 790 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xdf, 0x4e, 0x13, 0x4d, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x41, 0x4f, 0xdb, 0x48,
0x14, 0xef, 0xd2, 0x52, 0x60, 0xfa, 0x7d, 0xf4, 0x63, 0x3e, 0x08, 0xb5, 0x26, 0x5b, 0x6c, 0x82, 0x14, 0x8e, 0x49, 0x08, 0x30, 0xd9, 0x4d, 0x96, 0x59, 0x10, 0xd9, 0xac, 0xe4, 0xb0, 0x91, 0x58,
0x41, 0x8d, 0xbb, 0xd2, 0x88, 0x91, 0x98, 0x68, 0x58, 0x20, 0x06, 0x05, 0x31, 0x03, 0xf1, 0x02, 0xb1, 0xbb, 0x5a, 0x7b, 0x89, 0x96, 0xaa, 0xb4, 0x52, 0x2b, 0x0c, 0xa8, 0xa2, 0x85, 0x52, 0x4d,
0xbd, 0x70, 0xba, 0x3b, 0x6e, 0xd7, 0x76, 0x77, 0x36, 0x3b, 0xd3, 0x26, 0xdc, 0x18, 0x1f, 0xc1, 0x50, 0x0f, 0xb4, 0x87, 0x4e, 0xec, 0xa9, 0xe3, 0x26, 0xf6, 0x58, 0x9e, 0x49, 0x24, 0x2e, 0x55,
0x07, 0xf1, 0xd2, 0x87, 0xe0, 0xca, 0x70, 0x63, 0x42, 0x62, 0xd2, 0xc8, 0xfa, 0x16, 0x5c, 0x99, 0x7f, 0x42, 0xfb, 0x3f, 0x7a, 0xec, 0x8f, 0xe0, 0x54, 0x71, 0x44, 0xaa, 0x14, 0x15, 0xf7, 0x5f,
0x99, 0xdd, 0xb6, 0x6c, 0xbb, 0xc4, 0x86, 0x8b, 0x26, 0x9d, 0x73, 0xce, 0xef, 0x77, 0xfe, 0xcc, 0x70, 0xaa, 0x66, 0xec, 0x38, 0x38, 0x09, 0x6a, 0xc4, 0x21, 0x52, 0xe6, 0xbd, 0xf7, 0x7d, 0xef,
0x6f, 0xce, 0x82, 0x57, 0xcd, 0xc7, 0x4c, 0x73, 0xa8, 0xde, 0x6c, 0xd7, 0x49, 0xe0, 0x11, 0x4e, 0xcd, 0x37, 0xdf, 0x8c, 0xc1, 0xd3, 0xf6, 0x5d, 0xa6, 0x39, 0x54, 0x6f, 0x77, 0x9b, 0x24, 0xf0,
0x98, 0xde, 0x21, 0x9e, 0x45, 0x03, 0x3d, 0x76, 0x60, 0xdf, 0x11, 0x3f, 0x46, 0x82, 0x0e, 0x09, 0x08, 0x27, 0x4c, 0xef, 0x11, 0xcf, 0xa2, 0x81, 0x1e, 0x27, 0xb0, 0xef, 0x88, 0x1f, 0x23, 0x41,
0x1c, 0x8f, 0x93, 0xc0, 0xc3, 0x2d, 0xbd, 0xb3, 0x8a, 0x5b, 0x7e, 0x03, 0xaf, 0xea, 0x36, 0xf1, 0x8f, 0x04, 0x8e, 0xc7, 0x49, 0xe0, 0xe1, 0x8e, 0xde, 0xdb, 0xc0, 0x1d, 0xbf, 0x85, 0x37, 0x74,
0x48, 0x80, 0x39, 0xb1, 0x34, 0x3f, 0xa0, 0x9c, 0xc2, 0xe5, 0x08, 0xa6, 0x61, 0xdf, 0xd1, 0x46, 0x9b, 0x78, 0x24, 0xc0, 0x9c, 0x58, 0x9a, 0x1f, 0x50, 0x4e, 0xe1, 0x5a, 0x04, 0xd3, 0xb0, 0xef,
0x60, 0x5a, 0x0f, 0x56, 0xbe, 0x6f, 0x3b, 0xbc, 0xd1, 0xae, 0x6b, 0x26, 0x75, 0x75, 0x9b, 0xda, 0x68, 0x63, 0x30, 0x6d, 0x00, 0xab, 0xfc, 0x6b, 0x3b, 0xbc, 0xd5, 0x6d, 0x6a, 0x26, 0x75, 0x75,
0x54, 0x97, 0xe8, 0x7a, 0xfb, 0x83, 0x3c, 0xc9, 0x83, 0xfc, 0x17, 0xb1, 0x96, 0x1f, 0x0e, 0x8a, 0x9b, 0xda, 0x54, 0x97, 0xe8, 0x66, 0xf7, 0xb5, 0x5c, 0xc9, 0x85, 0xfc, 0x17, 0xb1, 0x56, 0xfe,
0x71, 0xb1, 0xd9, 0x70, 0x3c, 0x12, 0x1c, 0xeb, 0x7e, 0xd3, 0x96, 0x95, 0xe9, 0x2e, 0xe1, 0x58, 0x1f, 0x0e, 0xe3, 0x62, 0xb3, 0xe5, 0x78, 0x24, 0x38, 0xd5, 0xfd, 0xb6, 0x2d, 0x27, 0xd3, 0x5d,
0xef, 0x8c, 0xd4, 0x52, 0xd6, 0xaf, 0x42, 0x05, 0x6d, 0x8f, 0x3b, 0x2e, 0x19, 0x01, 0x3c, 0xfa, 0xc2, 0xb1, 0xde, 0x1b, 0x9b, 0xa5, 0xa2, 0xdf, 0x84, 0x0a, 0xba, 0x1e, 0x77, 0x5c, 0x32, 0x06,
0x1b, 0x80, 0x99, 0x0d, 0xe2, 0xe2, 0x61, 0x5c, 0xf5, 0x87, 0x02, 0xe6, 0x0f, 0x64, 0xa7, 0x07, 0xb8, 0xf3, 0x23, 0x00, 0x33, 0x5b, 0xc4, 0xc5, 0xa3, 0xb8, 0xda, 0x87, 0x19, 0xb0, 0xd4, 0x90,
0x9c, 0x06, 0xd8, 0x26, 0x6f, 0x48, 0xc0, 0x1c, 0xea, 0xc1, 0x35, 0x50, 0xc0, 0xbe, 0x13, 0xb9, 0x3b, 0x6d, 0x70, 0x1a, 0x60, 0x9b, 0x3c, 0x27, 0x01, 0x73, 0xa8, 0x07, 0x37, 0x41, 0x01, 0xfb,
0x76, 0xb6, 0x4a, 0xca, 0x92, 0xb2, 0x32, 0x63, 0xfc, 0x7f, 0xd2, 0xad, 0x64, 0xc2, 0x6e, 0xa5, 0x4e, 0x94, 0xda, 0xdf, 0x2d, 0x2b, 0xab, 0xca, 0xfa, 0x82, 0xf1, 0xeb, 0x59, 0xbf, 0x9a, 0x09,
0xb0, 0xf1, 0x7a, 0xa7, 0xe7, 0x42, 0x97, 0xe3, 0xe0, 0x06, 0x28, 0x12, 0xcf, 0xa4, 0x96, 0xe3, 0xfb, 0xd5, 0xc2, 0xf6, 0xb3, 0xfd, 0x41, 0x0a, 0x5d, 0xaf, 0x83, 0xdb, 0xa0, 0x44, 0x3c, 0x93,
0xd9, 0x31, 0x53, 0x69, 0x42, 0x42, 0x17, 0x63, 0x68, 0x71, 0x3b, 0xe9, 0x46, 0xc3, 0xf1, 0x70, 0x5a, 0x8e, 0x67, 0xc7, 0x4c, 0xe5, 0x19, 0x09, 0x5d, 0x89, 0xa1, 0xa5, 0xbd, 0x74, 0x1a, 0x8d,
0x13, 0xcc, 0x59, 0xc4, 0xa4, 0x16, 0xae, 0xb7, 0x7a, 0xd5, 0xb0, 0x52, 0x76, 0x29, 0xbb, 0x32, 0xd6, 0xc3, 0x1d, 0xb0, 0x68, 0x11, 0x93, 0x5a, 0xb8, 0xd9, 0x19, 0x4c, 0xc3, 0xca, 0xd9, 0xd5,
0x63, 0x2c, 0x84, 0xdd, 0xca, 0xdc, 0xd6, 0xb0, 0x13, 0x8d, 0xc6, 0x57, 0xbf, 0x4d, 0x80, 0xd9, 0xec, 0xfa, 0x82, 0xb1, 0x1c, 0xf6, 0xab, 0x8b, 0xbb, 0xa3, 0x49, 0x34, 0x5e, 0x0f, 0xef, 0x81,
0xa1, 0x8e, 0xde, 0x83, 0x69, 0x31, 0x6e, 0x0b, 0x73, 0x2c, 0xdb, 0x29, 0xd4, 0x1e, 0x68, 0x83, 0xa2, 0x3c, 0x40, 0x2b, 0x61, 0xc8, 0x49, 0x06, 0x18, 0xf6, 0xab, 0xc5, 0x46, 0x2a, 0x83, 0x46,
0x2b, 0xef, 0x4f, 0x4d, 0xf3, 0x9b, 0xb6, 0xbc, 0x7f, 0x4d, 0x44, 0x6b, 0x9d, 0x55, 0x6d, 0xbf, 0x2a, 0x6b, 0x9f, 0x66, 0x40, 0x71, 0x44, 0x8d, 0x57, 0x60, 0x5e, 0x1c, 0x95, 0x85, 0x39, 0x96,
0xfe, 0x91, 0x98, 0x7c, 0x8f, 0x70, 0x6c, 0xc0, 0xb8, 0x0b, 0x30, 0xb0, 0xa1, 0x3e, 0x2b, 0x7c, 0x52, 0x14, 0xea, 0xff, 0x69, 0x43, 0xbb, 0x24, 0x8a, 0x6b, 0x7e, 0xdb, 0x96, 0xde, 0xd1, 0x44,
0x0b, 0x72, 0xcc, 0x27, 0xa6, 0xec, 0xb8, 0x50, 0x5b, 0xd7, 0xc6, 0x12, 0x94, 0x96, 0x2c, 0xf3, 0xb5, 0xd6, 0xdb, 0xd0, 0x8e, 0x9a, 0x6f, 0x88, 0xc9, 0x0f, 0x09, 0xc7, 0x06, 0x8c, 0x15, 0x00,
0xc0, 0x27, 0xa6, 0xf1, 0x4f, 0x9c, 0x26, 0x27, 0x4e, 0x48, 0x92, 0x42, 0x13, 0xe4, 0x19, 0xc7, 0xc3, 0x18, 0x4a, 0x58, 0xe1, 0x0b, 0x90, 0x63, 0x3e, 0x31, 0xa5, 0x5a, 0x85, 0xfa, 0x96, 0x36,
0xbc, 0x2d, 0x66, 0x21, 0xe8, 0x9f, 0x5c, 0x8f, 0x5e, 0x52, 0x18, 0xb3, 0x71, 0x82, 0x7c, 0x74, 0x95, 0x19, 0xb5, 0xf4, 0x98, 0x0d, 0x9f, 0x98, 0xc6, 0x4f, 0x71, 0x9b, 0x9c, 0x58, 0x21, 0x49,
0x46, 0x31, 0x75, 0xf5, 0x6b, 0x16, 0x2c, 0x26, 0x01, 0x9b, 0xd4, 0xb3, 0x1c, 0x2e, 0xe6, 0xf7, 0x0a, 0x4d, 0x90, 0x67, 0x1c, 0xf3, 0xae, 0xd0, 0x51, 0xd0, 0xdf, 0xbf, 0x1d, 0xbd, 0xa4, 0x30,
0x0c, 0xe4, 0xf8, 0xb1, 0x4f, 0x62, 0x29, 0xdc, 0xeb, 0x95, 0x78, 0x78, 0xec, 0x93, 0x8b, 0x6e, 0x8a, 0x71, 0x83, 0x7c, 0xb4, 0x46, 0x31, 0x75, 0xed, 0x63, 0x16, 0xac, 0xa4, 0x01, 0x3b, 0xd4,
0xe5, 0xe6, 0x15, 0x30, 0xe1, 0x46, 0x12, 0x08, 0xd7, 0xfb, 0x1d, 0x44, 0x92, 0xb8, 0x95, 0x2c, 0xb3, 0x1c, 0x2e, 0xf4, 0x7b, 0x08, 0x72, 0xfc, 0xd4, 0x27, 0xb1, 0x8d, 0xfe, 0x19, 0x8c, 0x78,
0xe2, 0xa2, 0x5b, 0x29, 0xf6, 0x61, 0xc9, 0xba, 0xe0, 0x0b, 0x00, 0x69, 0x5d, 0x76, 0x68, 0x3d, 0x7c, 0xea, 0x93, 0xab, 0x7e, 0xf5, 0xf7, 0x1b, 0x60, 0x22, 0x8d, 0x24, 0x10, 0x6e, 0x25, 0x3b,
0x8f, 0x14, 0x2c, 0x94, 0x25, 0x06, 0x91, 0x35, 0xca, 0x31, 0x0d, 0xdc, 0x1f, 0x89, 0x40, 0x29, 0x88, 0xec, 0xf4, 0x47, 0x7a, 0x88, 0xab, 0x7e, 0xb5, 0x94, 0xc0, 0xd2, 0x73, 0xc1, 0xc7, 0x00,
0x28, 0xd8, 0x01, 0xb0, 0x85, 0x19, 0x3f, 0x0c, 0xb0, 0xc7, 0xa2, 0x12, 0x1d, 0x97, 0x94, 0x72, 0xd2, 0x66, 0x74, 0xc4, 0x8f, 0x22, 0xf7, 0x0b, 0x57, 0x0a, 0x21, 0xb2, 0x46, 0x25, 0xa6, 0x81,
0x72, 0xa8, 0x77, 0xc7, 0x53, 0x84, 0x40, 0x0c, 0xf2, 0xee, 0x8e, 0xb0, 0xa1, 0x94, 0x0c, 0xf0, 0x47, 0x63, 0x15, 0x68, 0x02, 0x0a, 0xf6, 0x00, 0xec, 0x60, 0xc6, 0x8f, 0x03, 0xec, 0xb1, 0x68,
0x36, 0xc8, 0x07, 0x04, 0x33, 0xea, 0x95, 0x26, 0x65, 0xfb, 0xfd, 0x3b, 0x40, 0xd2, 0x8a, 0x62, 0x44, 0xc7, 0x25, 0xe5, 0x9c, 0x14, 0xf5, 0xef, 0xe9, 0x1c, 0x21, 0x10, 0xc3, 0xbe, 0x07, 0x63,
0x2f, 0xbc, 0x03, 0xa6, 0x5c, 0xc2, 0x18, 0xb6, 0x49, 0x29, 0x2f, 0x03, 0x8b, 0x71, 0xe0, 0xd4, 0x6c, 0x68, 0x42, 0x07, 0xf8, 0x27, 0xc8, 0x07, 0x04, 0x33, 0xea, 0x95, 0x67, 0xe5, 0xf6, 0x93,
0x5e, 0x64, 0x46, 0x3d, 0x7f, 0xf5, 0xbb, 0x02, 0x60, 0x72, 0xee, 0xbb, 0x0e, 0xe3, 0xf0, 0xdd, 0x33, 0x40, 0x32, 0x8a, 0xe2, 0x2c, 0xfc, 0x0b, 0xcc, 0xb9, 0x84, 0x31, 0x6c, 0x93, 0x72, 0x5e,
0x88, 0xd2, 0xb5, 0xf1, 0xfa, 0x12, 0x68, 0xa9, 0xf3, 0xff, 0xe2, 0x94, 0xd3, 0x3d, 0xcb, 0x25, 0x16, 0x96, 0xe2, 0xc2, 0xb9, 0xc3, 0x28, 0x8c, 0x06, 0xf9, 0xda, 0x67, 0x05, 0xc0, 0xb4, 0xee,
0x95, 0x1f, 0x81, 0x49, 0x87, 0x13, 0x57, 0xdc, 0x62, 0x76, 0xa5, 0x50, 0x5b, 0xbb, 0x96, 0x0e, 0x07, 0x0e, 0xe3, 0xf0, 0xe5, 0x98, 0xd3, 0xb5, 0xe9, 0xf6, 0x25, 0xd0, 0xd2, 0xe7, 0xbf, 0xc4,
0x8d, 0x7f, 0xe3, 0x0c, 0x93, 0x3b, 0x82, 0x0b, 0x45, 0x94, 0xd5, 0xf9, 0xe1, 0x7e, 0xc4, 0x03, 0x2d, 0xe7, 0x07, 0x91, 0x6b, 0x2e, 0x3f, 0x01, 0xb3, 0x0e, 0x27, 0xae, 0x38, 0xc5, 0xec, 0x7a,
0xa8, 0xfe, 0x9c, 0x00, 0xf3, 0x69, 0x32, 0x86, 0x9f, 0x40, 0x91, 0x25, 0xec, 0xac, 0xa4, 0xc8, 0xa1, 0xbe, 0x79, 0x2b, 0x1f, 0x1a, 0x3f, 0xc7, 0x1d, 0x66, 0xf7, 0x05, 0x17, 0x8a, 0x28, 0x6b,
0xa2, 0xc6, 0x7e, 0x1c, 0x29, 0xab, 0x6f, 0xb0, 0xaa, 0x92, 0x76, 0x86, 0x86, 0x93, 0xc1, 0x7d, 0x4b, 0xa3, 0xfb, 0x11, 0x17, 0xa0, 0xf6, 0x45, 0x3c, 0x70, 0x13, 0x6c, 0x0c, 0xdf, 0x82, 0x12,
0xb0, 0x60, 0x52, 0xd7, 0xa5, 0xde, 0x76, 0xea, 0xce, 0xbb, 0x11, 0x76, 0x2b, 0x0b, 0x9b, 0x69, 0x4b, 0xc5, 0x59, 0x59, 0x91, 0x43, 0x4d, 0x7d, 0x39, 0x26, 0x3c, 0x9b, 0xc3, 0x67, 0x2e, 0x1d,
0x01, 0x28, 0x1d, 0x07, 0x03, 0x00, 0xcc, 0xde, 0x13, 0x88, 0x96, 0x5e, 0xa1, 0xf6, 0xf4, 0x5a, 0x67, 0x68, 0xb4, 0x19, 0x3c, 0x02, 0xcb, 0x26, 0x75, 0x5d, 0xea, 0xed, 0x4d, 0x7c, 0x2f, 0x7f,
0x03, 0xee, 0xbf, 0xa4, 0xc1, 0xce, 0xea, 0x9b, 0x18, 0xba, 0x94, 0xc5, 0x78, 0x79, 0x72, 0xae, 0x0b, 0xfb, 0xd5, 0xe5, 0x9d, 0x49, 0x05, 0x68, 0x32, 0x0e, 0x06, 0x00, 0x98, 0x83, 0x2b, 0x10,
0x66, 0x4e, 0xcf, 0xd5, 0xcc, 0xd9, 0xb9, 0x9a, 0xf9, 0x1c, 0xaa, 0xca, 0x49, 0xa8, 0x2a, 0xa7, 0x3d, 0x98, 0x85, 0xfa, 0x83, 0x5b, 0x09, 0x9c, 0xdc, 0xa4, 0xe1, 0x9b, 0x95, 0x84, 0x18, 0xba,
0xa1, 0xaa, 0x9c, 0x85, 0xaa, 0xf2, 0x2b, 0x54, 0x95, 0x2f, 0xbf, 0xd5, 0xcc, 0xd1, 0xf2, 0x58, 0xd6, 0xc5, 0x78, 0x72, 0x76, 0xa9, 0x66, 0xce, 0x2f, 0xd5, 0xcc, 0xc5, 0xa5, 0x9a, 0x79, 0x17,
0x1f, 0xd5, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa0, 0xd0, 0x65, 0xbc, 0x95, 0x07, 0x00, 0x00, 0xaa, 0xca, 0x59, 0xa8, 0x2a, 0xe7, 0xa1, 0xaa, 0x5c, 0x84, 0xaa, 0xf2, 0x35, 0x54, 0x95, 0xf7,
0xdf, 0xd4, 0xcc, 0xc9, 0xda, 0x54, 0x1f, 0xe4, 0xef, 0x01, 0x00, 0x00, 0xff, 0xff, 0xa0, 0x3a,
0x2e, 0x07, 0xd1, 0x07, 0x00, 0x00,
} }
func (m *ServerStorageVersion) Marshal() (dAtA []byte, err error) { func (m *ServerStorageVersion) Marshal() (dAtA []byte, err error) {
@ -296,6 +298,15 @@ func (m *ServerStorageVersion) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.ServedVersions) > 0 {
for iNdEx := len(m.ServedVersions) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.ServedVersions[iNdEx])
copy(dAtA[i:], m.ServedVersions[iNdEx])
i = encodeVarintGenerated(dAtA, i, uint64(len(m.ServedVersions[iNdEx])))
i--
dAtA[i] = 0x22
}
}
if len(m.DecodableVersions) > 0 { if len(m.DecodableVersions) > 0 {
for iNdEx := len(m.DecodableVersions) - 1; iNdEx >= 0; iNdEx-- { for iNdEx := len(m.DecodableVersions) - 1; iNdEx >= 0; iNdEx-- {
i -= len(m.DecodableVersions[iNdEx]) i -= len(m.DecodableVersions[iNdEx])
@ -582,6 +593,12 @@ func (m *ServerStorageVersion) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
} }
} }
if len(m.ServedVersions) > 0 {
for _, s := range m.ServedVersions {
l = len(s)
n += 1 + l + sovGenerated(uint64(l))
}
}
return n return n
} }
@ -685,6 +702,7 @@ func (this *ServerStorageVersion) String() string {
`APIServerID:` + fmt.Sprintf("%v", this.APIServerID) + `,`, `APIServerID:` + fmt.Sprintf("%v", this.APIServerID) + `,`,
`EncodingVersion:` + fmt.Sprintf("%v", this.EncodingVersion) + `,`, `EncodingVersion:` + fmt.Sprintf("%v", this.EncodingVersion) + `,`,
`DecodableVersions:` + fmt.Sprintf("%v", this.DecodableVersions) + `,`, `DecodableVersions:` + fmt.Sprintf("%v", this.DecodableVersions) + `,`,
`ServedVersions:` + fmt.Sprintf("%v", this.ServedVersions) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -896,6 +914,38 @@ func (m *ServerStorageVersion) Unmarshal(dAtA []byte) error {
} }
m.DecodableVersions = append(m.DecodableVersions, string(dAtA[iNdEx:postIndex])) m.DecodableVersions = append(m.DecodableVersions, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ServedVersions", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGenerated
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ServedVersions = append(m.ServedVersions, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:]) skippy, err := skipGenerated(dAtA[iNdEx:])

View File

@ -42,6 +42,11 @@ message ServerStorageVersion {
// The encodingVersion must be included in the decodableVersions. // The encodingVersion must be included in the decodableVersions.
// +listType=set // +listType=set
repeated string decodableVersions = 3; repeated string decodableVersions = 3;
// The API server can serve these versions.
// DecodableVersions must include all ServedVersions.
// +listType=set
repeated string servedVersions = 4;
} }
// Storage version of a specific resource. // Storage version of a specific resource.

View File

@ -77,6 +77,11 @@ type ServerStorageVersion struct {
// The encodingVersion must be included in the decodableVersions. // The encodingVersion must be included in the decodableVersions.
// +listType=set // +listType=set
DecodableVersions []string `json:"decodableVersions,omitempty" protobuf:"bytes,3,opt,name=decodableVersions"` DecodableVersions []string `json:"decodableVersions,omitempty" protobuf:"bytes,3,opt,name=decodableVersions"`
// The API server can serve these versions.
// DecodableVersions must include all ServedVersions.
// +listType=set
ServedVersions []string `json:"servedVersions,omitempty" protobuf:"bytes,4,opt,name=servedVersions"`
} }
type StorageVersionConditionType string type StorageVersionConditionType string

View File

@ -32,6 +32,7 @@ var map_ServerStorageVersion = map[string]string{
"apiServerID": "The ID of the reporting API server.", "apiServerID": "The ID of the reporting API server.",
"encodingVersion": "The API server encodes the object to this version when persisting it in the backend (e.g., etcd).", "encodingVersion": "The API server encodes the object to this version when persisting it in the backend (e.g., etcd).",
"decodableVersions": "The API server can decode objects encoded in these versions. The encodingVersion must be included in the decodableVersions.", "decodableVersions": "The API server can decode objects encoded in these versions. The encodingVersion must be included in the decodableVersions.",
"servedVersions": "The API server can serve these versions. DecodableVersions must include all ServedVersions.",
} }
func (ServerStorageVersion) SwaggerDoc() map[string]string { func (ServerStorageVersion) SwaggerDoc() map[string]string {

View File

@ -33,6 +33,11 @@ func (in *ServerStorageVersion) DeepCopyInto(out *ServerStorageVersion) {
*out = make([]string, len(*in)) *out = make([]string, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.ServedVersions != nil {
in, out := &in.ServedVersions, &out.ServedVersions
*out = make([]string, len(*in))
copy(*out, *in)
}
return return
} }

View File

@ -51,6 +51,9 @@
"encodingVersion": "encodingVersionValue", "encodingVersion": "encodingVersionValue",
"decodableVersions": [ "decodableVersions": [
"decodableVersionsValue" "decodableVersionsValue"
],
"servedVersions": [
"servedVersionsValue"
] ]
} }
], ],

View File

@ -47,3 +47,5 @@ status:
decodableVersions: decodableVersions:
- decodableVersionsValue - decodableVersionsValue
encodingVersion: encodingVersionValue encodingVersion: encodingVersionValue
servedVersions:
- servedVersionsValue

View File

@ -25,6 +25,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
serverstorage "k8s.io/apiserver/pkg/server/storage"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
_ "k8s.io/component-base/metrics/prometheus/workqueue" // for workqueue metric registration _ "k8s.io/component-base/metrics/prometheus/workqueue" // for workqueue metric registration
@ -51,7 +52,7 @@ type Manager interface {
// AddResourceInfo records resources whose StorageVersions need updates // AddResourceInfo records resources whose StorageVersions need updates
AddResourceInfo(resources ...*ResourceInfo) AddResourceInfo(resources ...*ResourceInfo)
// UpdateStorageVersions tries to update the StorageVersions of the recorded resources // UpdateStorageVersions tries to update the StorageVersions of the recorded resources
UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, apiserverID string) UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, apiserverID string, apiResourceConfigSource serverstorage.APIResourceConfigSource)
// PendingUpdate returns true if the StorageVersion of the given resource is still pending update. // PendingUpdate returns true if the StorageVersion of the given resource is still pending update.
PendingUpdate(gr schema.GroupResource) bool PendingUpdate(gr schema.GroupResource) bool
// LastUpdateError returns the last error hit when updating the storage version of the given resource. // LastUpdateError returns the last error hit when updating the storage version of the given resource.
@ -111,7 +112,7 @@ func (s *defaultManager) addPendingManagedStatusLocked(r *ResourceInfo) {
} }
// UpdateStorageVersions tries to update the StorageVersions of the recorded resources // UpdateStorageVersions tries to update the StorageVersions of the recorded resources
func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, serverID string) { func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.Config, serverID string, apiResourceConfigSource serverstorage.APIResourceConfigSource) {
clientset, err := kubernetes.NewForConfig(kubeAPIServerClientConfig) clientset, err := kubernetes.NewForConfig(kubeAPIServerClientConfig)
if err != nil { if err != nil {
utilruntime.HandleError(fmt.Errorf("failed to get clientset: %v", err)) utilruntime.HandleError(fmt.Errorf("failed to get clientset: %v", err))
@ -143,7 +144,14 @@ func (s *defaultManager) UpdateStorageVersions(kubeAPIServerClientConfig *rest.C
if len(gr.Group) == 0 { if len(gr.Group) == 0 {
gr.Group = "core" gr.Group = "core"
} }
if err := updateStorageVersionFor(sc, serverID, gr, r.EncodingVersion, decodableVersions); err != nil {
servedVersions := []string{}
for _, dv := range decodableVersions {
if apiResourceConfigSource.ResourceEnabled(gr.WithVersion(dv)) {
servedVersions = append(servedVersions, dv)
}
}
if err := updateStorageVersionFor(sc, serverID, gr, r.EncodingVersion, decodableVersions, servedVersions); err != nil {
utilruntime.HandleError(fmt.Errorf("failed to update storage version for %v: %v", r.GroupResource, err)) utilruntime.HandleError(fmt.Errorf("failed to update storage version for %v: %v", r.GroupResource, err))
s.recordStatusFailure(&r, err) s.recordStatusFailure(&r, err)
hasFailure = true hasFailure = true

View File

@ -123,12 +123,12 @@ func setStatusCondition(conditions *[]v1alpha1.StorageVersionCondition, newCondi
} }
// updateStorageVersionFor updates the storage version object for the resource. // updateStorageVersionFor updates the storage version object for the resource.
func updateStorageVersionFor(c Client, apiserverID string, gr schema.GroupResource, encodingVersion string, decodableVersions []string) error { func updateStorageVersionFor(c Client, apiserverID string, gr schema.GroupResource, encodingVersion string, decodableVersions []string, servedVersions []string) error {
retries := 3 retries := 3
var retry int var retry int
var err error var err error
for retry < retries { for retry < retries {
err = singleUpdate(c, apiserverID, gr, encodingVersion, decodableVersions) err = singleUpdate(c, apiserverID, gr, encodingVersion, decodableVersions, servedVersions)
if err == nil { if err == nil {
return nil return nil
} }
@ -145,7 +145,7 @@ func updateStorageVersionFor(c Client, apiserverID string, gr schema.GroupResour
return err return err
} }
func singleUpdate(c Client, apiserverID string, gr schema.GroupResource, encodingVersion string, decodableVersions []string) error { func singleUpdate(c Client, apiserverID string, gr schema.GroupResource, encodingVersion string, decodableVersions []string, servedVersions []string) error {
shouldCreate := false shouldCreate := false
name := fmt.Sprintf("%s.%s", gr.Group, gr.Resource) name := fmt.Sprintf("%s.%s", gr.Group, gr.Resource)
sv, err := c.Get(context.TODO(), name, metav1.GetOptions{}) sv, err := c.Get(context.TODO(), name, metav1.GetOptions{})
@ -157,7 +157,7 @@ func singleUpdate(c Client, apiserverID string, gr schema.GroupResource, encodin
sv = &v1alpha1.StorageVersion{} sv = &v1alpha1.StorageVersion{}
sv.ObjectMeta.Name = name sv.ObjectMeta.Name = name
} }
updatedSV := localUpdateStorageVersion(sv, apiserverID, encodingVersion, decodableVersions) updatedSV := localUpdateStorageVersion(sv, apiserverID, encodingVersion, decodableVersions, servedVersions)
if shouldCreate { if shouldCreate {
createdSV, err := c.Create(context.TODO(), updatedSV, metav1.CreateOptions{}) createdSV, err := c.Create(context.TODO(), updatedSV, metav1.CreateOptions{})
if err != nil { if err != nil {
@ -174,11 +174,12 @@ func singleUpdate(c Client, apiserverID string, gr schema.GroupResource, encodin
// localUpdateStorageVersion updates the input storageversion with given server storageversion info. // localUpdateStorageVersion updates the input storageversion with given server storageversion info.
// The function updates the input storageversion in place. // The function updates the input storageversion in place.
func localUpdateStorageVersion(sv *v1alpha1.StorageVersion, apiserverID, encodingVersion string, decodableVersions []string) *v1alpha1.StorageVersion { func localUpdateStorageVersion(sv *v1alpha1.StorageVersion, apiserverID, encodingVersion string, decodableVersions []string, servedVersions []string) *v1alpha1.StorageVersion {
newSSV := v1alpha1.ServerStorageVersion{ newSSV := v1alpha1.ServerStorageVersion{
APIServerID: apiserverID, APIServerID: apiserverID,
EncodingVersion: encodingVersion, EncodingVersion: encodingVersion,
DecodableVersions: decodableVersions, DecodableVersions: decodableVersions,
ServedVersions: servedVersions,
} }
foundSSV := false foundSSV := false
for i, ssv := range sv.Status.StorageVersions { for i, ssv := range sv.Status.StorageVersions {

View File

@ -32,27 +32,32 @@ var (
APIServerID: "1", APIServerID: "1",
EncodingVersion: "v1", EncodingVersion: "v1",
DecodableVersions: []string{"v1", "v2"}, DecodableVersions: []string{"v1", "v2"},
ServedVersions: []string{"v1"},
} }
ssv2 = v1alpha1.ServerStorageVersion{ ssv2 = v1alpha1.ServerStorageVersion{
APIServerID: "2", APIServerID: "2",
EncodingVersion: "v1", EncodingVersion: "v1",
DecodableVersions: []string{"v1", "v2"}, DecodableVersions: []string{"v1", "v2"},
ServedVersions: []string{"v1", "v2"},
} }
// ssv3 has a different encoding version // ssv3 has a different encoding version
ssv3 = v1alpha1.ServerStorageVersion{ ssv3 = v1alpha1.ServerStorageVersion{
APIServerID: "3", APIServerID: "3",
EncodingVersion: "v2", EncodingVersion: "v2",
DecodableVersions: []string{"v1", "v2"}, DecodableVersions: []string{"v1", "v2"},
ServedVersions: []string{"v1", "v2"},
} }
ssv4 = v1alpha1.ServerStorageVersion{ ssv4 = v1alpha1.ServerStorageVersion{
APIServerID: "4", APIServerID: "4",
EncodingVersion: "v1", EncodingVersion: "v1",
DecodableVersions: []string{"v1", "v2", "v4"}, DecodableVersions: []string{"v1", "v2", "v4"},
ServedVersions: []string{"v1", "v2"},
} }
ssv5 = v1alpha1.ServerStorageVersion{ ssv5 = v1alpha1.ServerStorageVersion{
APIServerID: "5", APIServerID: "5",
EncodingVersion: "v2", EncodingVersion: "v2",
DecodableVersions: []string{"v1", "v2", "v4"}, DecodableVersions: []string{"v1", "v2", "v4"},
ServedVersions: []string{"v1", "v2"},
} }
) )
@ -114,7 +119,7 @@ func TestLocalUpdateStorageVersion(t *testing.T) {
for _, tc := range tests { for _, tc := range tests {
sv := &v1alpha1.StorageVersion{Status: tc.old} sv := &v1alpha1.StorageVersion{Status: tc.old}
updated := localUpdateStorageVersion(sv, tc.newSSV.APIServerID, tc.newSSV.EncodingVersion, tc.newSSV.DecodableVersions) updated := localUpdateStorageVersion(sv, tc.newSSV.APIServerID, tc.newSSV.EncodingVersion, tc.newSSV.DecodableVersions, tc.newSSV.ServedVersions)
if tc.expectLastTransitionTimeUpdate == updated.Status.Conditions[0].LastTransitionTime.IsZero() { if tc.expectLastTransitionTimeUpdate == updated.Status.Conditions[0].LastTransitionTime.IsZero() {
t.Errorf("unexpected LastTransitionTime, expected update: %v, got: %v", t.Errorf("unexpected LastTransitionTime, expected update: %v, got: %v",
tc.expectLastTransitionTimeUpdate, updated.Status.Conditions[0].LastTransitionTime) tc.expectLastTransitionTimeUpdate, updated.Status.Conditions[0].LastTransitionTime)

View File

@ -24,6 +24,7 @@ type ServerStorageVersionApplyConfiguration struct {
APIServerID *string `json:"apiServerID,omitempty"` APIServerID *string `json:"apiServerID,omitempty"`
EncodingVersion *string `json:"encodingVersion,omitempty"` EncodingVersion *string `json:"encodingVersion,omitempty"`
DecodableVersions []string `json:"decodableVersions,omitempty"` DecodableVersions []string `json:"decodableVersions,omitempty"`
ServedVersions []string `json:"servedVersions,omitempty"`
} }
// ServerStorageVersionApplyConfiguration constructs an declarative configuration of the ServerStorageVersion type for use with // ServerStorageVersionApplyConfiguration constructs an declarative configuration of the ServerStorageVersion type for use with
@ -57,3 +58,13 @@ func (b *ServerStorageVersionApplyConfiguration) WithDecodableVersions(values ..
} }
return b return b
} }
// WithServedVersions adds the given value to the ServedVersions field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the ServedVersions field.
func (b *ServerStorageVersionApplyConfiguration) WithServedVersions(values ...string) *ServerStorageVersionApplyConfiguration {
for i := range values {
b.ServedVersions = append(b.ServedVersions, values[i])
}
return b
}

View File

@ -695,6 +695,12 @@ var schemaYAML = typed.YAMLObject(`types:
- name: encodingVersion - name: encodingVersion
type: type:
scalar: string scalar: string
- name: servedVersions
type:
list:
elementType:
scalar: string
elementRelationship: associative
- name: io.k8s.api.apiserverinternal.v1alpha1.StorageVersion - name: io.k8s.api.apiserverinternal.v1alpha1.StorageVersion
map: map:
fields: fields:

View File

@ -367,7 +367,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
// All apiservers (aggregator-apiserver, kube-apiserver, apiextensions-apiserver) // All apiservers (aggregator-apiserver, kube-apiserver, apiextensions-apiserver)
// share the same generic apiserver config. The same StorageVersion manager is used // share the same generic apiserver config. The same StorageVersion manager is used
// to register all built-in resources when the generic apiservers install APIs. // to register all built-in resources when the generic apiservers install APIs.
s.GenericAPIServer.StorageVersionManager.UpdateStorageVersions(hookContext.LoopbackClientConfig, s.GenericAPIServer.APIServerID) s.GenericAPIServer.StorageVersionManager.UpdateStorageVersions(hookContext.LoopbackClientConfig, s.GenericAPIServer.APIServerID, c.GenericConfig.MergedResourceConfig)
return false, nil return false, nil
}, hookContext.StopCh) }, hookContext.StopCh)
// Once the storage version updater finishes the first round of update, // Once the storage version updater finishes the first round of update,

View File

@ -31,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/features"
serverstorage "k8s.io/apiserver/pkg/server/storage"
"k8s.io/apiserver/pkg/storageversion" "k8s.io/apiserver/pkg/storageversion"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
@ -52,9 +53,9 @@ type wrappedStorageVersionManager struct {
completed <-chan struct{} completed <-chan struct{}
} }
func (w *wrappedStorageVersionManager) UpdateStorageVersions(loopbackClientConfig *rest.Config, serverID string) { func (w *wrappedStorageVersionManager) UpdateStorageVersions(loopbackClientConfig *rest.Config, serverID string, apiResourceConfigSource serverstorage.APIResourceConfigSource) {
<-w.startUpdateSV <-w.startUpdateSV
w.Manager.UpdateStorageVersions(loopbackClientConfig, serverID) w.Manager.UpdateStorageVersions(loopbackClientConfig, serverID, apiResourceConfigSource)
close(w.updateFinished) close(w.updateFinished)
<-w.finishUpdateSV <-w.finishUpdateSV
} }