From 4f5e7fe060b93821ed30a50b07f63de898d609b6 Mon Sep 17 00:00:00 2001 From: Chris Lundquist Date: Tue, 20 Mar 2018 19:30:46 +0000 Subject: [PATCH] first pass at allowing configurable sleep timeouts, profiles, and launch configs --- builder/lxd/config.go | 15 +++++++++++++-- builder/lxd/step_lxd_launch.go | 26 ++++++++++++++++++++------ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/builder/lxd/config.go b/builder/lxd/config.go index ea467f09b..bcd3aea80 100644 --- a/builder/lxd/config.go +++ b/builder/lxd/config.go @@ -2,7 +2,6 @@ package lxd import ( "fmt" - "time" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/helper/config" @@ -17,8 +16,10 @@ type Config struct { ContainerName string `mapstructure:"container_name"` CommandWrapper string `mapstructure:"command_wrapper"` Image string `mapstructure:"image"` + Profile string `mapstructure:"profile"` + InitSleep string `mapstructure:"init_sleep"` PublishProperties map[string]string `mapstructure:"publish_properties"` - InitTimeout time.Duration + LaunchConfig map[string]string `mapstructure:"launch_config"` ctx interpolate.Context } @@ -54,6 +55,16 @@ func NewConfig(raws ...interface{}) (*Config, error) { errs = packer.MultiErrorAppend(errs, fmt.Errorf("`image` is a required parameter for LXD. Please specify an image by alias or fingerprint. e.g. `ubuntu-daily:x`")) } + if c.Profile == "" { + c.Profile = "default" + } + + // Sadly we have to wait a few seconds for /tmp to be intialized and networking + // to finish starting. There isn't a great cross platform to check when things are ready. + if c.InitSleep == "" { + c.InitSleep = "3" + } + if errs != nil && len(errs.Errors) > 0 { return nil, errs } diff --git a/builder/lxd/step_lxd_launch.go b/builder/lxd/step_lxd_launch.go index 7549a408d..09464cd2d 100644 --- a/builder/lxd/step_lxd_launch.go +++ b/builder/lxd/step_lxd_launch.go @@ -3,6 +3,7 @@ package lxd import ( "context" "fmt" + "strconv" "time" "github.com/hashicorp/packer/helper/multistep" @@ -17,22 +18,35 @@ func (s *stepLxdLaunch) Run(_ context.Context, state multistep.StateBag) multist name := config.ContainerName image := config.Image + profile := fmt.Sprintf("--profile=%s", config.Profile) - args := []string{ - "launch", "--ephemeral=false", image, name, + launch_args := []string{ + "launch", "--ephemeral=false", profile, image, name, + } + + for k, v := range config.LaunchConfig { + launch_args = append(launch_args, fmt.Sprintf("--config %s=%s", k, v)) } ui.Say("Creating container...") - _, err := LXDCommand(args...) + _, err := LXDCommand(launch_args...) if err != nil { err := fmt.Errorf("Error creating container: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } + sleep_seconds, err := strconv.Atoi(config.InitSleep) + if err != nil { + err := fmt.Errorf("Error parsing InitSleep into int: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + // TODO: Should we check `lxc info ` for "Running"? // We have to do this so /tmp doesn't get cleared and lose our provisioner scripts. - time.Sleep(1 * time.Second) + time.Sleep(time.Duration(sleep_seconds) * time.Second) return multistep.ActionContinue } @@ -41,12 +55,12 @@ func (s *stepLxdLaunch) Cleanup(state multistep.StateBag) { config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) - args := []string{ + cleanup_args := []string{ "delete", "--force", config.ContainerName, } ui.Say("Unregistering and deleting deleting container...") - if _, err := LXDCommand(args...); err != nil { + if _, err := LXDCommand(cleanup_args...); err != nil { ui.Error(fmt.Sprintf("Error deleting container: %s", err)) } }