1
16
17 package testing
18
19 import (
20 "fmt"
21 "sync"
22
23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24 "k8s.io/apimachinery/pkg/runtime"
25 "k8s.io/apimachinery/pkg/watch"
26 restclient "k8s.io/client-go/rest"
27 )
28
29
30
31
32 type Fake struct {
33 sync.RWMutex
34 actions []Action
35
36
37
38 ReactionChain []Reactor
39
40
41 WatchReactionChain []WatchReactor
42
43
44 ProxyReactionChain []ProxyReactor
45
46 Resources []*metav1.APIResourceList
47 }
48
49
50 type Reactor interface {
51
52
53 Handles(action Action) bool
54
55
56 React(action Action) (handled bool, ret runtime.Object, err error)
57 }
58
59
60 type WatchReactor interface {
61
62
63 Handles(action Action) bool
64
65
66 React(action Action) (handled bool, ret watch.Interface, err error)
67 }
68
69
70
71 type ProxyReactor interface {
72
73
74 Handles(action Action) bool
75
76
77 React(action Action) (handled bool, ret restclient.ResponseWrapper, err error)
78 }
79
80
81
82
83
84
85 type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error)
86
87
88
89
90 type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error)
91
92
93
94
95 type ProxyReactionFunc func(action Action) (handled bool, ret restclient.ResponseWrapper, err error)
96
97
98 func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) {
99 c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction})
100 }
101
102
103 func (c *Fake) PrependReactor(verb, resource string, reaction ReactionFunc) {
104 c.ReactionChain = append([]Reactor{&SimpleReactor{verb, resource, reaction}}, c.ReactionChain...)
105 }
106
107
108 func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) {
109 c.Lock()
110 defer c.Unlock()
111 c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction})
112 }
113
114
115 func (c *Fake) PrependWatchReactor(resource string, reaction WatchReactionFunc) {
116 c.Lock()
117 defer c.Unlock()
118 c.WatchReactionChain = append([]WatchReactor{&SimpleWatchReactor{resource, reaction}}, c.WatchReactionChain...)
119 }
120
121
122 func (c *Fake) AddProxyReactor(resource string, reaction ProxyReactionFunc) {
123 c.ProxyReactionChain = append(c.ProxyReactionChain, &SimpleProxyReactor{resource, reaction})
124 }
125
126
127 func (c *Fake) PrependProxyReactor(resource string, reaction ProxyReactionFunc) {
128 c.ProxyReactionChain = append([]ProxyReactor{&SimpleProxyReactor{resource, reaction}}, c.ProxyReactionChain...)
129 }
130
131
132
133
134 func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) {
135 c.Lock()
136 defer c.Unlock()
137
138 actionCopy := action.DeepCopy()
139 c.actions = append(c.actions, action.DeepCopy())
140 for _, reactor := range c.ReactionChain {
141 if !reactor.Handles(actionCopy) {
142 continue
143 }
144
145 handled, ret, err := reactor.React(actionCopy)
146 if !handled {
147 continue
148 }
149
150 return ret, err
151 }
152
153 return defaultReturnObj, nil
154 }
155
156
157
158 func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) {
159 c.Lock()
160 defer c.Unlock()
161
162 actionCopy := action.DeepCopy()
163 c.actions = append(c.actions, action.DeepCopy())
164 for _, reactor := range c.WatchReactionChain {
165 if !reactor.Handles(actionCopy) {
166 continue
167 }
168
169 handled, ret, err := reactor.React(actionCopy)
170 if !handled {
171 continue
172 }
173
174 return ret, err
175 }
176
177 return nil, fmt.Errorf("unhandled watch: %#v", action)
178 }
179
180
181
182 func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper {
183 c.Lock()
184 defer c.Unlock()
185
186 actionCopy := action.DeepCopy()
187 c.actions = append(c.actions, action.DeepCopy())
188 for _, reactor := range c.ProxyReactionChain {
189 if !reactor.Handles(actionCopy) {
190 continue
191 }
192
193 handled, ret, err := reactor.React(actionCopy)
194 if !handled || err != nil {
195 continue
196 }
197
198 return ret
199 }
200
201 return nil
202 }
203
204
205 func (c *Fake) ClearActions() {
206 c.Lock()
207 defer c.Unlock()
208
209 c.actions = make([]Action, 0)
210 }
211
212
213
214 func (c *Fake) Actions() []Action {
215 c.RLock()
216 defer c.RUnlock()
217 fa := make([]Action, len(c.actions))
218 copy(fa, c.actions)
219 return fa
220 }
221
View as plain text