Refactor artifacts and output_dir implementations.

This commit is contained in:
Alexander Laamanen 2017-02-03 15:56:13 +02:00 committed by Megan Marsh
parent 2d00dc6756
commit 4d9cb19012
7 changed files with 73 additions and 83 deletions

View File

@ -3,22 +3,26 @@ package common
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
) )
// BuilderId for the local artifacts // BuilderId for the local artifacts
const BuilderId = "mitchellh.vmware" const BuilderId = "mitchellh.vmware"
const BuilderIdESX = "mitchellh.vmware-esx"
// Artifact is the result of running the VMware builder, namely a set // Artifact is the result of running the VMware builder, namely a set
// of files associated with the resulting machine. // of files associated with the resulting machine.
type localArtifact struct { type artifact struct {
id string builderId string
dir string id string
f []string dir string
f []string
config map[string]string
} }
// NewLocalArtifact returns a VMware artifact containing the files
// in the given directory.
// NewLocalArtifact returns a VMware artifact containing the files // NewLocalArtifact returns a VMware artifact containing the files
// in the given directory. // in the given directory.
func NewLocalArtifact(id string, dir string) (packer.Artifact, error) { func NewLocalArtifact(id string, dir string) (packer.Artifact, error) {
@ -37,33 +41,46 @@ func NewLocalArtifact(id string, dir string) (packer.Artifact, error) {
return nil, err return nil, err
} }
return &localArtifact{ return &artifact{
id: id, builderId: id,
dir: dir, dir: dir,
f: files, f: files,
}, nil }, nil
} }
func (a *localArtifact) BuilderId() string { func NewArtifact(dir OutputDir, files []string, esxi bool) (packer.Artifact, err) {
builderID := BuilderId
if esxi {
builderID = BuilderIdESX
}
return &artifact{
builderId: builderID,
dir: dir.String(),
f: files,
}, nil
}
func (a *artifact) BuilderId() string {
return BuilderId return BuilderId
} }
func (a *localArtifact) Files() []string { func (a *artifact) Files() []string {
return a.f return a.f
} }
func (a *localArtifact) Id() string { func (*artifact) Id() string {
return a.id return a.id
} }
func (a *localArtifact) String() string { func (a *artifact) String() string {
return fmt.Sprintf("VM files in directory: %s", a.dir) return fmt.Sprintf("VM files in directory: %s", a.dir)
} }
func (a *localArtifact) State(name string) interface{} { func (a *artifact) State(name string) interface{} {
return nil return nil
} }
func (a *localArtifact) Destroy() error { func (a *artifact) Destroy() error {
return os.RemoveAll(a.dir) return os.RemoveAll(a.dir)
} }

View File

