Skip to content

Commit 10474fc

Browse files
Introduced Rate Limiter and Retry Options (429 response) for all platform clients
1 parent 00a3e94 commit 10474fc

File tree

7 files changed

+35
-13
lines changed

7 files changed

+35
-13
lines changed

dynatrace/api/automation/business_calendars/service.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"encoding/json"
2323
"net/url"
24+
"time"
2425

2526
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api"
2627
tfrest "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/rest"
@@ -51,7 +52,8 @@ func (me *service) client(ctx context.Context) *automation.Client {
5152
TokenURL: me.credentials.OAuth.TokenURL,
5253
})
5354
u, _ := url.Parse(me.credentials.OAuth.EnvironmentURL)
54-
restClient := rest.NewClient(u, httpClient)
55+
56+
restClient := rest.NewClient(u, httpClient, rest.WithRateLimiter(), rest.WithRetryOptions(&rest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: rest.RetryIfTooManyRequests}))
5557
restClient.SetHeader("User-Agent", "Dynatrace Terraform Provider")
5658
return automation.NewClient(restClient)
5759
}

dynatrace/api/automation/scheduling_rules/service.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"encoding/json"
2323
"net/url"
24+
"time"
2425

2526
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api"
2627
tfrest "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/rest"
@@ -51,7 +52,7 @@ func (me *service) client(ctx context.Context) *automation.Client {
5152
TokenURL: me.credentials.OAuth.TokenURL,
5253
})
5354
u, _ := url.Parse(me.credentials.OAuth.EnvironmentURL)
54-
restClient := rest.NewClient(u, httpClient)
55+
restClient := rest.NewClient(u, httpClient, rest.WithRateLimiter(), rest.WithRetryOptions(&rest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: rest.RetryIfTooManyRequests}))
5556
restClient.SetHeader("User-Agent", "Dynatrace Terraform Provider")
5657
return automation.NewClient(restClient)
5758
}

dynatrace/api/automation/workflows/service.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"encoding/json"
2323
"net/url"
24+
"time"
2425

2526
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api"
2627
tfrest "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/rest"
@@ -53,7 +54,7 @@ func (me *service) client(ctx context.Context) *automation.Client {
5354
TokenURL: me.credentials.OAuth.TokenURL,
5455
})
5556
u, _ := url.Parse(me.credentials.OAuth.EnvironmentURL)
56-
restClient := rest.NewClient(u, httpClient)
57+
restClient := rest.NewClient(u, httpClient, rest.WithRateLimiter(), rest.WithRetryOptions(&rest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: rest.RetryIfTooManyRequests}))
5758
restClient.SetHeader("User-Agent", "Dynatrace Terraform Provider")
5859
return automation.NewClient(restClient)
5960
}

dynatrace/api/grail/segments/service.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ package segments
2020
import (
2121
"context"
2222
"encoding/json"
23+
"time"
2324

2425
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api"
2526
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/rest"
2627
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/settings"
2728
segmentsapi "github.com/dynatrace/dynatrace-configuration-as-code-core/api"
29+
crest "github.com/dynatrace/dynatrace-configuration-as-code-core/api/rest"
2830
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients"
2931
segmentsclient "github.com/dynatrace/dynatrace-configuration-as-code-core/clients/segments"
3032
"golang.org/x/oauth2/clientcredentials"
@@ -51,7 +53,9 @@ func (me *service) client(ctx context.Context) *segmentsclient.Client {
5153
ClientSecret: me.credentials.OAuth.ClientSecret,
5254
TokenURL: me.credentials.OAuth.TokenURL,
5355
}).
54-
WithUserAgent("Dynatrace Terraform Provider")
56+
WithUserAgent("Dynatrace Terraform Provider").
57+
WithRetryOptions(&crest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: crest.RetryIfTooManyRequests}).
58+
WithRateLimiter(true)
5559

5660
segmentClient, _ := clientsFactory.SegmentsClient(ctx)
5761
return segmentClient

dynatrace/api/openpipeline/service.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ package openpipeline
2020
import (
2121
"context"
2222
"encoding/json"
23+
"time"
2324

2425
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api"
2526
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/automation/httplog"
2627
openpipeline "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/openpipeline/settings"
2728
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/rest"
2829
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/settings"
30+
crest "github.com/dynatrace/dynatrace-configuration-as-code-core/api/rest"
2931
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients"
3032
caclib "github.com/dynatrace/dynatrace-configuration-as-code-core/clients/openpipeline"
3133
"golang.org/x/oauth2/clientcredentials"
@@ -66,7 +68,9 @@ func (s *service) createClient(ctx context.Context) (*caclib.Client, error) {
6668
ClientSecret: s.credentials.OAuth.ClientSecret,
6769
TokenURL: s.credentials.OAuth.TokenURL,
6870
}).
69-
WithHTTPListener(httplog.HTTPListener)
71+
WithHTTPListener(httplog.HTTPListener).
72+
WithRetryOptions(&crest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: crest.RetryIfTooManyRequests}).
73+
WithRateLimiter(true)
7074

