builder/vmware: move outputdir stuff to common
This commit is contained in:
parent
8bd3ca4470
commit
50f8b2c1a3
|
@ -0,0 +1,15 @@
|
|||
package common
|
||||
|
||||
// OutputDir is an interface type that abstracts the creation and handling
|
||||
// of the output directory for VMware-based products. The abstraction is made
|
||||
// so that the output directory can be properly made on remote (ESXi) based
|
||||
// VMware products as well as local.
|
||||
type OutputDir interface {
|
||||
DirExists() (bool, error)
|
||||
ListFiles() ([]string, error)
|
||||
MkdirAll() error
|
||||
Remove(string) error
|
||||
RemoveAll() error
|
||||
SetOutputDir(string)
|
||||
String() string
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// LocalOutputDir is an OutputDir implementation where the directory
|
||||
// is on the local machine.
|
||||
type LocalOutputDir struct {
|
||||
Dir string
|
||||
}
|
||||
|
||||
func (d *LocalOutputDir) DirExists() (bool, error) {
|
||||
_, err := os.Stat(d.Dir)
|
||||
return err == nil, nil
|
||||
}
|
||||
|
||||
func (d *LocalOutputDir) ListFiles() ([]string, error) {
|
||||
files := make([]string, 0, 10)
|
||||
|
||||
visit := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
files = append(files, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return files, filepath.Walk(d.Dir, visit)
|
||||
}
|
||||
|
||||
func (d *LocalOutputDir) MkdirAll() error {
|
||||
return os.MkdirAll(d.Dir, 0755)
|
||||
}
|
||||
|
||||
func (d *LocalOutputDir) Remove(path string) error {
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
||||
func (d *LocalOutputDir) RemoveAll() error {
|
||||
return os.RemoveAll(d.Dir)
|
||||
}
|
||||
|
||||
func (d *LocalOutputDir) SetOutputDir(path string) {
|
||||
d.Dir = path
|
||||
}
|
||||
|
||||
func (d *LocalOutputDir) String() string {
|
||||
return d.Dir
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLocalOuputDir_impl(t *testing.T) {
|
||||
var _ OutputDir = new(LocalOutputDir)
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
// StepOutputDir sets up the output directory by creating it if it does
|
||||
// not exist, deleting it if it does exist and we're forcing, and cleaning
|
||||
// it up when we're done with it.
|
||||
type StepOutputDir struct {
|
||||
Force bool
|
||||
|
||||
success bool
|
||||
}
|
||||
|
||||
func (s *StepOutputDir) Run(state multistep.StateBag) multistep.StepAction {
|
||||
dir := state.Get("dir").(OutputDir)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
exists, err := dir.DirExists()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if exists {
|
||||
if s.Force {
|
||||
ui.Say("Deleting previous output directory...")
|
||||
dir.RemoveAll()
|
||||
} else {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Output directory '%s' already exists.", dir.String()))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
if err := dir.MkdirAll(); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.success = true
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepOutputDir) Cleanup(state multistep.StateBag) {
|
||||
if !s.success {
|
||||
return
|
||||
}
|
||||
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
if cancelled || halted {
|
||||
dir := state.Get("dir").(OutputDir)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Deleting output directory...")
|
||||
for i := 0; i < 5; i++ {
|
||||
err := dir.RemoveAll()
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("Error removing output dir: %s", err)
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testOutputDir(t *testing.T) *LocalOutputDir {
|
||||
td, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
os.RemoveAll(td)
|
||||
return &LocalOutputDir{Dir: td}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_impl(t *testing.T) {
|
||||
var _ multistep.Step = new(StepOutputDir)
|
||||
}
|
||||
|
||||
func TestStepOutputDir(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.Dir); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test the cleanup
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(dir.Dir); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_existsNoForce(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
|
||||
// Make sure the dir exists
|
||||
if err := os.MkdirAll(dir.Dir, 0755); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionHalt {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); !ok {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
// Test the cleanup
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(dir.Dir); err != nil {
|
||||
t.Fatal("should not delete dir")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_existsForce(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
step.Force = true
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
|
||||
// Make sure the dir exists
|
||||
if err := os.MkdirAll(dir.Dir, 0755); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.Dir); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_cancel(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.Dir); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test cancel/halt
|
||||
state.Put(multistep.StateCancelled, true)
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(dir.Dir); err == nil {
|
||||
t.Fatal("directory should not exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_halt(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.Dir); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test cancel/halt
|
||||
state.Put(multistep.StateHalted, true)
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(dir.Dir); err == nil {
|
||||
t.Fatal("directory should not exist")
|
||||
}
|
||||
}
|
|
@ -346,6 +346,25 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
return nil, fmt.Errorf("Failed creating VMware driver: %s", err)
|
||||
}
|
||||
|
||||
// Determine the output dir implementation
|
||||
var dir OutputDir
|
||||
switch d := driver.(type) {
|
||||
case OutputDir:
|
||||
dir = d
|
||||
default:
|
||||
dir = new(vmwcommon.LocalOutputDir)
|
||||
}
|
||||
dir.SetOutputDir(b.config.OutputDir)
|
||||
|
||||
// Setup the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("cache", cache)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("dir", dir)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
// Seed the random number generator
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
|
||||
|
@ -358,7 +377,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
ResultKey: "iso_path",
|
||||
Url: b.config.ISOUrls,
|
||||
},
|
||||
&stepPrepareOutputDir{},
|
||||
&vmwcommon.StepOutputDir{
|
||||
Force: b.config.PackerForce,
|
||||
},
|
||||
&common.StepCreateFloppy{
|
||||
Files: b.config.FloppyFiles,
|
||||
},
|
||||
|
@ -390,14 +411,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
&stepCompactDisk{},
|
||||
}
|
||||
|
||||
// Setup the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("cache", cache)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
// Run!
|
||||
if b.config.PackerDebug {
|
||||
b.runner = &multistep.DebugRunner{
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
package iso
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type stepPrepareOutputDir struct {
|
||||
dir OutputDir
|
||||
}
|
||||
|
||||
func (s *stepPrepareOutputDir) Run(state multistep.StateBag) multistep.StepAction {
|
||||
config := state.Get("config").(*config)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
dir := s.outputDir(state)
|
||||
dir.SetOutputDir(config.OutputDir)
|
||||
|
||||
exists, err := dir.DirExists()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if exists {
|
||||
if config.PackerForce {
|
||||
ui.Say("Deleting previous output directory...")
|
||||
dir.RemoveAll()
|
||||
} else {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"Output directory '%s' already exists.", config.OutputDir))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
if err := dir.MkdirAll(); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.dir = dir
|
||||
state.Put("dir", dir)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *stepPrepareOutputDir) Cleanup(state multistep.StateBag) {
|
||||
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||
_, halted := state.GetOk(multistep.StateHalted)
|
||||
|
||||
if cancelled || halted {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if s.dir != nil {
|
||||
ui.Say("Deleting output directory...")
|
||||
for i := 0; i < 5; i++ {
|
||||
err := s.dir.RemoveAll()
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("Error removing output dir: %s", err)
|
||||
time.Sleep(2 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stepPrepareOutputDir) outputDir(state multistep.StateBag) (dir OutputDir) {
|
||||
driver := state.Get("driver").(Driver)
|
||||
|
||||
switch d := driver.(type) {
|
||||
case OutputDir:
|
||||
log.Printf("Using driver as the OutputDir implementation")
|
||||
dir = d
|
||||
default:
|
||||
log.Printf("Using localOutputDir implementation")
|
||||
dir = new(localOutputDir)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue