Skip to content

Commit

Permalink
Add provider configuration settings for retry mode and max retry time
Browse files Browse the repository at this point in the history
(cherry picked from commit 9f22000)
  • Loading branch information
ddelnano committed Oct 3, 2023
1 parent 0a2e447 commit 1bf03cd
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 8 deletions.
39 changes: 31 additions & 8 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,31 @@ type XOClient interface {
}

type Client struct {
rpc jsonrpc2.JSONRPC2
httpClient http.Client
restApiURL *url.URL
RetryMode RetryMode
RetryMaxTime time.Duration
rpc jsonrpc2.JSONRPC2
httpClient http.Client
restApiURL *url.URL
}

type RetryMode int

const (
None RetryMode = iota // specifies that no retries will be made
// Specifies that exponential backoff will be used for certain retryable errors. When
// a guest is booting there is the potential for a race condition if the given action
// relies on the existance of a PV driver (unplugging / plugging a device). This open
// allows the provider to retry these errors until the guest is initialized.
Backoff
)

type Config struct {
Url string
Username string
Password string
InsecureSkipVerify bool
RetryMode RetryMode
RetryMaxTime time.Duration
}

var dialer = gorillawebsocket.Dialer{
Expand Down Expand Up @@ -223,13 +238,20 @@ func NewClient(config Config) (XOClient, error) {
},
}
return &Client{
rpc: c,
httpClient: httpClient,
restApiURL: restApiURL,
RetryMode: config.RetryMode,
RetryMaxTime: config.RetryMaxTime,
rpc: c,
httpClient: httpClient,
restApiURL: restApiURL,
}, nil
}

func IsRetryableError(err jsonrpc2.Error) bool {
func (c *Client) IsRetryableError(err jsonrpc2.Error) bool {

if c.RetryMode == None {
return false
}

// Error code 11 corresponds to an error condition where a VM is missing PV drivers.
// https://github.com/vatesfr/xen-orchestra/blob/a3a2fda157fa30af4b93d34c99bac550f7c82bbc/packages/xo-common/api-errors.js#L95

Expand Down Expand Up @@ -262,7 +284,7 @@ func (c *Client) Call(method string, params, result interface{}) error {
return backoff.Permanent(err)
}

if IsRetryableError(*rpcErr) {
if c.IsRetryableError(*rpcErr) {
return err
}

Expand All @@ -278,6 +300,7 @@ func (c *Client) Call(method string, params, result interface{}) error {
}

bo := backoff.NewExponentialBackOff()
bo.MaxElapsedTime = c.RetryMaxTime
return backoff.Retry(operation, bo)
}

Expand Down
42 changes: 42 additions & 0 deletions xoa/provider.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
package xoa

import (
"errors"
"fmt"
"regexp"
"time"

"github.com/ddelnano/terraform-provider-xenorchestra/client"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

var (
retryModeMap = map[string]client.RetryMode{
"none": client.None,
"backoff": client.Backoff,
}
)

func Provider() *schema.Provider {
Expand Down Expand Up @@ -33,6 +46,20 @@ func Provider() *schema.Provider {
DefaultFunc: schema.EnvDefaultFunc("XOA_INSECURE", nil),
Description: "Whether SSL should be verified or not. Can be set via the XOA_INSECURE environment variable.",
},
"retry_mode": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("XOA_RETRY_MODE", "backoff"),
Description: "Specifies if retries should be attempted for requests that require eventual . Can be set via the XOA_RETRY_MODE environment variable.",
ValidateFunc: validation.StringInSlice([]string{"backoff", "none"}, false),
},
"retry_max_time": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("XOA_RETRY_MAX_TIME", "5m"),
Description: "If `retry_mode` is set, this specifies the duration for which the backoff method will continue retries. Can be set via the `XOA_RETRY_MAX_TIME` environment variable",
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[0-9]+(\.[0-9]+)?(ms|s|m|h)$`), "must be a number immediately followed by ms (milliseconds), s (seconds), m (minutes), or h (hours). For example, \"30s\" for 30 seconds."),
},
},
ResourcesMap: map[string]*schema.Resource{
"xenorchestra_acl": resourceAcl(),
Expand Down Expand Up @@ -66,11 +93,26 @@ func xoaConfigure(d *schema.ResourceData) (interface{}, error) {
username := d.Get("username").(string)
password := d.Get("password").(string)
insecure := d.Get("insecure").(bool)
retryMode := d.Get("retry_mode").(string)
retryMaxTime := d.Get("retry_max_time").(string)

duration, err := time.ParseDuration(retryMaxTime)
if err != nil {
return client.Config{}, err
}

retry, ok := retryModeMap[retryMode]
if !ok {
return client.Config{}, errors.New(fmt.Sprintf("retry mode provided invalid: %s", retryMode))
}

config := client.Config{
Url: url,
Username: username,
Password: password,
InsecureSkipVerify: insecure,
RetryMode: retry,
RetryMaxTime: duration,
}
return client.NewClient(config)
}

0 comments on commit 1bf03cd

Please sign in to comment.