-
Notifications
You must be signed in to change notification settings - Fork 1
/
ec2dynamicdata.go
88 lines (75 loc) · 2.23 KB
/
ec2dynamicdata.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Package ec2dynamicdata gets ec2 dynamic data or meta data for the current
// running ec2 host
package ec2dynamicdata
import (
"encoding/json"
"errors"
"fmt"
"net"
"net/http"
"net/url"
"time"
)
const endpoint = "http://169.254.169.254/latest/dynamic/instance-identity/document"
var (
// DialTimeout holds timeout value for ec2 dynamic data calls
DialTimeout = time.Second * 5
)
// Err wraps any possible errors for api call
type Err struct {
Err error
Original error
}
// Error implements the error interface.
func (e *Err) Error() string {
return e.Err.Error()
}
// Data holds dynamic data about current ec2 host
type Data struct {
InstanceID string `json:"instanceId"`
BillingProducts interface{} `json:"billingProducts"`
ImageID string `json:"imageId"`
Architecture string `json:"architecture"`
PendingTime time.Time `json:"pendingTime"`
InstanceType string `json:"instanceType"`
AccountID string `json:"accountId"`
KernelID interface{} `json:"kernelId"`
RamdiskID interface{} `json:"ramdiskId"`
Region string `json:"region"`
Version string `json:"version"`
AvailabilityZone string `json:"availabilityZone"`
PrivateID string `json:"privateIp"`
DevpayProductCodes interface{} `json:"devpayProductCodes"`
}
// Get returns EC2 dynamic data
func Get() (*Data, error) {
client := http.Client{
Transport: &http.Transport{
// timeout only for dialing, because if we are not in ec2, this will timeout
Dial: func(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, DialTimeout)
},
},
}
resp, err := client.Get(endpoint)
if err != nil {
return nil, wrapEC2Error(err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, fmt.Errorf("err: status code (%d)", resp.StatusCode)
}
identity := &Data{}
if err := json.NewDecoder(resp.Body).Decode(&identity); err != nil {
return nil, err
}
return identity, nil
}
func wrapEC2Error(err error) error {
if uerr, ok := err.(*url.Error); ok {
if _, ok := uerr.Err.(*net.OpError); ok {
return &Err{Original: err, Err: errors.New("not an ec2 instance")}
}
}
return err
}