Add StepPostMountCommands

This commit is contained in:
Paul Meyer 2019-05-31 18:39:43 +00:00
parent d1f8b8545d
commit addbdedea9
3 changed files with 151 additions and 7 deletions

View File

@ -19,7 +19,7 @@ type StepPostMountCommands struct {
}
func (s *StepPostMountCommands) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*Config)
config := state.Get("config").(interpolateContextProvider)
device := state.Get("device").(string)
mountPath := state.Get("mount_path").(string)
ui := state.Get("ui").(packer.Ui)
@ -29,7 +29,7 @@ func (s *StepPostMountCommands) Run(ctx context.Context, state multistep.StateBa
return multistep.ActionContinue
}
ictx := config.ctx
ictx := config.GetContext()
ictx.Data = &postMountCommandsData{
Device: device,
MountPath: mountPath,

View File

@ -8,7 +8,7 @@ import (
"runtime"
"github.com/Azure/azure-sdk-for-go/profiles/latest/compute/mgmt/compute"
amznchroot "github.com/hashicorp/packer/builder/amazon/chroot"
"github.com/hashicorp/packer/builder/amazon/chroot"
azcommon "github.com/hashicorp/packer/builder/azure/common"
"github.com/hashicorp/packer/builder/azure/common/client"
"github.com/hashicorp/packer/common"
@ -23,8 +23,12 @@ type Config struct {
FromScratch bool `mapstructure:"from_scratch"`
CommandWrapper string `mapstructure:"command_wrapper"`
PreMountCommands []string `mapstructure:"pre_mount_commands"`
CommandWrapper string `mapstructure:"command_wrapper"`
MountOptions []string `mapstructure:"mount_options"`
MountPartition string `mapstructure:"mount_partition"`
MountPath string `mapstructure:"mount_path"`
PreMountCommands []string `mapstructure:"pre_mount_commands"`
PostMountCommands []string `mapstructure:"post_mount_commands"`
OSDiskSizeGB int32 `mapstructure:"osdisk_size_gb"`
OSDiskStorageAccountType string `mapstructure:"osdisk_storageaccounttype"`
@ -93,7 +97,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
state.Put("config", &b.config)
state.Put("hook", hook)
state.Put("ui", ui)
state.Put("wrappedCommand", amznchroot.CommandWrapper(wrappedCommand))
state.Put("wrappedCommand", chroot.CommandWrapper(wrappedCommand))
info, err := azcli.MetadataClient().GetComputeInfo()
if err != nil {
@ -136,9 +140,17 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
ResourceGroup: info.ResourceGroupName,
DiskName: osDiskName,
},
&amznchroot.StepPreMountCommands{
&chroot.StepPreMountCommands{
Commands: b.config.PreMountCommands,
},
&StepMountDevice{
MountOptions: b.config.MountOptions,
MountPartition: b.config.MountPartition,
MountPath: b.config.MountPath,
},
&chroot.StepPostMountCommands{
Commands: b.config.PostMountCommands,
},
)
// Run!

View File

@ -0,0 +1,132 @@
package chroot
// mostly borrowed from ./builder/amazon/chroot/step_mount_device.go
import (
"bytes"
"context"
"fmt"
"github.com/hashicorp/packer/builder/amazon/chroot"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"log"
"os"
"path/filepath"
"strings"
)
var _ multistep.Step = &StepMountDevice{}
type StepMountDevice struct {
MountOptions []string
MountPartition string
MountPath string
mountPath string
}
func (s *StepMountDevice) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
device := state.Get("device").(string)
config := state.Get("config").(*Config)
wrappedCommand := state.Get("wrappedCommand").(chroot.CommandWrapper)
ictx := config.ctx
ictx.Data = &struct{ Device string }{Device: filepath.Base(device)}
mountPath, err := interpolate.Render(s.MountPath, &ictx)
if err != nil {
err := fmt.Errorf("error preparing mount directory: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
mountPath, err = filepath.Abs(mountPath)
if err != nil {
err := fmt.Errorf("error preparing mount directory: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
log.Printf("Mount path: %s", mountPath)
if err := os.MkdirAll(mountPath, 0755); err != nil {
err := fmt.Errorf("error creating mount directory: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
deviceMount := fmt.Sprintf("%s%s", device, s.MountPartition)
state.Put("deviceMount", deviceMount)
ui.Say("Mounting the root device...")
stderr := new(bytes.Buffer)
// build mount options from mount_options config, useful for nouuid options
// or other specific device type settings for mount
opts := ""
if len(s.MountOptions) > 0 {
opts = "-o " + strings.Join(s.MountOptions, " -o ")
}
mountCommand, err := wrappedCommand(
fmt.Sprintf("mount %s %s %s", opts, deviceMount, mountPath))
if err != nil {
err := fmt.Errorf("error creating mount command: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
log.Printf("[DEBUG] (step mount) mount command is %s", mountCommand)
cmd := chroot.ShellCommand(mountCommand)
cmd.Stderr = stderr
if err := cmd.Run(); err != nil {
err := fmt.Errorf(
"error mounting root volume: %s\nStderr: %s", err, stderr.String())
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
// Set the mount path so we remember to unmount it later
s.mountPath = mountPath
state.Put("mount_path", s.mountPath)
state.Put("mount_device_cleanup", s)
return multistep.ActionContinue
}
func (s *StepMountDevice) Cleanup(state multistep.StateBag) {
ui := state.Get("ui").(packer.Ui)
if err := s.CleanupFunc(state); err != nil {
ui.Error(err.Error())
}
}
func (s *StepMountDevice) CleanupFunc(state multistep.StateBag) error {
if s.mountPath == "" {
return nil
}
ui := state.Get("ui").(packer.Ui)
wrappedCommand := state.Get("wrappedCommand").(chroot.CommandWrapper)
ui.Say("Unmounting the root device...")
unmountCommand, err := wrappedCommand(fmt.Sprintf("umount %s", s.mountPath))
if err != nil {
return fmt.Errorf("error creating unmount command: %s", err)
}
cmd := chroot.ShellCommand(unmountCommand)
if err := cmd.Run(); err != nil {
return fmt.Errorf("error unmounting root device: %s", err)
}
s.mountPath = ""
return nil
}