@@ -21,12 +21,17 @@ import (
21
21
)
22
22
23
23
const (
24
- clusterSyncTimeout = 1 * time .Hour
24
+ clusterSyncTimeout = 24 * time .Hour
25
25
clusterRetryTimeout = 10 * time .Second
26
26
)
27
27
28
+ type gkInfo struct {
29
+ resource metav1.APIResource
30
+ listVersion string
31
+ }
32
+
28
33
type clusterInfo struct {
29
- apis map [schema.GroupVersionKind ]metav1. APIResource
34
+ apis map [schema.GroupKind ] * gkInfo
30
35
nodes map [kube.ResourceKey ]* node
31
36
nsIndex map [string ]map [kube.ResourceKey ]* node
32
37
lock * sync.Mutex
@@ -40,6 +45,46 @@ type clusterInfo struct {
40
45
settings * settings.ArgoCDSettings
41
46
}
42
47
48
+ func (c * clusterInfo ) getResourceVersion (gk schema.GroupKind ) string {
49
+ c .lock .Lock ()
50
+ defer c .lock .Unlock ()
51
+ info , ok := c .apis [gk ]
52
+ if ok {
53
+ return info .listVersion
54
+ }
55
+ return ""
56
+ }
57
+
58
+ func (c * clusterInfo ) updateCache (gk schema.GroupKind , resourceVersion string , objs []unstructured.Unstructured ) {
59
+ c .lock .Lock ()
60
+ defer c .lock .Unlock ()
61
+ info , ok := c .apis [gk ]
62
+ if ok {
63
+ objByKind := make (map [kube.ResourceKey ]* unstructured.Unstructured )
64
+ for i := range objs {
65
+ objByKind [kube .GetResourceKey (& objs [i ])] = & objs [i ]
66
+ }
67
+
68
+ for i := range objs {
69
+ obj := & objs [i ]
70
+ key := kube .GetResourceKey (& objs [i ])
71
+ existingNode , exists := c .nodes [key ]
72
+ c .onNodeUpdated (exists , existingNode , obj , key )
73
+ }
74
+
75
+ for key , existingNode := range c .nodes {
76
+ if key .Kind != gk .Kind || key .Group != gk .Group {
77
+ continue
78
+ }
79
+
80
+ if _ , ok := objByKind [key ]; ! ok {
81
+ c .onNodeRemoved (key , existingNode )
82
+ }
83
+ }
84
+ info .listVersion = resourceVersion
85
+ }
86
+ }
87
+
43
88
func createObjInfo (un * unstructured.Unstructured , appInstanceLabel string ) * node {
44
89
ownerRefs := un .GetOwnerReferences ()
45
90
// Special case for endpoint. Remove after https://github.com/kubernetes/kubernetes/issues/28483 is fixed
@@ -113,34 +158,29 @@ func (c *clusterInfo) sync() (err error) {
113
158
114
159
c .log .Info ("Start syncing cluster" )
115
160
116
- clusterResources , err := c .kubectl .GetAPIResources (c .cluster .RESTConfig ())
117
- if err != nil {
118
- if len (clusterResources ) == 0 {
119
- return err
120
- }
121
- log .Warnf ("Partial success when getting API resources during sync: %v" , err )
122
- }
123
- c .apis = make (map [schema.GroupVersionKind ]metav1.APIResource )
124
- for _ , r := range clusterResources {
125
- gv , err := schema .ParseGroupVersion (r .GroupVersion )
126
- if err != nil {
127
- gv = schema.GroupVersion {}
128
- }
129
- for i := range r .APIResources {
130
- c .apis [gv .WithKind (r .APIResources [i ].Kind )] = r .APIResources [i ]
131
- }
132
- }
133
-
161
+ c .apis = make (map [schema.GroupKind ]* gkInfo )
134
162
c .nodes = make (map [kube.ResourceKey ]* node )
163
+
135
164
resources , err := c .kubectl .GetResources (c .cluster .RESTConfig (), c .settings , "" )
136
165
if err != nil {
137
166
log .Errorf ("Failed to sync cluster %s: %v" , c .cluster .Server , err )
138
167
return err
139
168
}
140
169
141
170
appLabelKey := c .settings .GetAppInstanceLabelKey ()
142
- for i := range resources {
143
- c .setNode (createObjInfo (resources [i ], appLabelKey ))
171
+ for res := range resources {
172
+ if res .Error != nil {
173
+ return res .Error
174
+ }
175
+ if _ , ok := c .apis [res .GVK .GroupKind ()]; ! ok {
176
+ c .apis [res .GVK .GroupKind ()] = & gkInfo {
177
+ listVersion : res .ListResourceVersion ,
178
+ resource : res .ResourceInfo ,
179
+ }
180
+ }
181
+ for i := range res .Objects {
182
+ c .setNode (createObjInfo (& res .Objects [i ], appLabelKey ))
183
+ }
144
184
}
145
185
146
186
c .log .Info ("Cluster successfully synced" )
@@ -179,8 +219,8 @@ func (c *clusterInfo) getChildren(obj *unstructured.Unstructured) []appv1.Resour
179
219
return children
180
220
}
181
221
182
- func (c * clusterInfo ) isNamespaced (gvk schema.GroupVersionKind ) bool {
183
- if api , ok := c .apis [gvk ]; ok && ! api .Namespaced {
222
+ func (c * clusterInfo ) isNamespaced (gk schema.GroupKind ) bool {
223
+ if api , ok := c .apis [gk ]; ok && ! api . resource .Namespaced {
184
224
return false
185
225
}
186
226
return true
@@ -202,7 +242,7 @@ func (c *clusterInfo) getManagedLiveObjs(a *appv1.Application, targetObjs []*uns
202
242
lock := & sync.Mutex {}
203
243
err := util .RunAllAsync (len (targetObjs ), func (i int ) error {
204
244
targetObj := targetObjs [i ]
205
- key := GetTargetObjKey (a , targetObj , c .isNamespaced (targetObj .GroupVersionKind ()))
245
+ key := GetTargetObjKey (a , targetObj , c .isNamespaced (targetObj .GroupVersionKind (). GroupKind () ))
206
246
lock .Lock ()
207
247
managedObj := managedObjs [key ]
208
248
lock .Unlock ()
@@ -274,38 +314,44 @@ func (c *clusterInfo) processEvent(event watch.EventType, un *unstructured.Unstr
274
314
existingNode , exists := c .nodes [key ]
275
315
if event == watch .Deleted {
276
316
if exists {
277
- c .removeNode (key )
278
- if existingNode .appName != "" {
279
- c .onAppUpdated (existingNode .appName )
280
- }
317
+ c .onNodeRemoved (key , existingNode )
281
318
}
282
319
} else if event != watch .Deleted {
283
- nodes := make ([]* node , 0 )
284
- if exists {
285
- nodes = append (nodes , existingNode )
286
- }
287
- newObj := createObjInfo (un , c .settings .GetAppInstanceLabelKey ())
288
- c .setNode (newObj )
289
- nodes = append (nodes , newObj )
290
-
291
- toNotify := make (map [string ]bool )
292
- for i := range nodes {
293
- n := nodes [i ]
294
- if ns , ok := c .nsIndex [n .ref .Namespace ]; ok {
295
- app := n .getApp (ns )
296
- if app == "" || skipAppRequeing (key ) {
297
- continue
298
- }
299
- toNotify [app ] = true
300
- }
301
- }
320
+ c .onNodeUpdated (exists , existingNode , un , key )
321
+ }
322
+
323
+ return nil
324
+ }
302
325
303
- for name := range toNotify {
304
- c .onAppUpdated (name )
326
+ func (c * clusterInfo ) onNodeUpdated (exists bool , existingNode * node , un * unstructured.Unstructured , key kube.ResourceKey ) {
327
+ nodes := make ([]* node , 0 )
328
+ if exists {
329
+ nodes = append (nodes , existingNode )
330
+ }
331
+ newObj := createObjInfo (un , c .settings .GetAppInstanceLabelKey ())
332
+ c .setNode (newObj )
333
+ nodes = append (nodes , newObj )
334
+ toNotify := make (map [string ]bool )
335
+ for i := range nodes {
336
+ n := nodes [i ]
337
+ if ns , ok := c .nsIndex [n .ref .Namespace ]; ok {
338
+ app := n .getApp (ns )
339
+ if app == "" || skipAppRequeing (key ) {
340
+ continue
341
+ }
342
+ toNotify [app ] = true
305
343
}
306
344
}
345
+ for name := range toNotify {
346
+ c .onAppUpdated (name )
347
+ }
348
+ }
307
349
308
- return nil
350
+ func (c * clusterInfo ) onNodeRemoved (key kube.ResourceKey , existingNode * node ) {
351
+ c .removeNode (key )
352
+ if existingNode .appName != "" {
353
+ c .onAppUpdated (existingNode .appName )
354
+ }
309
355
}
310
356
311
357
var (
0 commit comments