github.com/grailbio/base@v0.0.11/cloud/ec2util/iid.go (about) 1 package ec2util 2 3 import ( 4 "fmt" 5 "net/http" 6 "time" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/aws/ec2metadata" 10 "github.com/aws/aws-sdk-go/aws/session" 11 "github.com/grailbio/base/sync/once" 12 ) 13 14 var ( 15 iidOnce once.Task 16 iid ec2metadata.EC2InstanceIdentityDocument 17 ) 18 19 // GetInstanceIdentityDocument returns the EC2 Instance ID document (if the current 20 // process is running within an EC2 instance) or an error. 21 // Unlike the SDK's implementation, this will use longer timeouts and multiple retries 22 // to improve the reliability of getting the Instance ID document. 23 // The first result, whether success or failure, is cached for the lifetime of the process. 24 func GetInstanceIdentityDocument(sess *session.Session) (doc ec2metadata.EC2InstanceIdentityDocument, err error) { 25 err = iidOnce.Do(func() (oerr error) { 26 // Use HTTP client with custom timeout and max retries to prevent the SDK from 27 // using an HTTP client with a small timeout and a small number of retries for 28 // the ec2metadata client 29 metaClient := ec2metadata.New(sess, &aws.Config{ 30 HTTPClient: &http.Client{Timeout: 5 * time.Second}, 31 MaxRetries: aws.Int(5), 32 }) 33 for retries := 0; retries < 5; retries++ { 34 iid, oerr = metaClient.GetInstanceIdentityDocument() 35 if oerr == nil { 36 break 37 } 38 } 39 return 40 }) 41 switch { 42 case err != nil: 43 err = fmt.Errorf("ec2util.GetInstanceIdentityDocument: %v", err) 44 case iid.InstanceID == "": 45 err = fmt.Errorf("ec2util.GetInstanceIdentityDocument: Unable to get EC2InstanceIdentityDocument") 46 default: 47 doc = iid 48 } 49 return 50 }