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

Merge pull request #112 from cmurphy/unformatter-store

Drop unrecognized fields before update
This commit is contained in:
Colleen Murphy 2023-07-17 09:02:51 -07:00 committed by GitHub
commit d040cffef3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 191 additions and 11 deletions

View File

@ -88,18 +88,20 @@ type Store struct {
// NewProxyStore returns a wrapped types.Store.
func NewProxyStore(clientGetter ClientGetter, notifier RelationshipNotifier, lookup accesscontrol.AccessSetLookup, namespaceCache corecontrollers.NamespaceCache) types.Store {
return &errorStore{
Store: &WatchRefresh{
Store: partition.NewStore(
&rbacPartitioner{
proxyStore: &Store{
clientGetter: clientGetter,
notifier: notifier,
Store: &unformatterStore{
Store: &WatchRefresh{
Store: partition.NewStore(
&rbacPartitioner{
proxyStore: &Store{
clientGetter: clientGetter,
notifier: notifier,
},
},
},
lookup,
namespaceCache,
),
asl: lookup,
lookup,
namespaceCache,
),
asl: lookup,
},
},
}
}

View File

@ -0,0 +1,66 @@
package proxy
import (
"github.com/rancher/apiserver/pkg/types"
"github.com/rancher/wrangler/pkg/data"
"github.com/rancher/wrangler/pkg/data/convert"
)
// unformatterStore removes fields added by the formatter that kubernetes cannot recognize.
type unformatterStore struct {
types.Store
}
// ByID looks up a single object by its ID.
func (u *unformatterStore) ByID(apiOp *types.APIRequest, schema *types.APISchema, id string) (types.APIObject, error) {
return u.Store.ByID(apiOp, schema, id)
}
// List returns a list of resources.
func (u *unformatterStore) List(apiOp *types.APIRequest, schema *types.APISchema) (types.APIObjectList, error) {
return u.Store.List(apiOp, schema)
}
// Create creates a single object in the store.
func (u *unformatterStore) Create(apiOp *types.APIRequest, schema *types.APISchema, data types.APIObject) (types.APIObject, error) {
return u.Store.Create(apiOp, schema, data)
}
// Update updates a single object in the store.
func (u *unformatterStore) Update(apiOp *types.APIRequest, schema *types.APISchema, data types.APIObject, id string) (types.APIObject, error) {
data = unformat(data)
return u.Store.Update(apiOp, schema, data, id)
}
// Delete deletes an object from a store.
func (u *unformatterStore) Delete(apiOp *types.APIRequest, schema *types.APISchema, id string) (types.APIObject, error) {
return u.Store.Delete(apiOp, schema, id)
}
// Watch returns a channel of events for a list or resource.
func (u *unformatterStore) Watch(apiOp *types.APIRequest, schema *types.APISchema, wr types.WatchRequest) (chan types.APIEvent, error) {
return u.Store.Watch(apiOp, schema, wr)
}
func unformat(obj types.APIObject) types.APIObject {
unst, ok := obj.Object.(map[string]interface{})
if !ok {
return obj
}
data.RemoveValue(unst, "metadata", "fields")
data.RemoveValue(unst, "metadata", "relationships")
data.RemoveValue(unst, "metadata", "state")
conditions, ok := data.GetValue(unst, "status", "conditions")
if ok {
conditionsSlice := convert.ToMapSlice(conditions)
for i := range conditionsSlice {
data.RemoveValue(conditionsSlice[i], "error")
data.RemoveValue(conditionsSlice[i], "transitioning")
data.RemoveValue(conditionsSlice[i], "lastUpdateTime")
}
data.PutValue(unst, conditionsSlice, "status", "conditions")
}
obj.Object = unst
return obj
}

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)
})
}
}