@@ -12,6 +12,7 @@ import (
1212 "github.com/zalando/postgres-operator/pkg/util/config"
1313 "github.com/zalando/postgres-operator/pkg/util/k8sutil"
1414 appsv1 "k8s.io/api/apps/v1"
15+ batchv1 "k8s.io/api/batch/v1"
1516 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1617 "k8s.io/apimachinery/pkg/runtime"
1718 "k8s.io/client-go/kubernetes/fake"
@@ -1232,4 +1233,194 @@ func TestManageHibernateState_StateTransitionSequence(t *testing.T) {
12321233 assert .True (t , continueSync )
12331234 assert .Equal (t , int32 (3 ), newSpec .Spec .NumberOfInstances )
12341235 })
1236+ }
1237+
1238+ func TestSuspendLogicalBackupJob (t * testing.T ) {
1239+ tests := []struct {
1240+ name string
1241+ jobExists bool
1242+ patchFails bool
1243+ wantErr bool
1244+ }{
1245+ {
1246+ name : "job exists, suspend succeeds" ,
1247+ jobExists : true ,
1248+ wantErr : false ,
1249+ },
1250+ {
1251+ name : "job does not exist - no-op" ,
1252+ jobExists : false ,
1253+ wantErr : false ,
1254+ },
1255+ {
1256+ name : "job exists but patch fails" ,
1257+ jobExists : true ,
1258+ patchFails : true ,
1259+ wantErr : true ,
1260+ },
1261+ }
1262+
1263+ for _ , tt := range tests {
1264+ t .Run (tt .name , func (t * testing.T ) {
1265+ clientSet := fake .NewSimpleClientset ()
1266+ jobName := "logical-backup-test-cluster"
1267+
1268+ if tt .jobExists {
1269+ clientSet .BatchV1 ().CronJobs ("default" ).Create (context .TODO (), & batchv1.CronJob {
1270+ ObjectMeta : metav1.ObjectMeta {
1271+ Name : jobName ,
1272+ Namespace : "default" ,
1273+ },
1274+ Spec : batchv1.CronJobSpec {
1275+ Schedule : "30 00 * * *" ,
1276+ },
1277+ }, metav1.CreateOptions {})
1278+ }
1279+
1280+ if tt .patchFails {
1281+ clientSet .PrependReactor ("patch" , "cronjobs" , func (action k8stesting.Action ) (bool , runtime.Object , error ) {
1282+ return true , nil , fmt .Errorf ("network error" )
1283+ })
1284+ }
1285+
1286+ kubeClient := & k8sutil.KubernetesClient {
1287+ CronJobsGetter : clientSet .BatchV1 (),
1288+ }
1289+
1290+ var job * batchv1.CronJob
1291+ if tt .jobExists {
1292+ job , _ = kubeClient .CronJobs ("default" ).Get (context .TODO (), jobName , metav1.GetOptions {})
1293+ }
1294+
1295+ c := New (
1296+ Config {
1297+ OpConfig : config.Config {
1298+ LogicalBackup : config.LogicalBackup {
1299+ LogicalBackupJobPrefix : "logical-backup-" ,
1300+ },
1301+ },
1302+ },
1303+ * kubeClient ,
1304+ acidv1.Postgresql {
1305+ ObjectMeta : metav1.ObjectMeta {
1306+ Name : "test-cluster" ,
1307+ Namespace : "default" ,
1308+ },
1309+ },
1310+ lifecycleLogger ,
1311+ lifecycleEventRecorder ,
1312+ )
1313+ c .LogicalBackupJob = job
1314+
1315+ err := c .suspendLogicalBackupJob ()
1316+
1317+ if tt .wantErr {
1318+ assert .Error (t , err )
1319+ } else {
1320+ assert .NoError (t , err )
1321+ if tt .jobExists && ! tt .patchFails {
1322+ updatedJob , _ := kubeClient .CronJobs ("default" ).Get (context .TODO (), jobName , metav1.GetOptions {})
1323+ if updatedJob != nil {
1324+ assert .True (t , * updatedJob .Spec .Suspend , "job should be suspended" )
1325+ }
1326+ }
1327+ }
1328+ })
1329+ }
1330+ }
1331+
1332+ func TestUnsuspendLogicalBackupJob (t * testing.T ) {
1333+ tests := []struct {
1334+ name string
1335+ jobExists bool
1336+ patchFails bool
1337+ wantErr bool
1338+ }{
1339+ {
1340+ name : "job exists, unsuspend succeeds" ,
1341+ jobExists : true ,
1342+ wantErr : false ,
1343+ },
1344+ {
1345+ name : "job does not exist - no-op" ,
1346+ jobExists : false ,
1347+ wantErr : false ,
1348+ },
1349+ {
1350+ name : "job exists but patch fails" ,
1351+ jobExists : true ,
1352+ patchFails : true ,
1353+ wantErr : true ,
1354+ },
1355+ }
1356+
1357+ for _ , tt := range tests {
1358+ t .Run (tt .name , func (t * testing.T ) {
1359+ clientSet := fake .NewSimpleClientset ()
1360+ jobName := "logical-backup-test-cluster"
1361+
1362+ if tt .jobExists {
1363+ suspendTrue := true
1364+ clientSet .BatchV1 ().CronJobs ("default" ).Create (context .TODO (), & batchv1.CronJob {
1365+ ObjectMeta : metav1.ObjectMeta {
1366+ Name : jobName ,
1367+ Namespace : "default" ,
1368+ },
1369+ Spec : batchv1.CronJobSpec {
1370+ Schedule : "30 00 * * *" ,
1371+ Suspend : & suspendTrue ,
1372+ },
1373+ }, metav1.CreateOptions {})
1374+ }
1375+
1376+ if tt .patchFails {
1377+ clientSet .PrependReactor ("patch" , "cronjobs" , func (action k8stesting.Action ) (bool , runtime.Object , error ) {
1378+ return true , nil , fmt .Errorf ("network error" )
1379+ })
1380+ }
1381+
1382+ kubeClient := & k8sutil.KubernetesClient {
1383+ CronJobsGetter : clientSet .BatchV1 (),
1384+ }
1385+
1386+ var job * batchv1.CronJob
1387+ if tt .jobExists {
1388+ job , _ = kubeClient .CronJobs ("default" ).Get (context .TODO (), jobName , metav1.GetOptions {})
1389+ }
1390+
1391+ c := New (
1392+ Config {
1393+ OpConfig : config.Config {
1394+ LogicalBackup : config.LogicalBackup {
1395+ LogicalBackupJobPrefix : "logical-backup-" ,
1396+ },
1397+ },
1398+ },
1399+ * kubeClient ,
1400+ acidv1.Postgresql {
1401+ ObjectMeta : metav1.ObjectMeta {
1402+ Name : "test-cluster" ,
1403+ Namespace : "default" ,
1404+ },
1405+ },
1406+ lifecycleLogger ,
1407+ lifecycleEventRecorder ,
1408+ )
1409+ c .LogicalBackupJob = job
1410+
1411+ err := c .unsuspendLogicalBackupJob ()
1412+
1413+ if tt .wantErr {
1414+ assert .Error (t , err )
1415+ } else {
1416+ assert .NoError (t , err )
1417+ if tt .jobExists && ! tt .patchFails {
1418+ updatedJob , _ := kubeClient .CronJobs ("default" ).Get (context .TODO (), jobName , metav1.GetOptions {})
1419+ if updatedJob != nil {
1420+ assert .False (t , * updatedJob .Spec .Suspend , "job should be unsuspended" )
1421+ }
1422+ }
1423+ }
1424+ })
1425+ }
12351426}
0 commit comments