131 lines
3.7 KiB
Go
131 lines
3.7 KiB
Go
|
package googlecomputeexport
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/mitchellh/multistep"
|
||
|
"github.com/mitchellh/packer/builder/googlecompute"
|
||
|
"github.com/mitchellh/packer/common"
|
||
|
"github.com/mitchellh/packer/helper/config"
|
||
|
"github.com/mitchellh/packer/packer"
|
||
|
"github.com/mitchellh/packer/template/interpolate"
|
||
|
)
|
||
|
|
||
|
type Config struct {
|
||
|
common.PackerConfig `mapstructure:",squash"`
|
||
|
|
||
|
Paths []string `mapstructure:"paths"`
|
||
|
KeepOriginalImage bool `mapstructure:"keep_input_artifact"`
|
||
|
|
||
|
ctx interpolate.Context
|
||
|
}
|
||
|
|
||
|
type PostProcessor struct {
|
||
|
config Config
|
||
|
runner multistep.Runner
|
||
|
}
|
||
|
|
||
|
func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||
|
err := config.Decode(&p.config, &config.DecodeOpts{
|
||
|
Interpolate: true,
|
||
|
InterpolateContext: &p.config.ctx,
|
||
|
}, raws...)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
|
||
|
ui.Say("Starting googlecompute-export...")
|
||
|
ui.Say(fmt.Sprintf("Exporting image to destinations: %v", p.config.Paths))
|
||
|
if artifact.BuilderId() != googlecompute.BuilderId {
|
||
|
err := fmt.Errorf(
|
||
|
"Unknown artifact type: %s\nCan only export from Google Compute Engine builder artifacts.",
|
||
|
artifact.BuilderId())
|
||
|
return nil, p.config.KeepOriginalImage, err
|
||
|
}
|
||
|
|
||
|
result := &Artifact{paths: p.config.Paths}
|
||
|
|
||
|
if len(p.config.Paths) > 0 {
|
||
|
accountKeyFilePath := artifact.State("AccountFilePath").(string)
|
||
|
imageName := artifact.State("ImageName").(string)
|
||
|
imageSizeGb := artifact.State("ImageSizeGb").(int64)
|
||
|
projectId := artifact.State("ProjectId").(string)
|
||
|
zone := artifact.State("BuildZone").(string)
|
||
|
|
||
|
// Set up instance configuration.
|
||
|
instanceName := fmt.Sprintf("%s-exporter", artifact.Id())
|
||
|
metadata := map[string]string{
|
||
|
"image_name": imageName,
|
||
|
"name": instanceName,
|
||
|
"paths": strings.Join(p.config.Paths, " "),
|
||
|
"startup-script": StartupScript,
|
||
|
"zone": zone,
|
||
|
}
|
||
|
exporterConfig := googlecompute.Config{
|
||
|
InstanceName: instanceName,
|
||
|
SourceImageProjectId: "debian-cloud",
|
||
|
SourceImage: "debian-8-jessie-v20160629",
|
||
|
DiskName: instanceName,
|
||
|
DiskSizeGb: imageSizeGb + 10,
|
||
|
DiskType: "pd-standard",
|
||
|
Metadata: metadata,
|
||
|
MachineType: "n1-standard-4",
|
||
|
Zone: zone,
|
||
|
Network: "default",
|
||
|
RawStateTimeout: "5m",
|
||
|
}
|
||
|
exporterConfig.CalcTimeout()
|
||
|
|
||
|
// Set up credentials and GCE driver.
|
||
|
b, err := ioutil.ReadFile(accountKeyFilePath)
|
||
|
if err != nil {
|
||
|
err = fmt.Errorf("Error fetching account credentials: %s", err)
|
||
|
return nil, p.config.KeepOriginalImage, err
|
||
|
}
|
||
|
accountKeyContents := string(b)
|
||
|
googlecompute.ProcessAccountFile(&exporterConfig.Account, accountKeyContents)
|
||
|
driver, err := googlecompute.NewDriverGCE(ui, projectId, &exporterConfig.Account)
|
||
|
if err != nil {
|
||
|
return nil, p.config.KeepOriginalImage, err
|
||
|
}
|
||
|
|
||
|
// Set up the state.
|
||
|
state := new(multistep.BasicStateBag)
|
||
|
state.Put("config", &exporterConfig)
|
||
|
state.Put("driver", driver)
|
||
|
state.Put("ui", ui)
|
||
|
|
||
|
// Build the steps.
|
||
|
steps := []multistep.Step{
|
||
|
&googlecompute.StepCreateSSHKey{
|
||
|
Debug: p.config.PackerDebug,
|
||
|
DebugKeyPath: fmt.Sprintf("gce_%s.pem", p.config.PackerBuildName),
|
||
|
},
|
||
|
&googlecompute.StepCreateInstance{
|
||
|
Debug: p.config.PackerDebug,
|
||
|
},
|
||
|
new(googlecompute.StepWaitInstanceStartup),
|
||
|
new(googlecompute.StepTeardownInstance),
|
||
|
}
|
||
|
|
||
|
// Run the steps.
|
||
|
if p.config.PackerDebug {
|
||
|
p.runner = &multistep.DebugRunner{
|
||
|
Steps: steps,
|
||
|
PauseFn: common.MultistepDebugFn(ui),
|
||
|
}
|
||
|
} else {
|
||
|
p.runner = &multistep.BasicRunner{Steps: steps}
|
||
|
}
|
||
|
p.runner.Run(state)
|
||
|
}
|
||
|
|
||
|
return result, p.config.KeepOriginalImage, nil
|
||
|
}
|