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

     1  package triton
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/hashicorp/go-multierror"
     7  	"github.com/hashicorp/packer/common"
     8  	"github.com/hashicorp/packer/helper/communicator"
     9  	"github.com/hashicorp/packer/helper/config"
    10  	"github.com/hashicorp/packer/helper/multistep"
    11  	"github.com/hashicorp/packer/packer"
    12  )
    13  
    14  const (
    15  	BuilderId = "joyent.triton"
    16  )
    17  
    18  type Builder struct {
    19  	config Config
    20  	runner multistep.Runner
    21  }
    22  
    23  func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
    24  	errs := &multierror.Error{}
    25  
    26  	err := config.Decode(&b.config, &config.DecodeOpts{
    27  		Interpolate:        true,
    28  		InterpolateContext: &b.config.ctx,
    29  	}, raws...)
    30  	if err != nil {
    31  		errs = multierror.Append(errs, err)
    32  	}
    33  
    34  	errs = multierror.Append(errs, b.config.AccessConfig.Prepare(&b.config.ctx)...)
    35  	errs = multierror.Append(errs, b.config.SourceMachineConfig.Prepare(&b.config.ctx)...)
    36  	errs = multierror.Append(errs, b.config.Comm.Prepare(&b.config.ctx)...)
    37  	errs = multierror.Append(errs, b.config.TargetImageConfig.Prepare(&b.config.ctx)...)
    38  
    39  	// If we are using an SSH agent to sign requests, and no private key has been
    40  	// specified for SSH, use the agent for connecting for provisioning.
    41  	if b.config.AccessConfig.KeyMaterial == "" && b.config.Comm.SSHPrivateKeyFile == "" {
    42  		b.config.Comm.SSHAgentAuth = true
    43  	}
    44  
    45  	return nil, errs.ErrorOrNil()
    46  }
    47  
    48  func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
    49  	config := b.config
    50  
    51  	driver, err := NewDriverTriton(ui, config)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	state := new(multistep.BasicStateBag)
    57  	state.Put("config", &b.config)
    58  	state.Put("debug", b.config.PackerDebug)
    59  	state.Put("driver", driver)
    60  	state.Put("hook", hook)
    61  	state.Put("ui", ui)
    62  
    63  	steps := []multistep.Step{
    64  		&StepCreateSourceMachine{},
    65  		&communicator.StepConnect{
    66  			Config:    &config.Comm,
    67  			Host:      commHost,
    68  			SSHConfig: b.config.Comm.SSHConfigFunc(),
    69  		},
    70  		&common.StepProvision{},
    71  		&common.StepCleanupTempKeys{
    72  			Comm: &config.Comm,
    73  		},
    74  		&StepStopMachine{},
    75  		&StepCreateImageFromMachine{},
    76  		&StepDeleteMachine{},
    77  	}
    78  
    79  	b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state)
    80  	b.runner.Run(state)
    81  
    82  	// If there was an error, return that
    83  	if rawErr, ok := state.GetOk("error"); ok {
    84  		return nil, rawErr.(error)
    85  	}
    86  
    87  	// If there is no image, just return
    88  	if _, ok := state.GetOk("image"); !ok {
    89  		return nil, nil
    90  	}
    91  
    92  	artifact := &Artifact{
    93  		ImageID:        state.Get("image").(string),
    94  		BuilderIDValue: BuilderId,
    95  		Driver:         driver,
    96  	}
    97  
    98  	return artifact, nil
    99  }
   100  
   101  // Cancel cancels a possibly running Builder. This should block until
   102  // the builder actually cancels and cleans up after itself.
   103  func (b *Builder) Cancel() {
   104  	if b.runner != nil {
   105  		log.Println("Cancelling the step runner...")
   106  		b.runner.Cancel()
   107  	}
   108  }