@ -68,7 +68,7 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error {
return fmt.Errorf("Failed to copy the vmx file %s: %s", srcVmx, err) return fmt.Errorf("Failed to copy the vmx file %s: %s", srcVmx, err)
} }
filesToClone, err := d.run(nil, "find", srcDir, "! -name '*.vmdk' ! -name '*.vmx' -type f") filesToClone, err := d.run(nil, "find", srcDir, "! -name '*.vmdk' ! -name '*.vmx' -type f ! -size 0")
if err != nil { if err != nil {
return fmt.Errorf("Failed to get the file list to copy: %s", err) return fmt.Errorf("Failed to get the file list to copy: %s", err)
} }
@ -96,22 +96,6 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error {
return fmt.Errorf("Failing to clone disk %s: %s", srcDisk, err) return fmt.Errorf("Failing to clone disk %s: %s", srcDisk, err)
} }
} }
//
// // FIXME: VMName should be taken from the config.
// vmxEdits := []string{
// "s/\\(display[Nn]ame = \\).*/\\1\"" + vmName + "\"/",
// "/ethernet..generated[aA]ddress =/d",
// "/uuid.bios =/d",
// "/uuid.location =/d",
// "/vc.uuid =/d",
// }
// for _, edit := range vmxEdits {
// err := d.sh("sed -i -e", "'", edit, "'", dstVmx)
// if err != nil {
// return fmt.Errorf("Failed to edit the destination file %s: %s", dstVmx, err)
// }
// }
log.Printf("Successfully cloned %s to %s\n", src, dst) log.Printf("Successfully cloned %s to %s\n", src, dst)
return nil return nil
} }
@ -460,7 +444,11 @@ func (ESX5Driver) UpdateVMX(_, password string, port uint, data map[string]strin
} }
func (d *ESX5Driver) CommHost(state multistep.StateBag) (string, error) { func (d *ESX5Driver) CommHost(state multistep.StateBag) (string, error) {
port := d.CommConfig.Port() sshc := state.Get("sshConfig").(SSHConfig).Comm
port := sshc.SSHPort
if sshc.Type == "winrm" {
port = sshc.WinRMPort
}
if address, ok := state.GetOk("vm_address"); ok { if address, ok := state.GetOk("vm_address"); ok {
return address.(string), nil return address.(string), nil

View File

@ -1,4 +1,4 @@
package iso package common
import ( import (
"fmt" "fmt"
@ -12,7 +12,7 @@ const (
// Artifact is the result of running the VMware builder, namely a set // Artifact is the result of running the VMware builder, namely a set
// of files associated with the resulting machine. // of files associated with the resulting machine.
type Artifact struct { type RemoteArtifact struct {
builderId string builderId string
id string id string
dir OutputDir dir OutputDir
@ -20,26 +20,26 @@ type Artifact struct {
config map[string]string config map[string]string
} }
func (a *Artifact) BuilderId() string { func (a *RemoteArtifact) BuilderId() string {
return a.builderId return a.builderId
} }
func (a *Artifact) Files() []string { func (a *RemoteArtifact) Files() []string {
return a.f return a.f
} }
func (a *Artifact) Id() string { func (*RemoteArtifact) Id() string {
return a.id return a.id
} }
func (a *Artifact) String() string { func (a *RemoteArtifact) String() string {
return fmt.Sprintf("VM files in directory: %s", a.dir) return fmt.Sprintf("VM files in directory: %s", a.dir)
} }
func (a *Artifact) State(name string) interface{} { func (a *RemoteArtifact) State(name string) interface{} {
return a.config[name] return a.config[name]
} }
func (a *Artifact) Destroy() error { func (a *RemoteArtifact) Destroy() error {
return a.dir.RemoveAll() return a.dir.RemoveAll()
} }

View File

@ -1,4 +1,4 @@
package iso package common
import ( import (
"testing" "testing"
@ -8,7 +8,7 @@ import (
func TestArtifact_Impl(t *testing.T) { func TestArtifact_Impl(t *testing.T) {
var raw interface{} var raw interface{}
raw = &Artifact{} raw = &RemoteArtifact{}
if _, ok := raw.(packer.Artifact); !ok { if _, ok := raw.(packer.Artifact); !ok {
t.Fatal("Artifact must be a proper artifact") t.Fatal("Artifact must be a proper artifact")
} }

View File

@ -19,8 +19,6 @@ import (
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
) )
const BuilderIdESX = "mitchellh.vmware-esx"
type Builder struct { type Builder struct {
config Config config Config
runner multistep.Runner runner multistep.Runner
@ -257,9 +255,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} }
// Determine the output dir implementation // Determine the output dir implementation
var dir OutputDir var dir vmwcommon.OutputDir
switch d := driver.(type) { switch d := driver.(type) {
case OutputDir: case vmwcommon.OutputDir:
dir = d dir = d
default: default:
dir = new(vmwcommon.LocalOutputDir) dir = new(vmwcommon.LocalOutputDir)
@ -281,6 +279,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
state.Put("driver", driver) state.Put("driver", driver)
state.Put("hook", hook) state.Put("hook", hook)
state.Put("ui", ui) state.Put("ui", ui)
state.Put("sshConfig", &b.config.SSHConfig)
steps := []multistep.Step{ steps := []multistep.Step{
&vmwcommon.StepPrepareTools{ &vmwcommon.StepPrepareTools{
@ -413,30 +412,13 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
dir.SetOutputDir(exportOutputPath) dir.SetOutputDir(exportOutputPath)
files, err = dir.ListFiles() files, err = dir.ListFiles()
} else { } else {
files, err = state.Get("dir").(OutputDir).ListFiles() files, err = state.Get("dir").(vmwcommon.OutputDir).ListFiles()
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Set the proper builder ID return vmwcommon.NewArtifact(dir, files, b.config.RemoteType != ""), nil
builderId := vmwcommon.BuilderId
if b.config.RemoteType != "" {
builderId = BuilderIdESX
}
config := make(map[string]string)
config[ArtifactConfKeepRegistered] = strconv.FormatBool(b.config.KeepRegistered)
config[ArtifactConfFormat] = b.config.Format
config[ArtifactConfSkipExport] = strconv.FormatBool(b.config.SkipExport)
return &Artifact{
builderId: builderId,
id: b.config.VMName,
dir: dir,
f: files,
config: config,
}, nil
} }
func (b *Builder) Cancel() { func (b *Builder) Cancel() {

View File

@ -1,14 +0,0 @@
package iso
// 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)
}

View File

@ -39,8 +39,17 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
return nil, fmt.Errorf("Failed creating VMware driver: %s", err) return nil, fmt.Errorf("Failed creating VMware driver: %s", err)
} }
// Setup the directory // Determine the output dir implementation
dir := new(vmwcommon.LocalOutputDir) var dir vmwcommon.OutputDir
switch d := driver.(type) {
case vmwcommon.OutputDir:
dir = d
default:
dir = new(vmwcommon.LocalOutputDir)
}
if b.config.RemoteType != "" {
b.config.OutputDir = b.config.VMName
}
dir.SetOutputDir(b.config.OutputDir) dir.SetOutputDir(b.config.OutputDir)
// Set up the state. // Set up the state.
@ -51,6 +60,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
state.Put("driver", driver) state.Put("driver", driver)
state.Put("hook", hook) state.Put("hook", hook)
state.Put("ui", ui) state.Put("ui", ui)
state.Put("sshConfig", b.config.SSHConfig)
// Build the steps. // Build the steps.
steps := []multistep.Step{ steps := []multistep.Step{
@ -138,6 +148,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
RemoveEthernetInterfaces: b.config.VMXConfig.VMXRemoveEthernet, RemoveEthernetInterfaces: b.config.VMXConfig.VMXRemoveEthernet,
VNCEnabled: !b.config.DisableVNC, VNCEnabled: !b.config.DisableVNC,
}, },
&vmwcommon.StepUploadVMX{
RemoteType: b.config.RemoteType,
},
} }
// Run the steps. // Run the steps.
@ -157,8 +170,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
if _, ok := state.GetOk(multistep.StateHalted); ok { if _, ok := state.GetOk(multistep.StateHalted); ok {
return nil, errors.New("Build was halted.") return nil, errors.New("Build was halted.")
} }
files, err := state.Get("dir").(vmwcommon.OutputDir).ListFiles()
if err != nil {
return nil, err
}
return vmwcommon.NewLocalArtifact(b.config.VMName, b.config.OutputDir) return vmwcommon.NewArtifact(dir, files, b.config.RemoteType != ""), nil
} }
// Cancel. // Cancel.