11package e2e
22
33import (
4+ "bufio"
45 "bytes"
56 "context"
7+ "encoding/json"
68 "fmt"
79 "html/template"
810 "os"
911 "os/exec"
1012 "path/filepath"
13+ "regexp"
1114 "time"
1215
1316 finv1 "github.com/cybozu-go/fin/api/v1"
17+ "github.com/cybozu-go/fin/internal/model"
1418 "github.com/cybozu-go/fin/test/utils"
1519 . "github.com/onsi/ginkgo/v2"
1620 . "github.com/onsi/gomega"
@@ -26,6 +30,7 @@ import (
2630)
2731
2832const (
33+ finDeploymentName = "fin-controller-manager"
2934 rookNamespace = "rook-ceph"
3035 rookStorageClass = "rook-ceph-block"
3136 poolName = "rook-ceph-block-pool"
@@ -80,7 +85,7 @@ func checkDeploymentReady(namespace, name string) error {
8085func waitEnvironment () {
8186 It ("wait for fin-controller to be ready" , func () {
8287 Eventually (func () error {
83- return checkDeploymentReady (rookNamespace , "fin-controller-manager" )
88+ return checkDeploymentReady (rookNamespace , finDeploymentName )
8489 }).Should (Succeed ())
8590 })
8691}
@@ -455,6 +460,58 @@ func WaitForPVCDeletion(ctx context.Context, k8sClient kubernetes.Interface, pvc
455460 })
456461}
457462
463+ // WaitControllerLog waits until the controller log matches the given pattern or the duration is exceeded.
464+ func WaitControllerLog (ctx SpecContext , pattern string , duration time.Duration ) error {
465+ GinkgoHelper ()
466+
467+ timeoutCtx , cancel := context .WithTimeout (ctx , duration )
468+ defer cancel ()
469+
470+ matcher := regexp .MustCompile (pattern )
471+
472+ command := exec .CommandContext (timeoutCtx , "kubectl" , "logs" , "-n" , rookNamespace , "deployment/" + finDeploymentName , "-f" )
473+ stdoutPipe , err := command .StdoutPipe ()
474+ if err != nil {
475+ panic (err )
476+ }
477+ err = command .Start ()
478+ if err != nil {
479+ panic (err )
480+ }
481+ defer func () {
482+ _ = command .Process .Kill ()
483+ _ = command .Wait ()
484+ }()
485+
486+ // read stdout line by line until the pattern is found
487+ scanner := bufio .NewScanner (stdoutPipe )
488+ found := make (chan struct {})
489+ go func () {
490+ for scanner .Scan () {
491+ select {
492+ case <- timeoutCtx .Done ():
493+ return
494+ default :
495+ }
496+ line := scanner .Text ()
497+ if matcher .MatchString (line ) {
498+ close (found )
499+ return
500+ }
501+ }
502+ if scanner .Err () != nil {
503+ panic (scanner .Err ())
504+ }
505+ }()
506+
507+ select {
508+ case <- timeoutCtx .Done ():
509+ return timeoutCtx .Err ()
510+ case <- found :
511+ return nil
512+ }
513+ }
514+
458515func VerifySizeOfRestorePVC (ctx context.Context , c client.Client , restore * finv1.FinRestore ) {
459516 GinkgoHelper ()
460517
@@ -679,6 +736,30 @@ func GetNodeNames(ctx context.Context, k8sClient kubernetes.Interface) ([]string
679736 return nodeNames , nil
680737}
681738
739+ func GetPvByPvc (ctx context.Context , k8sClient kubernetes.Interface , pvc * corev1.PersistentVolumeClaim ) (* corev1.PersistentVolume , error ) {
740+ GinkgoHelper ()
741+
742+ return k8sClient .CoreV1 ().PersistentVolumes ().Get (ctx , pvc .Spec .VolumeName , metav1.GetOptions {})
743+ }
744+
745+ func ListRBDSnapshots (ctx context.Context , poolName , imageName string ) ([]* model.RBDSnapshot , error ) {
746+ GinkgoHelper ()
747+
748+ stdout , stderr , err := kubectl ("exec" , "-n" , rookNamespace , "deploy/rook-ceph-tools" , "--" ,
749+ "rbd" , "snap" , "ls" , "-p" , poolName , imageName , "--format" , "json" )
750+ if err != nil {
751+ return nil , fmt .Errorf ("failed to list RBD snapshots. stdout: %s, stderr: %s, err: %w" ,
752+ string (stdout ), string (stderr ), err )
753+ }
754+
755+ var snapshots []* model.RBDSnapshot
756+ if err := json .Unmarshal (stdout , & snapshots ); err != nil {
757+ return nil , fmt .Errorf ("failed to unmarshal RBD snapshot list. err: %w" , err )
758+ }
759+
760+ return snapshots , nil
761+ }
762+
682763func VerifyRawImage (pvc * corev1.PersistentVolumeClaim , node string , expected []byte ) {
683764 GinkgoHelper ()
684765
@@ -706,13 +787,22 @@ func VerifyDeletionOfJobsForBackup(ctx context.Context, client kubernetes.Interf
706787 Expect (err ).NotTo (HaveOccurred (), "Deletion job should be deleted." )
707788}
708789
709- func VerifyDeletionOfSnapshotInFinBackup (ctx context.Context , ctrlClient client. Client , finbackup * finv1.FinBackup ) {
790+ func VerifyDeletionOfSnapshotInFinBackup (ctx context.Context , finbackup * finv1.FinBackup ) error {
710791 GinkgoHelper ()
711792
712- rbdImage := finbackup .Annotations ["fin.cybozu.io/backup-target-rbd-image" ]
713- stdout , stderr , err := kubectl ("exec" , "-n" , rookNamespace , "deploy/rook-ceph-tools" , "--" ,
714- "rbd" , "info" , fmt .Sprintf ("%s/%s@fin-backup-%s" , poolName , rbdImage , finbackup .UID ))
715- Expect (err ).To (HaveOccurred (), "Snapshot should be deleted. stdout: %s, stderr: %s" , stdout , stderr )
793+ imageName := finbackup .Annotations ["fin.cybozu.io/backup-target-rbd-image" ]
794+ snapshots , err := ListRBDSnapshots (ctx , poolName , imageName )
795+ if err != nil {
796+ return err
797+ }
798+
799+ expectedSnapName := fmt .Sprintf ("fin-backup-%s" , finbackup .UID )
800+ for _ , snapshot := range snapshots {
801+ if snapshot .Name == expectedSnapName {
802+ return fmt .Errorf ("snapshot %s still exists" , expectedSnapName )
803+ }
804+ }
805+ return nil
716806}
717807
718808func VerifyDeletionOfResourcesForRestore (
0 commit comments