@@ -30,8 +30,10 @@ import (
3030 "k8s.io/apimachinery/pkg/types"
3131 "k8s.io/client-go/dynamic"
3232 dynfake "k8s.io/client-go/dynamic/fake"
33+ "k8s.io/client-go/kubernetes"
3334 clientsetfake "k8s.io/client-go/kubernetes/fake"
3435 "k8s.io/client-go/kubernetes/scheme"
36+ "k8s.io/client-go/tools/clientcmd"
3537 "k8s.io/client-go/tools/record"
3638 klog "k8s.io/klog/v2"
3739 parentpolicyv1 "open-cluster-management.io/governance-policy-propagator/api/v1"
@@ -57,11 +59,6 @@ func (d *DryRunner) dryRun(cmd *cobra.Command, args []string) error {
5759 return fmt .Errorf ("unable to read input policy: %w" , err )
5860 }
5961
60- inputObjects , err := d .readInputResources (cmd , args )
61- if err != nil {
62- return fmt .Errorf ("unable to read input resources: %w" , err )
63- }
64-
6562 if err := d .setupLogs (); err != nil {
6663 return fmt .Errorf ("unable to setup the logging configuration: %w" , err )
6764 }
@@ -74,9 +71,16 @@ func (d *DryRunner) dryRun(cmd *cobra.Command, args []string) error {
7471 return fmt .Errorf ("unable to setup the dryrun reconciler: %w" , err )
7572 }
7673
77- err = d .applyInputResources (ctx , rec , inputObjects )
78- if err != nil {
79- return fmt .Errorf ("unable to apply input resources: %w" , err )
74+ if ! d .fromCluster {
75+ inputObjects , err := d .readInputResources (cmd , args )
76+ if err != nil {
77+ return fmt .Errorf ("unable to read input resources: %w" , err )
78+ }
79+
80+ err = d .applyInputResources (ctx , rec , inputObjects )
81+ if err != nil {
82+ return fmt .Errorf ("unable to apply input resources: %w" , err )
83+ }
8084 }
8185
8286 cfgPolicyNN := types.NamespacedName {
@@ -332,10 +336,12 @@ func (d *DryRunner) readInputResources(cmd *cobra.Command, args []string) (
332336 return rawInputs , nil
333337}
334338
339+ // applyInputResources applies the user's resources to the fake cluster
335340func (d * DryRunner ) applyInputResources (
336- ctx context.Context , rec * ctrl.ConfigurationPolicyReconciler , inputObjects []* unstructured.Unstructured ,
341+ ctx context.Context ,
342+ rec * ctrl.ConfigurationPolicyReconciler ,
343+ inputObjects []* unstructured.Unstructured ,
337344) error {
338- // Apply the user's resources to the fake cluster
339345 for _ , obj := range inputObjects {
340346 gvk := obj .GroupVersionKind ()
341347
@@ -346,7 +352,7 @@ func (d *DryRunner) applyInputResources(
346352 "entry in the mappings file" , err , gvk .Kind )
347353 }
348354
349- return fmt . Errorf ( "unable to apply an input resource: %w" , err )
355+ return err
350356 }
351357
352358 var resInt dynamic.ResourceInterface
@@ -365,7 +371,7 @@ func (d *DryRunner) applyInputResources(
365371
366372 if _ , err := resInt .Create (ctx , obj , metav1.CreateOptions {}); err != nil &&
367373 ! k8serrors .IsAlreadyExists (err ) {
368- return fmt . Errorf ( "unable to apply an input resource: %w" , err )
374+ return err
369375 }
370376
371377 // Manually convert resources from the dynamic client to the runtime client
@@ -428,10 +434,34 @@ func (d *DryRunner) setupReconciler(
428434 return nil , err
429435 }
430436
431- dynamicClient := dynfake .NewSimpleDynamicClient (scheme .Scheme )
432- clientset := clientsetfake .NewSimpleClientset ()
433- watcherReconciler , _ := depclient .NewControllerRuntimeSource ()
437+ runtimeClient := clientfake .NewClientBuilder ().
438+ WithScheme (scheme .Scheme ).
439+ WithObjects (configPolCRD , cfgPolicy ).
440+ WithStatusSubresource (cfgPolicy ).
441+ Build ()
442+ nsSelUpdatesChan := make (chan event.GenericEvent , 20 )
434443
444+ var clientset kubernetes.Interface
445+ var dynamicClient dynamic.Interface
446+ var nsSelReconciler common.NamespaceSelectorReconciler
447+
448+ if d .fromCluster {
449+ var nsSelClient client.Client
450+ var err error
451+
452+ clientset , dynamicClient , nsSelClient , err = setupClusterClients ()
453+ if err != nil {
454+ return nil , err
455+ }
456+
457+ nsSelReconciler = common .NewNamespaceSelectorReconciler (nsSelClient , nsSelUpdatesChan )
458+ } else {
459+ dynamicClient = dynfake .NewSimpleDynamicClient (scheme .Scheme )
460+ clientset = clientsetfake .NewSimpleClientset ()
461+ nsSelReconciler = common .NewNamespaceSelectorReconciler (runtimeClient , nsSelUpdatesChan )
462+ }
463+
464+ watcherReconciler , _ := depclient .NewControllerRuntimeSource ()
435465 dynamicWatcher := depclient .NewWithClients (
436466 dynamicClient ,
437467 clientset .Discovery (),
@@ -446,14 +476,28 @@ func (d *DryRunner) setupReconciler(
446476 }
447477 }()
448478
449- runtimeClient := clientfake .NewClientBuilder ().
450- WithScheme (scheme .Scheme ).
451- WithObjects (configPolCRD , cfgPolicy ).
452- WithStatusSubresource (cfgPolicy ).
453- Build ()
479+ rec := ctrl.ConfigurationPolicyReconciler {
480+ Client : runtimeClient ,
481+ DecryptionConcurrency : 1 ,
482+ DynamicWatcher : dynamicWatcher ,
483+ Scheme : scheme .Scheme ,
484+ Recorder : record .NewFakeRecorder (8 ),
485+ InstanceName : "policy-cli" ,
486+ TargetK8sClient : clientset ,
487+ TargetK8sDynamicClient : dynamicClient ,
488+ SelectorReconciler : & nsSelReconciler ,
489+ EnableMetrics : false ,
490+ UninstallMode : false ,
491+ EvalBackoffSeconds : 5 ,
492+ FullDiffs : d .fullDiffs ,
493+ }
454494
455- nsSelUpdatesChan := make (chan event.GenericEvent , 20 )
456- nsSelReconciler := common .NewNamespaceSelectorReconciler (runtimeClient , nsSelUpdatesChan )
495+ // wait for dynamic watcher to have started
496+ <- rec .DynamicWatcher .Started ()
497+
498+ if d .fromCluster {
499+ return & rec , nil
500+ }
457501
458502 defaultNs := & unstructured.Unstructured {
459503 Object : map [string ]interface {}{
@@ -478,21 +522,7 @@ func (d *DryRunner) setupReconciler(
478522 return nil , err
479523 }
480524
481- rec := ctrl.ConfigurationPolicyReconciler {
482- Client : runtimeClient ,
483- DecryptionConcurrency : 1 ,
484- DynamicWatcher : dynamicWatcher ,
485- Scheme : scheme .Scheme ,
486- Recorder : record .NewFakeRecorder (8 ),
487- InstanceName : "policy-cli" ,
488- TargetK8sClient : clientset ,
489- TargetK8sDynamicClient : dynamicClient ,
490- SelectorReconciler : & nsSelReconciler ,
491- EnableMetrics : false ,
492- UninstallMode : false ,
493- EvalBackoffSeconds : 5 ,
494- FullDiffs : d .fullDiffs ,
495- }
525+ fakeClientset := clientset .(* clientsetfake.Clientset )
496526
497527 if d .mappingsPath != "" {
498528 mFile , err := os .ReadFile (d .mappingsPath )
@@ -505,19 +535,16 @@ func (d *DryRunner) setupReconciler(
505535 return nil , err
506536 }
507537
508- clientset .Resources = mappings .ResourceLists (apiMappings )
538+ fakeClientset .Resources = mappings .ResourceLists (apiMappings )
509539 } else {
510- clientset .Resources , err = mappings .DefaultResourceLists ()
540+ fakeClientset .Resources , err = mappings .DefaultResourceLists ()
511541 if err != nil {
512542 return nil , err
513543 }
514544 }
515545
516546 // Add open-cluster-management policy CRD
517- addSupportedResources (clientset )
518-
519- // wait for dynamic watcher to have started
520- <- rec .DynamicWatcher .Started ()
547+ addSupportedResources (fakeClientset )
521548
522549 return & rec , nil
523550}
@@ -633,6 +660,40 @@ func sanitizeForCreation(obj *unstructured.Unstructured) {
633660 delete (obj .Object ["metadata" ].(map [string ]interface {}), "uid" )
634661}
635662
663+ func setupClusterClients () (kubernetes.Interface , dynamic.Interface , client.Client , error ) {
664+ loadingRules := clientcmd .NewDefaultClientConfigLoadingRules ()
665+ clientConfig := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (
666+ loadingRules , & clientcmd.ConfigOverrides {},
667+ )
668+
669+ kubeConfig , err := clientConfig .ClientConfig ()
670+ if err != nil {
671+ return nil , nil , nil , err
672+ }
673+
674+ clientset , err := kubernetes .NewForConfig (kubeConfig )
675+ if err != nil {
676+ return nil , nil , nil , err
677+ }
678+
679+ dynamicClient , err := dynamic .NewForConfig (kubeConfig )
680+ if err != nil {
681+ return nil , nil , nil , err
682+ }
683+
684+ readOnlyMode := true // Prevent modifications to the cluster
685+
686+ runtimeClient , err := client .New (kubeConfig , client.Options {
687+ Scheme : scheme .Scheme ,
688+ DryRun : & readOnlyMode ,
689+ })
690+ if err != nil {
691+ return nil , nil , nil , err
692+ }
693+
694+ return clientset , dynamicClient , runtimeClient , nil
695+ }
696+
636697func addSupportedResources (clientset * clientsetfake.Clientset ) {
637698 clientset .Resources = append (clientset .Resources , & metav1.APIResourceList {
638699 GroupVersion : parentpolicyv1 .GroupVersion .String (),
0 commit comments