@@ -27,9 +27,12 @@ import (
2727
2828 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2929 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3031 "k8s.io/apimachinery/pkg/runtime"
32+ runtimeschema "k8s.io/apimachinery/pkg/runtime/schema"
3133 "k8s.io/apimachinery/pkg/util/sets"
3234 "k8s.io/apimachinery/pkg/util/wait"
35+ "k8s.io/client-go/discovery"
3336 "k8s.io/client-go/rest"
3437 "sigs.k8s.io/controller-runtime/pkg/client"
3538 "sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -57,11 +60,11 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
5760 ctx context.Context
5861 cancel context.CancelFunc
5962
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
6568 )
6669
6770 BeforeAll (func () {
@@ -73,6 +76,7 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
7376
7477 _ , provider = envtest .NewWorkspaceFixture (GinkgoT (), cli , core .RootCluster .Path (), envtest .WithNamePrefix ("provider" ))
7578 consumerWS , consumer = envtest .NewWorkspaceFixture (GinkgoT (), cli , core .RootCluster .Path (), envtest .WithNamePrefix ("consumer" ))
79+ _ , other = envtest .NewWorkspaceFixture (GinkgoT (), cli , core .RootCluster .Path (), envtest .WithNamePrefix ("other" ))
7680
7781 By (fmt .Sprintf ("creating a schema in the provider workspace %q" , provider ))
7882 schema := & apisv1alpha1.APIResourceSchema {
@@ -154,12 +158,32 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
154158 return len (endpoints .Status .APIExportEndpoints ) > 0 , toYAML (GinkgoT (), endpoints )
155159 }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see endpoints in APIExportEndpointSlice in %s" , provider )
156160 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+ u := & unstructured.UnstructuredList {}
173+ u .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "ThingList" })
174+ err = cli .Cluster (consumer ).List (ctx , u )
175+ if err != nil {
176+ return false , fmt .Sprintf ("failed to list things in %s: %v\n \n %s" , consumer , err , toYAML (GinkgoT (), current ))
177+ }
178+ return true , ""
179+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to list things in %s workspace" , consumer )
157180 })
158181
159182 Describe ("with a multicluster provider and manager" , func () {
160183 var (
161184 lock sync.RWMutex
162185 engaged = sets .NewString ()
186+ p * virtualworkspace.Provider
163187 g * errgroup.Group
164188 cancelGroup context.CancelFunc
165189 )
@@ -168,16 +192,42 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
168192 By ("creating a multicluster provider for APIBindings against the apiexport virtual workspace" )
169193 vwConfig := rest .CopyConfig (kcpConfig )
170194 vwConfig .Host = vwEndpoint
171- p , err := virtualworkspace .New (vwConfig , & apisv1alpha1.APIBinding {}, virtualworkspace.Options {})
195+ var err error
196+ p , err = virtualworkspace .New (vwConfig , & apisv1alpha1.APIBinding {}, virtualworkspace.Options {})
172197 Expect (err ).NotTo (HaveOccurred ())
173198
199+ By ("waiting for discovery of the virtual workspace to show 'example.com'" )
200+ wildcardConfig := rest .CopyConfig (vwConfig )
201+ wildcardConfig .Host += logicalcluster .Wildcard .RequestPath ()
202+ disc , err := discovery .NewDiscoveryClientForConfig (wildcardConfig )
203+ Expect (err ).NotTo (HaveOccurred ())
204+ envtest .Eventually (GinkgoT (), func () (bool , string ) {
205+ ret , err := disc .ServerGroups ()
206+ Expect (err ).NotTo (HaveOccurred ())
207+ for _ , g := range ret .Groups {
208+ if g .Name == "example.com" {
209+ return true , ""
210+ }
211+ }
212+ return false , fmt .Sprintf ("failed to find group example.com in:\n %s" , toYAML (GinkgoT (), ret ))
213+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to find group example.com in the virtual workspace" )
214+
174215 By ("creating a manager against the provider workspace" )
175216 rootConfig := rest .CopyConfig (kcpConfig )
176217 rootConfig .Host += provider .RequestPath ()
177218 mgr , err = mcmanager .New (rootConfig , p , mcmanager.Options {})
178219 Expect (err ).NotTo (HaveOccurred ())
179220
180- By ("creating a reconciler for the APIBinding" )
221+ By ("adding an index on label 'color'" )
222+ thing := & unstructured.Unstructured {}
223+ thing .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "Thing" })
224+ err = mgr .GetFieldIndexer ().IndexField (ctx , thing , "color" , func (obj client.Object ) []string {
225+ u := obj .(* unstructured.Unstructured )
226+ return []string {u .GetLabels ()["color" ]}
227+ })
228+ Expect (err ).NotTo (HaveOccurred ())
229+
230+ By ("creating a reconciler for APIBindings" )
181231 err = mcbuilder .ControllerManagedBy (mgr ).
182232 Named ("things" ).
183233 For (& apisv1alpha1.APIBinding {}).
@@ -211,6 +261,60 @@ var _ = Describe("VirtualWorkspace Provider", Ordered, func() {
211261 }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see the consumer workspace %q as a cluster" , consumer )
212262 })
213263
264+ It ("sees only the stone in the consumer clusters" , func () {
265+ By ("creating a stone in the consumer workspace" , func () {
266+ thing := & unstructured.Unstructured {}
267+ thing .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "Thing" })
268+ thing .SetNamespace ("stone" )
269+ thing .SetLabels (map [string ]string {"color" : "gray" })
270+ err := cli .Cluster (consumer ).Create (ctx , thing )
271+ Expect (err ).NotTo (HaveOccurred ())
272+ })
273+
274+ By ("creating a box in the other workspace" , func () {
275+ thing := & unstructured.Unstructured {}
276+ thing .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "Thing" })
277+ thing .SetNamespace ("box" )
278+ thing .SetLabels (map [string ]string {"color" : "white" })
279+ err := cli .Cluster (other ).Create (ctx , thing )
280+ Expect (err ).NotTo (HaveOccurred ())
281+ })
282+
283+ consumerCl , err := mgr .GetCluster (ctx , consumerWS .Spec .Cluster )
284+ Expect (err ).NotTo (HaveOccurred ())
285+
286+ envtest .Eventually (GinkgoT (), func () (success bool , reason string ) {
287+ l := & unstructured.UnstructuredList {}
288+ l .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "ThingList" })
289+ err = consumerCl .GetCache ().List (ctx , l )
290+ Expect (err ).NotTo (HaveOccurred ())
291+ if len (l .Items ) != 1 {
292+ return false , fmt .Sprintf ("expected 1 item, got %d\n \n %s" , len (l .Items ), toYAML (GinkgoT (), l .Object ))
293+ } else if name := l .Items [0 ].GetName (); name != "stone" {
294+ return false , fmt .Sprintf ("expected item name to be stone, got %q\n \n %s" , name , toYAML (GinkgoT (), l .Items [0 ]))
295+ }
296+ return true , ""
297+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see the stone in the consumer cluster" )
298+ })
299+
300+ It ("sees only the stone as grey thing in the consumer clusters" , func () {
301+ consumerCl , err := mgr .GetCluster (ctx , consumerWS .Spec .Cluster )
302+ Expect (err ).NotTo (HaveOccurred ())
303+
304+ envtest .Eventually (GinkgoT (), func () (success bool , reason string ) {
305+ l := & unstructured.UnstructuredList {}
306+ l .SetGroupVersionKind (runtimeschema.GroupVersionKind {Group : "example.com" , Version : "v1" , Kind : "ThingList" })
307+ err = consumerCl .GetCache ().List (ctx , l , client.MatchingFields {"color" : "gray" })
308+ Expect (err ).NotTo (HaveOccurred ())
309+ if len (l .Items ) != 1 {
310+ return false , fmt .Sprintf ("expected 1 item, got %d\n \n %s" , len (l .Items ), toYAML (GinkgoT (), l .Object ))
311+ } else if name := l .Items [0 ].GetName (); name != "stone" {
312+ return false , fmt .Sprintf ("expected item name to be stone, got %q\n \n %s" , name , toYAML (GinkgoT (), l .Items [0 ]))
313+ }
314+ return true , ""
315+ }, wait .ForeverTestTimeout , time .Millisecond * 100 , "failed to see the stone as only thing of color 'grey' in the consumer cluster" )
316+ })
317+
214318 AfterAll (func () {
215319 cancelGroup ()
216320 err := g .Wait ()
0 commit comments