From 559efbe2d7a399091759dc05bc6b1b8e3853031a Mon Sep 17 00:00:00 2001 From: Inessa Vasilevskaya Date: Mon, 20 Jan 2025 14:49:05 +0100 Subject: [PATCH] Allow to specify user_data in a template For some cases relying on a script to be passed to shell provisioner is not enough. So let's allow user to specify actual userdata to be passed to the vm on creation, this will help in complex scenarios like persistently changing network routing that will survive reboots. Sample configuration: "user_data": "#cloud-config\nbootcmd:\n- ip route add 10.0.0.0/8 via 10.130.68.1 dev eth0" --- builder/powervs/builder.go | 1 + builder/powervs/builder.hcl2spec.go | 2 ++ builder/powervs/common/run_config.go | 1 + builder/powervs/step_create_instance.go | 3 +++ 4 files changed, 7 insertions(+) diff --git a/builder/powervs/builder.go b/builder/powervs/builder.go index 72d020d..d9b6eb6 100644 --- a/builder/powervs/builder.go +++ b/builder/powervs/builder.go @@ -103,6 +103,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &StepCreateInstance{ InstanceName: b.config.InstanceName, KeyPairName: b.config.KeyPairName, + UserData: b.config.UserData, }, &communicator.StepConnect{ Config: &b.config.RunConfig.Comm, diff --git a/builder/powervs/builder.hcl2spec.go b/builder/powervs/builder.hcl2spec.go index a6f9833..4f5fb93 100644 --- a/builder/powervs/builder.hcl2spec.go +++ b/builder/powervs/builder.hcl2spec.go @@ -28,6 +28,7 @@ type FlatConfig struct { InstanceName *string `mapstructure:"instance_name" required:"true" cty:"instance_name" hcl:"instance_name"` KeyPairName *string `mapstructure:"key_pair_name" required:"true" cty:"key_pair_name" hcl:"key_pair_name"` SubnetIDs []string `mapstructure:"subnet_ids" required:"false" cty:"subnet_ids" hcl:"subnet_ids"` + UserData *string `mapstructure:"user_data" required:"false" cty:"user_data" hcl:"user_data"` DHCPNetwork *bool `mapstructure:"dhcp_network" required:"false" cty:"dhcp_network" hcl:"dhcp_network"` Source *common.FlatSource `mapstructure:"source" required:"true" cty:"source" hcl:"source"` Capture *common.FlatCapture `mapstructure:"capture" required:"true" cty:"capture" hcl:"capture"` @@ -111,6 +112,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false}, "key_pair_name": &hcldec.AttrSpec{Name: "key_pair_name", Type: cty.String, Required: false}, "subnet_ids": &hcldec.AttrSpec{Name: "subnet_ids", Type: cty.List(cty.String), Required: false}, + "user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false}, "dhcp_network": &hcldec.AttrSpec{Name: "dhcp_network", Type: cty.Bool, Required: false}, "source": &hcldec.BlockSpec{TypeName: "source", Nested: hcldec.ObjectSpec((*common.FlatSource)(nil).HCL2Spec())}, "capture": &hcldec.BlockSpec{TypeName: "capture", Nested: hcldec.ObjectSpec((*common.FlatCapture)(nil).HCL2Spec())}, diff --git a/builder/powervs/common/run_config.go b/builder/powervs/common/run_config.go index 01368da..a268077 100644 --- a/builder/powervs/common/run_config.go +++ b/builder/powervs/common/run_config.go @@ -40,6 +40,7 @@ type RunConfig struct { InstanceName string `mapstructure:"instance_name" required:"true"` KeyPairName string `mapstructure:"key_pair_name" required:"true"` SubnetIDs []string `mapstructure:"subnet_ids" required:"false"` + UserData string `mapstructure:"user_data" required:"false"` DHCPNetwork bool `mapstructure:"dhcp_network" required:"false"` Source Source `mapstructure:"source" required:"true"` Capture Capture `mapstructure:"capture" required:"true"` diff --git a/builder/powervs/step_create_instance.go b/builder/powervs/step_create_instance.go index 4b62195..3aeef7f 100644 --- a/builder/powervs/step_create_instance.go +++ b/builder/powervs/step_create_instance.go @@ -2,6 +2,7 @@ package powervs import ( "context" + b64 "encoding/base64" "fmt" "time" @@ -15,6 +16,7 @@ import ( type StepCreateInstance struct { InstanceName string KeyPairName string + UserData string doCleanup bool } @@ -54,6 +56,7 @@ func (s *StepCreateInstance) Run(_ context.Context, state multistep.StateBag) mu Processors: core.Float64Ptr(0.5), ServerName: &s.InstanceName, StorageType: *imageRef.StorageType, + UserData: b64.StdEncoding.EncodeToString([]byte(s.UserData)), } ui.Message("Creating Instance") ins, err := instanceClient.Create(body)