diff --git a/.golangci.yaml b/.golangci.yaml index f229f2187..fdbb2e980 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -124,6 +124,8 @@ linters-settings: alias: ctrlpredicate - pkg: "github.com/kyma-project/telemetry-manager/internal/reconciler/commonstatus/stubs" alias: commonStatusStubs + - pkg: "k8s.io/client-go/testing" + alias: clienttesting errcheck: check-type-assertions: true # Reports type assertions: `a := b.(SomeStruct)`. check-blank: true # Report assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`. diff --git a/controllers/telemetry/logpipeline_controller.go b/controllers/telemetry/logpipeline_controller.go index 1e989149e..1b7e488f0 100644 --- a/controllers/telemetry/logpipeline_controller.go +++ b/controllers/telemetry/logpipeline_controller.go @@ -24,6 +24,8 @@ import ( rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" ctrlbuilder "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -65,6 +67,7 @@ type LogPipelineControllerConfig struct { PriorityClassName string SelfMonitorName string TelemetryNamespace string + RestConfig *rest.Config } func NewLogPipelineController(client client.Client, reconcileTriggerChan <-chan event.GenericEvent, config LogPipelineControllerConfig) (*LogPipelineController, error) { @@ -72,7 +75,6 @@ func NewLogPipelineController(client client.Client, reconcileTriggerChan <-chan if err != nil { return nil, err } - reconcilerCfg := logpipeline.Config{ SectionsConfigMap: types.NamespacedName{Name: "telemetry-fluent-bit-sections", Namespace: config.TelemetryNamespace}, FilesConfigMap: types.NamespacedName{Name: "telemetry-fluent-bit-files", Namespace: config.TelemetryNamespace}, @@ -99,12 +101,16 @@ func NewLogPipelineController(client client.Client, reconcileTriggerChan <-chan SecretRefValidator: &secretref.Validator{Client: client}, } + discoveryClient, err := discovery.NewDiscoveryClientForConfig(config.RestConfig) + if err != nil { + return nil, err + } reconciler := logpipeline.New( client, reconcilerCfg, &workloadstatus.DaemonSetProber{Client: client}, flowHealthProber, - istiostatus.NewChecker(client), + istiostatus.NewChecker(discoveryClient), overrides.New(client, overrides.HandlerConfig{SystemNamespace: config.TelemetryNamespace}), pipelineValidator, &conditions.ErrorToMessageConverter{}, diff --git a/controllers/telemetry/metricpipeline_controller.go b/controllers/telemetry/metricpipeline_controller.go index 9c8bc8076..81b03366e 100644 --- a/controllers/telemetry/metricpipeline_controller.go +++ b/controllers/telemetry/metricpipeline_controller.go @@ -26,6 +26,8 @@ import ( rbacv1 "k8s.io/api/rbac/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" ctrlbuilder "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -62,7 +64,7 @@ type MetricPipelineController struct { type MetricPipelineControllerConfig struct { metricpipeline.Config - + RestConfig *rest.Config SelfMonitorName string TelemetryNamespace string } @@ -84,7 +86,10 @@ func NewMetricPipelineController(client client.Client, reconcileTriggerChan <-ch agentRBAC := otelcollector.MakeMetricAgentRBAC(types.NamespacedName{Name: config.Agent.BaseName, Namespace: config.Agent.Namespace}) gatewayRBAC := otelcollector.MakeMetricGatewayRBAC(types.NamespacedName{Name: config.Gateway.BaseName, Namespace: config.Gateway.Namespace}, config.KymaInputAllowed) - + discoveryClient, err := discovery.NewDiscoveryClientForConfig(config.RestConfig) + if err != nil { + return nil, err + } reconciler := metricpipeline.New( client, config.Config, @@ -99,7 +104,7 @@ func NewMetricPipelineController(client client.Client, reconcileTriggerChan <-ch &otelcollector.GatewayApplierDeleter{Config: config.Gateway, RBAC: gatewayRBAC}, &gateway.Builder{Reader: client}, &workloadstatus.DeploymentProber{Client: client}, - istiostatus.NewChecker(client), + istiostatus.NewChecker(discoveryClient), overrides.New(client, overrides.HandlerConfig{SystemNamespace: config.TelemetryNamespace}), pipelineLock, pipelineValidator, diff --git a/controllers/telemetry/tracepipeline_controller.go b/controllers/telemetry/tracepipeline_controller.go index d3a974bbd..2ab1819eb 100644 --- a/controllers/telemetry/tracepipeline_controller.go +++ b/controllers/telemetry/tracepipeline_controller.go @@ -25,6 +25,8 @@ import ( networkingv1 "k8s.io/api/networking/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/discovery" + "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" ctrlbuilder "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -60,7 +62,7 @@ type TracePipelineController struct { type TracePipelineControllerConfig struct { tracepipeline.Config - + RestConfig *rest.Config SelfMonitorName string TelemetryNamespace string } @@ -81,7 +83,10 @@ func NewTracePipelineController(client client.Client, reconcileTriggerChan <-cha } gatewayRBAC := otelcollector.MakeTraceGatewayRBAC(types.NamespacedName{Name: config.Gateway.BaseName, Namespace: config.Gateway.Namespace}) - + discoveryClient, err := discovery.NewDiscoveryClientForConfig(config.RestConfig) + if err != nil { + return nil, err + } reconciler := tracepipeline.New( client, config.Config, @@ -89,7 +94,7 @@ func NewTracePipelineController(client client.Client, reconcileTriggerChan <-cha &otelcollector.GatewayApplierDeleter{Config: config.Gateway, RBAC: gatewayRBAC}, &gateway.Builder{Reader: client}, &workloadstatus.DeploymentProber{Client: client}, - istiostatus.NewChecker(client), + istiostatus.NewChecker(discoveryClient), overrides.New(client, overrides.HandlerConfig{SystemNamespace: config.TelemetryNamespace}), pipelineLock, pipelineValidator, diff --git a/internal/istiostatus/istio_status_checker.go b/internal/istiostatus/istio_status_checker.go index 0cd9b0377..462718506 100644 --- a/internal/istiostatus/istio_status_checker.go +++ b/internal/istiostatus/istio_status_checker.go @@ -2,36 +2,33 @@ package istiostatus import ( "context" - "slices" "strings" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/client-go/discovery" logf "sigs.k8s.io/controller-runtime/pkg/log" ) type Checker struct { - client client.Reader + discovery discovery.DiscoveryInterface } -const peerAuthenticationIstioCRD = "peerauthentications.security.istio.io" - -func NewChecker(client client.Reader) *Checker { - return &Checker{ - client: client, - } - +func NewChecker(d discovery.DiscoveryInterface) *Checker { + return &Checker{discovery: d} } // IsIstioActive checks if Istio is active on the cluster based on the presence of Istio CRDs func (isc *Checker) IsIstioActive(ctx context.Context) bool { - var crdList apiextensionsv1.CustomResourceDefinitionList - if err := isc.client.List(ctx, &crdList); err != nil { - logf.FromContext(ctx).Error(err, "Unable to list CRDs to check Istio status") - return false + + groupList, err := isc.discovery.ServerGroups() + if err != nil { + logf.FromContext(ctx).Error(err, "error getting group list from server") + } + + for _, group := range groupList.Groups { + if strings.Contains(group.Name, ".istio.io") { + return true + } } + return false - return slices.ContainsFunc(crdList.Items, func(crd apiextensionsv1.CustomResourceDefinition) bool { - return strings.EqualFold(crd.GetName(), peerAuthenticationIstioCRD) - }) } diff --git a/internal/istiostatus/istio_status_checker_test.go b/internal/istiostatus/istio_status_checker_test.go index eaabbebd7..bf6d2552b 100644 --- a/internal/istiostatus/istio_status_checker_test.go +++ b/internal/istiostatus/istio_status_checker_test.go @@ -7,48 +7,53 @@ import ( "github.com/stretchr/testify/assert" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/discovery/fake" clientgoscheme "k8s.io/client-go/kubernetes/scheme" - "sigs.k8s.io/controller-runtime/pkg/client/fake" + clienttesting "k8s.io/client-go/testing" ) func TestIsIstioActive(t *testing.T) { scheme := clientgoscheme.Scheme - _ = apiextensionsv1.AddToScheme(scheme) - + err := apiextensionsv1.AddToScheme(scheme) + if err != nil { + t.Fatalf("failed to add api extensions v1 scheme: %v", err) + } tests := []struct { - name string - crds []*apiextensionsv1.CustomResourceDefinition - want bool + name string + resources []*metav1.APIResourceList + want bool }{ { name: "should return true if peerauthentication crd found", - crds: []*apiextensionsv1.CustomResourceDefinition{ + resources: []*metav1.APIResourceList{ { - ObjectMeta: metav1.ObjectMeta{ - Name: "peerauthentications.security.istio.io", - }, + GroupVersion: "peerauthentication.security.istio.io/v1beta1", + APIResources: []metav1.APIResource{}, }, }, want: true, }, { name: "should return false if peerauthentication not crd found", - crds: []*apiextensionsv1.CustomResourceDefinition{}, + resources: []*metav1.APIResourceList{ + { + GroupVersion: "operator.kyma-project.io/v1beta1", + APIResources: []metav1.APIResource{}, + }, + }, want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - fakeClientBuilder := fake.NewClientBuilder().WithScheme(scheme) - for _, crd := range tt.crds { - fakeClientBuilder.WithObjects(crd) + discovery := fake.FakeDiscovery{ + Fake: &clienttesting.Fake{ + Resources: tt.resources, + }, } - fakeClient := fakeClientBuilder.Build() - - isc := &Checker{client: fakeClient} - - got := isc.IsIstioActive(context.Background()) + checker := NewChecker(&discovery) + got := checker.IsIstioActive(context.Background()) assert.Equal(t, tt.want, got) }) diff --git a/internal/reconciler/logpipeline/reconciler.go b/internal/reconciler/logpipeline/reconciler.go index 4ffc5f901..04350043c 100644 --- a/internal/reconciler/logpipeline/reconciler.go +++ b/internal/reconciler/logpipeline/reconciler.go @@ -27,6 +27,7 @@ import ( rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -56,6 +57,7 @@ type Config struct { PipelineDefaults builder.PipelineDefaults Overrides overrides.Config DaemonSetConfig fluentbit.DaemonSetConfig + RestConfig rest.Config } type DaemonSetAnnotator interface { diff --git a/main.go b/main.go index 2bdc3a35b..4efefbc00 100644 --- a/main.go +++ b/main.go @@ -440,6 +440,7 @@ func enableLoggingController(mgr manager.Manager, reconcileTriggerChan <-chan ev PriorityClassName: fluentBitPriorityClassName, SelfMonitorName: selfMonitorName, TelemetryNamespace: telemetryNamespace, + RestConfig: mgr.GetConfig(), }, ) if err != nil { @@ -491,6 +492,7 @@ func enableTracingController(mgr manager.Manager, reconcileTriggerChan <-chan ev }, MaxPipelines: maxTracePipelines, }, + RestConfig: mgr.GetConfig(), TelemetryNamespace: telemetryNamespace, SelfMonitorName: selfMonitorName, }, @@ -550,6 +552,7 @@ func enableMetricsController(mgr manager.Manager, reconcileTriggerChan <-chan ev ModuleVersion: version, KymaInputAllowed: kymaInputAllowed, }, + RestConfig: mgr.GetConfig(), TelemetryNamespace: telemetryNamespace, SelfMonitorName: selfMonitorName, },