1
0
mirror of https://github.com/rancher/steve.git synced 2025-09-09 19:29:56 +00:00

Drop unrecognized fields before update

Add a nested store to the proxy store to strip non-Kubernetes fields
from the object being updated.

The steve formatter and proxy store adds fields to objects when it
outputs them to the client, for usability by the UI. It adds the
object's fields[1], relationships to other objects[2], a summary of the
object's state[3], and additional information in the conditions[4].
These fields are not native to Kubernetes, so when a client submits the
object back as an update, Kubernetes reports a warning that they are
unrecognized. This change ensures the extra fields are removed before
submitting the update.

[1] bf2e9655f5/pkg/stores/proxy/proxy_store.go (L189)
[2] bf2e9655f5/pkg/resources/common/formatter.go (L106)
[3] bf2e9655f5/pkg/resources/common/formatter.go (L100)
[4] bf2e9655f5/pkg/resources/common/formatter.go (L108)
This commit is contained in:
Colleen Murphy
2023-06-16 14:24:57 -07:00
parent bf2e9655f5
commit adaa391ddf
3 changed files with 191 additions and 11 deletions

View File

@@ -0,0 +1,112 @@
package proxy
import (
"testing"
"github.com/rancher/apiserver/pkg/types"
"github.com/stretchr/testify/assert"
)
func Test_unformat(t *testing.T) {
tests := []struct {
name string
obj types.APIObject
want types.APIObject
}{
{
name: "noop",
obj: types.APIObject{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "noop",
},
},
},
want: types.APIObject{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "noop",
},
},
},
},
{
name: "remove fields",
obj: types.APIObject{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "foo",
"fields": []string{
"name",
"address",
"phonenumber",
},
"relationships": []map[string]interface{}{
{
"toId": "bar",
"rel": "uses",
},
},
"state": map[string]interface{}{
"error": false,
},
},
"status": map[string]interface{}{
"conditions": []map[string]interface{}{
{
"type": "Ready",
"status": "True",
"lastUpdateTime": "a minute ago",
"transitioning": false,
"error": false,
},
{
"type": "Initialized",
"status": "True",
"lastUpdateTime": "yesterday",
"transitioning": false,
"error": false,
},
},
},
},
},
want: types.APIObject{
Object: map[string]interface{}{
"metadata": map[string]interface{}{
"name": "foo",
},
"status": map[string]interface{}{
"conditions": []map[string]interface{}{
{
"type": "Ready",
"status": "True",
},
{
"type": "Initialized",
"status": "True",
},
},
},
},
},
},
{
name: "unrecognized object",
obj: types.APIObject{
Object: "object",
},
want: types.APIObject{
Object: "object",
},
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
got := unformat(test.obj)
assert.Equal(t, test.want, got)
})
}
}