Skip to content

Commit

Permalink
[PagerDuty#274] Handle race condition where a newly created resource …
Browse files Browse the repository at this point in the history
…can return a 404 on create
  • Loading branch information
eric-spence-code committed Aug 27, 2021
1 parent 50d7853 commit 6b98b88
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 69 deletions.
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
Expand Down Expand Up @@ -113,6 +114,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down
7 changes: 5 additions & 2 deletions pagerduty/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,17 @@ func isErrCode(err error, code int) bool {
return false
}

func genError(err error, d *schema.ResourceData) error {
return fmt.Errorf("Error reading: %s: %s", d.Id(), err)
}

func handleNotFoundError(err error, d *schema.ResourceData) error {
if isErrCode(err, 404) {
log.Printf("[WARN] Removing %s because it's gone", d.Id())
d.SetId("")
return nil
}

return fmt.Errorf("Error reading: %s: %s", d.Id(), err)
return genError(err, d)
}

func providerConfigure(data *schema.ResourceData, terraformVersion string) (interface{}, error) {
Expand Down
138 changes: 71 additions & 67 deletions pagerduty/resource_pagerduty_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,94 +328,98 @@ func buildServiceStruct(d *schema.ResourceData) (*pagerduty.Service, error) {
return &service, nil
}

func resourcePagerDutyServiceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*pagerduty.Client)

service, err := buildServiceStruct(d)
if err != nil {
return err
func configureResource(d *schema.ResourceData, service *pagerduty.Service) *resource.RetryError {
d.Set("name", service.Name)
d.Set("html_url", service.HTMLURL)
d.Set("status", service.Status)
d.Set("created_at", service.CreatedAt)
d.Set("escalation_policy", service.EscalationPolicy.ID)
d.Set("description", service.Description)
if service.AutoResolveTimeout == nil {
d.Set("auto_resolve_timeout", "null")
} else {
d.Set("auto_resolve_timeout", strconv.Itoa(*service.AutoResolveTimeout))
}

log.Printf("[INFO] Creating PagerDuty service %s", service.Name)

service, _, err = client.Services.Create(service)
if err != nil {
return err
d.Set("last_incident_timestamp", service.LastIncidentTimestamp)
if service.AcknowledgementTimeout == nil {
d.Set("acknowledgement_timeout", "null")
} else {
d.Set("acknowledgement_timeout", strconv.Itoa(*service.AcknowledgementTimeout))
}
d.Set("alert_creation", service.AlertCreation)
if service.AlertGrouping != nil && *service.AlertGrouping != "" {
d.Set("alert_grouping", *service.AlertGrouping)
}
if service.AlertGroupingTimeout == nil {
d.Set("alert_grouping_timeout", "null")
} else {
d.Set("alert_grouping_timeout", *service.AlertGroupingTimeout)
}
if service.AlertGroupingParameters != nil {
if err := d.Set("alert_grouping_parameters", flattenAlertGroupingParameters(service.AlertGroupingParameters)); err != nil {
return resource.NonRetryableError(err)
}
}
if service.IncidentUrgencyRule != nil {
if err := d.Set("incident_urgency_rule", flattenIncidentUrgencyRule(service.IncidentUrgencyRule)); err != nil {
return resource.NonRetryableError(err)
}
}

d.SetId(service.ID)
if service.SupportHours != nil {
if err := d.Set("support_hours", flattenSupportHours(service.SupportHours)); err != nil {
return resource.NonRetryableError(err)
}
}

return resourcePagerDutyServiceRead(d, meta)
if service.ScheduledActions != nil {
if err := d.Set("scheduled_actions", flattenScheduledActions(service.ScheduledActions)); err != nil {
return resource.NonRetryableError(err)
}
}
return nil
}

func resourcePagerDutyServiceRead(d *schema.ResourceData, meta interface{}) error {
func fetchResource(d *schema.ResourceData, meta interface{}, errCallback func(error, *schema.ResourceData) error) error {
client := meta.(*pagerduty.Client)

log.Printf("[INFO] Reading PagerDuty service %s", d.Id())

return resource.Retry(2*time.Minute, func() *resource.RetryError {
service, _, err := client.Services.Get(d.Id(), &pagerduty.GetServiceOptions{})
if err != nil {
log.Printf("[WARN] Service read error")
errResp := handleNotFoundError(err, d)
errResp := errCallback(err, d)
if errResp != nil {
time.Sleep(2 * time.Second)
return resource.RetryableError(errResp)
}

return nil
}
return configureResource(d, service)
})
}

d.Set("name", service.Name)
d.Set("html_url", service.HTMLURL)
d.Set("status", service.Status)
d.Set("created_at", service.CreatedAt)
d.Set("escalation_policy", service.EscalationPolicy.ID)
d.Set("description", service.Description)
if service.AutoResolveTimeout == nil {
d.Set("auto_resolve_timeout", "null")
} else {
d.Set("auto_resolve_timeout", strconv.Itoa(*service.AutoResolveTimeout))
}
d.Set("last_incident_timestamp", service.LastIncidentTimestamp)
if service.AcknowledgementTimeout == nil {
d.Set("acknowledgement_timeout", "null")
} else {
d.Set("acknowledgement_timeout", strconv.Itoa(*service.AcknowledgementTimeout))
}
d.Set("alert_creation", service.AlertCreation)
if service.AlertGrouping != nil && *service.AlertGrouping != "" {
d.Set("alert_grouping", *service.AlertGrouping)
}
if service.AlertGroupingTimeout == nil {
d.Set("alert_grouping_timeout", "null")
} else {
d.Set("alert_grouping_timeout", *service.AlertGroupingTimeout)
}
if service.AlertGroupingParameters != nil {
if err := d.Set("alert_grouping_parameters", flattenAlertGroupingParameters(service.AlertGroupingParameters)); err != nil {
return resource.NonRetryableError(err)
}
}
if service.IncidentUrgencyRule != nil {
if err := d.Set("incident_urgency_rule", flattenIncidentUrgencyRule(service.IncidentUrgencyRule)); err != nil {
return resource.NonRetryableError(err)
}
}
func resourcePagerDutyServiceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*pagerduty.Client)
service, err := buildServiceStruct(d)
if err != nil {
return err
}

if service.SupportHours != nil {
if err := d.Set("support_hours", flattenSupportHours(service.SupportHours)); err != nil {
return resource.NonRetryableError(err)
}
}
log.Printf("[INFO] Creating PagerDuty service %s", service.Name)

if service.ScheduledActions != nil {
if err := d.Set("scheduled_actions", flattenScheduledActions(service.ScheduledActions)); err != nil {
return resource.NonRetryableError(err)
}
}
return nil
})
service, _, err = client.Services.Create(service)
if err != nil {
return err
}

d.SetId(service.ID)

return fetchResource(d, meta, genError)
}

func resourcePagerDutyServiceRead(d *schema.ResourceData, meta interface{}) error {
log.Printf("[INFO] Reading PagerDuty service %s", d.Id())
return fetchResource(d, meta, handleNotFoundError)
}

func resourcePagerDutyServiceUpdate(d *schema.ResourceData, meta interface{}) error {
Expand Down

0 comments on commit 6b98b88

Please sign in to comment.