diff --git a/builder/lxc/artifact.go b/builder/lxc/artifact.go deleted file mode 100644 index 0f18d7786..000000000 --- a/builder/lxc/artifact.go +++ /dev/null @@ -1,38 +0,0 @@ -package lxc - -import ( - "fmt" - "os" -) - -type Artifact struct { - dir string - f []string - // StateData should store data such as GeneratedData - // to be shared with post-processors - StateData map[string]interface{} -} - -func (*Artifact) BuilderId() string { - return BuilderId -} - -func (a *Artifact) Files() []string { - return a.f -} - -func (*Artifact) Id() string { - return "VM" -} - -func (a *Artifact) String() string { - return fmt.Sprintf("VM files in directory: %s", a.dir) -} - -func (a *Artifact) State(name string) interface{} { - return a.StateData[name] -} - -func (a *Artifact) Destroy() error { - return os.RemoveAll(a.dir) -} diff --git a/builder/lxc/builder.go b/builder/lxc/builder.go deleted file mode 100644 index df4b88a41..000000000 --- a/builder/lxc/builder.go +++ /dev/null @@ -1,91 +0,0 @@ -package lxc - -import ( - "context" - "os" - "path/filepath" - - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/hashicorp/packer-plugin-sdk/multistep" - "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -// The unique ID for this builder -const BuilderId = "ustream.lxc" - -type wrappedCommandTemplate struct { - Command string -} - -type Builder struct { - config Config - runner multistep.Runner -} - -func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } - -func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { - errs := b.config.Prepare(raws...) - if errs != nil { - return nil, nil, errs - } - - return nil, nil, nil -} - -func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - wrappedCommand := func(command string) (string, error) { - b.config.ctx.Data = &wrappedCommandTemplate{Command: command} - return interpolate.Render(b.config.CommandWrapper, &b.config.ctx) - } - - steps := []multistep.Step{ - new(stepPrepareOutputDir), - new(stepLxcCreate), - &StepWaitInit{ - WaitTimeout: b.config.InitTimeout, - }, - new(StepProvision), - new(stepExport), - } - - // Setup the state bag - state := new(multistep.BasicStateBag) - state.Put("config", &b.config) - state.Put("hook", hook) - state.Put("ui", ui) - state.Put("wrappedCommand", CommandWrapper(wrappedCommand)) - - // Run - b.runner = commonsteps.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state) - b.runner.Run(ctx, state) - - // If there was an error, return that - if rawErr, ok := state.GetOk("error"); ok { - return nil, rawErr.(error) - } - - // Compile the artifact list - files := make([]string, 0, 5) - visit := func(path string, info os.FileInfo, err error) error { - if !info.IsDir() { - files = append(files, path) - } - - return err - } - - if err := filepath.Walk(b.config.OutputDir, visit); err != nil { - return nil, err - } - - artifact := &Artifact{ - dir: b.config.OutputDir, - f: files, - StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, - } - - return artifact, nil -} diff --git a/builder/lxc/builder_test.go b/builder/lxc/builder_test.go deleted file mode 100644 index d7c3244a2..000000000 --- a/builder/lxc/builder_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package lxc - -import ( - "os" - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func testConfig() map[string]interface{} { - return map[string]interface{}{ - "config_file": "builder_test.go", - "template_name": "debian", - "template_environment_vars": "SUITE=jessie", - } -} - -func TestBuilder_Foo(t *testing.T) { - if os.Getenv("PACKER_ACC") == "" { - t.Skip("This test is only run with PACKER_ACC=1") - } -} - -func TestBuilderPrepare_ConfigFile(t *testing.T) { - var b Builder - // Good - config := testConfig() - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Bad, missing config file - config = testConfig() - delete(config, "config_file") - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatalf("should have error") - } - -} - -func TestBuilder_ImplementsBuilder(t *testing.T) { - var raw interface{} - raw = &Builder{} - if _, ok := raw.(packersdk.Builder); !ok { - t.Fatalf("Builder should be a builder") - } -} diff --git a/builder/lxc/command.go b/builder/lxc/command.go deleted file mode 100644 index 4afa56844..000000000 --- a/builder/lxc/command.go +++ /dev/null @@ -1,41 +0,0 @@ -package lxc - -import ( - "bytes" - "fmt" - "log" - "os/exec" - "strings" -) - -// CommandWrapper is a type that given a command, will possibly modify that -// command in-flight. This might return an error. -type CommandWrapper func(string) (string, error) - -// ShellCommand takes a command string and returns an *exec.Cmd to execute -// it within the context of a shell (/bin/sh). -func ShellCommand(command string) *exec.Cmd { - return exec.Command("/bin/sh", "-c", command) -} - -func RunCommand(args ...string) error { - var stdout, stderr bytes.Buffer - - log.Printf("Executing args: %#v", args) - cmd := exec.Command(args[0], args[1:]...) - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - - stdoutString := strings.TrimSpace(stdout.String()) - stderrString := strings.TrimSpace(stderr.String()) - - if _, ok := err.(*exec.ExitError); ok { - err = fmt.Errorf("Command error: %s", stderrString) - } - - log.Printf("stdout: %s", stdoutString) - log.Printf("stderr: %s", stderrString) - - return err -} diff --git a/builder/lxc/communicator.go b/builder/lxc/communicator.go deleted file mode 100644 index f73fbcc91..000000000 --- a/builder/lxc/communicator.go +++ /dev/null @@ -1,181 +0,0 @@ -package lxc - -import ( - "context" - "fmt" - "io" - "io/ioutil" - "log" - "os" - "os/exec" - "path/filepath" - "strings" - "syscall" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/tmp" -) - -type LxcAttachCommunicator struct { - RootFs string - ContainerName string - AttachOptions []string - CmdWrapper CommandWrapper -} - -func (c *LxcAttachCommunicator) Start(ctx context.Context, cmd *packersdk.RemoteCmd) error { - localCmd, err := c.Execute(cmd.Command) - - if err != nil { - return err - } - - localCmd.Stdin = cmd.Stdin - localCmd.Stdout = cmd.Stdout - localCmd.Stderr = cmd.Stderr - if err := localCmd.Start(); err != nil { - return err - } - - go func() { - exitStatus := 0 - if err := localCmd.Wait(); err != nil { - if exitErr, ok := err.(*exec.ExitError); ok { - exitStatus = 1 - - // There is no process-independent way to get the REAL - // exit status so we just try to go deeper. - if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { - exitStatus = status.ExitStatus() - } - } - } - - log.Printf( - "lxc-attach execution exited with '%d': '%s'", - exitStatus, cmd.Command) - cmd.SetExited(exitStatus) - }() - - return nil -} - -func (c *LxcAttachCommunicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error { - log.Printf("Uploading to rootfs: %s", dst) - tf, err := tmp.File("packer-lxc-attach") - if err != nil { - return fmt.Errorf("Error uploading file to rootfs: %s", err) - } - defer os.Remove(tf.Name()) - io.Copy(tf, r) - - attachCommand := []string{"cat", "%s", " | ", "lxc-attach"} - attachCommand = append(attachCommand, c.AttachOptions...) - attachCommand = append(attachCommand, []string{"--name", "%s", "--", "/bin/sh -c \"/bin/cat > %s\""}...) - - cpCmd, err := c.CmdWrapper(fmt.Sprintf(strings.Join(attachCommand, " "), tf.Name(), c.ContainerName, dst)) - if err != nil { - return err - } - - if fi != nil { - tfDir := filepath.Dir(tf.Name()) - // rename tempfile to match original file name. This makes sure that if file is being - // moved into a directory, the filename is preserved instead of a temp name. - adjustedTempName := filepath.Join(tfDir, (*fi).Name()) - mvCmd, err := c.CmdWrapper(fmt.Sprintf("mv %s %s", tf.Name(), adjustedTempName)) - if err != nil { - return err - } - defer os.Remove(adjustedTempName) - ShellCommand(mvCmd).Run() - // change cpCmd to use new file name as source - cpCmd, err = c.CmdWrapper(fmt.Sprintf(strings.Join(attachCommand, " "), adjustedTempName, c.ContainerName, dst)) - if err != nil { - return err - } - } - - log.Printf("Running copy command: %s", dst) - - return ShellCommand(cpCmd).Run() -} - -func (c *LxcAttachCommunicator) UploadDir(dst string, src string, exclude []string) error { - // TODO: remove any file copied if it appears in `exclude` - dest := filepath.Join(c.RootFs, dst) - log.Printf("Uploading directory '%s' to rootfs '%s'", src, dest) - cpCmd, err := c.CmdWrapper(fmt.Sprintf("cp -R %s/. %s", src, dest)) - if err != nil { - return err - } - - return ShellCommand(cpCmd).Run() -} - -func (c *LxcAttachCommunicator) Download(src string, w io.Writer) error { - src = filepath.Join(c.RootFs, src) - log.Printf("Downloading from rootfs dir: %s", src) - f, err := os.Open(src) - if err != nil { - return err - } - defer f.Close() - - if _, err := io.Copy(w, f); err != nil { - return err - } - - return nil -} - -func (c *LxcAttachCommunicator) DownloadDir(src string, dst string, exclude []string) error { - return fmt.Errorf("DownloadDir is not implemented for lxc") -} - -func (c *LxcAttachCommunicator) Execute(commandString string) (*exec.Cmd, error) { - log.Printf("Executing with lxc-attach in container: %s %s %s", c.ContainerName, c.RootFs, commandString) - - attachCommand := []string{"lxc-attach"} - attachCommand = append(attachCommand, c.AttachOptions...) - attachCommand = append(attachCommand, []string{"--name", "%s", "--", "/bin/sh -c \"%s\""}...) - - command, err := c.CmdWrapper( - fmt.Sprintf(strings.Join(attachCommand, " "), c.ContainerName, commandString)) - if err != nil { - return nil, err - } - - localCmd := ShellCommand(command) - log.Printf("Executing lxc-attach: %s %#v", localCmd.Path, localCmd.Args) - - return localCmd, nil -} - -func (c *LxcAttachCommunicator) CheckInit() (string, error) { - log.Printf("Debug runlevel exec") - localCmd, err := c.Execute("/sbin/runlevel") - - if err != nil { - return "", err - } - - pr, _ := localCmd.StdoutPipe() - if err = localCmd.Start(); err != nil { - return "", err - } - - output, err := ioutil.ReadAll(pr) - - if err != nil { - return "", err - } - - err = localCmd.Wait() - - if err != nil { - return "", err - } - - return strings.TrimSpace(string(output)), nil -} diff --git a/builder/lxc/communicator_test.go b/builder/lxc/communicator_test.go deleted file mode 100644 index 149a4d0ca..000000000 --- a/builder/lxc/communicator_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package lxc - -import ( - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func TestCommunicator_ImplementsCommunicator(t *testing.T) { - var raw interface{} - raw = &LxcAttachCommunicator{} - if _, ok := raw.(packersdk.Communicator); !ok { - t.Fatalf("Communicator should be a communicator") - } -} diff --git a/builder/lxc/config.go b/builder/lxc/config.go deleted file mode 100644 index 2981ca35a..000000000 --- a/builder/lxc/config.go +++ /dev/null @@ -1,114 +0,0 @@ -//go:generate packer-sdc struct-markdown -//go:generate packer-sdc mapstructure-to-hcl2 -type Config - -package lxc - -import ( - "fmt" - "os" - "time" - - "github.com/hashicorp/packer-plugin-sdk/common" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/config" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" - "github.com/mitchellh/mapstructure" -) - -type Config struct { - common.PackerConfig `mapstructure:",squash"` - // The path to the lxc configuration file. - ConfigFile string `mapstructure:"config_file" required:"true"` - // The directory in which to save the exported - // tar.gz. Defaults to `output-` in the current directory. - OutputDir string `mapstructure:"output_directory" required:"false"` - // The name of the LXC container. Usually stored - // in `/var/lib/lxc/containers/`. Defaults to - // `packer-`. - ContainerName string `mapstructure:"container_name" required:"false"` - // Allows you to specify a wrapper command, such - // as ssh so you can execute packer builds on a remote host. Defaults to - // `{{.Command}}`; i.e. no wrapper. - CommandWrapper string `mapstructure:"command_wrapper" required:"false"` - // The timeout in seconds to wait for the the - // container to start. Defaults to 20 seconds. - InitTimeout time.Duration `mapstructure:"init_timeout" required:"false"` - - // Options to pass to lxc-create. For - // instance, you can specify a custom LXC container configuration file with - // ["-f", "/path/to/lxc.conf"]. Defaults to []. See man 1 lxc-create for - // available options. - CreateOptions []string `mapstructure:"create_options" required:"false"` - // Options to pass to lxc-start. For - // instance, you can override parameters from the LXC container configuration - // file via ["--define", "KEY=VALUE"]. Defaults to []. See - // man 1 lxc-start for available options. - StartOptions []string `mapstructure:"start_options" required:"false"` - // Options to pass to lxc-attach. For - // instance, you can prevent the container from inheriting the host machine's - // environment by specifying ["--clear-env"]. Defaults to []. See - // man 1 lxc-attach for available options. - AttachOptions []string `mapstructure:"attach_options" required:"false"` - // The LXC template name to use. - Name string `mapstructure:"template_name" required:"true"` - // Options to pass to the given - // lxc-template command, usually located in - // `/usr/share/lxc/templates/lxc-`. Note: This gets passed as - // ARGV to the template command. Ensure you have an array of strings, as a - // single string with spaces probably won't work. Defaults to []. - Parameters []string `mapstructure:"template_parameters" required:"false"` - // Environmental variables to - // use to build the template with. - EnvVars []string `mapstructure:"template_environment_vars" required:"true"` - // The minimum run level to wait for the - // container to reach. Note some distributions (Ubuntu) simulate run levels - // and may report 5 rather than 3. - TargetRunlevel int `mapstructure:"target_runlevel" required:"false"` - - ctx interpolate.Context -} - -func (c *Config) Prepare(raws ...interface{}) error { - - var md mapstructure.Metadata - err := config.Decode(c, &config.DecodeOpts{ - Metadata: &md, - Interpolate: true, - }, raws...) - if err != nil { - return err - } - - // Accumulate any errors - var errs *packersdk.MultiError - - if c.OutputDir == "" { - c.OutputDir = fmt.Sprintf("output-%s", c.PackerBuildName) - } - - if c.ContainerName == "" { - c.ContainerName = fmt.Sprintf("packer-%s", c.PackerBuildName) - } - - if c.TargetRunlevel == 0 { - c.TargetRunlevel = 3 - } - - if c.CommandWrapper == "" { - c.CommandWrapper = "{{.Command}}" - } - - if c.InitTimeout == 0 { - c.InitTimeout = 20 * time.Second - } - - if _, err := os.Stat(c.ConfigFile); os.IsNotExist(err) { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("LXC Config file appears to be missing: %s", c.ConfigFile)) - } - - if errs != nil && len(errs.Errors) > 0 { - return errs - } - - return nil -} diff --git a/builder/lxc/config.hcl2spec.go b/builder/lxc/config.hcl2spec.go deleted file mode 100644 index 1aa474f1c..000000000 --- a/builder/lxc/config.hcl2spec.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package lxc - -import ( - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/zclconf/go-cty/cty" -) - -// FlatConfig is an auto-generated flat version of Config. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatConfig struct { - PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"` - PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"` - PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"` - PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"` - PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"` - PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"` - PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"` - PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"` - ConfigFile *string `mapstructure:"config_file" required:"true" cty:"config_file" hcl:"config_file"` - OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory" hcl:"output_directory"` - ContainerName *string `mapstructure:"container_name" required:"false" cty:"container_name" hcl:"container_name"` - CommandWrapper *string `mapstructure:"command_wrapper" required:"false" cty:"command_wrapper" hcl:"command_wrapper"` - InitTimeout *string `mapstructure:"init_timeout" required:"false" cty:"init_timeout" hcl:"init_timeout"` - CreateOptions []string `mapstructure:"create_options" required:"false" cty:"create_options" hcl:"create_options"` - StartOptions []string `mapstructure:"start_options" required:"false" cty:"start_options" hcl:"start_options"` - AttachOptions []string `mapstructure:"attach_options" required:"false" cty:"attach_options" hcl:"attach_options"` - Name *string `mapstructure:"template_name" required:"true" cty:"template_name" hcl:"template_name"` - Parameters []string `mapstructure:"template_parameters" required:"false" cty:"template_parameters" hcl:"template_parameters"` - EnvVars []string `mapstructure:"template_environment_vars" required:"true" cty:"template_environment_vars" hcl:"template_environment_vars"` - TargetRunlevel *int `mapstructure:"target_runlevel" required:"false" cty:"target_runlevel" hcl:"target_runlevel"` -} - -// FlatMapstructure returns a new FlatConfig. -// FlatConfig is an auto-generated flat version of Config. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatConfig) -} - -// HCL2Spec returns the hcl spec of a Config. -// This spec is used by HCL to read the fields of Config. -// The decoded values from this spec will then be applied to a FlatConfig. -func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "config_file": &hcldec.AttrSpec{Name: "config_file", Type: cty.String, Required: false}, - "output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false}, - "container_name": &hcldec.AttrSpec{Name: "container_name", Type: cty.String, Required: false}, - "command_wrapper": &hcldec.AttrSpec{Name: "command_wrapper", Type: cty.String, Required: false}, - "init_timeout": &hcldec.AttrSpec{Name: "init_timeout", Type: cty.String, Required: false}, - "create_options": &hcldec.AttrSpec{Name: "create_options", Type: cty.List(cty.String), Required: false}, - "start_options": &hcldec.AttrSpec{Name: "start_options", Type: cty.List(cty.String), Required: false}, - "attach_options": &hcldec.AttrSpec{Name: "attach_options", Type: cty.List(cty.String), Required: false}, - "template_name": &hcldec.AttrSpec{Name: "template_name", Type: cty.String, Required: false}, - "template_parameters": &hcldec.AttrSpec{Name: "template_parameters", Type: cty.List(cty.String), Required: false}, - "template_environment_vars": &hcldec.AttrSpec{Name: "template_environment_vars", Type: cty.List(cty.String), Required: false}, - "target_runlevel": &hcldec.AttrSpec{Name: "target_runlevel", Type: cty.Number, Required: false}, - } - return s -} diff --git a/builder/lxc/step_export.go b/builder/lxc/step_export.go deleted file mode 100644 index e57f397c9..000000000 --- a/builder/lxc/step_export.go +++ /dev/null @@ -1,87 +0,0 @@ -package lxc - -import ( - "context" - "fmt" - "io" - "log" - "os" - "os/user" - "path/filepath" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepExport struct{} - -func (s *stepExport) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - name := config.ContainerName - - lxc_dir := "/var/lib/lxc" - user, err := user.Current() - if err != nil { - log.Print("Cannot find current user. Falling back to /var/lib/lxc...") - } - if user.Uid != "0" && user.HomeDir != "" { - lxc_dir = filepath.Join(user.HomeDir, ".local", "share", "lxc") - } - - containerDir := filepath.Join(lxc_dir, name) - outputPath := filepath.Join(config.OutputDir, "rootfs.tar.gz") - configFilePath := filepath.Join(config.OutputDir, "lxc-config") - - configFile, err := os.Create(configFilePath) - - if err != nil { - err := fmt.Errorf("Error creating config file: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - originalConfigFile, err := os.Open(config.ConfigFile) - - if err != nil { - err := fmt.Errorf("Error opening config file: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - _, err = io.Copy(configFile, originalConfigFile) - if err != nil { - err := fmt.Errorf("error copying file %s: %v", config.ConfigFile, err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - commands := make([][]string, 3) - commands[0] = []string{ - "lxc-stop", "--name", name, - } - commands[1] = []string{ - "tar", "-C", containerDir, "--numeric-owner", "--anchored", "--exclude=./rootfs/dev/log", "-czf", outputPath, "./rootfs", - } - commands[2] = []string{ - "chmod", "+x", configFilePath, - } - - ui.Say("Exporting container...") - for _, command := range commands { - err := RunCommand(command...) - if err != nil { - err := fmt.Errorf("Error exporting container: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - } - - return multistep.ActionContinue -} - -func (s *stepExport) Cleanup(state multistep.StateBag) {} diff --git a/builder/lxc/step_lxc_create.go b/builder/lxc/step_lxc_create.go deleted file mode 100644 index e5b4ddb15..000000000 --- a/builder/lxc/step_lxc_create.go +++ /dev/null @@ -1,78 +0,0 @@ -package lxc - -import ( - "context" - "fmt" - "log" - "os/user" - "path/filepath" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepLxcCreate struct{} - -func (s *stepLxcCreate) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - name := config.ContainerName - - // TODO: read from env - lxc_dir := "/var/lib/lxc" - user, err := user.Current() - if err != nil { - log.Print("Cannot find current user. Falling back to /var/lib/lxc...") - } - if user.Uid != "0" && user.HomeDir != "" { - lxc_dir = filepath.Join(user.HomeDir, ".local", "share", "lxc") - } - rootfs := filepath.Join(lxc_dir, name, "rootfs") - - if config.PackerForce { - s.Cleanup(state) - } - - commands := make([][]string, 3) - commands[0] = append(commands[0], "env") - commands[0] = append(commands[0], config.EnvVars...) - commands[0] = append(commands[0], "lxc-create") - commands[0] = append(commands[0], config.CreateOptions...) - commands[0] = append(commands[0], []string{"-n", name, "-t", config.Name, "--"}...) - commands[0] = append(commands[0], config.Parameters...) - // prevent tmp from being cleaned on boot, we put provisioning scripts there - // todo: wait for init to finish before moving on to provisioning instead of this - commands[1] = []string{"touch", filepath.Join(rootfs, "tmp", ".tmpfs")} - commands[2] = append([]string{"lxc-start"}, config.StartOptions...) - commands[2] = append(commands[2], []string{"-d", "--name", name}...) - - ui.Say("Creating container...") - for _, command := range commands { - err := RunCommand(command...) - if err != nil { - err := fmt.Errorf("Error creating container: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - } - - state.Put("mount_path", rootfs) - - return multistep.ActionContinue -} - -func (s *stepLxcCreate) Cleanup(state multistep.StateBag) { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - command := []string{ - "lxc-destroy", "-f", "-n", config.ContainerName, - } - - ui.Say("Unregistering and deleting virtual machine...") - if err := RunCommand(command...); err != nil { - ui.Error(fmt.Sprintf("Error deleting virtual machine: %s", err)) - } -} diff --git a/builder/lxc/step_prepare_output_dir.go b/builder/lxc/step_prepare_output_dir.go deleted file mode 100644 index c38f90f8f..000000000 --- a/builder/lxc/step_prepare_output_dir.go +++ /dev/null @@ -1,51 +0,0 @@ -package lxc - -import ( - "context" - "log" - "os" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepPrepareOutputDir struct{} - -func (stepPrepareOutputDir) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - if _, err := os.Stat(config.OutputDir); err == nil && config.PackerForce { - ui.Say("Deleting previous output directory...") - os.RemoveAll(config.OutputDir) - } - - if err := os.MkdirAll(config.OutputDir, 0755); err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - - return multistep.ActionContinue -} - -func (stepPrepareOutputDir) Cleanup(state multistep.StateBag) { - _, cancelled := state.GetOk(multistep.StateCancelled) - _, halted := state.GetOk(multistep.StateHalted) - - if cancelled || halted { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - ui.Say("Deleting output directory...") - for i := 0; i < 5; i++ { - err := os.RemoveAll(config.OutputDir) - if err == nil { - break - } - - log.Printf("Error removing output dir: %s", err) - time.Sleep(2 * time.Second) - } - } -} diff --git a/builder/lxc/step_provision.go b/builder/lxc/step_provision.go deleted file mode 100644 index 435f57e1b..000000000 --- a/builder/lxc/step_provision.go +++ /dev/null @@ -1,47 +0,0 @@ -package lxc - -import ( - "context" - "log" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -// StepProvision provisions the instance within a chroot. -type StepProvision struct{} - -func (s *StepProvision) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - hook := state.Get("hook").(packersdk.Hook) - config := state.Get("config").(*Config) - mountPath := state.Get("mount_path").(string) - ui := state.Get("ui").(packersdk.Ui) - wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) - - // Create our communicator - comm := &LxcAttachCommunicator{ - ContainerName: config.ContainerName, - AttachOptions: config.AttachOptions, - RootFs: mountPath, - CmdWrapper: wrappedCommand, - } - - // Loads hook data from builder's state, if it has been set. - hookData := commonsteps.PopulateProvisionHookData(state) - - // Update state generated_data with complete hookData - // to make them accessible by post-processors - state.Put("generated_data", hookData) - - // Provision - log.Println("Running the provision hook") - if err := hook.Run(ctx, packersdk.HookProvision, ui, comm, hookData); err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - - return multistep.ActionContinue -} - -func (s *StepProvision) Cleanup(state multistep.StateBag) {} diff --git a/builder/lxc/step_wait_init.go b/builder/lxc/step_wait_init.go deleted file mode 100644 index fb9840231..000000000 --- a/builder/lxc/step_wait_init.go +++ /dev/null @@ -1,105 +0,0 @@ -package lxc - -import ( - "context" - "errors" - "fmt" - "log" - "strings" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type StepWaitInit struct { - WaitTimeout time.Duration -} - -func (s *StepWaitInit) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - - var err error - - cancel := make(chan struct{}) - waitDone := make(chan bool, 1) - go func() { - ui.Say("Waiting for container to finish init...") - err = s.waitForInit(state, cancel) - waitDone <- true - }() - - log.Printf("Waiting for container to finish init, up to timeout: %s", s.WaitTimeout) - timeout := time.After(s.WaitTimeout) -WaitLoop: - for { - select { - case <-waitDone: - if err != nil { - ui.Error(fmt.Sprintf("Error waiting for container to finish init: %s", err)) - return multistep.ActionHalt - } - - ui.Say("Container finished init!") - break WaitLoop - case <-timeout: - err := fmt.Errorf("Timeout waiting for container to finish init.") - state.Put("error", err) - ui.Error(err.Error()) - close(cancel) - return multistep.ActionHalt - case <-time.After(1 * time.Second): - if _, ok := state.GetOk(multistep.StateCancelled); ok { - close(cancel) - log.Println("Interrupt detected, quitting waiting for container to finish init.") - return multistep.ActionHalt - } - } - } - - return multistep.ActionContinue -} - -func (s *StepWaitInit) Cleanup(multistep.StateBag) { -} - -func (s *StepWaitInit) waitForInit(state multistep.StateBag, cancel <-chan struct{}) error { - config := state.Get("config").(*Config) - mountPath := state.Get("mount_path").(string) - wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) - - for { - select { - case <-cancel: - log.Println("Cancelled. Exiting loop.") - return errors.New("Wait cancelled") - case <-time.After(1 * time.Second): - } - - comm := &LxcAttachCommunicator{ - ContainerName: config.ContainerName, - AttachOptions: config.AttachOptions, - RootFs: mountPath, - CmdWrapper: wrappedCommand, - } - - runlevel, _ := comm.CheckInit() - currentRunlevel := "unknown" - if arr := strings.Split(runlevel, " "); len(arr) >= 2 { - currentRunlevel = arr[1] - } - - log.Printf("Current runlevel in container: '%s'", runlevel) - - targetRunlevel := fmt.Sprintf("%d", config.TargetRunlevel) - if currentRunlevel == targetRunlevel { - log.Printf("Container finished init.") - break - } else if currentRunlevel > targetRunlevel { - log.Printf("Expected Runlevel %s, Got Runlevel %s, continuing", targetRunlevel, currentRunlevel) - break - } - } - - return nil -} diff --git a/builder/lxc/version/version.go b/builder/lxc/version/version.go deleted file mode 100644 index 7d85f3295..000000000 --- a/builder/lxc/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import ( - "github.com/hashicorp/packer-plugin-sdk/version" - packerVersion "github.com/hashicorp/packer/version" -) - -var LXCPluginVersion *version.PluginVersion - -func init() { - LXCPluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/builder/lxd/artifact.go b/builder/lxd/artifact.go deleted file mode 100644 index ad229a82c..000000000 --- a/builder/lxd/artifact.go +++ /dev/null @@ -1,38 +0,0 @@ -package lxd - -import ( - "fmt" -) - -type Artifact struct { - id string - - // StateData should store data such as GeneratedData - // to be shared with post-processors - StateData map[string]interface{} -} - -func (*Artifact) BuilderId() string { - return BuilderId -} - -func (a *Artifact) Files() []string { - return nil -} - -func (a *Artifact) Id() string { - return a.id -} - -func (a *Artifact) String() string { - return fmt.Sprintf("image: %s", a.id) -} - -func (a *Artifact) State(name string) interface{} { - return a.StateData[name] -} - -func (a *Artifact) Destroy() error { - _, err := LXDCommand("image", "delete", a.id) - return err -} diff --git a/builder/lxd/builder.go b/builder/lxd/builder.go deleted file mode 100644 index f1b2ca81d..000000000 --- a/builder/lxd/builder.go +++ /dev/null @@ -1,70 +0,0 @@ -package lxd - -import ( - "context" - - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/hashicorp/packer-plugin-sdk/multistep" - "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -// The unique ID for this builder -const BuilderId = "lxd" - -type wrappedCommandTemplate struct { - Command string -} - -type Builder struct { - config Config - runner multistep.Runner -} - -func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } - -func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { - errs := b.config.Prepare(raws...) - if errs != nil { - return nil, nil, errs - } - - return nil, nil, nil -} - -func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - wrappedCommand := func(command string) (string, error) { - b.config.ctx.Data = &wrappedCommandTemplate{Command: command} - return interpolate.Render(b.config.CommandWrapper, &b.config.ctx) - } - - steps := []multistep.Step{ - &stepLxdLaunch{}, - &StepProvision{}, - &stepPublish{}, - } - - // Setup the state bag - state := new(multistep.BasicStateBag) - state.Put("config", &b.config) - state.Put("hook", hook) - state.Put("ui", ui) - state.Put("wrappedCommand", CommandWrapper(wrappedCommand)) - - // Run - b.runner = commonsteps.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state) - b.runner.Run(ctx, state) - - // If there was an error, return that - if rawErr, ok := state.GetOk("error"); ok { - return nil, rawErr.(error) - } - - artifact := &Artifact{ - id: state.Get("imageFingerprint").(string), - StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, - } - - return artifact, nil -} diff --git a/builder/lxd/builder_test.go b/builder/lxd/builder_test.go deleted file mode 100644 index ce0871db8..000000000 --- a/builder/lxd/builder_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package lxd - -import ( - "os" - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func testConfig() map[string]interface{} { - return map[string]interface{}{ - "output_image": "foo", - "image": "bar", - } -} - -func TestBuilder_Foo(t *testing.T) { - if os.Getenv("PACKER_ACC") == "" { - t.Skip("This test is only run with PACKER_ACC=1") - } -} - -func TestBuilderPrepare_ConfigFile(t *testing.T) { - var b Builder - // Good - config := testConfig() - _, warnings, err := b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Good, remote image - config = testConfig() - config["image"] = "remote:bar" - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Good, remote output image - config = testConfig() - config["output_image"] = "remote:foo" - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err != nil { - t.Fatalf("should not have error: %s", err) - } - - // Bad, missing image name - config = testConfig() - delete(config, "image") - b = Builder{} - _, warnings, err = b.Prepare(config) - if len(warnings) > 0 { - t.Fatalf("bad: %#v", warnings) - } - if err == nil { - t.Fatalf("should have error") - } - -} - -func TestBuilder_ImplementsBuilder(t *testing.T) { - var raw interface{} - raw = &Builder{} - if _, ok := raw.(packersdk.Builder); !ok { - t.Fatalf("Builder should be a builder") - } -} diff --git a/builder/lxd/command.go b/builder/lxd/command.go deleted file mode 100644 index c9a39279d..000000000 --- a/builder/lxd/command.go +++ /dev/null @@ -1,43 +0,0 @@ -package lxd - -import ( - "bytes" - "fmt" - "log" - "os/exec" - "strings" -) - -// CommandWrapper is a type that given a command, will possibly modify that -// command in-flight. This might return an error. -type CommandWrapper func(string) (string, error) - -// ShellCommand takes a command string and returns an *exec.Cmd to execute -// it within the context of a shell (/bin/sh). -func ShellCommand(command string) *exec.Cmd { - return exec.Command("/bin/sh", "-c", command) -} - -// Yeah...LXD calls `lxc` because the command line is different between the -// packages. This should also avoid a naming collision between the LXC builder. -func LXDCommand(args ...string) (string, error) { - var stdout, stderr bytes.Buffer - - log.Printf("Executing lxc command: %#v", args) - cmd := exec.Command("lxc", args...) - cmd.Stdout = &stdout - cmd.Stderr = &stderr - err := cmd.Run() - - stdoutString := strings.TrimSpace(stdout.String()) - stderrString := strings.TrimSpace(stderr.String()) - - if _, ok := err.(*exec.ExitError); ok { - err = fmt.Errorf("LXD command error: %s", stderrString) - } - - log.Printf("stdout: %s", stdoutString) - log.Printf("stderr: %s", stderrString) - - return stdoutString, err -} diff --git a/builder/lxd/communicator.go b/builder/lxd/communicator.go deleted file mode 100644 index aebd70905..000000000 --- a/builder/lxd/communicator.go +++ /dev/null @@ -1,142 +0,0 @@ -package lxd - -import ( - "context" - "fmt" - "io" - "log" - "os" - "os/exec" - "path/filepath" - "syscall" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type Communicator struct { - ContainerName string - CmdWrapper CommandWrapper -} - -func (c *Communicator) Start(ctx context.Context, cmd *packersdk.RemoteCmd) error { - localCmd, err := c.Execute(cmd.Command) - - if err != nil { - return err - } - - localCmd.Stdin = cmd.Stdin - localCmd.Stdout = cmd.Stdout - localCmd.Stderr = cmd.Stderr - if err := localCmd.Start(); err != nil { - return err - } - - go func() { - exitStatus := 0 - if err := localCmd.Wait(); err != nil { - if exitErr, ok := err.(*exec.ExitError); ok { - exitStatus = 1 - - // There is no process-independent way to get the REAL - // exit status so we just try to go deeper. - if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { - exitStatus = status.ExitStatus() - } - } - } - - log.Printf( - "lxc exec execution exited with '%d': '%s'", - exitStatus, cmd.Command) - cmd.SetExited(exitStatus) - }() - - return nil -} - -func (c *Communicator) Upload(dst string, r io.Reader, fi *os.FileInfo) error { - ctx := context.TODO() - - fileDestination := filepath.Join(c.ContainerName, dst) - // find out if the place we are pushing to is a directory - testDirectoryCommand := fmt.Sprintf(`test -d "%s"`, dst) - cmd := &packersdk.RemoteCmd{Command: testDirectoryCommand} - err := c.Start(ctx, cmd) - - if err != nil { - log.Printf("Unable to check whether remote path is a dir: %s", err) - return err - } - cmd.Wait() - - if cmd.ExitStatus() == 0 { - log.Printf("path is a directory; copying file into directory.") - fileDestination = filepath.Join(c.ContainerName, dst, (*fi).Name()) - } - - cpCmd, err := c.CmdWrapper(fmt.Sprintf("lxc file push - %s", fileDestination)) - if err != nil { - return err - } - - log.Printf("Running copy command: %s", cpCmd) - command := ShellCommand(cpCmd) - command.Stdin = r - - return command.Run() -} - -func (c *Communicator) UploadDir(dst string, src string, exclude []string) error { - fileDestination := fmt.Sprintf("%s/%s", c.ContainerName, dst) - pushCommand := fmt.Sprintf("lxc file push --debug -pr %s %s", src, fileDestination) - log.Printf(pushCommand) - cp, err := c.CmdWrapper(pushCommand) - if err != nil { - log.Printf("Error running cp command: %s", err) - return err - } - - cpCmd := ShellCommand(cp) - - log.Printf("Running cp command: %s", cp) - err = cpCmd.Run() - if err != nil { - log.Printf("Error running cp command: %s", err) - return err - } - - return nil -} - -func (c *Communicator) Download(src string, w io.Writer) error { - cpCmd, err := c.CmdWrapper(fmt.Sprintf("lxc file pull %s -", filepath.Join(c.ContainerName, src))) - if err != nil { - return err - } - - log.Printf("Running copy command: %s", cpCmd) - command := ShellCommand(cpCmd) - command.Stdout = w - - return command.Run() -} - -func (c *Communicator) DownloadDir(src string, dst string, exclude []string) error { - // TODO This could probably be "lxc exec -- cd && tar -czf - | tar -xzf - -C " - return fmt.Errorf("DownloadDir is not implemented for lxc") -} - -func (c *Communicator) Execute(commandString string) (*exec.Cmd, error) { - log.Printf("Executing with lxc exec in container: %s %s", c.ContainerName, commandString) - command, err := c.CmdWrapper( - fmt.Sprintf("lxc exec %s -- /bin/sh -c \"%s\"", c.ContainerName, commandString)) - if err != nil { - return nil, err - } - - localCmd := ShellCommand(command) - log.Printf("Executing lxc exec: %s %#v", localCmd.Path, localCmd.Args) - - return localCmd, nil -} diff --git a/builder/lxd/communicator_test.go b/builder/lxd/communicator_test.go deleted file mode 100644 index de46eb313..000000000 --- a/builder/lxd/communicator_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package lxd - -import ( - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func TestCommunicator_ImplementsCommunicator(t *testing.T) { - var raw interface{} - raw = &Communicator{} - if _, ok := raw.(packersdk.Communicator); !ok { - t.Fatalf("Communicator should be a communicator") - } -} - -// Acceptance tests -// TODO Execute a command -// TODO Upload a file -// TODO Download a file -// TODO Upload a Directory diff --git a/builder/lxd/config.go b/builder/lxd/config.go deleted file mode 100644 index 6e3670b6a..000000000 --- a/builder/lxd/config.go +++ /dev/null @@ -1,92 +0,0 @@ -//go:generate packer-sdc struct-markdown -//go:generate packer-sdc mapstructure-to-hcl2 -type Config - -package lxd - -import ( - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/common" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/config" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" - "github.com/mitchellh/mapstructure" -) - -type Config struct { - common.PackerConfig `mapstructure:",squash"` - // The name of the output artifact. Defaults to - // name. - OutputImage string `mapstructure:"output_image" required:"false"` - ContainerName string `mapstructure:"container_name"` - // Lets you prefix all builder commands, such as - // with ssh for a remote build host. Defaults to `{{.Command}}`; i.e. no - // wrapper. - CommandWrapper string `mapstructure:"command_wrapper" required:"false"` - // The source image to use when creating the build - // container. This can be a (local or remote) image (name or fingerprint). - // E.G. my-base-image, ubuntu-daily:x, 08fababf6f27, ... - Image string `mapstructure:"image" required:"true"` - Profile string `mapstructure:"profile"` - // The number of seconds to sleep between launching - // the LXD instance and provisioning it; defaults to 3 seconds. - InitSleep string `mapstructure:"init_sleep" required:"false"` - // Pass key values to the publish - // step to be set as properties on the output image. This is most helpful to - // set the description, but can be used to set anything needed. See - // https://stgraber.org/2016/03/30/lxd-2-0-image-management-512/ - // for more properties. - PublishProperties map[string]string `mapstructure:"publish_properties" required:"false"` - // List of key/value pairs you wish to - // pass to lxc launch via --config. Defaults to empty. - LaunchConfig map[string]string `mapstructure:"launch_config" required:"false"` - - ctx interpolate.Context -} - -func (c *Config) Prepare(raws ...interface{}) error { - - var md mapstructure.Metadata - err := config.Decode(c, &config.DecodeOpts{ - Metadata: &md, - Interpolate: true, - }, raws...) - if err != nil { - return err - } - - // Accumulate any errors - var errs *packersdk.MultiError - - if c.ContainerName == "" { - c.ContainerName = fmt.Sprintf("packer-%s", c.PackerBuildName) - } - - if c.OutputImage == "" { - c.OutputImage = c.ContainerName - } - - if c.CommandWrapper == "" { - c.CommandWrapper = "{{.Command}}" - } - - if c.Image == "" { - errs = packersdk.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 errs - } - - return nil -} diff --git a/builder/lxd/config.hcl2spec.go b/builder/lxd/config.hcl2spec.go deleted file mode 100644 index 7acf90ce9..000000000 --- a/builder/lxd/config.hcl2spec.go +++ /dev/null @@ -1,61 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package lxd - -import ( - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/zclconf/go-cty/cty" -) - -// FlatConfig is an auto-generated flat version of Config. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatConfig struct { - PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"` - PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"` - PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"` - PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"` - PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"` - PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"` - PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"` - PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"` - OutputImage *string `mapstructure:"output_image" required:"false" cty:"output_image" hcl:"output_image"` - ContainerName *string `mapstructure:"container_name" cty:"container_name" hcl:"container_name"` - CommandWrapper *string `mapstructure:"command_wrapper" required:"false" cty:"command_wrapper" hcl:"command_wrapper"` - Image *string `mapstructure:"image" required:"true" cty:"image" hcl:"image"` - Profile *string `mapstructure:"profile" cty:"profile" hcl:"profile"` - InitSleep *string `mapstructure:"init_sleep" required:"false" cty:"init_sleep" hcl:"init_sleep"` - PublishProperties map[string]string `mapstructure:"publish_properties" required:"false" cty:"publish_properties" hcl:"publish_properties"` - LaunchConfig map[string]string `mapstructure:"launch_config" required:"false" cty:"launch_config" hcl:"launch_config"` -} - -// FlatMapstructure returns a new FlatConfig. -// FlatConfig is an auto-generated flat version of Config. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatConfig) -} - -// HCL2Spec returns the hcl spec of a Config. -// This spec is used by HCL to read the fields of Config. -// The decoded values from this spec will then be applied to a FlatConfig. -func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "output_image": &hcldec.AttrSpec{Name: "output_image", Type: cty.String, Required: false}, - "container_name": &hcldec.AttrSpec{Name: "container_name", Type: cty.String, Required: false}, - "command_wrapper": &hcldec.AttrSpec{Name: "command_wrapper", Type: cty.String, Required: false}, - "image": &hcldec.AttrSpec{Name: "image", Type: cty.String, Required: false}, - "profile": &hcldec.AttrSpec{Name: "profile", Type: cty.String, Required: false}, - "init_sleep": &hcldec.AttrSpec{Name: "init_sleep", Type: cty.String, Required: false}, - "publish_properties": &hcldec.AttrSpec{Name: "publish_properties", Type: cty.Map(cty.String), Required: false}, - "launch_config": &hcldec.AttrSpec{Name: "launch_config", Type: cty.Map(cty.String), Required: false}, - } - return s -} diff --git a/builder/lxd/step_lxd_launch.go b/builder/lxd/step_lxd_launch.go deleted file mode 100644 index 7730d508b..000000000 --- a/builder/lxd/step_lxd_launch.go +++ /dev/null @@ -1,68 +0,0 @@ -package lxd - -import ( - "context" - "fmt" - "log" - "strconv" - "time" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepLxdLaunch struct{} - -func (s *stepLxdLaunch) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - name := config.ContainerName - image := config.Image - profile := fmt.Sprintf("--profile=%s", config.Profile) - - launch_args := []string{ - "launch", "--ephemeral=false", profile, image, name, - } - - for k, v := range config.LaunchConfig { - launch_args = append(launch_args, "--config", fmt.Sprintf("%s=%s", k, v)) - } - - ui.Say("Creating container...") - _, 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(time.Duration(sleep_seconds) * time.Second) - log.Printf("Sleeping for %d seconds...", sleep_seconds) - return multistep.ActionContinue -} - -func (s *stepLxdLaunch) Cleanup(state multistep.StateBag) { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - cleanup_args := []string{ - "delete", "--force", config.ContainerName, - } - - ui.Say("Unregistering and deleting deleting container...") - if _, err := LXDCommand(cleanup_args...); err != nil { - ui.Error(fmt.Sprintf("Error deleting container: %s", err)) - } -} diff --git a/builder/lxd/step_provision.go b/builder/lxd/step_provision.go deleted file mode 100644 index e0c0efada..000000000 --- a/builder/lxd/step_provision.go +++ /dev/null @@ -1,44 +0,0 @@ -package lxd - -import ( - "context" - "log" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -// StepProvision provisions the container -type StepProvision struct{} - -func (s *StepProvision) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - hook := state.Get("hook").(packersdk.Hook) - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - wrappedCommand := state.Get("wrappedCommand").(CommandWrapper) - - // Create our communicator - comm := &Communicator{ - ContainerName: config.ContainerName, - CmdWrapper: wrappedCommand, - } - - // Loads hook data from builder's state, if it has been set. - hookData := commonsteps.PopulateProvisionHookData(state) - - // Update state generated_data with complete hookData - // to make them accessible by post-processors - state.Put("generated_data", hookData) - - // Provision - log.Println("Running the provision hook") - if err := hook.Run(ctx, packersdk.HookProvision, ui, comm, hookData); err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - - return multistep.ActionContinue -} - -func (s *StepProvision) Cleanup(state multistep.StateBag) {} diff --git a/builder/lxd/step_publish.go b/builder/lxd/step_publish.go deleted file mode 100644 index 992bc1bc0..000000000 --- a/builder/lxd/step_publish.go +++ /dev/null @@ -1,60 +0,0 @@ -package lxd - -import ( - "context" - "fmt" - "regexp" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepPublish struct{} - -func (s *stepPublish) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - config := state.Get("config").(*Config) - ui := state.Get("ui").(packersdk.Ui) - - name := config.ContainerName - stop_args := []string{ - // We created the container with "--ephemeral=false" so we know it is safe to stop. - "stop", name, - } - - ui.Say("Stopping container...") - _, err := LXDCommand(stop_args...) - if err != nil { - err := fmt.Errorf("Error stopping container: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - publish_args := []string{ - "publish", name, "--alias", config.OutputImage, - } - - for k, v := range config.PublishProperties { - publish_args = append(publish_args, fmt.Sprintf("%s=%s", k, v)) - } - - ui.Say("Publishing container...") - stdoutString, err := LXDCommand(publish_args...) - if err != nil { - err := fmt.Errorf("Error publishing container: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - r := regexp.MustCompile("([0-9a-fA-F]+)$") - fingerprint := r.FindAllStringSubmatch(stdoutString, -1)[0][0] - - ui.Say(fmt.Sprintf("Created image: %s", fingerprint)) - - state.Put("imageFingerprint", fingerprint) - - return multistep.ActionContinue -} - -func (s *stepPublish) Cleanup(state multistep.StateBag) {} diff --git a/builder/lxd/version/version.go b/builder/lxd/version/version.go deleted file mode 100644 index b48000710..000000000 --- a/builder/lxd/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import ( - "github.com/hashicorp/packer-plugin-sdk/version" - packerVersion "github.com/hashicorp/packer/version" -) - -var LXDPluginVersion *version.PluginVersion - -func init() { - LXDPluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/command/plugin.go b/command/plugin.go index a7fa5f653..09365d693 100644 --- a/command/plugin.go +++ b/command/plugin.go @@ -18,8 +18,6 @@ import ( azuredtlbuilder "github.com/hashicorp/packer/builder/azure/dtl" filebuilder "github.com/hashicorp/packer/builder/file" hcloudbuilder "github.com/hashicorp/packer/builder/hcloud" - lxcbuilder "github.com/hashicorp/packer/builder/lxc" - lxdbuilder "github.com/hashicorp/packer/builder/lxd" nullbuilder "github.com/hashicorp/packer/builder/null" oneandonebuilder "github.com/hashicorp/packer/builder/oneandone" profitbricksbuilder "github.com/hashicorp/packer/builder/profitbricks" @@ -55,8 +53,6 @@ var Builders = map[string]packersdk.Builder{ "azure-dtl": new(azuredtlbuilder.Builder), "file": new(filebuilder.Builder), "hcloud": new(hcloudbuilder.Builder), - "lxc": new(lxcbuilder.Builder), - "lxd": new(lxdbuilder.Builder), "null": new(nullbuilder.Builder), "oneandone": new(oneandonebuilder.Builder), "profitbricks": new(profitbricksbuilder.Builder), diff --git a/command/vendored_plugins.go b/command/vendored_plugins.go index 312d60b0b..526e557c2 100644 --- a/command/vendored_plugins.go +++ b/command/vendored_plugins.go @@ -38,6 +38,8 @@ import ( hypervvmcxbuilder "github.com/hashicorp/packer-plugin-hyperv/builder/hyperv/vmcx" jdcloudbuilder "github.com/hashicorp/packer-plugin-jdcloud/builder/jdcloud" linodebuilder "github.com/hashicorp/packer-plugin-linode/builder/linode" + lxcbuilder "github.com/hashicorp/packer-plugin-lxc/builder/lxc" + lxdbuilder "github.com/hashicorp/packer-plugin-lxd/builder/lxd" ncloudbuilder "github.com/hashicorp/packer-plugin-ncloud/builder/ncloud" openstackbuilder "github.com/hashicorp/packer-plugin-openstack/builder/openstack" oracleclassicbuilder "github.com/hashicorp/packer-plugin-oracle/builder/classic" @@ -96,6 +98,8 @@ var VendoredBuilders = map[string]packersdk.Builder{ "hyperone": new(hyperonebuilder.Builder), "jdcloud": new(jdcloudbuilder.Builder), "linode": new(linodebuilder.Builder), + "lxc": new(lxcbuilder.Builder), + "lxd": new(lxdbuilder.Builder), "ncloud": new(ncloudbuilder.Builder), "openstack": new(openstackbuilder.Builder), "oracle-classic": new(oracleclassicbuilder.Builder), diff --git a/go.mod b/go.mod index 31ec52404..c52435d7b 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,8 @@ require ( github.com/hashicorp/packer-plugin-hyperv v0.0.1 github.com/hashicorp/packer-plugin-jdcloud v0.0.1 github.com/hashicorp/packer-plugin-linode v0.0.2 + github.com/hashicorp/packer-plugin-lxc v0.0.1 + github.com/hashicorp/packer-plugin-lxd v0.0.1 github.com/hashicorp/packer-plugin-ncloud v0.0.2 github.com/hashicorp/packer-plugin-openstack v0.0.2 github.com/hashicorp/packer-plugin-oracle v0.0.3 diff --git a/go.sum b/go.sum index 28e78f3a8..366d35312 100644 --- a/go.sum +++ b/go.sum @@ -544,6 +544,10 @@ github.com/hashicorp/packer-plugin-jdcloud v0.0.1 h1:MLvAroDOHWimBf6cBa0trlHJpB8 github.com/hashicorp/packer-plugin-jdcloud v0.0.1/go.mod h1:bVGtjp3v98rpguEYxJAXQbg8CjllInh5WFqO9a0T4lc= github.com/hashicorp/packer-plugin-linode v0.0.2 h1:obN0kQKlfCQuFmRwVx6ksQApQZ85gPAcSCtjDd0F30c= github.com/hashicorp/packer-plugin-linode v0.0.2/go.mod h1:uF8FAE3+PG/lVI1TwjXSaS3AHv4+Wb3/3gsrg0h6IQ0= +github.com/hashicorp/packer-plugin-lxc v0.0.1 h1:UPcoEYb/MFArZZLKyMdEiNqbvDthw+3PULKhgN98tKM= +github.com/hashicorp/packer-plugin-lxc v0.0.1/go.mod h1:W5fbCd3CnNUa+ApVGJ6QwAt646QT3eMhNeBWIcM51As= +github.com/hashicorp/packer-plugin-lxd v0.0.1 h1:CrFbQmQmdgI3n1RHMPmTUDinRPnPa/bIS9IsMtzERp8= +github.com/hashicorp/packer-plugin-lxd v0.0.1/go.mod h1:h3wqgxQiWy8pIJytTjeqXlAd1PXfNTvhTdODnvzDG3w= github.com/hashicorp/packer-plugin-ncloud v0.0.2 h1:MGvGkOVfzeosqOSs5dteghLwv9VRcRxTuLoLX1ssUag= github.com/hashicorp/packer-plugin-ncloud v0.0.2/go.mod h1:Hud2R1pkky96TQy3TPTTrr9Kej4b/4dqC/v+uEE0VDY= github.com/hashicorp/packer-plugin-openstack v0.0.2 h1:wGNE8es3Bn9auuIoX+gqT9chXzYY9GlM55eSpM4uwtU= diff --git a/website/content/docs/builders/lxc.mdx b/website/content/docs/builders/lxc.mdx deleted file mode 100644 index 9e803c5e5..000000000 --- a/website/content/docs/builders/lxc.mdx +++ /dev/null @@ -1,116 +0,0 @@ ---- -description: | - The `lxc` Packer builder builds containers for lxc1. The builder starts an LXC - container, runs provisioners within this container, then exports the container - as a tar.gz of the root file system. -page_title: LXC - Builders ---- - -# LXC Builder - -Type: `lxc` -Artifact BuilderId: `ustream.lxc` - -The `lxc` Packer builder builds containers for lxc1. The builder starts an LXC -container, runs provisioners within this container, then exports the container -as a tar.gz of the root file system. - -The LXC builder requires a modern linux kernel and the `lxc` or `lxc1` package. -This builder does not work with LXD. - -~> Note: to build Centos images on a Debian family host, you will need the -`yum` package installed.
Some provisioners such as `ansible-local` get -confused when running in a container of a different family. E.G. it will -attempt to use `apt-get` to install packages, when running in a Centos -container if the parent OS is Debian based. - -## Basic Example - -Below is a fully functioning example. - -```json -{ - "builders": [ - { - "type": "lxc", - "name": "lxc-trusty", - "config_file": "/tmp/lxc/config", - "template_name": "ubuntu", - "template_environment_vars": ["SUITE=trusty"] - }, - { - "type": "lxc", - "name": "lxc-xenial", - "config_file": "/tmp/lxc/config", - "template_name": "ubuntu", - "template_environment_vars": ["SUITE=xenial"] - }, - { - "type": "lxc", - "name": "lxc-jessie", - "config_file": "/tmp/lxc/config", - "template_name": "debian", - "template_environment_vars": ["SUITE=jessie"] - }, - { - "type": "lxc", - "name": "lxc-centos-7-x64", - "config_file": "/tmp/lxc/config", - "template_name": "centos", - "template_parameters": ["-R", "7", "-a", "x86_64"] - } - ] -} -``` - -## Configuration Reference - -### Required: - -- `config_file` (string) - The path to the lxc configuration file. - -- `template_name` (string) - The LXC template name to use. - -- `template_environment_vars` (array of strings) - Environmental variables to - use to build the template with. - -### Optional: - -- `target_runlevel` (number) - The minimum run level to wait for the - container to reach. Note some distributions (Ubuntu) simulate run levels - and may report 5 rather than 3. - -- `output_directory` (string) - The directory in which to save the exported - tar.gz. Defaults to `output-` in the current directory. - -- `container_name` (string) - The name of the LXC container. Usually stored - in `/var/lib/lxc/containers/`. Defaults to - `packer-`. - -- `command_wrapper` (string) - Allows you to specify a wrapper command, such - as `ssh` so you can execute Packer builds on a remote host. Defaults to - Empty. - -- `init_timeout` (string) - The timeout in seconds to wait for the the - container to start. Defaults to 20 seconds. - -- `template_parameters` (array of strings) - Options to pass to the given - `lxc-template` command, usually located in - `/usr/share/lxc/templates/lxc-`. Note: This gets passed as - ARGV to the template command. Ensure you have an array of strings, as a - single string with spaces probably won't work. Defaults to `[]`. - -- `create_options` (array of strings) - Options to pass to `lxc-create`. For - instance, you can specify a custom LXC container configuration file with - `["-f", "/path/to/lxc.conf"]`. Defaults to `[]`. See `man 1 lxc-create` for - available options. - -- `start_options` (array of strings) - Options to pass to `lxc-start`. For - instance, you can override parameters from the LXC container configuration - file via `["--define", "KEY=VALUE"]`. Defaults to `[]`. See - `man 1 lxc-start` for available options. - -- `attach_options` (array of strings) - Options to pass to `lxc-attach`. For - instance, you can prevent the container from inheriting the host machine's - environment by specifying `["--clear-env"]`. Defaults to `[]`. See - `man 1 lxc-attach` for available options. diff --git a/website/content/docs/builders/lxd.mdx b/website/content/docs/builders/lxd.mdx deleted file mode 100644 index 9552a094d..000000000 --- a/website/content/docs/builders/lxd.mdx +++ /dev/null @@ -1,80 +0,0 @@ ---- -description: > - The `lxd` Packer builder builds containers for LXD. The builder starts an LXD - - container, runs provisioners within this container, then saves the container - as - - an LXD image. -page_title: LXD - Builders ---- - -# LXD Builder - -Type: `lxd` -Artifact BuilderId: `lxd` - -The `lxd` Packer builder builds containers for LXD. The builder starts an LXD -container, runs provisioners within this container, then saves the container as -an LXD image. - -The LXD builder requires a modern linux kernel and the `lxd` package. This -builder does not work with LXC. - -## Basic Example - -Below is a fully functioning example. - -```json -{ - "builders": [ - { - "type": "lxd", - "name": "lxd-xenial", - "image": "ubuntu-daily:xenial", - "output_image": "ubuntu-xenial", - "publish_properties": { - "description": "Trivial repackage with Packer" - } - } - ] -} -``` - -## Configuration Reference - -### Required: - -- `image` (string) - The source image to use when creating the build - container. This can be a (local or remote) image (name or fingerprint). - E.G. `my-base-image`, `ubuntu-daily:x`, `08fababf6f27`, ... - - ~> Note: The builder may appear to pause if required to download a - remote image, as they are usually 100-200MB. `/var/log/lxd/lxd.log` will - mention starting such downloads. - -### Optional: - -- `init_sleep` (string) - The number of seconds to sleep between launching - the LXD instance and provisioning it; defaults to 3 seconds. - -- `name` (string) - Name of the builder. Defaults to `lxd`. - -- `container_name` (string) - Name of the build container. - Defaults to `packer-$name`. - -- `profile` - Name of the LXD profile used for the build container. - Defaults to `default`. - -- `output_image` (string) - The name of the output artifact. Defaults to - `name`. - -- `command_wrapper` (string) - Lets you prefix all builder commands, such as - with `ssh` for a remote build host. Defaults to `""`. - -- `publish_properties` (map\[string\]string) - Pass key values to the publish - step to be set as properties on the output image. This is most helpful to - set the description, but can be used to set anything needed. See [here](https://stgraber.org/2016/03/30/lxd-2-0-image-management-512/) for more properties. - -- `launch_config` (map\[string\]string) - List of key/value pairs you wish to - pass to `lxc launch` via `--config`. Defaults to empty. diff --git a/website/content/partials/builder/lxc/Config-not-required.mdx b/website/content/partials/builder/lxc/Config-not-required.mdx deleted file mode 100644 index 03e3c005e..000000000 --- a/website/content/partials/builder/lxc/Config-not-required.mdx +++ /dev/null @@ -1,42 +0,0 @@ - - -- `output_directory` (string) - The directory in which to save the exported - tar.gz. Defaults to `output-` in the current directory. - -- `container_name` (string) - The name of the LXC container. Usually stored - in `/var/lib/lxc/containers/`. Defaults to - `packer-`. - -- `command_wrapper` (string) - Allows you to specify a wrapper command, such - as ssh so you can execute packer builds on a remote host. Defaults to - `{{.Command}}`; i.e. no wrapper. - -- `init_timeout` (duration string | ex: "1h5m2s") - The timeout in seconds to wait for the the - container to start. Defaults to 20 seconds. - -- `create_options` ([]string) - Options to pass to lxc-create. For - instance, you can specify a custom LXC container configuration file with - ["-f", "/path/to/lxc.conf"]. Defaults to []. See man 1 lxc-create for - available options. - -- `start_options` ([]string) - Options to pass to lxc-start. For - instance, you can override parameters from the LXC container configuration - file via ["--define", "KEY=VALUE"]. Defaults to []. See - man 1 lxc-start for available options. - -- `attach_options` ([]string) - Options to pass to lxc-attach. For - instance, you can prevent the container from inheriting the host machine's - environment by specifying ["--clear-env"]. Defaults to []. See - man 1 lxc-attach for available options. - -- `template_parameters` ([]string) - Options to pass to the given - lxc-template command, usually located in - `/usr/share/lxc/templates/lxc-`. Note: This gets passed as - ARGV to the template command. Ensure you have an array of strings, as a - single string with spaces probably won't work. Defaults to []. - -- `target_runlevel` (int) - The minimum run level to wait for the - container to reach. Note some distributions (Ubuntu) simulate run levels - and may report 5 rather than 3. - - diff --git a/website/content/partials/builder/lxc/Config-required.mdx b/website/content/partials/builder/lxc/Config-required.mdx deleted file mode 100644 index bcd9b77d2..000000000 --- a/website/content/partials/builder/lxc/Config-required.mdx +++ /dev/null @@ -1,10 +0,0 @@ - - -- `config_file` (string) - The path to the lxc configuration file. - -- `template_name` (string) - The LXC template name to use. - -- `template_environment_vars` ([]string) - Environmental variables to - use to build the template with. - - diff --git a/website/content/partials/builder/lxd/Config-not-required.mdx b/website/content/partials/builder/lxd/Config-not-required.mdx deleted file mode 100644 index 579374114..000000000 --- a/website/content/partials/builder/lxd/Config-not-required.mdx +++ /dev/null @@ -1,26 +0,0 @@ - - -- `output_image` (string) - The name of the output artifact. Defaults to - name. - -- `container_name` (string) - Container Name - -- `command_wrapper` (string) - Lets you prefix all builder commands, such as - with ssh for a remote build host. Defaults to `{{.Command}}`; i.e. no - wrapper. - -- `profile` (string) - Profile - -- `init_sleep` (string) - The number of seconds to sleep between launching - the LXD instance and provisioning it; defaults to 3 seconds. - -- `publish_properties` (map[string]string) - Pass key values to the publish - step to be set as properties on the output image. This is most helpful to - set the description, but can be used to set anything needed. See - https://stgraber.org/2016/03/30/lxd-2-0-image-management-512/ - for more properties. - -- `launch_config` (map[string]string) - List of key/value pairs you wish to - pass to lxc launch via --config. Defaults to empty. - - diff --git a/website/content/partials/builder/lxd/Config-required.mdx b/website/content/partials/builder/lxd/Config-required.mdx deleted file mode 100644 index add0c0f31..000000000 --- a/website/content/partials/builder/lxd/Config-required.mdx +++ /dev/null @@ -1,7 +0,0 @@ - - -- `image` (string) - The source image to use when creating the build - container. This can be a (local or remote) image (name or fingerprint). - E.G. my-base-image, ubuntu-daily:x, 08fababf6f27, ... - - diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index e8c5d12c9..3fe567188 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -704,14 +704,6 @@ "title": "Hetzner Cloud", "path": "builders/hetzner-cloud" }, - { - "title": "LXC", - "path": "builders/lxc" - }, - { - "title": "LXD", - "path": "builders/lxd" - }, { "title": "Null", "path": "builders/null" diff --git a/website/data/docs-remote-plugins.json b/website/data/docs-remote-plugins.json index d34c1154c..7a3452033 100644 --- a/website/data/docs-remote-plugins.json +++ b/website/data/docs-remote-plugins.json @@ -86,6 +86,20 @@ "pluginTier": "community", "version": "latest" }, + { + "title": "LXC", + "path": "lxc", + "repo": "hashicorp/packer-plugin-lxc", + "pluginTier": "community", + "version": "latest" + }, + { + "title": "LXD", + "path": "lxd", + "repo": "hashicorp/packer-plugin-lxd", + "pluginTier": "community", + "version": "latest" + }, { "title": "Naver Cloud", "path": "ncloud",