From 9453308c7848438f4b4a4a1c07749eb23304367d Mon Sep 17 00:00:00 2001 From: Sander van Harmelen Date: Tue, 5 May 2020 18:13:01 +0200 Subject: [PATCH] Make sure the WinRM communicator can reconnect --- .../provisioners/chef/resource_provisioner.go | 22 ++++++++++++++----- communicator/winrm/communicator.go | 5 ++--- website/docs/provisioners/chef.html.markdown | 5 +++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/builtin/provisioners/chef/resource_provisioner.go b/builtin/provisioners/chef/resource_provisioner.go index d729587d6..6f2f3ae52 100644 --- a/builtin/provisioners/chef/resource_provisioner.go +++ b/builtin/provisioners/chef/resource_provisioner.go @@ -204,7 +204,7 @@ func Provisioner() terraform.ResourceProvisioner { "max_retries": &schema.Schema{ Type: schema.TypeInt, Optional: true, - Default: 1, + Default: 0, }, "no_proxy": &schema.Schema{ Type: schema.TypeList, @@ -392,6 +392,11 @@ func applyFn(ctx context.Context) error { o.Output("Starting initial Chef-Client run...") for attempt := 0; attempt <= p.MaxRetries; attempt++ { + // We need a new retry context for each attempt, to make sure + // they all get the correct timeout. + retryCtx, cancel := context.WithTimeout(ctx, comm.Timeout()) + defer cancel() + // Make sure to (re)connect before trying to run Chef-Client. if err := communicator.Retry(retryCtx, func() error { return comm.Connect(o) @@ -795,7 +800,7 @@ func decodeConfig(d *schema.ResourceData) (*provisioner, error) { OSType: d.Get("os_type").(string), RecreateClient: d.Get("recreate_client").(bool), PreventSudo: d.Get("prevent_sudo").(bool), - RetryOnExitCode: getIntListAsMap(d.Get("retry_on_exit_code")), + RetryOnExitCode: getRetryOnExitCodes(d), RunList: getStringList(d.Get("run_list")), SecretKey: d.Get("secret_key").(string), ServerURL: d.Get("server_url").(string), @@ -855,12 +860,19 @@ func decodeConfig(d *schema.ResourceData) (*provisioner, error) { return p, nil } -func getIntListAsMap(v interface{}) map[int]bool { +func getRetryOnExitCodes(d *schema.ResourceData) map[int]bool { result := make(map[int]bool) - switch v := v.(type) { - case nil: + v, ok := d.GetOk("retry_on_exit_code") + if !ok || v == nil { + // Use default exit codes + result[35] = true + result[37] = true + result[213] = true return result + } + + switch v := v.(type) { case []interface{}: for _, vv := range v { if vv, ok := vv.(int); ok { diff --git a/communicator/winrm/communicator.go b/communicator/winrm/communicator.go index cdeab9383..6f48085e1 100644 --- a/communicator/winrm/communicator.go +++ b/communicator/winrm/communicator.go @@ -52,9 +52,8 @@ func New(s *terraform.InstanceState) (*Communicator, error) { // Connect implementation of communicator.Communicator interface func (c *Communicator) Connect(o terraform.UIOutput) error { - if c.client != nil { - return nil - } + // Set the client to nil since we'll (re)create it + c.client = nil params := winrm.DefaultParameters params.Timeout = formatDuration(c.Timeout()) diff --git a/website/docs/provisioners/chef.html.markdown b/website/docs/provisioners/chef.html.markdown index 59293aa97..fcb330472 100644 --- a/website/docs/provisioners/chef.html.markdown +++ b/website/docs/provisioners/chef.html.markdown @@ -112,7 +112,7 @@ The following arguments are supported: * `https_proxy (string)` - (Optional) The proxy server for Chef Client HTTPS connections. * `max_retries (integer)` - (Optional) The number of times to retry the provisioning process - after receiving an exit code in the `retry_on_error` list. Defaults to `1` + after receiving an exit code in the `retry_on_error` list. Defaults to `0` * `named_run_list (string)` - (Optional) The name of an alternate run-list to invoke during the initial Chef Client run. The run-list must already exist in the Policyfile that defines @@ -136,9 +136,10 @@ The following arguments are supported: * `recreate_client (boolean)` - (Optional) If `true`, first delete any existing Chef Node and Client before registering the new Chef Client. -* `retry_on_error (list of integers)` - (Optional) The error codes upon which Terraform should +* `retry_on_error (array)` - (Optional) The error codes upon which Terraform should gracefully retry the provisioning process. Intended for use with [Chef RFC062 codes](https://github.com/chef-boneyard/chef-rfc/blob/master/rfc062-exit-status.md). + (Defaults to `[35, 37, 213]`) * `run_list (array)` - (Optional) A list with recipes that will be invoked during the initial Chef Client run. The run-list will also be saved to the Chef Server after a successful