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 (
"fmt"
"os"
"path/filepath"
"github.com/hashicorp/packer/packer"
)
// BuilderId for the local artifacts
const BuilderId = "mitchellh.vmware"
const BuilderIdESX = "mitchellh.vmware-esx"
// Artifact is the result of running the VMware builder, namely a set
// of files associated with the resulting machine.
type localArtifact struct {
type artifact struct {
builderId string
id 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
// in the given directory.
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 &localArtifact{
id: id,
return &artifact{
builderId: id,
dir: dir,
f: files,
}, 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
}
func (a *localArtifact) Files() []string {
func (a *artifact) Files() []string {
return a.f
}
func (a *localArtifact) Id() string {
func (*artifact) Id() string {
return a.id
}
func (a *localArtifact) String() string {
func (a *artifact) String() string {
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
}
func (a *localArtifact) Destroy() error {
func (a *artifact) Destroy() error {
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)
}
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 {
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)
}
}
//
// // 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)
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) {
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 {
return address.(string), nil

View File

@ -1,4 +1,4 @@
package iso
package common
import (
"fmt"
@ -12,7 +12,7 @@ const (
// Artifact is the result of running the VMware builder, namely a set
// of files associated with the resulting machine.
type Artifact struct {
type RemoteArtifact struct {
builderId string
id string
dir OutputDir
@ -20,26 +20,26 @@ type Artifact struct {
config map[string]string
}
func (a *Artifact) BuilderId() string {
func (a *RemoteArtifact) BuilderId() string {
return a.builderId
}
func (a *Artifact) Files() []string {
func (a *RemoteArtifact) Files() []string {
return a.f
}
func (a *Artifact) Id() string {
func (*RemoteArtifact) Id() string {
return a.id
}
func (a *Artifact) String() string {
func (a *RemoteArtifact) String() string {
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]
}
func (a *Artifact) Destroy() error {
func (a *RemoteArtifact) Destroy() error {
return a.dir.RemoveAll()
}

View File

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

View File

@ -19,8 +19,6 @@ import (
"github.com/hashicorp/packer/template/interpolate"
)
const BuilderIdESX = "mitchellh.vmware-esx"
type Builder struct {
config Config
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
var dir OutputDir
var dir vmwcommon.OutputDir
switch d := driver.(type) {
case OutputDir:
case vmwcommon.OutputDir:
dir = d
default:
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("hook", hook)
state.Put("ui", ui)
state.Put("sshConfig", &b.config.SSHConfig)
steps := []multistep.Step{
&vmwcommon.StepPrepareTools{
@ -413,30 +412,13 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
dir.SetOutputDir(exportOutputPath)
files, err = dir.ListFiles()
} else {
files, err = state.Get("dir").(OutputDir).ListFiles()
files, err = state.Get("dir").(vmwcommon.OutputDir).ListFiles()
}
if err != nil {
return nil, err
}
// Set the proper builder ID
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
return vmwcommon.NewArtifact(dir, files, b.config.RemoteType != ""), nil
}
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)
}
// Setup the directory
dir := new(vmwcommon.LocalOutputDir)
// Determine the output dir implementation
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)
// 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("hook", hook)
state.Put("ui", ui)
state.Put("sshConfig", b.config.SSHConfig)
// Build the steps.
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,
VNCEnabled: !b.config.DisableVNC,
},
&vmwcommon.StepUploadVMX{
RemoteType: b.config.RemoteType,
},
}
// 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 {
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.