1//go:build example
2// +build example
3
4package main
5
6import (
7	"fmt"
8
9	"github.com/aws/aws-sdk-go/aws"
10	"github.com/aws/aws-sdk-go/aws/awserr"
11	"github.com/aws/aws-sdk-go/aws/client"
12	"github.com/aws/aws-sdk-go/aws/credentials"
13	"github.com/aws/aws-sdk-go/aws/defaults"
14	"github.com/aws/aws-sdk-go/aws/endpoints"
15	"github.com/aws/aws-sdk-go/aws/request"
16	"github.com/aws/aws-sdk-go/aws/session"
17	"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
18)
19
20func main() {
21	sess := session.Must(
22		session.NewSession(&aws.Config{
23			// Use a custom retryer to provide custom retry rules.
24			Retryer: CustomRetryer{
25				DefaultRetryer: client.DefaultRetryer{
26					NumMaxRetries: client.DefaultRetryerMaxNumRetries,
27				}},
28
29			// Use the SDK's SharedCredentialsProvider directly instead of the
30			// SDK's default credential chain. This ensures that the
31			// application can call Config.Credentials.Expire. This  is counter
32			// to the SDK's default credentials chain, which  will never reread
33			// the shared credentials file.
34			Credentials: credentials.NewCredentials(&credentials.SharedCredentialsProvider{
35				Filename: defaults.SharedCredentialsFilename(),
36				Profile:  "default",
37			}),
38			Region: aws.String(endpoints.UsWest2RegionID),
39		}),
40	)
41	// Add a request handler to the AfterRetry handler stack that is used by the
42	// SDK to be executed after the SDK has determined if it will retry.
43	// This handler forces the SDK's Credentials to be expired, and next call to
44	// Credentials.Get will attempt to refresh the credentials.
45	sess.Handlers.AfterRetry.PushBack(func(req *request.Request) {
46		if aerr, ok := req.Error.(awserr.RequestFailure); ok && aerr != nil {
47			if aerr.Code() == "InvalidClaimException" {
48				// Force the credentials to expire based on error code.  Next
49				// call to Credentials.Get will attempt to refresh credentials.
50				req.Config.Credentials.Expire()
51			}
52		}
53	})
54
55	svc := cloudwatchlogs.New(sess)
56
57	resp, err := svc.DescribeLogGroups(&cloudwatchlogs.DescribeLogGroupsInput{})
58
59	fmt.Println(resp, err)
60}
61
62// CustomRetryer wraps the SDK's built in DefaultRetryer adding additional
63// custom features. Such as, no retry for 5xx status codes, and refresh
64// credentials.
65type CustomRetryer struct {
66	client.DefaultRetryer
67}
68
69// ShouldRetry overrides the SDK's built in DefaultRetryer adding customization
70// to not retry 5xx status codes.
71func (r CustomRetryer) ShouldRetry(req *request.Request) bool {
72	if req.HTTPResponse.StatusCode >= 500 {
73		// Don't retry any 5xx status codes.
74		return false
75	}
76
77	// Fallback to SDK's built in retry rules
78	return r.DefaultRetryer.ShouldRetry(req)
79}
80