fix(api): declare OpenAPIModelName for apps types so SSA resolves catalog kinds

After the k8s 0.35 bump, server-side apply of any apps.cozystack.io kind
(e.g. Bucket) fails at field management with "no corresponding type for
apps.cozystack.io/v1alpha1, Kind=Bucket", blocking backupstrategy-controller
and the whole install.

The apps API multiplexes every catalog kind (Bucket, Postgres, …) onto the
single Application Go type via Scheme.AddKnownTypeWithName. The SSA field
manager attaches a kind's GroupVersionKind to the Application OpenAPI model
only when the model's name matches the name the apiserver's DefinitionNamer
computed for it. Since Kubernetes 0.35 the DefinitionNamer keys that lookup by
Scheme.ToOpenAPIDefinitionName (the "friendly" reversed-path form,
com.github.cozystack…Application) while the model builder still uses the Go
import-path form. With no OpenAPIModelName the two disagree, the GVK extension
is never attached, and the type converter ends up with no apps kinds at all.

Declare OpenAPIModelName on Application/ApplicationList/ApplicationStatus so
GetCanonicalTypeName, ToOpenAPIDefinitionName and the generated openapi map key
all agree on the friendly form. This is done via the +k8s:openapi-model-package
package tag plus hand-written methods rather than code-generator's
--output-model-name-file flag, because that flag also rewrites
zz_generated.model_name.go inside the read-only apimachinery / apiextensions
module-cache packages the shared gen_openapi helper always passes as inputs,
which fails on any consumer (including CI) that vendors deps from the cache.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
This commit is contained in:
Myasnikov Daniil committed 2026-07-16 16:45:17 +05:00
1 parent 1ea4eb452c
commit b916d7475b
3 files changed
+64 -7

No files matched your search

+1
View File
@@ -15,6 +15,7 @@ limitations under the License.
*/
// +k8s:openapi-gen=true
// +k8s:openapi-model-package=com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1
// +k8s:deepcopy-gen=package
// +k8s:conversion-gen=github.com/cozystack/cozystack/pkg/apis/apps
// +k8s:conversion-gen=k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
+55
View File
@@ -0,0 +1,55 @@
/*
Copyright 2025 The Cozystack Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
// OpenAPIModelName pins the OpenAPI model name for the apps.cozystack.io
// types. This is hand-written (not generated) on purpose.
//
// The apps API multiplexes every catalog kind (Bucket, Postgres, …) onto the
// single Application Go type via Scheme.AddKnownTypeWithName. Server-side-apply
// field management resolves a kind by matching the model's OpenAPI name against
// the name the apiserver's DefinitionNamer computed for it. Since Kubernetes
// 0.35 the DefinitionNamer keys that lookup by Scheme.ToOpenAPIDefinitionName
// (the "friendly" reversed-path form, e.g. com.github.cozystack…Application),
// while the model builder still looks it up by the Go import-path form. When a
// type has no OpenAPIModelName the two disagree, the group-version-kind
// extension is never attached to the Application model, and the SSA type
// converter ends up with no entry for any apps kind ("no corresponding type for
// apps.cozystack.io/v1alpha1, Kind=Bucket"). Declaring OpenAPIModelName makes
// GetCanonicalTypeName, ToOpenAPIDefinitionName and the generated openapi map
// key all agree on the friendly form, so the extension attaches again.
//
// code-generator's openapi-gen could emit these via --output-model-name-file,
// but that also rewrites zz_generated.model_name.go in the read-only apimachinery
// / apiextensions module-cache packages the shared gen_openapi helper always
// passes as inputs, which fails on any consumer (including CI) that vendors deps
// from the module cache. Keeping the methods here sidesteps that; add one for
// every new apps.cozystack.io type.
//
// The returned string must match apiPrefix in pkg/cmd/server/openapi.go.
func (in Application) OpenAPIModelName() string {
return "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Application"
}
func (in ApplicationList) OpenAPIModelName() string {
return "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.ApplicationList"
}
func (in ApplicationStatus) OpenAPIModelName() string {
return "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.ApplicationStatus"
}
@@ -22,6 +22,7 @@ limitations under the License.
package openapi
import (
v1alpha1 "github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1"
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
resource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -33,9 +34,9 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.Application": schema_pkg_apis_apps_v1alpha1_Application(ref),
"github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationList": schema_pkg_apis_apps_v1alpha1_ApplicationList(ref),
"github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationStatus": schema_pkg_apis_apps_v1alpha1_ApplicationStatus(ref),
v1alpha1.Application{}.OpenAPIModelName(): schema_pkg_apis_apps_v1alpha1_Application(ref),
v1alpha1.ApplicationList{}.OpenAPIModelName(): schema_pkg_apis_apps_v1alpha1_ApplicationList(ref),
v1alpha1.ApplicationStatus{}.OpenAPIModelName(): schema_pkg_apis_apps_v1alpha1_ApplicationStatus(ref),
"github.com/cozystack/cozystack/pkg/apis/core/v1alpha1.Option": schema_pkg_apis_core_v1alpha1_Option(ref),
"github.com/cozystack/cozystack/pkg/apis/core/v1alpha1.OptionItem": schema_pkg_apis_core_v1alpha1_OptionItem(ref),
"github.com/cozystack/cozystack/pkg/apis/core/v1alpha1.OptionList": schema_pkg_apis_core_v1alpha1_OptionList(ref),
@@ -181,14 +182,14 @@ func schema_pkg_apis_apps_v1alpha1_Application(ref common.ReferenceCallback) com
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationStatus"),
Ref: ref(v1alpha1.ApplicationStatus{}.OpenAPIModelName()),
},
},
},
},
},
Dependencies: []string{
"github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.ApplicationStatus", v1.JSON{}.OpenAPIModelName(), metav1.ObjectMeta{}.OpenAPIModelName()},
v1alpha1.ApplicationStatus{}.OpenAPIModelName(), v1.JSON{}.OpenAPIModelName(), metav1.ObjectMeta{}.OpenAPIModelName()},
}
}
@@ -226,7 +227,7 @@ func schema_pkg_apis_apps_v1alpha1_ApplicationList(ref common.ReferenceCallback)
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.Application"),
Ref: ref(v1alpha1.Application{}.OpenAPIModelName()),
},
},
},
@@ -237,7 +238,7 @@ func schema_pkg_apis_apps_v1alpha1_ApplicationList(ref common.ReferenceCallback)
},
},
Dependencies: []string{
"github.com/cozystack/cozystack/pkg/apis/apps/v1alpha1.Application", metav1.ListMeta{}.OpenAPIModelName()},
v1alpha1.Application{}.OpenAPIModelName(), metav1.ListMeta{}.OpenAPIModelName()},
}
}