mirror of
https://github.com/hashicorp/packer.git
synced 2026-03-14 14:42:24 -04:00
- Startup scripts can be provided through the instance creation metadata field 'startup-script'. - Script log can be copied to a GCS location by setting the metadata field 'startup-script-log-dest'. Added Retry method to googlecompute package. Added GetSerialPortOutput to googlecompute Drivers. Added StepWaitInstanceStartup (and associated test) which waits for an instance startup-script to finish. Changed the instance service account to use the same service account as the one provided in the Packer config template. It was the project default service account. Tested googlecompute package with 'go test' and also performed builds with a startup script and without a startup script.
108 lines
2.5 KiB
Go
108 lines
2.5 KiB
Go
// The googlecompute package contains a packer.Builder implementation that
|
|
// builds images for Google Compute Engine.
|
|
package googlecompute
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/mitchellh/multistep"
|
|
"github.com/mitchellh/packer/common"
|
|
"github.com/mitchellh/packer/helper/communicator"
|
|
"github.com/mitchellh/packer/packer"
|
|
)
|
|
|
|
// The unique ID for this builder.
|
|
const BuilderId = "packer.googlecompute"
|
|
|
|
// Builder represents a Packer Builder.
|
|
type Builder struct {
|
|
config *Config
|
|
runner multistep.Runner
|
|
}
|
|
|
|
// Prepare processes the build configuration parameters.
|
|
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
|
|
c, warnings, errs := NewConfig(raws...)
|
|
if errs != nil {
|
|
return warnings, errs
|
|
}
|
|
b.config = c
|
|
|
|
return warnings, nil
|
|
}
|
|
|
|
// Run executes a googlecompute Packer build and returns a packer.Artifact
|
|
// representing a GCE machine image.
|
|
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
|
|
driver, err := NewDriverGCE(
|
|
ui, b.config.ProjectId, &b.config.account)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Set up the state.
|
|
state := new(multistep.BasicStateBag)
|
|
state.Put("config", b.config)
|
|
state.Put("driver", driver)
|
|
state.Put("hook", hook)
|
|
state.Put("ui", ui)
|
|
|
|
// Build the steps.
|
|
steps := []multistep.Step{
|
|
new(StepCheckExistingImage),
|
|
&StepCreateSSHKey{
|
|
Debug: b.config.PackerDebug,
|
|
DebugKeyPath: fmt.Sprintf("gce_%s.pem", b.config.PackerBuildName),
|
|
},
|
|
&StepCreateInstance{
|
|
Debug: b.config.PackerDebug,
|
|
},
|
|
&StepInstanceInfo{
|
|
Debug: b.config.PackerDebug,
|
|
},
|
|
&communicator.StepConnect{
|
|
Config: &b.config.Comm,
|
|
Host: commHost,
|
|
SSHConfig: sshConfig,
|
|
},
|
|
new(common.StepProvision),
|
|
new(StepWaitInstanceStartup),
|
|
new(StepTeardownInstance),
|
|
new(StepCreateImage),
|
|
}
|
|
|
|
// Run the steps.
|
|
if b.config.PackerDebug {
|
|
b.runner = &multistep.DebugRunner{
|
|
Steps: steps,
|
|
PauseFn: common.MultistepDebugFn(ui),
|
|
}
|
|
} else {
|
|
b.runner = &multistep.BasicRunner{Steps: steps}
|
|
}
|
|
b.runner.Run(state)
|
|
|
|
// Report any errors.
|
|
if rawErr, ok := state.GetOk("error"); ok {
|
|
return nil, rawErr.(error)
|
|
}
|
|
if _, ok := state.GetOk("image"); !ok {
|
|
log.Println("Failed to find image in state. Bug?")
|
|
return nil, nil
|
|
}
|
|
|
|
artifact := &Artifact{
|
|
image: state.Get("image").(Image),
|
|
driver: driver,
|
|
}
|
|
return artifact, nil
|
|
}
|
|
|
|
// Cancel.
|
|
func (b *Builder) Cancel() {
|
|
if b.runner != nil {
|
|
log.Println("Cancelling the step runner...")
|
|
b.runner.Cancel()
|
|
}
|
|
}
|