builder/docker: use exec for v1.4+
This commit is contained in:
parent
966d70148e
commit
6570b53c4a
|
@ -1,10 +1,11 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/common"
|
"github.com/mitchellh/packer/common"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const BuilderId = "packer.docker"
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version, err := driver.Version()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Printf("[DEBUG] Docker version: %s", version.String())
|
||||||
|
|
||||||
steps := []multistep.Step{
|
steps := []multistep.Step{
|
||||||
&StepTempDir{},
|
&StepTempDir{},
|
||||||
&StepPull{},
|
&StepPull{},
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
@ -24,36 +23,20 @@ type Communicator struct {
|
||||||
ContainerId string
|
ContainerId string
|
||||||
HostDir string
|
HostDir string
|
||||||
ContainerDir string
|
ContainerDir string
|
||||||
|
Version *version.Version
|
||||||
|
|
||||||
lock sync.Mutex
|
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 {
|
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
|
// Create a temporary file to store the output. Because of a bug in
|
||||||
// Docker, sometimes all the output doesn't properly show up. This
|
// Docker, sometimes all the output doesn't properly show up. This
|
||||||
// file will capture ALL of the output, and we'll read that.
|
// 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"
|
exitCodePath := outputFile.Name() + "-exit"
|
||||||
|
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
if useDockerExec {
|
if useExec {
|
||||||
cmd = exec.Command("docker", "exec", "-i", c.ContainerId, "/bin/sh")
|
cmd = exec.Command("docker", "exec", "-i", c.ContainerId, "/bin/sh")
|
||||||
} else {
|
} else {
|
||||||
cmd = exec.Command("docker", "attach", c.ContainerId)
|
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())
|
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)
|
dest, err := os.Readlink(path)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,6 +2,8 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Driver is the interface that has to be implemented to communicate with
|
// 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 verifies that the driver can run
|
||||||
Verify() error
|
Verify() error
|
||||||
|
|
||||||
|
// Version reads the Docker version
|
||||||
|
Version() (*version.Version, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerConfig is the configuration used to start a container.
|
// ContainerConfig is the configuration used to start a container.
|
||||||
|
|
|
@ -7,9 +7,11 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"github.com/mitchellh/packer/template/interpolate"
|
"github.com/mitchellh/packer/template/interpolate"
|
||||||
)
|
)
|
||||||
|
@ -263,3 +265,17 @@ func (d *DockerDriver) Verify() error {
|
||||||
|
|
||||||
return nil
|
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 (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockDriver is a driver implementation that can be used for tests.
|
// MockDriver is a driver implementation that can be used for tests.
|
||||||
|
@ -63,6 +65,9 @@ type MockDriver struct {
|
||||||
StopCalled bool
|
StopCalled bool
|
||||||
StopID string
|
StopID string
|
||||||
VerifyCalled bool
|
VerifyCalled bool
|
||||||
|
|
||||||
|
VersionCalled bool
|
||||||
|
VersionVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *MockDriver) Commit(id string) (string, error) {
|
func (d *MockDriver) Commit(id string) (string, error) {
|
||||||
|
@ -162,3 +167,8 @@ func (d *MockDriver) Verify() error {
|
||||||
d.VerifyCalled = true
|
d.VerifyCalled = true
|
||||||
return d.VerifyError
|
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 {
|
func (s *StepProvision) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
containerId := state.Get("container_id").(string)
|
containerId := state.Get("container_id").(string)
|
||||||
|
driver := state.Get("driver").(Driver)
|
||||||
tempDir := state.Get("temp_dir").(string)
|
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
|
// Create the communicator that talks to Docker via various
|
||||||
// os/exec tricks.
|
// os/exec tricks.
|
||||||
comm := &Communicator{
|
comm := &Communicator{
|
||||||
ContainerId: containerId,
|
ContainerId: containerId,
|
||||||
HostDir: tempDir,
|
HostDir: tempDir,
|
||||||
ContainerDir: "/packer-files",
|
ContainerDir: "/packer-files",
|
||||||
|
Version: version,
|
||||||
}
|
}
|
||||||
|
|
||||||
prov := common.StepProvision{Comm: comm}
|
prov := common.StepProvision{Comm: comm}
|
||||||
|
|
Loading…
Reference in New Issue