Skip to content

Commit 2d58893

Browse files
authored
fix: wait server firewall actions to settle (#209)
Closes #205 Prevents a server `locked` error from the API, when trying to change the type of the server, while `firewall_apply` are still running in the backend. The `firewall_apply` actions are triggered by label selectors.
1 parent de02717 commit 2d58893

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

builder/hcloud/step_create_server.go

+32
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"net/netip"
1010
"os"
11+
"slices"
1112
"sort"
1213
"strings"
1314

@@ -142,6 +143,16 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu
142143
}
143144
state.Put(StateServerIP, serverIP)
144145

146+
// Wait that the server to settle before continuing. Prevents possible `locked`
147+
// error when changing the server type.
148+
actions, err := getServerRunningActions(ctx, client, server)
149+
if err != nil {
150+
return errorHandler(state, ui, "Could not fetch server running actions", err)
151+
}
152+
if err := client.Action.WaitFor(ctx, actions...); err != nil {
153+
return errorHandler(state, ui, "Could not wait for server running actions", err)
154+
}
155+
145156
if c.UpgradeServerType != "" {
146157
ui.Say("Upgrading server type...")
147158
serverChangeTypeAction, _, err := client.Server.ChangeType(ctx, server, hcloud.ServerChangeTypeOpts{
@@ -302,3 +313,24 @@ func firstAvailableIP(server *hcloud.Server) string {
302313
}
303314
return ""
304315
}
316+
317+
func getServerRunningActions(ctx context.Context, client *hcloud.Client, server *hcloud.Server) ([]*hcloud.Action, error) {
318+
actions, err := client.Firewall.Action.All(ctx,
319+
hcloud.ActionListOpts{
320+
Status: []hcloud.ActionStatus{
321+
hcloud.ActionStatusRunning,
322+
},
323+
},
324+
)
325+
if err != nil {
326+
return nil, err
327+
}
328+
329+
actions = slices.DeleteFunc(actions, func(action *hcloud.Action) bool {
330+
return !slices.ContainsFunc(action.Resources, func(resource *hcloud.ActionResource) bool {
331+
return resource.Type == hcloud.ActionResourceTypeServer && resource.ID == server.ID
332+
})
333+
})
334+
335+
return actions, nil
336+
}

builder/hcloud/step_create_server_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ func TestStepCreateServer(t *testing.T) {
6363
"meta": { "pagination": { "page": 1 }}
6464
}`,
6565
},
66+
{Method: "GET", Path: "/firewalls/actions?page=1&status=running",
67+
Status: 200,
68+
JSONRaw: `{
69+
"actions": [],
70+
"meta": { "pagination": { "page": 1 }}
71+
}`,
72+
},
6673
},
6774
WantStepAction: multistep.ActionContinue,
6875
WantStateFunc: func(t *testing.T, state multistep.StateBag) {
@@ -126,6 +133,13 @@ func TestStepCreateServer(t *testing.T) {
126133
"meta": { "pagination": { "page": 1 }}
127134
}`,
128135
},
136+
{Method: "GET", Path: "/firewalls/actions?page=1&status=running",
137+
Status: 200,
138+
JSONRaw: `{
139+
"actions": [],
140+
"meta": { "pagination": { "page": 1 }}
141+
}`,
142+
},
129143
},
130144

131145
WantStepAction: multistep.ActionContinue,
@@ -220,6 +234,13 @@ func TestStepCreateServer(t *testing.T) {
220234
"meta": { "pagination": { "page": 1 }}
221235
}`,
222236
},
237+
{Method: "GET", Path: "/firewalls/actions?page=1&status=running",
238+
Status: 200,
239+
JSONRaw: `{
240+
"actions": [],
241+
"meta": { "pagination": { "page": 1 }}
242+
}`,
243+
},
223244
},
224245
WantStepAction: multistep.ActionContinue,
225246
WantStateFunc: func(t *testing.T, state multistep.StateBag) {
@@ -319,6 +340,13 @@ func TestStepCreateServer(t *testing.T) {
319340
"meta": { "pagination": { "page": 1 }}
320341
}`,
321342
},
343+
{Method: "GET", Path: "/firewalls/actions?page=1&status=running",
344+
Status: 200,
345+
JSONRaw: `{
346+
"actions": [],
347+
"meta": { "pagination": { "page": 1 }}
348+
}`,
349+
},
322350
},
323351
WantStepAction: multistep.ActionContinue,
324352
WantStateFunc: func(t *testing.T, state multistep.StateBag) {

0 commit comments

Comments
 (0)