Rework polling (#531)

Rework the polling code for `pulumi` when targeting hosted scenarios. (i.e. absorb https://github.com/pulumi/pulumi-service/pull/282.) We now return an `updateID` for update, preview, and destroy. And use bake that into the URL.

This PR also silently ignores 504 errors which are now returned from the Pulumi Service if the PPC request times out.

Combined, this should ameliorate some of the symptoms we see from https://github.com/pulumi/pulumi-ppc/issues/60. Though we'll continue to try to identify and fix the root cause.
This commit is contained in:
Chris Smith 2017-11-06 14:12:20 -08:00 committed by GitHub
parent fbb3887343
commit 5085c7eef8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 18 deletions

View file

@ -96,16 +96,16 @@ func (b *pulumiCloudPulumiBackend) Preview(stackName tokens.QName, debug bool, o
return err
}
var updateResponse apitype.PreviewUpdateResponse
var response apitype.PreviewUpdateResponse
path := fmt.Sprintf("/orgs/%s/programs/%s/%s/stacks/%s/preview",
projID.Owner, projID.Repository, projID.Project, string(stackName))
if err = pulumiRESTCall("POST", path, &updateRequest, &updateResponse); err != nil {
if err = pulumiRESTCall("POST", path, &updateRequest, &response); err != nil {
return err
}
fmt.Printf("Previewing update to Stack '%s'...\n", string(stackName))
// Wait for the update to complete.
status, err := waitForUpdate(fmt.Sprintf("%s/%s", path, updateResponse.PreviewID))
status, err := waitForUpdate(fmt.Sprintf("%s/%s", path, response.UpdateID))
fmt.Println() // The PPC's final message we print to STDOUT doesn't include a newline.
if err != nil {
@ -128,15 +128,15 @@ func (b *pulumiCloudPulumiBackend) Update(stackName tokens.QName, debug bool, op
return err
}
var updateResponse apitype.UpdateProgramResponse
var response apitype.UpdateProgramResponse
path := fmt.Sprintf("/orgs/%s/programs/%s/%s/stacks/%s/update", projID.Owner, projID.Repository, projID.Project, string(stackName))
if err = pulumiRESTCall("POST", path, &updateRequest, &updateResponse); err != nil {
if err = pulumiRESTCall("POST", path, &updateRequest, &response); err != nil {
return err
}
fmt.Printf("Updating Stack '%s' to version %d...\n", string(stackName), updateResponse.Version)
fmt.Printf("Updating Stack '%s' to version %d...\n", string(stackName), response.Version)
// Wait for the update to complete.
status, err := waitForUpdate(path)
status, err := waitForUpdate(fmt.Sprintf("%s/%s", path, response.UpdateID))
fmt.Println() // The PPC's final message we print to STDOUT doesn't include a newline.
if err != nil {
@ -164,15 +164,15 @@ func (b *pulumiCloudPulumiBackend) Destroy(stackName tokens.QName, debug bool, o
return err
}
var response apitype.DestroyProgramResponse
path := fmt.Sprintf("/orgs/%s/programs/%s/%s/stacks/%s/destroy", projID.Owner, projID.Repository, projID.Project, string(stackName))
if err = pulumiRESTCall("POST", path, &updateRequest, nil /*destroy does not return data upon success*/); err != nil {
if err = pulumiRESTCall("POST", path, &updateRequest, &response); err != nil {
return err
}
fmt.Printf("Destroying Stack '%s'...\n", string(stackName))
// Wait for the update to complete.
status, err := waitForUpdate(path)
status, err := waitForUpdate(fmt.Sprintf("%s/%s", path, response.UpdateID))
fmt.Println() // The PPC's final message we print to STDOUT doesn't include a newline.
if err != nil {
@ -315,7 +315,13 @@ func waitForUpdate(path string) (apitype.UpdateStatus, error) {
var updateResults apitype.UpdateResults
pathWithIndex := fmt.Sprintf("%s?afterIndex=%s", path, eventIndex)
if err := pulumiRESTCall("GET", pathWithIndex, nil, &updateResults); err != nil {
return "", err
// If our request to the Pulumi Service returned a 504 (Gateway Timeout), ignore it
// and keep continuing.
// TODO(pulumi/pulumi-ppc/issues/60): Elminate these timeouts all together.
if errResp, ok := err.(*apitype.ErrorResponse); ok && errResp.Code == 504 {
time.Sleep(5 * time.Second)
continue
}
}
for _, event := range updateResults.Events {

View file

@ -31,13 +31,6 @@ func (err ErrorResponse) Error() string {
return fmt.Sprintf("[%d] %s", err.Code, err.Message)
}
// PreviewUpdateResponse is returned when previewing a potential update.
// Since multiple previews can be running concurrently, the caller must keep
// track of the opaque preview ID for future requests.
type PreviewUpdateResponse struct {
PreviewID string `json:"previewID"`
}
// UpdateProgramRequest is the request type for updating (aka deploying) a Pulumi program.
type UpdateProgramRequest struct {
// Properties from the Project file.
@ -51,11 +44,23 @@ type UpdateProgramRequest struct {
Config map[tokens.ModuleMember]string `json:"config"`
}
// PreviewUpdateResponse is returned when previewing a potential update.
type PreviewUpdateResponse struct {
UpdateID string `json:"updateID"`
}
// UpdateProgramResponse is the response type when updating a Pulumi program.
type UpdateProgramResponse struct {
UpdateID string `json:"updateID"`
// Version is the program's new version being updated to.
Version int `json:"version"`
}
// DestroyProgramResponse is the response type when destroying a Pulumi program's resources.
type DestroyProgramResponse struct {
UpdateID string `json:"updateID"`
}
// UpdateEventKind is an enum for the type of update events.
type UpdateEventKind string