From 77a8481bfb2e583f2e5758e9264bf50bf8df159f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Wed, 10 May 2023 15:11:03 +0200 Subject: [PATCH 1/2] Update name Reply->Retry --- api/security_firewall.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/security_firewall.go b/api/security_firewall.go index 6c39bb6..6660645 100644 --- a/api/security_firewall.go +++ b/api/security_firewall.go @@ -39,7 +39,7 @@ func (api *API) waitUntilFirewallConfigured(instanceID, attempt, sleep, timeout func (api *API) CreateFirewallSettings(instanceID int, params []map[string]interface{}, sleep, timeout int) ([]map[string]interface{}, error) { - attempt, err := api.createFirewallSettingsWithReply(instanceID, params, 1, sleep, timeout) + attempt, err := api.createFirewallSettingsWithRetry(instanceID, params, 1, sleep, timeout) if err != nil { return nil, err } @@ -50,7 +50,7 @@ func (api *API) CreateFirewallSettings(instanceID int, params []map[string]inter return api.ReadFirewallSettings(instanceID) } -func (api *API) createFirewallSettingsWithReply(instanceID int, params []map[string]interface{}, +func (api *API) createFirewallSettingsWithRetry(instanceID int, params []map[string]interface{}, attempt, sleep, timeout int) (int, error) { var ( failed map[string]interface{} @@ -77,7 +77,7 @@ func (api *API) createFirewallSettingsWithReply(instanceID int, params []map[str "attempt: %d, until timeout: %d", attempt, (timeout - (attempt * sleep))) attempt++ time.Sleep(time.Duration(sleep) * time.Second) - return api.createFirewallSettingsWithReply(instanceID, params, attempt, sleep, timeout) + return api.createFirewallSettingsWithRetry(instanceID, params, attempt, sleep, timeout) case failed["error_code"].(float64) == 40002: return attempt, fmt.Errorf("Firewall rules validation failed due to: %s", failed["error"].(string)) } From 7690f552ebede929bc7b8f9b8dcf11f88ccc60bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Brod=C3=A9n?= Date: Wed, 10 May 2023 15:24:18 +0200 Subject: [PATCH 2/2] Add retry functionality to delete firewall settings. Be able to catch and retry error code 40001, if previous firewall configuration not yet finished. --- api/security_firewall.go | 55 ++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/api/security_firewall.go b/api/security_firewall.go index 6660645..2dc6e95 100644 --- a/api/security_firewall.go +++ b/api/security_firewall.go @@ -133,10 +133,10 @@ func (api *API) updateFirewallSettingsWithRetry(instanceID int, params []map[str return attempt, fmt.Errorf("Update firewall settings failed, reached timeout of %d seconds", timeout) } - switch { - case response.StatusCode == 204: + switch response.StatusCode { + case 204: return attempt, nil - case response.StatusCode == 400: + case 400: switch { case failed["error_code"] == nil: break @@ -150,34 +150,61 @@ func (api *API) updateFirewallSettingsWithRetry(instanceID int, params []map[str return attempt, fmt.Errorf("Firewall rules validation failed due to: %s", failed["error"].(string)) } } - return attempt, fmt.Errorf("Update firewall rules failed, status: %v, message: %v", response.StatusCode, failed) + return attempt, fmt.Errorf("Update firewall rules failed, status: %v, message: %v", + response.StatusCode, failed) } func (api *API) DeleteFirewallSettings(instanceID, sleep, timeout int) ([]map[string]interface{}, error) { + log.Printf("[DEBUG] go-api::security_firewall::delete instance id: %v, sleep: %d, timeout: %d", + instanceID, sleep, timeout) + attempt, err := api.deleteFirewallSettingsWithRetry(instanceID, 1, sleep, timeout) + if err != nil { + return nil, err + } + + err = api.waitUntilFirewallConfigured(instanceID, attempt, sleep, timeout) + if err != nil { + return nil, err + } + return api.ReadFirewallSettings(instanceID) +} + +func (api *API) deleteFirewallSettingsWithRetry(instanceID, attempt, sleep, timeout int) (int, error) { var ( params [1]map[string]interface{} failed map[string]interface{} path = fmt.Sprintf("/api/instances/%d/security/firewall", instanceID) ) - log.Printf("[DEBUG] go-api::security_firewall::delete instance id: %v", instanceID) // Use default firewall rule and update firewall upon delete. params[0] = DefaultFirewallSettings() log.Printf("[DEBUG] go-api::security_firewall::delete default firewall: %v", params[0]) response, err := api.sling.New().Put(path).BodyJSON(params).Receive(nil, &failed) - if err != nil { - return nil, err - } - if response.StatusCode != 204 { - return nil, fmt.Errorf("DeleteFirewallSettings failed, status: %v, message: %s", response.StatusCode, failed) + return attempt, err + } else if attempt*sleep > timeout { + return attempt, fmt.Errorf("Delete firewall settings failed, reached timeout of %d seconds", timeout) } - err = api.waitUntilFirewallConfigured(instanceID, 1, sleep, timeout) - if err != nil { - return nil, err + switch response.StatusCode { + case 204: + return attempt, nil + case 400: + switch { + case failed["error_code"] == nil: + break + case failed["error_code"].(float64) == 40001: + log.Printf("[INFO] go-api::security_firewall::delete Firewall not finished configuring "+ + "attempt: %d until timeout: %d", attempt, (timeout - (attempt * sleep))) + attempt++ + time.Sleep(time.Duration(sleep) * time.Second) + return api.deleteFirewallSettingsWithRetry(instanceID, attempt, sleep, timeout) + case failed["error_code"].(float64) == 40002: + return attempt, fmt.Errorf("Firewall rules validation failed due to: %s", failed["error"].(string)) + } } - return api.ReadFirewallSettings(instanceID) + return attempt, fmt.Errorf("Delete firewall rules failed, status: %v, message: %v", + response.StatusCode, failed) } func DefaultFirewallSettings() map[string]interface{} {