Merge pull request #5008 from hashicorp/pp-vc-u1
post-processor/vagrant-cloud: try upload once
This commit is contained in:
commit
4b4c2e4a59
|
@ -105,7 +105,7 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
|
|||
ReportTags(ui, snapshotTags)
|
||||
|
||||
// Retry creating tags for about 2.5 minutes
|
||||
err = retry.Retry(0.2, 30, 11, func() (bool, error) {
|
||||
err = retry.Retry(0.2, 30, 11, func(_ uint) (bool, error) {
|
||||
// Tag images and snapshots
|
||||
_, err := regionconn.CreateTags(&ec2.CreateTagsInput{
|
||||
Resources: resourceIds,
|
||||
|
|
|
@ -294,7 +294,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||
ReportTags(ui, ec2Tags)
|
||||
|
||||
// Retry creating tags for about 2.5 minutes
|
||||
err = retry.Retry(0.2, 30, 11, func() (bool, error) {
|
||||
err = retry.Retry(0.2, 30, 11, func(_ uint) (bool, error) {
|
||||
_, err := ec2conn.CreateTags(&ec2.CreateTagsInput{
|
||||
Tags: ec2Tags,
|
||||
Resources: []*string{instance.InstanceId},
|
||||
|
|
|
@ -582,7 +582,7 @@ type stateRefreshFunc func() (string, error)
|
|||
// waitForState will spin in a loop forever waiting for state to
|
||||
// reach a certain target.
|
||||
func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) error {
|
||||
err := common.Retry(2, 2, 0, func() (bool, error) {
|
||||
err := common.Retry(2, 2, 0, func(_ uint) (bool, error) {
|
||||
state, err := refresh()
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
|
|
@ -22,7 +22,7 @@ func (s *StepWaitStartupScript) Run(state multistep.StateBag) multistep.StepActi
|
|||
ui.Say("Waiting for any running startup script to finish...")
|
||||
|
||||
// Keep checking the serial port output to see if the startup script is done.
|
||||
err := common.Retry(10, 60, 0, func() (bool, error) {
|
||||
err := common.Retry(10, 60, 0, func(_ uint) (bool, error) {
|
||||
status, err := driver.GetInstanceMetadata(config.Zone,
|
||||
instanceName, StartupScriptStatusKey)
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ func (s *StepRemoveDevices) Run(state multistep.StateBag) multistep.StepAction {
|
|||
var vboxErr error
|
||||
// Retry for 10 minutes to remove the floppy controller.
|
||||
log.Printf("Trying for 10 minutes to remove floppy controller.")
|
||||
err := common.Retry(15, 15, 40, func() (bool, error) {
|
||||
err := common.Retry(15, 15, 40, func(_ uint) (bool, error) {
|
||||
// Don't forget to remove the floppy controller as well
|
||||
command = []string{
|
||||
"storagectl", vmName,
|
||||
|
|
|
@ -8,7 +8,11 @@ import (
|
|||
|
||||
var RetryExhaustedError error = fmt.Errorf("Function never succeeded in Retry")
|
||||
|
||||
type RetryableFunc func() (bool, error)
|
||||
// RetryableFunc performs an action and returns a bool indicating whether the
|
||||
// function is done, or if it should keep retrying, and an erorr which will
|
||||
// abort the retry and be returned by the Retry function. The 0-indexed attempt
|
||||
// is passed with each call.
|
||||
type RetryableFunc func(uint) (bool, error)
|
||||
|
||||
// Retry retries a function up to numTries times with exponential backoff.
|
||||
// If numTries == 0, retry indefinitely. If interval == 0, Retry will not delay retrying and there will be
|
||||
|
@ -27,7 +31,7 @@ func Retry(initialInterval float64, maxInterval float64, numTries uint, function
|
|||
done := false
|
||||
interval := initialInterval
|
||||
for i := uint(0); !done && (numTries == 0 || i < numTries); i++ {
|
||||
done, err = function()
|
||||
done, err = function(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
func TestRetry(t *testing.T) {
|
||||
numTries := uint(0)
|
||||
// Test that a passing function only gets called once.
|
||||
err := Retry(0, 0, 0, func() (bool, error) {
|
||||
err := Retry(0, 0, 0, func(i uint) (bool, error) {
|
||||
numTries++
|
||||
return true, nil
|
||||
})
|
||||
|
@ -22,7 +22,7 @@ func TestRetry(t *testing.T) {
|
|||
// Test that a failing function gets retried (once in this example).
|
||||
numTries = 0
|
||||
results := []bool{false, true}
|
||||
err = Retry(0, 0, 0, func() (bool, error) {
|
||||
err = Retry(0, 0, 0, func(i uint) (bool, error) {
|
||||
result := results[numTries]
|
||||
numTries++
|
||||
return result, nil
|
||||
|
@ -37,7 +37,7 @@ func TestRetry(t *testing.T) {
|
|||
// Test that a function error gets returned, and the function does not get called again.
|
||||
numTries = 0
|
||||
funcErr := fmt.Errorf("This function had an error!")
|
||||
err = Retry(0, 0, 0, func() (bool, error) {
|
||||
err = Retry(0, 0, 0, func(i uint) (bool, error) {
|
||||
numTries++
|
||||
return false, funcErr
|
||||
})
|
||||
|
@ -51,7 +51,7 @@ func TestRetry(t *testing.T) {
|
|||
// Test when a function exhausts its retries.
|
||||
numTries = 0
|
||||
expectedTries := uint(3)
|
||||
err = Retry(0, 0, expectedTries, func() (bool, error) {
|
||||
err = Retry(0, 0, expectedTries, func(i uint) (bool, error) {
|
||||
numTries++
|
||||
return false, nil
|
||||
})
|
||||
|
|
|
@ -152,7 +152,6 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
|||
new(stepCreateProvider),
|
||||
new(stepPrepareUpload),
|
||||
new(stepUpload),
|
||||
new(stepVerifyUpload),
|
||||
new(stepReleaseVersion),
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -2,12 +2,12 @@ package vagrantcloud
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type Upload struct {
|
||||
Token string `json:"token"`
|
||||
UploadPath string `json:"upload_path"`
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,6 @@ func (s *stepPrepareUpload) Run(state multistep.StateBag) multistep.StepAction {
|
|||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Message(fmt.Sprintf("Box upload prepared with token %s", upload.Token))
|
||||
|
||||
// Save the upload details to the state
|
||||
state.Put("upload", upload)
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@ package vagrantcloud
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
@ -23,34 +24,27 @@ func (s *stepUpload) Run(state multistep.StateBag) multistep.StepAction {
|
|||
"Depending on your internet connection and the size of the box,\n" +
|
||||
"this may take some time")
|
||||
|
||||
var finalErr error
|
||||
for i := 0; i < 3; i++ {
|
||||
if i > 0 {
|
||||
ui.Message(fmt.Sprintf("Uploading box, attempt %d", i+1))
|
||||
}
|
||||
err := common.Retry(10, 10, 3, func(i uint) (bool, error) {
|
||||
ui.Message(fmt.Sprintf("Uploading box, attempt %d", i+1))
|
||||
|
||||
resp, err := client.Upload(artifactFilePath, url)
|
||||
if err != nil {
|
||||
finalErr = err
|
||||
ui.Message(fmt.Sprintf(
|
||||
"Error uploading box! Will retry in 10 seconds. Error: %s", err))
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
return false, nil
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
finalErr = fmt.Errorf("bad HTTP status: %d", resp.StatusCode)
|
||||
log.Printf("bad HTTP status: %d", resp.StatusCode)
|
||||
ui.Message(fmt.Sprintf(
|
||||
"Error uploading box! Will retry in 10 seconds. Status: %d",
|
||||
resp.StatusCode))
|
||||
time.Sleep(10 * time.Second)
|
||||
continue
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
finalErr = nil
|
||||
}
|
||||
|
||||
if finalErr != nil {
|
||||
state.Put("error", finalErr)
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
package vagrantcloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
)
|
||||
|
||||
type stepVerifyUpload struct {
|
||||
}
|
||||
|
||||
func (s *stepVerifyUpload) Run(state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*VagrantCloudClient)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
box := state.Get("box").(*Box)
|
||||
version := state.Get("version").(*Version)
|
||||
upload := state.Get("upload").(*Upload)
|
||||
provider := state.Get("provider").(*Provider)
|
||||
|
||||
path := fmt.Sprintf("box/%s/version/%v/provider/%s", box.Tag, version.Version, provider.Name)
|
||||
|
||||
providerCheck := &Provider{}
|
||||
|
||||
ui.Say(fmt.Sprintf("Verifying provider upload: %s", provider.Name))
|
||||
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
|
||||
result := make(chan error, 1)
|
||||
|
||||
go func() {
|
||||
attempts := 0
|
||||
for {
|
||||
attempts += 1
|
||||
|
||||
log.Printf("Checking token match for provider.. (attempt: %d)", attempts)
|
||||
|
||||
resp, err := client.Get(path)
|
||||
|
||||
if err != nil || (resp.StatusCode != 200) {
|
||||
cloudErrors := &VagrantCloudErrors{}
|
||||
err = decodeBody(resp, cloudErrors)
|
||||
err = fmt.Errorf("Error retrieving provider: %s", cloudErrors.FormatErrors())
|
||||
result <- err
|
||||
return
|
||||
}
|
||||
|
||||
if err = decodeBody(resp, providerCheck); err != nil {
|
||||
err = fmt.Errorf("Error parsing provider response: %s", err)
|
||||
result <- err
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
result <- err
|
||||
return
|
||||
}
|
||||
|
||||
if upload.Token == providerCheck.HostedToken {
|
||||
// success!
|
||||
result <- nil
|
||||
return
|
||||
}
|
||||
|
||||
// Wait 3 seconds in between
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
// Verify we shouldn't exit
|
||||
select {
|
||||
case <-done:
|
||||
// We finished, so just exit the goroutine
|
||||
return
|
||||
default:
|
||||
// Keep going
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
ui.Message("Waiting for upload token match")
|
||||
log.Printf("Waiting for up to 600 seconds for provider hosted token to match %s", upload.Token)
|
||||
|
||||
select {
|
||||
case err := <-result:
|
||||
if err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Message(fmt.Sprintf("Upload successfully verified with token %s", providerCheck.HostedToken))
|
||||
log.Printf("Box successfully verified %s == %s", upload.Token, providerCheck.HostedToken)
|
||||
|
||||
return multistep.ActionContinue
|
||||
case <-time.After(600 * time.Second):
|
||||
state.Put("error", fmt.Errorf("Timeout while waiting to for upload to verify token '%s'", upload.Token))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stepVerifyUpload) Cleanup(state multistep.StateBag) {
|
||||
// No cleanup
|
||||
}
|
Loading…
Reference in New Issue