Skip to content

Commit b5e9485

Browse files
IaaS Server waiters (#865)
* Add server waiters * Add waiter unit tests * Fix litn * Rename variables
1 parent 3cee42a commit b5e9485

File tree

2 files changed

+410
-5
lines changed

2 files changed

+410
-5
lines changed

services/iaasalpha/wait/wait.go

Lines changed: 107 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ import (
1212
)
1313

1414
const (
15-
AvailableStatus = "AVAILABLE"
16-
DeleteSuccess = "DELETED"
17-
ErrorStatus = "ERROR"
15+
VolumeAvailableStatus = "AVAILABLE"
16+
DeleteSuccess = "DELETED"
17+
ErrorStatus = "ERROR"
18+
ServerActiveStatus = "ACTIVE"
19+
ServerResizingStatus = "RESIZING"
1820
)
1921

2022
// Interfaces needed for tests
2123
type APIClientInterface interface {
2224
GetVolumeExecute(ctx context.Context, projectId string, volumeId string) (*iaasalpha.Volume, error)
25+
GetServerExecute(ctx context.Context, projectId string, serverId string) (*iaasalpha.Server, error)
2326
}
2427

2528
// CreateVolumeWaitHandler will wait for volume creation
@@ -32,7 +35,7 @@ func CreateVolumeWaitHandler(ctx context.Context, a APIClientInterface, projectI
3235
if volume.Id == nil || volume.Status == nil {
3336
return false, volume, fmt.Errorf("create failed for volume with id %s, the response is not valid: the id or the status are missing", volumeId)
3437
}
35-
if *volume.Id == volumeId && *volume.Status == AvailableStatus {
38+
if *volume.Id == volumeId && *volume.Status == VolumeAvailableStatus {
3639
return true, volume, nil
3740
}
3841
if *volume.Id == volumeId && *volume.Status == ErrorStatus {
@@ -71,3 +74,103 @@ func DeleteVolumeWaitHandler(ctx context.Context, a APIClientInterface, projectI
7174
handler.SetTimeout(10 * time.Minute)
7275
return handler
7376
}
77+
78+
// CreateServerWaitHandler will wait for server creation
79+
func CreateServerWaitHandler(ctx context.Context, a APIClientInterface, projectId, serverId string) *wait.AsyncActionHandler[iaasalpha.Server] {
80+
handler := wait.New(func() (waitFinished bool, response *iaasalpha.Server, err error) {
81+
server, err := a.GetServerExecute(ctx, projectId, serverId)
82+
if err != nil {
83+
return false, server, err
84+
}
85+
if server.Id == nil || server.Status == nil {
86+
return false, server, fmt.Errorf("create failed for server with id %s, the response is not valid: the id or the status are missing", serverId)
87+
}
88+
if *server.Id == serverId && *server.Status == ServerActiveStatus {
89+
return true, server, nil
90+
}
91+
if *server.Id == serverId && *server.Status == ErrorStatus {
92+
return true, server, fmt.Errorf("create failed for server with id %s", serverId)
93+
}
94+
return false, server, nil
95+
})
96+
handler.SetTimeout(20 * time.Minute)
97+
return handler
98+
}
99+
100+
// ResizingServerWaitHandler will wait for a server to be resizing
101+
// Ii is an intermediate step inside the ResizeServerWaitHandler
102+
func resizingServerWaitHandler(ctx context.Context, a APIClientInterface, projectId, serverId string) *wait.AsyncActionHandler[iaasalpha.Server] {
103+
handler := wait.New(func() (waitFinished bool, response *iaasalpha.Server, err error) {
104+
server, err := a.GetServerExecute(ctx, projectId, serverId)
105+
if err != nil {
106+
return false, server, err
107+
}
108+
if server.Id == nil || server.Status == nil {
109+
return false, server, fmt.Errorf("resizing failed for server with id %s, the response is not valid: the id or the status are missing", serverId)
110+
}
111+
if *server.Id == serverId && *server.Status == ServerResizingStatus {
112+
return true, server, nil
113+
}
114+
if *server.Id == serverId && *server.Status == ErrorStatus {
115+
return true, server, fmt.Errorf("resizing failed for server with id %s", serverId)
116+
}
117+
return false, server, nil
118+
})
119+
handler.SetTimeout(10 * time.Minute)
120+
return handler
121+
}
122+
123+
// ResizeServerWaitHandler will wait for server resize
124+
// It checks for an intermediate resizing status and only then waits for the server to become active
125+
func ResizeServerWaitHandler(ctx context.Context, a APIClientInterface, projectId, serverId string) *wait.AsyncActionHandler[iaasalpha.Server] {
126+
handler := wait.New(func() (waitFinished bool, response *iaasalpha.Server, err error) {
127+
server, err := resizingServerWaitHandler(ctx, a, projectId, serverId).WaitWithContext(ctx)
128+
if err != nil {
129+
return false, server, err
130+
}
131+
server, err = a.GetServerExecute(ctx, projectId, serverId)
132+
if err != nil {
133+
return false, server, err
134+
}
135+
if server.Id == nil || server.Status == nil {
136+
return false, server, fmt.Errorf("resizing failed for server with id %s, the response is not valid: the id or the status are missing", serverId)
137+
}
138+
if *server.Id == serverId && *server.Status == ServerActiveStatus {
139+
return true, server, nil
140+
}
141+
if *server.Id == serverId && *server.Status == ErrorStatus {
142+
return true, server, fmt.Errorf("resizing failed for server with id %s", serverId)
143+
}
144+
return false, server, nil
145+
})
146+
handler.SetTimeout(20 * time.Minute)
147+
return handler
148+
}
149+
150+
// DeleteServerWaitHandler will wait for volume deletion
151+
func DeleteServerWaitHandler(ctx context.Context, a APIClientInterface, projectId, serverId string) *wait.AsyncActionHandler[iaasalpha.Server] {
152+
handler := wait.New(func() (waitFinished bool, response *iaasalpha.Server, err error) {
153+
server, err := a.GetServerExecute(ctx, projectId, serverId)
154+
if err == nil {
155+
if server != nil {
156+
if server.Id == nil || server.Status == nil {
157+
return false, server, fmt.Errorf("delete failed for server with id %s, the response is not valid: the id or the status are missing", serverId)
158+
}
159+
if *server.Id == serverId && *server.Status == DeleteSuccess {
160+
return true, server, nil
161+
}
162+
}
163+
return false, nil, nil
164+
}
165+
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
166+
if !ok {
167+
return false, server, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError: %w", err)
168+
}
169+
if oapiErr.StatusCode != http.StatusNotFound {
170+
return false, server, err
171+
}
172+
return true, nil, nil
173+
})
174+
handler.SetTimeout(20 * time.Minute)
175+
return handler
176+
}

0 commit comments

Comments
 (0)