github.com/newrelic/go-agent@v3.26.0+incompatible/internal/utilization/aws.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package utilization 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "io/ioutil" 10 "net/http" 11 ) 12 13 const ( 14 awsHostname = "169.254.169.254" 15 awsEndpointPath = "/2016-09-02/dynamic/instance-identity/document" 16 awsEndpoint = "http://" + awsHostname + awsEndpointPath 17 ) 18 19 type aws struct { 20 InstanceID string `json:"instanceId,omitempty"` 21 InstanceType string `json:"instanceType,omitempty"` 22 AvailabilityZone string `json:"availabilityZone,omitempty"` 23 } 24 25 func gatherAWS(util *Data, client *http.Client) error { 26 aws, err := getAWS(client) 27 if err != nil { 28 // Only return the error here if it is unexpected to prevent 29 // warning customers who aren't running AWS about a timeout. 30 if _, ok := err.(unexpectedAWSErr); ok { 31 return err 32 } 33 return nil 34 } 35 util.Vendors.AWS = aws 36 37 return nil 38 } 39 40 type unexpectedAWSErr struct{ e error } 41 42 func (e unexpectedAWSErr) Error() string { 43 return fmt.Sprintf("unexpected AWS error: %v", e.e) 44 } 45 46 func getAWS(client *http.Client) (*aws, error) { 47 response, err := client.Get(awsEndpoint) 48 if err != nil { 49 // No unexpectedAWSErr here: A timeout is usually going to 50 // happen. 51 return nil, err 52 } 53 defer response.Body.Close() 54 55 if response.StatusCode != 200 { 56 return nil, unexpectedAWSErr{e: fmt.Errorf("response code %d", response.StatusCode)} 57 } 58 59 data, err := ioutil.ReadAll(response.Body) 60 if err != nil { 61 return nil, unexpectedAWSErr{e: err} 62 } 63 a := &aws{} 64 if err := json.Unmarshal(data, a); err != nil { 65 return nil, unexpectedAWSErr{e: err} 66 } 67 68 if err := a.validate(); err != nil { 69 return nil, unexpectedAWSErr{e: err} 70 } 71 72 return a, nil 73 } 74 75 func (a *aws) validate() (err error) { 76 a.InstanceID, err = normalizeValue(a.InstanceID) 77 if err != nil { 78 return fmt.Errorf("invalid instance ID: %v", err) 79 } 80 81 a.InstanceType, err = normalizeValue(a.InstanceType) 82 if err != nil { 83 return fmt.Errorf("invalid instance type: %v", err) 84 } 85 86 a.AvailabilityZone, err = normalizeValue(a.AvailabilityZone) 87 if err != nil { 88 return fmt.Errorf("invalid availability zone: %v", err) 89 } 90 91 return 92 }