Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
packer
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kristopher Ruzic
packer
Commits
a72d31fb
Commit
a72d31fb
authored
Dec 13, 2013
by
Mitchell Hashimoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
builder/googlecompute: get instance info
parent
57f707df
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
233 additions
and
44 deletions
+233
-44
builder/googlecompute/api.go
builder/googlecompute/api.go
+0
-32
builder/googlecompute/builder.go
builder/googlecompute/builder.go
+1
-1
builder/googlecompute/driver.go
builder/googlecompute/driver.go
+6
-0
builder/googlecompute/driver_gce.go
builder/googlecompute/driver_gce.go
+37
-0
builder/googlecompute/driver_mock.go
builder/googlecompute/driver_mock.go
+31
-0
builder/googlecompute/step_instance_info.go
builder/googlecompute/step_instance_info.go
+24
-11
builder/googlecompute/step_instance_info_test.go
builder/googlecompute/step_instance_info_test.go
+134
-0
No files found.
builder/googlecompute/api.go
View file @
a72d31fb
...
...
@@ -66,18 +66,6 @@ func New(projectId string, zone string, c *clientSecrets, pemKey []byte) (*Googl
return
googleComputeClient
,
nil
}
// InstanceStatus returns a string representing the status of the named instance.
// Status will be one of: "PROVISIONING", "STAGING", "RUNNING", "STOPPING",
// "STOPPED", "TERMINATED".
func
(
g
*
GoogleComputeClient
)
InstanceStatus
(
zone
,
name
string
)
(
string
,
error
)
{
instanceGetCall
:=
g
.
Service
.
Instances
.
Get
(
g
.
ProjectId
,
zone
,
name
)
instance
,
err
:=
instanceGetCall
.
Do
()
if
err
!=
nil
{
return
""
,
err
}
return
instance
.
Status
,
nil
}
// CreateImage registers a GCE Image with a project.
func
(
g
*
GoogleComputeClient
)
CreateImage
(
name
,
description
,
sourceURL
string
)
(
*
compute
.
Operation
,
error
)
{
imageRawDisk
:=
&
compute
.
ImageRawDisk
{
...
...
@@ -98,26 +86,6 @@ func (g *GoogleComputeClient) CreateImage(name, description, sourceURL string) (
return
operation
,
nil
}
// GetNatIp returns the public IPv4 address for named GCE instance.
func
(
g
*
GoogleComputeClient
)
GetNatIP
(
zone
,
name
string
)
(
string
,
error
)
{
instanceGetCall
:=
g
.
Service
.
Instances
.
Get
(
g
.
ProjectId
,
zone
,
name
)
instance
,
err
:=
instanceGetCall
.
Do
()
if
err
!=
nil
{
return
""
,
err
}
for
_
,
ni
:=
range
instance
.
NetworkInterfaces
{
if
ni
.
AccessConfigs
==
nil
{
continue
}
for
_
,
ac
:=
range
ni
.
AccessConfigs
{
if
ac
.
NatIP
!=
""
{
return
ac
.
NatIP
,
nil
}
}
}
return
""
,
nil
}
// ZoneOperationStatus returns the status for the named zone operation.
func
(
g
*
GoogleComputeClient
)
ZoneOperationStatus
(
zone
,
name
string
)
(
string
,
error
)
{
zoneOperationsGetCall
:=
g
.
Service
.
ZoneOperations
.
Get
(
g
.
ProjectId
,
zone
,
name
)
...
...
builder/googlecompute/builder.go
View file @
a72d31fb
...
...
@@ -50,9 +50,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
steps
:=
[]
multistep
.
Step
{
new
(
StepCreateSSHKey
),
new
(
StepCreateInstance
),
new
(
StepInstanceInfo
),
}
/*
new(stepInstanceInfo),
&common.StepConnectSSH{
SSHAddress: sshAddress,
SSHConfig: sshConfig,
...
...
builder/googlecompute/driver.go
View file @
a72d31fb
...
...
@@ -7,8 +7,14 @@ type Driver interface {
// DeleteInstance deletes the given instance.
DeleteInstance
(
zone
,
name
string
)
(
<-
chan
error
,
error
)
// GetNatIP gets the NAT IP address for the instance.
GetNatIP
(
zone
,
name
string
)
(
string
,
error
)
// RunInstance takes the given config and launches an instance.
RunInstance
(
*
InstanceConfig
)
(
<-
chan
error
,
error
)
// WaitForInstance waits for an instance to reach the given state.
WaitForInstance
(
state
,
zone
,
name
string
)
<-
chan
error
}
type
InstanceConfig
struct
{
...
...
builder/googlecompute/driver_gce.go
View file @
a72d31fb
...
...
@@ -70,6 +70,27 @@ func (d *driverGCE) DeleteInstance(zone, name string) (<-chan error, error) {
return
errCh
,
nil
}
func
(
d
*
driverGCE
)
GetNatIP
(
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
.
AccessConfigs
==
nil
{
continue
}
for
_
,
ac
:=
range
ni
.
AccessConfigs
{
if
ac
.
NatIP
!=
""
{
return
ac
.
NatIP
,
nil
}
}
}
return
""
,
nil
}
func
(
d
*
driverGCE
)
RunInstance
(
c
*
InstanceConfig
)
(
<-
chan
error
,
error
)
{
// Get the zone
d
.
ui
.
Message
(
fmt
.
Sprintf
(
"Loading zone: %s"
,
c
.
Zone
))
...
...
@@ -156,6 +177,12 @@ func (d *driverGCE) RunInstance(c *InstanceConfig) (<-chan error, error) {
return
errCh
,
nil
}
func
(
d
*
driverGCE
)
WaitForInstance
(
state
,
zone
,
name
string
)
<-
chan
error
{
errCh
:=
make
(
chan
error
,
1
)
go
waitForState
(
errCh
,
state
,
d
.
refreshInstanceState
(
zone
,
name
))
return
errCh
}
func
(
d
*
driverGCE
)
getImage
(
name
string
)
(
image
*
compute
.
Image
,
err
error
)
{
projects
:=
[]
string
{
d
.
projectId
,
"debian-cloud"
,
"centos-cloud"
}
for
_
,
project
:=
range
projects
{
...
...
@@ -173,6 +200,16 @@ func (d *driverGCE) getImage(name string) (image *compute.Image, err error) {
return
}
func
(
d
*
driverGCE
)
refreshInstanceState
(
zone
,
name
string
)
stateRefreshFunc
{
return
func
()
(
string
,
error
)
{
instance
,
err
:=
d
.
service
.
Instances
.
Get
(
d
.
projectId
,
zone
,
name
)
.
Do
()
if
err
!=
nil
{
return
""
,
err
}
return
instance
.
Status
,
nil
}
}
func
(
d
*
driverGCE
)
refreshZoneOp
(
zone
string
,
op
*
compute
.
Operation
)
stateRefreshFunc
{
return
func
()
(
string
,
error
)
{
newOp
,
err
:=
d
.
service
.
ZoneOperations
.
Get
(
d
.
projectId
,
zone
,
op
.
Name
)
.
Do
()
...
...
builder/googlecompute/driver_mock.go
View file @
a72d31fb
...
...
@@ -8,9 +8,19 @@ type DriverMock struct {
DeleteInstanceErrCh
<-
chan
error
DeleteInstanceErr
error
GetNatIPZone
string
GetNatIPName
string
GetNatIPResult
string
GetNatIPErr
error
RunInstanceConfig
*
InstanceConfig
RunInstanceErrCh
<-
chan
error
RunInstanceErr
error
WaitForInstanceState
string
WaitForInstanceZone
string
WaitForInstanceName
string
WaitForInstanceErrCh
<-
chan
error
}
func
(
d
*
DriverMock
)
DeleteInstance
(
zone
,
name
string
)
(
<-
chan
error
,
error
)
{
...
...
@@ -27,6 +37,12 @@ func (d *DriverMock) DeleteInstance(zone, name string) (<-chan error, error) {
return
resultCh
,
d
.
DeleteInstanceErr
}
func
(
d
*
DriverMock
)
GetNatIP
(
zone
,
name
string
)
(
string
,
error
)
{
d
.
GetNatIPZone
=
zone
d
.
GetNatIPName
=
name
return
d
.
GetNatIPResult
,
d
.
GetNatIPErr
}
func
(
d
*
DriverMock
)
RunInstance
(
c
*
InstanceConfig
)
(
<-
chan
error
,
error
)
{
d
.
RunInstanceConfig
=
c
...
...
@@ -39,3 +55,18 @@ func (d *DriverMock) RunInstance(c *InstanceConfig) (<-chan error, error) {
return
resultCh
,
d
.
RunInstanceErr
}
func
(
d
*
DriverMock
)
WaitForInstance
(
state
,
zone
,
name
string
)
<-
chan
error
{
d
.
WaitForInstanceState
=
state
d
.
WaitForInstanceZone
=
zone
d
.
WaitForInstanceName
=
name
resultCh
:=
d
.
WaitForInstanceErrCh
if
resultCh
==
nil
{
ch
:=
make
(
chan
error
)
close
(
ch
)
resultCh
=
ch
}
return
resultCh
}
builder/googlecompute/step_instance_info.go
View file @
a72d31fb
package
googlecompute
import
(
"errors"
"fmt"
"time"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)
// stepInstanceInfo represents a Packer build step that gathers GCE instance info.
type
s
tepInstanceInfo
int
type
S
tepInstanceInfo
int
// Run executes the Packer build step that gathers GCE instance info.
func
(
s
*
stepInstanceInfo
)
Run
(
state
multistep
.
StateBag
)
multistep
.
StepAction
{
var
(
client
=
state
.
Get
(
"client"
)
.
(
*
GoogleComputeClient
)
config
=
state
.
Get
(
"config"
)
.
(
*
Config
)
ui
=
state
.
Get
(
"ui"
)
.
(
packer
.
Ui
)
)
func
(
s
*
StepInstanceInfo
)
Run
(
state
multistep
.
StateBag
)
multistep
.
StepAction
{
config
:=
state
.
Get
(
"config"
)
.
(
*
Config
)
driver
:=
state
.
Get
(
"driver"
)
.
(
Driver
)
ui
:=
state
.
Get
(
"ui"
)
.
(
packer
.
Ui
)
instanceName
:=
state
.
Get
(
"instance_name"
)
.
(
string
)
err
:=
waitForInstanceState
(
"RUNNING"
,
config
.
Zone
,
instanceName
,
client
,
config
.
stateTimeout
)
ui
.
Say
(
"Waiting for the instance to become running..."
)
errCh
:=
driver
.
WaitForInstance
(
"RUNNING"
,
config
.
Zone
,
instanceName
)
var
err
error
select
{
case
err
=
<-
errCh
:
case
<-
time
.
After
(
config
.
stateTimeout
)
:
err
=
errors
.
New
(
"time out while waiting for instance to become running"
)
}
if
err
!=
nil
{
err
:=
fmt
.
Errorf
(
"Error
creating
instance: %s"
,
err
)
err
:=
fmt
.
Errorf
(
"Error
waiting for
instance: %s"
,
err
)
state
.
Put
(
"error"
,
err
)
ui
.
Error
(
err
.
Error
())
return
multistep
.
ActionHalt
}
ip
,
err
:=
client
.
GetNatIP
(
config
.
Zone
,
instanceName
)
ip
,
err
:=
driver
.
GetNatIP
(
config
.
Zone
,
instanceName
)
if
err
!=
nil
{
err
:=
fmt
.
Errorf
(
"Error retrieving instance nat ip address: %s"
,
err
)
state
.
Put
(
"error"
,
err
)
ui
.
Error
(
err
.
Error
())
return
multistep
.
ActionHalt
}
ui
.
Message
(
fmt
.
Sprintf
(
"IP: %s"
,
ip
))
state
.
Put
(
"instance_ip"
,
ip
)
return
multistep
.
ActionContinue
}
// Cleanup.
func
(
s
*
s
tepInstanceInfo
)
Cleanup
(
state
multistep
.
StateBag
)
{}
func
(
s
*
S
tepInstanceInfo
)
Cleanup
(
state
multistep
.
StateBag
)
{}
builder/googlecompute/step_instance_info_test.go
0 → 100644
View file @
a72d31fb
package
googlecompute
import
(
"errors"
"github.com/mitchellh/multistep"
"testing"
"time"
)
func
TestStepInstanceInfo_impl
(
t
*
testing
.
T
)
{
var
_
multistep
.
Step
=
new
(
StepInstanceInfo
)
}
func
TestStepInstanceInfo
(
t
*
testing
.
T
)
{
state
:=
testState
(
t
)
step
:=
new
(
StepInstanceInfo
)
defer
step
.
Cleanup
(
state
)
state
.
Put
(
"instance_name"
,
"foo"
)
config
:=
state
.
Get
(
"config"
)
.
(
*
Config
)
driver
:=
state
.
Get
(
"driver"
)
.
(
*
DriverMock
)
driver
.
GetNatIPResult
=
"1.2.3.4"
// 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
!=
"1.2.3.4"
{
t
.
Fatalf
(
"bad ip: %s"
,
ip
)
}
}
func
TestStepInstanceInfo_getNatIPError
(
t
*
testing
.
T
)
{
state
:=
testState
(
t
)
step
:=
new
(
StepInstanceInfo
)
defer
step
.
Cleanup
(
state
)
state
.
Put
(
"instance_name"
,
"foo"
)
driver
:=
state
.
Get
(
"driver"
)
.
(
*
DriverMock
)
driver
.
GetNatIPErr
=
errors
.
New
(
"error"
)
// run the step
if
action
:=
step
.
Run
(
state
);
action
!=
multistep
.
ActionHalt
{
t
.
Fatalf
(
"bad action: %#v"
,
action
)
}
// Verify state
if
_
,
ok
:=
state
.
GetOk
(
"error"
);
!
ok
{
t
.
Fatal
(
"should have error"
)
}
if
_
,
ok
:=
state
.
GetOk
(
"instance_ip"
);
ok
{
t
.
Fatal
(
"should NOT have instance IP"
)
}
}
func
TestStepInstanceInfo_waitError
(
t
*
testing
.
T
)
{
state
:=
testState
(
t
)
step
:=
new
(
StepInstanceInfo
)
defer
step
.
Cleanup
(
state
)
state
.
Put
(
"instance_name"
,
"foo"
)
errCh
:=
make
(
chan
error
,
1
)
errCh
<-
errors
.
New
(
"error"
)
driver
:=
state
.
Get
(
"driver"
)
.
(
*
DriverMock
)
driver
.
WaitForInstanceErrCh
=
errCh
// run the step
if
action
:=
step
.
Run
(
state
);
action
!=
multistep
.
ActionHalt
{
t
.
Fatalf
(
"bad action: %#v"
,
action
)
}
// Verify state
if
_
,
ok
:=
state
.
GetOk
(
"error"
);
!
ok
{
t
.
Fatal
(
"should have error"
)
}
if
_
,
ok
:=
state
.
GetOk
(
"instance_ip"
);
ok
{
t
.
Fatal
(
"should NOT have instance IP"
)
}
}
func
TestStepInstanceInfo_errorTimeout
(
t
*
testing
.
T
)
{
state
:=
testState
(
t
)
step
:=
new
(
StepInstanceInfo
)
defer
step
.
Cleanup
(
state
)
errCh
:=
make
(
chan
error
,
1
)
go
func
()
{
<-
time
.
After
(
10
*
time
.
Millisecond
)
errCh
<-
nil
}()
state
.
Put
(
"instance_name"
,
"foo"
)
config
:=
state
.
Get
(
"config"
)
.
(
*
Config
)
config
.
stateTimeout
=
1
*
time
.
Microsecond
driver
:=
state
.
Get
(
"driver"
)
.
(
*
DriverMock
)
driver
.
WaitForInstanceErrCh
=
errCh
// run the step
if
action
:=
step
.
Run
(
state
);
action
!=
multistep
.
ActionHalt
{
t
.
Fatalf
(
"bad action: %#v"
,
action
)
}
// Verify state
if
_
,
ok
:=
state
.
GetOk
(
"error"
);
!
ok
{
t
.
Fatal
(
"should have error"
)
}
if
_
,
ok
:=
state
.
GetOk
(
"instance_ip"
);
ok
{
t
.
Fatal
(
"should NOT have instance IP"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment