@@ -24,12 +24,12 @@ import (
24
24
"time"
25
25
26
26
"github.com/go-logr/logr"
27
-
28
27
mcmanager "github.com/multicluster-runtime/multicluster-runtime/pkg/manager"
29
28
"github.com/multicluster-runtime/multicluster-runtime/pkg/multicluster"
30
29
"k8s.io/apimachinery/pkg/util/sets"
31
30
"k8s.io/apimachinery/pkg/util/wait"
32
31
"k8s.io/client-go/tools/clientcmd"
32
+ "sigs.k8s.io/controller-runtime/pkg/client"
33
33
"sigs.k8s.io/controller-runtime/pkg/cluster"
34
34
"sigs.k8s.io/controller-runtime/pkg/log"
35
35
kind "sigs.k8s.io/kind/pkg/cluster"
@@ -46,29 +46,36 @@ func New() *Provider {
46
46
}
47
47
}
48
48
49
+ type index struct {
50
+ object client.Object
51
+ field string
52
+ extractValue client.IndexerFunc
53
+ }
54
+
49
55
// Provider is a cluster Provider that works with a local Kind instance.
50
56
type Provider struct {
51
57
opts []cluster.Option
52
58
log logr.Logger
53
59
lock sync.RWMutex
54
60
clusters map [string ]cluster.Cluster
55
61
cancelFns map [string ]context.CancelFunc
62
+ indexers []index
56
63
}
57
64
58
65
// Get returns the cluster with the given name, if it is known.
59
- func (k * Provider ) Get (ctx context.Context , clusterName string ) (cluster.Cluster , error ) {
60
- k .lock .RLock ()
61
- defer k .lock .RUnlock ()
62
- if cl , ok := k .clusters [clusterName ]; ok {
66
+ func (p * Provider ) Get (ctx context.Context , clusterName string ) (cluster.Cluster , error ) {
67
+ p .lock .RLock ()
68
+ defer p .lock .RUnlock ()
69
+ if cl , ok := p .clusters [clusterName ]; ok {
63
70
return cl , nil
64
71
}
65
72
66
73
return nil , fmt .Errorf ("cluster %s not found" , clusterName )
67
74
}
68
75
69
76
// Run starts the provider and blocks.
70
- func (k * Provider ) Run (ctx context.Context , mgr mcmanager.Manager ) error {
71
- k .log .Info ("Starting kind cluster provider" )
77
+ func (p * Provider ) Run (ctx context.Context , mgr mcmanager.Manager ) error {
78
+ p .log .Info ("Starting kind cluster provider" )
72
79
73
80
provider := kind .NewProvider ()
74
81
@@ -80,41 +87,46 @@ func (k *Provider) Run(ctx context.Context, mgr mcmanager.Manager) error {
80
87
return wait .PollUntilContextCancel (ctx , time .Second * 2 , true , func (ctx context.Context ) (done bool , err error ) {
81
88
list , err := provider .List ()
82
89
if err != nil {
83
- k .log .Info ("failed to list kind clusters" , "error" , err )
90
+ p .log .Info ("failed to list kind clusters" , "error" , err )
84
91
return false , nil // keep going
85
92
}
86
93
87
94
// start new clusters
88
95
for _ , clusterName := range list {
89
- log := k .log .WithValues ("cluster" , clusterName )
96
+ log := p .log .WithValues ("cluster" , clusterName )
90
97
91
98
// skip?
92
99
if ! strings .HasPrefix (clusterName , "fleet-" ) {
93
100
continue
94
101
}
95
- k .lock .RLock ()
96
- if _ , ok := k .clusters [clusterName ]; ok {
97
- k .lock .RUnlock ()
102
+ p .lock .RLock ()
103
+ if _ , ok := p .clusters [clusterName ]; ok {
104
+ p .lock .RUnlock ()
98
105
continue
99
106
}
100
- k .lock .RUnlock ()
107
+ p .lock .RUnlock ()
101
108
102
109
// create a new cluster
103
110
kubeconfig , err := provider .KubeConfig (clusterName , false )
104
111
if err != nil {
105
- k .log .Info ("failed to get kind kubeconfig" , "error" , err )
112
+ p .log .Info ("failed to get kind kubeconfig" , "error" , err )
106
113
return false , nil // keep going
107
114
}
108
115
cfg , err := clientcmd .RESTConfigFromKubeConfig ([]byte (kubeconfig ))
109
116
if err != nil {
110
- k .log .Info ("failed to create rest config" , "error" , err )
117
+ p .log .Info ("failed to create rest config" , "error" , err )
111
118
return false , nil // keep going
112
119
}
113
- cl , err := cluster .New (cfg , k .opts ... )
120
+ cl , err := cluster .New (cfg , p .opts ... )
114
121
if err != nil {
115
- k .log .Info ("failed to create cluster" , "error" , err )
122
+ p .log .Info ("failed to create cluster" , "error" , err )
116
123
return false , nil // keep going
117
124
}
125
+ for _ , idx := range p .indexers {
126
+ if err := cl .GetCache ().IndexField (ctx , idx .object , idx .field , idx .extractValue ); err != nil {
127
+ return false , fmt .Errorf ("failed to index field %q: %w" , idx .field , err )
128
+ }
129
+ }
118
130
clusterCtx , cancel := context .WithCancel (ctx )
119
131
go func () {
120
132
if err := cl .Start (clusterCtx ); err != nil {
@@ -129,47 +141,69 @@ func (k *Provider) Run(ctx context.Context, mgr mcmanager.Manager) error {
129
141
}
130
142
131
143
// remember
132
- k .lock .Lock ()
133
- k .clusters [clusterName ] = cl
134
- k .cancelFns [clusterName ] = cancel
135
- k .lock .Unlock ()
144
+ p .lock .Lock ()
145
+ p .clusters [clusterName ] = cl
146
+ p .cancelFns [clusterName ] = cancel
147
+ p .lock .Unlock ()
136
148
137
- k .log .Info ("Added new cluster" , "cluster" , clusterName )
149
+ p .log .Info ("Added new cluster" , "cluster" , clusterName )
138
150
139
151
// engage manager
140
152
if mgr != nil {
141
153
if err := mgr .Engage (clusterCtx , clusterName , cl ); err != nil {
142
154
log .Error (err , "failed to engage manager" )
143
- k .lock .Lock ()
144
- delete (k .clusters , clusterName )
145
- delete (k .cancelFns , clusterName )
146
- k .lock .Unlock ()
155
+ p .lock .Lock ()
156
+ delete (p .clusters , clusterName )
157
+ delete (p .cancelFns , clusterName )
158
+ p .lock .Unlock ()
147
159
return false , nil
148
160
}
149
161
}
150
162
}
151
163
152
164
// remove old clusters
153
165
kindNames := sets .New (list ... )
154
- k .lock .Lock ()
155
- clusterNames := make ([]string , 0 , len (k .clusters ))
156
- for name := range k .clusters {
166
+ p .lock .Lock ()
167
+ clusterNames := make ([]string , 0 , len (p .clusters ))
168
+ for name := range p .clusters {
157
169
clusterNames = append (clusterNames , name )
158
170
}
159
- k .lock .Unlock ()
171
+ p .lock .Unlock ()
160
172
for _ , name := range clusterNames {
161
173
if ! kindNames .Has (name ) {
162
174
// stop and forget
163
- k .lock .Lock ()
164
- k .cancelFns [name ]()
165
- delete (k .clusters , name )
166
- delete (k .cancelFns , name )
167
- k .lock .Unlock ()
175
+ p .lock .Lock ()
176
+ p .cancelFns [name ]()
177
+ delete (p .clusters , name )
178
+ delete (p .cancelFns , name )
179
+ p .lock .Unlock ()
168
180
169
- k .log .Info ("Cluster removed" , "cluster" , name )
181
+ p .log .Info ("Cluster removed" , "cluster" , name )
170
182
}
171
183
}
172
184
173
185
return false , nil
174
186
})
175
187
}
188
+
189
+ // IndexField indexes a field on all clusters, existing and future.
190
+ func (p * Provider ) IndexField (ctx context.Context , obj client.Object , field string , extractValue client.IndexerFunc ) error {
191
+ p .lock .Lock ()
192
+ defer p .lock .Unlock ()
193
+
194
+ // save for future clusters.
195
+ p .indexers = append (p .indexers , index {
196
+ object : obj ,
197
+ field : field ,
198
+ extractValue : extractValue ,
199
+ })
200
+
201
+ // apply to existing clusters.
202
+ for name , cl := range p .clusters {
203
+ if err := cl .GetCache ().IndexField (ctx , obj , field , extractValue ); err != nil {
204
+ return fmt .Errorf ("failed to index field %q on cluster %q: %w" , field , name , err )
205
+ }
206
+ }
207
+
208
+ return nil
209
+ }
0 commit comments