7175
return factory.OpenPipelineClient(ctx)
7276
}

dynatrace/api/platform/buckets/service.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ import (
2626
"time"
2727

2828
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api"
29+
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/automation/httplog"
30+
buckets "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/platform/buckets/settings"
2931
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/rest"
3032
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/settings"
3133
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/shutdown"
32-
33-
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/automation/httplog"
34-
buckets "github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/api/platform/buckets/settings"
3534
coreapi "github.com/dynatrace/dynatrace-configuration-as-code-core/api"
35+
crest "github.com/dynatrace/dynatrace-configuration-as-code-core/api/rest"
3636
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients"
3737
bucket "github.com/dynatrace/dynatrace-configuration-as-code-core/clients/buckets"
3838
"golang.org/x/oauth2/clientcredentials"
@@ -55,7 +55,10 @@ func (me *service) client(ctx context.Context) *bucket.Client {
5555
ClientSecret: me.credentials.OAuth.ClientSecret,
5656
TokenURL: me.credentials.OAuth.TokenURL,
5757
}).
58-
WithHTTPListener(httplog.HTTPListener)
58+
WithHTTPListener(httplog.HTTPListener).
59+
WithRetryOptions(&crest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: crest.RetryIfTooManyRequests}).
60+
WithRateLimiter(true)
61+
5962
bucketClient, _ := factory.BucketClient(ctx)
6063
return bucketClient
6164
}

dynatrace/rest/platform_request.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"regexp"
1010
"strings"
1111
"sync"
12+
"time"
1213

1314
"github.com/dynatrace-oss/terraform-provider-dynatrace/dynatrace/rest/logging"
1415
"github.com/dynatrace/dynatrace-configuration-as-code-core/api/rest"
@@ -47,15 +48,19 @@ func createPlatformRestClient(u string, httpClient *http.Client) (*rest.Client,
4748
return nil, fmt.Errorf("failed to parse URL %q: %w", u, err)
4849
}
4950

50-
opts := []rest.Option{rest.WithHTTPListener(logging.HTTPListener("plat/tok"))}
51+
opts := []rest.Option{
52+
rest.WithHTTPListener(logging.HTTPListener("plat/tok")),
53+
rest.WithRateLimiter(),
54+
rest.WithRetryOptions(&rest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: rest.RetryIfTooManyRequests}),
55+
}
5156

5257
restClient := rest.NewClient(parsedURL, httpClient, opts...)
5358
restClient.SetHeader("User-Agent", "Dynatrace Terraform Provider")
5459

5560
return restClient, nil
5661
}
5762

58-
func platformClient(platformURL string, credentials *Credentials) (*rest.Client, error) {
63+
func platformClient(ctx context.Context, platformURL string, credentials *Credentials) (*rest.Client, error) {
5964
clientID := credentials.OAuth.ClientID
6065
clientSecret := credentials.OAuth.ClientSecret
6166

@@ -72,11 +77,13 @@ func platformClient(platformURL string, credentials *Credentials) (*rest.Client,
7277
client, err = createPlatformRestClient(platformURL, NewBearerTokenBasedClient(credentials.OAuth.PlatformToken))
7378
} else if credentials.ContainsOAuth() {
7479
factory := clients.Factory()
80+
factory = factory.WithRetryOptions(&rest.RetryOptions{MaxRetries: 30, DelayAfterRetry: 10 * time.Second, ShouldRetryFunc: rest.RetryIfTooManyRequests})
81+
factory = factory.WithRateLimiter(true)
7582
factory = factory.WithUserAgent("Dynatrace Terraform Provider")
7683
factory = factory.WithPlatformURL(platformURL)
7784
factory = factory.WithHTTPListener(logging.HTTPListener("platform"))
7885
factory = factory.WithOAuthCredentials(clientcredentials.Config{ClientID: clientID, ClientSecret: clientSecret, TokenURL: evalTokenURL(platformURL)})
79-
client, err = factory.CreatePlatformClient(context.Background())
86+
client, err = factory.CreatePlatformClient(ctx)
8087
} else {
8188
return nil, errors.New("neither oauth credentials nor platform token present")
8289
}
@@ -98,7 +105,7 @@ func (me *platform_request) Finish(optionalTarget ...any) error {
98105

99106
platformURL := me.evalPlatformURL()
100107

101-
client, err := platformClient(platformURL, me.client.Credentials())
108+
client, err := platformClient(me.ctx, platformURL, me.client.Credentials())
102109
if err != nil {
103110
return err
104111
}

0 commit comments

Comments
 (0)