@@ -2447,6 +2447,62 @@ func TestDPAReconciler_ValidateDataProtectionCR(t *testing.T) {
24472447 },
24482448 wantErr : false ,
24492449 },
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+ },
24502506 }
24512507 for _ , tt := range tests {
24522508 tt .objects = append (tt .objects , tt .dpa )
@@ -2483,3 +2539,220 @@ func TestDPAReconciler_ValidateDataProtectionCR(t *testing.T) {
24832539 })
24842540 }
24852541}
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