1package ec2metadata 2 3import ( 4 "encoding/json" 5 "fmt" 6 "path" 7 "strings" 8 "time" 9 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/aws/request" 12) 13 14// GetMetadata uses the path provided to request information from the EC2 15// instance metdata service. The content will be returned as a string, or 16// error if the request failed. 17func (c *EC2Metadata) GetMetadata(p string) (string, error) { 18 op := &request.Operation{ 19 Name: "GetMetadata", 20 HTTPMethod: "GET", 21 HTTPPath: path.Join("/", "meta-data", p), 22 } 23 24 output := &metadataOutput{} 25 req := c.NewRequest(op, nil, output) 26 27 return output.Content, req.Send() 28} 29 30// GetDynamicData uses the path provided to request information from the EC2 31// instance metadata service for dynamic data. The content will be returned 32// as a string, or error if the request failed. 33func (c *EC2Metadata) GetDynamicData(p string) (string, error) { 34 op := &request.Operation{ 35 Name: "GetDynamicData", 36 HTTPMethod: "GET", 37 HTTPPath: path.Join("/", "dynamic", p), 38 } 39 40 output := &metadataOutput{} 41 req := c.NewRequest(op, nil, output) 42 43 return output.Content, req.Send() 44} 45 46// GetInstanceIdentityDocument retrieves an identity document describing an 47// instance. Error is returned if the request fails or is unable to parse 48// the response. 49func (c *EC2Metadata) GetInstanceIdentityDocument() (EC2InstanceIdentityDocument, error) { 50 resp, err := c.GetDynamicData("instance-identity/document") 51 if err != nil { 52 return EC2InstanceIdentityDocument{}, 53 awserr.New("EC2MetadataRequestError", 54 "failed to get EC2 instance identity document", err) 55 } 56 57 doc := EC2InstanceIdentityDocument{} 58 if err := json.NewDecoder(strings.NewReader(resp)).Decode(&doc); err != nil { 59 return EC2InstanceIdentityDocument{}, 60 awserr.New("SerializationError", 61 "failed to decode EC2 instance identity document", err) 62 } 63 64 return doc, nil 65} 66 67// IAMInfo retrieves IAM info from the metadata API 68func (c *EC2Metadata) IAMInfo() (EC2IAMInfo, error) { 69 resp, err := c.GetMetadata("iam/info") 70 if err != nil { 71 return EC2IAMInfo{}, 72 awserr.New("EC2MetadataRequestError", 73 "failed to get EC2 IAM info", err) 74 } 75 76 info := EC2IAMInfo{} 77 if err := json.NewDecoder(strings.NewReader(resp)).Decode(&info); err != nil { 78 return EC2IAMInfo{}, 79 awserr.New("SerializationError", 80 "failed to decode EC2 IAM info", err) 81 } 82 83 if info.Code != "Success" { 84 errMsg := fmt.Sprintf("failed to get EC2 IAM Info (%s)", info.Code) 85 return EC2IAMInfo{}, 86 awserr.New("EC2MetadataError", errMsg, nil) 87 } 88 89 return info, nil 90} 91 92// Region returns the region the instance is running in. 93func (c *EC2Metadata) Region() (string, error) { 94 resp, err := c.GetMetadata("placement/availability-zone") 95 if err != nil { 96 return "", err 97 } 98 99 // returns region without the suffix. Eg: us-west-2a becomes us-west-2 100 return resp[:len(resp)-1], nil 101} 102 103// Available returns if the application has access to the EC2 Metadata service. 104// Can be used to determine if application is running within an EC2 Instance and 105// the metadata service is available. 106func (c *EC2Metadata) Available() bool { 107 if _, err := c.GetMetadata("instance-id"); err != nil { 108 return false 109 } 110 111 return true 112} 113 114// An EC2IAMInfo provides the shape for unmarshalling 115// an IAM info from the metadata API 116type EC2IAMInfo struct { 117 Code string 118 LastUpdated time.Time 119 InstanceProfileArn string 120 InstanceProfileID string 121} 122 123// An EC2InstanceIdentityDocument provides the shape for unmarshalling 124// an instance identity document 125type EC2InstanceIdentityDocument struct { 126 DevpayProductCodes []string `json:"devpayProductCodes"` 127 AvailabilityZone string `json:"availabilityZone"` 128 PrivateIP string `json:"privateIp"` 129 Version string `json:"version"` 130 Region string `json:"region"` 131 InstanceID string `json:"instanceId"` 132 BillingProducts []string `json:"billingProducts"` 133 InstanceType string `json:"instanceType"` 134 AccountID string `json:"accountId"` 135 PendingTime time.Time `json:"pendingTime"` 136 ImageID string `json:"imageId"` 137 KernelID string `json:"kernelId"` 138 RamdiskID string `json:"ramdiskId"` 139 Architecture string `json:"architecture"` 140} 141