mirror of
https://github.com/outbackdingo/cozystack.git
synced 2026-01-27 10:18:39 +00:00
[cozystack-api] Disable startegic-json-patch support (#1179)
Signed-off-by: Andrei Kvapil <kvapss@gmail.com> <!-- Thank you for making a contribution! Here are some tips for you: - Start the PR title with the [label] of Cozystack component: - For system components: [platform], [system], [linstor], [cilium], [kube-ovn], [dashboard], [cluster-api], etc. - For managed apps: [apps], [tenant], [kubernetes], [postgres], [virtual-machine] etc. - For development and maintenance: [tests], [ci], [docs], [maintenance]. - If it's a work in progress, consider creating this PR as a draft. - Don't hesistate to ask for opinion and review in the community chats, even if it's still a draft. - Add the label `backport` if it's a bugfix that needs to be backported to a previous version. --> ## What this PR does This PR adds a post-processing hook that removes application/strategic-merge-patch+json from every PATCH operation in the generated OpenAPI v2/v3 specs. Strategic-merge-patch (SMP) is never supported for CRDs, and our aggregated API implementation can’t handle it either. When the spec advertises SMP, kubectl picks that media-type by default and sends an SMP body, which the apiserver then rejects with unable to find api field in struct JSON for the json field …. By dropping SMP from consumes / content: * kubectl apply|patch … transparently falls back to application/merge-patch+json or application/json-patch+json. * Server-side-apply (kubectl apply --server-side …) keeps working via application/apply-patch+yaml. No changes are required on the handler side—only the advertised media-types are updated. ### Release note <!-- Write a release note: - Explain what has changed internally and for users. - Start with the same [label] as in the PR title - Follow the guidelines at https://github.com/kubernetes/community/blob/master/contributors/guide/release-notes.md. --> ```release-note [cozystack-api] Disable startegic-json-patch support ```
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
const (
|
||||
baseRef = "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1.Application"
|
||||
baseListRef = baseRef + "List"
|
||||
smp = "application/strategic-merge-patch+json"
|
||||
)
|
||||
|
||||
func deepCopySchema(in *spec.Schema) *spec.Schema {
|
||||
@@ -101,21 +102,20 @@ func patchSpec(target *spec.Schema, raw string) error {
|
||||
func buildPostProcessV3(kindSchemas map[string]string) func(*spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
|
||||
return func(doc *spec3.OpenAPI) (*spec3.OpenAPI, error) {
|
||||
|
||||
// Replace the basic "Application" schema with the user-supplied kinds.
|
||||
if doc.Components == nil {
|
||||
doc.Components = &spec3.Components{}
|
||||
}
|
||||
if doc.Components.Schemas == nil {
|
||||
doc.Components.Schemas = map[string]*spec.Schema{}
|
||||
}
|
||||
|
||||
base, ok := doc.Components.Schemas[baseRef]
|
||||
if !ok {
|
||||
return doc, fmt.Errorf("base schema %q not found", baseRef)
|
||||
}
|
||||
|
||||
for kind, raw := range kindSchemas {
|
||||
ref := fmt.Sprintf("%s.%s", "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1", kind)
|
||||
|
||||
s := doc.Components.Schemas[ref]
|
||||
if s == nil { // first time – clone "Application"
|
||||
s = deepCopySchema(base)
|
||||
@@ -128,7 +128,6 @@ func buildPostProcessV3(kindSchemas map[string]string) func(*spec3.OpenAPI) (*sp
|
||||
}
|
||||
doc.Components.Schemas[ref] = s
|
||||
}
|
||||
|
||||
container := findSpecContainer(s)
|
||||
if container == nil { // fallback: use the root
|
||||
container = s
|
||||
@@ -137,9 +136,19 @@ func buildPostProcessV3(kindSchemas map[string]string) func(*spec3.OpenAPI) (*sp
|
||||
return nil, fmt.Errorf("kind %s: %w", kind, err)
|
||||
}
|
||||
}
|
||||
|
||||
delete(doc.Components.Schemas, baseRef)
|
||||
delete(doc.Components.Schemas, baseListRef)
|
||||
|
||||
// Disable strategic-merge-patch+json support in all PATCH operations
|
||||
for p, pi := range doc.Paths.Paths {
|
||||
if pi == nil || pi.Patch == nil || pi.Patch.RequestBody == nil {
|
||||
continue
|
||||
}
|
||||
delete(pi.Patch.RequestBody.Content, smp)
|
||||
|
||||
doc.Paths.Paths[p] = pi
|
||||
}
|
||||
|
||||
return doc, nil
|
||||
}
|
||||
}
|
||||
@@ -150,15 +159,15 @@ func buildPostProcessV3(kindSchemas map[string]string) func(*spec3.OpenAPI) (*sp
|
||||
func buildPostProcessV2(kindSchemas map[string]string) func(*spec.Swagger) (*spec.Swagger, error) {
|
||||
|
||||
return func(sw *spec.Swagger) (*spec.Swagger, error) {
|
||||
|
||||
// Replace the basic "Application" schema with the user-supplied kinds.
|
||||
defs := sw.Definitions
|
||||
base, ok := defs[baseRef]
|
||||
if !ok {
|
||||
return sw, fmt.Errorf("base schema %q not found", baseRef)
|
||||
}
|
||||
|
||||
for kind, raw := range kindSchemas {
|
||||
ref := fmt.Sprintf("%s.%s", "com.github.cozystack.cozystack.pkg.apis.apps.v1alpha1", kind)
|
||||
|
||||
s := deepCopySchema(&base)
|
||||
s.Extensions = map[string]interface{}{
|
||||
"x-kubernetes-group-version-kind": []interface{}{
|
||||
@@ -167,13 +176,10 @@ func buildPostProcessV2(kindSchemas map[string]string) func(*spec.Swagger) (*spe
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := patchSpec(s, raw); err != nil {
|
||||
return nil, fmt.Errorf("kind %s: %w", kind, err)
|
||||
}
|
||||
|
||||
defs[ref] = *s
|
||||
|
||||
// clone the List variant
|
||||
listName := ref + "List"
|
||||
listSrc := defs[baseListRef]
|
||||
@@ -193,9 +199,23 @@ func buildPostProcessV2(kindSchemas map[string]string) func(*spec.Swagger) (*spe
|
||||
}
|
||||
defs[listName] = *listCopy
|
||||
}
|
||||
|
||||
delete(defs, baseRef)
|
||||
delete(defs, baseListRef)
|
||||
|
||||
// Disable strategic-merge-patch+json support in all PATCH operations
|
||||
for p, op := range sw.Paths.Paths {
|
||||
if op.Patch != nil && len(op.Patch.Consumes) > 0 {
|
||||
var out []string
|
||||
for _, c := range op.Patch.Consumes {
|
||||
if c != smp {
|
||||
out = append(out, c)
|
||||
}
|
||||
}
|
||||
op.Patch.Consumes = out
|
||||
sw.Paths.Paths[p] = op
|
||||
}
|
||||
}
|
||||
|
||||
return sw, nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user