diff --git a/builder/googlecompute/config.go b/builder/googlecompute/config.go index 462836f69..24f4a39e8 100644 --- a/builder/googlecompute/config.go +++ b/builder/googlecompute/config.go @@ -210,6 +210,8 @@ type Config struct { // - The contents of the script file will be wrapped in Packer's startup script wrapper, unless `wrap_startup_script` is disabled. See `wrap_startup_script` for more details. // - Not supported by Windows instances. See [Startup Scripts for Windows](https://cloud.google.com/compute/docs/startupscript#providing_a_startup_script_for_windows_instances) for more details. StartupScriptFile string `mapstructure:"startup_script_file" required:"false"` + // The time to wait for windows password to be retrieved. Defaults to "3m". + WindowsPasswordTimeout time.Duration `mapstructure:"windows_password_timeout" required:"false"` // For backwards compatibility this option defaults to `"true"` in the future it will default to `"false"`. // If "true", the contents of `startup_script_file` or `"startup_script"` in the instance metadata // is wrapped in a Packer specific script that tracks the execution and completion of the provided @@ -542,6 +544,10 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) { c.WrapStartupScriptFile = config.TriTrue } } + // Check windows password timeout is provided + if c.WindowsPasswordTimeout == 0 { + c.WindowsPasswordTimeout = 3 * time.Minute + } // Check for any errors. if errs != nil && len(errs.Errors) > 0 { diff --git a/builder/googlecompute/config.hcl2spec.go b/builder/googlecompute/config.hcl2spec.go index 7001840be..3879719fd 100644 --- a/builder/googlecompute/config.hcl2spec.go +++ b/builder/googlecompute/config.hcl2spec.go @@ -112,6 +112,7 @@ type FlatConfig struct { SourceImageFamily *string `mapstructure:"source_image_family" required:"true" cty:"source_image_family" hcl:"source_image_family"` SourceImageProjectId []string `mapstructure:"source_image_project_id" required:"false" cty:"source_image_project_id" hcl:"source_image_project_id"` StartupScriptFile *string `mapstructure:"startup_script_file" required:"false" cty:"startup_script_file" hcl:"startup_script_file"` + WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"` WrapStartupScriptFile *bool `mapstructure:"wrap_startup_script" required:"false" cty:"wrap_startup_script" hcl:"wrap_startup_script"` Subnetwork *string `mapstructure:"subnetwork" required:"false" cty:"subnetwork" hcl:"subnetwork"` Tags []string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"` @@ -236,6 +237,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "source_image_family": &hcldec.AttrSpec{Name: "source_image_family", Type: cty.String, Required: false}, "source_image_project_id": &hcldec.AttrSpec{Name: "source_image_project_id", Type: cty.List(cty.String), Required: false}, "startup_script_file": &hcldec.AttrSpec{Name: "startup_script_file", Type: cty.String, Required: false}, + "windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false}, "wrap_startup_script": &hcldec.AttrSpec{Name: "wrap_startup_script", Type: cty.Bool, Required: false}, "subnetwork": &hcldec.AttrSpec{Name: "subnetwork", Type: cty.String, Required: false}, "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.List(cty.String), Required: false}, diff --git a/builder/googlecompute/driver.go b/builder/googlecompute/driver.go index 0c8afbda5..631062aea 100644 --- a/builder/googlecompute/driver.go +++ b/builder/googlecompute/driver.go @@ -107,13 +107,14 @@ type InstanceConfig struct { // WindowsPasswordConfig is the data structure that GCE needs to encrypt the created // windows password. type WindowsPasswordConfig struct { - key *rsa.PrivateKey - password string - UserName string `json:"userName"` - Modulus string `json:"modulus"` - Exponent string `json:"exponent"` - Email string `json:"email"` - ExpireOn time.Time `json:"expireOn"` + key *rsa.PrivateKey + password string + UserName string `json:"userName"` + Modulus string `json:"modulus"` + Exponent string `json:"exponent"` + Email string `json:"email"` + ExpireOn time.Time `json:"expireOn"` + WindowsPasswordTimeout time.Duration `json:"timeout"` } type windowsPasswordResponse struct { diff --git a/builder/googlecompute/driver_gce.go b/builder/googlecompute/driver_gce.go index dfd1c9c06..cf2c727cf 100644 --- a/builder/googlecompute/driver_gce.go +++ b/builder/googlecompute/driver_gce.go @@ -568,7 +568,7 @@ func (d *driverGCE) createWindowsPassword(errCh chan<- error, name, zone string, return } - timeout := time.Now().Add(time.Minute * 3) + timeout := time.Now().Add(c.WindowsPasswordTimeout) hash := sha1.New() random := rand.Reader diff --git a/builder/googlecompute/step_create_windows_password.go b/builder/googlecompute/step_create_windows_password.go index a5dd9c18a..4a5850888 100644 --- a/builder/googlecompute/step_create_windows_password.go +++ b/builder/googlecompute/step_create_windows_password.go @@ -60,12 +60,13 @@ func (s *StepCreateWindowsPassword) Run(ctx context.Context, state multistep.Sta } data := WindowsPasswordConfig{ - key: priv, - UserName: c.Comm.WinRMUser, - Modulus: base64.StdEncoding.EncodeToString(priv.N.Bytes()), - Exponent: base64.StdEncoding.EncodeToString(buf[1:]), - Email: email, - ExpireOn: time.Now().Add(time.Minute * 5), + key: priv, + UserName: c.Comm.WinRMUser, + Modulus: base64.StdEncoding.EncodeToString(priv.N.Bytes()), + Exponent: base64.StdEncoding.EncodeToString(buf[1:]), + Email: email, + ExpireOn: time.Now().Add(time.Minute * 5), + WindowsPasswordTimeout: c.WindowsPasswordTimeout, } if s.Debug { @@ -98,7 +99,7 @@ func (s *StepCreateWindowsPassword) Run(ctx context.Context, state multistep.Sta ui.Message("Waiting for windows password to complete...") select { case err = <-errCh: - case <-time.After(c.StateTimeout): + case <-time.After(c.WindowsPasswordTimeout): err = errors.New("time out while waiting for the password to be created") } } diff --git a/website/content/partials/builder/googlecompute/Config-not-required.mdx b/website/content/partials/builder/googlecompute/Config-not-required.mdx index 3bc4a6647..90ab25cdf 100644 --- a/website/content/partials/builder/googlecompute/Config-not-required.mdx +++ b/website/content/partials/builder/googlecompute/Config-not-required.mdx @@ -167,6 +167,8 @@ - The contents of the script file will be wrapped in Packer's startup script wrapper, unless `wrap_startup_script` is disabled. See `wrap_startup_script` for more details. - Not supported by Windows instances. See [Startup Scripts for Windows](https://cloud.google.com/compute/docs/startupscript#providing_a_startup_script_for_windows_instances) for more details. +- `windows_password_timeout` (duration string | ex: "1h5m2s") - The time to wait for windows password to be retrieved. Defaults to "3m". + - `wrap_startup_script` (boolean) - For backwards compatibility this option defaults to `"true"` in the future it will default to `"false"`. If "true", the contents of `startup_script_file` or `"startup_script"` in the instance metadata is wrapped in a Packer specific script that tracks the execution and completion of the provided