@@ -18,6 +18,8 @@ package server
1818
1919import (
2020 "context"
21+ "crypto/sha256"
22+ "encoding/hex"
2123 "encoding/json"
2224 "fmt"
2325 "io"
@@ -38,8 +40,6 @@ import (
3840 utilversionpkg "k8s.io/apiserver/pkg/util/version"
3941 "k8s.io/component-base/featuregate"
4042 baseversion "k8s.io/component-base/version"
41- "k8s.io/klog/v2"
42- "k8s.io/kube-openapi/pkg/validation/spec"
4343 netutils "k8s.io/utils/net"
4444)
4545
@@ -159,22 +159,6 @@ func (o AppsServerOptions) Validate(args []string) error {
159159 return utilerrors .NewAggregate (allErrors )
160160}
161161
162- // DeepCopySchema делает глубокую копию структуры spec.Schema
163- func DeepCopySchema (schema * spec.Schema ) (* spec.Schema , error ) {
164- data , err := json .Marshal (schema )
165- if err != nil {
166- return nil , fmt .Errorf ("failed to marshal schema: %w" , err )
167- }
168-
169- var newSchema spec.Schema
170- err = json .Unmarshal (data , & newSchema )
171- if err != nil {
172- return nil , fmt .Errorf ("failed to unmarshal schema: %w" , err )
173- }
174-
175- return & newSchema , nil
176- }
177-
178162// Config returns the configuration for the API server based on AppsServerOptions
179163func (o * AppsServerOptions ) Config () (* apiserver.Config , error ) {
180164 // TODO: set the "real" external address
@@ -195,107 +179,34 @@ func (o *AppsServerOptions) Config() (*apiserver.Config, error) {
195179 serverConfig .OpenAPIConfig = genericapiserver .DefaultOpenAPIConfig (
196180 sampleopenapi .GetOpenAPIDefinitions , openapi .NewDefinitionNamer (apiserver .Scheme ),
197181 )
198- serverConfig .OpenAPIConfig .Info .Title = "Apps"
199- serverConfig .OpenAPIConfig .Info .Version = "0.1"
200182
201- serverConfig .OpenAPIConfig .PostProcessSpec = func (swagger * spec.Swagger ) (* spec.Swagger , error ) {
202- defs := swagger .Definitions
203-
204- // Verify the presence of the base Application/ApplicationList definitions
205- appDef , exists := defs ["com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Application" ]
206- if ! exists {
207- return swagger , fmt .Errorf ("Application definition not found" )
208- }
209-
210- listDef , exists := defs ["com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.ApplicationList" ]
211- if ! exists {
212- return swagger , fmt .Errorf ("ApplicationList definition not found" )
183+ version := "0.1"
184+ if o .ResourceConfig != nil {
185+ raw , err := json .Marshal (o .ResourceConfig )
186+ if err != nil {
187+ return nil , fmt .Errorf ("failed to marshal resource config: %v" , err )
213188 }
189+ sum := sha256 .Sum256 (raw )
190+ version = "0.1-" + hex .EncodeToString (sum [:8 ])
191+ }
214192
215- // Iterate over all registered GVKs (e.g., Bucket, Database, etc.)
216- for _ , gvk := range v1alpha1 .RegisteredGVKs {
217- // This will be something like:
218- // "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Bucket"
219- resourceName := fmt .Sprintf ("com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.%s" , gvk .Kind )
220-
221- // 1. Create a copy of the base Application definition for the new resource
222- newDef , err := DeepCopySchema (& appDef )
223- if err != nil {
224- return nil , fmt .Errorf ("failed to deepcopy schema for %s: %w" , gvk .Kind , err )
225- }
226-
227- // 2. Update x-kubernetes-group-version-kind to match the new resource
228- if newDef .Extensions == nil {
229- newDef .Extensions = map [string ]interface {}{}
230- }
231- newDef .Extensions ["x-kubernetes-group-version-kind" ] = []map [string ]interface {}{
232- {
233- "group" : gvk .Group ,
234- "version" : gvk .Version ,
235- "kind" : gvk .Kind ,
236- },
237- }
238-
239- // make `.spec` schemaless so any keys are accepted
240- if specProp , ok := newDef .Properties ["spec" ]; ok {
241- specProp .AdditionalProperties = & spec.SchemaOrBool {
242- Allows : true ,
243- Schema : & spec.Schema {},
244- }
245- newDef .Properties ["spec" ] = specProp
246- }
247-
248- // 3. Save the new resource definition under the correct name
249- defs [resourceName ] = * newDef
250- klog .V (6 ).Infof ("PostProcessSpec: Added OpenAPI definition for %s\n " , resourceName )
251-
252- // 4. Now handle the corresponding List type (e.g., BucketList).
253- // We'll start by copying the ApplicationList definition.
254- listResourceName := fmt .Sprintf ("com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.%sList" , gvk .Kind )
255- newListDef , err := DeepCopySchema (& listDef )
256- if err != nil {
257- return nil , fmt .Errorf ("failed to deepcopy schema for %sList: %w" , gvk .Kind , err )
258- }
259-
260- // 5. Update x-kubernetes-group-version-kind for the List definition
261- if newListDef .Extensions == nil {
262- newListDef .Extensions = map [string ]interface {}{}
263- }
264- newListDef .Extensions ["x-kubernetes-group-version-kind" ] = []map [string ]interface {}{
265- {
266- "group" : gvk .Group ,
267- "version" : gvk .Version ,
268- "kind" : fmt .Sprintf ("%sList" , gvk .Kind ),
269- },
270- }
271-
272- // 6. IMPORTANT: Fix the "items" reference so it points to the new resource
273- // rather than to "Application".
274- if itemsProp , found := newListDef .Properties ["items" ]; found {
275- if itemsProp .Items != nil && itemsProp .Items .Schema != nil {
276- itemsProp .Items .Schema .Ref = spec .MustCreateRef ("#/definitions/" + resourceName )
277- newListDef .Properties ["items" ] = itemsProp
278- }
279- }
280-
281- // 7. Finally, save the new List definition
282- defs [listResourceName ] = * newListDef
283- klog .V (6 ).Infof ("PostProcessSpec: Added OpenAPI definition for %s\n " , listResourceName )
284- }
285-
286- // Remove the original Application/ApplicationList from the definitions
287- delete (defs , "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Application" )
288- delete (defs , "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.ApplicationList" )
289-
290- swagger .Definitions = defs
291- return swagger , nil
193+ // capture schemas from config once for fast lookup inside the closure
194+ kindSchemas := map [string ]string {}
195+ for _ , r := range o .ResourceConfig .Resources {
196+ kindSchemas [r .Application .Kind ] = r .Application .OpenAPISchema
292197 }
293198
199+ serverConfig .OpenAPIConfig .Info .Title = "Apps"
200+ serverConfig .OpenAPIConfig .Info .Version = version
201+ serverConfig .OpenAPIConfig .PostProcessSpec = buildPostProcessV2 (kindSchemas )
202+
294203 serverConfig .OpenAPIV3Config = genericapiserver .DefaultOpenAPIV3Config (
295204 sampleopenapi .GetOpenAPIDefinitions , openapi .NewDefinitionNamer (apiserver .Scheme ),
296205 )
297206 serverConfig .OpenAPIV3Config .Info .Title = "Apps"
298- serverConfig .OpenAPIV3Config .Info .Version = "0.1"
207+ serverConfig .OpenAPIV3Config .Info .Version = version
208+
209+ serverConfig .OpenAPIV3Config .PostProcessSpec = buildPostProcessV3 (kindSchemas )
299210
300211 serverConfig .FeatureGate = utilversionpkg .DefaultComponentGlobalsRegistry .FeatureGateFor (
301212 utilversionpkg .DefaultKubeComponent ,
0 commit comments