github.com/newrelic/go-agent@v3.26.0+incompatible/internal/utilization/azure.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 azureHostname = "169.254.169.254" 15 azureEndpointPath = "/metadata/instance/compute?api-version=2017-03-01" 16 azureEndpoint = "http://" + azureHostname + azureEndpointPath 17 ) 18 19 type azure struct { 20 Location string `json:"location,omitempty"` 21 Name string `json:"name,omitempty"` 22 VMID string `json:"vmId,omitempty"` 23 VMSize string `json:"vmSize,omitempty"` 24 } 25 26 func gatherAzure(util *Data, client *http.Client) error { 27 az, err := getAzure(client) 28 if err != nil { 29 // Only return the error here if it is unexpected to prevent 30 // warning customers who aren't running Azure about a timeout. 31 if _, ok := err.(unexpectedAzureErr); ok { 32 return err 33 } 34 return nil 35 } 36 util.Vendors.Azure = az 37 38 return nil 39 } 40 41 type unexpectedAzureErr struct{ e error } 42 43 func (e unexpectedAzureErr) Error() string { 44 return fmt.Sprintf("unexpected Azure error: %v", e.e) 45 } 46 47 func getAzure(client *http.Client) (*azure, error) { 48 req, err := http.NewRequest("GET", azureEndpoint, nil) 49 if err != nil { 50 return nil, err 51 } 52 req.Header.Add("Metadata", "true") 53 54 response, err := client.Do(req) 55 if err != nil { 56 // No unexpectedAzureErr here: a timeout isusually going to 57 // happen. 58 return nil, err 59 } 60 defer response.Body.Close() 61 62 if response.StatusCode != 200 { 63 return nil, unexpectedAzureErr{e: fmt.Errorf("response code %d", response.StatusCode)} 64 } 65 66 data, err := ioutil.ReadAll(response.Body) 67 if err != nil { 68 return nil, unexpectedAzureErr{e: err} 69 } 70 71 az := &azure{} 72 if err := json.Unmarshal(data, az); err != nil { 73 return nil, unexpectedAzureErr{e: err} 74 } 75 76 if err := az.validate(); err != nil { 77 return nil, unexpectedAzureErr{e: err} 78 } 79 80 return az, nil 81 } 82 83 func (az *azure) validate() (err error) { 84 az.Location, err = normalizeValue(az.Location) 85 if err != nil { 86 return fmt.Errorf("Invalid location: %v", err) 87 } 88 89 az.Name, err = normalizeValue(az.Name) 90 if err != nil { 91 return fmt.Errorf("Invalid name: %v", err) 92 } 93 94 az.VMID, err = normalizeValue(az.VMID) 95 if err != nil { 96 return fmt.Errorf("Invalid VM ID: %v", err) 97 } 98 99 az.VMSize, err = normalizeValue(az.VMSize) 100 if err != nil { 101 return fmt.Errorf("Invalid VM size: %v", err) 102 } 103 104 return 105 }