Skip to content

Commit 11e6080

Browse files
Merge pull request #131196 from siyuanfoundation/forward-api
bug fix: fix version order in emulation forward compatibility. Kubernetes-commit: 640489ae0cefea2358b4d248aaae9b3b2128cf7d
2 parents e87c9db + 9ca332f commit 11e6080

File tree

9 files changed

+302
-162
lines changed

9 files changed

+302
-162
lines changed

go.mod

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ require (
4848
gopkg.in/evanphx/json-patch.v4 v4.12.0
4949
gopkg.in/go-jose/go-jose.v2 v2.6.3
5050
gopkg.in/natefinch/lumberjack.v2 v2.2.1
51-
k8s.io/api v0.0.0
52-
k8s.io/apimachinery v0.0.0
53-
k8s.io/client-go v0.0.0
54-
k8s.io/component-base v0.0.0
51+
k8s.io/api v0.0.0-20250411021314-16cedc7a66ae
52+
k8s.io/apimachinery v0.0.0-20250411020758-955939ffb819
53+
k8s.io/client-go v0.0.0-20250411022055-ecbbb0606499
54+
k8s.io/component-base v0.0.0-20250411023622-8e0b9e84850c
5555
k8s.io/klog/v2 v2.130.1
56-
k8s.io/kms v0.0.0
56+
k8s.io/kms v0.0.0-20250411024139-18052dfff32e
5757
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
5858
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
5959
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2
@@ -124,11 +124,3 @@ require (
124124
gopkg.in/inf.v0 v0.9.1 // indirect
125125
gopkg.in/yaml.v3 v3.0.1 // indirect
126126
)
127-
128-
replace (
129-
k8s.io/api => ../api
130-
k8s.io/apimachinery => ../apimachinery
131-
k8s.io/client-go => ../client-go
132-
k8s.io/component-base => ../component-base
133-
k8s.io/kms => ../kms
134-
)

go.sum

Lines changed: 10 additions & 141 deletions
Large diffs are not rendered by default.

pkg/server/config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,9 @@ type Config struct {
156156
EffectiveVersion basecompatibility.EffectiveVersion
157157
// EmulationForwardCompatible is an option to implicitly enable all APIs which are introduced after the emulation version and
158158
// have higher priority than APIs of the same group resource enabled at the emulation version.
159-
// If true, all APIs that have higher priority than the APIs of the same group resource enabled at the emulation version will be installed.
159+
// If true, all APIs that have higher priority than the APIs(beta+) of the same group resource enabled at the emulation version will be installed.
160160
// This is needed when a controller implementation migrates to newer API versions, for the binary version, and also uses the newer API versions even when emulation version is set.
161+
// Not applicable to alpha APIs.
161162
EmulationForwardCompatible bool
162163
// RuntimeConfigEmulationForwardCompatible is an option to explicitly enable specific APIs introduced after the emulation version through the runtime-config.
163164
// If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. --runtime-config flag values that identify multiple APIs, such as api/all,api/ga,api/beta, are not influenced by this flag and will only enable APIs available at the current emulation version.

pkg/server/deleted_kinds.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"os"
2222
"regexp"
23+
"sort"
2324
"strconv"
2425
"strings"
2526

@@ -28,6 +29,7 @@ import (
2829
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2930
"k8s.io/apimachinery/pkg/util/sets"
3031
apimachineryversion "k8s.io/apimachinery/pkg/util/version"
32+
"k8s.io/apimachinery/pkg/version"
3133
"k8s.io/apiserver/pkg/registry/rest"
3234
serverstorage "k8s.io/apiserver/pkg/server/storage"
3335
"k8s.io/klog/v2"
@@ -71,6 +73,7 @@ type ResourceExpirationEvaluatorOptions struct {
7173
Prerelease string
7274
// EmulationForwardCompatible indicates whether the apiserver should serve resources that are introduced after the current version,
7375
// when resources of the same group and resource name but with lower priority are served.
76+
// Not applicable to alpha APIs.
7477
EmulationForwardCompatible bool
7578
// RuntimeConfigEmulationForwardCompatible indicates whether the apiserver should serve resources that are introduced after the current version,
7679
// when the resource is explicitly enabled in runtime-config.
@@ -222,6 +225,9 @@ func (e *resourceExpirationEvaluator) RemoveUnavailableKinds(groupName string, v
222225
func (e *resourceExpirationEvaluator) removeUnintroducedKinds(groupName string, versioner runtime.ObjectVersioner, versionedResourcesStorageMap map[string]map[string]rest.Storage, apiResourceConfigSource serverstorage.APIResourceConfigSource) error {
223226
versionsToRemove := sets.NewString()
224227
prioritizedVersions := versioner.PrioritizedVersionsForGroup(groupName)
228+
sort.Slice(prioritizedVersions, func(i, j int) bool {
229+
return version.CompareKubeAwareVersionStrings(prioritizedVersions[i].Version, prioritizedVersions[j].Version) > 0
230+
})
225231
enabledResources := sets.NewString()
226232

227233
// iterate from the end to the front, so that we remove the lower priority versions first.

pkg/server/deleted_kinds_test.go

Lines changed: 260 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,13 +801,272 @@ func Test_removeUnIntroducedKinds(t *testing.T) {
801801
},
802802
},
803803
},
804+
{
805+
name: "both-runtime-config-and-emulation-forward-compatible-runtime-config-alpha-api",
806+
resourceExpirationEvaluator: resourceExpirationEvaluator{
807+
currentVersion: apimachineryversion.MajorMinor(1, 19),
808+
runtimeConfigEmulationForwardCompatible: true,
809+
emulationForwardCompatible: true,
810+
},
811+
runtimeConfig: map[string]string{
812+
groupName + "/v2alpha1": "true",
813+
},
814+
versionedResourcesStorageMap: map[string]map[string]rest.Storage{
815+
"v1": {
816+
resource1: storageIntroducedIn(1, 19),
817+
},
818+
"v2alpha1": {
819+
resource1: storageIntroducedAndRemovedIn(1, 20, 1, 21),
820+
resource2: storageIntroducedAndRemovedIn(1, 20, 1, 21),
821+
},
822+
"v2beta1": {
823+
resource1: storageIntroducedAndRemovedIn(1, 21, 1, 22),
824+
},
825+
"v2beta2": {
826+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
827+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
828+
},
829+
"v2": {
830+
resource1: storageIntroducedIn(1, 23),
831+
resource2: storageIntroducedIn(1, 23),
832+
},
833+
},
834+
expectedStorage: map[string]map[string]rest.Storage{
835+
"v1": {
836+
resource1: storageIntroducedIn(1, 19),
837+
},
838+
"v2alpha1": {
839+
resource1: storageIntroducedAndRemovedIn(1, 20, 1, 21),
840+
resource2: storageIntroducedAndRemovedIn(1, 20, 1, 21),
841+
},
842+
"v2": {
843+
resource1: storageIntroducedIn(1, 23),
844+
},
845+
},
846+
},
847+
{
848+
name: "both-runtime-config-and-emulation-forward-compatible-runtime-config-alpha-resource",
849+
resourceExpirationEvaluator: resourceExpirationEvaluator{
850+
currentVersion: apimachineryversion.MajorMinor(1, 19),
851+
runtimeConfigEmulationForwardCompatible: true,
852+
emulationForwardCompatible: true,
853+
},
854+
runtimeConfig: map[string]string{
855+
groupName + "/v2alpha1/resource2": "true",
856+
},
857+
versionedResourcesStorageMap: map[string]map[string]rest.Storage{
858+
"v1": {
859+
resource1: storageIntroducedIn(1, 19),
860+
},
861+
"v2alpha1": {
862+
resource1: storageIntroducedAndRemovedIn(1, 20, 1, 21),
863+
resource2: storageIntroducedAndRemovedIn(1, 20, 1, 21),
864+
},
865+
"v2beta1": {
866+
resource1: storageIntroducedAndRemovedIn(1, 21, 1, 22),
867+
},
868+
"v2beta2": {
869+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
870+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
871+
},
872+
"v2": {
873+
resource1: storageIntroducedIn(1, 23),
874+
resource2: storageIntroducedIn(1, 23),
875+
},
876+
},
877+
expectedStorage: map[string]map[string]rest.Storage{
878+
"v1": {
879+
resource1: storageIntroducedIn(1, 19),
880+
},
881+
"v2alpha1": {
882+
resource2: storageIntroducedAndRemovedIn(1, 20, 1, 21),
883+
},
884+
"v2": {
885+
resource1: storageIntroducedIn(1, 23),
886+
},
887+
},
888+
},
889+
{
890+
name: "emulation-forward-compatible-beta1-api",
891+
resourceExpirationEvaluator: resourceExpirationEvaluator{
892+
currentVersion: apimachineryversion.MajorMinor(1, 21),
893+
emulationForwardCompatible: true,
894+
},
895+
runtimeConfig: map[string]string{
896+
groupName + "/v2beta1": "true",
897+
},
898+
versionedResourcesStorageMap: map[string]map[string]rest.Storage{
899+
"v1": {
900+
resource1: storageIntroducedIn(1, 20),
901+
},
902+
"v2beta1": {
903+
resource1: storageIntroducedAndRemovedIn(1, 21, 1, 22),
904+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
905+
},
906+
"v2beta2": {
907+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
908+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
909+
},
910+
"v2": {
911+
resource1: storageIntroducedIn(1, 23),
912+
resource2: storageIntroducedIn(1, 23),
913+
},
914+
},
915+
expectedStorage: map[string]map[string]rest.Storage{
916+
"v1": {
917+
resource1: storageIntroducedIn(1, 20),
918+
},
919+
"v2beta1": {
920+
resource1: storageIntroducedAndRemovedIn(1, 21, 1, 22),
921+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
922+
},
923+
"v2beta2": {
924+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
925+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
926+
},
927+
"v2": {
928+
resource1: storageIntroducedIn(1, 23),
929+
resource2: storageIntroducedIn(1, 23),
930+
},
931+
},
932+
},
933+
{
934+
name: "emulation-forward-compatible-beta1-resource",
935+
resourceExpirationEvaluator: resourceExpirationEvaluator{
936+
currentVersion: apimachineryversion.MajorMinor(1, 21),
937+
emulationForwardCompatible: true,
938+
},
939+
runtimeConfig: map[string]string{
940+
groupName + "/v2beta1/resource2": "true",
941+
},
942+
versionedResourcesStorageMap: map[string]map[string]rest.Storage{
943+
"v1": {
944+
resource1: storageIntroducedIn(1, 20),
945+
},
946+
"v2beta1": {
947+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
948+
},
949+
"v2beta2": {
950+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
951+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
952+
},
953+
"v2": {
954+
resource1: storageIntroducedIn(1, 23),
955+
resource2: storageIntroducedIn(1, 23),
956+
},
957+
},
958+
expectedStorage: map[string]map[string]rest.Storage{
959+
"v1": {
960+
resource1: storageIntroducedIn(1, 20),
961+
},
962+
"v2beta1": {
963+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
964+
},
965+
"v2beta2": {
966+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
967+
},
968+
"v2": {
969+
resource1: storageIntroducedIn(1, 23),
970+
resource2: storageIntroducedIn(1, 23),
971+
},
972+
},
973+
},
974+
{
975+
name: "both-runtime-config-and-emulation-forward-compatible-runtime-config-beta1-api",
976+
resourceExpirationEvaluator: resourceExpirationEvaluator{
977+
currentVersion: apimachineryversion.MajorMinor(1, 20),
978+
emulationForwardCompatible: true,
979+
runtimeConfigEmulationForwardCompatible: true,
980+
},
981+
runtimeConfig: map[string]string{
982+
groupName + "/v2beta1": "true",
983+
},
984+
versionedResourcesStorageMap: map[string]map[string]rest.Storage{
985+
"v1": {
986+
resource1: storageIntroducedIn(1, 20),
987+
},
988+
"v2beta1": {
989+
resource1: storageIntroducedAndRemovedIn(1, 21, 1, 22),
990+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
991+
},
992+
"v2beta2": {
993+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
994+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
995+
},
996+
"v2": {
997+
resource1: storageIntroducedIn(1, 23),
998+
resource2: storageIntroducedIn(1, 23),
999+
},
1000+
},
1001+
expectedStorage: map[string]map[string]rest.Storage{
1002+
"v1": {
1003+
resource1: storageIntroducedIn(1, 20),
1004+
},
1005+
"v2beta1": {
1006+
resource1: storageIntroducedAndRemovedIn(1, 21, 1, 22),
1007+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
1008+
},
1009+
"v2beta2": {
1010+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
1011+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
1012+
},
1013+
"v2": {
1014+
resource1: storageIntroducedIn(1, 23),
1015+
resource2: storageIntroducedIn(1, 23),
1016+
},
1017+
},
1018+
},
1019+
{
1020+
name: "both-runtime-config-and-emulation-forward-compatible-runtime-config-beta1-resource",
1021+
resourceExpirationEvaluator: resourceExpirationEvaluator{
1022+
currentVersion: apimachineryversion.MajorMinor(1, 20),
1023+
emulationForwardCompatible: true,
1024+
runtimeConfigEmulationForwardCompatible: true,
1025+
},
1026+
runtimeConfig: map[string]string{
1027+
groupName + "/v2beta1/resource2": "true",
1028+
},
1029+
versionedResourcesStorageMap: map[string]map[string]rest.Storage{
1030+
"v1": {
1031+
resource1: storageIntroducedIn(1, 20),
1032+
},
1033+
"v2beta1": {
1034+
resource1: storageIntroducedAndRemovedIn(1, 21, 1, 22),
1035+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
1036+
},
1037+
"v2beta2": {
1038+
resource1: storageIntroducedAndRemovedIn(1, 22, 1, 23),
1039+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
1040+
},
1041+
"v2": {
1042+
resource1: storageIntroducedIn(1, 23),
1043+
resource2: storageIntroducedIn(1, 23),
1044+
},
1045+
},
1046+
expectedStorage: map[string]map[string]rest.Storage{
1047+
"v1": {
1048+
resource1: storageIntroducedIn(1, 20),
1049+
},
1050+
"v2beta1": {
1051+
resource2: storageIntroducedAndRemovedIn(1, 21, 1, 22),
1052+
},
1053+
"v2beta2": {
1054+
resource2: storageIntroducedAndRemovedIn(1, 22, 1, 23),
1055+
},
1056+
"v2": {
1057+
resource1: storageIntroducedIn(1, 23),
1058+
resource2: storageIntroducedIn(1, 23),
1059+
},
1060+
},
1061+
},
8041062
}
8051063
for _, tt := range tests {
8061064
t.Run(tt.name, func(t *testing.T) {
8071065
resourceConfig := serverstorage.NewResourceConfig()
8081066
convertor := &dummyConvertor{prioritizedVersions: []schema.GroupVersion{
8091067
{Group: groupName, Version: "v2"}, {Group: groupName, Version: "v1"},
810-
{Group: groupName, Version: "v2beta2"}, {Group: groupName, Version: "v2beta1"},
1068+
{Group: groupName, Version: "v2beta1"},
1069+
{Group: groupName, Version: "v2beta2"},
8111070
{Group: groupName, Version: "v2alpha1"}}}
8121071
resourceConfig.EnableVersions(convertor.PrioritizedVersionsForGroup(groupName)...)
8131072
resourceConfig, err := resourceconfig.MergeAPIResourceConfigs(resourceConfig, tt.runtimeConfig, convertor)

pkg/server/genericapiserver.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,9 @@ type GenericAPIServer struct {
247247
EffectiveVersion basecompatibility.EffectiveVersion
248248
// EmulationForwardCompatible is an option to implicitly enable all APIs which are introduced after the emulation version and
249249
// have higher priority than APIs of the same group resource enabled at the emulation version.
250-
// If true, all APIs that have higher priority than the APIs of the same group resource enabled at the emulation version will be installed.
250+
// If true, all APIs that have higher priority than the APIs(beta+) of the same group resource enabled at the emulation version will be installed.
251251
// This is needed when a controller implementation migrates to newer API versions, for the binary version, and also uses the newer API versions even when emulation version is set.
252+
// Not applicable to alpha APIs.
252253
EmulationForwardCompatible bool
253254
// RuntimeConfigEmulationForwardCompatible is an option to explicitly enable specific APIs introduced after the emulation version through the runtime-config.
254255
// If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. --runtime-config flag values that identify multiple APIs, such as api/all,api/ga,api/beta, are not influenced by this flag and will only enable APIs available at the current emulation version.

pkg/server/options/server_run_options.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ type ServerRunOptions struct {
100100
ComponentName string
101101
// EmulationForwardCompatible is an option to implicitly enable all APIs which are introduced after the emulation version and
102102
// have higher priority than APIs of the same group resource enabled at the emulation version.
103-
// If true, all APIs that have higher priority than the APIs of the same group resource enabled at the emulation version will be installed.
103+
// If true, all APIs that have higher priority than the APIs(beta+) of the same group resource enabled at the emulation version will be installed.
104104
// This is needed when a controller implementation migrates to newer API versions, for the binary version, and also uses the newer API versions even when emulation version is set.
105+
// Not applicable to alpha APIs.
105106
EmulationForwardCompatible bool
106107
// RuntimeConfigEmulationForwardCompatible is an option to explicitly enable specific APIs introduced after the emulation version through the runtime-config.
107108
// If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. --runtime-config flag values that identify multiple APIs, such as api/all,api/ga,api/beta, are not influenced by this flag and will only enable APIs available at the current emulation version.
@@ -399,10 +400,11 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
399400

400401
s.ComponentGlobalsRegistry.AddFlags(fs)
401402
fs.BoolVar(&s.EmulationForwardCompatible, "emulation-forward-compatible", s.EmulationForwardCompatible, ""+
402-
"If true all APIs that have higher priority than the APIs enabled at the emulation version of the same group resource will be installed. "+
403+
"If true, for any beta+ APIs enabled by default or by --runtime-config at the emulation version, their future versions with higher priority/stability will be auto enabled even if they introduced after the emulation version. "+
403404
"Can only be set to true if the emulation version is lower than the binary version.")
404405
fs.BoolVar(&s.RuntimeConfigEmulationForwardCompatible, "runtime-config-emulation-forward-compatible", s.RuntimeConfigEmulationForwardCompatible, ""+
405406
"If true, APIs identified by group/version that are enabled in the --runtime-config flag will be installed even if it is introduced after the emulation version. "+
407+
"If false, server would fail to start if any APIs identified by group/version that are enabled in the --runtime-config flag are introduced after the emulation version. "+
406408
"Can only be set to true if the emulation version is lower than the binary version.")
407409
}
408410

0 commit comments

Comments
 (0)