[lxd] refactor commands to dry things up
This commit is contained in:
parent
05f072929f
commit
e29f06fe1c
|
@ -1,7 +1,11 @@
|
||||||
package lxd
|
package lxd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommandWrapper is a type that given a command, will possibly modify that
|
// CommandWrapper is a type that given a command, will possibly modify that
|
||||||
|
@ -13,3 +17,27 @@ type CommandWrapper func(string) (string, error)
|
||||||
func ShellCommand(command string) *exec.Cmd {
|
func ShellCommand(command string) *exec.Cmd {
|
||||||
return exec.Command("/bin/sh", "-c", command)
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ func (c *Communicator) DownloadDir(src string, dst string, exclude []string) err
|
||||||
func (c *Communicator) Execute(commandString string) (*exec.Cmd, error) {
|
func (c *Communicator) Execute(commandString string) (*exec.Cmd, error) {
|
||||||
log.Printf("Executing with lxc exec in container: %s %s", c.ContainerName, commandString)
|
log.Printf("Executing with lxc exec in container: %s %s", c.ContainerName, commandString)
|
||||||
command, err := c.CmdWrapper(
|
command, err := c.CmdWrapper(
|
||||||
fmt.Sprintf("sudo lxc exec %s -- /bin/sh -c \"%s\"", c.ContainerName, commandString))
|
fmt.Sprintf("lxc exec %s -- /bin/sh -c \"%s\"", c.ContainerName, commandString))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
package lxd
|
package lxd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,20 +16,17 @@ func (s *stepLxdLaunch) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
name := config.ContainerName
|
name := config.ContainerName
|
||||||
image := config.Image
|
image := config.Image
|
||||||
|
|
||||||
commands := [][]string{
|
args := []string{
|
||||||
{"lxc", "launch", image, name},
|
"launch", image, name,
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Creating container...")
|
ui.Say("Creating container...")
|
||||||
for _, command := range commands {
|
_, err := LXDCommand(args...)
|
||||||
log.Printf("Executing sudo command: %#v", command)
|
if err != nil {
|
||||||
err := s.SudoCommand(command...)
|
err := fmt.Errorf("Error creating container: %s", err)
|
||||||
if err != nil {
|
state.Put("error", err)
|
||||||
err := fmt.Errorf("Error creating container: %s", err)
|
ui.Error(err.Error())
|
||||||
state.Put("error", err)
|
return multistep.ActionHalt
|
||||||
ui.Error(err.Error())
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// TODO: Should we check `lxc info <container>` for "Running"?
|
// TODO: Should we check `lxc info <container>` for "Running"?
|
||||||
// We have to do this so /tmp doens't get cleared and lose our provisioner scripts.
|
// We have to do this so /tmp doens't get cleared and lose our provisioner scripts.
|
||||||
|
@ -46,34 +39,12 @@ func (s *stepLxdLaunch) Cleanup(state multistep.StateBag) {
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
command := []string{
|
args := []string{
|
||||||
"lxc", "delete", "--force", config.ContainerName,
|
"delete", "--force", config.ContainerName,
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Unregistering and deleting deleting container...")
|
ui.Say("Unregistering and deleting deleting container...")
|
||||||
if err := s.SudoCommand(command...); err != nil {
|
if _, err := LXDCommand(args...); err != nil {
|
||||||
ui.Error(fmt.Sprintf("Error deleting container: %s", err))
|
ui.Error(fmt.Sprintf("Error deleting container: %s", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepLxdLaunch) SudoCommand(args ...string) error {
|
|
||||||
var stdout, stderr bytes.Buffer
|
|
||||||
|
|
||||||
log.Printf("Executing sudo command: %#v", args)
|
|
||||||
cmd := exec.Command("sudo", 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("Sudo command error: %s", stderrString)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("stdout: %s", stdoutString)
|
|
||||||
log.Printf("stderr: %s", stderrString)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StepProvision provisions the instance within a chroot.
|
// StepProvision provisions the container
|
||||||
type StepProvision struct{}
|
type StepProvision struct{}
|
||||||
|
|
||||||
func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
|
|
@ -1,20 +1,15 @@
|
||||||
package lxd
|
package lxd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
|
||||||
"os/exec"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepPublish struct{}
|
type stepPublish struct{}
|
||||||
|
|
||||||
func (s *stepPublish) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *stepPublish) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
var stdout, stderr bytes.Buffer
|
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
|
@ -23,25 +18,13 @@ func (s *stepPublish) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
args := []string{
|
args := []string{
|
||||||
// If we use `lxc stop <container>`, an ephemeral container would die forever.
|
// If we use `lxc stop <container>`, an ephemeral container would die forever.
|
||||||
// `lxc publish` has special logic to handle this case.
|
// `lxc publish` has special logic to handle this case.
|
||||||
"lxc", "publish", "--force", name, "--alias", config.OutputImage,
|
"publish", "--force", name, "--alias", config.OutputImage,
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Publishing container...")
|
ui.Say("Publishing container...")
|
||||||
cmd := exec.Command("sudo", args...)
|
stdoutString, err := LXDCommand(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("Sudo command error: %s", stderrString)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("stdout: %s", stdoutString)
|
|
||||||
log.Printf("stderr: %s", stderrString)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
err := fmt.Errorf("Error publishing container: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
|
Loading…
Reference in New Issue