github.phpd.cn/hashicorp/packer@v1.3.2/builder/googlecompute/builder.go (about)

     1  // The googlecompute package contains a packer.Builder implementation that
     2  // builds images for Google Compute Engine.
     3  package googlecompute
     4  
     5  import (
     6  	"fmt"
     7  	"log"
     8  
     9  	"github.com/hashicorp/packer/common"
    10  	"github.com/hashicorp/packer/helper/communicator"
    11  	"github.com/hashicorp/packer/helper/multistep"
    12  	"github.com/hashicorp/packer/packer"
    13  )
    14  
    15  // The unique ID for this builder.
    16  const BuilderId = "packer.googlecompute"
    17  
    18  // Builder represents a Packer Builder.
    19  type Builder struct {
    20  	config *Config
    21  	runner multistep.Runner
    22  }
    23  
    24  // Prepare processes the build configuration parameters.
    25  func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
    26  	c, warnings, errs := NewConfig(raws...)
    27  	if errs != nil {
    28  		return warnings, errs
    29  	}
    30  	b.config = c
    31  	return warnings, nil
    32  }
    33  
    34  // Run executes a googlecompute Packer build and returns a packer.Artifact
    35  // representing a GCE machine image.
    36  func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
    37  	driver, err := NewDriverGCE(
    38  		ui, b.config.ProjectId, &b.config.Account)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	// Set up the state.
    44  	state := new(multistep.BasicStateBag)
    45  	state.Put("config", b.config)
    46  	state.Put("driver", driver)
    47  	state.Put("hook", hook)
    48  	state.Put("ui", ui)
    49  
    50  	// Build the steps.
    51  	steps := []multistep.Step{
    52  		new(StepCheckExistingImage),
    53  		&StepCreateSSHKey{
    54  			Debug:        b.config.PackerDebug,
    55  			DebugKeyPath: fmt.Sprintf("gce_%s.pem", b.config.PackerBuildName),
    56  		},
    57  		&StepCreateInstance{
    58  			Debug: b.config.PackerDebug,
    59  		},
    60  		&StepCreateWindowsPassword{
    61  			Debug:        b.config.PackerDebug,
    62  			DebugKeyPath: fmt.Sprintf("gce_windows_%s.pem", b.config.PackerBuildName),
    63  		},
    64  		&StepInstanceInfo{
    65  			Debug: b.config.PackerDebug,
    66  		},
    67  		&communicator.StepConnect{
    68  			Config:      &b.config.Comm,
    69  			Host:        commHost,
    70  			SSHConfig:   b.config.Comm.SSHConfigFunc(),
    71  			WinRMConfig: winrmConfig,
    72  		},
    73  		new(common.StepProvision),
    74  		&common.StepCleanupTempKeys{
    75  			Comm: &b.config.Comm,
    76  		},
    77  	}
    78  	if _, exists := b.config.Metadata[StartupScriptKey]; exists || b.config.StartupScriptFile != "" {
    79  		steps = append(steps, new(StepWaitStartupScript))
    80  	}
    81  	steps = append(steps, new(StepTeardownInstance), new(StepCreateImage))
    82  
    83  	// Run the steps.
    84  	b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
    85  	b.runner.Run(state)
    86  
    87  	// Report any errors.
    88  	if rawErr, ok := state.GetOk("error"); ok {
    89  		return nil, rawErr.(error)
    90  	}
    91  	if _, ok := state.GetOk("image"); !ok {
    92  		log.Println("Failed to find image in state. Bug?")
    93  		return nil, nil
    94  	}
    95  
    96  	artifact := &Artifact{
    97  		image:  state.Get("image").(*Image),
    98  		driver: driver,
    99  		config: b.config,
   100  	}
   101  	return artifact, nil
   102  }
   103  
   104  // Cancel.
   105  func (b *Builder) Cancel() {
   106  	if b.runner != nil {
   107  		log.Println("Cancelling the step runner...")
   108  		b.runner.Cancel()
   109  	}
   110  }