github.com/sneal/packer@v0.5.2/builder/openstack/builder.go (about)

     1  // The openstack package contains a packer.Builder implementation that
     2  // builds Images for openstack.
     3  
     4  package openstack
     5  
     6  import (
     7  	"fmt"
     8  	"github.com/mitchellh/multistep"
     9  	"github.com/mitchellh/packer/common"
    10  	"github.com/mitchellh/packer/packer"
    11  	"github.com/rackspace/gophercloud"
    12  	"log"
    13  )
    14  
    15  // The unique ID for this builder
    16  const BuilderId = "mitchellh.openstack"
    17  
    18  type config struct {
    19  	common.PackerConfig `mapstructure:",squash"`
    20  	AccessConfig        `mapstructure:",squash"`
    21  	ImageConfig         `mapstructure:",squash"`
    22  	RunConfig           `mapstructure:",squash"`
    23  
    24  	tpl *packer.ConfigTemplate
    25  }
    26  
    27  type Builder struct {
    28  	config config
    29  	runner multistep.Runner
    30  }
    31  
    32  func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
    33  	md, err := common.DecodeConfig(&b.config, raws...)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	b.config.tpl, err = packer.NewConfigTemplate()
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	b.config.tpl.UserVars = b.config.PackerUserVars
    43  
    44  	// Accumulate any errors
    45  	errs := common.CheckUnusedConfig(md)
    46  	errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(b.config.tpl)...)
    47  	errs = packer.MultiErrorAppend(errs, b.config.ImageConfig.Prepare(b.config.tpl)...)
    48  	errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
    49  
    50  	if errs != nil && len(errs.Errors) > 0 {
    51  		return nil, errs
    52  	}
    53  
    54  	log.Println(common.ScrubConfig(b.config, b.config.Password))
    55  	return nil, nil
    56  }
    57  
    58  func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
    59  	auth, err := b.config.AccessConfig.Auth()
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	api := &gophercloud.ApiCriteria{
    64  		Name:      "cloudServersOpenStack",
    65  		Region:    b.config.AccessConfig.Region(),
    66  		VersionId: "2",
    67  		UrlChoice: gophercloud.PublicURL,
    68  	}
    69  	csp, err := gophercloud.ServersApi(auth, *api)
    70  	if err != nil {
    71  		log.Printf("Region: %s", b.config.AccessConfig.Region())
    72  		return nil, err
    73  	}
    74  
    75  	// Setup the state bag and initial state for the steps
    76  	state := new(multistep.BasicStateBag)
    77  	state.Put("config", b.config)
    78  	state.Put("csp", csp)
    79  	state.Put("hook", hook)
    80  	state.Put("ui", ui)
    81  
    82  	// Build the steps
    83  	steps := []multistep.Step{
    84  		&StepKeyPair{
    85  			Debug:        b.config.PackerDebug,
    86  			DebugKeyPath: fmt.Sprintf("os_%s.pem", b.config.PackerBuildName),
    87  		},
    88  		&StepRunSourceServer{
    89  			Name:        b.config.ImageName,
    90  			Flavor:      b.config.Flavor,
    91  			SourceImage: b.config.SourceImage,
    92  		},
    93  		&common.StepConnectSSH{
    94  			SSHAddress:     SSHAddress(csp, b.config.SSHPort),
    95  			SSHConfig:      SSHConfig(b.config.SSHUsername),
    96  			SSHWaitTimeout: b.config.SSHTimeout(),
    97  		},
    98  		&common.StepProvision{},
    99  		&stepCreateImage{},
   100  	}
   101  
   102  	// Run!
   103  	if b.config.PackerDebug {
   104  		b.runner = &multistep.DebugRunner{
   105  			Steps:   steps,
   106  			PauseFn: common.MultistepDebugFn(ui),
   107  		}
   108  	} else {
   109  		b.runner = &multistep.BasicRunner{Steps: steps}
   110  	}
   111  
   112  	b.runner.Run(state)
   113  
   114  	// If there was an error, return that
   115  	if rawErr, ok := state.GetOk("error"); ok {
   116  		return nil, rawErr.(error)
   117  	}
   118  
   119  	// If there are no images, then just return
   120  	if _, ok := state.GetOk("image"); !ok {
   121  		return nil, nil
   122  	}
   123  
   124  	// Build the artifact and return it
   125  	artifact := &Artifact{
   126  		ImageId:        state.Get("image").(string),
   127  		BuilderIdValue: BuilderId,
   128  		Conn:           csp,
   129  	}
   130  
   131  	return artifact, nil
   132  }
   133  
   134  func (b *Builder) Cancel() {
   135  	if b.runner != nil {
   136  		log.Println("Cancelling the step runner...")
   137  		b.runner.Cancel()
   138  	}
   139  }