extract output dir configuration and defaulting into the step_output_dir, using pointers to make sure they get set properly back on the main config
This commit is contained in:
parent
3b2bedf794
commit
a2cfaace59
|
@ -33,7 +33,11 @@ type RemoteDriverMock struct {
|
|||
RemovedCachePath string
|
||||
CacheRemoved bool
|
||||
|
||||
ReturnValDirExists bool
|
||||
|
||||
ReloadVMErr error
|
||||
|
||||
outputDir string
|
||||
}
|
||||
|
||||
func (d *RemoteDriverMock) UploadISO(path string, checksum string, ui packer.Ui) (string, error) {
|
||||
|
@ -81,3 +85,33 @@ func (d *RemoteDriverMock) RemoveCache(localPath string) error {
|
|||
func (d *RemoteDriverMock) ReloadVM() error {
|
||||
return d.ReloadVMErr
|
||||
}
|
||||
|
||||
// the following functions satisfy the Outputdir interface
|
||||
|
||||
func (d *RemoteDriverMock) DirExists() (bool, error) {
|
||||
return d.ReturnValDirExists, nil
|
||||
}
|
||||
|
||||
func (d *RemoteDriverMock) ListFiles() ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func (d *RemoteDriverMock) MkdirAll() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *RemoteDriverMock) Remove(string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *RemoteDriverMock) RemoveAll() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *RemoteDriverMock) SetOutputDir(s string) {
|
||||
d.outputDir = s
|
||||
}
|
||||
|
||||
func (d *RemoteDriverMock) String() string {
|
||||
return d.outputDir
|
||||
}
|
||||
|
|
|
@ -16,13 +16,62 @@ import (
|
|||
type StepOutputDir struct {
|
||||
Force bool
|
||||
|
||||
OutputConfig *OutputConfig
|
||||
VMName string
|
||||
|
||||
RemoteType string
|
||||
|
||||
success bool
|
||||
}
|
||||
|
||||
func (s *StepOutputDir) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
dir := state.Get("dir").(OutputDir)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
func (s *StepOutputDir) SetOutputAndExportDirs(state multistep.StateBag) OutputDir {
|
||||
driver := state.Get("driver")
|
||||
|
||||
// Hold on to your pants. The output configuration is a little more complex
|
||||
// than you'd expect because of all the moving parts between local and
|
||||
// remote output, and exports, and legacy behavior.
|
||||
var dir OutputDir
|
||||
switch d := driver.(type) {
|
||||
case OutputDir:
|
||||
// The driver fulfils the OutputDir interface so that it can create
|
||||
// output files on the remote instance.
|
||||
dir = d
|
||||
default:
|
||||
// The driver will be running the build and creating the output
|
||||
// directory locally
|
||||
dir = new(LocalOutputDir)
|
||||
}
|
||||
|
||||
// If remote type is esx, we need to track both the output dir on the remote
|
||||
// instance and the output dir locally. exportOutputPath is where we track
|
||||
// the local output dir.
|
||||
exportOutputPath := s.OutputConfig.OutputDir
|
||||
|
||||
if s.RemoteType != "" {
|
||||
if s.OutputConfig.RemoteOutputDir != "" {
|
||||
// User set the remote output dir.
|
||||
s.OutputConfig.OutputDir = s.OutputConfig.RemoteOutputDir
|
||||
} else {
|
||||
// Default output dir to vm name. On remote esx instance, this will
|
||||
// become something like /vmfs/volumes/mydatastore/vmname/vmname.vmx
|
||||
s.OutputConfig.OutputDir = s.VMName
|
||||
}
|
||||
}
|
||||
// Remember, this one's either the output from a local build, or the remote
|
||||
// output from a remote build. Not the local export path for a remote build.
|
||||
dir.SetOutputDir(s.OutputConfig.OutputDir)
|
||||
|
||||
// Set dir in the state for use in file cleanup and artifact
|
||||
state.Put("dir", dir)
|
||||
state.Put("export_output_path", exportOutputPath)
|
||||
return dir
|
||||
}
|
||||
|
||||
func (s *StepOutputDir) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
ui.Say("Configuring output and export directories...")
|
||||
|
||||
dir := s.SetOutputAndExportDirs(state)
|
||||
exists, err := dir.DirExists()
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
|
@ -31,7 +80,7 @@ func (s *StepOutputDir) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
|
||||
if exists {
|
||||
if s.Force {
|
||||
ui.Say("Deleting previous output directory...")
|
||||
ui.Message("Deleting previous output directory...")
|
||||
dir.RemoveAll()
|
||||
} else {
|
||||
state.Put("error", fmt.Errorf(
|
||||
|
|
|
@ -9,16 +9,14 @@ import (
|
|||
"github.com/hashicorp/packer/helper/multistep"
|
||||
)
|
||||
|
||||
func testOutputDir(t *testing.T) *LocalOutputDir {
|
||||
func testOutputDir(t *testing.T) string {
|
||||
td, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
os.RemoveAll(td)
|
||||
|
||||
result := new(LocalOutputDir)
|
||||
result.SetOutputDir(td)
|
||||
return result
|
||||
return td
|
||||
}
|
||||
|
||||
func TestStepOutputDir_impl(t *testing.T) {
|
||||
|
@ -27,12 +25,20 @@ func TestStepOutputDir_impl(t *testing.T) {
|
|||
|
||||
func TestStepOutputDir(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
driver := new(DriverMock)
|
||||
state.Put("driver", driver)
|
||||
|
||||
dir := testOutputDir(t)
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(dir.dir)
|
||||
state.Put("dir", dir)
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
|
@ -41,29 +47,37 @@ func TestStepOutputDir(t *testing.T) {
|
|||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.dir); err != nil {
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test the cleanup
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(dir.dir); err != nil {
|
||||
if _, err := os.Stat(td); 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)
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Make sure the dir exists
|
||||
if err := os.MkdirAll(dir.dir, 0755); err != nil {
|
||||
if err := os.MkdirAll(td, 0755); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(dir.dir)
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
|
||||
|
@ -75,24 +89,33 @@ func TestStepOutputDir_existsNoForce(t *testing.T) {
|
|||
|
||||
// Test the cleanup
|
||||
step.Cleanup(state)
|
||||
if _, err := os.Stat(dir.dir); err != nil {
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatal("should not delete dir")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_existsForce(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
step.Force = true
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Make sure the dir exists
|
||||
if err := os.MkdirAll(dir.dir, 0755); err != nil {
|
||||
if err := os.MkdirAll(td, 0755); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(dir.dir)
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
|
@ -101,17 +124,22 @@ func TestStepOutputDir_existsForce(t *testing.T) {
|
|||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.dir); err != nil {
|
||||
if _, err := os.Stat(td); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_cancel(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
|
@ -120,24 +148,29 @@ func TestStepOutputDir_cancel(t *testing.T) {
|
|||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.dir); err != nil {
|
||||
if _, err := os.Stat(td); 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 {
|
||||
if _, err := os.Stat(td); err == nil {
|
||||
t.Fatal("directory should not exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_halt(t *testing.T) {
|
||||
state := testState(t)
|
||||
step := new(StepOutputDir)
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
}
|
||||
|
||||
dir := testOutputDir(t)
|
||||
state.Put("dir", dir)
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
}
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
|
@ -146,14 +179,46 @@ func TestStepOutputDir_halt(t *testing.T) {
|
|||
if _, ok := state.GetOk("error"); ok {
|
||||
t.Fatal("should NOT have error")
|
||||
}
|
||||
if _, err := os.Stat(dir.dir); err != nil {
|
||||
if _, err := os.Stat(td); 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 {
|
||||
if _, err := os.Stat(td); err == nil {
|
||||
t.Fatal("directory should not exist")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStepOutputDir_Remote(t *testing.T) {
|
||||
// Tests remote driver
|
||||
state := testState(t)
|
||||
driver := new(RemoteDriverMock)
|
||||
state.Put("driver", driver)
|
||||
|
||||
td := testOutputDir(t)
|
||||
outconfig := &OutputConfig{
|
||||
OutputDir: td,
|
||||
RemoteOutputDir: "remote_path",
|
||||
}
|
||||
|
||||
step := &StepOutputDir{
|
||||
OutputConfig: outconfig,
|
||||
VMName: "testVM",
|
||||
RemoteType: "esx5",
|
||||
}
|
||||
// Delete the test output directory when done
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
// Test the run
|
||||
if action := step.Run(context.Background(), state); action != multistep.ActionContinue {
|
||||
t.Fatalf("bad action: %#v", action)
|
||||
}
|
||||
|
||||
// We don't pre-create the output path for export but we do set it in state.
|
||||
exportOutputPath := state.Get("export_output_path").(string)
|
||||
if exportOutputPath != td {
|
||||
t.Fatalf("err: should have set export_output_path!")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,20 @@ import (
|
|||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func testLocalOutputDir(t *testing.T) *LocalOutputDir {
|
||||
td, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
os.RemoveAll(td)
|
||||
|
||||
result := new(LocalOutputDir)
|
||||
result.SetOutputDir(td)
|
||||
return result
|
||||
}
|
||||
|
||||
func testStepShutdownState(t *testing.T) multistep.StateBag {
|
||||
dir := testOutputDir(t)
|
||||
dir := testLocalOutputDir(t)
|
||||
if err := dir.MkdirAll(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
|
|
@ -36,44 +36,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, fmt.Errorf("Failed creating VMware driver: %s", err)
|
||||
}
|
||||
|
||||
// Hold on to your pants. The output configuration is a little complex
|
||||
// because of all the moving parts between local and remote output, and
|
||||
// exports, and legacy behavior.
|
||||
var dir vmwcommon.OutputDir
|
||||
switch d := driver.(type) {
|
||||
case vmwcommon.OutputDir:
|
||||
// Remote type is esx; the driver fulfils the OutputDir interface so
|
||||
// that it can create output files on the remote instance.
|
||||
dir = d
|
||||
default:
|
||||
// Remote type is ""; the driver will be running the build and creating
|
||||
// the output directory locally
|
||||
dir = new(vmwcommon.LocalOutputDir)
|
||||
}
|
||||
|
||||
// If remote type is esx, we need to track both the output dir on the remote
|
||||
// instance and the output dir locally. This is where we track the local
|
||||
// output dir.
|
||||
exportOutputPath := b.config.OutputDir
|
||||
|
||||
if b.config.RemoteType != "" {
|
||||
if b.config.RemoteOutputDir != "" {
|
||||
b.config.OutputDir = b.config.RemoteOutputDir
|
||||
} else {
|
||||
// Default output dir to vm name. On remote esx instance, this will
|
||||
// become something like /vmfs/volumes/mydatastore/vmname/vmname.vmx
|
||||
b.config.OutputDir = b.config.VMName
|
||||
}
|
||||
}
|
||||
// Remember, this one's either the output from a local build, or the remote
|
||||
// output from a remote build. Not the local export path for a remote build.
|
||||
dir.SetOutputDir(b.config.OutputDir)
|
||||
|
||||
// Setup the state bag
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("dir", dir)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
@ -95,7 +61,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Url: b.config.ISOUrls,
|
||||
},
|
||||
&vmwcommon.StepOutputDir{
|
||||
Force: b.config.PackerForce,
|
||||
Force: b.config.PackerForce,
|
||||
OutputConfig: &b.config.OutputConfig,
|
||||
RemoteType: b.config.RemoteType,
|
||||
VMName: b.config.VMName,
|
||||
},
|
||||
&common.StepCreateFloppy{
|
||||
Files: b.config.FloppyConfig.FloppyFiles,
|
||||
|
@ -194,7 +163,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
SkipExport: b.config.SkipExport,
|
||||
VMName: b.config.VMName,
|
||||
OVFToolOptions: b.config.OVFToolOptions,
|
||||
OutputDir: exportOutputPath,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -217,6 +185,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
// Compile the artifact list
|
||||
exportOutputPath := state.Get("export_output_path").(string) // set in StepOutputDir
|
||||
return vmwcommon.NewArtifact(b.config.RemoteType, b.config.Format, exportOutputPath,
|
||||
b.config.VMName, b.config.SkipExport, b.config.KeepRegistered, state)
|
||||
}
|
||||
|
|
|
@ -41,28 +41,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, fmt.Errorf("Failed creating VMware driver: %s", err)
|
||||
}
|
||||
|
||||
// Determine the output dir implementation
|
||||
var dir vmwcommon.OutputDir
|
||||
switch d := driver.(type) {
|
||||
case vmwcommon.OutputDir:
|
||||
dir = d
|
||||
default:
|
||||
dir = new(vmwcommon.LocalOutputDir)
|
||||
}
|
||||
|
||||
// The OutputDir will track remote esxi output; exportOutputPath preserves
|
||||
// the path to the output on the machine running Packer.
|
||||
exportOutputPath := b.config.OutputDir
|
||||
|
||||
if b.config.RemoteType != "" {
|
||||
b.config.OutputDir = b.config.VMName
|
||||
}
|
||||
dir.SetOutputDir(b.config.OutputDir)
|
||||
|
||||
// Set up the state.
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("debug", b.config.PackerDebug)
|
||||
state.Put("dir", dir)
|
||||
state.Put("driver", driver)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
@ -77,7 +58,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
ToolsUploadFlavor: b.config.ToolsUploadFlavor,
|
||||
},
|
||||
&vmwcommon.StepOutputDir{
|
||||
Force: b.config.PackerForce,
|
||||
Force: b.config.PackerForce,
|
||||
OutputConfig: &b.config.OutputConfig,
|
||||
RemoteType: b.config.RemoteType,
|
||||
VMName: b.config.VMName,
|
||||
},
|
||||
&common.StepCreateFloppy{
|
||||
Files: b.config.FloppyConfig.FloppyFiles,
|
||||
|
@ -91,8 +75,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Checksum: "none",
|
||||
},
|
||||
&StepCloneVMX{
|
||||
OutputDir: b.config.OutputDir,
|
||||
Path: b.config.SourcePath,
|
||||
OutputDir: &b.config.OutputDir,
|
||||
VMName: b.config.VMName,
|
||||
Linked: b.config.Linked,
|
||||
},
|
||||
|
@ -177,7 +161,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
SkipExport: b.config.SkipExport,
|
||||
VMName: b.config.VMName,
|
||||
OVFToolOptions: b.config.OVFToolOptions,
|
||||
OutputDir: exportOutputPath,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -201,6 +184,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
// Artifact
|
||||
log.Printf("Generating artifact...")
|
||||
exportOutputPath := state.Get("export_output_path").(string) // set in StepOutputDir
|
||||
return vmwcommon.NewArtifact(b.config.RemoteType, b.config.Format, exportOutputPath,
|
||||
b.config.VMName, b.config.SkipExport, b.config.KeepRegistered, state)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
// StepCloneVMX takes a VMX file and clones the VM into the output directory.
|
||||
type StepCloneVMX struct {
|
||||
OutputDir string
|
||||
OutputDir *string
|
||||
Path string
|
||||
VMName string
|
||||
Linked bool
|
||||
|
@ -33,7 +33,7 @@ func (s *StepCloneVMX) Run(ctx context.Context, state multistep.StateBag) multis
|
|||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
// Set the path we want for the new .vmx file and clone
|
||||
vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx")
|
||||
vmxPath := filepath.Join(*s.OutputDir, s.VMName+".vmx")
|
||||
ui.Say("Cloning source VM...")
|
||||
log.Printf("Cloning from: %s", s.Path)
|
||||
log.Printf("Cloning to: %s", vmxPath)
|
||||
|
@ -96,7 +96,7 @@ func (s *StepCloneVMX) Run(ctx context.Context, state multistep.StateBag) multis
|
|||
var diskFullPaths []string
|
||||
for _, diskFilename := range diskFilenames {
|
||||
log.Printf("Found attached disk with filename: %s", diskFilename)
|
||||
diskFullPaths = append(diskFullPaths, filepath.Join(s.OutputDir, diskFilename))
|
||||
diskFullPaths = append(diskFullPaths, filepath.Join(*s.OutputDir, diskFilename))
|
||||
}
|
||||
|
||||
if len(diskFullPaths) == 0 {
|
||||
|
|
|
@ -62,7 +62,7 @@ func TestStepCloneVMX(t *testing.T) {
|
|||
|
||||
state := testState(t)
|
||||
step := new(StepCloneVMX)
|
||||
step.OutputDir = td
|
||||
step.OutputDir = &td
|
||||
step.Path = sourcePath
|
||||
step.VMName = "foo"
|
||||
|
||||
|
|
Loading…
Reference in New Issue