github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/post-processor/vagrant-cloud/post-processor.go (about) 1 // vagrant_cloud implements the packer.PostProcessor interface and adds a 2 // post-processor that uploads artifacts from the vagrant post-processor 3 // to Vagrant Cloud (vagrantcloud.com) 4 package vagrantcloud 5 6 import ( 7 "fmt" 8 "github.com/mitchellh/multistep" 9 "github.com/mitchellh/packer/common" 10 "github.com/mitchellh/packer/packer" 11 "log" 12 "strings" 13 ) 14 15 const VAGRANT_CLOUD_URL = "https://vagrantcloud.com/api/v1" 16 17 type Config struct { 18 common.PackerConfig `mapstructure:",squash"` 19 20 Tag string `mapstructure:"box_tag"` 21 Version string `mapstructure:"version"` 22 VersionDescription string `mapstructure:"version_description"` 23 NoRelease bool `mapstructure:"no_release"` 24 25 AccessToken string `mapstructure:"access_token"` 26 VagrantCloudUrl string `mapstructure:"vagrant_cloud_url"` 27 28 tpl *packer.ConfigTemplate 29 } 30 31 type PostProcessor struct { 32 config Config 33 client *VagrantCloudClient 34 runner multistep.Runner 35 } 36 37 func (p *PostProcessor) Configure(raws ...interface{}) error { 38 _, err := common.DecodeConfig(&p.config, raws...) 39 if err != nil { 40 return err 41 } 42 43 p.config.tpl, err = packer.NewConfigTemplate() 44 if err != nil { 45 return err 46 } 47 p.config.tpl.UserVars = p.config.PackerUserVars 48 49 // Default configuration 50 if p.config.VagrantCloudUrl == "" { 51 p.config.VagrantCloudUrl = VAGRANT_CLOUD_URL 52 } 53 54 // Accumulate any errors 55 errs := new(packer.MultiError) 56 57 // required configuration 58 templates := map[string]*string{ 59 "box_tag": &p.config.Tag, 60 "version": &p.config.Version, 61 "access_token": &p.config.AccessToken, 62 } 63 64 for key, ptr := range templates { 65 if *ptr == "" { 66 errs = packer.MultiErrorAppend( 67 errs, fmt.Errorf("%s must be set", key)) 68 } 69 } 70 71 // Template process 72 for key, ptr := range templates { 73 *ptr, err = p.config.tpl.Process(*ptr, nil) 74 if err != nil { 75 errs = packer.MultiErrorAppend( 76 errs, fmt.Errorf("Error processing %s: %s", key, err)) 77 } 78 } 79 80 if len(errs.Errors) > 0 { 81 return errs 82 } 83 84 return nil 85 } 86 87 func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { 88 // Only accepts input from the vagrant post-processor 89 if artifact.BuilderId() != "mitchellh.post-processor.vagrant" { 90 return nil, false, fmt.Errorf( 91 "Unknown artifact type, requires box from vagrant post-processor: %s", artifact.BuilderId()) 92 } 93 94 // We assume that there is only one .box file to upload 95 if !strings.HasSuffix(artifact.Files()[0], ".box") { 96 return nil, false, fmt.Errorf( 97 "Unknown files in artifact from vagrant post-processor: %s", artifact.Files()) 98 } 99 100 // create the HTTP client 101 p.client = VagrantCloudClient{}.New(p.config.VagrantCloudUrl, p.config.AccessToken) 102 103 // The name of the provider for vagrant cloud, and vagrant 104 providerName := providerFromBuilderName(artifact.Id()) 105 106 // Set up the state 107 state := new(multistep.BasicStateBag) 108 state.Put("config", p.config) 109 state.Put("client", p.client) 110 state.Put("artifact", artifact) 111 state.Put("artifactFilePath", artifact.Files()[0]) 112 state.Put("ui", ui) 113 state.Put("providerName", providerName) 114 115 // Build the steps 116 steps := []multistep.Step{ 117 new(stepVerifyBox), 118 new(stepCreateVersion), 119 new(stepCreateProvider), 120 new(stepPrepareUpload), 121 new(stepUpload), 122 new(stepVerifyUpload), 123 new(stepReleaseVersion), 124 } 125 126 // Run the steps 127 if p.config.PackerDebug { 128 p.runner = &multistep.DebugRunner{ 129 Steps: steps, 130 PauseFn: common.MultistepDebugFn(ui), 131 } 132 } else { 133 p.runner = &multistep.BasicRunner{Steps: steps} 134 } 135 136 p.runner.Run(state) 137 138 // If there was an error, return that 139 if rawErr, ok := state.GetOk("error"); ok { 140 return nil, false, rawErr.(error) 141 } 142 143 return NewArtifact(providerName, p.config.Tag), true, nil 144 } 145 146 // Runs a cleanup if the post processor fails to upload 147 func (p *PostProcessor) Cancel() { 148 if p.runner != nil { 149 log.Println("Cancelling the step runner...") 150 p.runner.Cancel() 151 } 152 } 153 154 // converts a packer builder name to the corresponding vagrant 155 // provider 156 func providerFromBuilderName(name string) string { 157 switch name { 158 case "aws": 159 return "aws" 160 case "digitalocean": 161 return "digitalocean" 162 case "virtualbox": 163 return "virtualbox" 164 case "vmware": 165 return "vmware_desktop" 166 case "parallels": 167 return "parallels" 168 default: 169 return name 170 } 171 }