diff --git a/hack/update-openapi-spec.sh b/hack/update-openapi-spec.sh index 46570855c6f..0b830b9c81a 100755 --- a/hack/update-openapi-spec.sh +++ b/hack/update-openapi-spec.sh @@ -72,7 +72,11 @@ fi # Start kube-apiserver # omit enums from static openapi snapshots used to generate clients until #109177 is resolved kube::log::status "Starting kube-apiserver" -kube-apiserver \ +# KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA ensures that the OpenAPI is updated with all APIs +# that are intended to be removed at a particular release during alpha. +# If a new version tag was just created and you are seeing an unrelated diff when adding +# a new API, run `KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA=false ./hack/update-openapi-spec.sh`. +KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA=${KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA:-true} kube-apiserver \ --bind-address="${API_HOST}" \ --secure-port="${API_PORT}" \ --etcd-servers="http://${ETCD_HOST}:${ETCD_PORT}" \ diff --git a/hack/verify-openapi-spec.sh b/hack/verify-openapi-spec.sh index a8eaf4ef3f2..707b94e1a02 100755 --- a/hack/verify-openapi-spec.sh +++ b/hack/verify-openapi-spec.sh @@ -15,6 +15,11 @@ # limitations under the License. # This script checks whether updating of OpenAPI specification is needed or not. +# It verifies that the OpenAPI specification is up to date in strict mode, and +# will fallback to check in non-strict mode if that fails. Strict mode removes +# all APIs marked # as removed in a particular version, while non-strict mode +# allows them to persist until the release cutoff. We allow non-strict to +# prevent CI failures when we bump the version number in the git tag. # We should run `hack/update-openapi-spec.sh` if OpenAPI specification is out of # date. # Usage: `hack/verify-openapi-spec.sh`. @@ -26,5 +31,7 @@ set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. source "${KUBE_ROOT}/hack/lib/verify-generated.sh" - -kube::verify::generated "Generated files need to be updated" "Please run 'hack/update-openapi-spec.sh'" hack/update-openapi-spec.sh "$@" +( + kube::verify::generated "Generated files failed strict alpha check and MAY need be updated" "Running verification again without strict alpha check" hack/update-openapi-spec.sh "$@" +) || \ +KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA=false kube::verify::generated "Generated files need to be updated" "Please run 'hack/update-openapi-spec.sh'" hack/update-openapi-spec.sh "$@" \ No newline at end of file diff --git a/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds.go b/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds.go index 28cc0bf05d3..026d3e87782 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds.go +++ b/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds.go @@ -35,8 +35,12 @@ import ( type resourceExpirationEvaluator struct { currentVersion *apimachineryversion.Version isAlpha bool + // Special flag checking for the existence of alpha.0 + // alpha.0 is a special case where everything merged to master is auto propagated to the release-1.n branch + isAlphaZero bool // This is usually set for testing for which tests need to be removed. This prevent insta-failing CI. // Set KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA to see what will be removed when we tag beta + // This flag only takes effect during alpha but not alphaZero. strictRemovedHandlingInAlpha bool // This is usually set by a cluster-admin looking for a short-term escape hatch after something bad happened. // This should be made a flag before merge @@ -64,6 +68,7 @@ func NewResourceExpirationEvaluator(currentVersion *apimachineryversion.Version) // Only keeps the major and minor versions from input version. ret.currentVersion = apimachineryversion.MajorMinor(currentVersion.Major(), currentVersion.Minor()) ret.isAlpha = strings.Contains(currentVersion.PreRelease(), "alpha") + ret.isAlphaZero = strings.Contains(currentVersion.PreRelease(), "alpha.0") if envString, ok := os.LookupEnv("KUBE_APISERVER_STRICT_REMOVED_API_HANDLING_IN_ALPHA"); !ok { // do nothing @@ -127,7 +132,7 @@ func (e *resourceExpirationEvaluator) ShouldServeForVersion(majorRemoved, minorR // at this point major and minor are equal, so this API should be removed when the current release GAs. // If this is an alpha tag, don't remove by default, but allow the option. // If the cluster-admin has requested serving one more release, allow it. - if e.isAlpha && e.strictRemovedHandlingInAlpha { // don't serve in alpha if we want strict handling + if e.isAlpha && !e.isAlphaZero && e.strictRemovedHandlingInAlpha { // don't serve in alpha.1+ if we want strict handling return false } if e.isAlpha { // alphas are allowed to continue serving expired betas while we clean up the test diff --git a/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds_test.go b/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds_test.go index 84403fd1587..56eb5cb4350 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/deleted_kinds_test.go @@ -42,10 +42,16 @@ func Test_newResourceExpirationEvaluator(t *testing.T) { expected: resourceExpirationEvaluator{currentVersion: apimachineryversion.MajorMinor(1, 20)}, }, { - name: "alpha", + name: "alpha .0", currentVersion: "v1.20.0-alpha.0.62+a5d22854a2ac21", - expected: resourceExpirationEvaluator{currentVersion: apimachineryversion.MajorMinor(1, 20), isAlpha: true}, + expected: resourceExpirationEvaluator{currentVersion: apimachineryversion.MajorMinor(1, 20), isAlpha: true, isAlphaZero: true}, }, + { + name: "alpha not .0", + currentVersion: "v1.20.0-alpha.1.62+a5d22854a2ac21", + expected: resourceExpirationEvaluator{currentVersion: apimachineryversion.MajorMinor(1, 20), isAlpha: true, isAlphaZero: false}, + }, + { name: "maintenance", currentVersion: "v1.20.1", @@ -196,6 +202,17 @@ func Test_resourceExpirationEvaluator_shouldServe(t *testing.T) { restStorage: storageRemovedIn(1, 20), expected: false, }, + { + name: "removed-in-curr-but-alpha-but-strict-and-alpha-zero", + resourceExpirationEvaluator: resourceExpirationEvaluator{ + currentVersion: apimachineryversion.MajorMinor(1, 20), + isAlpha: true, + isAlphaZero: true, + strictRemovedHandlingInAlpha: true, + }, + restStorage: storageRemovedIn(1, 20), + expected: true, + }, { name: "removed-in-prev-deferral-does-not-help", resourceExpirationEvaluator: resourceExpirationEvaluator{