@@ -2447,6 +2447,62 @@ func TestDPAReconciler_ValidateDataProtectionCR(t *testing.T) {
2447
2447
},
2448
2448
wantErr : false ,
2449
2449
},
2450
+ {
2451
+ name : "[valid] DPA CR with deprecated PodAnnotations should pass validation but log warning" ,
2452
+ dpa : & oadpv1alpha1.DataProtectionApplication {
2453
+ ObjectMeta : metav1.ObjectMeta {
2454
+ Name : "test-DPA-CR" ,
2455
+ Namespace : "test-ns" ,
2456
+ },
2457
+ Spec : oadpv1alpha1.DataProtectionApplicationSpec {
2458
+ PodAnnotations : map [string ]string {
2459
+ "deprecated.annotation" : "value" ,
2460
+ },
2461
+ BackupLocations : []oadpv1alpha1.BackupLocation {
2462
+ {
2463
+ Velero : & velerov1.BackupStorageLocationSpec {
2464
+ Provider : "aws" ,
2465
+ StorageType : velerov1.StorageType {
2466
+ ObjectStorage : & velerov1.ObjectStorageLocation {
2467
+ Bucket : "bucket" ,
2468
+ },
2469
+ },
2470
+ Config : map [string ]string {
2471
+ "region" : "us-east-1" ,
2472
+ },
2473
+ Credential : & corev1.SecretKeySelector {
2474
+ LocalObjectReference : corev1.LocalObjectReference {
2475
+ Name : "cloud-credentials" ,
2476
+ },
2477
+ Key : "credentials" ,
2478
+ },
2479
+ Default : true ,
2480
+ },
2481
+ },
2482
+ },
2483
+ Configuration : & oadpv1alpha1.ApplicationConfig {
2484
+ Velero : & oadpv1alpha1.VeleroConfig {
2485
+ DefaultPlugins : []oadpv1alpha1.DefaultPlugin {
2486
+ oadpv1alpha1 .DefaultPluginAWS ,
2487
+ },
2488
+ },
2489
+ },
2490
+ BackupImages : ptr .To (false ),
2491
+ },
2492
+ },
2493
+ objects : []client.Object {
2494
+ & corev1.Secret {
2495
+ ObjectMeta : metav1.ObjectMeta {
2496
+ Name : "cloud-credentials" ,
2497
+ Namespace : "test-ns" ,
2498
+ },
2499
+ Data : map [string ][]byte {
2500
+ "credentials" : []byte ("fake-creds" ),
2501
+ },
2502
+ },
2503
+ },
2504
+ wantErr : false ,
2505
+ },
2450
2506
}
2451
2507
for _ , tt := range tests {
2452
2508
tt .objects = append (tt .objects , tt .dpa )
@@ -2483,3 +2539,220 @@ func TestDPAReconciler_ValidateDataProtectionCR(t *testing.T) {
2483
2539
})
2484
2540
}
2485
2541
}
2542
+
2543
+ func TestDPAReconciler_ValidateDataProtectionCR_PodAnnotationsDeprecationWarning (t * testing.T ) {
2544
+ // Create a test logger that captures log messages
2545
+ var logOutput []string
2546
+ testLogger := logr .New (& testLogSink {logs : & logOutput })
2547
+
2548
+ // DPA with deprecated PodAnnotations field
2549
+ dpa := & oadpv1alpha1.DataProtectionApplication {
2550
+ ObjectMeta : metav1.ObjectMeta {
2551
+ Name : "test-DPA-CR" ,
2552
+ Namespace : "test-ns" ,
2553
+ },
2554
+ Spec : oadpv1alpha1.DataProtectionApplicationSpec {
2555
+ PodAnnotations : map [string ]string {
2556
+ "deprecated.annotation" : "value" ,
2557
+ },
2558
+ BackupLocations : []oadpv1alpha1.BackupLocation {
2559
+ {
2560
+ Velero : & velerov1.BackupStorageLocationSpec {
2561
+ Provider : "aws" ,
2562
+ StorageType : velerov1.StorageType {
2563
+ ObjectStorage : & velerov1.ObjectStorageLocation {
2564
+ Bucket : "bucket" ,
2565
+ },
2566
+ },
2567
+ Config : map [string ]string {
2568
+ "region" : "us-east-1" ,
2569
+ },
2570
+ Credential : & corev1.SecretKeySelector {
2571
+ LocalObjectReference : corev1.LocalObjectReference {
2572
+ Name : "cloud-credentials" ,
2573
+ },
2574
+ Key : "credentials" ,
2575
+ },
2576
+ Default : true ,
2577
+ },
2578
+ },
2579
+ },
2580
+ Configuration : & oadpv1alpha1.ApplicationConfig {
2581
+ Velero : & oadpv1alpha1.VeleroConfig {
2582
+ DefaultPlugins : []oadpv1alpha1.DefaultPlugin {
2583
+ oadpv1alpha1 .DefaultPluginAWS ,
2584
+ },
2585
+ },
2586
+ },
2587
+ BackupImages : ptr .To (false ),
2588
+ },
2589
+ }
2590
+
2591
+ // Add required secret for AWS plugin validation
2592
+ cloudCredentialsSecret := & corev1.Secret {
2593
+ ObjectMeta : metav1.ObjectMeta {
2594
+ Name : "cloud-credentials" ,
2595
+ Namespace : "test-ns" ,
2596
+ },
2597
+ Data : map [string ][]byte {
2598
+ "credentials" : []byte ("fake-creds" ),
2599
+ },
2600
+ }
2601
+
2602
+ objects := []client.Object {dpa , cloudCredentialsSecret }
2603
+ fakeClient , err := getFakeClientFromObjects (objects ... )
2604
+ if err != nil {
2605
+ t .Errorf ("error in creating fake client: %v" , err )
2606
+ return
2607
+ }
2608
+
2609
+ r := & DataProtectionApplicationReconciler {
2610
+ Client : fakeClient ,
2611
+ ClusterWideClient : fakeClient ,
2612
+ Scheme : fakeClient .Scheme (),
2613
+ Log : testLogger ,
2614
+ Context : newContextForTest (),
2615
+ NamespacedName : types.NamespacedName {
2616
+ Namespace : dpa .Namespace ,
2617
+ Name : dpa .Name ,
2618
+ },
2619
+ dpa : dpa ,
2620
+ EventRecorder : record .NewFakeRecorder (10 ),
2621
+ }
2622
+
2623
+ // Run validation
2624
+ valid , err := r .ValidateDataProtectionCR (testLogger )
2625
+ if err != nil {
2626
+ t .Errorf ("ValidateDataProtectionCR() unexpected error = %v" , err )
2627
+ return
2628
+ }
2629
+ if ! valid {
2630
+ t .Errorf ("ValidateDataProtectionCR() = %v, want true" , valid )
2631
+ return
2632
+ }
2633
+
2634
+ // Check that deprecation warning was logged
2635
+ found := false
2636
+ for _ , log := range logOutput {
2637
+ if log == "(Deprecation Warning) The 'podAnnotations' field is deprecated. Please migrate to 'configuration.velero.podConfig.annotations' for Velero pods and 'configuration.nodeAgent.podConfig.annotations' for NodeAgent pods." {
2638
+ found = true
2639
+ break
2640
+ }
2641
+ }
2642
+ if ! found {
2643
+ t .Errorf ("Expected deprecation warning was not logged. Logs: %v" , logOutput )
2644
+ }
2645
+ }
2646
+
2647
+ // Test DPA without PodAnnotations should not log warning
2648
+ func TestDPAReconciler_ValidateDataProtectionCR_NoPodAnnotationsNoWarning (t * testing.T ) {
2649
+ // Create a test logger that captures log messages
2650
+ var logOutput []string
2651
+ testLogger := logr .New (& testLogSink {logs : & logOutput })
2652
+
2653
+ // DPA without deprecated PodAnnotations field
2654
+ dpa := & oadpv1alpha1.DataProtectionApplication {
2655
+ ObjectMeta : metav1.ObjectMeta {
2656
+ Name : "test-DPA-CR" ,
2657
+ Namespace : "test-ns" ,
2658
+ },
2659
+ Spec : oadpv1alpha1.DataProtectionApplicationSpec {
2660
+ BackupLocations : []oadpv1alpha1.BackupLocation {
2661
+ {
2662
+ Velero : & velerov1.BackupStorageLocationSpec {
2663
+ Provider : "aws" ,
2664
+ StorageType : velerov1.StorageType {
2665
+ ObjectStorage : & velerov1.ObjectStorageLocation {
2666
+ Bucket : "bucket" ,
2667
+ },
2668
+ },
2669
+ Config : map [string ]string {
2670
+ "region" : "us-east-1" ,
2671
+ },
2672
+ Credential : & corev1.SecretKeySelector {
2673
+ LocalObjectReference : corev1.LocalObjectReference {
2674
+ Name : "cloud-credentials" ,
2675
+ },
2676
+ Key : "credentials" ,
2677
+ },
2678
+ Default : true ,
2679
+ },
2680
+ },
2681
+ },
2682
+ Configuration : & oadpv1alpha1.ApplicationConfig {
2683
+ Velero : & oadpv1alpha1.VeleroConfig {
2684
+ DefaultPlugins : []oadpv1alpha1.DefaultPlugin {
2685
+ oadpv1alpha1 .DefaultPluginAWS ,
2686
+ },
2687
+ },
2688
+ },
2689
+ BackupImages : ptr .To (false ),
2690
+ },
2691
+ }
2692
+
2693
+ // Add required secret for AWS plugin validation
2694
+ cloudCredentialsSecret := & corev1.Secret {
2695
+ ObjectMeta : metav1.ObjectMeta {
2696
+ Name : "cloud-credentials" ,
2697
+ Namespace : "test-ns" ,
2698
+ },
2699
+ Data : map [string ][]byte {
2700
+ "credentials" : []byte ("fake-creds" ),
2701
+ },
2702
+ }
2703
+
2704
+ objects := []client.Object {dpa , cloudCredentialsSecret }
2705
+ fakeClient , err := getFakeClientFromObjects (objects ... )
2706
+ if err != nil {
2707
+ t .Errorf ("error in creating fake client: %v" , err )
2708
+ return
2709
+ }
2710
+
2711
+ r := & DataProtectionApplicationReconciler {
2712
+ Client : fakeClient ,
2713
+ ClusterWideClient : fakeClient ,
2714
+ Scheme : fakeClient .Scheme (),
2715
+ Log : testLogger ,
2716
+ Context : newContextForTest (),
2717
+ NamespacedName : types.NamespacedName {
2718
+ Namespace : dpa .Namespace ,
2719
+ Name : dpa .Name ,
2720
+ },
2721
+ dpa : dpa ,
2722
+ EventRecorder : record .NewFakeRecorder (10 ),
2723
+ }
2724
+
2725
+ // Run validation
2726
+ valid , err := r .ValidateDataProtectionCR (testLogger )
2727
+ if err != nil {
2728
+ t .Errorf ("ValidateDataProtectionCR() unexpected error = %v" , err )
2729
+ return
2730
+ }
2731
+ if ! valid {
2732
+ t .Errorf ("ValidateDataProtectionCR() = %v, want true" , valid )
2733
+ return
2734
+ }
2735
+
2736
+ // Check that deprecation warning was NOT logged
2737
+ for _ , log := range logOutput {
2738
+ if log == "(Deprecation Warning) The 'podAnnotations' field is deprecated. Please migrate to 'configuration.velero.podConfig.annotations' for Velero pods and 'configuration.nodeAgent.podConfig.annotations' for NodeAgent pods." {
2739
+ t .Errorf ("Deprecation warning should not be logged when PodAnnotations is not used. Logs: %v" , logOutput )
2740
+ }
2741
+ }
2742
+ }
2743
+
2744
+ // testLogSink implements logr.LogSink for testing
2745
+ type testLogSink struct {
2746
+ logs * []string
2747
+ }
2748
+
2749
+ func (t * testLogSink ) Init (info logr.RuntimeInfo ) {}
2750
+ func (t * testLogSink ) Enabled (level int ) bool { return true }
2751
+ func (t * testLogSink ) Info (level int , msg string , keysAndValues ... interface {}) {
2752
+ * t .logs = append (* t .logs , msg )
2753
+ }
2754
+ func (t * testLogSink ) Error (err error , msg string , keysAndValues ... interface {}) {
2755
+ * t .logs = append (* t .logs , msg )
2756
+ }
2757
+ func (t * testLogSink ) WithValues (keysAndValues ... interface {}) logr.LogSink { return t }
2758
+ func (t * testLogSink ) WithName (name string ) logr.LogSink { return t }
0 commit comments