From e5fd91a2e32607347203fa4c42d5e3ab1efdc45c Mon Sep 17 00:00:00 2001 From: root Date: Fri, 27 Aug 2021 15:40:32 -0400 Subject: [PATCH] [#273] Handle race condition where a newly created resource can return a 404 on create --- go.sum | 2 + pagerduty/provider.go | 7 +- pagerduty/resource_pagerduty_service.go | 138 ++++++++++++------------ 3 files changed, 78 insertions(+), 69 deletions(-) diff --git a/go.sum b/go.sum index 6e06a9372..69cca87ff 100644 --- a/go.sum +++ b/go.sum @@ -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= @@ -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= diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 80de9aae4..23e4341e5 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -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) { diff --git a/pagerduty/resource_pagerduty_service.go b/pagerduty/resource_pagerduty_service.go index 1c4223935..1de521d96 100644 --- a/pagerduty/resource_pagerduty_service.go +++ b/pagerduty/resource_pagerduty_service.go @@ -328,36 +328,65 @@ 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) @@ -365,57 +394,32 @@ func resourcePagerDutyServiceRead(d *schema.ResourceData, meta interface{}) erro 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 {