Support for local HTTP server (#116)

pull/8480/head
Michael Kuzmin 7 years ago
commit a62012a78c

@ -63,12 +63,19 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Datastore: b.config.Datastore,
Host: b.config.Host,
},
&packerCommon.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
HTTPPortMin: b.config.HTTPPortMin,
HTTPPortMax: b.config.HTTPPortMax,
},
&common.StepRun{
Config: &b.config.RunConfig,
SetOrder: true,
},
&StepBootCommand{
Config: &b.config.BootConfig,
Ctx: b.config.ctx,
VMName: b.config.VMName,
},
&common.StepWaitForIp{},
&communicator.StepConnect{

@ -11,6 +11,7 @@ import (
type Config struct {
packerCommon.PackerConfig `mapstructure:",squash"`
packerCommon.HTTPConfig `mapstructure:",squash"`
common.ConnectConfig `mapstructure:",squash"`
CreateConfig `mapstructure:",squash"`
@ -36,6 +37,11 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &c.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"boot_command",
},
},
}, raws...)
if err != nil {
return nil, nil, err
@ -46,6 +52,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, c.CreateConfig.Prepare()...)
errs = packer.MultiErrorAppend(errs, c.LocationConfig.Prepare()...)
errs = packer.MultiErrorAppend(errs, c.HardwareConfig.Prepare()...)
errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...)
errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare()...)

@ -3,12 +3,14 @@ package iso
import (
"context"
"fmt"
"github.com/hashicorp/packer/common"
packerCommon "github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"github.com/jetbrains-infra/packer-builder-vsphere/driver"
"golang.org/x/mobile/event/key"
"log"
"net"
"os"
"strings"
"time"
@ -18,10 +20,17 @@ import (
type BootConfig struct {
BootCommand []string `mapstructure:"boot_command"`
RawBootWait string `mapstructure:"boot_wait"` // example: "1m30s"; default: "10s"
HTTPIP string `mapstructure:"http_ip"`
bootWait time.Duration
}
type bootCommandTemplateData struct {
HTTPIP string
HTTPPort uint
Name string
}
func (c *BootConfig) Prepare() []error {
var errs []error
@ -40,6 +49,8 @@ func (c *BootConfig) Prepare() []error {
type StepBootCommand struct {
Config *BootConfig
VMName string
Ctx interpolate.Context
}
var special = map[string]key.Code{
@ -71,10 +82,10 @@ var special = map[string]key.Code{
"<down>": key.CodeDownArrow,
}
var keyInterval = common.PackerKeyDefault
var keyInterval = packerCommon.PackerKeyDefault
func init() {
if delay, err := time.ParseDuration(os.Getenv(common.PackerKeyEnv)); err == nil {
if delay, err := time.ParseDuration(os.Getenv(packerCommon.PackerKeyEnv)); err == nil {
keyInterval = delay
}
}
@ -101,13 +112,35 @@ WAITLOOP:
}
}
ui.Say("Typing boot command...")
ip, err := getHostIP(s.Config.HTTPIP)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
err = packerCommon.SetHTTPIP(ip)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
port := state.Get("http_port").(uint)
s.Ctx.Data = &bootCommandTemplateData{
ip,
port,
s.VMName,
}
ui.Say(fmt.Sprintf("HTTP server is working at http://%v:%v/", ip, port))
ui.Say("Typing boot command...")
var keyAlt bool
var keyCtrl bool
var keyShift bool
for _, command := range s.Config.BootCommand {
message, err := interpolate.Render(command, &s.Ctx)
if err != nil {
state.Put("error", err)
return multistep.ActionHalt
}
for _, message := range s.Config.BootCommand {
for len(message) > 0 {
if _, ok := state.GetOk(multistep.StateCancelled); ok {
return multistep.ActionHalt
@ -205,3 +238,28 @@ WAITLOOP:
}
func (s *StepBootCommand) Cleanup(state multistep.StateBag) {}
func getHostIP(s string) (string, error) {
if s != "" {
if net.ParseIP(s) != nil {
return s, nil
} else {
return "", fmt.Errorf("invalid IP address")
}
}
addrs, err := net.InterfaceAddrs()
if err != nil {
return "", err
}
for _, a := range addrs {
ipnet, ok := a.(*net.IPNet)
if ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String(), nil
}
}
}
return "", fmt.Errorf("IP not found")
}

Loading…
Cancel
Save