Skip to content

Commit e093189

Browse files
committed
WIP
Signed-off-by: Siddhesh Ghadi <sghadi1203@gmail.com>
1 parent 34b24f2 commit e093189

File tree

2 files changed

+141
-3
lines changed

2 files changed

+141
-3
lines changed

cmd/main.go

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ import (
2828
configv1 "github.com/openshift/api/config/v1"
2929
routev1 "github.com/openshift/api/route/v1"
3030
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
31+
v1 "k8s.io/api/core/v1"
3132
"k8s.io/client-go/kubernetes"
3233
"sigs.k8s.io/controller-runtime/pkg/cache"
34+
crclient "sigs.k8s.io/controller-runtime/pkg/client"
3335
"sigs.k8s.io/controller-runtime/pkg/client/config"
3436
"sigs.k8s.io/controller-runtime/pkg/manager"
3537
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -58,7 +60,10 @@ import (
5860

5961
v1alpha1 "github.com/argoproj-labs/argocd-operator/api/v1alpha1"
6062
v1beta1 "github.com/argoproj-labs/argocd-operator/api/v1beta1"
63+
wc "github.com/argoproj-labs/argocd-operator/pkg/clientwrapper"
6164
"github.com/argoproj-labs/argocd-operator/version"
65+
corev1 "k8s.io/api/core/v1"
66+
toolscache "k8s.io/client-go/tools/cache"
6267
//+kubebuilder:scaffold:imports
6368
)
6469

@@ -179,6 +184,12 @@ func main() {
179184
Controller: controllerconfig.Controller{
180185
SkipNameValidation: &skipControllerNameValidation,
181186
},
187+
Cache: cache.Options{
188+
Scheme: scheme,
189+
ByObject: map[crclient.Object]cache.ByObject{
190+
&corev1.Secret{}: {Transform: slimSecret()},
191+
},
192+
},
182193
}
183194

184195
if watchedNsCache := getDefaultWatchedNamespacesCacheOptions(); watchedNsCache != nil {
@@ -193,6 +204,10 @@ func main() {
193204
os.Exit(1)
194205
}
195206

207+
liveClient, err := crclient.New(ctrl.GetConfigOrDie(), crclient.Options{Scheme: mgr.GetScheme()})
208+
client := wc.NewClientWrapper(mgr.GetClient(), liveClient)
209+
//print(client)
210+
196211
setupLog.Info("Registering Components.")
197212

198213
// Setup Scheme for all resources
@@ -236,7 +251,7 @@ func main() {
236251
os.Exit(1)
237252
}
238253
if err = (&argocd.ReconcileArgoCD{
239-
Client: mgr.GetClient(),
254+
Client: client,
240255
Scheme: mgr.GetScheme(),
241256
LabelSelector: labelSelectorFlag,
242257
K8sClient: k8sClient,
@@ -248,14 +263,14 @@ func main() {
248263
os.Exit(1)
249264
}
250265
if err = (&argocdexport.ReconcileArgoCDExport{
251-
Client: mgr.GetClient(),
266+
Client: client,
252267
Scheme: mgr.GetScheme(),
253268
}).SetupWithManager(mgr); err != nil {
254269
setupLog.Error(err, "unable to create controller", "controller", "ArgoCDExport")
255270
os.Exit(1)
256271
}
257272
if err = (&notificationsConfig.NotificationsConfigurationReconciler{
258-
Client: mgr.GetClient(),
273+
Client: client,
259274
Scheme: mgr.GetScheme(),
260275
}).SetupWithManager(mgr); err != nil {
261276
setupLog.Error(err, "unable to create controller", "controller", "NotificationsConfiguration")
@@ -338,3 +353,36 @@ func initK8sClient() (*kubernetes.Clientset, error) {
338353

339354
return k8sClient, nil
340355
}
356+
357+
func slimSecret() toolscache.TransformFunc {
358+
return func(in interface{}) (interface{}, error) {
359+
if s, ok := in.(*v1.Secret); ok {
360+
if isRequiredByOperator(s.Labels) {
361+
return in, nil
362+
}
363+
out := &v1.Secret{
364+
TypeMeta: s.TypeMeta,
365+
ObjectMeta: *s.ObjectMeta.DeepCopy(),
366+
Type: s.Type, // keep if you match on it
367+
}
368+
// (Data and StringData intentionally omitted)
369+
// managedFields can also be stripped via DefaultTransform if you set it.
370+
return out, nil
371+
}
372+
return in, nil
373+
}
374+
}
375+
376+
func isRequiredByOperator(labels map[string]string) bool {
377+
interestedLabels := []string{
378+
common.ArgoCDTrackedByOperatorLabel,
379+
common.ArgoCDSecretTypeLabel,
380+
}
381+
382+
for _, l := range interestedLabels {
383+
if _, exists := labels[l]; exists {
384+
return true
385+
}
386+
}
387+
return false
388+
}

pkg/clientwrapper/client.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package clientwrapper
2+
3+
import (
4+
"context"
5+
6+
"github.com/argoproj-labs/argocd-operator/common"
7+
corev1 "k8s.io/api/core/v1"
8+
"k8s.io/apimachinery/pkg/types"
9+
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" // Renamed to avoid conflict with our wrapper's name
10+
)
11+
12+
// ClientWrapper wraps a controller-runtime client to customize Get behavior.
13+
// It embeds the cachedClient, allowing other methods (Create, Update, Delete etc.)
14+
// to be directly inherited from the cachedClient's implementation.
15+
// For Get, it falls back to liveClient on cache miss and labels the object.
16+
type ClientWrapper struct {
17+
ctrlclient.Client // Embedded cached client. This provides all methods by default.
18+
liveClient ctrlclient.Client // Client for direct API server calls on cache misses.
19+
}
20+
21+
// NewClientWrapper creates a new ClientWrapper.
22+
// `cachedClient` is typically the client from the Manager (which uses the cache and respects cache filters).
23+
// `liveClient` is a client configured to bypass the cache and talk directly to the API server.
24+
func NewClientWrapper(cachedClient ctrlclient.Client, liveClient ctrlclient.Client) *ClientWrapper {
25+
return &ClientWrapper{
26+
Client: cachedClient, // Embed the cached client
27+
liveClient: liveClient,
28+
}
29+
}
30+
31+
// Get overrides the embedded client's Get method to implement cache fallback.
32+
func (cw *ClientWrapper) Get(ctx context.Context, key types.NamespacedName, obj ctrlclient.Object, opts ...ctrlclient.GetOption) error {
33+
// Try getting from the cached client first (this is the embedded client's Get)
34+
err := cw.Client.Get(ctx, key, obj, opts...)
35+
if err != nil {
36+
// Found in cache, return successfully
37+
return err
38+
}
39+
40+
makeLiveCheck := false
41+
switch obj := obj.(type) {
42+
case *corev1.Secret:
43+
if !isRequiredByOperator(obj.GetLabels()) {
44+
makeLiveCheck = true
45+
}
46+
default:
47+
return nil
48+
}
49+
50+
// If not found in cache, check if it's a NotFound error
51+
if makeLiveCheck {
52+
// Use liveClient to do a live lookup of resource
53+
liveErr := cw.liveClient.Get(ctx, key, obj, opts...)
54+
if liveErr == nil {
55+
// Resource found live - try to label it for future caching
56+
// Create patch from the original live state
57+
patch := ctrlclient.MergeFrom(obj.DeepCopyObject().(ctrlclient.Object))
58+
// Add the tracking label to match cache filtering
59+
labels := obj.GetLabels()
60+
if labels == nil {
61+
labels = make(map[string]string)
62+
}
63+
labels[common.ArgoCDTrackedByOperatorLabel] = common.ArgoCDAppName
64+
obj.SetLabels(labels)
65+
// Attempt to patch the live object with the new label
66+
// If patching fails, we still succeeded in getting the resource
67+
// Return success - we found the object live
68+
cw.liveClient.Patch(ctx, obj, patch)
69+
return nil
70+
}
71+
// Object not found in both cache and live - return the live error
72+
return liveErr
73+
}
74+
75+
return nil
76+
}
77+
78+
func isRequiredByOperator(labels map[string]string) bool {
79+
interestedLabels := []string{
80+
common.ArgoCDTrackedByOperatorLabel,
81+
common.ArgoCDSecretTypeLabel,
82+
}
83+
84+
for _, l := range interestedLabels {
85+
if _, exists := labels[l]; exists {
86+
return true
87+
}
88+
}
89+
return false
90+
}

0 commit comments

Comments
 (0)