Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloudrun: Check knative observed generation when polling #3277

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/4793.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
cloudrun: fixed a bug where resources would return successfully due to responses based on a previous version of the resource
```
70 changes: 48 additions & 22 deletions google-beta/cloudrun_polling.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,37 +26,63 @@ type KnativeStatus struct {
SelfLink string
}
Status struct {
Conditions []Condition
Conditions []Condition
ObservedGeneration float64
}
}

func PollCheckKnativeStatus(resp map[string]interface{}, respErr error) PollResult {
if respErr != nil {
return ErrorPollResult(respErr)
func getGeneration(res map[string]interface{}) (int, error) {
metadata, ok := res["metadata"]
if !ok {
return 0, fmt.Errorf("Unable to find knative metadata")
}
s := KnativeStatus{}
if err := Convert(resp, &s); err != nil {
return ErrorPollResult(errwrap.Wrapf("unable to get KnativeStatus: {{err}}", err))
m, ok := metadata.(map[string]interface{})
if !ok {
return 0, fmt.Errorf("Unable to find generation in knative metadata")
}
gen, ok := m["generation"]
if !ok {
return 0, fmt.Errorf("Unable to find generation in knative metadata")
}
return int(gen.(float64)), nil
}

for _, condition := range s.Status.Conditions {
if condition.Type == readyStatusType {
log.Printf("[DEBUG] checking KnativeStatus Ready condition %s: %s", condition.Status, condition.Message)
switch condition.Status {
case "True":
// Resource is ready
return SuccessPollResult()
case "Unknown":
// DomainMapping can enter a 'terminal' state where "Ready" status is "Unknown"
// but the resource is waiting for external verification of DNS records.
if condition.Reason == pendingCertificateReason {
func PollCheckKnativeStatusFunc(knativeRestResponse map[string]interface{}) func(resp map[string]interface{}, respErr error) PollResult {
return func(resp map[string]interface{}, respErr error) PollResult {
if respErr != nil {
return ErrorPollResult(respErr)
}
s := KnativeStatus{}
if err := Convert(resp, &s); err != nil {
return ErrorPollResult(errwrap.Wrapf("unable to get KnativeStatus: {{err}}", err))
}

gen, err := getGeneration(knativeRestResponse)
if err != nil {
return ErrorPollResult(errwrap.Wrapf("unable to find Knative generation: {{err}}", err))
}
if int(s.Status.ObservedGeneration) != gen {
return PendingStatusPollResult("waiting for observed generation to match")
}
for _, condition := range s.Status.Conditions {
if condition.Type == readyStatusType {
log.Printf("[DEBUG] checking KnativeStatus Ready condition %s: %s", condition.Status, condition.Message)
switch condition.Status {
case "True":
// Resource is ready
return SuccessPollResult()
case "Unknown":
// DomainMapping can enter a 'terminal' state where "Ready" status is "Unknown"
// but the resource is waiting for external verification of DNS records.
if condition.Reason == pendingCertificateReason {
return SuccessPollResult()
}
return PendingStatusPollResult(fmt.Sprintf("%s:%s", condition.Status, condition.Message))
case "False":
return ErrorPollResult(fmt.Errorf(`resource is in failed state "Ready:False", message: %s`, condition.Message))
}
return PendingStatusPollResult(fmt.Sprintf("%s:%s", condition.Status, condition.Message))
case "False":
return ErrorPollResult(fmt.Errorf(`resource is in failed state "Ready:False", message: %s`, condition.Message))
}
}
return PendingStatusPollResult("no status yet")
}
return PendingStatusPollResult("no status yet")
}
2 changes: 1 addition & 1 deletion google-beta/resource_cloud_run_domain_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func resourceCloudRunDomainMappingCreate(d *schema.ResourceData, meta interface{
}
d.SetId(id)

err = PollingWaitTime(resourceCloudRunDomainMappingPollRead(d, meta), PollCheckKnativeStatus, "Creating DomainMapping", d.Timeout(schema.TimeoutCreate), 1)
err = PollingWaitTime(resourceCloudRunDomainMappingPollRead(d, meta), PollCheckKnativeStatusFunc(res), "Creating DomainMapping", d.Timeout(schema.TimeoutCreate), 1)
if err != nil {
return fmt.Errorf("Error waiting to create DomainMapping: %s", err)
}
Expand Down
4 changes: 2 additions & 2 deletions google-beta/resource_cloud_run_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ func resourceCloudRunServiceCreate(d *schema.ResourceData, meta interface{}) err
}
d.SetId(id)

err = PollingWaitTime(resourceCloudRunServicePollRead(d, meta), PollCheckKnativeStatus, "Creating Service", d.Timeout(schema.TimeoutCreate), 1)
err = PollingWaitTime(resourceCloudRunServicePollRead(d, meta), PollCheckKnativeStatusFunc(res), "Creating Service", d.Timeout(schema.TimeoutCreate), 1)
if err != nil {
return fmt.Errorf("Error waiting to create Service: %s", err)
}
Expand Down Expand Up @@ -1064,7 +1064,7 @@ func resourceCloudRunServiceUpdate(d *schema.ResourceData, meta interface{}) err
log.Printf("[DEBUG] Finished updating Service %q: %#v", d.Id(), res)
}

err = PollingWaitTime(resourceCloudRunServicePollRead(d, meta), PollCheckKnativeStatus, "Updating Service", d.Timeout(schema.TimeoutUpdate), 1)
err = PollingWaitTime(resourceCloudRunServicePollRead(d, meta), PollCheckKnativeStatusFunc(res), "Updating Service", d.Timeout(schema.TimeoutUpdate), 1)
if err != nil {
return err
}
Expand Down