Skip to content

Commit f7f5112

Browse files
committed
Fix OpenAPIv2 definitions for dynamic resources
1 parent 647a557 commit f7f5112

File tree

4 files changed

+92
-9
lines changed

4 files changed

+92
-9
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
cozystackAPI:
2-
image: ghcr.io/aenix-io/cozystack/cozystack-api:v0.18.0@sha256:d3f817ee20cc502b7c5deffa46a1ad94a6e1a74fa035dbeb65ef742e67fd1fe5
2+
image: ghcr.io/aenix-io/cozystack/cozystack-api:latest@sha256:96d277a34aff6d9847251da521ca86615af2aae370ec095d046112bc4044ddea

pkg/apis/apps/v1alpha1/register.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import (
2828
// GroupName holds the API group name.
2929
const GroupName = "apps.cozystack.io"
3030

31+
var (
32+
RegisteredGVKs []schema.GroupVersionKind
33+
)
34+
3135
// SchemeGroupVersion is group version used to register these objects
3236
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
3337

@@ -70,7 +74,7 @@ func RegisterDynamicTypes(scheme *runtime.Scheme, cfg *config.ResourceConfig) er
7074
scheme.AddKnownTypeWithName(gvk.GroupVersion().WithKind(kind+"List"), &ApplicationList{})
7175

7276
log.Printf("Registered kind: %s\n", kind)
73-
77+
RegisteredGVKs = append(RegisteredGVKs, gvk)
7478
}
7579

7680
return nil

pkg/apiserver/apiserver.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131

3232
"github.com/aenix.io/cozystack/pkg/apis/apps"
3333
"github.com/aenix.io/cozystack/pkg/apis/apps/install"
34-
appsv1alpha1 "github.com/aenix.io/cozystack/pkg/apis/apps/v1alpha1"
3534
"github.com/aenix.io/cozystack/pkg/config"
3635
appsregistry "github.com/aenix.io/cozystack/pkg/registry"
3736
applicationstorage "github.com/aenix.io/cozystack/pkg/registry/apps/application"
@@ -112,12 +111,6 @@ func (c completedConfig) New() (*AppsServer, error) {
112111

113112
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apps.GroupName, Scheme, metav1.ParameterCodec, Codecs)
114113

