diff --git a/api/baremetal/v1/server_utils.go b/api/baremetal/v1/server_utils.go index 07acbb2ef..6df64bfd6 100644 --- a/api/baremetal/v1/server_utils.go +++ b/api/baremetal/v1/server_utils.go @@ -8,26 +8,31 @@ import ( "github.com/scaleway/scaleway-sdk-go/scw" ) -var ( - // RetryInterval is needed when running recorded tests (e.g. on scaleway-cli) - // it allows to execute the WaitFor funcs immediately - RetryInterval = defaultRetryInterval -) - const ( defaultRetryInterval = 15 * time.Second + defaultTimeout = 2 * time.Hour ) // WaitForServerRequest is used by WaitForServer method. type WaitForServerRequest struct { - ServerID string - Zone scw.Zone - Timeout time.Duration + ServerID string + Zone scw.Zone + Timeout time.Duration + RetryInterval time.Duration } // WaitForServer wait for the server to be in a "terminal state" before returning. // This function can be used to wait for a server to be created. func (s *API) WaitForServer(req *WaitForServerRequest) (*Server, error) { + timeout := req.Timeout + if timeout == 0 { + timeout = defaultTimeout + } + retryInterval := req.RetryInterval + if retryInterval == 0 { + retryInterval = defaultRetryInterval + } + terminalStatus := map[ServerStatus]struct{}{ ServerStatusReady: {}, ServerStatusStopped: {}, @@ -49,8 +54,8 @@ func (s *API) WaitForServer(req *WaitForServerRequest) (*Server, error) { _, isTerminal := terminalStatus[res.Status] return res, isTerminal, err }, - Timeout: req.Timeout, - IntervalStrategy: async.LinearIntervalStrategy(RetryInterval), + Timeout: timeout, + IntervalStrategy: async.LinearIntervalStrategy(retryInterval), }) if err != nil { return nil, errors.Wrap(err, "waiting for server failed") @@ -61,15 +66,25 @@ func (s *API) WaitForServer(req *WaitForServerRequest) (*Server, error) { // WaitForServerInstallRequest is used by WaitForServerInstall method. type WaitForServerInstallRequest struct { - ServerID string - Zone scw.Zone - Timeout time.Duration + ServerID string + Zone scw.Zone + Timeout time.Duration + RetryInterval time.Duration } // WaitForServerInstall wait for the server install to be in a // "terminal state" before returning. // This function can be used to wait for a server to be installed. func (s *API) WaitForServerInstall(req *WaitForServerInstallRequest) (*Server, error) { + timeout := req.Timeout + if timeout == 0 { + timeout = defaultTimeout + } + retryInterval := req.RetryInterval + if retryInterval == 0 { + retryInterval = defaultRetryInterval + } + installTerminalStatus := map[ServerInstallStatus]struct{}{ ServerInstallStatusCompleted: {}, ServerInstallStatusError: {}, @@ -93,8 +108,8 @@ func (s *API) WaitForServerInstall(req *WaitForServerInstallRequest) (*Server, e _, isTerminal := installTerminalStatus[res.Install.Status] return res, isTerminal, err }, - Timeout: req.Timeout, - IntervalStrategy: async.LinearIntervalStrategy(RetryInterval), + Timeout: timeout, + IntervalStrategy: async.LinearIntervalStrategy(retryInterval), }) if err != nil { return nil, errors.Wrap(err, "waiting for server installation failed") diff --git a/api/registry/v1/image_utils.go b/api/registry/v1/image_utils.go new file mode 100644 index 000000000..0ea40002d --- /dev/null +++ b/api/registry/v1/image_utils.go @@ -0,0 +1,59 @@ +package registry + +import ( + "time" + + "github.com/scaleway/scaleway-sdk-go/internal/async" + "github.com/scaleway/scaleway-sdk-go/internal/errors" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +// WaitForNamespaceRequest is used by WaitForNamespace method +type WaitForImageRequest struct { + ImageID string + Region scw.Region + Timeout time.Duration + RetryInterval time.Duration +} + +// WaitForImage wait for the image to be in a "terminal state" before returning. +// This function can be used to wait for an image to be ready for example. +func (s *API) WaitForImage(req *WaitForImageRequest) (*Image, error) { + timeout := req.Timeout + if timeout == 0 { + timeout = defaultTimeout + } + retryInterval := req.RetryInterval + if retryInterval == 0 { + retryInterval = defaultRetryInterval + } + + terminalStatus := map[ImageStatus]struct{}{ + ImageStatusReady: {}, + ImageStatusLocked: {}, + ImageStatusError: {}, + ImageStatusUnknown: {}, + } + + image, err := async.WaitSync(&async.WaitSyncConfig{ + Get: func() (interface{}, bool, error) { + img, err := s.GetImage(&GetImageRequest{ + Region: req.Region, + ImageID: req.ImageID, + }) + if err != nil { + return nil, false, err + } + + _, isTerminal := terminalStatus[img.Status] + + return img, isTerminal, err + }, + Timeout: timeout, + IntervalStrategy: async.LinearIntervalStrategy(retryInterval), + }) + if err != nil { + return nil, errors.Wrap(err, "waiting for image failed") + } + return image.(*Image), nil +} diff --git a/api/registry/v1/registry_utils.go b/api/registry/v1/registry_utils.go index 8e639753c..b03ecbc22 100644 --- a/api/registry/v1/registry_utils.go +++ b/api/registry/v1/registry_utils.go @@ -8,16 +8,31 @@ import ( "github.com/scaleway/scaleway-sdk-go/scw" ) +const ( + defaultTimeout = 5 * time.Minute + defaultRetryInterval = 15 * time.Second +) + // WaitForNamespaceRequest is used by WaitForNamespace method type WaitForNamespaceRequest struct { - NamespaceID string - Region scw.Region - Timeout time.Duration + NamespaceID string + Region scw.Region + Timeout time.Duration + RetryInterval time.Duration } // WaitForNamespace wait for the namespace to be in a "terminal state" before returning. // This function can be used to wait for a namespace to be ready for example. func (s *API) WaitForNamespace(req *WaitForNamespaceRequest) (*Namespace, error) { + timeout := req.Timeout + if timeout == 0 { + timeout = defaultTimeout + } + retryInterval := req.RetryInterval + if retryInterval == 0 { + retryInterval = defaultRetryInterval + } + terminalStatus := map[NamespaceStatus]struct{}{ NamespaceStatusReady: {}, NamespaceStatusLocked: {}, @@ -39,8 +54,8 @@ func (s *API) WaitForNamespace(req *WaitForNamespaceRequest) (*Namespace, error) return ns, isTerminal, err }, - Timeout: req.Timeout, - IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), + Timeout: timeout, + IntervalStrategy: async.LinearIntervalStrategy(retryInterval), }) if err != nil { return nil, errors.Wrap(err, "waiting for namespace failed") diff --git a/api/registry/v1/tag_utils.go b/api/registry/v1/tag_utils.go new file mode 100644 index 000000000..9f834a558 --- /dev/null +++ b/api/registry/v1/tag_utils.go @@ -0,0 +1,59 @@ +package registry + +import ( + "time" + + "github.com/scaleway/scaleway-sdk-go/internal/async" + "github.com/scaleway/scaleway-sdk-go/internal/errors" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +// WaitForTagRequest is used by WaitForTag method +type WaitForTagRequest struct { + TagID string + Region scw.Region + Timeout time.Duration + RetryInterval time.Duration +} + +// WaitForTag wait for the tag to be in a "terminal state" before returning. +// This function can be used to wait for a tag to be ready for example. +func (s *API) WaitForTag(req *WaitForTagRequest) (*Tag, error) { + timeout := req.Timeout + if timeout == 0 { + timeout = defaultTimeout + } + retryInterval := req.RetryInterval + if retryInterval == 0 { + retryInterval = defaultRetryInterval + } + + terminalStatus := map[TagStatus]struct{}{ + TagStatusReady: {}, + TagStatusLocked: {}, + TagStatusError: {}, + TagStatusUnknown: {}, + } + + tag, err := async.WaitSync(&async.WaitSyncConfig{ + Get: func() (interface{}, bool, error) { + t, err := s.GetTag(&GetTagRequest{ + Region: req.Region, + TagID: req.TagID, + }) + if err != nil { + return nil, false, err + } + + _, isTerminal := terminalStatus[t.Status] + + return t, isTerminal, err + }, + Timeout: timeout, + IntervalStrategy: async.LinearIntervalStrategy(retryInterval), + }) + if err != nil { + return nil, errors.Wrap(err, "waiting for tag failed") + } + return tag.(*Tag), nil +}