Commit 9bb7d0a2 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

Merge pull request #2152 from abayer/gce-optional-internal-ip

builder/google: Adds support for using the internal IP rather than NAT IP in GCE
parents 6fbf4147 ebdd0d99
...@@ -35,6 +35,7 @@ type Config struct { ...@@ -35,6 +35,7 @@ type Config struct {
SourceImageProjectId string `mapstructure:"source_image_project_id"` SourceImageProjectId string `mapstructure:"source_image_project_id"`
RawStateTimeout string `mapstructure:"state_timeout"` RawStateTimeout string `mapstructure:"state_timeout"`
Tags []string `mapstructure:"tags"` Tags []string `mapstructure:"tags"`
UseInternalIP bool `mapstructure:"use_internal_ip"`
Zone string `mapstructure:"zone"` Zone string `mapstructure:"zone"`
account accountFile account accountFile
......
...@@ -116,6 +116,21 @@ func TestConfigPrepare(t *testing.T) { ...@@ -116,6 +116,21 @@ func TestConfigPrepare(t *testing.T) {
"5s", "5s",
false, false,
}, },
{
"use_internal_ip",
nil,
false,
},
{
"use_internal_ip",
false,
false,
},
{
"use_internal_ip",
"SO VERY BAD",
true,
},
} }
for _, tc := range cases { for _, tc := range cases {
......
...@@ -24,6 +24,9 @@ type Driver interface { ...@@ -24,6 +24,9 @@ type Driver interface {
// GetNatIP gets the NAT IP address for the instance. // GetNatIP gets the NAT IP address for the instance.
GetNatIP(zone, name string) (string, error) GetNatIP(zone, name string) (string, error)
// GetInternalIP gets the GCE-internal IP address for the instance.
GetInternalIP(zone, name string) (string, error)
// RunInstance takes the given config and launches an instance. // RunInstance takes the given config and launches an instance.
RunInstance(*InstanceConfig) (<-chan error, error) RunInstance(*InstanceConfig) (<-chan error, error)
......
...@@ -157,7 +157,6 @@ func (d *driverGCE) GetNatIP(zone, name string) (string, error) { ...@@ -157,7 +157,6 @@ func (d *driverGCE) GetNatIP(zone, name string) (string, error) {
if ni.AccessConfigs == nil { if ni.AccessConfigs == nil {
continue continue
} }
for _, ac := range ni.AccessConfigs { for _, ac := range ni.AccessConfigs {
if ac.NatIP != "" { if ac.NatIP != "" {
return ac.NatIP, nil return ac.NatIP, nil
...@@ -168,6 +167,22 @@ func (d *driverGCE) GetNatIP(zone, name string) (string, error) { ...@@ -168,6 +167,22 @@ func (d *driverGCE) GetNatIP(zone, name string) (string, error) {
return "", nil return "", nil
} }
func (d *driverGCE) GetInternalIP(zone, name string) (string, error) {
instance, err := d.service.Instances.Get(d.projectId, zone, name).Do()
if err != nil {
return "", err
}
for _, ni := range instance.NetworkInterfaces {
if ni.NetworkIP == "" {
continue
}
return ni.NetworkIP, nil
}
return "", nil
}
func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) { func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
// Get the zone // Get the zone
d.ui.Message(fmt.Sprintf("Loading zone: %s", c.Zone)) d.ui.Message(fmt.Sprintf("Loading zone: %s", c.Zone))
......
...@@ -30,6 +30,11 @@ type DriverMock struct { ...@@ -30,6 +30,11 @@ type DriverMock struct {
GetNatIPResult string GetNatIPResult string
GetNatIPErr error GetNatIPErr error
GetInternalIPZone string
GetInternalIPName string
GetInternalIPResult string
GetInternalIPErr error
RunInstanceConfig *InstanceConfig RunInstanceConfig *InstanceConfig
RunInstanceErrCh <-chan error RunInstanceErrCh <-chan error
RunInstanceErr error RunInstanceErr error
...@@ -108,6 +113,12 @@ func (d *DriverMock) GetNatIP(zone, name string) (string, error) { ...@@ -108,6 +113,12 @@ func (d *DriverMock) GetNatIP(zone, name string) (string, error) {
return d.GetNatIPResult, d.GetNatIPErr return d.GetNatIPResult, d.GetNatIPErr
} }
func (d *DriverMock) GetInternalIP(zone, name string) (string, error) {
d.GetInternalIPZone = zone
d.GetInternalIPName = name
return d.GetInternalIPResult, d.GetInternalIPErr
}
func (d *DriverMock) RunInstance(c *InstanceConfig) (<-chan error, error) { func (d *DriverMock) RunInstance(c *InstanceConfig) (<-chan error, error) {
d.RunInstanceConfig = c d.RunInstanceConfig = c
......
...@@ -40,6 +40,24 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction { ...@@ -40,6 +40,24 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt return multistep.ActionHalt
} }
if config.UseInternalIP {
ip, err := driver.GetInternalIP(config.Zone, instanceName)
if err != nil {
err := fmt.Errorf("Error retrieving instance internal ip address: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if s.Debug {
if ip != "" {
ui.Message(fmt.Sprintf("Internal IP: %s", ip))
}
}
ui.Message(fmt.Sprintf("IP: %s", ip))
state.Put("instance_ip", ip)
return multistep.ActionContinue
} else {
ip, err := driver.GetNatIP(config.Zone, instanceName) ip, err := driver.GetNatIP(config.Zone, instanceName)
if err != nil { if err != nil {
err := fmt.Errorf("Error retrieving instance nat ip address: %s", err) err := fmt.Errorf("Error retrieving instance nat ip address: %s", err)
...@@ -53,10 +71,10 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction { ...@@ -53,10 +71,10 @@ func (s *StepInstanceInfo) Run(state multistep.StateBag) multistep.StepAction {
ui.Message(fmt.Sprintf("Public IP: %s", ip)) ui.Message(fmt.Sprintf("Public IP: %s", ip))
} }
} }
ui.Message(fmt.Sprintf("IP: %s", ip)) ui.Message(fmt.Sprintf("IP: %s", ip))
state.Put("instance_ip", ip) state.Put("instance_ip", ip)
return multistep.ActionContinue return multistep.ActionContinue
}
} }
// Cleanup. // Cleanup.
......
...@@ -49,6 +49,46 @@ func TestStepInstanceInfo(t *testing.T) { ...@@ -49,6 +49,46 @@ func TestStepInstanceInfo(t *testing.T) {
} }
} }
func TestStepInstanceInfo_InternalIP(t *testing.T) {
state := testState(t)
step := new(StepInstanceInfo)
defer step.Cleanup(state)
state.Put("instance_name", "foo")
config := state.Get("config").(*Config)
config.UseInternalIP = true
driver := state.Get("driver").(*DriverMock)
driver.GetNatIPResult = "1.2.3.4"
driver.GetInternalIPResult = "5.6.7.8"
// run the step
if action := step.Run(state); action != multistep.ActionContinue {
t.Fatalf("bad action: %#v", action)
}
// Verify state
if driver.WaitForInstanceState != "RUNNING" {
t.Fatalf("bad: %#v", driver.WaitForInstanceState)
}
if driver.WaitForInstanceZone != config.Zone {
t.Fatalf("bad: %#v", driver.WaitForInstanceZone)
}
if driver.WaitForInstanceName != "foo" {
t.Fatalf("bad: %#v", driver.WaitForInstanceName)
}
ipRaw, ok := state.GetOk("instance_ip")
if !ok {
t.Fatal("should have ip")
}
if ip, ok := ipRaw.(string); !ok {
t.Fatal("ip is not a string")
} else if ip != "5.6.7.8" {
t.Fatalf("bad ip: %s", ip)
}
}
func TestStepInstanceInfo_getNatIPError(t *testing.T) { func TestStepInstanceInfo_getNatIPError(t *testing.T) {
state := testState(t) state := testState(t)
step := new(StepInstanceInfo) step := new(StepInstanceInfo)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment