deep copy fake client actions to avoid accidental mutation

Kubernetes-commit: 9ef99d189f2e454a293b8c343fee173c876ed21f
This commit is contained in:
David Eads 2018-03-02 09:19:52 -05:00 committed by Kubernetes Publisher
parent 467c17c87a
commit f8d192aa24
2 changed files with 109 additions and 6 deletions

View File

@ -324,6 +324,10 @@ type Action interface {
GetResource() schema.GroupVersionResource GetResource() schema.GroupVersionResource
GetSubresource() string GetSubresource() string
Matches(verb, resource string) bool Matches(verb, resource string) bool
// DeepCopy is used to copy an action to avoid any risk of accidental mutation. Most people never need to call this
// because the invocation logic deep copies before calls to storage and reactors.
DeepCopy() Action
} }
type GenericAction interface { type GenericAction interface {
@ -404,6 +408,10 @@ func (a ActionImpl) Matches(verb, resource string) bool {
return strings.ToLower(verb) == strings.ToLower(a.Verb) && return strings.ToLower(verb) == strings.ToLower(a.Verb) &&
strings.ToLower(resource) == strings.ToLower(a.Resource.Resource) strings.ToLower(resource) == strings.ToLower(a.Resource.Resource)
} }
func (a ActionImpl) DeepCopy() Action {
ret := a
return ret
}
type GenericActionImpl struct { type GenericActionImpl struct {
ActionImpl ActionImpl
@ -414,6 +422,14 @@ func (a GenericActionImpl) GetValue() interface{} {
return a.Value return a.Value
} }
func (a GenericActionImpl) DeepCopy() Action {
return GenericActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
// TODO this is wrong, but no worse than before
Value: a.Value,
}
}
type GetActionImpl struct { type GetActionImpl struct {
ActionImpl ActionImpl
Name string Name string
@ -423,6 +439,13 @@ func (a GetActionImpl) GetName() string {
return a.Name return a.Name
} }
func (a GetActionImpl) DeepCopy() Action {
return GetActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
Name: a.Name,
}
}
type ListActionImpl struct { type ListActionImpl struct {
ActionImpl ActionImpl
Kind schema.GroupVersionKind Kind schema.GroupVersionKind
@ -438,6 +461,18 @@ func (a ListActionImpl) GetListRestrictions() ListRestrictions {
return a.ListRestrictions return a.ListRestrictions
} }
func (a ListActionImpl) DeepCopy() Action {
return ListActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
Kind: a.Kind,
Name: a.Name,
ListRestrictions: ListRestrictions{
Labels: a.ListRestrictions.Labels.DeepCopySelector(),
Fields: a.ListRestrictions.Fields.DeepCopySelector(),
},
}
}
type CreateActionImpl struct { type CreateActionImpl struct {
ActionImpl ActionImpl
Name string Name string
@ -448,6 +483,14 @@ func (a CreateActionImpl) GetObject() runtime.Object {
return a.Object return a.Object
} }
func (a CreateActionImpl) DeepCopy() Action {
return CreateActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
Name: a.Name,
Object: a.Object.DeepCopyObject(),
}
}
type UpdateActionImpl struct { type UpdateActionImpl struct {
ActionImpl ActionImpl
Object runtime.Object Object runtime.Object
@ -457,6 +500,13 @@ func (a UpdateActionImpl) GetObject() runtime.Object {
return a.Object return a.Object
} }
func (a UpdateActionImpl) DeepCopy() Action {
return UpdateActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
Object: a.Object.DeepCopyObject(),
}
}
type PatchActionImpl struct { type PatchActionImpl struct {
ActionImpl ActionImpl
Name string Name string
@ -471,6 +521,16 @@ func (a PatchActionImpl) GetPatch() []byte {
return a.Patch return a.Patch
} }
func (a PatchActionImpl) DeepCopy() Action {
patch := make([]byte, len(a.Patch))
copy(patch, a.Patch)
return PatchActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
Name: a.Name,
Patch: patch,
}
}
type DeleteActionImpl struct { type DeleteActionImpl struct {
ActionImpl ActionImpl
Name string Name string
@ -480,6 +540,13 @@ func (a DeleteActionImpl) GetName() string {
return a.Name return a.Name
} }
func (a DeleteActionImpl) DeepCopy() Action {
return DeleteActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
Name: a.Name,
}
}
type DeleteCollectionActionImpl struct { type DeleteCollectionActionImpl struct {
ActionImpl ActionImpl
ListRestrictions ListRestrictions ListRestrictions ListRestrictions
@ -489,6 +556,16 @@ func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions {
return a.ListRestrictions return a.ListRestrictions
} }
func (a DeleteCollectionActionImpl) DeepCopy() Action {
return DeleteCollectionActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
ListRestrictions: ListRestrictions{
Labels: a.ListRestrictions.Labels.DeepCopySelector(),
Fields: a.ListRestrictions.Fields.DeepCopySelector(),
},
}
}
type WatchActionImpl struct { type WatchActionImpl struct {
ActionImpl ActionImpl
WatchRestrictions WatchRestrictions WatchRestrictions WatchRestrictions
@ -498,6 +575,17 @@ func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions {
return a.WatchRestrictions return a.WatchRestrictions
} }
func (a WatchActionImpl) DeepCopy() Action {
return WatchActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
WatchRestrictions: WatchRestrictions{
Labels: a.WatchRestrictions.Labels.DeepCopySelector(),
Fields: a.WatchRestrictions.Fields.DeepCopySelector(),
ResourceVersion: a.WatchRestrictions.ResourceVersion,
},
}
}
type ProxyGetActionImpl struct { type ProxyGetActionImpl struct {
ActionImpl ActionImpl
Scheme string Scheme string
@ -526,3 +614,18 @@ func (a ProxyGetActionImpl) GetPath() string {
func (a ProxyGetActionImpl) GetParams() map[string]string { func (a ProxyGetActionImpl) GetParams() map[string]string {
return a.Params return a.Params
} }
func (a ProxyGetActionImpl) DeepCopy() Action {
params := map[string]string{}
for k, v := range a.Params {
params[k] = v
}
return ProxyGetActionImpl{
ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
Scheme: a.Scheme,
Name: a.Name,
Port: a.Port,
Path: a.Path,
Params: params,
}
}

View File

@ -131,13 +131,13 @@ func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
c.actions = append(c.actions, action) c.actions = append(c.actions, action.DeepCopy())
for _, reactor := range c.ReactionChain { for _, reactor := range c.ReactionChain {
if !reactor.Handles(action) { if !reactor.Handles(action) {
continue continue
} }
handled, ret, err := reactor.React(action) handled, ret, err := reactor.React(action.DeepCopy())
if !handled { if !handled {
continue continue
} }
@ -154,13 +154,13 @@ func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
c.actions = append(c.actions, action) c.actions = append(c.actions, action.DeepCopy())
for _, reactor := range c.WatchReactionChain { for _, reactor := range c.WatchReactionChain {
if !reactor.Handles(action) { if !reactor.Handles(action) {
continue continue
} }
handled, ret, err := reactor.React(action) handled, ret, err := reactor.React(action.DeepCopy())
if !handled { if !handled {
continue continue
} }
@ -177,13 +177,13 @@ func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper {
c.Lock() c.Lock()
defer c.Unlock() defer c.Unlock()
c.actions = append(c.actions, action) c.actions = append(c.actions, action.DeepCopy())
for _, reactor := range c.ProxyReactionChain { for _, reactor := range c.ProxyReactionChain {
if !reactor.Handles(action) { if !reactor.Handles(action) {
continue continue
} }
handled, ret, err := reactor.React(action) handled, ret, err := reactor.React(action.DeepCopy())
if !handled || err != nil { if !handled || err != nil {
continue continue
} }