Commit 7816fc0b authored by Tristan Helmich's avatar Tristan Helmich

vagrantcloud post-processor selfhosted box feature

parent e39f555f
// vagrant_cloud implements the packer.PostProcessor interface and adds a // vagrant_cloud implements the packer.PostProcessor interface and adds a
// post-processor that uploads artifacts from the vagrant post-processor // post-processor that uploads artifacts from the vagrant post-processor
// to Vagrant Cloud (vagrantcloud.com) // to Vagrant Cloud (vagrantcloud.com) or manages self hosted boxes on the
// Vagrant Cloud
package vagrantcloud package vagrantcloud
import ( import (
...@@ -25,9 +26,16 @@ type Config struct { ...@@ -25,9 +26,16 @@ type Config struct {
AccessToken string `mapstructure:"access_token"` AccessToken string `mapstructure:"access_token"`
VagrantCloudUrl string `mapstructure:"vagrant_cloud_url"` VagrantCloudUrl string `mapstructure:"vagrant_cloud_url"`
BoxDownloadUrl string `mapstructure:"box_download_url"`
tpl *packer.ConfigTemplate tpl *packer.ConfigTemplate
} }
type boxDownloadUrlTemplate struct {
ArtifactId string
Provider string
}
type PostProcessor struct { type PostProcessor struct {
config Config config Config
client *VagrantCloudClient client *VagrantCloudClient
...@@ -103,6 +111,14 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac ...@@ -103,6 +111,14 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
// The name of the provider for vagrant cloud, and vagrant // The name of the provider for vagrant cloud, and vagrant
providerName := providerFromBuilderName(artifact.Id()) providerName := providerFromBuilderName(artifact.Id())
boxDownloadUrl, err := p.config.tpl.Process(p.config.BoxDownloadUrl, &boxDownloadUrlTemplate {
ArtifactId: artifact.Id(),
Provider: providerName,
})
if err != nil {
return nil, false, fmt.Errorf("Error processing box_download_url: %s", err)
}
// Set up the state // Set up the state
state := new(multistep.BasicStateBag) state := new(multistep.BasicStateBag)
state.Put("config", p.config) state.Put("config", p.config)
...@@ -111,16 +127,27 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac ...@@ -111,16 +127,27 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
state.Put("artifactFilePath", artifact.Files()[0]) state.Put("artifactFilePath", artifact.Files()[0])
state.Put("ui", ui) state.Put("ui", ui)
state.Put("providerName", providerName) state.Put("providerName", providerName)
state.Put("boxDownloadUrl", boxDownloadUrl)
// Build the steps // Build the steps
steps := []multistep.Step{ steps := []multistep.Step{}
new(stepVerifyBox), if p.config.BoxDownloadUrl == "" {
new(stepCreateVersion), steps = []multistep.Step{
new(stepCreateProvider), new(stepVerifyBox),
new(stepPrepareUpload), new(stepCreateVersion),
new(stepUpload), new(stepCreateProvider),
new(stepVerifyUpload), new(stepPrepareUpload),
new(stepReleaseVersion), new(stepUpload),
new(stepVerifyUpload),
new(stepReleaseVersion),
}
} else {
steps = []multistep.Step{
new(stepVerifyBox),
new(stepCreateVersion),
new(stepCreateProvider),
new(stepReleaseVersion),
}
} }
// Run the steps // Run the steps
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
type Provider struct { type Provider struct {
Name string `json:"name"` Name string `json:"name"`
Url string `json:"url,omitempty"`
HostedToken string `json:"hosted_token,omitempty"` HostedToken string `json:"hosted_token,omitempty"`
UploadUrl string `json:"upload_url,omitempty"` UploadUrl string `json:"upload_url,omitempty"`
} }
...@@ -22,11 +23,16 @@ func (s *stepCreateProvider) Run(state multistep.StateBag) multistep.StepAction ...@@ -22,11 +23,16 @@ func (s *stepCreateProvider) Run(state multistep.StateBag) multistep.StepAction
box := state.Get("box").(*Box) box := state.Get("box").(*Box)
version := state.Get("version").(*Version) version := state.Get("version").(*Version)
providerName := state.Get("providerName").(string) providerName := state.Get("providerName").(string)
downloadUrl := state.Get("boxDownloadUrl").(string)
path := fmt.Sprintf("box/%s/version/%v/providers", box.Tag, version.Number) path := fmt.Sprintf("box/%s/version/%v/providers", box.Tag, version.Number)
provider := &Provider{Name: providerName} provider := &Provider{Name: providerName}
if downloadUrl != "" {
provider.Url = downloadUrl
}
// Wrap the provider in a provider object for the API // Wrap the provider in a provider object for the API
wrapper := make(map[string]interface{}) wrapper := make(map[string]interface{})
wrapper["provider"] = provider wrapper["provider"] = provider
......
...@@ -2,6 +2,7 @@ package vagrantcloud ...@@ -2,6 +2,7 @@ package vagrantcloud
import ( import (
"fmt" "fmt"
"strings"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
) )
...@@ -30,6 +31,10 @@ func (s *stepReleaseVersion) Run(state multistep.StateBag) multistep.StepAction ...@@ -30,6 +31,10 @@ func (s *stepReleaseVersion) Run(state multistep.StateBag) multistep.StepAction
if err != nil || (resp.StatusCode != 200) { if err != nil || (resp.StatusCode != 200) {
cloudErrors := &VagrantCloudErrors{} cloudErrors := &VagrantCloudErrors{}
err = decodeBody(resp, cloudErrors) err = decodeBody(resp, cloudErrors)
if strings.Contains(cloudErrors.FormatErrors(), "already been released") {
ui.Message("Not releasing version, already released")
return multistep.ActionContinue
}
state.Put("error", fmt.Errorf("Error releasing version: %s", cloudErrors.FormatErrors())) state.Put("error", fmt.Errorf("Error releasing version: %s", cloudErrors.FormatErrors()))
return multistep.ActionHalt return multistep.ActionHalt
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment