diff --git a/builder/alicloud/ecs/builder.go b/builder/alicloud/ecs/builder.go index 20c070f6a..e7cfd5814 100644 --- a/builder/alicloud/ecs/builder.go +++ b/builder/alicloud/ecs/builder.go @@ -44,7 +44,7 @@ const ( func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -56,7 +56,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, raws...) b.config.ctx.EnableEnv = true if err != nil { - return nil, err + return nil, nil, err } if b.config.PackerConfig.PackerForce { @@ -71,11 +71,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } packer.LogSecretFilter.Set(b.config.AlicloudAccessKey, b.config.AlicloudSecretKey) - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/alicloud/ecs/builder_test.go b/builder/alicloud/ecs/builder_test.go index e67861f5d..9a691de77 100644 --- a/builder/alicloud/ecs/builder_test.go +++ b/builder/alicloud/ecs/builder_test.go @@ -35,7 +35,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "access_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -50,7 +50,7 @@ func TestBuilderPrepare_ECSImageName(t *testing.T) { // Test good config["image_name"] = "ecs.n1.tiny" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -61,7 +61,7 @@ func TestBuilderPrepare_ECSImageName(t *testing.T) { // Test bad config["ecs_image_name"] = "foo {{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -72,7 +72,7 @@ func TestBuilderPrepare_ECSImageName(t *testing.T) { // Test bad delete(config, "image_name") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -87,7 +87,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -120,7 +120,7 @@ func TestBuilderPrepare_Devices(t *testing.T) { "disk_device": "/dev/xvdc", }, } - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -160,7 +160,7 @@ func TestBuilderPrepare_IgnoreDataDisks(t *testing.T) { var b Builder config := testBuilderConfig() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -173,7 +173,7 @@ func TestBuilderPrepare_IgnoreDataDisks(t *testing.T) { } config["image_ignore_data_disks"] = "false" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -186,7 +186,7 @@ func TestBuilderPrepare_IgnoreDataDisks(t *testing.T) { } config["image_ignore_data_disks"] = "true" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -203,7 +203,7 @@ func TestBuilderPrepare_WaitSnapshotReadyTimeout(t *testing.T) { var b Builder config := testBuilderConfig() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -219,7 +219,7 @@ func TestBuilderPrepare_WaitSnapshotReadyTimeout(t *testing.T) { } config["wait_snapshot_ready_timeout"] = ALICLOUD_DEFAULT_TIMEOUT - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/alicloud/ecs/step_create_instance.go b/builder/alicloud/ecs/step_create_instance.go index 909720e2d..24d3acf27 100644 --- a/builder/alicloud/ecs/step_create_instance.go +++ b/builder/alicloud/ecs/step_create_instance.go @@ -77,6 +77,9 @@ func (s *stepCreateAlicloudInstance) Run(ctx context.Context, state multistep.St ui.Message(fmt.Sprintf("Created instance: %s", instanceId)) s.instance = &instances.Instances.Instance[0] state.Put("instance", s.instance) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", instanceId) return multistep.ActionContinue } diff --git a/builder/amazon/chroot/builder.go b/builder/amazon/chroot/builder.go index 91d00f749..ddadd76c4 100644 --- a/builder/amazon/chroot/builder.go +++ b/builder/amazon/chroot/builder.go @@ -185,7 +185,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = awscommon.TemplateFuncs err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, @@ -204,7 +204,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } if b.config.Architecture == "" { @@ -322,11 +322,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warns, errs + return nil, warns, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return warns, nil + return nil, warns, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/amazon/chroot/builder_test.go b/builder/amazon/chroot/builder_test.go index e6999bff6..b181b878f 100644 --- a/builder/amazon/chroot/builder_test.go +++ b/builder/amazon/chroot/builder_test.go @@ -31,7 +31,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test good config["ami_name"] = "foo" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -42,7 +42,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test bad config["ami_name"] = "foo {{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -53,7 +53,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test bad delete(config, "ami_name") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -67,7 +67,7 @@ func TestBuilderPrepare_ChrootMounts(t *testing.T) { config := testConfig() config["chroot_mounts"] = nil - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -83,7 +83,7 @@ func TestBuilderPrepare_ChrootMountsBadDefaults(t *testing.T) { config["chroot_mounts"] = [][]string{ {"bad"}, } - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -96,7 +96,7 @@ func TestBuilderPrepare_SourceAmi(t *testing.T) { config := testConfig() config["source_ami"] = "" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -105,7 +105,7 @@ func TestBuilderPrepare_SourceAmi(t *testing.T) { } config["source_ami"] = "foo" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -119,7 +119,7 @@ func TestBuilderPrepare_CommandWrapper(t *testing.T) { config := testConfig() config["command_wrapper"] = "echo hi; {{.Command}}" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -132,7 +132,7 @@ func TestBuilderPrepare_CopyFiles(t *testing.T) { b := &Builder{} config := testConfig() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -150,7 +150,7 @@ func TestBuilderPrepare_CopyFilesNoDefault(t *testing.T) { config := testConfig() config["copy_files"] = []string{} - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -171,7 +171,7 @@ func TestBuilderPrepare_RootDeviceNameAndAMIMappings(t *testing.T) { config["root_device_name"] = "/dev/sda" config["ami_block_device_mappings"] = []interface{}{map[string]string{}} config["root_volume_size"] = 15 - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) == 0 { t.Fatal("Missing warning, stating block device mappings will be overwritten") } else if len(warnings) > 1 { @@ -187,7 +187,7 @@ func TestBuilderPrepare_AMIMappingsNoRootDeviceName(t *testing.T) { config := testConfig() config["ami_block_device_mappings"] = []interface{}{map[string]string{}} - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -201,7 +201,7 @@ func TestBuilderPrepare_RootDeviceNameNoAMIMappings(t *testing.T) { config := testConfig() config["root_device_name"] = "/dev/sda" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/amazon/common/step_get_password.go b/builder/amazon/common/step_get_password.go index 3b751cc98..a2d741af6 100644 --- a/builder/amazon/common/step_get_password.go +++ b/builder/amazon/common/step_get_password.go @@ -13,7 +13,6 @@ import ( "github.com/aws/aws-sdk-go/service/ec2" "github.com/hashicorp/packer/common/retry" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -91,16 +90,13 @@ WaitLoop: "Password (since debug is enabled): %s", s.Comm.WinRMPassword)) } // store so that we can access this later during provisioning - - commonhelper.SetSharedState("winrm_password", s.Comm.WinRMPassword, s.BuildName) + state.Put("winrm_password", s.Comm.WinRMPassword) packer.LogSecretFilter.Set(s.Comm.WinRMPassword) return multistep.ActionContinue } -func (s *StepGetPassword) Cleanup(multistep.StateBag) { - commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName) -} +func (s *StepGetPassword) Cleanup(multistep.StateBag) {} func (s *StepGetPassword) waitForPassword(ctx context.Context, state multistep.StateBag) (string, error) { ec2conn := state.Get("ec2").(*ec2.EC2) diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index 0f1941b85..b83db0383 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -280,6 +280,9 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa } state.Put("instance", instance) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", instance.InstanceId) // If we're in a region that doesn't support tagging on instance creation, // do that now. diff --git a/builder/amazon/common/step_run_spot_instance.go b/builder/amazon/common/step_run_spot_instance.go index 06cb28912..d6db5be62 100644 --- a/builder/amazon/common/step_run_spot_instance.go +++ b/builder/amazon/common/step_run_spot_instance.go @@ -441,6 +441,9 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } state.Put("instance", instance) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", instance.InstanceId) return multistep.ActionContinue } diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 6e9b25de4..6bc2ec777 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -75,7 +75,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = awscommon.TemplateFuncs err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, @@ -92,7 +92,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } if b.config.PackerConfig.PackerForce { @@ -126,11 +126,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warns, errs + return nil, warns, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return warns, nil + return nil, warns, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/amazon/ebs/builder_test.go b/builder/amazon/ebs/builder_test.go index a8200b5a8..4ea816130 100644 --- a/builder/amazon/ebs/builder_test.go +++ b/builder/amazon/ebs/builder_test.go @@ -32,7 +32,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "access_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -48,7 +48,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test good config["ami_name"] = "foo" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -59,7 +59,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test bad config["ami_name"] = "foo {{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -70,7 +70,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test bad delete(config, "ami_name") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -85,7 +85,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -101,7 +101,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "terminate" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -111,7 +111,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "stop" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -121,7 +121,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test bad config["shutdown_behavior"] = "foobar" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index 4a52c1de9..052a01ee1 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -74,7 +74,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = awscommon.TemplateFuncs err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, @@ -91,7 +91,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } if b.config.PackerConfig.PackerForce { @@ -149,12 +149,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, errors.New(`The only valid ami_architecture values are "x86_64" and "arm64"`)) } if errs != nil && len(errs.Errors) > 0 { - return warns, errs + return nil, warns, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return warns, nil + return nil, warns, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/amazon/ebssurrogate/builder_test.go b/builder/amazon/ebssurrogate/builder_test.go index 94fdacd6b..37490bc61 100644 --- a/builder/amazon/ebssurrogate/builder_test.go +++ b/builder/amazon/ebssurrogate/builder_test.go @@ -31,7 +31,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "access_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/amazon/ebsvolume/builder.go b/builder/amazon/ebsvolume/builder.go index 886123cb4..a71158778 100644 --- a/builder/amazon/ebsvolume/builder.go +++ b/builder/amazon/ebsvolume/builder.go @@ -83,7 +83,7 @@ type EngineVarsTemplate struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = awscommon.TemplateFuncs // Create passthrough for {{ .BuildRegion }} and {{ .SourceAMI }} variables // so we can fill them in later @@ -96,7 +96,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { InterpolateContext: &b.config.ctx, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors @@ -133,11 +133,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warns, errs + return nil, warns, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return warns, nil + return nil, warns, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/amazon/ebsvolume/builder_test.go b/builder/amazon/ebsvolume/builder_test.go index 85c8ae833..0d8b27ac1 100644 --- a/builder/amazon/ebsvolume/builder_test.go +++ b/builder/amazon/ebsvolume/builder_test.go @@ -31,7 +31,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "access_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -62,7 +62,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "terminate" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -72,7 +72,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "stop" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -82,7 +82,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test bad config["shutdown_behavior"] = "foobar" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index ba87b61d8..36b429612 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -97,7 +97,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { configs := make([]interface{}, len(raws)+1) configs[0] = map[string]interface{}{ "bundle_prefix": "image-{{timestamp}}", @@ -122,7 +122,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, configs...) if err != nil { - return nil, err + return nil, nil, err } if b.config.PackerConfig.PackerForce { @@ -222,10 +222,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warns, errs + return nil, warns, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return warns, nil + return nil, warns, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/amazon/instance/builder_test.go b/builder/amazon/instance/builder_test.go index 0c2a05145..21d4d4030 100644 --- a/builder/amazon/instance/builder_test.go +++ b/builder/amazon/instance/builder_test.go @@ -47,7 +47,7 @@ func TestBuilderPrepare_AccountId(t *testing.T) { defer tempfile.Close() config["account_id"] = "" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -56,7 +56,7 @@ func TestBuilderPrepare_AccountId(t *testing.T) { } config["account_id"] = "foo" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -65,7 +65,7 @@ func TestBuilderPrepare_AccountId(t *testing.T) { } config["account_id"] = "0123-0456-7890" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -87,7 +87,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test good config["ami_name"] = "foo" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -98,7 +98,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test bad config["ami_name"] = "foo {{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -109,7 +109,7 @@ func TestBuilderPrepare_AMIName(t *testing.T) { // Test bad delete(config, "ami_name") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -126,7 +126,7 @@ func TestBuilderPrepare_BundleDestination(t *testing.T) { defer tempfile.Close() config["bundle_destination"] = "" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -146,7 +146,7 @@ func TestBuilderPrepare_BundlePrefix(t *testing.T) { defer os.Remove(tempfile.Name()) defer tempfile.Close() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -167,7 +167,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -184,7 +184,7 @@ func TestBuilderPrepare_S3Bucket(t *testing.T) { defer tempfile.Close() config["s3_bucket"] = "" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -193,7 +193,7 @@ func TestBuilderPrepare_S3Bucket(t *testing.T) { } config["s3_bucket"] = "foo" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -210,7 +210,7 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) { defer tempfile.Close() config["x509_cert_path"] = "" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -219,7 +219,7 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) { } config["x509_cert_path"] = "i/am/a/file/that/doesnt/exist" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -235,7 +235,7 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) { defer tf.Close() config["x509_cert_path"] = tf.Name() - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -252,7 +252,7 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) { defer tempfile.Close() config["x509_key_path"] = "" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -261,7 +261,7 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) { } config["x509_key_path"] = "i/am/a/file/that/doesnt/exist" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -277,7 +277,7 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) { defer tf.Close() config["x509_key_path"] = tf.Name() - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -294,7 +294,7 @@ func TestBuilderPrepare_X509UploadPath(t *testing.T) { defer tempfile.Close() config["x509_upload_path"] = "" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/azure/arm/builder.go b/builder/azure/arm/builder.go index 39917f0a2..981e22e92 100644 --- a/builder/azure/arm/builder.go +++ b/builder/azure/arm/builder.go @@ -37,10 +37,10 @@ const ( func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } b.stateBag = new(multistep.BasicStateBag) @@ -48,7 +48,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.setTemplateParameters(b.stateBag) b.setImageParameters(b.stateBag) - return warnings, errs + return nil, warnings, errs } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { @@ -232,10 +232,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack NewStepValidateTemplate(azureClient, ui, &b.config, GetVirtualMachineDeployment), NewStepDeployTemplate(azureClient, ui, &b.config, deploymentName, GetVirtualMachineDeployment), NewStepGetIPAddress(azureClient, ui, endpointConnectType), - &StepSaveWinRMPassword{ - Password: b.config.tmpAdminPassword, - BuildName: b.config.PackerBuildName, - }, &communicator.StepConnectWinRM{ Config: &b.config.Comm, Host: func(stateBag multistep.StateBag) (string, error) { diff --git a/builder/azure/arm/builder_test.go b/builder/azure/arm/builder_test.go index d22a49314..547a0c18a 100644 --- a/builder/azure/arm/builder_test.go +++ b/builder/azure/arm/builder_test.go @@ -8,7 +8,7 @@ import ( func TestStateBagShouldBePopulatedExpectedValues(t *testing.T) { var testSubject Builder - _, err := testSubject.Prepare(getArmBuilderConfiguration(), getPackerConfiguration()) + _, _, err := testSubject.Prepare(getArmBuilderConfiguration(), getPackerConfiguration()) if err != nil { t.Fatalf("failed to prepare: %s", err) } diff --git a/builder/azure/arm/config.go b/builder/azure/arm/config.go index 271ff967c..0f4b49a51 100644 --- a/builder/azure/arm/config.go +++ b/builder/azure/arm/config.go @@ -27,7 +27,6 @@ import ( "github.com/hashicorp/packer/builder/azure/common/constants" "github.com/hashicorp/packer/builder/azure/pkcs12" "github.com/hashicorp/packer/common" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" @@ -598,7 +597,6 @@ func setRuntimeValues(c *Config) { c.tmpAdminPassword = tempName.AdminPassword // store so that we can access this later during provisioning - commonhelper.SetSharedState("winrm_password", c.tmpAdminPassword, c.PackerConfig.PackerBuildName) packer.LogSecretFilter.Set(c.tmpAdminPassword) c.tmpCertificatePassword = tempName.CertificatePassword diff --git a/builder/azure/arm/step_save_winrm_password.go b/builder/azure/arm/step_save_winrm_password.go deleted file mode 100644 index c23c6b26b..000000000 --- a/builder/azure/arm/step_save_winrm_password.go +++ /dev/null @@ -1,25 +0,0 @@ -package arm - -import ( - "context" - - commonhelper "github.com/hashicorp/packer/helper/common" - "github.com/hashicorp/packer/helper/multistep" - "github.com/hashicorp/packer/packer" -) - -type StepSaveWinRMPassword struct { - Password string - BuildName string -} - -func (s *StepSaveWinRMPassword) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - // store so that we can access this later during provisioning - commonhelper.SetSharedState("winrm_password", s.Password, s.BuildName) - packer.LogSecretFilter.Set(s.Password) - return multistep.ActionContinue -} - -func (s *StepSaveWinRMPassword) Cleanup(multistep.StateBag) { - commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName) -} diff --git a/builder/azure/chroot/builder.go b/builder/azure/chroot/builder.go index 8cf4ba205..bc35cea7a 100644 --- a/builder/azure/chroot/builder.go +++ b/builder/azure/chroot/builder.go @@ -120,7 +120,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = azcommon.TemplateFuncs b.config.ctx.Funcs["vm"] = CreateVMMetadataTemplateFunc() err := config.Decode(&b.config, &config.DecodeOpts{ @@ -138,7 +138,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } var errs *packer.MultiError @@ -147,7 +147,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { // Defaults err = b.config.ClientConfig.SetDefaultValues() if err != nil { - return nil, err + return nil, nil, err } if b.config.ChrootMounts == nil { @@ -258,11 +258,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil { - return warns, errs + return nil, warns, errs } packer.LogSecretFilter.Set(b.config.ClientConfig.ClientSecret, b.config.ClientConfig.ClientJWT) - return warns, nil + return nil, warns, nil } func checkDiskCacheType(s string) interface{} { diff --git a/builder/azure/chroot/builder_test.go b/builder/azure/chroot/builder_test.go index dd40f7737..f84dd9ccc 100644 --- a/builder/azure/chroot/builder_test.go +++ b/builder/azure/chroot/builder_test.go @@ -55,7 +55,7 @@ func TestBuilder_Prepare(t *testing.T) { t.Run(tt.name, func(t *testing.T) { b := &Builder{} - _, err := b.Prepare(tt.config) + _, _, err := b.Prepare(tt.config) if (err != nil) != tt.wantErr { t.Errorf("Builder.Prepare() error = %v, wantErr %v", err, tt.wantErr) diff --git a/builder/cloudstack/builder.go b/builder/cloudstack/builder.go index ae18e93bc..9a92a41da 100644 --- a/builder/cloudstack/builder.go +++ b/builder/cloudstack/builder.go @@ -23,13 +23,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { errs := b.config.Prepare(raws...) if errs != nil { - return nil, errs + return nil, nil, errs } - return nil, nil + return nil, nil, nil } // Run implements the packer.Builder interface. diff --git a/builder/cloudstack/builder_test.go b/builder/cloudstack/builder_test.go index 158ff5d0b..e6b94a4c0 100644 --- a/builder/cloudstack/builder_test.go +++ b/builder/cloudstack/builder_test.go @@ -41,7 +41,7 @@ func TestBuilder_Prepare(t *testing.T) { } for desc, tc := range cases { - _, errs := (&Builder{}).Prepare(tc.Config) + _, _, errs := (&Builder{}).Prepare(tc.Config) if tc.Err { if errs == nil { diff --git a/builder/digitalocean/builder.go b/builder/digitalocean/builder.go index 0812f3c78..8dc6fdec1 100644 --- a/builder/digitalocean/builder.go +++ b/builder/digitalocean/builder.go @@ -28,13 +28,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/digitalocean/builder_test.go b/builder/digitalocean/builder_test.go index 70ec6fea9..5113495cf 100644 --- a/builder/digitalocean/builder_test.go +++ b/builder/digitalocean/builder_test.go @@ -32,7 +32,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "api_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -47,7 +47,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -62,7 +62,7 @@ func TestBuilderPrepare_Region(t *testing.T) { // Test default delete(config, "region") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -75,7 +75,7 @@ func TestBuilderPrepare_Region(t *testing.T) { // Test set config["region"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -94,7 +94,7 @@ func TestBuilderPrepare_Size(t *testing.T) { // Test default delete(config, "size") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -107,7 +107,7 @@ func TestBuilderPrepare_Size(t *testing.T) { // Test set config["size"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -126,7 +126,7 @@ func TestBuilderPrepare_Image(t *testing.T) { // Test default delete(config, "image") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -139,7 +139,7 @@ func TestBuilderPrepare_Image(t *testing.T) { // Test set config["image"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -157,7 +157,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) { config := testConfig() // Test default - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -172,7 +172,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) { // Test set config["state_timeout"] = "5m" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -183,7 +183,7 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) { // Test bad config["state_timeout"] = "tubes" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -197,7 +197,7 @@ func TestBuilderPrepare_SnapshotTimeout(t *testing.T) { config := testConfig() // Test default - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -212,7 +212,7 @@ func TestBuilderPrepare_SnapshotTimeout(t *testing.T) { // Test set config["snapshot_timeout"] = "15m" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -223,7 +223,7 @@ func TestBuilderPrepare_SnapshotTimeout(t *testing.T) { // Test bad config["snapshot_timeout"] = "badstring" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -237,7 +237,7 @@ func TestBuilderPrepare_PrivateNetworking(t *testing.T) { config := testConfig() // Test default - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -252,7 +252,7 @@ func TestBuilderPrepare_PrivateNetworking(t *testing.T) { // Test set config["private_networking"] = true b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -270,7 +270,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) { config := testConfig() // Test default - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -285,7 +285,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) { // Test set config["snapshot_name"] = "foobarbaz" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -296,7 +296,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) { // Test set with template config["snapshot_name"] = "{{timestamp}}" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -316,7 +316,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) { config := testConfig() // Test default - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -331,7 +331,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) { // Test normal set config["droplet_name"] = "foobar" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -342,7 +342,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) { // Test with template config["droplet_name"] = "foobar-{{timestamp}}" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -353,7 +353,7 @@ func TestBuilderPrepare_DropletName(t *testing.T) { // Test with bad template config["droplet_name"] = "foobar-{{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/digitalocean/step_create_droplet.go b/builder/digitalocean/step_create_droplet.go index a64325d35..d3a54c955 100644 --- a/builder/digitalocean/step_create_droplet.go +++ b/builder/digitalocean/step_create_droplet.go @@ -63,6 +63,9 @@ func (s *stepCreateDroplet) Run(ctx context.Context, state multistep.StateBag) m // Store the droplet id for later state.Put("droplet_id", droplet.ID) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", droplet.ID) return multistep.ActionContinue } diff --git a/builder/docker/builder.go b/builder/docker/builder.go index 470fa0f6e..706740e45 100644 --- a/builder/docker/builder.go +++ b/builder/docker/builder.go @@ -23,13 +23,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/docker/communicator_test.go b/builder/docker/communicator_test.go index b028d367a..afaa5e60f 100644 --- a/builder/docker/communicator_test.go +++ b/builder/docker/communicator_test.go @@ -35,7 +35,7 @@ func TestUploadDownload(t *testing.T) { // Setup the builder builder := &Builder{} - warnings, err := builder.Prepare(tpl.Builders["docker"].Config) + _, warnings, err := builder.Prepare(tpl.Builders["docker"].Config) if err != nil { t.Fatalf("Error preparing configuration %s", err) } @@ -118,7 +118,7 @@ func TestLargeDownload(t *testing.T) { // Setup the builder builder := &Builder{} - warnings, err := builder.Prepare(tpl.Builders["docker"].Config) + _, warnings, err := builder.Prepare(tpl.Builders["docker"].Config) if err != nil { t.Fatalf("Error preparing configuration %s", err) } @@ -222,7 +222,7 @@ func TestFixUploadOwner(t *testing.T) { // Setup the builder builder := &Builder{} - warnings, err := builder.Prepare(tpl.Builders["docker"].Config) + _, warnings, err := builder.Prepare(tpl.Builders["docker"].Config) if err != nil { t.Fatalf("Error preparing configuration %s", err) } diff --git a/builder/docker/step_run.go b/builder/docker/step_run.go index 281505104..bdd8e7dcd 100644 --- a/builder/docker/step_run.go +++ b/builder/docker/step_run.go @@ -42,6 +42,9 @@ func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.S // Save the container ID s.containerId = containerId state.Put("container_id", s.containerId) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.containerId) ui.Message(fmt.Sprintf("Container ID: %s", s.containerId)) return multistep.ActionContinue } diff --git a/builder/file/builder.go b/builder/file/builder.go index 4178e6f1c..e2756b141 100644 --- a/builder/file/builder.go +++ b/builder/file/builder.go @@ -26,13 +26,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run is where the actual build should take place. It takes a Build and a Ui. diff --git a/builder/googlecompute/builder.go b/builder/googlecompute/builder.go index 163cc9d2c..0d31530f4 100644 --- a/builder/googlecompute/builder.go +++ b/builder/googlecompute/builder.go @@ -25,12 +25,12 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a googlecompute Packer build and returns a packer.Artifact diff --git a/builder/googlecompute/step_create_instance.go b/builder/googlecompute/step_create_instance.go index ca15eeccb..088c88925 100644 --- a/builder/googlecompute/step_create_instance.go +++ b/builder/googlecompute/step_create_instance.go @@ -176,6 +176,9 @@ func (s *StepCreateInstance) Run(ctx context.Context, state multistep.StateBag) // Things succeeded, store the name so we can remove it later state.Put("instance_name", name) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", name) return multistep.ActionContinue } diff --git a/builder/googlecompute/step_create_windows_password.go b/builder/googlecompute/step_create_windows_password.go index 2112b843c..8ac19f068 100644 --- a/builder/googlecompute/step_create_windows_password.go +++ b/builder/googlecompute/step_create_windows_password.go @@ -13,7 +13,6 @@ import ( "os" "time" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) @@ -119,7 +118,6 @@ func (s *StepCreateWindowsPassword) Run(ctx context.Context, state multistep.Sta } state.Put("winrm_password", data.password) - commonhelper.SetSharedState("winrm_password", data.password, c.PackerConfig.PackerBuildName) packer.LogSecretFilter.Set(data.password) return multistep.ActionContinue diff --git a/builder/hcloud/builder.go b/builder/hcloud/builder.go index efd29adc9..e360149df 100644 --- a/builder/hcloud/builder.go +++ b/builder/hcloud/builder.go @@ -25,12 +25,13 @@ var pluginVersion = "1.0.0" func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return nil, nil + + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/hcloud/step_create_server.go b/builder/hcloud/step_create_server.go index c5c38b9ad..f0d2f863a 100644 --- a/builder/hcloud/step_create_server.go +++ b/builder/hcloud/step_create_server.go @@ -85,6 +85,9 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu // Store the server id for later state.Put("server_id", serverCreateResult.Server.ID) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", serverCreateResult.Server.ID) if err := waitForAction(ctx, client, serverCreateResult.Action); err != nil { err := fmt.Errorf("Error creating server: %s", err) diff --git a/builder/hyperone/builder.go b/builder/hyperone/builder.go index 93c0b84c4..e4b1bee2a 100644 --- a/builder/hyperone/builder.go +++ b/builder/hyperone/builder.go @@ -23,10 +23,10 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } cfg := openapi.NewConfiguration() @@ -44,7 +44,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.client = openapi.NewAPIClient(cfg) - return nil, nil + return nil, nil, nil } type wrappedCommandTemplate struct { diff --git a/builder/hyperone/step_create_vm.go b/builder/hyperone/step_create_vm.go index 155f383a0..58c1dfbc0 100644 --- a/builder/hyperone/step_create_vm.go +++ b/builder/hyperone/step_create_vm.go @@ -67,6 +67,9 @@ func (s *stepCreateVM) Run(ctx context.Context, state multistep.StateBag) multis s.vmID = vm.Id state.Put("vm_id", vm.Id) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", vm.Id) hdds, _, err := client.VmApi.VmListHdd(ctx, vm.Id) if err != nil { diff --git a/builder/hyperv/common/step_clone_vm.go b/builder/hyperv/common/step_clone_vm.go index 20d40abfe..5213574e1 100644 --- a/builder/hyperv/common/step_clone_vm.go +++ b/builder/hyperv/common/step_clone_vm.go @@ -154,6 +154,9 @@ func (s *StepCloneVM) Run(ctx context.Context, state multistep.StateBag) multist // Set the final name in the state bag so others can use it state.Put("vmName", s.VMName) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.VMName) return multistep.ActionContinue } diff --git a/builder/hyperv/common/step_create_vm.go b/builder/hyperv/common/step_create_vm.go index f9a05f797..920edfa45 100644 --- a/builder/hyperv/common/step_create_vm.go +++ b/builder/hyperv/common/step_create_vm.go @@ -166,6 +166,9 @@ func (s *StepCreateVM) Run(ctx context.Context, state multistep.StateBag) multis // Set the final name in the state bag so others can use it state.Put("vmName", s.VMName) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.VMName) return multistep.ActionContinue } diff --git a/builder/hyperv/iso/builder.go b/builder/hyperv/iso/builder.go index 193cce388..34079364c 100644 --- a/builder/hyperv/iso/builder.go +++ b/builder/hyperv/iso/builder.go @@ -87,7 +87,7 @@ type Config struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -98,7 +98,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors and warnings @@ -166,10 +166,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a Packer build and returns a packer.Artifact representing diff --git a/builder/hyperv/iso/builder_test.go b/builder/hyperv/iso/builder_test.go index 640221de2..b3c4736f3 100644 --- a/builder/hyperv/iso/builder_test.go +++ b/builder/hyperv/iso/builder_test.go @@ -42,7 +42,7 @@ func TestBuilderPrepare_Defaults(t *testing.T) { var b Builder config := testConfig() - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -60,7 +60,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config := testConfig() delete(config, "disk_size") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -74,7 +74,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config["disk_size"] = 256 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -96,7 +96,7 @@ func TestBuilderPrepare_DiskBlockSize(t *testing.T) { // Test default with empty disk_block_size delete(config, "disk_block_size") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -112,7 +112,7 @@ func TestBuilderPrepare_DiskBlockSize(t *testing.T) { for _, test_size := range test_sizes { config["disk_block_size"] = test_size b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if test_size > expected_max_block_size || test_size < expected_min_block_size { if len(warns) > 0 { t.Fatalf("bad, should have no warns: %#v", warns) @@ -153,7 +153,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) { // use_fixed_vhd_format should work with generation = 1, skip_compaction // = true, and differencing_disk = false - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -164,7 +164,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) { //use_fixed_vhd_format should not work with differencing_disk = true config["differencing_disk"] = true b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -176,7 +176,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) { //use_fixed_vhd_format should not work with skip_compaction = false config["skip_compaction"] = false b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -188,7 +188,7 @@ func TestBuilderPrepare_FixedVHDFormat(t *testing.T) { //use_fixed_vhd_format should not work with generation = 2 config["generation"] = 2 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -202,7 +202,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { config := testConfig() delete(config, "floppy_files") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -217,7 +217,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { floppiesPath := "../../../common/test-fixtures/floppies" config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppiesPath), fmt.Sprintf("%s/foo.ps1", floppiesPath)} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -236,7 +236,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) { config := testConfig() config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} b = Builder{} - _, errs := b.Prepare(config) + _, _, errs := b.Prepare(config) if errs == nil { t.Fatalf("Nonexistent floppies should trigger multierror") } @@ -252,7 +252,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -267,7 +267,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) { // Test bad config["iso_checksum"] = "" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -278,7 +278,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) { // Test good config["iso_checksum"] = "FOo" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -294,7 +294,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { // Test bad config["iso_checksum_type"] = "" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -305,7 +305,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { // Test good config["iso_checksum_type"] = "mD5" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -320,7 +320,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { // Test unknown config["iso_checksum_type"] = "fake" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -331,7 +331,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { // Test none config["iso_checksum_type"] = "none" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) == 0 { t.Fatalf("bad: %#v", warns) } @@ -353,7 +353,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { // Test both empty config["iso_url"] = "" b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -364,7 +364,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { // Test iso_url set config["iso_url"] = "http://www.packer.io" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -381,7 +381,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { config["iso_url"] = "http://www.packer.io" config["iso_urls"] = []string{"http://www.packer.io"} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -397,7 +397,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { } b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -431,7 +431,7 @@ func TestBuilderPrepare_SizeNotRequiredWhenUsingExistingHarddrive(t *testing.T) } b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -455,7 +455,7 @@ func TestBuilderPrepare_SizeNotRequiredWhenUsingExistingHarddrive(t *testing.T) } b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -489,7 +489,7 @@ func TestBuilderPrepare_SizeIsRequiredWhenNotUsingExistingHarddrive(t *testing.T } b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -517,7 +517,7 @@ func TestBuilderPrepare_MaximumOfSixtyFourAdditionalDisks(t *testing.T) { config["disk_additional_size"] = disks b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -537,7 +537,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) { config["winrm_host"] = "1.2.3.4" var b Builder - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -565,7 +565,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) { config["ssh_host"] = "1.2.3.4" var b Builder - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -593,7 +593,7 @@ func TestUserVariablesInBootCommand(t *testing.T) { config[packer.UserVariablesConfigKey] = map[string]string{"test-variable": "test"} config["boot_command"] = []string{"blah {{user `test-variable`}} blah"} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -634,7 +634,7 @@ func TestBuilderPrepare_UseLegacyNetworkAdapter(t *testing.T) { config["use_legacy_network_adapter"] = true b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -646,7 +646,7 @@ func TestBuilderPrepare_UseLegacyNetworkAdapter(t *testing.T) { config["generation"] = 2 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } diff --git a/builder/hyperv/vmcx/builder.go b/builder/hyperv/vmcx/builder.go index 3ab84a6f2..c7adee1b1 100644 --- a/builder/hyperv/vmcx/builder.go +++ b/builder/hyperv/vmcx/builder.go @@ -80,7 +80,7 @@ type Config struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -91,7 +91,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors and warnings @@ -206,10 +206,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a Packer build and returns a packer.Artifact representing diff --git a/builder/hyperv/vmcx/builder_test.go b/builder/hyperv/vmcx/builder_test.go index 9f268aab4..2fa7ba3cf 100644 --- a/builder/hyperv/vmcx/builder_test.go +++ b/builder/hyperv/vmcx/builder_test.go @@ -49,7 +49,7 @@ func TestBuilderPrepare_Defaults(t *testing.T) { defer os.RemoveAll(td) config["clone_from_vmcx_path"] = td - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -76,7 +76,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -90,7 +90,7 @@ func TestBuilderPrepare_CloneFromExistingMachineOrImportFromExportedMachineSetti config := testConfig() delete(config, "clone_from_vmcx_path") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -114,7 +114,7 @@ func TestBuilderPrepare_ExportedMachinePathDoesNotExist(t *testing.T) { config["clone_from_vmcx_path"] = td - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -138,7 +138,7 @@ func TestBuilderPrepare_ExportedMachinePathExists(t *testing.T) { config["clone_from_vmcx_path"] = td - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -154,7 +154,7 @@ func disabled_TestBuilderPrepare_CloneFromVmSettingUsedSoNoCloneFromVmcxPathRequ config["clone_from_vm_name"] = "test_machine_name_that_does_not_exist" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -184,7 +184,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) { // Test bad config["iso_checksum"] = "" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -195,7 +195,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) { // Test good config["iso_checksum"] = "FOo" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -219,7 +219,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { // Test bad config["iso_checksum_type"] = "" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -230,7 +230,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { // Test good config["iso_checksum_type"] = "mD5" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -245,7 +245,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { // Test none config["iso_checksum_type"] = "none" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) == 0 { t.Fatalf("bad: %#v", warns) } @@ -276,7 +276,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { // Test both empty (should be allowed, as we cloning a vm so we probably don't need an ISO file) config["iso_url"] = "" b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -287,7 +287,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { // Test iso_url set config["iso_url"] = "http://www.packer.io" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -304,7 +304,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { config["iso_url"] = "http://www.packer.io" config["iso_urls"] = []string{"http://www.packer.io"} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -320,7 +320,7 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { } b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -350,7 +350,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { config["clone_from_vmcx_path"] = td delete(config, "floppy_files") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -365,7 +365,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { floppies_path := "../../../common/test-fixtures/floppies" config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -393,7 +393,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) { config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} b = Builder{} - _, errs := b.Prepare(config) + _, _, errs := b.Prepare(config) if errs == nil { t.Fatalf("Nonexistent floppies should trigger multierror") } @@ -422,7 +422,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) { config["winrm_host"] = "1.2.3.4" var b Builder - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -459,7 +459,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) { config["ssh_host"] = "1.2.3.4" var b Builder - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -494,7 +494,7 @@ func TestUserVariablesInBootCommand(t *testing.T) { config[packer.UserVariablesConfigKey] = map[string]string{"test-variable": "test"} config["boot_command"] = []string{"blah {{user `test-variable`}} blah"} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } diff --git a/builder/jdcloud/builder.go b/builder/jdcloud/builder.go index 2115827b4..3e385d081 100644 --- a/builder/jdcloud/builder.go +++ b/builder/jdcloud/builder.go @@ -15,7 +15,7 @@ import ( func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -26,19 +26,19 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, fmt.Errorf("[ERROR] Failed in decoding JSON->mapstructure") + return nil, nil, fmt.Errorf("[ERROR] Failed in decoding JSON->mapstructure") } errs := &packer.MultiError{} errs = packer.MultiErrorAppend(errs, b.config.JDCloudCredentialConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.JDCloudInstanceSpecConfig.Prepare(&b.config.ctx)...) if errs != nil && len(errs.Errors) != 0 { - return nil, errs + return nil, nil, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey) - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/jdcloud/step_create_instance.go b/builder/jdcloud/step_create_instance.go index 950f360d4..353c7304d 100644 --- a/builder/jdcloud/step_create_instance.go +++ b/builder/jdcloud/step_create_instance.go @@ -97,6 +97,9 @@ func (s *stepCreateJDCloudInstance) Run(_ context.Context, state multistep.State "Hi, we have created the instance, its name=%v , "+ "its id=%v, "+ "and its eip=%v :) ", instance.InstanceName, s.InstanceSpecConfig.InstanceId, eip.Result.ElasticIp.ElasticIpAddress)) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.InstanceSpecConfig.InstanceId) return multistep.ActionContinue } diff --git a/builder/linode/builder.go b/builder/linode/builder.go index 65a6c30c5..95504219f 100644 --- a/builder/linode/builder.go +++ b/builder/linode/builder.go @@ -28,12 +28,12 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (ret packer.Artifact, err error) { diff --git a/builder/linode/builder_test.go b/builder/linode/builder_test.go index c80d1c76c..8176114a4 100644 --- a/builder/linode/builder_test.go +++ b/builder/linode/builder_test.go @@ -31,7 +31,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "linode_token": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -61,7 +61,7 @@ func TestBuilderPrepare_Region(t *testing.T) { // Test default delete(config, "region") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -74,7 +74,7 @@ func TestBuilderPrepare_Region(t *testing.T) { // Test set config["region"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -93,7 +93,7 @@ func TestBuilderPrepare_Size(t *testing.T) { // Test default delete(config, "instance_type") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -106,7 +106,7 @@ func TestBuilderPrepare_Size(t *testing.T) { // Test set config["instance_type"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -125,7 +125,7 @@ func TestBuilderPrepare_Image(t *testing.T) { // Test default delete(config, "image") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -138,7 +138,7 @@ func TestBuilderPrepare_Image(t *testing.T) { // Test set config["image"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -156,7 +156,7 @@ func TestBuilderPrepare_ImageLabel(t *testing.T) { config := testConfig() // Test default - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -171,7 +171,7 @@ func TestBuilderPrepare_ImageLabel(t *testing.T) { // Test set config["image_label"] = "foobarbaz" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -182,7 +182,7 @@ func TestBuilderPrepare_ImageLabel(t *testing.T) { // Test set with template config["image_label"] = "{{timestamp}}" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -202,7 +202,7 @@ func TestBuilderPrepare_Label(t *testing.T) { config := testConfig() // Test default - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -217,7 +217,7 @@ func TestBuilderPrepare_Label(t *testing.T) { // Test normal set config["instance_label"] = "foobar" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -228,7 +228,7 @@ func TestBuilderPrepare_Label(t *testing.T) { // Test with template config["instance_label"] = "foobar-{{timestamp}}" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -239,7 +239,7 @@ func TestBuilderPrepare_Label(t *testing.T) { // Test with bad template config["instance_label"] = "foobar-{{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/linode/step_create_linode.go b/builder/linode/step_create_linode.go index ca15facfd..90dc6342a 100644 --- a/builder/linode/step_create_linode.go +++ b/builder/linode/step_create_linode.go @@ -49,6 +49,9 @@ func (s *stepCreateLinode) Run(ctx context.Context, state multistep.StateBag) mu return multistep.ActionHalt } state.Put("instance", instance) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", instance.ID) } disk, err := s.findDisk(ctx, instance.ID) diff --git a/builder/lxc/builder.go b/builder/lxc/builder.go index 54044ebc0..9c628b4b1 100644 --- a/builder/lxc/builder.go +++ b/builder/lxc/builder.go @@ -26,13 +26,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { errs := b.config.Prepare(raws...) if errs != nil { - return nil, errs + return nil, nil, errs } - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/lxc/builder_test.go b/builder/lxc/builder_test.go index 4eeb27594..20108202d 100644 --- a/builder/lxc/builder_test.go +++ b/builder/lxc/builder_test.go @@ -25,7 +25,7 @@ func TestBuilderPrepare_ConfigFile(t *testing.T) { var b Builder // Good config := testConfig() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -37,7 +37,7 @@ func TestBuilderPrepare_ConfigFile(t *testing.T) { config = testConfig() delete(config, "config_file") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/lxd/builder.go b/builder/lxd/builder.go index 9312dd158..f3b3f3e57 100644 --- a/builder/lxd/builder.go +++ b/builder/lxd/builder.go @@ -24,13 +24,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { errs := b.config.Prepare(raws...) if errs != nil { - return nil, errs + return nil, nil, errs } - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/lxd/builder_test.go b/builder/lxd/builder_test.go index b2ea70e55..a2277932c 100644 --- a/builder/lxd/builder_test.go +++ b/builder/lxd/builder_test.go @@ -24,7 +24,7 @@ func TestBuilderPrepare_ConfigFile(t *testing.T) { var b Builder // Good config := testConfig() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -35,7 +35,7 @@ func TestBuilderPrepare_ConfigFile(t *testing.T) { // Good, remote image config = testConfig() config["image"] = "remote:bar" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -46,7 +46,7 @@ func TestBuilderPrepare_ConfigFile(t *testing.T) { // Good, remote output image config = testConfig() config["output_image"] = "remote:foo" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -58,7 +58,7 @@ func TestBuilderPrepare_ConfigFile(t *testing.T) { config = testConfig() delete(config, "image") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/ncloud/builder.go b/builder/ncloud/builder.go index 45c616e92..4df0ed8d4 100644 --- a/builder/ncloud/builder.go +++ b/builder/ncloud/builder.go @@ -20,15 +20,15 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } b.stateBag = new(multistep.BasicStateBag) - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/ncloud/step_create_public_ip_instance.go b/builder/ncloud/step_create_public_ip_instance.go index 39c31966c..e4550e6ef 100644 --- a/builder/ncloud/step_create_public_ip_instance.go +++ b/builder/ncloud/step_create_public_ip_instance.go @@ -97,6 +97,9 @@ func (s *StepCreatePublicIPInstance) Run(ctx context.Context, state multistep.St if err == nil { state.Put("PublicIP", publicIPInstance.PublicIP) state.Put("PublicIPInstance", publicIPInstance) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", publicIPInstance) } return processStepResult(err, s.Error, state) diff --git a/builder/ncloud/step_create_server_instance.go b/builder/ncloud/step_create_server_instance.go index 2a72789f6..49648cbb0 100644 --- a/builder/ncloud/step_create_server_instance.go +++ b/builder/ncloud/step_create_server_instance.go @@ -96,6 +96,9 @@ func (s *StepCreateServerInstance) Run(ctx context.Context, state multistep.Stat serverInstanceNo, err := s.CreateServerInstance(loginKey.KeyName, zoneNo, feeSystemTypeCode) if err == nil { state.Put("InstanceNo", serverInstanceNo) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", serverInstanceNo) } return processStepResult(err, s.Error, state) diff --git a/builder/null/builder.go b/builder/null/builder.go index d6d2f1c70..3ad24150e 100644 --- a/builder/null/builder.go +++ b/builder/null/builder.go @@ -19,13 +19,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/oneandone/builder.go b/builder/oneandone/builder.go index 759f9bd00..d30b930b8 100644 --- a/builder/oneandone/builder.go +++ b/builder/oneandone/builder.go @@ -21,13 +21,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/oneandone/builder_test.go b/builder/oneandone/builder_test.go index daa8536e3..46045bf9d 100644 --- a/builder/oneandone/builder_test.go +++ b/builder/oneandone/builder_test.go @@ -30,7 +30,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "api_key": []string{}, } - warns, err := b.Prepare(c) + _, warns, err := b.Prepare(c) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { config := testConfig() config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/oneandone/step_create_server.go b/builder/oneandone/step_create_server.go index 1fc9863aa..6d70db862 100644 --- a/builder/oneandone/step_create_server.go +++ b/builder/oneandone/step_create_server.go @@ -94,6 +94,9 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu } state.Put("server_id", server_id) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", server_id) state.Put("server_ip", server.Ips[0].Ip) diff --git a/builder/openstack/builder.go b/builder/openstack/builder.go index ca4c31e5a..57ede0103 100644 --- a/builder/openstack/builder.go +++ b/builder/openstack/builder.go @@ -38,13 +38,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors @@ -54,11 +54,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } if b.config.ImageConfig.ImageDiskFormat != "" && !b.config.RunConfig.UseBlockStorageVolume { - return nil, fmt.Errorf("use_blockstorage_volume must be true if image_disk_format is specified.") + return nil, nil, fmt.Errorf("use_blockstorage_volume must be true if image_disk_format is specified.") } // By default, instance name is same as image name @@ -67,7 +67,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } packer.LogSecretFilter.Set(b.config.Password) - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/openstack/builder_test.go b/builder/openstack/builder_test.go index 5fa296d30..0a9ac3288 100644 --- a/builder/openstack/builder_test.go +++ b/builder/openstack/builder_test.go @@ -20,7 +20,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "password": []string{}, } - warns, err := b.Prepare(c) + _, warns, err := b.Prepare(c) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } diff --git a/builder/openstack/step_get_password.go b/builder/openstack/step_get_password.go index c97bc4944..fd9bfa156 100644 --- a/builder/openstack/step_get_password.go +++ b/builder/openstack/step_get_password.go @@ -8,7 +8,6 @@ import ( "time" "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -78,12 +77,9 @@ func (s *StepGetPassword) Run(ctx context.Context, state multistep.StateBag) mul "Password (since debug is enabled) \"%s\"", s.Comm.WinRMPassword)) } - commonhelper.SetSharedState("winrm_password", s.Comm.WinRMPassword, s.BuildName) packer.LogSecretFilter.Set(s.Comm.WinRMPassword) return multistep.ActionContinue } -func (s *StepGetPassword) Cleanup(multistep.StateBag) { - commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName) -} +func (s *StepGetPassword) Cleanup(multistep.StateBag) {} diff --git a/builder/openstack/step_run_source_server.go b/builder/openstack/step_run_source_server.go index 3c3bdff1b..59cf63afe 100644 --- a/builder/openstack/step_run_source_server.go +++ b/builder/openstack/step_run_source_server.go @@ -128,6 +128,9 @@ func (s *StepRunSourceServer) Run(ctx context.Context, state multistep.StateBag) s.server = latestServer.(*servers.Server) state.Put("server", s.server) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.server.ID) return multistep.ActionContinue } diff --git a/builder/oracle/classic/builder.go b/builder/oracle/classic/builder.go index e91717c75..921150d98 100644 --- a/builder/oracle/classic/builder.go +++ b/builder/oracle/classic/builder.go @@ -29,10 +29,10 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := b.config.Prepare(raws...) if err != nil { - return nil, err + return nil, nil, err } var errs *packer.MultiError @@ -40,9 +40,9 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.PVConfig.Prepare(&b.config.ctx)) if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/oracle/oci/builder.go b/builder/oracle/oci/builder.go index 5b0922018..255fc5808 100644 --- a/builder/oracle/oci/builder.go +++ b/builder/oracle/oci/builder.go @@ -29,13 +29,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := b.config.Prepare(raws...) if err != nil { - return nil, err + return nil, nil, err } - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/oracle/oci/step_get_default_credentials.go b/builder/oracle/oci/step_get_default_credentials.go index 1f4ea20b3..0ed44b7f6 100644 --- a/builder/oracle/oci/step_get_default_credentials.go +++ b/builder/oracle/oci/step_get_default_credentials.go @@ -5,7 +5,6 @@ import ( "fmt" "log" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -52,7 +51,7 @@ func (s *stepGetDefaultCredentials) Run(ctx context.Context, state multistep.Sta } // store so that we can access this later during provisioning - commonhelper.SetSharedState("winrm_password", s.Comm.WinRMPassword, s.BuildName) + state.Put("winrm_password", s.Comm.WinRMPassword) packer.LogSecretFilter.Set(s.Comm.WinRMPassword) return multistep.ActionContinue } diff --git a/builder/osc/bsu/builder.go b/builder/osc/bsu/builder.go index bc93a7a58..dc7ce678c 100644 --- a/builder/osc/bsu/builder.go +++ b/builder/osc/bsu/builder.go @@ -45,7 +45,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = osccommon.TemplateFuncs err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, @@ -62,7 +62,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } if b.config.PackerConfig.PackerForce { @@ -78,11 +78,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/osc/bsu/builder_test.go b/builder/osc/bsu/builder_test.go index 1736044df..c700ccc06 100644 --- a/builder/osc/bsu/builder_test.go +++ b/builder/osc/bsu/builder_test.go @@ -32,7 +32,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "access_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -48,7 +48,7 @@ func TestBuilderPrepare_OMIName(t *testing.T) { // Test good config["omi_name"] = "foo" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -59,7 +59,7 @@ func TestBuilderPrepare_OMIName(t *testing.T) { // Test bad config["omi_name"] = "foo {{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -70,7 +70,7 @@ func TestBuilderPrepare_OMIName(t *testing.T) { // Test bad delete(config, "omi_name") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -85,7 +85,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -101,7 +101,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "terminate" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -111,7 +111,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "stop" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -121,7 +121,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test bad config["shutdown_behavior"] = "foobar" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/osc/bsusurrogate/builder.go b/builder/osc/bsusurrogate/builder.go index 120f81413..3669c3952 100644 --- a/builder/osc/bsusurrogate/builder.go +++ b/builder/osc/bsusurrogate/builder.go @@ -44,7 +44,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = osccommon.TemplateFuncs @@ -63,7 +63,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } if b.config.PackerConfig.PackerForce { @@ -95,11 +95,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return nil, nil + return nil, nil, nil } diff --git a/builder/osc/bsuvolume/builder.go b/builder/osc/bsuvolume/builder.go index b40503f60..53101d041 100644 --- a/builder/osc/bsuvolume/builder.go +++ b/builder/osc/bsuvolume/builder.go @@ -47,7 +47,7 @@ type EngineVarsTemplate struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = osccommon.TemplateFuncs // Create passthrough for {{ .BuildRegion }} and {{ .SourceOMI }} variables // so we can fill them in later @@ -60,7 +60,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { InterpolateContext: &b.config.ctx, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors @@ -81,11 +81,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/osc/bsuvolume/builder_test.go b/builder/osc/bsuvolume/builder_test.go index 956fba60f..27c4a80c0 100644 --- a/builder/osc/bsuvolume/builder_test.go +++ b/builder/osc/bsuvolume/builder_test.go @@ -31,7 +31,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "access_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -62,7 +62,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "terminate" config["skip_region_validation"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -72,7 +72,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test good config["shutdown_behavior"] = "stop" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -82,7 +82,7 @@ func TestBuilderPrepare_InvalidShutdownBehavior(t *testing.T) { // Test bad config["shutdown_behavior"] = "foobar" - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/osc/chroot/builder.go b/builder/osc/chroot/builder.go index 939ef4f4f..a4963deb6 100644 --- a/builder/osc/chroot/builder.go +++ b/builder/osc/chroot/builder.go @@ -66,7 +66,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { b.config.ctx.Funcs = osccommon.TemplateFuncs err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, @@ -85,7 +85,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } if b.config.PackerConfig.PackerForce { @@ -181,11 +181,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warns, errs + return nil, warns, errs } packer.LogSecretFilter.Set(b.config.AccessKey, b.config.SecretKey, b.config.Token) - return warns, nil + return nil, warns, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/osc/common/step_get_password.go b/builder/osc/common/step_get_password.go index 63ebbb288..9971379d5 100644 --- a/builder/osc/common/step_get_password.go +++ b/builder/osc/common/step_get_password.go @@ -11,7 +11,6 @@ import ( "log" "time" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -95,19 +94,12 @@ WaitLoop: "Password (since debug is enabled): %s", s.Comm.WinRMPassword)) } // store so that we can access this later during provisioning - - err = commonhelper.SetSharedState("winrm_password", s.Comm.WinRMPassword, s.BuildName) - if err != nil { - log.Printf("[WARN] commonhelper.SetSharedState returned error: %s", err) - } packer.LogSecretFilter.Set(s.Comm.WinRMPassword) return multistep.ActionContinue } -func (s *StepGetPassword) Cleanup(multistep.StateBag) { - commonhelper.RemoveSharedStateFile("winrm_password", s.BuildName) -} +func (s *StepGetPassword) Cleanup(multistep.StateBag) {} func (s *StepGetPassword) waitForPassword(state multistep.StateBag, cancel <-chan struct{}) (string, error) { oapiconn := state.Get("oapi").(*oapi.Client) diff --git a/builder/osc/common/step_run_source_vm.go b/builder/osc/common/step_run_source_vm.go index 04fe1d5b3..a0f92a6a5 100644 --- a/builder/osc/common/step_run_source_vm.go +++ b/builder/osc/common/step_run_source_vm.go @@ -253,6 +253,9 @@ func (s *StepRunSourceVm) Run(ctx context.Context, state multistep.StateBag) mul } state.Put("vm", vm) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", vmId) // If we're in a region that doesn't support tagging on vm creation, // do that now. diff --git a/builder/parallels/common/step_run.go b/builder/parallels/common/step_run.go index d3d60fd1a..062312069 100644 --- a/builder/parallels/common/step_run.go +++ b/builder/parallels/common/step_run.go @@ -36,6 +36,9 @@ func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.S } s.vmName = vmName + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", vmName) return multistep.ActionContinue } diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index e5afcc2c5..31a160226 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -85,7 +85,7 @@ type Config struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -99,7 +99,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors and warnings @@ -172,10 +172,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/parallels/iso/builder_test.go b/builder/parallels/iso/builder_test.go index 88a28144e..e131bc137 100644 --- a/builder/parallels/iso/builder_test.go +++ b/builder/parallels/iso/builder_test.go @@ -32,7 +32,7 @@ func TestBuilder_ImplementsBuilder(t *testing.T) { func TestBuilderPrepare_Defaults(t *testing.T) { var b Builder config := testConfig() - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -54,7 +54,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { config := testConfig() delete(config, "floppy_files") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -69,7 +69,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { floppies_path := "../../../common/test-fixtures/floppies" config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -88,7 +88,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) { config := testConfig() config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} b = Builder{} - _, errs := b.Prepare(config) + _, _, errs := b.Prepare(config) if errs == nil { t.Fatalf("Nonexistent floppies should trigger multierror") } @@ -103,7 +103,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config := testConfig() delete(config, "disk_size") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -117,7 +117,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config["disk_size"] = 60000 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -136,7 +136,7 @@ func TestBuilderPrepare_DiskType(t *testing.T) { // Test a default disk_type delete(config, "disk_type") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -151,7 +151,7 @@ func TestBuilderPrepare_DiskType(t *testing.T) { // Test with a bad config["disk_type"] = "fake" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -163,7 +163,7 @@ func TestBuilderPrepare_DiskType(t *testing.T) { config["disk_type"] = "plain" config["skip_compaction"] = false b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) == 0 { t.Fatalf("should have warning") } @@ -175,7 +175,7 @@ func TestBuilderPrepare_DiskType(t *testing.T) { config["disk_type"] = "plain" config["skip_compaction"] = true b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -191,7 +191,7 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) { // Test a default boot_wait delete(config, "hard_drive_interface") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -206,7 +206,7 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) { // Test with a bad config["hard_drive_interface"] = "fake" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -217,7 +217,7 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) { // Test with a good config["hard_drive_interface"] = "scsi" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -232,7 +232,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } diff --git a/builder/parallels/pvm/builder.go b/builder/parallels/pvm/builder.go index 41a118eeb..b66329073 100644 --- a/builder/parallels/pvm/builder.go +++ b/builder/parallels/pvm/builder.go @@ -22,13 +22,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a Packer build and returns a packer.Artifact representing diff --git a/builder/profitbricks/builder.go b/builder/profitbricks/builder.go index 6c5cc4e61..87ff324da 100644 --- a/builder/profitbricks/builder.go +++ b/builder/profitbricks/builder.go @@ -20,13 +20,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/profitbricks/builder_test.go b/builder/profitbricks/builder_test.go index 98252b410..f16953a33 100644 --- a/builder/profitbricks/builder_test.go +++ b/builder/profitbricks/builder_test.go @@ -31,7 +31,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "api_key": []string{}, } - warns, err := b.Prepare(c) + _, warns, err := b.Prepare(c) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -47,7 +47,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { config := testConfig() config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/profitbricks/step_create_server.go b/builder/profitbricks/step_create_server.go index 3d2e44d70..b7320d6d0 100644 --- a/builder/profitbricks/step_create_server.go +++ b/builder/profitbricks/step_create_server.go @@ -147,6 +147,9 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu state.Put("volume_id", server.Entities.Volumes.Items[0].Id) server = profitbricks.GetServer(datacenter.Id, server.Id) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", server.Id) state.Put("server_ip", server.Entities.Nics.Items[0].Properties.Ips[0]) diff --git a/builder/proxmox/builder.go b/builder/proxmox/builder.go index e671e67cb..e29645114 100644 --- a/builder/proxmox/builder.go +++ b/builder/proxmox/builder.go @@ -30,13 +30,12 @@ var pluginVersion = "1.0.0" func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/proxmox/config_test.go b/builder/proxmox/config_test.go index 3fa496c3f..f925a1adb 100644 --- a/builder/proxmox/config_test.go +++ b/builder/proxmox/config_test.go @@ -82,7 +82,7 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) { } b := &Builder{} - warn, err := b.Prepare(tpl.Builders["proxmox"].Config) + _, warn, err := b.Prepare(tpl.Builders["proxmox"].Config) if err != nil { t.Fatal(err, warn) } @@ -150,7 +150,7 @@ func TestAgentSetToFalse(t *testing.T) { } b := &Builder{} - warn, err := b.Prepare(tpl.Builders["proxmox"].Config) + _, warn, err := b.Prepare(tpl.Builders["proxmox"].Config) if err != nil { t.Fatal(err, warn) } diff --git a/builder/proxmox/step_start_vm.go b/builder/proxmox/step_start_vm.go index 8020cf9db..378b689ea 100644 --- a/builder/proxmox/step_start_vm.go +++ b/builder/proxmox/step_start_vm.go @@ -76,6 +76,9 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist // Store the vm id for later state.Put("vmRef", vmRef) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", vmRef) ui.Say("Starting VM") _, err = client.StartVm(vmRef) diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index 9cb2e54e6..7b97f7d8a 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -339,7 +339,7 @@ type Config struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -351,7 +351,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } var errs *packer.MultiError @@ -572,10 +572,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/qemu/builder_test.go b/builder/qemu/builder_test.go index 4616ed3e2..4eea7174e 100644 --- a/builder/qemu/builder_test.go +++ b/builder/qemu/builder_test.go @@ -62,7 +62,7 @@ func TestBuilder_ImplementsBuilder(t *testing.T) { func TestBuilderPrepare_Defaults(t *testing.T) { var b Builder config := testConfig() - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -101,7 +101,7 @@ func TestBuilderPrepare_VNCBindAddress(t *testing.T) { // Test a default boot_wait delete(config, "vnc_bind_address") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -122,7 +122,7 @@ func TestBuilderPrepare_DiskCompaction(t *testing.T) { config["skip_compaction"] = false config["disk_compression"] = true config["format"] = "img" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -141,7 +141,7 @@ func TestBuilderPrepare_DiskCompaction(t *testing.T) { config["disk_compression"] = true config["format"] = "qcow2" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -178,7 +178,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { delete(config, "disk_size") config["disk_size"] = tc.InputSize - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -198,7 +198,7 @@ func TestBuilderPrepare_AdditionalDiskSize(t *testing.T) { config["disk_additional_size"] = []string{"1M"} config["disk_image"] = true - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -209,7 +209,7 @@ func TestBuilderPrepare_AdditionalDiskSize(t *testing.T) { delete(config, "disk_image") config["disk_additional_size"] = []string{"1M"} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -228,7 +228,7 @@ func TestBuilderPrepare_Format(t *testing.T) { // Bad config["format"] = "illegal value" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -239,7 +239,7 @@ func TestBuilderPrepare_Format(t *testing.T) { // Good config["format"] = "qcow2" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -250,7 +250,7 @@ func TestBuilderPrepare_Format(t *testing.T) { // Good config["format"] = "raw" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -269,7 +269,7 @@ func TestBuilderPrepare_UseBackingFile(t *testing.T) { config["disk_image"] = false config["format"] = "qcow2" b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -281,7 +281,7 @@ func TestBuilderPrepare_UseBackingFile(t *testing.T) { config["disk_image"] = true config["format"] = "raw" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -293,7 +293,7 @@ func TestBuilderPrepare_UseBackingFile(t *testing.T) { config["disk_image"] = true config["format"] = "qcow2" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -307,7 +307,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { config := testConfig() delete(config, "floppy_files") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -322,7 +322,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { floppies_path := "../../common/test-fixtures/floppies" config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -341,7 +341,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) { config := testConfig() config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} b = Builder{} - _, errs := b.Prepare(config) + _, _, errs := b.Prepare(config) if errs == nil { t.Fatalf("Nonexistent floppies should trigger multierror") } @@ -357,7 +357,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -379,7 +379,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) { config["output_directory"] = dir b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -390,7 +390,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) { // Test with a good one config["output_directory"] = "i-hope-i-dont-exist" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -405,7 +405,7 @@ func TestBuilderPrepare_ShutdownTimeout(t *testing.T) { // Test with a bad value config["shutdown_timeout"] = "this is not good" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -416,7 +416,7 @@ func TestBuilderPrepare_ShutdownTimeout(t *testing.T) { // Test with a good one config["shutdown_timeout"] = "5s" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -433,7 +433,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) { config["ssh_host_port_min"] = 1000 config["ssh_host_port_max"] = 500 b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -444,7 +444,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) { // Bad config["ssh_host_port_min"] = -500 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -456,7 +456,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) { config["ssh_host_port_min"] = 500 config["ssh_host_port_max"] = 1000 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -471,7 +471,7 @@ func TestBuilderPrepare_SSHPrivateKey(t *testing.T) { config["ssh_private_key_file"] = "" b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -481,7 +481,7 @@ func TestBuilderPrepare_SSHPrivateKey(t *testing.T) { config["ssh_private_key_file"] = "/i/dont/exist" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -503,7 +503,7 @@ func TestBuilderPrepare_SSHPrivateKey(t *testing.T) { config["ssh_private_key_file"] = tf.Name() b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -517,7 +517,7 @@ func TestBuilderPrepare_SSHPrivateKey(t *testing.T) { tf.Write([]byte(testPem)) config["ssh_private_key_file"] = tf.Name() b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -532,7 +532,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) { // Test a default boot_wait delete(config, "ssh_wait_timeout") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -543,7 +543,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) { // Test with a bad value config["ssh_wait_timeout"] = "this is not good" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -554,7 +554,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) { // Test with a good one config["ssh_wait_timeout"] = "5s" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -569,7 +569,7 @@ func TestBuilderPrepare_QemuArgs(t *testing.T) { // Test with empty delete(config, "qemuargs") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -587,7 +587,7 @@ func TestBuilderPrepare_QemuArgs(t *testing.T) { } b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -611,7 +611,7 @@ func TestBuilderPrepare_VNCPassword(t *testing.T) { config["vnc_use_password"] = true config["output_directory"] = "not-a-real-directory" b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } diff --git a/builder/scaleway/builder.go b/builder/scaleway/builder.go index 751de3977..6d9e7a209 100644 --- a/builder/scaleway/builder.go +++ b/builder/scaleway/builder.go @@ -26,13 +26,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/scaleway/builder_test.go b/builder/scaleway/builder_test.go index a1a0fccc3..cfb192614 100644 --- a/builder/scaleway/builder_test.go +++ b/builder/scaleway/builder_test.go @@ -32,7 +32,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "api_token": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -46,7 +46,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { config := testConfig() config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -60,7 +60,7 @@ func TestBuilderPrepare_Region(t *testing.T) { config := testConfig() delete(config, "region") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -72,7 +72,7 @@ func TestBuilderPrepare_Region(t *testing.T) { config["region"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -90,7 +90,7 @@ func TestBuilderPrepare_CommercialType(t *testing.T) { config := testConfig() delete(config, "commercial_type") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -102,7 +102,7 @@ func TestBuilderPrepare_CommercialType(t *testing.T) { config["commercial_type"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -120,7 +120,7 @@ func TestBuilderPrepare_Image(t *testing.T) { config := testConfig() delete(config, "image") - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -132,7 +132,7 @@ func TestBuilderPrepare_Image(t *testing.T) { config["image"] = expected b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -149,7 +149,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) { var b Builder config := testConfig() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -163,7 +163,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) { config["snapshot_name"] = "foobarbaz" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -173,7 +173,7 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) { config["snapshot_name"] = "{{timestamp}}" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -192,7 +192,7 @@ func TestBuilderPrepare_ServerName(t *testing.T) { var b Builder config := testConfig() - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -206,7 +206,7 @@ func TestBuilderPrepare_ServerName(t *testing.T) { config["server_name"] = "foobar" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -216,7 +216,7 @@ func TestBuilderPrepare_ServerName(t *testing.T) { config["server_name"] = "foobar-{{timestamp}}" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -226,7 +226,7 @@ func TestBuilderPrepare_ServerName(t *testing.T) { config["server_name"] = "foobar-{{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/scaleway/step_create_server.go b/builder/scaleway/step_create_server.go index 9cfee4207..06a72d95a 100644 --- a/builder/scaleway/step_create_server.go +++ b/builder/scaleway/step_create_server.go @@ -60,6 +60,9 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu s.serverID = server state.Put("server_id", server) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.serverID) return multistep.ActionContinue } diff --git a/builder/tencentcloud/cvm/builder.go b/builder/tencentcloud/cvm/builder.go index b180d873f..d13a09828 100644 --- a/builder/tencentcloud/cvm/builder.go +++ b/builder/tencentcloud/cvm/builder.go @@ -33,7 +33,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -45,7 +45,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, raws...) b.config.ctx.EnableEnv = true if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors @@ -54,12 +54,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.TencentCloudImageConfig.Prepare(&b.config.ctx)...) errs = packer.MultiErrorAppend(errs, b.config.TencentCloudRunConfig.Prepare(&b.config.ctx)...) if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } packer.LogSecretFilter.Set(b.config.SecretId, b.config.SecretKey) - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/tencentcloud/cvm/step_run_instance.go b/builder/tencentcloud/cvm/step_run_instance.go index b43e1fbf6..72f3f7b90 100644 --- a/builder/tencentcloud/cvm/step_run_instance.go +++ b/builder/tencentcloud/cvm/step_run_instance.go @@ -175,6 +175,9 @@ func (s *stepRunInstance) Run(ctx context.Context, state multistep.StateBag) mul } state.Put("instance", describeResp.Response.InstanceSet[0]) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.instanceId) Message(state, s.instanceId, "Instance created") return multistep.ActionContinue diff --git a/builder/triton/builder.go b/builder/triton/builder.go index c4bd477e1..22759406b 100644 --- a/builder/triton/builder.go +++ b/builder/triton/builder.go @@ -23,7 +23,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { errs := &multierror.Error{} err := config.Decode(&b.config, &config.DecodeOpts{ @@ -45,7 +45,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { b.config.Comm.SSHAgentAuth = true } - return nil, errs.ErrorOrNil() + return nil, nil, errs.ErrorOrNil() } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/triton/step_create_source_machine.go b/builder/triton/step_create_source_machine.go index 1aad77508..24080ba23 100644 --- a/builder/triton/step_create_source_machine.go +++ b/builder/triton/step_create_source_machine.go @@ -43,6 +43,9 @@ func (s *StepCreateSourceMachine) Run(ctx context.Context, state multistep.State } state.Put("machine", machineId) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", machineId) return multistep.ActionContinue } diff --git a/builder/ucloud/uhost/builder.go b/builder/ucloud/uhost/builder.go index 5b9f0b32a..676114a6d 100644 --- a/builder/ucloud/uhost/builder.go +++ b/builder/ucloud/uhost/builder.go @@ -36,7 +36,7 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -48,7 +48,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, raws...) b.config.ctx.EnableEnv = true if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors @@ -58,11 +58,11 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) if errs != nil && len(errs.Errors) > 0 { - return nil, errs + return nil, nil, errs } packer.LogSecretFilter.Set(b.config.PublicKey, b.config.PrivateKey) - return nil, nil + return nil, nil, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/ucloud/uhost/builder_test.go b/builder/ucloud/uhost/builder_test.go index 7d0a2d5ce..cbc8d1d4e 100644 --- a/builder/ucloud/uhost/builder_test.go +++ b/builder/ucloud/uhost/builder_test.go @@ -36,7 +36,7 @@ func TestBuilder_Prepare_BadType(t *testing.T) { "public_key": []string{}, } - warnings, err := b.Prepare(c) + _, warnings, err := b.Prepare(c) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -51,7 +51,7 @@ func TestBuilderPrepare_ImageName(t *testing.T) { // Test good config["image_name"] = "foo" - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -62,7 +62,7 @@ func TestBuilderPrepare_ImageName(t *testing.T) { // Test bad config["image_name"] = "foo {{" b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -73,7 +73,7 @@ func TestBuilderPrepare_ImageName(t *testing.T) { // Test bad delete(config, "image_name") b = Builder{} - warnings, err = b.Prepare(config) + _, warnings, err = b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -88,7 +88,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } @@ -114,7 +114,7 @@ func TestBuilderPrepare_ImageDestinations(t *testing.T) { "description": "bar", }, } - warnings, err := b.Prepare(config) + _, warnings, err := b.Prepare(config) if len(warnings) > 0 { t.Fatalf("bad: %#v", warnings) } diff --git a/builder/ucloud/uhost/step_create_instance.go b/builder/ucloud/uhost/step_create_instance.go index a4a312ce8..f80c14690 100644 --- a/builder/ucloud/uhost/step_create_instance.go +++ b/builder/ucloud/uhost/step_create_instance.go @@ -78,6 +78,9 @@ func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) s.instanceId = instanceId state.Put("instance", instance) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", instance) if instance.BootDiskState != ucloudcommon.BootDiskStateNormal { ui.Say("Waiting for boot disk of instance initialized") diff --git a/builder/vagrant/builder.go b/builder/vagrant/builder.go index 984654c51..f0bf3ab16 100644 --- a/builder/vagrant/builder.go +++ b/builder/vagrant/builder.go @@ -134,7 +134,7 @@ type Config struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -145,7 +145,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors and warnings @@ -216,10 +216,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a Packer build and returns a packer.Artifact representing diff --git a/builder/vagrant/builder_test.go b/builder/vagrant/builder_test.go index 5327706af..704c23f2a 100644 --- a/builder/vagrant/builder_test.go +++ b/builder/vagrant/builder_test.go @@ -82,7 +82,7 @@ func TestBuilder_Prepare_ValidateSource(t *testing.T) { } for _, tc := range cases { - _, err := (&Builder{}).Prepare(tc.config) + _, _, err := (&Builder{}).Prepare(tc.config) if (err != nil) != tc.errExpected { t.Fatalf("Unexpected behavior from test case %#v; %s.", tc.config, tc.reason) } diff --git a/builder/vagrant/step_up.go b/builder/vagrant/step_up.go index 6ca931f3a..e78834f36 100644 --- a/builder/vagrant/step_up.go +++ b/builder/vagrant/step_up.go @@ -35,7 +35,11 @@ func (s *StepUp) Run(ctx context.Context, state multistep.StateBag) multistep.St ui.Say("Calling Vagrant Up (this can take some time)...") - _, _, err := driver.Up(s.generateArgs()) + args := s.generateArgs() + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", args[0]) + _, _, err := driver.Up(args) if err != nil { state.Put("error", err) diff --git a/builder/virtualbox/common/step_run.go b/builder/virtualbox/common/step_run.go index 46a45d001..8144087b2 100644 --- a/builder/virtualbox/common/step_run.go +++ b/builder/virtualbox/common/step_run.go @@ -57,6 +57,9 @@ func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.S } s.vmName = vmName + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", s.vmName) return multistep.ActionContinue } diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index fe1ba87a2..2bf69b49f 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -133,7 +133,7 @@ type Config struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { err := config.Decode(&b.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &b.config.ctx, @@ -148,7 +148,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { }, }, raws...) if err != nil { - return nil, err + return nil, nil, err } // Accumulate any errors and warnings @@ -270,10 +270,10 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } if errs != nil && len(errs.Errors) > 0 { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/virtualbox/iso/builder_test.go b/builder/virtualbox/iso/builder_test.go index 370ebe675..7f996efdf 100644 --- a/builder/virtualbox/iso/builder_test.go +++ b/builder/virtualbox/iso/builder_test.go @@ -32,7 +32,7 @@ func TestBuilder_ImplementsBuilder(t *testing.T) { func TestBuilderPrepare_Defaults(t *testing.T) { var b Builder config := testConfig() - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -62,7 +62,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config := testConfig() delete(config, "disk_size") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -76,7 +76,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config["disk_size"] = 60000 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -94,7 +94,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { config := testConfig() delete(config, "floppy_files") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -109,7 +109,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { floppies_path := "../../../common/test-fixtures/floppies" config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -128,7 +128,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) { config := testConfig() config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} b = Builder{} - _, errs := b.Prepare(config) + _, _, errs := b.Prepare(config) if errs == nil { t.Fatalf("Nonexistent floppies should trigger multierror") } @@ -144,7 +144,7 @@ func TestBuilderPrepare_GuestAdditionsMode(t *testing.T) { // test default mode delete(config, "guest_additions_mode") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -155,7 +155,7 @@ func TestBuilderPrepare_GuestAdditionsMode(t *testing.T) { // Test another mode config["guest_additions_mode"] = "attach" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -170,7 +170,7 @@ func TestBuilderPrepare_GuestAdditionsMode(t *testing.T) { // Test bad mode config["guest_additions_mode"] = "teleport" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -184,7 +184,7 @@ func TestBuilderPrepare_GuestAdditionsPath(t *testing.T) { config := testConfig() delete(config, "guest_additions_path") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -198,7 +198,7 @@ func TestBuilderPrepare_GuestAdditionsPath(t *testing.T) { config["guest_additions_path"] = "foo" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -216,7 +216,7 @@ func TestBuilderPrepare_GuestAdditionsSHA256(t *testing.T) { config := testConfig() delete(config, "guest_additions_sha256") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -230,7 +230,7 @@ func TestBuilderPrepare_GuestAdditionsSHA256(t *testing.T) { config["guest_additions_sha256"] = "FOO" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -248,7 +248,7 @@ func TestBuilderPrepare_GuestAdditionsURL(t *testing.T) { config := testConfig() config["guest_additions_url"] = "" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -262,7 +262,7 @@ func TestBuilderPrepare_GuestAdditionsURL(t *testing.T) { config["guest_additions_url"] = "http://www.packer.io" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -277,7 +277,7 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) { // Test a default boot_wait delete(config, "hard_drive_interface") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -292,7 +292,7 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) { // Test with a bad config["hard_drive_interface"] = "fake" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -303,7 +303,7 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) { // Test with a good config["hard_drive_interface"] = "sata" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -318,7 +318,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -333,7 +333,7 @@ func TestBuilderPrepare_ISOInterface(t *testing.T) { // Test a default boot_wait delete(config, "iso_interface") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -348,7 +348,7 @@ func TestBuilderPrepare_ISOInterface(t *testing.T) { // Test with a bad config["iso_interface"] = "fake" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -359,7 +359,7 @@ func TestBuilderPrepare_ISOInterface(t *testing.T) { // Test with a good config["iso_interface"] = "sata" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index f0e92d5db..9fdb7b189 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -22,13 +22,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a Packer build and returns a packer.Artifact representing diff --git a/builder/virtualbox/vm/builder.go b/builder/virtualbox/vm/builder.go index 3deda5ee7..be24f8a6e 100644 --- a/builder/virtualbox/vm/builder.go +++ b/builder/virtualbox/vm/builder.go @@ -22,13 +22,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a Packer build and returns a packer.Artifact representing diff --git a/builder/vmware/common/step_run.go b/builder/vmware/common/step_run.go index 5f03ebca5..e9ac27331 100644 --- a/builder/vmware/common/step_run.go +++ b/builder/vmware/common/step_run.go @@ -64,6 +64,10 @@ func (s *StepRun) Run(ctx context.Context, state multistep.StateBag) multistep.S return multistep.ActionHalt } + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", vmxPath) + return multistep.ActionContinue } diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 0c230d91b..4af036035 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -21,13 +21,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { diff --git a/builder/vmware/iso/builder_test.go b/builder/vmware/iso/builder_test.go index 195f8e381..38441d633 100644 --- a/builder/vmware/iso/builder_test.go +++ b/builder/vmware/iso/builder_test.go @@ -33,7 +33,7 @@ func TestBuilder_ImplementsBuilder(t *testing.T) { func TestBuilderPrepare_Defaults(t *testing.T) { var b Builder config := testConfig() - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -63,7 +63,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config := testConfig() delete(config, "disk_size") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -77,7 +77,7 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { config["disk_size"] = 60000 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -95,7 +95,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { config := testConfig() delete(config, "floppy_files") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -110,7 +110,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { floppies_path := "../../../common/test-fixtures/floppies" config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -129,7 +129,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) { config := testConfig() config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} b = Builder{} - _, errs := b.Prepare(config) + _, _, errs := b.Prepare(config) if errs == nil { t.Fatalf("Nonexistent floppies should trigger multierror") } @@ -149,7 +149,7 @@ func TestBuilderPrepare_RemoteType(t *testing.T) { config["skip_validate_credentials"] = true // Bad config["remote_type"] = "foobar" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -161,7 +161,7 @@ func TestBuilderPrepare_RemoteType(t *testing.T) { // Bad config["remote_host"] = "" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -176,7 +176,7 @@ func TestBuilderPrepare_RemoteType(t *testing.T) { config["remote_password"] = "" config["remote_private_key_file"] = "" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -189,7 +189,7 @@ func TestBuilderPrepare_RemoteType(t *testing.T) { config["remote_host"] = "foobar.example.com" config["remote_password"] = "supersecret" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -207,7 +207,7 @@ func TestBuilderPrepare_RemoteExport(t *testing.T) { config["skip_validate_credentials"] = true // Bad config["remote_password"] = "" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) != 0 { t.Fatalf("bad: %#v", warns) } @@ -218,7 +218,7 @@ func TestBuilderPrepare_RemoteExport(t *testing.T) { // Good config["remote_password"] = "supersecret" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) != 0 { t.Fatalf("err: %s", err) } @@ -233,7 +233,7 @@ func TestBuilderPrepare_Format(t *testing.T) { // Bad config["format"] = "foobar" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -252,7 +252,7 @@ func TestBuilderPrepare_Format(t *testing.T) { config["skip_validate_credentials"] = true b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -268,7 +268,7 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { // Add a random key config["i_should_not_be_valid"] = true - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -290,7 +290,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) { config["output_directory"] = dir b = Builder{} - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -301,7 +301,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) { // Test with a good one config["output_directory"] = "i-hope-i-dont-exist" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -316,7 +316,7 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) { // Test a default delete(config, "tools_upload_path") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -331,7 +331,7 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) { // Test with a bad value config["tools_upload_path"] = "{{{nope}" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -342,7 +342,7 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) { // Test with a good one config["tools_upload_path"] = "hey" b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -357,7 +357,7 @@ func TestBuilderPrepare_VMXTemplatePath(t *testing.T) { // Test bad config["vmx_template_path"] = "/i/dont/exist/forreal" - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -379,7 +379,7 @@ func TestBuilderPrepare_VMXTemplatePath(t *testing.T) { config["vmx_template_path"] = tf.Name() b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -401,7 +401,7 @@ func TestBuilderPrepare_VMXTemplatePath(t *testing.T) { config["vmx_template_path"] = tf2.Name() b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -417,7 +417,7 @@ func TestBuilderPrepare_VNCPort(t *testing.T) { // Bad config["vnc_port_min"] = 1000 config["vnc_port_max"] = 500 - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -428,7 +428,7 @@ func TestBuilderPrepare_VNCPort(t *testing.T) { // Bad config["vnc_port_min"] = -500 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -440,7 +440,7 @@ func TestBuilderPrepare_VNCPort(t *testing.T) { config["vnc_port_min"] = 500 config["vnc_port_max"] = 1000 b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -458,7 +458,7 @@ func TestBuilderCheckCollisions(t *testing.T) { } { var b Builder - warns, _ := b.Prepare(config) + _, warns, _ := b.Prepare(config) if len(warns) != 1 { t.Fatalf("Should have warning about two collisions.") } @@ -466,7 +466,7 @@ func TestBuilderCheckCollisions(t *testing.T) { { config["vmx_template_path"] = "some/path.vmx" var b Builder - warns, _ := b.Prepare(config) + _, warns, _ := b.Prepare(config) if len(warns) != 0 { t.Fatalf("Should not check for collisions with custom template.") } @@ -484,7 +484,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) { config["winrm_host"] = "1.2.3.4" var b Builder - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -512,7 +512,7 @@ func TestBuilderPrepare_CommConfig(t *testing.T) { config["ssh_host"] = "1.2.3.4" var b Builder - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index a37b0b313..1b5d1f685 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -24,13 +24,13 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a Packer build and returns a packer.Artifact representing diff --git a/builder/vmware/vmx/builder_test.go b/builder/vmware/vmx/builder_test.go index 841d4f718..4e2a165a7 100644 --- a/builder/vmware/vmx/builder_test.go +++ b/builder/vmware/vmx/builder_test.go @@ -24,7 +24,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { config["source_path"] = tf.Name() delete(config, "floppy_files") - warns, err := b.Prepare(config) + _, warns, err := b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -39,7 +39,7 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) { floppies_path := "../../../common/test-fixtures/floppies" config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} b = Builder{} - warns, err = b.Prepare(config) + _, warns, err = b.Prepare(config) if len(warns) > 0 { t.Fatalf("bad: %#v", warns) } @@ -58,7 +58,7 @@ func TestBuilderPrepare_InvalidFloppies(t *testing.T) { config := testConfig(t) config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} b = Builder{} - _, errs := b.Prepare(config) + _, _, errs := b.Prepare(config) if errs == nil { t.Fatalf("Nonexistent floppies should trigger multierror") } diff --git a/builder/yandex/builder.go b/builder/yandex/builder.go index 5f0b68102..d461eb525 100644 --- a/builder/yandex/builder.go +++ b/builder/yandex/builder.go @@ -26,12 +26,12 @@ type Builder struct { func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } -func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { +func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { warnings, errs := b.config.Prepare(raws...) if errs != nil { - return warnings, errs + return nil, warnings, errs } - return warnings, nil + return nil, warnings, nil } // Run executes a yandex Packer build and returns a packer.Artifact diff --git a/builder/yandex/step_create_instance.go b/builder/yandex/step_create_instance.go index 5d7b28f10..b13cbca1e 100644 --- a/builder/yandex/step_create_instance.go +++ b/builder/yandex/step_create_instance.go @@ -249,6 +249,9 @@ runcmd: } state.Put("disk_id", instance.BootDisk.DiskId) + // instance_id is the generic term used so that users can have access to the + // instance id inside of the provisioners, used in step_provision. + state.Put("instance_id", instance.Id) if s.Debug { ui.Message(fmt.Sprintf("Instance ID %s started. Current instance status %s", instance.Id, instance.Status)) diff --git a/command/build_parallel_test.go b/command/build_parallel_test.go index 4634f5191..b6e4ceb8c 100644 --- a/command/build_parallel_test.go +++ b/command/build_parallel_test.go @@ -29,8 +29,11 @@ type ParallelTestBuilder struct { wg sync.WaitGroup } -func (b *ParallelTestBuilder) ConfigSpec() hcldec.ObjectSpec { return nil } -func (b *ParallelTestBuilder) Prepare(raws ...interface{}) ([]string, error) { return nil, nil } +func (b *ParallelTestBuilder) ConfigSpec() hcldec.ObjectSpec { return nil } + +func (b *ParallelTestBuilder) Prepare(raws ...interface{}) ([]string, []string, error) { + return nil, nil, nil +} func (b *ParallelTestBuilder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { ui.Say("building") @@ -41,8 +44,9 @@ func (b *ParallelTestBuilder) Run(ctx context.Context, ui packer.Ui, hook packer // LockedBuilder wont run until unlock is called type LockedBuilder struct{ unlock chan interface{} } -func (b *LockedBuilder) ConfigSpec() hcldec.ObjectSpec { return nil } -func (b *LockedBuilder) Prepare(raws ...interface{}) ([]string, error) { return nil, nil } +func (b *LockedBuilder) ConfigSpec() hcldec.ObjectSpec { return nil } + +func (b *LockedBuilder) Prepare(raws ...interface{}) ([]string, []string, error) { return nil, nil, nil } func (b *LockedBuilder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { ui.Say("locking build") diff --git a/common/shell-local/config.go b/common/shell-local/config.go index 2e6064258..37c2605f8 100644 --- a/common/shell-local/config.go +++ b/common/shell-local/config.go @@ -5,6 +5,7 @@ package shell_local import ( "errors" "fmt" + // "log" "os" "path/filepath" "runtime" @@ -41,15 +42,14 @@ type Config struct { // End dedupe with postprocessor UseLinuxPathing bool `mapstructure:"use_linux_pathing"` - ctx interpolate.Context + // used to track the data sent to shell-local from the builder + // GeneratedData + + ctx interpolate.Context + generatedData map[string]interface{} } func Decode(config *Config, raws ...interface{}) error { - //Create passthrough for winrm password so we can fill it in once we know it - config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: `{{.WinRMPassword}}`, - } - err := configHelper.Decode(config, &configHelper.DecodeOpts{ Interpolate: true, InterpolateContext: &config.ctx, @@ -60,7 +60,8 @@ func Decode(config *Config, raws ...interface{}) error { }, }, raws...) if err != nil { - return fmt.Errorf("Error decoding config: %s, config is %#v, and raws is %#v", err, config, raws) + return fmt.Errorf("Error decoding config: %s", err) + // return fmt.Errorf("Error decoding config: %s, config is %#v, and raws is %#v", err, config, raws) } return nil diff --git a/common/shell-local/run.go b/common/shell-local/run.go index 06b8c78d3..9f7170394 100644 --- a/common/shell-local/run.go +++ b/common/shell-local/run.go @@ -11,24 +11,20 @@ import ( "strings" "github.com/hashicorp/packer/common" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer/tmp" "github.com/hashicorp/packer/template/interpolate" ) -type ExecuteCommandTemplate struct { - Vars string - Script string - Command string - WinRMPassword string -} - -type EnvVarsTemplate struct { - WinRMPassword string -} - -func Run(ctx context.Context, ui packer.Ui, config *Config) (bool, error) { +func Run(ctx context.Context, ui packer.Ui, config *Config, generatedData map[string]interface{}) (bool, error) { + if generatedData != nil { + config.generatedData = generatedData + } else { + // No fear; probably just in the post-processor, not provisioner. + // Make sure it's not a nil map so we can assign to it later. + config.generatedData = make(map[string]interface{}) + } + config.ctx.Data = generatedData // Check if shell-local can even execute against this runtime OS if len(config.OnlyOn) > 0 { runCommand := false @@ -120,11 +116,6 @@ func createInlineScriptFile(config *Config) (string, error) { writer.WriteString(shebang) } - // generate context so you can interpolate the command - config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: getWinRMPassword(config.PackerBuildName), - } - for _, command := range config.Inline { // interpolate command to check for template variables. command, err := interpolate.Render(command, &config.ctx) @@ -152,12 +143,11 @@ func createInlineScriptFile(config *Config) (string, error) { // user-provided ExecuteCommand or defaulting to something that makes sense for // the host OS func createInterpolatedCommands(config *Config, script string, flattenedEnvVars string) ([]string, error) { - config.ctx.Data = &ExecuteCommandTemplate{ - Vars: flattenedEnvVars, - Script: script, - Command: script, - WinRMPassword: getWinRMPassword(config.PackerBuildName), - } + config.generatedData["Vars"] = flattenedEnvVars + config.generatedData["Script"] = script + config.generatedData["Command"] = script + + config.ctx.Data = config.generatedData interpolatedCmds := make([]string, len(config.ExecuteCommand)) for i, cmd := range config.ExecuteCommand { @@ -192,10 +182,6 @@ func createFlattenedEnvVars(config *Config) (string, error) { envVars["PACKER_HTTP_PORT"] = httpPort } - // interpolate environment variables - config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: getWinRMPassword(config.PackerBuildName), - } // Split vars into key/value components for _, envVar := range config.Vars { envVar, err := interpolate.Render(envVar, &config.ctx) @@ -221,9 +207,3 @@ func createFlattenedEnvVars(config *Config) (string, error) { } return flattened, nil } - -func getWinRMPassword(buildName string) string { - winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName) - packer.LogSecretFilter.Set(winRMPass) - return winRMPass -} diff --git a/common/step_provision.go b/common/step_provision.go index 07ba39f81..c9c399e16 100644 --- a/common/step_provision.go +++ b/common/step_provision.go @@ -4,8 +4,10 @@ import ( "context" "fmt" "log" + "os" "time" + "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" ) @@ -19,6 +21,57 @@ import ( // // Produces: // + +func PopulateProvisionHookData(state multistep.StateBag) map[string]interface{} { + hookData := make(map[string]interface{}) + + // Load Builder hook data from state, if it has been set. + hd, ok := state.GetOk("generated_data") + if ok { + hookData = hd.(map[string]interface{}) + } + + // instance_id is placed in state by the builders. + // Not yet implemented in Chroot, lxc/lxd, Azure, Qemu. + // Implemented in most others including digitalOcean (droplet id), + // docker (container_id), and clouds which use "server" internally instead + // of instance. + + // Also note that Chroot and lxc/lxd builders tend to have their own custom + // step_provision, so they won't use this code path. + id, ok := state.GetOk("instance_id") + if ok { + hookData["ID"] = id + } else { + // Warn user that the id isn't implemented + hookData["ID"] = "ERR_ID_NOT_IMPLEMENTED_BY_BUILDER" + } + hookData["PackerRunUUID"] = os.Getenv("PACKER_RUN_UUID") + + // Read communicator data into hook data + comm, ok := state.GetOk("communicator_config") + if !ok { + log.Printf("Unable to load config from state to populate provisionHookData") + return hookData + } + commConf := comm.(*communicator.Config) + + // Loop over all field values and retrieve them from the ssh config + hookData["Host"] = commConf.Host() + hookData["Port"] = commConf.Port() + hookData["User"] = commConf.User() + hookData["Password"] = commConf.Password() + hookData["ConnType"] = commConf.Type + hookData["SSHPublicKey"] = commConf.SSHPublicKey + hookData["SSHPrivateKey"] = commConf.SSHPrivateKey + + // Backwards compatibility; in practice, WinRMPassword is fulfilled by + // Password. + hookData["WinRMPassword"] = commConf.WinRMPassword + + return hookData +} + type StepProvision struct { Comm packer.Communicator } @@ -32,9 +85,12 @@ func (s *StepProvision) runWithHook(ctx context.Context, state multistep.StateBa comm = raw.(packer.Communicator) } } + hook := state.Get("hook").(packer.Hook) ui := state.Get("ui").(packer.Ui) + hookData := PopulateProvisionHookData(state) + // Run the provisioner in a goroutine so we can continually check // for cancellations... if hooktype == packer.HookProvision { @@ -44,7 +100,7 @@ func (s *StepProvision) runWithHook(ctx context.Context, state multistep.StateBa } errCh := make(chan error, 1) go func() { - errCh <- hook.Run(ctx, hooktype, ui, comm, nil) + errCh <- hook.Run(ctx, hooktype, ui, comm, hookData) }() for { diff --git a/hcl2template/mock.go b/hcl2template/mock.go index 09fbf0c19..8576a0439 100644 --- a/hcl2template/mock.go +++ b/hcl2template/mock.go @@ -40,8 +40,8 @@ var _ packer.Builder = new(MockBuilder) func (b *MockBuilder) ConfigSpec() hcldec.ObjectSpec { return b.Config.FlatMapstructure().HCL2Spec() } -func (b *MockBuilder) Prepare(raws ...interface{}) ([]string, error) { - return nil, config.Decode(&b.Config, &config.DecodeOpts{ +func (b *MockBuilder) Prepare(raws ...interface{}) ([]string, []string, error) { + return nil, nil, config.Decode(&b.Config, &config.DecodeOpts{ Interpolate: true, }, raws...) } @@ -70,7 +70,7 @@ func (b *MockProvisioner) Prepare(raws ...interface{}) error { }, raws...) } -func (b *MockProvisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (b *MockProvisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { return nil } diff --git a/hcl2template/types.build.provisioners.go b/hcl2template/types.build.provisioners.go index 33d0fb324..7fd832a6c 100644 --- a/hcl2template/types.build.provisioners.go +++ b/hcl2template/types.build.provisioners.go @@ -3,6 +3,7 @@ package hcl2template import ( "fmt" "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/packer" ) @@ -31,7 +32,7 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia return provisioner, diags } -func (p *Parser) StartProvisioner(pb *ProvisionerBlock) (packer.Provisioner, hcl.Diagnostics) { +func (p *Parser) StartProvisioner(pb *ProvisionerBlock, generatedVars []string) (packer.Provisioner, hcl.Diagnostics) { var diags hcl.Diagnostics provisioner, err := p.ProvisionersSchemas.Start(pb.PType) @@ -43,12 +44,30 @@ func (p *Parser) StartProvisioner(pb *ProvisionerBlock) (packer.Provisioner, hcl }) return nil, diags } - flatProvisinerCfg, moreDiags := decodeHCL2Spec(pb.block, nil, provisioner) + flatProvisionerCfg, moreDiags := decodeHCL2Spec(pb.block, nil, provisioner) diags = append(diags, moreDiags...) if diags.HasErrors() { return nil, diags } - err = provisioner.Prepare(flatProvisinerCfg) + // manipulate generatedVars from builder to add to the interfaces being + // passed to the provisioner Prepare() + + // If the builder has provided a list of to-be-generated variables that + // should be made accessible to provisioners, pass that list into + // the provisioner prepare() so that the provisioner can appropriately + // validate user input against what will become available. Otherwise, + // only pass the default variables, using the basic placeholder data. + generatedPlaceholderMap := packer.BasicPlaceholderData() + if generatedVars != nil { + for _, k := range generatedVars { + generatedPlaceholderMap[k] = fmt.Sprintf("Generated_%s. "+ + common.PlaceholderMsg, k) + } + } + // configs := make([]interface{}, 2) + // configs = append(, flatProvisionerCfg) + // configs = append(configs, generatedPlaceholderMap) + err = provisioner.Prepare(flatProvisionerCfg, generatedPlaceholderMap) if err != nil { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index 623360388..d33adf93d 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -14,11 +14,11 @@ type PackerConfig struct { Builds Builds } -func (p *Parser) CoreBuildProvisioners(blocks []*ProvisionerBlock) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) { +func (p *Parser) CoreBuildProvisioners(blocks []*ProvisionerBlock, generatedVars []string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) { var diags hcl.Diagnostics res := []packer.CoreBuildProvisioner{} for _, pb := range blocks { - provisioner, moreDiags := p.StartProvisioner(pb) + provisioner, moreDiags := p.StartProvisioner(pb, generatedVars) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue @@ -63,12 +63,12 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics) }) continue } - builder, moreDiags := p.StartBuilder(src) + builder, moreDiags, generatedVars := p.StartBuilder(src) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue } - provisioners, moreDiags := p.CoreBuildProvisioners(build.ProvisionerBlocks) + provisioners, moreDiags := p.CoreBuildProvisioners(build.ProvisionerBlocks, generatedVars) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue diff --git a/hcl2template/types.source.go b/hcl2template/types.source.go index fd81ee5cc..47eddfa70 100644 --- a/hcl2template/types.source.go +++ b/hcl2template/types.source.go @@ -39,7 +39,7 @@ func (p *Parser) decodeSource(block *hcl.Block) (*Source, hcl.Diagnostics) { return source, diags } -func (p *Parser) StartBuilder(source *Source) (packer.Builder, hcl.Diagnostics) { +func (p *Parser) StartBuilder(source *Source) (packer.Builder, hcl.Diagnostics, []string) { var diags hcl.Diagnostics builder, err := p.BuilderSchemas.Start(source.Type) @@ -49,18 +49,19 @@ func (p *Parser) StartBuilder(source *Source) (packer.Builder, hcl.Diagnostics) Detail: err.Error(), Subject: &source.block.LabelRanges[0], }) - return builder, diags + return builder, diags, nil } decoded, moreDiags := decodeHCL2Spec(source.block, nil, builder) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { - return nil, diags + return nil, diags, nil } - warning, err := builder.Prepare(decoded) + + generatedVars, warning, err := builder.Prepare(decoded) moreDiags = warningErrorsToDiags(source.block, warning, err) diags = append(diags, moreDiags...) - return builder, diags + return builder, diags, generatedVars } func (source *Source) Ref() SourceRef { diff --git a/helper/common/shared_state.go b/helper/common/shared_state.go index 87e111cfb..10f3803ae 100644 --- a/helper/common/shared_state.go +++ b/helper/common/shared_state.go @@ -7,6 +7,11 @@ import ( "path/filepath" ) +// This is used in the BasicPlaceholderData() func in the packer/provisioner.go +// To force users to access generated data via the "generated" func. +const PlaceholderMsg = "To set this dynamically in the Packer template, " + + "you must use the `build` function" + // Used to set variables which we need to access later in the build, where // state bag and config information won't work func sharedStateFilename(suffix string, buildName string) string { diff --git a/helper/communicator/step_connect.go b/helper/communicator/step_connect.go index 6bb062f80..7694e0b1a 100644 --- a/helper/communicator/step_connect.go +++ b/helper/communicator/step_connect.go @@ -101,7 +101,6 @@ func (s *StepConnect) Run(ctx context.Context, state multistep.StateBag) multist if host, err := s.Host(state); err == nil { ui.Say(fmt.Sprintf("Using %s communicator to connect: %s", s.Config.Type, host)) - } else { log.Printf("[DEBUG] Unable to get address during connection step: %s", err) } @@ -119,6 +118,10 @@ func (s *StepConnect) Run(ctx context.Context, state multistep.StateBag) multist } } + // Put communicator config into state so we can pass it to provisioners + // for specialized interpolation later + state.Put("communicator_config", s.Config) + return multistep.ActionContinue } diff --git a/helper/communicator/step_connect_ssh.go b/helper/communicator/step_connect_ssh.go index 962615c3a..1584c3e61 100644 --- a/helper/communicator/step_connect_ssh.go +++ b/helper/communicator/step_connect_ssh.go @@ -134,6 +134,8 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, ctx context.Contex log.Printf("[DEBUG] Error getting SSH address: %s", err) continue } + // store host and port in config so we can access them from provisioners + s.Config.SSHHost = host port := s.Config.SSHPort if s.SSHPort != nil { port, err = s.SSHPort(state) @@ -141,7 +143,9 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, ctx context.Contex log.Printf("[DEBUG] Error getting SSH port: %s", err) continue } + s.Config.SSHPort = port } + state.Put("communicator_config", s.Config) // Retrieve the SSH configuration sshConfig, err := s.SSHConfig(state) @@ -204,7 +208,6 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, ctx context.Contex } log.Printf("[INFO] Attempting SSH connection to %s...", address) - log.Printf("[DEBUG] Config to %#v...", config) comm, err = ssh.New(address, config) if err != nil { log.Printf("[DEBUG] SSH handshake err: %s", err) diff --git a/helper/communicator/step_connect_winrm.go b/helper/communicator/step_connect_winrm.go index 275468bc1..8825f98b0 100644 --- a/helper/communicator/step_connect_winrm.go +++ b/helper/communicator/step_connect_winrm.go @@ -103,6 +103,7 @@ func (s *StepConnectWinRM) waitForWinRM(state multistep.StateBag, ctx context.Co log.Printf("[DEBUG] Error getting WinRM host: %s", err) continue } + s.Config.WinRMHost = host port := s.Config.WinRMPort if s.WinRMPort != nil { @@ -111,8 +112,11 @@ func (s *StepConnectWinRM) waitForWinRM(state multistep.StateBag, ctx context.Co log.Printf("[DEBUG] Error getting WinRM port: %s", err) continue } + s.Config.WinRMPort = port } + state.Put("communicator_config", s.Config) + user := s.Config.WinRMUser password := s.Config.WinRMPassword if s.WinRMConfig != nil { diff --git a/helper/config/decode.go b/helper/config/decode.go index eec3bbdf7..5205bf266 100644 --- a/helper/config/decode.go +++ b/helper/config/decode.go @@ -76,9 +76,11 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error { config = &DecodeOpts{Interpolate: true} } + // Detect user variables from the raws and merge them into our context + ctxData, raws := DetectContextData(raws...) + // Interpolate first if config.Interpolate { - // Detect user variables from the raws and merge them into our context ctx, err := DetectContext(raws...) if err != nil { return err @@ -90,6 +92,9 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error { config.InterpolateContext.BuildType = ctx.BuildType config.InterpolateContext.TemplatePath = ctx.TemplatePath config.InterpolateContext.UserVariables = ctx.UserVariables + if config.InterpolateContext.Data == nil { + config.InterpolateContext.Data = ctxData + } } ctx = config.InterpolateContext @@ -138,7 +143,7 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error { for _, unused := range md.Unused { if unused != "type" && !strings.HasPrefix(unused, "packer_") { err = multierror.Append(err, fmt.Errorf( - "unknown configuration key: %q", unused)) + "unknown configuration key: %q; raws is %#v \n\n and ctx data is %#v", unused, raws, ctxData)) } } if err != nil { @@ -149,6 +154,40 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error { return nil } +func DetectContextData(raws ...interface{}) (map[interface{}]interface{}, []interface{}) { + // In provisioners, the last value pulled from raws is the placeholder data + // for build-specific variables. Pull these out to add to interpolation + // context. + + // Internally, our tests may cause this to be read as a map[string]string + placeholderData := raws[len(raws)-1] + if pd, ok := placeholderData.(map[string]string); ok { + if uuid, ok := pd["PackerRunUUID"]; ok { + if strings.Contains(uuid, "Build_PackerRunUUID.") { + cast := make(map[interface{}]interface{}) + for k, v := range pd { + cast[k] = v + } + raws = raws[:len(raws)-1] + return cast, raws + } + } + } + + // but with normal interface conversion across the rpc, it'll look like a + // map[interface]interface, not a map[string]string + if pd, ok := placeholderData.(map[interface{}]interface{}); ok { + if uuid, ok := pd["PackerRunUUID"]; ok { + if strings.Contains(uuid.(string), "Build_PackerRunUUID.") { + raws = raws[:len(raws)-1] + return pd, raws + } + } + } + + return nil, raws +} + // DetectContext builds a base interpolate.Context, automatically // detecting things like user variables from the raw configuration params. func DetectContext(raws ...interface{}) (*interpolate.Context, error) { diff --git a/packer/build.go b/packer/build.go index 526dc05e4..9403adcd8 100644 --- a/packer/build.go +++ b/packer/build.go @@ -5,6 +5,8 @@ import ( "fmt" "log" "sync" + + "github.com/hashicorp/packer/helper/common" ) const ( @@ -148,17 +150,30 @@ func (b *CoreBuild) Prepare() (warn []string, err error) { } // Prepare the builder - warn, err = b.Builder.Prepare(b.BuilderConfig, packerConfig) + generatedVars, warn, err := b.Builder.Prepare(b.BuilderConfig, packerConfig) if err != nil { log.Printf("Build '%s' prepare failure: %s\n", b.Type, err) return } + // If the builder has provided a list of to-be-generated variables that + // should be made accessible to provisioners, pass that list into + // the provisioner prepare() so that the provisioner can appropriately + // validate user input against what will become available. + generatedPlaceholderMap := BasicPlaceholderData() + if generatedVars != nil { + for _, k := range generatedVars { + generatedPlaceholderMap[k] = fmt.Sprintf("Build_%s. "+ + common.PlaceholderMsg, k) + } + } + // Prepare the provisioners for _, coreProv := range b.Provisioners { configs := make([]interface{}, len(coreProv.config), len(coreProv.config)+1) copy(configs, coreProv.config) configs = append(configs, packerConfig) + configs = append(configs, generatedPlaceholderMap) if err = coreProv.Provisioner.Prepare(configs...); err != nil { return @@ -170,6 +185,7 @@ func (b *CoreBuild) Prepare() (warn []string, err error) { configs := make([]interface{}, len(b.CleanupProvisioner.config), len(b.CleanupProvisioner.config)+1) copy(configs, b.CleanupProvisioner.config) configs = append(configs, packerConfig) + configs = append(configs, generatedPlaceholderMap) err = b.CleanupProvisioner.Provisioner.Prepare(configs...) if err != nil { return diff --git a/packer/build_test.go b/packer/build_test.go index 2168214f2..3f657f63b 100644 --- a/packer/build_test.go +++ b/packer/build_test.go @@ -4,6 +4,8 @@ import ( "context" "reflect" "testing" + + "github.com/hashicorp/packer/helper/common" ) func boolPointer(tf bool) *bool { @@ -69,7 +71,7 @@ func TestBuild_Prepare(t *testing.T) { if !prov.PrepCalled { t.Fatal("prep should be called") } - if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig}) { + if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig, BasicPlaceholderData()}) { t.Fatalf("bad: %#v", prov.PrepConfigs) } @@ -144,7 +146,7 @@ func TestBuild_Prepare_Debug(t *testing.T) { if !prov.PrepCalled { t.Fatal("prepare should be called") } - if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig}) { + if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig, BasicPlaceholderData()}) { t.Fatalf("bad: %#v", prov.PrepConfigs) } } @@ -176,6 +178,34 @@ func TestBuildPrepare_variables_default(t *testing.T) { } } +func TestBuildPrepare_ProvisionerGetsGeneratedMap(t *testing.T) { + packerConfig := testDefaultPackerConfig() + + build := testBuild() + builder := build.Builder.(*MockBuilder) + builder.GeneratedVars = []string{"PartyVar"} + + build.Prepare() + if !builder.PrepareCalled { + t.Fatalf("should be called") + } + if !reflect.DeepEqual(builder.PrepareConfig, []interface{}{42, packerConfig}) { + t.Fatalf("bad: %#v", builder.PrepareConfig) + } + + coreProv := build.Provisioners[0] + prov := coreProv.Provisioner.(*MockProvisioner) + if !prov.PrepCalled { + t.Fatal("prepare should be called") + } + + generated := BasicPlaceholderData() + generated["PartyVar"] = "Build_PartyVar. " + common.PlaceholderMsg + if !reflect.DeepEqual(prov.PrepConfigs, []interface{}{42, packerConfig, generated}) { + t.Fatalf("bad: %#v", prov.PrepConfigs) + } +} + func TestBuild_Run(t *testing.T) { ui := testUi() diff --git a/packer/builder.go b/packer/builder.go index 19bfc7673..7c67196f1 100644 --- a/packer/builder.go +++ b/packer/builder.go @@ -29,9 +29,10 @@ type Builder interface { // Each of the configuration values should merge into the final // configuration. // - // Prepare should return a list of warnings along with any errors - // that occurred while preparing. - Prepare(...interface{}) ([]string, error) + // Prepare should return a list of variables that will be made accessible to + // users during the provison methods, a list of warnings along with any + // errors that occurred while preparing. + Prepare(...interface{}) ([]string, []string, error) // Run is where the actual build should take place. It takes a Build and a Ui. Run(context.Context, Ui, Hook) (Artifact, error) diff --git a/packer/builder_mock.go b/packer/builder_mock.go index 2fee11c77..06aa87291 100644 --- a/packer/builder_mock.go +++ b/packer/builder_mock.go @@ -25,16 +25,18 @@ type MockBuilder struct { RunUi Ui CancelCalled bool RunFn func(ctx context.Context) + + GeneratedVars []string } func (tb *MockBuilder) ConfigSpec() hcldec.ObjectSpec { return tb.FlatMapstructure().HCL2Spec() } func (tb *MockBuilder) FlatConfig() interface{} { return tb.FlatMapstructure() } -func (tb *MockBuilder) Prepare(config ...interface{}) ([]string, error) { +func (tb *MockBuilder) Prepare(config ...interface{}) ([]string, []string, error) { tb.PrepareCalled = true tb.PrepareConfig = config - return tb.PrepareWarnings, nil + return tb.GeneratedVars, tb.PrepareWarnings, nil } func (tb *MockBuilder) Run(ctx context.Context, ui Ui, h Hook) (Artifact, error) { diff --git a/packer/builder_mock.hcl2spec.go b/packer/builder_mock.hcl2spec.go index 0baca99da..d8835c294 100644 --- a/packer/builder_mock.hcl2spec.go +++ b/packer/builder_mock.hcl2spec.go @@ -20,6 +20,7 @@ type FlatMockBuilder struct { RunHook Hook `cty:"run_hook"` RunUi Ui `cty:"run_ui"` CancelCalled *bool `cty:"cancel_called"` + GeneratedVars []string `cty:"generated_vars"` } // FlatMapstructure returns a new FlatMockBuilder. @@ -44,6 +45,7 @@ func (*FlatMockBuilder) HCL2Spec() map[string]hcldec.Spec { "run_hook": &hcldec.AttrSpec{Name: "Hook", Type: cty.Bool, Required: false}, /* TODO(azr): could not find type */ "run_ui": &hcldec.AttrSpec{Name: "Ui", Type: cty.Bool, Required: false}, /* TODO(azr): could not find type */ "cancel_called": &hcldec.AttrSpec{Name: "cancel_called", Type: cty.Bool, Required: false}, + "generated_vars": &hcldec.AttrSpec{Name: "generated_vars", Type: cty.List(cty.String), Required: false}, } return s } diff --git a/packer/hook.go b/packer/hook.go index 25df5c855..ee8104ac9 100644 --- a/packer/hook.go +++ b/packer/hook.go @@ -34,7 +34,6 @@ type DispatchHook struct { // hooks if a mapping exists. If a mapping doesn't exist, then nothing // happens. func (h *DispatchHook) Run(ctx context.Context, name string, ui Ui, comm Communicator, data interface{}) error { - hooks, ok := h.Mapping[name] if !ok { // No hooks for that name. No problem. diff --git a/packer/plugin/builder.go b/packer/plugin/builder.go index 8eaa09f0b..abe508692 100644 --- a/packer/plugin/builder.go +++ b/packer/plugin/builder.go @@ -22,7 +22,7 @@ func (b *cmdBuilder) ConfigSpec() hcldec.ObjectSpec { return b.builder.ConfigSpec() } -func (b *cmdBuilder) Prepare(config ...interface{}) ([]string, error) { +func (b *cmdBuilder) Prepare(config ...interface{}) ([]string, []string, error) { defer func() { r := recover() b.checkExit(r, nil) diff --git a/packer/plugin/provisioner.go b/packer/plugin/provisioner.go index fcc47aea4..bc07d6b61 100644 --- a/packer/plugin/provisioner.go +++ b/packer/plugin/provisioner.go @@ -31,13 +31,13 @@ func (c *cmdProvisioner) Prepare(configs ...interface{}) error { return c.p.Prepare(configs...) } -func (c *cmdProvisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (c *cmdProvisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { defer func() { r := recover() c.checkExit(r, nil) }() - return c.p.Provision(ctx, ui, comm) + return c.p.Provision(ctx, ui, comm, generatedData) } func (c *cmdProvisioner) checkExit(p interface{}, cb func()) { diff --git a/packer/plugin/server.go b/packer/plugin/server.go index 839edc153..96e2011ce 100644 --- a/packer/plugin/server.go +++ b/packer/plugin/server.go @@ -36,7 +36,7 @@ const MagicCookieValue = "d602bf8f470bc67ca7faa0386276bbdd4330efaf76d1a219cb4d69 // The APIVersion is outputted along with the RPC address. The plugin // client validates this API version and will show an error if it doesn't // know how to speak it. -const APIVersion = "4" +const APIVersion = "5" // Server waits for a connection to this plugin and returns a Packer // RPC server that you can use to register components and serve them. diff --git a/packer/provisioner.go b/packer/provisioner.go index 98c91268f..68f5a2946 100644 --- a/packer/provisioner.go +++ b/packer/provisioner.go @@ -8,6 +8,7 @@ import ( "time" "github.com/hashicorp/hcl/v2/hcldec" + "github.com/hashicorp/packer/helper/common" ) // A provisioner is responsible for installing and configuring software @@ -24,7 +25,7 @@ type Provisioner interface { // given for cancellation, a UI is given to communicate with the user, and // a communicator is given that is guaranteed to be connected to some // machine so that provisioning can be done. - Provision(context.Context, Ui, Communicator) error + Provision(context.Context, Ui, Communicator, map[string]interface{}) error } // A HookedProvisioner represents a provisioner and information describing it @@ -41,6 +42,64 @@ type ProvisionHook struct { Provisioners []*HookedProvisioner } +// Provisioners interpolate most of their fields in the prepare stage; this +// placeholder map helps keep fields that are only generated at build time from +// accidentally being interpolated into empty strings at prepare time. +// This helper function generates the most basic placeholder data which should +// be accessible to the provisioners. It is used to initialize provisioners, to +// force validation using the `generated` template function. In the future, +// custom generated data could be passed into provisioners from builders to +// enable specialized builder-specific (but still validated!!) access to builder +// data. +func BasicPlaceholderData() map[string]string { + placeholderData := map[string]string{} + msg := "Build_%s. " + common.PlaceholderMsg + placeholderData["ID"] = fmt.Sprintf(msg, "ID") + // The following correspond to communicator-agnostic functions that are + // part of the SSH and WinRM communicator implementations. These functions + // are not part of the communicator interface, but are stored on the + // Communicator Config and return the appropriate values rather than + // depending on the actual communicator config values. E.g "Password" + // reprosents either WinRMPassword or SSHPassword, which makes this more + // useful if a template contains multiple builds. + placeholderData["Host"] = fmt.Sprintf(msg, "Host") + placeholderData["Port"] = fmt.Sprintf(msg, "Port") + placeholderData["User"] = fmt.Sprintf(msg, "User") + placeholderData["Password"] = fmt.Sprintf(msg, "Password") + placeholderData["ConnType"] = fmt.Sprintf(msg, "Type") + placeholderData["PackerRunUUID"] = fmt.Sprintf(msg, "PackerRunUUID") + placeholderData["SSHPublicKey"] = fmt.Sprintf(msg, "SSHPublicKey") + placeholderData["SSHPrivateKey"] = fmt.Sprintf(msg, "SSHPrivateKey") + + // Backwards-compatability: WinRM Password can get through without forcing + // the generated func validation. + placeholderData["WinRMPassword"] = "{{.WinRMPassword}}" + + return placeholderData +} + +func CastDataToMap(data interface{}) map[string]interface{} { + // Provisioners expect a map[string]interface{} in their data field, but + // it gets converted into a map[interface]interface on the way over the + // RPC. Check that data can be cast into such a form, and cast it. + cast := make(map[string]interface{}) + interMap, ok := data.(map[interface{}]interface{}) + if !ok { + log.Printf("Unable to read map[string]interface out of data."+ + "Using empty interface: %#v", data) + } else { + for key, val := range interMap { + keyString, ok := key.(string) + if ok { + cast[keyString] = val + } else { + log.Printf("Error casting generated data key to a string.") + } + } + } + return cast +} + // Runs the provisioners in order. func (h *ProvisionHook) Run(ctx context.Context, name string, ui Ui, comm Communicator, data interface{}) error { // Shortcut @@ -57,7 +116,8 @@ func (h *ProvisionHook) Run(ctx context.Context, name string, ui Ui, comm Commun for _, p := range h.Provisioners { ts := CheckpointReporter.AddSpan(p.TypeName, "provisioner", p.Config) - err := p.Provisioner.Provision(ctx, ui, comm) + cast := CastDataToMap(data) + err := p.Provisioner.Provision(ctx, ui, comm, cast) ts.End(err) if err != nil { @@ -81,7 +141,7 @@ func (p *PausedProvisioner) Prepare(raws ...interface{}) error { return p.Provisioner.Prepare(raws...) } -func (p *PausedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error { +func (p *PausedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData map[string]interface{}) error { // Use a select to determine if we get cancelled during the wait ui.Say(fmt.Sprintf("Pausing %s before the next provisioner...", p.PauseBefore)) @@ -91,7 +151,7 @@ func (p *PausedProvisioner) Provision(ctx context.Context, ui Ui, comm Communica return ctx.Err() } - return p.Provisioner.Provision(ctx, ui, comm) + return p.Provisioner.Provision(ctx, ui, comm, generatedData) } // DebuggedProvisioner is a Provisioner implementation that waits until a key @@ -110,7 +170,7 @@ func (p *DebuggedProvisioner) Prepare(raws ...interface{}) error { return p.Provisioner.Prepare(raws...) } -func (p *DebuggedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error { +func (p *DebuggedProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData map[string]interface{}) error { // Use a select to determine if we get cancelled during the wait message := "Pausing before the next provisioner . Press enter to continue." @@ -130,5 +190,5 @@ func (p *DebuggedProvisioner) Provision(ctx context.Context, ui Ui, comm Communi return ctx.Err() } - return p.Provisioner.Provision(ctx, ui, comm) + return p.Provisioner.Provision(ctx, ui, comm, generatedData) } diff --git a/packer/provisioner_mock.go b/packer/provisioner_mock.go index 2096a007d..bfc52aa88 100644 --- a/packer/provisioner_mock.go +++ b/packer/provisioner_mock.go @@ -28,7 +28,7 @@ func (t *MockProvisioner) Prepare(configs ...interface{}) error { return nil } -func (t *MockProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error { +func (t *MockProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData map[string]interface{}) error { t.ProvCalled = true t.ProvCommunicator = comm t.ProvUi = ui diff --git a/packer/provisioner_test.go b/packer/provisioner_test.go index 641702428..108dac90f 100644 --- a/packer/provisioner_test.go +++ b/packer/provisioner_test.go @@ -114,7 +114,7 @@ func TestPausedProvisionerProvision(t *testing.T) { ui := testUi() comm := new(MockCommunicator) - prov.Provision(context.Background(), ui, comm) + prov.Provision(context.Background(), ui, comm, make(map[string]interface{})) if !mock.ProvCalled { t.Fatal("prov should be called") } @@ -143,7 +143,7 @@ func TestPausedProvisionerProvision_waits(t *testing.T) { }, } - err := prov.Provision(context.Background(), testUi(), new(MockCommunicator)) + err := prov.Provision(context.Background(), testUi(), new(MockCommunicator), make(map[string]interface{})) if err != nil { t.Fatalf("prov failed: %v", err) @@ -164,7 +164,7 @@ func TestPausedProvisionerCancel(t *testing.T) { return ctx.Err() } - err := prov.Provision(topCtx, testUi(), new(MockCommunicator)) + err := prov.Provision(topCtx, testUi(), new(MockCommunicator), make(map[string]interface{})) if err == nil { t.Fatal("should have err") } @@ -198,7 +198,7 @@ func TestDebuggedProvisionerProvision(t *testing.T) { ui := testUi() comm := new(MockCommunicator) writeReader(ui, "\n") - prov.Provision(context.Background(), ui, comm) + prov.Provision(context.Background(), ui, comm, make(map[string]interface{})) if !mock.ProvCalled { t.Fatal("prov should be called") } @@ -224,7 +224,7 @@ func TestDebuggedProvisionerCancel(t *testing.T) { return ctx.Err() } - err := prov.Provision(topCtx, testUi(), new(MockCommunicator)) + err := prov.Provision(topCtx, testUi(), new(MockCommunicator), make(map[string]interface{})) if err == nil { t.Fatal("should have error") } diff --git a/packer/provisioner_timeout.go b/packer/provisioner_timeout.go index 1da02f563..a3104815c 100644 --- a/packer/provisioner_timeout.go +++ b/packer/provisioner_timeout.go @@ -13,7 +13,7 @@ type TimeoutProvisioner struct { Timeout time.Duration } -func (p *TimeoutProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator) error { +func (p *TimeoutProvisioner) Provision(ctx context.Context, ui Ui, comm Communicator, generatedData map[string]interface{}) error { ctx, cancel := context.WithTimeout(ctx, p.Timeout) defer cancel() @@ -37,7 +37,7 @@ func (p *TimeoutProvisioner) Provision(ctx context.Context, ui Ui, comm Communic } }() - err := p.Provisioner.Provision(ctx, ui, comm) + err := p.Provisioner.Provision(ctx, ui, comm, generatedData) close(errC) return err } diff --git a/packer/rpc/builder.go b/packer/rpc/builder.go index f6f7265a5..ae8b80a5c 100644 --- a/packer/rpc/builder.go +++ b/packer/rpc/builder.go @@ -28,26 +28,27 @@ type BuilderPrepareArgs struct { } type BuilderPrepareResponse struct { - Warnings []string - Error *BasicError + GeneratedVars []string + Warnings []string + Error *BasicError } -func (b *builder) Prepare(config ...interface{}) ([]string, error) { +func (b *builder) Prepare(config ...interface{}) ([]string, []string, error) { config, err := encodeCTYValues(config) if err != nil { - return nil, err + return nil, nil, err } var resp BuilderPrepareResponse cerr := b.client.Call(b.endpoint+".Prepare", &BuilderPrepareArgs{config}, &resp) if cerr != nil { - return nil, cerr + return nil, nil, cerr } if resp.Error != nil { err = resp.Error } - return resp.Warnings, err + return resp.GeneratedVars, resp.Warnings, err } func (b *builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) { @@ -93,10 +94,11 @@ func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *BuilderPrepareR if err != nil { return err } - warnings, err := b.builder.Prepare(config...) + generated, warnings, err := b.builder.Prepare(config...) *reply = BuilderPrepareResponse{ - Warnings: warnings, - Error: NewBasicError(err), + GeneratedVars: generated, + Warnings: warnings, + Error: NewBasicError(err), } return nil } diff --git a/packer/rpc/builder_test.go b/packer/rpc/builder_test.go index 9d89239b0..75d442865 100644 --- a/packer/rpc/builder_test.go +++ b/packer/rpc/builder_test.go @@ -20,7 +20,7 @@ func TestBuilderPrepare(t *testing.T) { // Test Prepare config := 42 - warnings, err := bClient.Prepare(config) + _, warnings, err := bClient.Prepare(config) if err != nil { t.Fatalf("bad: %s", err) } @@ -50,7 +50,7 @@ func TestBuilderPrepare_Warnings(t *testing.T) { b.PrepareWarnings = expected // Test Prepare - warnings, err := bClient.Prepare(nil) + _, warnings, err := bClient.Prepare(nil) if err != nil { t.Fatalf("bad: %s", err) } diff --git a/packer/rpc/provisioner.go b/packer/rpc/provisioner.go index 3ef1ea6b4..2d826e0a8 100644 --- a/packer/rpc/provisioner.go +++ b/packer/rpc/provisioner.go @@ -36,7 +36,12 @@ func (p *provisioner) Prepare(configs ...interface{}) error { return p.client.Call(p.endpoint+".Prepare", args, new(interface{})) } -func (p *provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +type ProvisionerProvisionArgs struct { + GeneratedData map[string]interface{} + StreamID uint32 +} + +func (p *provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { nextId := p.mux.NextId() server := newServerWithMux(p.mux, nextId) server.RegisterCommunicator(comm) @@ -57,7 +62,8 @@ func (p *provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C } }() - return p.client.Call(p.endpoint+".Provision", nextId, new(interface{})) + args := &ProvisionerProvisionArgs{generatedData, nextId} + return p.client.Call(p.endpoint+".Provision", args, new(interface{})) } func (p *ProvisionerServer) Prepare(args *ProvisionerPrepareArgs, reply *interface{}) error { @@ -68,7 +74,8 @@ func (p *ProvisionerServer) Prepare(args *ProvisionerPrepareArgs, reply *interfa return p.p.Prepare(config...) } -func (p *ProvisionerServer) Provision(streamId uint32, reply *interface{}) error { +func (p *ProvisionerServer) Provision(args *ProvisionerProvisionArgs, reply *interface{}) error { + streamId := args.StreamID client, err := newClientWithMux(p.mux, streamId) if err != nil { return NewBasicError(err) @@ -78,8 +85,7 @@ func (p *ProvisionerServer) Provision(streamId uint32, reply *interface{}) error if p.context == nil { p.context, p.contextCancel = context.WithCancel(context.Background()) } - - if err := p.p.Provision(p.context, client.Ui(), client.Communicator()); err != nil { + if err := p.p.Provision(p.context, client.Ui(), client.Communicator(), args.GeneratedData); err != nil { return NewBasicError(err) } diff --git a/packer/rpc/provisioner_test.go b/packer/rpc/provisioner_test.go index bbcbc88d8..f70e09dad 100644 --- a/packer/rpc/provisioner_test.go +++ b/packer/rpc/provisioner_test.go @@ -39,7 +39,7 @@ func TestProvisionerRPC(t *testing.T) { // Test Provision ui := &testUi{} comm := &packer.MockCommunicator{} - if err := pClient.Provision(topCtx, ui, comm); err == nil { + if err := pClient.Provision(topCtx, ui, comm, make(map[string]interface{})); err == nil { t.Fatalf("Provison should have err") } if !p.ProvCalled { diff --git a/post-processor/checksum/post-processor_test.go b/post-processor/checksum/post-processor_test.go index fce5fd1cf..e52974ec4 100644 --- a/post-processor/checksum/post-processor_test.go +++ b/post-processor/checksum/post-processor_test.go @@ -57,7 +57,7 @@ func setup(t *testing.T) (packer.Ui, packer.Artifact, error) { // Prepare the file builder builder := file.Builder{} - warnings, err := builder.Prepare(tpl.Builders["file"].Config) + _, warnings, err := builder.Prepare(tpl.Builders["file"].Config) if len(warnings) > 0 { for _, warn := range warnings { return nil, nil, fmt.Errorf("Configuration warning: %s", warn) diff --git a/post-processor/compress/post-processor_test.go b/post-processor/compress/post-processor_test.go index 0f5e1a19e..5b4cfcd9f 100644 --- a/post-processor/compress/post-processor_test.go +++ b/post-processor/compress/post-processor_test.go @@ -197,7 +197,7 @@ func setup(t *testing.T) (packer.Ui, packer.Artifact, error) { // Prepare the file builder builder := file.Builder{} - warnings, err := builder.Prepare(tpl.Builders["file"].Config) + _, warnings, err := builder.Prepare(tpl.Builders["file"].Config) if len(warnings) > 0 { for _, warn := range warnings { return nil, nil, fmt.Errorf("Configuration warning: %s", warn) diff --git a/post-processor/shell-local/post-processor.go b/post-processor/shell-local/post-processor.go index 0924314ff..5cbab3fd6 100644 --- a/post-processor/shell-local/post-processor.go +++ b/post-processor/shell-local/post-processor.go @@ -44,7 +44,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact // this particular post-processor doesn't do anything with the artifact // except to return it. - success, retErr := sl.Run(ctx, ui, &p.config) + success, retErr := sl.Run(ctx, ui, &p.config, map[string]interface{}{}) if !success { return nil, false, false, retErr } diff --git a/provisioner/ansible-local/provisioner.go b/provisioner/ansible-local/provisioner.go index 59fec5eac..c9ab144ea 100644 --- a/provisioner/ansible-local/provisioner.go +++ b/provisioner/ansible-local/provisioner.go @@ -191,7 +191,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { ui.Say("Provisioning with Ansible...") if len(p.config.PlaybookDir) > 0 { diff --git a/provisioner/ansible-local/provisioner_test.go b/provisioner/ansible-local/provisioner_test.go index d2af8abfb..1b8e5e34a 100644 --- a/provisioner/ansible-local/provisioner_test.go +++ b/provisioner/ansible-local/provisioner_test.go @@ -134,7 +134,7 @@ func TestProvisionerProvision_PlaybookFiles(t *testing.T) { } comm := &communicatorMock{} - if err := p.Provision(context.Background(), new(packer.NoopUi), comm); err != nil { + if err := p.Provision(context.Background(), new(packer.NoopUi), comm, make(map[string]interface{})); err != nil { t.Fatalf("err: %s", err) } @@ -168,7 +168,7 @@ func TestProvisionerProvision_PlaybookFilesWithPlaybookDir(t *testing.T) { } comm := &communicatorMock{} - if err := p.Provision(context.Background(), new(packer.NoopUi), comm); err != nil { + if err := p.Provision(context.Background(), new(packer.NoopUi), comm, make(map[string]interface{})); err != nil { t.Fatalf("err: %s", err) } @@ -343,7 +343,7 @@ func testProvisionerProvisionDockerWithPlaybookFiles(t *testing.T, templateStrin // Setup the builder builder := &docker.Builder{} - warnings, err := builder.Prepare(tpl.Builders["docker"].Config) + _, warnings, err := builder.Prepare(tpl.Builders["docker"].Config) if err != nil { t.Fatalf("Error preparing configuration %s", err) } diff --git a/provisioner/ansible/provisioner.go b/provisioner/ansible/provisioner.go index 729cc61e0..99389f924 100644 --- a/provisioner/ansible/provisioner.go +++ b/provisioner/ansible/provisioner.go @@ -31,7 +31,6 @@ import ( "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/adapter" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer/tmp" @@ -76,10 +75,7 @@ type Provisioner struct { done chan struct{} ansibleVersion string ansibleMajVersion uint -} - -type PassthroughTemplate struct { - WinRMPassword string + generatedData map[string]interface{} } func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() } @@ -87,12 +83,6 @@ func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapst func (p *Provisioner) Prepare(raws ...interface{}) error { p.done = make(chan struct{}) - // Create passthrough for winrm password so we can fill it in once we know - // it - p.config.ctx.Data = &PassthroughTemplate{ - WinRMPassword: `{{.WinRMPassword}}`, - } - err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, @@ -217,12 +207,11 @@ func (p *Provisioner) getVersion() error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { ui.Say("Provisioning with Ansible...") - // Interpolate env vars to check for .WinRMPassword - p.config.ctx.Data = &PassthroughTemplate{ - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } + // Interpolate env vars to check for generated values like password and port + p.generatedData = generatedData + p.config.ctx.Data = generatedData for i, envVar := range p.config.AnsibleEnvVars { envVar, err := interpolate.Render(envVar, &p.config.ctx) if err != nil { @@ -230,7 +219,7 @@ func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.C } p.config.AnsibleEnvVars[i] = envVar } - // Interpolate extra vars to check for .WinRMPassword + // Interpolate extra vars to check for generated values like password and port for i, arg := range p.config.ExtraArguments { arg, err := interpolate.Render(arg, &p.config.ctx) if err != nil { @@ -505,9 +494,10 @@ func (p *Provisioner) executeAnsible(ui packer.Ui, comm packer.Communicator, pri // remove winrm password from command, if it's been added flattenedCmd := strings.Join(cmd.Args, " ") sanitized := flattenedCmd - if len(getWinRMPassword(p.config.PackerBuildName)) > 0 { + winRMPass, ok := p.generatedData["WinRMPassword"] + if ok { sanitized = strings.Replace(sanitized, - getWinRMPassword(p.config.PackerBuildName), "*****", -1) + winRMPass.(string), "*****", -1) } ui.Say(fmt.Sprintf("Executing Ansible: %s", sanitized)) @@ -636,9 +626,3 @@ func newSigner(privKeyFile string) (*signer, error) { return signer, nil } - -func getWinRMPassword(buildName string) string { - winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName) - packer.LogSecretFilter.Set(winRMPass) - return winRMPass -} diff --git a/provisioner/ansible/provisioner_test.go b/provisioner/ansible/provisioner_test.go index 27fa27dc7..39035d4ed 100644 --- a/provisioner/ansible/provisioner_test.go +++ b/provisioner/ansible/provisioner_test.go @@ -349,7 +349,7 @@ func TestAnsibleLongMessages(t *testing.T) { Writer: new(bytes.Buffer), } - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatalf("err: %s", err) } diff --git a/provisioner/breakpoint/provisioner.go b/provisioner/breakpoint/provisioner.go index 4cb138cba..fa96e544b 100644 --- a/provisioner/breakpoint/provisioner.go +++ b/provisioner/breakpoint/provisioner.go @@ -45,7 +45,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { if p.config.Disable { if p.config.Note != "" { ui.Say(fmt.Sprintf( diff --git a/provisioner/chef-client/provisioner.go b/provisioner/chef-client/provisioner.go index c8d54968e..c9b57a2ae 100644 --- a/provisioner/chef-client/provisioner.go +++ b/provisioner/chef-client/provisioner.go @@ -18,7 +18,6 @@ import ( "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/uuid" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/provisioner" @@ -88,6 +87,7 @@ type Provisioner struct { communicator packer.Communicator guestOSTypeConfig guestOSTypeConfig guestCommands *provisioner.GuestCommands + generatedData map[string]interface{} } type ConfigTemplate struct { @@ -105,10 +105,6 @@ type ConfigTemplate struct { ValidationKeyPath string } -type EnvVarsTemplate struct { - WinRMPassword string -} - type ExecuteTemplate struct { ConfigPath string JsonPath string @@ -129,12 +125,8 @@ type KnifeTemplate struct { func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() } func (p *Provisioner) Prepare(raws ...interface{}) error { - // Create passthrough for winrm password so we can fill it in once we know - // it - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: `{{.WinRMPassword}}`, - } - + // Create passthrough for build-generated data + p.config.ctx.Data = packer.BasicPlaceholderData() err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, @@ -249,8 +241,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { - +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { + p.generatedData = generatedData p.communicator = comm nodeName := p.config.NodeName @@ -719,12 +711,6 @@ func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) { return result, nil } -func getWinRMPassword(buildName string) string { - winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName) - packer.LogSecretFilter.Set(winRMPass) - return winRMPass -} - func (p *Provisioner) Communicator() packer.Communicator { return p.communicator } @@ -735,9 +721,7 @@ func (p *Provisioner) ElevatedUser() string { func (p *Provisioner) ElevatedPassword() string { // Replace ElevatedPassword for winrm users who used this feature - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } + p.config.ctx.Data = p.generatedData elevatedPassword, _ := interpolate.Render(p.config.ElevatedPassword, &p.config.ctx) diff --git a/provisioner/chef-solo/provisioner.go b/provisioner/chef-solo/provisioner.go index cab586dc4..feb0a9505 100644 --- a/provisioner/chef-solo/provisioner.go +++ b/provisioner/chef-solo/provisioner.go @@ -241,7 +241,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { ui.Say("Provisioning with chef-solo") if !p.config.SkipInstall { diff --git a/provisioner/converge/provisioner.go b/provisioner/converge/provisioner.go index 99033a3c5..3cfff2540 100644 --- a/provisioner/converge/provisioner.go +++ b/provisioner/converge/provisioner.go @@ -110,7 +110,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } // Provision node somehow. TODO: actual docs -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { ui.Say("Provisioning with Converge") // bootstrapping diff --git a/provisioner/file/provisioner.go b/provisioner/file/provisioner.go index e7dc1c15a..7adf0197b 100644 --- a/provisioner/file/provisioner.go +++ b/provisioner/file/provisioner.go @@ -95,7 +95,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { if p.config.Direction == "download" { return p.ProvisionDownload(ui, comm) } else { diff --git a/provisioner/file/provisioner_test.go b/provisioner/file/provisioner_test.go index 46bccca6d..d27dfaaa7 100644 --- a/provisioner/file/provisioner_test.go +++ b/provisioner/file/provisioner_test.go @@ -127,7 +127,7 @@ func TestProvisionerProvision_SendsFile(t *testing.T) { Writer: b, } comm := &packer.MockCommunicator{} - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatalf("should successfully provision: %s", err) } diff --git a/provisioner/inspec/provisioner.go b/provisioner/inspec/provisioner.go index 099ca2e87..50a2609ca 100644 --- a/provisioner/inspec/provisioner.go +++ b/provisioner/inspec/provisioner.go @@ -189,7 +189,7 @@ func (p *Provisioner) getVersion() error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { ui.Say("Provisioning with Inspec...") for i, envVar := range p.config.InspecEnvVars { diff --git a/provisioner/powershell/provisioner.go b/provisioner/powershell/provisioner.go index d07190179..eb2383c5e 100644 --- a/provisioner/powershell/provisioner.go +++ b/provisioner/powershell/provisioner.go @@ -21,7 +21,6 @@ import ( "github.com/hashicorp/packer/common/retry" "github.com/hashicorp/packer/common/shell" "github.com/hashicorp/packer/common/uuid" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer/tmp" @@ -74,18 +73,9 @@ type Config struct { } type Provisioner struct { - config Config - communicator packer.Communicator -} - -type ExecuteCommandTemplate struct { - Vars string - Path string - WinRMPassword string -} - -type EnvVarsTemplate struct { - WinRMPassword string + config Config + communicator packer.Communicator + generatedData map[string]interface{} } func (p *Provisioner) defaultExecuteCommand() string { @@ -101,11 +91,8 @@ func (p *Provisioner) defaultExecuteCommand() string { func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() } func (p *Provisioner) Prepare(raws ...interface{}) error { - // Create passthrough for winrm password so we can fill it in once we know - // it - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: `{{.WinRMPassword}}`, - } + // Create passthrough for build-generated data + p.config.ctx.Data = packer.BasicPlaceholderData() err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, @@ -234,9 +221,10 @@ func extractScript(p *Provisioner) (string, error) { return temp.Name(), nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { ui.Say(fmt.Sprintf("Provisioning with Powershell...")) p.communicator = comm + p.generatedData = generatedData scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) @@ -346,9 +334,8 @@ func (p *Provisioner) createFlattenedEnvVars(elevated bool) (flattened string) { } // interpolate environment variables - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } + p.config.ctx.Data = p.generatedData + // Split vars into key/value components for _, envVar := range p.config.Vars { envVar, err := interpolate.Render(envVar, &p.config.ctx) @@ -420,11 +407,11 @@ func (p *Provisioner) createCommandTextNonPrivileged() (command string, err erro return "", err } - p.config.ctx.Data = &ExecuteCommandTemplate{ - Path: p.config.RemotePath, - Vars: p.config.RemoteEnvVarPath, - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } + ctxData := p.generatedData + ctxData["Path"] = p.config.RemotePath + ctxData["Vars"] = p.config.RemoteEnvVarPath + p.config.ctx.Data = ctxData + command, err = interpolate.Render(p.config.ExecuteCommand, &p.config.ctx) if err != nil { @@ -435,12 +422,6 @@ func (p *Provisioner) createCommandTextNonPrivileged() (command string, err erro return command, nil } -func getWinRMPassword(buildName string) string { - winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName) - packer.LogSecretFilter.Set(winRMPass) - return winRMPass -} - func (p *Provisioner) createCommandTextPrivileged() (command string, err error) { // Prepare everything needed to enable the required env vars within the // remote environment @@ -448,12 +429,11 @@ func (p *Provisioner) createCommandTextPrivileged() (command string, err error) if err != nil { return "", err } + ctxData := p.generatedData + ctxData["Path"] = p.config.RemotePath + ctxData["Vars"] = p.config.RemoteEnvVarPath + p.config.ctx.Data = ctxData - p.config.ctx.Data = &ExecuteCommandTemplate{ - Path: p.config.RemotePath, - Vars: p.config.RemoteEnvVarPath, - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } command, err = interpolate.Render(p.config.ElevatedExecuteCommand, &p.config.ctx) if err != nil { return "", fmt.Errorf("Error processing command: %s", err) @@ -477,10 +457,7 @@ func (p *Provisioner) ElevatedUser() string { func (p *Provisioner) ElevatedPassword() string { // Replace ElevatedPassword for winrm users who used this feature - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } - + p.config.ctx.Data = p.generatedData elevatedPassword, _ := interpolate.Render(p.config.ElevatedPassword, &p.config.ctx) return elevatedPassword diff --git a/provisioner/powershell/provisioner_test.go b/provisioner/powershell/provisioner_test.go index cef4611d1..152905bb8 100644 --- a/provisioner/powershell/provisioner_test.go +++ b/provisioner/powershell/provisioner_test.go @@ -355,7 +355,7 @@ func TestProvisionerProvision_ValidExitCodes(t *testing.T) { comm := new(packer.MockCommunicator) comm.StartExitStatus = 200 p.Prepare(config) - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -378,7 +378,7 @@ func TestProvisionerProvision_InvalidExitCodes(t *testing.T) { comm := new(packer.MockCommunicator) comm.StartExitStatus = 201 // Invalid! p.Prepare(config) - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err == nil { t.Fatal("should have error") } @@ -399,7 +399,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { p.config.PackerBuilderType = "iso" comm := new(packer.MockCommunicator) p.Prepare(config) - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -419,7 +419,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1" p.Prepare(config) - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -448,7 +448,7 @@ func TestProvisionerProvision_Scripts(t *testing.T) { p := new(Provisioner) comm := new(packer.MockCommunicator) p.Prepare(config) - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -484,7 +484,7 @@ func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) { p := new(Provisioner) comm := new(packer.MockCommunicator) p.Prepare(config) - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -511,7 +511,7 @@ func TestProvisionerProvision_UploadFails(t *testing.T) { comm := new(packer.ScriptUploadErrorMockCommunicator) p.Prepare(config) p.config.StartRetryTimeout = 1 * time.Second - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if !strings.Contains(err.Error(), packer.ScriptUploadErrorMockCommunicatorError.Error()) { t.Fatalf("expected Provision() error %q to contain %q", err.Error(), @@ -621,6 +621,7 @@ func TestProvision_createCommandText(t *testing.T) { p.config.PackerBuilderType = "iso" // Non-elevated + p.generatedData = make(map[string]interface{}) cmd, _ := p.createCommandText() re := regexp.MustCompile(`powershell -executionpolicy bypass "& { if \(Test-Path variable:global:ProgressPreference\){set-variable -name variable:global:ProgressPreference -value 'SilentlyContinue'};\. c:/Windows/Temp/packer-ps-env-vars-[[:alnum:]]{8}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{4}-[[:alnum:]]{12}\.ps1; &'c:/Windows/Temp/script.ps1'; exit \$LastExitCode }"`) diff --git a/provisioner/puppet-masterless/provisioner.go b/provisioner/puppet-masterless/provisioner.go index ed43bc427..3ec2c013f 100644 --- a/provisioner/puppet-masterless/provisioner.go +++ b/provisioner/puppet-masterless/provisioner.go @@ -14,7 +14,6 @@ import ( "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer/common" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/provisioner" @@ -131,6 +130,7 @@ type Provisioner struct { communicator packer.Communicator guestOSTypeConfig guestOSTypeConfig guestCommands *provisioner.GuestCommands + generatedData map[string]interface{} } type ExecuteTemplate struct { @@ -154,12 +154,8 @@ type EnvVarsTemplate struct { func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() } func (p *Provisioner) Prepare(raws ...interface{}) error { - // Create passthrough for winrm password so we can fill it in once we know - // it - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: `{{.WinRMPassword}}`, - } - + // Create passthrough for build-generated data + p.config.ctx.Data = packer.BasicPlaceholderData() err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, @@ -262,9 +258,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { ui.Say("Provisioning with Puppet...") p.communicator = comm + p.generatedData = generatedData ui.Message("Creating Puppet staging directory...") if err := p.createDir(ui, comm, p.config.StagingDir); err != nil { return fmt.Errorf("Error creating staging directory: %s", err) @@ -487,12 +484,6 @@ func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, ds return comm.UploadDir(dst, src, nil) } -func getWinRMPassword(buildName string) string { - winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName) - packer.LogSecretFilter.Set(winRMPass) - return winRMPass -} - func (p *Provisioner) Communicator() packer.Communicator { return p.communicator } @@ -503,9 +494,7 @@ func (p *Provisioner) ElevatedUser() string { func (p *Provisioner) ElevatedPassword() string { // Replace ElevatedPassword for winrm users who used this feature - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } + p.config.ctx.Data = p.generatedData elevatedPassword, _ := interpolate.Render(p.config.ElevatedPassword, &p.config.ctx) diff --git a/provisioner/puppet-masterless/provisioner_test.go b/provisioner/puppet-masterless/provisioner_test.go index f8a0ae782..582b8d311 100644 --- a/provisioner/puppet-masterless/provisioner_test.go +++ b/provisioner/puppet-masterless/provisioner_test.go @@ -494,7 +494,7 @@ func TestProvisionerProvision_extraArguments(t *testing.T) { t.Fatalf("err: %s", err) } - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatalf("err: %s", err) } @@ -514,7 +514,7 @@ func TestProvisionerProvision_extraArguments(t *testing.T) { t.Fatalf("err: %s", err) } - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatalf("err: %s", err) } diff --git a/provisioner/puppet-server/provisioner.go b/provisioner/puppet-server/provisioner.go index 91b0f4ca6..9468638f0 100644 --- a/provisioner/puppet-server/provisioner.go +++ b/provisioner/puppet-server/provisioner.go @@ -13,7 +13,6 @@ import ( "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer/common" - commonhelper "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/provisioner" @@ -126,6 +125,7 @@ type Provisioner struct { communicator packer.Communicator guestOSTypeConfig guestOSTypeConfig guestCommands *provisioner.GuestCommands + generatedData map[string]interface{} } type ExecuteTemplate struct { @@ -148,11 +148,8 @@ type EnvVarsTemplate struct { func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() } func (p *Provisioner) Prepare(raws ...interface{}) error { - // Create passthrough for winrm password so we can fill it in once we know - // it - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: `{{.WinRMPassword}}`, - } + // Create passthrough for build-generated data + p.config.ctx.Data = packer.BasicPlaceholderData() err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, @@ -232,9 +229,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, generatedData map[string]interface{}) error { ui.Say("Provisioning with Puppet...") p.communicator = comm + p.generatedData = generatedData ui.Message("Creating Puppet staging directory...") if err := p.createDir(ui, comm, p.config.StagingDir); err != nil { return fmt.Errorf("Error creating staging directory: %s", err) @@ -376,12 +374,6 @@ func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, ds return comm.UploadDir(dst, src, nil) } -func getWinRMPassword(buildName string) string { - winRMPass, _ := commonhelper.RetrieveSharedState("winrm_password", buildName) - packer.LogSecretFilter.Set(winRMPass) - return winRMPass -} - func (p *Provisioner) Communicator() packer.Communicator { return p.communicator } @@ -392,9 +384,7 @@ func (p *Provisioner) ElevatedUser() string { func (p *Provisioner) ElevatedPassword() string { // Replace ElevatedPassword for winrm users who used this feature - p.config.ctx.Data = &EnvVarsTemplate{ - WinRMPassword: getWinRMPassword(p.config.PackerBuildName), - } + p.config.ctx.Data = p.generatedData elevatedPassword, _ := interpolate.Render(p.config.ElevatedPassword, &p.config.ctx) diff --git a/provisioner/salt-masterless/provisioner.go b/provisioner/salt-masterless/provisioner.go index 2fddb034f..06983cd10 100644 --- a/provisioner/salt-masterless/provisioner.go +++ b/provisioner/salt-masterless/provisioner.go @@ -225,7 +225,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { var err error var src, dst string diff --git a/provisioner/shell-local/provisioner.go b/provisioner/shell-local/provisioner.go index 186644a42..991c94cea 100644 --- a/provisioner/shell-local/provisioner.go +++ b/provisioner/shell-local/provisioner.go @@ -28,8 +28,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, _ packer.Communicator) error { - _, retErr := sl.Run(ctx, ui, &p.config) +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, _ packer.Communicator, generatedData map[string]interface{}) error { + _, retErr := sl.Run(ctx, ui, &p.config, generatedData) return retErr } diff --git a/provisioner/shell/provisioner.go b/provisioner/shell/provisioner.go index f3a36c11c..a2285a6a6 100644 --- a/provisioner/shell/provisioner.go +++ b/provisioner/shell/provisioner.go @@ -182,7 +182,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) diff --git a/provisioner/sleep/provisioner.go b/provisioner/sleep/provisioner.go index d87152149..f3414c961 100644 --- a/provisioner/sleep/provisioner.go +++ b/provisioner/sleep/provisioner.go @@ -25,7 +25,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return config.Decode(&p, &config.DecodeOpts{}, raws...) } -func (p *Provisioner) Provision(ctx context.Context, _ packer.Ui, _ packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, _ packer.Ui, _ packer.Communicator, _ map[string]interface{}) error { select { case <-ctx.Done(): return ctx.Err() diff --git a/provisioner/sleep/provisioner_test.go b/provisioner/sleep/provisioner_test.go index 6ec26c59e..2ed66ff50 100644 --- a/provisioner/sleep/provisioner_test.go +++ b/provisioner/sleep/provisioner_test.go @@ -48,7 +48,7 @@ func TestProvisioner_Provision(t *testing.T) { p := &Provisioner{ Duration: tt.fields.Duration, } - if err := p.Provision(tt.args.ctx, nil, nil); (err != nil) != tt.wantErr { + if err := p.Provision(tt.args.ctx, nil, nil, make(map[string]interface{})); (err != nil) != tt.wantErr { t.Errorf("Provisioner.Provision() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/provisioner/windows-restart/provisioner.go b/provisioner/windows-restart/provisioner.go index 69f073690..f75e45ec4 100644 --- a/provisioner/windows-restart/provisioner.go +++ b/provisioner/windows-restart/provisioner.go @@ -99,7 +99,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { p.cancelLock.Lock() p.cancel = make(chan struct{}) p.cancelLock.Unlock() diff --git a/provisioner/windows-restart/provisioner_test.go b/provisioner/windows-restart/provisioner_test.go index ffe9c48a2..391068457 100644 --- a/provisioner/windows-restart/provisioner_test.go +++ b/provisioner/windows-restart/provisioner_test.go @@ -104,7 +104,7 @@ func TestProvisionerProvision_Success(t *testing.T) { waitForRestart = func(context.Context, *Provisioner, packer.Communicator) error { return nil } - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -140,7 +140,7 @@ func TestProvisionerProvision_CustomCommand(t *testing.T) { waitForRestart = func(context.Context, *Provisioner, packer.Communicator) error { return nil } - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -163,7 +163,7 @@ func TestProvisionerProvision_RestartCommandFail(t *testing.T) { comm.StartExitStatus = 1 p.Prepare(config) - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err == nil { t.Fatal("should have error") } @@ -182,7 +182,7 @@ func TestProvisionerProvision_WaitForRestartFail(t *testing.T) { waitForCommunicator = func(context.Context, *Provisioner) error { return fmt.Errorf("Machine did not restart properly") } - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err == nil { t.Fatal("should have error") } @@ -216,7 +216,7 @@ func TestProvision_waitForRestartTimeout(t *testing.T) { } go func() { - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) waitDone <- true }() <-waitContinue @@ -327,7 +327,7 @@ func TestProvision_Cancel(t *testing.T) { // Create two go routines to provision and cancel in parallel // Provision will block until cancel happens go func() { - done <- p.Provision(topCtx, ui, comm) + done <- p.Provision(topCtx, ui, comm, make(map[string]interface{})) }() // Expect interrupt error diff --git a/provisioner/windows-shell/provisioner.go b/provisioner/windows-shell/provisioner.go index c5a1289e0..4a338b234 100644 --- a/provisioner/windows-shell/provisioner.go +++ b/provisioner/windows-shell/provisioner.go @@ -159,7 +159,7 @@ func extractScript(p *Provisioner) (string, error) { return temp.Name(), nil } -func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator) error { +func (p *Provisioner) Provision(ctx context.Context, ui packer.Ui, comm packer.Communicator, _ map[string]interface{}) error { ui.Say(fmt.Sprintf("Provisioning with windows-shell...")) scripts := make([]string, len(p.config.Scripts)) copy(scripts, p.config.Scripts) diff --git a/provisioner/windows-shell/provisioner_test.go b/provisioner/windows-shell/provisioner_test.go index 32ec528e1..4a5663bdb 100644 --- a/provisioner/windows-shell/provisioner_test.go +++ b/provisioner/windows-shell/provisioner_test.go @@ -292,7 +292,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { p.config.PackerBuilderType = "iso" comm := new(packer.MockCommunicator) p.Prepare(config) - err := p.Provision(context.Background(), ui, comm) + err := p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -311,7 +311,7 @@ func TestProvisionerProvision_Inline(t *testing.T) { config["remote_path"] = "c:/Windows/Temp/inlineScript.bat" p.Prepare(config) - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -342,7 +342,7 @@ func TestProvisionerProvision_Scripts(t *testing.T) { p := new(Provisioner) comm := new(packer.MockCommunicator) p.Prepare(config) - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } @@ -381,7 +381,7 @@ func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) { p := new(Provisioner) comm := new(packer.MockCommunicator) p.Prepare(config) - err = p.Provision(context.Background(), ui, comm) + err = p.Provision(context.Background(), ui, comm, make(map[string]interface{})) if err != nil { t.Fatal("should not have error") } diff --git a/template/interpolate/funcs.go b/template/interpolate/funcs.go index 609d35f4a..9dcd5061d 100644 --- a/template/interpolate/funcs.go +++ b/template/interpolate/funcs.go @@ -12,6 +12,7 @@ import ( consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/packer/common/uuid" + "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/version" vaultapi "github.com/hashicorp/vault/api" strftime "github.com/jehiah/go-strftime" @@ -43,6 +44,7 @@ var FuncGens = map[string]interface{}{ "consul_key": funcGenConsul, "vault": funcGenVault, "sed": funcGenSed, + "build": funcGenBuild, "replace": replace, "replace_all": replace_all, @@ -162,6 +164,44 @@ func funcGenTemplateDir(ctx *Context) interface{} { } } +func funcGenBuild(ctx *Context) interface{} { + return func(s string) (string, error) { + if data, ok := ctx.Data.(map[string]string); ok { + if heldPlace, ok := data[s]; ok { + // If we're in the first interpolation pass, the goal is to + // make sure that we pass the value through. + // TODO match against an actual string constant + if strings.Contains(heldPlace, common.PlaceholderMsg) { + return fmt.Sprintf("{{.%s}}", s), nil + } else { + return heldPlace, nil + } + } + return "", fmt.Errorf("loaded data, but couldnt find %s in it.", s) + } + if data, ok := ctx.Data.(map[interface{}]interface{}); ok { + // PlaceholderData has been passed into generator, so if the given + // key already exists in data, then we know it's an "allowed" key + if heldPlace, ok := data[s]; ok { + if hp, ok := heldPlace.(string); ok { + // If we're in the first interpolation pass, the goal is to + // make sure that we pass the value through. + // TODO match against an actual string constant + if strings.Contains(hp, common.PlaceholderMsg) { + return fmt.Sprintf("{{.%s}}", s), nil + } else { + return hp, nil + } + } + } + return "", fmt.Errorf("loaded data, but couldnt find %s in it.", s) + } + + return "", fmt.Errorf("Error validating build variable: the given "+ + "variable %s will not be passed into your plugin.", s) + } +} + func funcGenTimestamp(ctx *Context) interface{} { return func() string { return strconv.FormatInt(InitTime.Unix(), 10) diff --git a/template/interpolate/funcs_test.go b/template/interpolate/funcs_test.go index f02e5678e..b9a586641 100644 --- a/template/interpolate/funcs_test.go +++ b/template/interpolate/funcs_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/version" ) @@ -318,6 +319,90 @@ func TestFuncUser(t *testing.T) { } } +func TestFuncPackerBuild(t *testing.T) { + type cases struct { + DataMap interface{} + ErrExpected bool + Template string + OutVal string + } + + testCases := []cases{ + // Data map is empty; there should be an error. + { + DataMap: nil, + ErrExpected: true, + Template: "{{ build `PartyVar` }}", + OutVal: "", + }, + // Data map is a map[string]string and contains value + { + DataMap: map[string]string{"PartyVar": "PartyVal"}, + ErrExpected: false, + Template: "{{ build `PartyVar` }}", + OutVal: "PartyVal", + }, + // Data map is a map[string]string and contains value + { + DataMap: map[string]string{"PartyVar": "PartyVal"}, + ErrExpected: false, + Template: "{{ build `PartyVar` }}", + OutVal: "PartyVal", + }, + // Data map is a map[string]string and contains value with placeholder. + { + DataMap: map[string]string{"PartyVar": "PartyVal" + common.PlaceholderMsg}, + ErrExpected: false, + Template: "{{ build `PartyVar` }}", + OutVal: "{{.PartyVar}}", + }, + // Data map is a map[interface{}]interface{} and contains value + { + DataMap: map[interface{}]interface{}{"PartyVar": "PartyVal"}, + ErrExpected: false, + Template: "{{ build `PartyVar` }}", + OutVal: "PartyVal", + }, + // Data map is a map[interface{}]interface{} and contains value + { + DataMap: map[interface{}]interface{}{"PartyVar": "PartyVal"}, + ErrExpected: false, + Template: "{{ build `PartyVar` }}", + OutVal: "PartyVal", + }, + // Data map is a map[interface{}]interface{} and contains value with placeholder. + { + DataMap: map[interface{}]interface{}{"PartyVar": "PartyVal" + common.PlaceholderMsg}, + ErrExpected: false, + Template: "{{ build `PartyVar` }}", + OutVal: "{{.PartyVar}}", + }, + // Data map is a map[interface{}]interface{} and doesn't have value. + { + DataMap: map[interface{}]interface{}{"BadVar": "PartyVal" + common.PlaceholderMsg}, + ErrExpected: true, + Template: "{{ build `MissingVar` }}", + OutVal: "", + }, + } + + for _, tc := range testCases { + ctx := &Context{} + ctx.Data = tc.DataMap + i := &I{Value: tc.Template} + + result, err := i.Render(ctx) + if (err != nil) != tc.ErrExpected { + t.Fatalf("Input: %s\n\nerr: %s", tc.Template, err) + } + + if ok := strings.Compare(result, tc.OutVal); ok != 0 { + t.Fatalf("Expected input to include: %s\n\nGot: %s", + tc.OutVal, result) + } + } +} + func TestFuncPackerVersion(t *testing.T) { template := `{{packer_version}}` diff --git a/website/source/docs/extending/custom-provisioners.html.md b/website/source/docs/extending/custom-provisioners.html.md index 3d3a1721d..7cfd55939 100644 --- a/website/source/docs/extending/custom-provisioners.html.md +++ b/website/source/docs/extending/custom-provisioners.html.md @@ -36,7 +36,7 @@ explaining what each method should do. ``` go type Provisioner interface { Prepare(...interface{}) error - Provision(Ui, Communicator) error + Provision(Ctx, Ui, Communicator, new(interface{})) error } ``` diff --git a/website/source/docs/templates/engine.html.md b/website/source/docs/templates/engine.html.md index 4c7883c88..f868669ef 100644 --- a/website/source/docs/templates/engine.html.md +++ b/website/source/docs/templates/engine.html.md @@ -62,6 +62,34 @@ Here is a full list of the available functions for reference. each function will behave. - `env` - Returns environment variables. See example in [using home variable](/docs/templates/user-variables.html#using-home-variable) +- `build` - This engine will allow you to access special variables that + provide connection information and basic instance state information. + Usage example: + ```json + { + "type": "shell-local", + "environment_vars": ["TESTVAR={{ build `PackerRunUUID`}}"], + "inline": ["echo $TESTVAR"] + }, + ``` + Valid variables to request are: "InstanceID", "CommunicatorHost", + "CommunicatorPort", "CommunicatorUser", "CommunicatorPassword", "ConnType", + "PackerRunUUID", "CommunicatorPublicKey", and "CommunicatorPrivateKey". + Depending on which communicator you are using, some of these values may be + empty -- for example, the public and private keys are unique to the SSH + communicator. InstanceID represents the vm being provisioned. For example, + in Amazon it is the instance id; in digitalocean, it is the droplet id; in + Vmware, it is the vm name. + + For backwards compatability, `WinRMPassword` is also available through this + engine, though it is no different than using the more general `Password`. + + This function is only for use within _provisioners_, and does not yet work + if the provisioners are being used in conjunction with our chroot builders + or with lxc/lxd builders. + + This engine is in beta; please report any issues or requests on the Packer + issue tracker on GitHub. - `isotime [FORMAT]` - UTC time, which can be [formatted](https://golang.org/pkg/time/#example_Time_Format). See more examples below in [the `isotime` format