@@ -40,7 +40,6 @@ import (
4040)
4141
4242type Config struct {
43- enableLearning bool
4443 learningNamespaceSelector string
4544 nriSocketPath string
4645 nriPluginIdx string
@@ -56,6 +55,10 @@ type Config struct {
5655 violationLogger otellog.Logger
5756}
5857
58+ func (c Config ) learningEnabled () bool {
59+ return strings .TrimSpace (c .learningNamespaceSelector ) != ""
60+ }
61+
5962func newControllerManager (config Config ) (manager.Manager , error ) {
6063 scheme := runtime .NewScheme ()
6164 utilruntime .Must (clientgoscheme .AddToScheme (scheme ))
@@ -165,31 +168,27 @@ func setupLearningReconciler(
165168 config Config ,
166169 ctrlMgr manager.Manager ,
167170) (func (eventscraper.KubeProcessInfo ), error ) {
168- if ! config .enableLearning {
171+ if ! config .learningEnabled () {
169172 logger .InfoContext (ctx , "learning mode is disabled" )
170173 return func (_ eventscraper.KubeProcessInfo ) {
171174 panic ("enqueue function should be never called when learning is disabled" )
172175 }, nil
173176 }
174177
175178 var nsSelector labels.Selector
176- // If the learning namespace selector is empty, the learning will apply to all namespaces.
177- // Otherwise, we parse the learning namespace selector.
178- if config .learningNamespaceSelector != "" {
179- selector , err := parseLearningNamespaceSelector (config .learningNamespaceSelector )
180- if err != nil {
181- return nil , fmt .Errorf ("invalid learning-namespace-selector %q: %w" , config .learningNamespaceSelector , err )
182- }
183- nsSelector = selector
179+ selector , err := parseLearningNamespaceSelector (config .learningNamespaceSelector )
180+ if err != nil {
181+ return nil , fmt .Errorf ("invalid learning-namespace-selector %q: %w" , config .learningNamespaceSelector , err )
184182 }
183+ nsSelector = selector
185184
186185 // Wait until mutating admission webhook is ready.
187- if err : = waitForMutatingAdmissionWebhook (ctx ); err != nil {
186+ if err = waitForMutatingAdmissionWebhook (ctx ); err != nil {
188187 return nil , err
189188 }
190189
191190 learningReconciler := eventhandler .NewLearningReconciler (ctrlMgr .GetClient (), nsSelector )
192- if err : = learningReconciler .SetupWithManager (ctrlMgr ); err != nil {
191+ if err = learningReconciler .SetupWithManager (ctrlMgr ); err != nil {
193192 return nil , fmt .Errorf ("unable to create learning reconciler: %w" , err )
194193 }
195194 logger .InfoContext (ctx , "learning mode is enabled" , "namespaceSelector" , config .learningNamespaceSelector )
@@ -210,7 +209,7 @@ func startAgent(ctx context.Context, logger *slog.Logger, config Config) error {
210209 //////////////////////
211210 // Create BPF manager
212211 //////////////////////
213- bpfManager , err := bpf .NewManager (logger , config .enableLearning )
212+ bpfManager , err := bpf .NewManager (logger , config .learningEnabled () )
214213 if err != nil {
215214 return fmt .Errorf ("cannot create BPF manager: %w" , err )
216215 }
@@ -320,29 +319,36 @@ func parseLogLevel(level string) slog.Level {
320319 }
321320}
322321
323- // parseLearningNamespaceSelector parses the learning namespace selector from either:
324- // - A JSON object (e.g. {"matchLabels":{"env":"prod"}}.
325- // - A string in Kubernetes label selector format (e.g. "env=prod").
322+ // parseLearningNamespaceSelector parses the learning namespace selector from a JSON object (e.g. {"matchLabels":{"env":"prod"}}).
326323func parseLearningNamespaceSelector (s string ) (labels.Selector , error ) {
327324 s = strings .TrimSpace (s )
328- if strings .HasPrefix (s , "{" ) {
329- var ls metav1.LabelSelector
330- if err := json .Unmarshal ([]byte (s ), & ls ); err != nil {
331- return nil , fmt .Errorf ("invalid JSON label selector %q: %w" , s , err )
332- }
333- return metav1 .LabelSelectorAsSelector (& ls )
325+ if ! strings .HasPrefix (s , "{" ) {
326+ return nil , fmt .Errorf ("invalid JSON label selector %q: must be a JSON object" , s )
327+ }
328+
329+ var ls metav1.LabelSelector
330+ if err := json .Unmarshal ([]byte (s ), & ls ); err != nil {
331+ return nil , fmt .Errorf ("invalid JSON label selector %q: %w" , s , err )
332+ }
333+ selector , err := metav1 .LabelSelectorAsSelector (& ls )
334+ if err != nil {
335+ return nil , err
336+ }
337+
338+ if selector .Empty () {
339+ return nil , fmt .Errorf ("invalid JSON label selector %q: must not be empty if learning is enabled" , s )
334340 }
335- return labels . Parse ( s )
341+ return selector , nil
336342}
337343
338344func parseFlags () Config {
339345 var config Config
340- flag . BoolVar ( & config . enableLearning , "enable-learning " , false , "Enable learning mode" )
346+ // If we receive something different from " ", it should be a valid json
341347 flag .StringVar (
342348 & config .learningNamespaceSelector ,
343349 "learning-namespace-selector" ,
344350 "" ,
345- "Label selector for namespaces to include in learning (empty = all) " ,
351+ "Namespace selector for learning. Accepts a JSON LabelSelector " ,
346352 )
347353 flag .StringVar (& config .nriSocketPath , "nri-socket-path" , "/var/run/nri/nri.sock" , "NRI socket path" )
348354 flag .StringVar (& config .nriPluginIdx , "nri-plugin-index" , "00" , "NRI plugin index" )
0 commit comments