github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/post-processor/googlecompute-export/post-processor.go (about) 1 package googlecomputeexport 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "strings" 7 8 "github.com/mitchellh/multistep" 9 "github.com/mitchellh/packer/builder/googlecompute" 10 "github.com/mitchellh/packer/common" 11 "github.com/mitchellh/packer/helper/config" 12 "github.com/mitchellh/packer/packer" 13 "github.com/mitchellh/packer/template/interpolate" 14 ) 15 16 type Config struct { 17 common.PackerConfig `mapstructure:",squash"` 18 19 Paths []string `mapstructure:"paths"` 20 KeepOriginalImage bool `mapstructure:"keep_input_artifact"` 21 22 ctx interpolate.Context 23 } 24 25 type PostProcessor struct { 26 config Config 27 runner multistep.Runner 28 } 29 30 func (p *PostProcessor) Configure(raws ...interface{}) error { 31 err := config.Decode(&p.config, &config.DecodeOpts{ 32 Interpolate: true, 33 InterpolateContext: &p.config.ctx, 34 }, raws...) 35 if err != nil { 36 return err 37 } 38 39 return nil 40 } 41 42 func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { 43 ui.Say("Starting googlecompute-export...") 44 ui.Say(fmt.Sprintf("Exporting image to destinations: %v", p.config.Paths)) 45 if artifact.BuilderId() != googlecompute.BuilderId { 46 err := fmt.Errorf( 47 "Unknown artifact type: %s\nCan only export from Google Compute Engine builder artifacts.", 48 artifact.BuilderId()) 49 return nil, p.config.KeepOriginalImage, err 50 } 51 52 result := &Artifact{paths: p.config.Paths} 53 54 if len(p.config.Paths) > 0 { 55 accountKeyFilePath := artifact.State("AccountFilePath").(string) 56 imageName := artifact.State("ImageName").(string) 57 imageSizeGb := artifact.State("ImageSizeGb").(int64) 58 projectId := artifact.State("ProjectId").(string) 59 zone := artifact.State("BuildZone").(string) 60 61 // Set up instance configuration. 62 instanceName := fmt.Sprintf("%s-exporter", artifact.Id()) 63 metadata := map[string]string{ 64 "image_name": imageName, 65 "name": instanceName, 66 "paths": strings.Join(p.config.Paths, " "), 67 "startup-script": StartupScript, 68 "zone": zone, 69 } 70 exporterConfig := googlecompute.Config{ 71 InstanceName: instanceName, 72 SourceImageProjectId: "debian-cloud", 73 SourceImage: "debian-8-jessie-v20160629", 74 DiskName: instanceName, 75 DiskSizeGb: imageSizeGb + 10, 76 DiskType: "pd-standard", 77 Metadata: metadata, 78 MachineType: "n1-standard-4", 79 Zone: zone, 80 Network: "default", 81 RawStateTimeout: "5m", 82 Scopes: []string{ 83 "https://www.googleapis.com/auth/userinfo.email", 84 "https://www.googleapis.com/auth/compute", 85 "https://www.googleapis.com/auth/devstorage.full_control", 86 }, 87 } 88 exporterConfig.CalcTimeout() 89 90 // Set up credentials and GCE driver. 91 b, err := ioutil.ReadFile(accountKeyFilePath) 92 if err != nil { 93 err = fmt.Errorf("Error fetching account credentials: %s", err) 94 return nil, p.config.KeepOriginalImage, err 95 } 96 accountKeyContents := string(b) 97 googlecompute.ProcessAccountFile(&exporterConfig.Account, accountKeyContents) 98 driver, err := googlecompute.NewDriverGCE(ui, projectId, &exporterConfig.Account) 99 if err != nil { 100 return nil, p.config.KeepOriginalImage, err 101 } 102 103 // Set up the state. 104 state := new(multistep.BasicStateBag) 105 state.Put("config", &exporterConfig) 106 state.Put("driver", driver) 107 state.Put("ui", ui) 108 109 // Build the steps. 110 steps := []multistep.Step{ 111 &googlecompute.StepCreateSSHKey{ 112 Debug: p.config.PackerDebug, 113 DebugKeyPath: fmt.Sprintf("gce_%s.pem", p.config.PackerBuildName), 114 }, 115 &googlecompute.StepCreateInstance{ 116 Debug: p.config.PackerDebug, 117 }, 118 new(googlecompute.StepWaitStartupScript), 119 new(googlecompute.StepTeardownInstance), 120 } 121 122 // Run the steps. 123 if p.config.PackerDebug { 124 p.runner = &multistep.DebugRunner{ 125 Steps: steps, 126 PauseFn: common.MultistepDebugFn(ui), 127 } 128 } else { 129 p.runner = &multistep.BasicRunner{Steps: steps} 130 } 131 p.runner.Run(state) 132 } 133 134 return result, p.config.KeepOriginalImage, nil 135 }