115-
// Dynamically register types based on the configuration.
116-
err = appsv1alpha1.RegisterDynamicTypes(Scheme, c.ResourceConfig)
117-
if err != nil {
118-
return nil, fmt.Errorf("failed to register dynamic types: %v", err)
119-
}
120-
121114
// Create a dynamic client for HelmRelease using InClusterConfig.
122115
inClusterConfig, err := restclient.InClusterConfig()
123116
if err != nil {

pkg/cmd/server/start.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package server
1818

1919
import (
2020
"context"
21+
"encoding/json"
2122
"fmt"
2223
"io"
2324
"net"
@@ -37,6 +38,7 @@ import (
3738
utilversionpkg "k8s.io/apiserver/pkg/util/version"
3839
"k8s.io/component-base/featuregate"
3940
baseversion "k8s.io/component-base/version"
41+
"k8s.io/kube-openapi/pkg/validation/spec"
4042
netutils "k8s.io/utils/net"
4143
)
4244

@@ -156,6 +158,22 @@ func (o AppsServerOptions) Validate(args []string) error {
156158
return utilerrors.NewAggregate(allErrors)
157159
}
158160

161+
// DeepCopySchema делает глубокую копию структуры spec.Schema
162+
func DeepCopySchema(schema *spec.Schema) (*spec.Schema, error) {
163+
data, err := json.Marshal(schema)
164+
if err != nil {
165+
return nil, fmt.Errorf("failed to marshal schema: %w", err)
166+
}
167+
168+
var newSchema spec.Schema
169+
err = json.Unmarshal(data, &newSchema)
170+
if err != nil {
171+
return nil, fmt.Errorf("failed to unmarshal schema: %w", err)
172+
}
173+
174+
return &newSchema, nil
175+
}
176+
159177
// Config returns the configuration for the API server based on AppsServerOptions
160178
func (o *AppsServerOptions) Config() (*apiserver.Config, error) {
161179
// TODO: set the "real" external address
@@ -165,6 +183,12 @@ func (o *AppsServerOptions) Config() (*apiserver.Config, error) {
165183
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
166184
}
167185

186+
// First, register the dynamic types
187+
err := v1alpha1.RegisterDynamicTypes(apiserver.Scheme, o.ResourceConfig)
188+
if err != nil {
189+
return nil, fmt.Errorf("failed to register dynamic types: %v", err)
190+
}
191+
168192
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
169193

170194
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(
@@ -173,6 +197,68 @@ func (o *AppsServerOptions) Config() (*apiserver.Config, error) {
173197
serverConfig.OpenAPIConfig.Info.Title = "Apps"
174198
serverConfig.OpenAPIConfig.Info.Version = "0.1"
175199

200+
serverConfig.OpenAPIConfig.PostProcessSpec = func(swagger *spec.Swagger) (*spec.Swagger, error) {
201+
defs := swagger.Definitions
202+
203+
// Check basic Application definition
204+
appDef, exists := defs["com.github.aenix.io.cozystack.pkg.apis.apps.v1alpha1.Application"]
205+
if !exists {
206+
return swagger, fmt.Errorf("Application definition not found")
207+
}
208+
209+
// Check basic ApplicationList definition
210+
listDef, exists := defs["com.github.aenix.io.cozystack.pkg.apis.apps.v1alpha1.ApplicationList"]
211+
if !exists {
212+
return swagger, fmt.Errorf("ApplicationList definition not found")
213+
}
214+
215+
for _, gvk := range v1alpha1.RegisteredGVKs {
216+
resourceName := fmt.Sprintf("com.github.aenix.io.cozystack.pkg.apis.apps.v1alpha1.%s", gvk.Kind)
217+
newDef, err := DeepCopySchema(&appDef)
218+
if err != nil {
219+
return nil, fmt.Errorf("failed to deepcopy schema for %s: %w", gvk.Kind, err)
220+
}
221+
222+
// Fix Extensions for resource
223+
if newDef.Extensions == nil {
224+
newDef.Extensions = map[string]interface{}{}
225+
}
226+
newDef.Extensions["x-kubernetes-group-version-kind"] = []map[string]interface{}{
227+
{
228+
"group": gvk.Group,
229+
"version": gvk.Version,
230+
"kind": gvk.Kind,
231+
},
232+
}
233+
defs[resourceName] = *newDef
234+
fmt.Printf("PostProcessSpec: Added OpenAPI definition for %s\n", resourceName)
235+
236+
// List resource
237+
listResourceName := fmt.Sprintf("com.github.aenix.io.cozystack.pkg.apis.apps.v1alpha1.%sList", gvk.Kind)
238+
newListDef, err := DeepCopySchema(&listDef)
239+
if err != nil {
240+
return nil, fmt.Errorf("failed to deepcopy schema for %sList: %w", gvk.Kind, err)
241+
}
242+
243+
// Fix Extensions for List resource
244+
if newListDef.Extensions == nil {
245+
newListDef.Extensions = map[string]interface{}{}
246+
}
247+
newListDef.Extensions["x-kubernetes-group-version-kind"] = []map[string]interface{}{
248+
{
249+
"group": gvk.Group,
250+
"version": gvk.Version,
251+
"kind": fmt.Sprintf("%sList", gvk.Kind),
252+
},
253+
}
254+
defs[listResourceName] = *newListDef
255+
fmt.Printf("PostProcessSpec: Added OpenAPI definition for %s\n", listResourceName)
256+
}
257+
258+
swagger.Definitions = defs
259+
return swagger, nil
260+
}
261+
176262
serverConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(
177263
sampleopenapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(apiserver.Scheme),
178264
)

0 commit comments

Comments
 (0)