Skip to content

fix: Respect x-kubernetes-list-type in OpenAPI spec for CRDs #5909

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions api/krusty/openapicustomschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,3 +643,58 @@ spec:
assert.Equal(t, kubernetesapi.DefaultOpenAPI, openapi.GetSchemaVersion())
})
}

// Test for issue #5878
func TestCustomOpenApiFieldWithoutMergePatchExtension(t *testing.T) {
runOpenApiTest(t, func(t *testing.T) {
t.Helper()
th := kusttest_test.MakeHarness(t)
writeTestSchema(th, "./")
th.WriteF("yetanothercrd_base.yaml", `
apiVersion: example.com/v1alpha1
kind: MyCRD
metadata:
name: service
spec:
custom:
objects:
- name: foo
value: foo
- name: bar
value: bar
`)
th.WriteF("yetanothercrd_patch.yaml", `
apiVersion: example.com/v1alpha1
kind: MyCRD
metadata:
name: service
spec:
custom:
objects:
- name: bar
value: patched
`)
th.WriteK(".", `
resources:
- yetanothercrd_base.yaml
openapi:
path: mycrd_schema.json
patches:
- path: yetanothercrd_patch.yaml
`)
m := th.Run(".", th.MakeDefaultOptions())
th.AssertActualEqualsExpected(m, `
apiVersion: example.com/v1alpha1
kind: MyCRD
metadata:
name: service
spec:
custom:
objects:
- name: bar
value: patched
- name: foo
value: foo
`)
})
}
30 changes: 27 additions & 3 deletions api/krusty/testdata/customschema.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
"properties": {
"template": {
"$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
},
"custom": {
"$ref": "#/definitions/com.example.v1alpha1.CustomSpec"
}
},
"type": "object"
},
"status": {
"properties": {
"properties": {
"success": {
"type": "boolean"
}
Expand Down Expand Up @@ -89,7 +92,7 @@
"type": "string"
},
"ports": {
"items": {
"items": {
"$ref": "#/definitions/io.k8s.api.core.v1.ContainerPort"
},
"type": "array",
Expand All @@ -105,7 +108,7 @@
"type": "object"
},
"io.k8s.api.core.v1.ContainerPort": {
"properties": {
"properties": {
"containerPort": {
"format": "int32",
"type": "integer"
Expand All @@ -118,6 +121,27 @@
}
},
"type": "object"
},
"com.example.v1alpha1.CustomSpec": {
"properties": {
"objects": {
"items": {
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"type": "array",
"x-kubernetes-list-map-keys": [
"name"
],
"x-kubernetes-list-type": "map"
}
}
}
}
}
16 changes: 16 additions & 0 deletions api/krusty/testdata/customschema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ definitions:
properties:
template:
"$ref": "#/definitions/io.k8s.api.core.v1.PodTemplateSpec"
custom:
"$ref": "#/definitions/com.example.v1alpha1.CustomSpec"
type: object
status:
properties:
Expand Down Expand Up @@ -70,9 +72,23 @@ definitions:
io.k8s.api.core.v1.ContainerPort:
properties:
containerPort:
format: int32
type: integer
name:
type: string
protocol:
type: string
type: object
com.example.v1alpha1.CustomSpec:
properties:
objects:
items:
properties:
name:
type: string
value:
type: string
type: array
x-kubernetes-list-map-keys:
- name
x-kubernetes-list-type: map
20 changes: 12 additions & 8 deletions examples/customOpenAPIschema.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,24 @@ spec:
EOF
```

This resource has an image field. Let's change its value from server
to nginx with a patch.
This resource has an image field. Let's change its value from server
to nginx with a patch.

Kustomize gets its merge key information from the OpenAPI data
provided by the kubernetes API server. It doesn't have information
about custom resources, so we will have to provide our own
schema file.
about custom resources, so we will have to provide our own
schema file.

Note: CRDs support declarative validation using an OpenAPI v3 schema.
See https://book.kubebuilder.io/reference/generating-crd.html#validation.

You can get an OpenAPI document like this by fetching the OpenAPI
document from your locally favored cluster with the command
`kustomize openapi fetch`. Kustomize will use the OpenAPI extensions
`x-kubernetes-patch-merge-key` and `x-kubernetes-patch-strategy` to
perform a strategic merge. `x-kubernetes-patch-strategy` should be set
to "merge", and you can set your merge key to whatever you like. Below,
our custom resource inherits merge keys from `PodTemplateSpec`.
`x-kubernetes-list-map-keys` and `x-kubernetes-list-type` to
perform a strategic merge. `x-kubernetes-list-type` should be set
to "map", and you can set your merge keys to whatever you like. Below,
our custom resource inherits merge keys from `PodTemplateSpec`.

<!-- @addCustomSchema @testAgainstLatestRelease -->
```
Expand Down Expand Up @@ -124,6 +124,10 @@ cat <<EOF >>$DEMO_HOME/mycr_schema.json
"\$ref": "#/definitions/io.k8s.api.core.v1.Container"
},
"type": "array",
"x-kubernetes-list-map-keys": [
"name"
],
"x-kubernetes-list-type": "map",
"x-kubernetes-patch-merge-key": "name",
"x-kubernetes-patch-strategy": "merge"
}
Expand Down
Loading
Loading