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  }