The new flow: 1) Provision the instance 2) Tear down the instance, but keep the boot disk 3) Create an image from the disk 4) Tear down the disk The step to update gcloud is no longer needed, since gceimagebundle isn't used anymore. Fixes #1507 and addresses https://github.com/mitchellh/packer/issues/1447#issuecomment-61610235.
106 lines
2.4 KiB
Go
106 lines
2.4 KiB
Go
// The googlecompute package contains a packer.Builder implementation that
|
|
// builds images for Google Compute Engine.
|
|
package googlecompute
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/mitchellh/multistep"
|
|
"github.com/mitchellh/packer/common"
|
|
"github.com/mitchellh/packer/packer"
|
|
"log"
|
|
"time"
|
|
)
|
|
|
|
// 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{
|
|
&StepCreateSSHKey{
|
|
Debug: b.config.PackerDebug,
|
|
DebugKeyPath: fmt.Sprintf("gce_%s.pem", b.config.PackerBuildName),
|
|
},
|
|
&StepCreateInstance{
|
|
Debug: b.config.PackerDebug,
|
|
},
|
|
&StepInstanceInfo{
|
|
Debug: b.config.PackerDebug,
|
|
},
|
|
&common.StepConnectSSH{
|
|
SSHAddress: sshAddress,
|
|
SSHConfig: sshConfig,
|
|
SSHWaitTimeout: 5 * time.Minute,
|
|
},
|
|
new(common.StepProvision),
|
|
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_name"); !ok {
|
|
log.Println("Failed to find image_name in state. Bug?")
|
|
return nil, nil
|
|
}
|
|
|
|
artifact := &Artifact{
|
|
imageName: state.Get("image_name").(string),
|
|
driver: driver,
|
|
}
|
|
return artifact, nil
|
|
}
|
|
|
|
// Cancel.
|
|
func (b *Builder) Cancel() {
|
|
if b.runner != nil {
|
|
log.Println("Cancelling the step runner...")
|
|
b.runner.Cancel()
|
|
}
|
|
}
|