From 29ec82d743b7f187c97e21ca5e33321a6717e7f5 Mon Sep 17 00:00:00 2001 From: Drew Minnear Date: Wed, 13 Aug 2025 14:29:42 -0400 Subject: [PATCH 1/3] add value to operator configmap for enabling/disabling analytics --- cmd/main.go | 25 ++++++++++- cmd/main_test.go | 74 +++++++++++++++++++++++++++++++++ internal/controller/defaults.go | 1 + 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 cmd/main_test.go diff --git a/cmd/main.go b/cmd/main.go index 2874b36a4..e2fd978fa 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -34,6 +34,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" + crclient "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -103,11 +104,12 @@ func main() { registerComponentOrExit(mgr, argov1beta1api.AddToScheme) - isAnalyticsDisabled := strings.ToLower(os.Getenv("ANALYTICS")) == "false" + analyticsDisabled := isAnalyticsDisabled(mgr.GetAPIReader()) + setupLog.Info("analytics disabled", "disabled", analyticsDisabled) if err = (&controllers.PatternReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - AnalyticsClient: controllers.AnalyticsInit(isAnalyticsDisabled, setupLog), + AnalyticsClient: controllers.AnalyticsInit(analyticsDisabled, setupLog), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Pattern") os.Exit(1) @@ -184,3 +186,22 @@ func registerComponentOrExit(mgr manager.Manager, f func(*k8sruntime.Scheme) err } setupLog.Info(fmt.Sprintf("Component registered: %v", reflect.ValueOf(f))) } + +// isAnalyticsDisabled determines whether analytics are disabled. +// Precedence: Operator ConfigMap key "analytics.disabled" (true/false) > ENV ANALYTICS (false means disabled) +func isAnalyticsDisabled(reader crclient.Reader) bool { + disabled := strings.ToLower(os.Getenv("ANALYTICS")) == "false" + + var cm corev1.ConfigMap + err := reader.Get(context.Background(), crclient.ObjectKey{Namespace: controllers.OperatorNamespace, Name: controllers.OperatorConfigMap}, &cm) + if err != nil { + setupLog.Error(err, "error reading operator configmap for analytics setting") + return disabled + } + + if v, ok := cm.Data["analytics.disabled"]; ok { + return strings.EqualFold(v, "true") + } + + return disabled +} diff --git a/cmd/main_test.go b/cmd/main_test.go new file mode 100644 index 000000000..c06fd0b09 --- /dev/null +++ b/cmd/main_test.go @@ -0,0 +1,74 @@ +package main + +import ( + "os" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + crclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + + controllers "github.com/hybrid-cloud-patterns/patterns-operator/internal/controller" +) + +func newFakeReader(objs ...crclient.Object) crclient.Reader { + scheme := runtime.NewScheme() + _ = corev1.AddToScheme(scheme) + builder := fake.NewClientBuilder().WithScheme(scheme) + if len(objs) > 0 { + builder = builder.WithObjects(objs...) + } + return builder.Build() +} + +func newOperatorConfigMap(analyticsDisabled string) *corev1.ConfigMap { + return &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: controllers.OperatorNamespace, + Name: controllers.OperatorConfigMap, + }, + Data: map[string]string{ + "analytics.disabled": analyticsDisabled, + }, + } +} + +func TestIsAnalyticsDisabledWithReader_ConfigMapTrue(t *testing.T) { + cm := newOperatorConfigMap("true") + reader := newFakeReader(cm) + + if got := isAnalyticsDisabled(reader); got != true { + t.Fatalf("expected true when configmap sets analytics.disabled=true, got %v", got) + } +} + +func TestIsAnalyticsDisabledWithReader_ConfigMapFalse(t *testing.T) { + cm := newOperatorConfigMap("false") + reader := newFakeReader(cm) + + if got := isAnalyticsDisabled(reader); got != false { + t.Fatalf("expected false when configmap sets analytics.disabled=false, got %v", got) + } +} + +func TestIsAnalyticsDisabledWithReader_NoConfigMap_EnvFalseDisables(t *testing.T) { + _ = os.Setenv("ANALYTICS", "false") + t.Cleanup(func() { _ = os.Unsetenv("ANALYTICS") }) + + reader := newFakeReader() + if got := isAnalyticsDisabled(reader); got != true { + t.Fatalf("expected true when no configmap and ANALYTICS=false, got %v", got) + } +} + +func TestIsAnalyticsDisabledWithReader_NoConfigMap_EnvTrueEnables(t *testing.T) { + _ = os.Setenv("ANALYTICS", "true") + t.Cleanup(func() { _ = os.Unsetenv("ANALYTICS") }) + + reader := newFakeReader() + if got := isAnalyticsDisabled(reader); got != false { + t.Fatalf("expected false when no configmap and ANALYTICS=true, got %v", got) + } +} diff --git a/internal/controller/defaults.go b/internal/controller/defaults.go index 9d26276b6..36e0c29e4 100644 --- a/internal/controller/defaults.go +++ b/internal/controller/defaults.go @@ -75,6 +75,7 @@ var DefaultPatternOperatorConfig = map[string]string{ "gitea.chartName": GiteaChartName, "gitea.helmRepoUrl": GiteaHelmRepoUrl, "gitea.chartVersion": GiteaDefaultChartVersion, + "analytics.disabled": "false", } type GitOpsConfig map[string]string From b1b0cc91e75dbab609353bb7a13bb98b3a4fdf30 Mon Sep 17 00:00:00 2001 From: Drew Minnear Date: Fri, 15 Aug 2025 18:04:15 -0400 Subject: [PATCH 2/3] use analytics.enabled from operator configmap instead of analytics.disabled for clarity --- cmd/main.go | 20 ++++++++++---------- cmd/main_test.go | 28 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index e2fd978fa..18f661844 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -104,12 +104,12 @@ func main() { registerComponentOrExit(mgr, argov1beta1api.AddToScheme) - analyticsDisabled := isAnalyticsDisabled(mgr.GetAPIReader()) - setupLog.Info("analytics disabled", "disabled", analyticsDisabled) + analyticsEnabled := areAnalyticsEnabled(mgr.GetAPIReader()) + setupLog.Info("analytics enabled", "enabled", analyticsEnabled) if err = (&controllers.PatternReconciler{ Client: mgr.GetClient(), Scheme: mgr.GetScheme(), - AnalyticsClient: controllers.AnalyticsInit(analyticsDisabled, setupLog), + AnalyticsClient: controllers.AnalyticsInit(!analyticsEnabled, setupLog), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Pattern") os.Exit(1) @@ -187,21 +187,21 @@ func registerComponentOrExit(mgr manager.Manager, f func(*k8sruntime.Scheme) err setupLog.Info(fmt.Sprintf("Component registered: %v", reflect.ValueOf(f))) } -// isAnalyticsDisabled determines whether analytics are disabled. -// Precedence: Operator ConfigMap key "analytics.disabled" (true/false) > ENV ANALYTICS (false means disabled) -func isAnalyticsDisabled(reader crclient.Reader) bool { - disabled := strings.ToLower(os.Getenv("ANALYTICS")) == "false" +// areAnalyticsEnabled determines whether analytics are enabled. +// Precedence: Operator ConfigMap key "analytics.enabled" (true/false) > ENV ANALYTICS (false means disabled) +func areAnalyticsEnabled(reader crclient.Reader) bool { + enabled := strings.ToLower(os.Getenv("ANALYTICS")) != "false" var cm corev1.ConfigMap err := reader.Get(context.Background(), crclient.ObjectKey{Namespace: controllers.OperatorNamespace, Name: controllers.OperatorConfigMap}, &cm) if err != nil { setupLog.Error(err, "error reading operator configmap for analytics setting") - return disabled + return enabled } - if v, ok := cm.Data["analytics.disabled"]; ok { + if v, ok := cm.Data["analytics.enabled"]; ok { return strings.EqualFold(v, "true") } - return disabled + return enabled } diff --git a/cmd/main_test.go b/cmd/main_test.go index c06fd0b09..fa9a7e4dd 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -23,52 +23,52 @@ func newFakeReader(objs ...crclient.Object) crclient.Reader { return builder.Build() } -func newOperatorConfigMap(analyticsDisabled string) *corev1.ConfigMap { +func newOperatorConfigMap(analyticsEnabled string) *corev1.ConfigMap { return &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Namespace: controllers.OperatorNamespace, Name: controllers.OperatorConfigMap, }, Data: map[string]string{ - "analytics.disabled": analyticsDisabled, + "analytics.enabled": analyticsEnabled, }, } } -func TestIsAnalyticsDisabledWithReader_ConfigMapTrue(t *testing.T) { +func TestAreAnalyticsEnabledWithReader_ConfigMapTrue(t *testing.T) { cm := newOperatorConfigMap("true") reader := newFakeReader(cm) - if got := isAnalyticsDisabled(reader); got != true { - t.Fatalf("expected true when configmap sets analytics.disabled=true, got %v", got) + if got := areAnalyticsEnabled(reader); got != true { + t.Fatalf("expected true when configmap sets analytics.enabled=true, got %v", got) } } -func TestIsAnalyticsDisabledWithReader_ConfigMapFalse(t *testing.T) { +func TestAreAnalyticsEnabledWithReader_ConfigMapFalse(t *testing.T) { cm := newOperatorConfigMap("false") reader := newFakeReader(cm) - if got := isAnalyticsDisabled(reader); got != false { - t.Fatalf("expected false when configmap sets analytics.disabled=false, got %v", got) + if got := areAnalyticsEnabled(reader); got != false { + t.Fatalf("expected false when configmap sets analytics.enabled=false, got %v", got) } } -func TestIsAnalyticsDisabledWithReader_NoConfigMap_EnvFalseDisables(t *testing.T) { +func TestAreAnalyticsEnabledWithReader_NoConfigMap_EnvFalseDisables(t *testing.T) { _ = os.Setenv("ANALYTICS", "false") t.Cleanup(func() { _ = os.Unsetenv("ANALYTICS") }) reader := newFakeReader() - if got := isAnalyticsDisabled(reader); got != true { - t.Fatalf("expected true when no configmap and ANALYTICS=false, got %v", got) + if got := areAnalyticsEnabled(reader); got != false { + t.Fatalf("expected false when no configmap and ANALYTICS=false, got %v", got) } } -func TestIsAnalyticsDisabledWithReader_NoConfigMap_EnvTrueEnables(t *testing.T) { +func TestAreAnalyticsEnabledWithReader_NoConfigMap_EnvTrueEnables(t *testing.T) { _ = os.Setenv("ANALYTICS", "true") t.Cleanup(func() { _ = os.Unsetenv("ANALYTICS") }) reader := newFakeReader() - if got := isAnalyticsDisabled(reader); got != false { - t.Fatalf("expected false when no configmap and ANALYTICS=true, got %v", got) + if got := areAnalyticsEnabled(reader); got != true { + t.Fatalf("expected true when no configmap and ANALYTICS=true, got %v", got) } } From c82747ffb3c3250d140f3e0aa1ab6772b46b97a1 Mon Sep 17 00:00:00 2001 From: Drew Minnear Date: Wed, 27 Aug 2025 10:25:49 -0400 Subject: [PATCH 3/3] update defaults to use analytics.enabled --- internal/controller/defaults.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/controller/defaults.go b/internal/controller/defaults.go index 36e0c29e4..030e5bb43 100644 --- a/internal/controller/defaults.go +++ b/internal/controller/defaults.go @@ -75,7 +75,7 @@ var DefaultPatternOperatorConfig = map[string]string{ "gitea.chartName": GiteaChartName, "gitea.helmRepoUrl": GiteaHelmRepoUrl, "gitea.chartVersion": GiteaDefaultChartVersion, - "analytics.disabled": "false", + "analytics.enabled": "true", } type GitOpsConfig map[string]string