@@ -27,9 +27,12 @@ import (
27
27
28
28
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
29
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
30
31
"k8s.io/apimachinery/pkg/runtime"
32
+ runtimeschema "k8s.io/apimachinery/pkg/runtime/schema"
31
33
"k8s.io/apimachinery/pkg/util/sets"
32
34
"k8s.io/apimachinery/pkg/util/wait"
35
+ "k8s.io/client-go/discovery"
33
36
"k8s.io/client-go/rest"
34
37
"sigs.k8s.io/controller-runtime/pkg/client"
35
38
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -57,11 +60,11 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
57
60
ctx context.Context
58
61
cancel context.CancelFunc
59
62
60
- cli clusterclient.ClusterClient
61
- provider , consumer logicalcluster.Path
62
- consumerWS * tenancyv1alpha1.Workspace
63
- mgr mcmanager.Manager
64
- vwEndpoint string
63
+ cli clusterclient.ClusterClient
64
+ provider , consumer , other logicalcluster.Path
65
+ consumerWS * tenancyv1alpha1.Workspace
66
+ mgr mcmanager.Manager
67
+ vwEndpoint string
65
68
)
66
69
67
70
BeforeAll (func () {
@@ -73,6 +76,7 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
73
76
74
77
_ , provider = envtest .NewWorkspaceFixture (GinkgoT (), cli , core .RootCluster .Path (), envtest .WithNamePrefix ("provider" ))
75
78
consumerWS , consumer = envtest .NewWorkspaceFixture (GinkgoT (), cli , core .RootCluster .Path (), envtest .WithNamePrefix ("consumer" ))
79
+ _ , other = envtest .NewWorkspaceFixture (GinkgoT (), cli , core .RootCluster .Path (), envtest .WithNamePrefix ("other" ))
76
80
77
81
By (fmt .Sprintf ("creating a schema in the provider workspace %q" , provider ))
78
82
schema := & apisv1alpha1.APIResourceSchema {
@@ -152,32 +156,101 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
152
156
return false , fmt .Sprintf ("failed to get APIExportEndpointSlice in %s: %v" , provider , err )
153
157
}
154
158
return len (endpoints .Status .APIExportEndpoints ) > 0 , toYAML (GinkgoT (), endpoints )
155
- }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see endpoints in APIExportEndpointSlice in %s " , provider )
159
+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see endpoints in APIExportEndpointSlice in %q " , provider )
156
160
vwEndpoint = endpoints .Status .APIExportEndpoints [0 ].URL
161
+
162
+ By (fmt .Sprintf ("waiting until the APIBinding in the consumer workspace %q to be ready" , consumer ))
163
+ envtest .Eventually (GinkgoT (), func () (bool , string ) {
164
+ current := & apisv1alpha1.APIBinding {}
165
+ err := cli .Cluster (consumer ).Get (ctx , client.ObjectKey {Name : "example.com" }, current )
166
+ if err != nil {
167
+ return false , fmt .Sprintf ("failed to get APIBinding in %s: %v" , consumer , err )
168
+ }
169
+ if current .Status .Phase != apisv1alpha1 .APIBindingPhaseBound {
170
+ return false , fmt .Sprintf ("binding not bound:\n \n %s" , toYAML (GinkgoT (), current ))
171
+ }
172
+ return true , ""
173
+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to wait for APIBinding in consumer workspace to be ready %q" , consumer )
174
+
175
+ By ("waiting until things can be listed in the consumer workspace" )
176
+ envtest .Eventually (GinkgoT (), func () (bool , string ) {
177
+ u := & unstructured.UnstructuredList {}
178
+ u .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "ThingList" })
179
+ err = cli .Cluster (consumer ).List (ctx , u )
180
+ if err != nil {
181
+ return false , fmt .Sprintf ("failed to list things in %s: %v" , consumer , err )
182
+ }
183
+ return true , ""
184
+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to wait for things to be listable in consumer workspace %q" , consumer )
157
185
})
158
186
159
187
Describe ("with a multicluster provider and manager" , func () {
160
188
var (
161
189
lock sync.RWMutex
162
190
engaged = sets .NewString ()
191
+ p * virtualworkspace.Provider
163
192
g * errgroup.Group
164
193
cancelGroup context.CancelFunc
165
194
)
166
195
167
196
BeforeAll (func () {
197
+ By ("creating a stone in the consumer workspace" , func () {
198
+ thing := & unstructured.Unstructured {}
199
+ thing .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "Thing" })
200
+ thing .SetNamespace ("stone" )
201
+ thing .SetLabels (map [string ]string {"color" : "gray" })
202
+ err := cli .Cluster (consumer ).Create (ctx , thing )
203
+ Expect (err ).NotTo (HaveOccurred ())
204
+ })
205
+
206
+ By ("creating a box in the other workspace" , func () {
207
+ thing := & unstructured.Unstructured {}
208
+ thing .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "Thing" })
209
+ thing .SetNamespace ("box" )
210
+ thing .SetLabels (map [string ]string {"color" : "white" })
211
+ err := cli .Cluster (other ).Create (ctx , thing )
212
+ Expect (err ).NotTo (HaveOccurred ())
213
+ })
214
+
168
215
By ("creating a multicluster provider for APIBindings against the apiexport virtual workspace" )
169
216
vwConfig := rest .CopyConfig (kcpConfig )
170
217
vwConfig .Host = vwEndpoint
171
- p , err := virtualworkspace .New (vwConfig , & apisv1alpha1.APIBinding {}, virtualworkspace.Options {})
218
+ var err error
219
+ p , err = virtualworkspace .New (vwConfig , & apisv1alpha1.APIBinding {}, virtualworkspace.Options {})
172
220
Expect (err ).NotTo (HaveOccurred ())
173
221
222
+ By ("waiting for discovery of the virtual workspace to show 'example.com'" )
223
+ wildcardConfig := rest .CopyConfig (vwConfig )
224
+ wildcardConfig .Host += logicalcluster .Wildcard .RequestPath ()
225
+ disc , err := discovery .NewDiscoveryClientForConfig (wildcardConfig )
226
+ Expect (err ).NotTo (HaveOccurred ())
227
+ envtest .Eventually (GinkgoT (), func () (bool , string ) {
228
+ ret , err := disc .ServerGroups ()
229
+ Expect (err ).NotTo (HaveOccurred ())
230
+ for _ , g := range ret .Groups {
231
+ if g .Name == "example.com" {
232
+ return true , ""
233
+ }
234
+ }
235
+ return false , fmt .Sprintf ("failed to find group example.com in:\n %s" , toYAML (GinkgoT (), ret ))
236
+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to find group example.com in the virtual workspace" )
237
+
174
238
By ("creating a manager against the provider workspace" )
175
239
rootConfig := rest .CopyConfig (kcpConfig )
176
240
rootConfig .Host += provider .RequestPath ()
177
241
mgr , err = mcmanager .New (rootConfig , p , mcmanager.Options {})
178
242
Expect (err ).NotTo (HaveOccurred ())
179
243
180
- By ("creating a reconciler for the APIBinding" )
244
+ By ("adding an index on label 'color'" )
245
+ thing := & unstructured.Unstructured {}
246
+ thing .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "Thing" })
247
+ err = mgr .GetFieldIndexer ().IndexField (ctx , thing , "color" , func (obj client.Object ) []string {
248
+ u := obj .(* unstructured.Unstructured )
249
+ return []string {u .GetLabels ()["color" ]}
250
+ })
251
+ Expect (err ).NotTo (HaveOccurred ())
252
+
253
+ By ("creating a reconciler for APIBindings" )
181
254
err = mcbuilder .ControllerManagedBy (mgr ).
182
255
Named ("things" ).
183
256
For (& apisv1alpha1.APIBinding {}).
@@ -211,6 +284,42 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
211
284
}, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see the consumer workspace %q as a cluster" , consumer )
212
285
})
213
286
287
+ It ("sees only the stone in the consumer clusters" , func () {
288
+ consumerCl , err := mgr .GetCluster (ctx , consumerWS .Spec .Cluster )
289
+ Expect (err ).NotTo (HaveOccurred ())
290
+
291
+ envtest .Eventually (GinkgoT (), func () (success bool , reason string ) {
292
+ l := & unstructured.UnstructuredList {}
293
+ l .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "ThingList" })
294
+ err = consumerCl .GetCache ().List (ctx , l )
295
+ Expect (err ).NotTo (HaveOccurred ())
296
+ if len (l .Items ) != 1 {
297
+ return false , fmt .Sprintf ("expected 1 item, got %d\n \n %s" , len (l .Items ), toYAML (GinkgoT (), l .Object ))
298
+ } else if name := l .Items [0 ].GetName (); name != "stone" {
299
+ return false , fmt .Sprintf ("expected item name to be stone, got %q\n \n %s" , name , toYAML (GinkgoT (), l .Items [0 ]))
300
+ }
301
+ return true , ""
302
+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see the stone in the consumer cluster" )
303
+ })
304
+
305
+ It ("sees only the stone as grey thing in the consumer clusters" , func () {
306
+ consumerCl , err := mgr .GetCluster (ctx , consumerWS .Spec .Cluster )
307
+ Expect (err ).NotTo (HaveOccurred ())
308
+
309
+ envtest .Eventually (GinkgoT (), func () (success bool , reason string ) {
310
+ l := & unstructured.UnstructuredList {}
311
+ l .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "ThingList" })
312
+ err = consumerCl .GetCache ().List (ctx , l , client.MatchingFields {"color" : "gray" })
313
+ Expect (err ).NotTo (HaveOccurred ())
314
+ if len (l .Items ) != 1 {
315
+ return false , fmt .Sprintf ("expected 1 item, got %d\n \n %s" , len (l .Items ), toYAML (GinkgoT (), l .Object ))
316
+ } else if name := l .Items [0 ].GetName (); name != "stone" {
317
+ return false , fmt .Sprintf ("expected item name to be stone, got %q\n \n %s" , name , toYAML (GinkgoT (), l .Items [0 ]))
318
+ }
319
+ return true , ""
320
+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see the stone as only thing of color 'grey' in the consumer cluster" )
321
+ })
322
+
214
323
AfterAll (func () {
215
324
cancelGroup ()
216
325
err := g .Wait ()
0 commit comments