builder/docker: use exec for v1.4+
This commit is contained in:
parent
966d70148e
commit
6570b53c4a
|
@ -1,10 +1,11 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/common"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
)
|
||||
|
||||
const BuilderId = "packer.docker"
|
||||
|
@ -31,6 +32,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
return nil, err
|
||||
}
|
||||
|
||||
version, err := driver.Version()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Printf("[DEBUG] Docker version: %s", version.String())
|
||||
|
||||
steps := []multistep.Step{
|
||||
&StepTempDir{},
|
||||
&StepPull{},
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
@ -24,36 +23,20 @@ type Communicator struct {
|
|||
ContainerId string
|
||||
HostDir string
|
||||
ContainerDir string
|
||||
Version *version.Version
|
||||
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
var dockerVersion *version.Version
|
||||
var useDockerExec bool
|
||||
|
||||
func init() {
|
||||
execConstraint, _ := version.NewConstraint(">= 1.4.0")
|
||||
|
||||
versionExtractor := regexp.MustCompile(version.VersionRegexpRaw)
|
||||
dockerVersionOutput, err := exec.Command("docker", "-v").Output()
|
||||
extractedVersion := versionExtractor.FindSubmatch(dockerVersionOutput)
|
||||
|
||||
if extractedVersion != nil {
|
||||
dockerVersionString := string(extractedVersion[0])
|
||||
dockerVersion, err = version.NewVersion(dockerVersionString)
|
||||
}
|
||||
|
||||
if dockerVersion == nil {
|
||||
log.Printf("Could not determine docker version: %v", err)
|
||||
log.Printf("Assuming no `exec` capability, using `attatch`")
|
||||
useDockerExec = false
|
||||
} else {
|
||||
log.Printf("Docker version detected as %s", dockerVersion)
|
||||
useDockerExec = execConstraint.Check(dockerVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Communicator) Start(remote *packer.RemoteCmd) error {
|
||||
// Determine if we're using docker exec or not
|
||||
useExec := false
|
||||
execConstraint, err := version.NewConstraint(">= 1.4.0")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
useExec = execConstraint.Check(c.Version)
|
||||
|
||||
// Create a temporary file to store the output. Because of a bug in
|
||||
// Docker, sometimes all the output doesn't properly show up. This
|
||||
// file will capture ALL of the output, and we'll read that.
|
||||
|
@ -69,7 +52,7 @@ func (c *Communicator) Start(remote *packer.RemoteCmd) error {
|
|||
exitCodePath := outputFile.Name() + "-exit"
|
||||
|
||||
var cmd *exec.Cmd
|
||||
if useDockerExec {
|
||||
if useExec {
|
||||
cmd = exec.Command("docker", "exec", "-i", c.ContainerId, "/bin/sh")
|
||||
} else {
|
||||
cmd = exec.Command("docker", "attach", c.ContainerId)
|
||||
|
@ -150,7 +133,7 @@ func (c *Communicator) UploadDir(dst string, src string, exclude []string) error
|
|||
return os.MkdirAll(hostpath, info.Mode())
|
||||
}
|
||||
|
||||
if info.Mode() & os.ModeSymlink == os.ModeSymlink {
|
||||
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
dest, err := os.Readlink(path)
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -2,6 +2,8 @@ package docker
|
|||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
)
|
||||
|
||||
// Driver is the interface that has to be implemented to communicate with
|
||||
|
@ -48,6 +50,9 @@ type Driver interface {
|
|||
|
||||
// Verify verifies that the driver can run
|
||||
Verify() error
|
||||
|
||||
// Version reads the Docker version
|
||||
Version() (*version.Version, error)
|
||||
}
|
||||
|
||||
// ContainerConfig is the configuration used to start a container.
|
||||
|
|
|
@ -7,9 +7,11 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
@ -263,3 +265,17 @@ func (d *DockerDriver) Verify() error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DockerDriver) Version() (*version.Version, error) {
|
||||
output, err := exec.Command("docker", "-v").Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
match := regexp.MustCompile(version.VersionRegexpRaw).FindSubmatch(output)
|
||||
if match == nil {
|
||||
return nil, fmt.Errorf("unknown version: %s", output)
|
||||
}
|
||||
|
||||
return version.NewVersion(string(match[0]))
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package docker
|
|||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
)
|
||||
|
||||
// MockDriver is a driver implementation that can be used for tests.
|
||||
|
@ -63,6 +65,9 @@ type MockDriver struct {
|
|||
StopCalled bool
|
||||
StopID string
|
||||
VerifyCalled bool
|
||||
|
||||
VersionCalled bool
|
||||
VersionVersion string
|
||||
}
|
||||
|
||||
func (d *MockDriver) Commit(id string) (string, error) {
|
||||
|
@ -162,3 +167,8 @@ func (d *MockDriver) Verify() error {
|
|||
d.VerifyCalled = true
|
||||
return d.VerifyError
|
||||
}
|
||||
|
||||
func (d *MockDriver) Version() (*version.Version, error) {
|
||||
d.VersionCalled = true
|
||||
return version.NewVersion(d.VersionVersion)
|
||||
}
|
||||
|
|
|
@ -9,14 +9,23 @@ type StepProvision struct{}
|
|||
|
||||
func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
|
||||
containerId := state.Get("container_id").(string)
|
||||
driver := state.Get("driver").(Driver)
|
||||
tempDir := state.Get("temp_dir").(string)
|
||||
|
||||
// Get the version so we can pass it to the communicator
|
||||
version, err := driver.Version()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Create the communicator that talks to Docker via various
|
||||
// os/exec tricks.
|
||||
comm := &Communicator{
|
||||
ContainerId: containerId,
|
||||
HostDir: tempDir,
|
||||
ContainerDir: "/packer-files",
|
||||
Version: version,
|
||||
}
|
||||
|
||||
prov := common.StepProvision{Comm: comm}
|
||||
|
|
Loading…
Reference in New Issue