builder/docker: StepPull test, driver abstraction for tests
This commit is contained in:
parent
2da9233655
commit
62b81dc432
|
@ -56,6 +56,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
||||||
state.Put("hook", hook)
|
state.Put("hook", hook)
|
||||||
state.Put("ui", ui)
|
state.Put("ui", ui)
|
||||||
|
|
||||||
|
// Setup the driver that will talk to Docker
|
||||||
|
state.Put("driver", &DockerDriver{
|
||||||
|
Ui: ui,
|
||||||
|
})
|
||||||
|
|
||||||
// Run!
|
// Run!
|
||||||
if b.config.PackerDebug {
|
if b.config.PackerDebug {
|
||||||
b.runner = &multistep.DebugRunner{
|
b.runner = &multistep.DebugRunner{
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
// Driver is the interface that has to be implemented to communicate with
|
||||||
|
// Docker. The Driver interface also allows the steps to be tested since
|
||||||
|
// a mock driver can be shimmed in.
|
||||||
|
type Driver interface {
|
||||||
|
// Pull should pull down the given image.
|
||||||
|
Pull(image string) error
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mitchellh/packer/packer"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DockerDriver struct {
|
||||||
|
Ui packer.Ui
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DockerDriver) Pull(image string) error {
|
||||||
|
cmd := exec.Command("docker", "pull", image)
|
||||||
|
return runAndStream(cmd, d.Ui)
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
// MockDriver is a driver implementation that can be used for tests.
|
||||||
|
type MockDriver struct {
|
||||||
|
PullError error
|
||||||
|
|
||||||
|
PullCalled bool
|
||||||
|
PullImage string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *MockDriver) Pull(image string) error {
|
||||||
|
d.PullCalled = true
|
||||||
|
d.PullImage = image
|
||||||
|
return d.PullError
|
||||||
|
}
|
|
@ -4,18 +4,17 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"os/exec"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type StepPull struct{}
|
type StepPull struct{}
|
||||||
|
|
||||||
func (s *StepPull) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *StepPull) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
|
driver := state.Get("driver").(Driver)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Pulling Docker image: %s", config.Image))
|
ui.Say(fmt.Sprintf("Pulling Docker image: %s", config.Image))
|
||||||
cmd := exec.Command("docker", "pull", config.Image)
|
if err := driver.Pull(config.Image); err != nil {
|
||||||
if err := runAndStream(cmd, ui); err != nil {
|
|
||||||
err := fmt.Errorf("Error pulling Docker image: %s", err)
|
err := fmt.Errorf("Error pulling Docker image: %s", err)
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/mitchellh/multistep"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStepPull_impl(t *testing.T) {
|
||||||
|
var _ multistep.Step = new(StepPull)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStepPull(t *testing.T) {
|
||||||
|
state := testState(t)
|
||||||
|
step := new(StepPull)
|
||||||
|
defer step.Cleanup(state)
|
||||||
|
|
||||||
|
config := state.Get("config").(*Config)
|
||||||
|
driver := state.Get("driver").(*MockDriver)
|
||||||
|
|
||||||
|
// run the step
|
||||||
|
if action := step.Run(state); action != multistep.ActionContinue {
|
||||||
|
t.Fatalf("bad action: %#v", action)
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify we did the right thing
|
||||||
|
if !driver.PullCalled {
|
||||||
|
t.Fatal("should've pulled")
|
||||||
|
}
|
||||||
|
if driver.PullImage != config.Image {
|
||||||
|
t.Fatalf("bad: %#v", driver.PullImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStepPull_error(t *testing.T) {
|
||||||
|
state := testState(t)
|
||||||
|
step := new(StepPull)
|
||||||
|
defer step.Cleanup(state)
|
||||||
|
|
||||||
|
driver := state.Get("driver").(*MockDriver)
|
||||||
|
driver.PullError = errors.New("foo")
|
||||||
|
|
||||||
|
// run the step
|
||||||
|
if action := step.Run(state); action != multistep.ActionHalt {
|
||||||
|
t.Fatalf("bad action: %#v", action)
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify we have an error
|
||||||
|
if _, ok := state.GetOk("error"); !ok {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import (
|
||||||
func testState(t *testing.T) multistep.StateBag {
|
func testState(t *testing.T) multistep.StateBag {
|
||||||
state := new(multistep.BasicStateBag)
|
state := new(multistep.BasicStateBag)
|
||||||
state.Put("config", testConfigStruct(t))
|
state.Put("config", testConfigStruct(t))
|
||||||
|
state.Put("driver", &MockDriver{})
|
||||||
state.Put("hook", &packer.MockHook{})
|
state.Put("hook", &packer.MockHook{})
|
||||||
state.Put("ui", &packer.BasicUi{
|
state.Put("ui", &packer.BasicUi{
|
||||||
Reader: new(bytes.Buffer),
|
Reader: new(bytes.Buffer),
|
||||||
|
|
Loading…
Reference in New Issue