@@ -24,6 +24,8 @@ const (
2424 ServerDeallocatedStatus = "DEALLOCATED"
2525 ServerRescueStatus = "RESCUE"
2626
27+ ImageAvailableStatus = "AVAILABLE"
28+
2729 RequestCreateAction = "CREATE"
2830 RequestUpdateAction = "UPDATE"
2931 RequestDeleteAction = "DELETE"
@@ -43,6 +45,7 @@ type APIClientInterface interface {
4345 GetVolumeExecute (ctx context.Context , projectId string , volumeId string ) (* iaas.Volume , error )
4446 GetServerExecute (ctx context.Context , projectId string , serverId string ) (* iaas.Server , error )
4547 GetAttachedVolumeExecute (ctx context.Context , projectId string , serverId string , volumeId string ) (* iaas.VolumeAttachment , error )
48+ GetImageExecute (ctx context.Context , projectId string , imageId string ) (* iaas.Image , error )
4649}
4750
4851// CreateNetworkAreaWaitHandler will wait for network area creation
@@ -546,3 +549,53 @@ func RemoveVolumeFromServerWaitHandler(ctx context.Context, a APIClientInterface
546549 handler .SetTimeout (10 * time .Minute )
547550 return handler
548551}
552+
553+ // UploadImageWaitHandler will wait for the status image to become AVAILABLE, which indicates the upload of the image has been completed successfully
554+ func UploadImageWaitHandler (ctx context.Context , a APIClientInterface , projectId , imageId string ) * wait.AsyncActionHandler [iaas.Image ] {
555+ handler := wait .New (func () (waitFinished bool , response * iaas.Image , err error ) {
556+ image , err := a .GetImageExecute (ctx , projectId , imageId )
557+ if err != nil {
558+ return false , image , err
559+ }
560+ if image .Id == nil || image .Status == nil {
561+ return false , image , fmt .Errorf ("upload failed for image with id %s, the response is not valid: the id or the status are missing" , imageId )
562+ }
563+ if * image .Id == imageId && * image .Status == ImageAvailableStatus {
564+ return true , image , nil
565+ }
566+ if * image .Id == imageId && * image .Status == ErrorStatus {
567+ return true , image , fmt .Errorf ("upload failed for image with id %s" , imageId )
568+ }
569+ return false , image , nil
570+ })
571+ handler .SetTimeout (45 * time .Minute )
572+ return handler
573+ }
574+
575+ // DeleteImageWaitHandler will wait for image deletion
576+ func DeleteImageWaitHandler (ctx context.Context , a APIClientInterface , projectId , imageId string ) * wait.AsyncActionHandler [iaas.Image ] {
577+ handler := wait .New (func () (waitFinished bool , response * iaas.Image , err error ) {
578+ image , err := a .GetImageExecute (ctx , projectId , imageId )
579+ if err == nil {
580+ if image != nil {
581+ if image .Id == nil || image .Status == nil {
582+ return false , image , fmt .Errorf ("delete failed for image with id %s, the response is not valid: the id or the status are missing" , imageId )
583+ }
584+ if * image .Id == imageId && * image .Status == DeleteSuccess {
585+ return true , image , nil
586+ }
587+ }
588+ return false , nil , nil
589+ }
590+ oapiErr , ok := err .(* oapierror.GenericOpenAPIError ) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
591+ if ! ok {
592+ return false , image , fmt .Errorf ("could not convert error to oapierror.GenericOpenAPIError: %w" , err )
593+ }
594+ if oapiErr .StatusCode != http .StatusNotFound {
595+ return false , image , err
596+ }
597+ return true , nil , nil
598+ })
599+ handler .SetTimeout (15 * time .Minute )
600+ return handler
601+ }
0 commit comments