[lxd] refactor commands to dry things up

This commit is contained in:
Chris Lundquist 2016-08-07 03:25:57 +00:00 committed by Megan Marsh
parent 05f072929f
commit e29f06fe1c
5 changed files with 44 additions and 62 deletions

View File

@ -1,7 +1,11 @@
package lxd
import (
"bytes"
"fmt"
"log"
"os/exec"
"strings"
)
// 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 {
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
}

View File

@ -128,7 +128,7 @@ func (c *Communicator) DownloadDir(src string, dst string, exclude []string) err
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("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 {
return nil, err
}

View File

@ -1,13 +1,9 @@
package lxd
import (
"bytes"
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"os/exec"
"strings"
"time"
)
@ -20,21 +16,18 @@ func (s *stepLxdLaunch) Run(state multistep.StateBag) multistep.StepAction {
name := config.ContainerName
image := config.Image
commands := [][]string{
{"lxc", "launch", image, name},
args := []string{
"launch", image, name,
}
ui.Say("Creating container...")
for _, command := range commands {
log.Printf("Executing sudo command: %#v", command)
err := s.SudoCommand(command...)
_, err := LXDCommand(args...)
if err != nil {
err := fmt.Errorf("Error creating container: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
// 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.
time.Sleep(1 * time.Second)
@ -46,34 +39,12 @@ func (s *stepLxdLaunch) Cleanup(state multistep.StateBag) {
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
command := []string{
"lxc", "delete", "--force", config.ContainerName,
args := []string{
"delete", "--force", config.ContainerName,
}
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))
}
}
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
}

View File

@ -6,7 +6,7 @@ import (
"log"
)
// StepProvision provisions the instance within a chroot.
// StepProvision provisions the container
type StepProvision struct{}
func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {

View File

@ -1,20 +1,15 @@
package lxd
import (
"bytes"
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"log"
"os/exec"
"regexp"
"strings"
)
type stepPublish struct{}
func (s *stepPublish) Run(state multistep.StateBag) multistep.StepAction {
var stdout, stderr bytes.Buffer
config := state.Get("config").(*Config)
ui := state.Get("ui").(packer.Ui)
@ -23,25 +18,13 @@ func (s *stepPublish) Run(state multistep.StateBag) multistep.StepAction {
args := []string{
// If we use `lxc stop <container>`, an ephemeral container would die forever.
// `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...")
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)
stdoutString, err := LXDCommand(args...)
if err != nil {
err := fmt.Errorf("Error publishing container: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt