forked from cloudfoundry/bosh-agent
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconcrete_metadata_service.go
153 lines (121 loc) · 3.59 KB
/
concrete_metadata_service.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package infrastructure
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
bosherr "github.com/cloudfoundry/bosh-agent/errors"
)
type concreteMetadataService struct {
metadataHost string
resolver dnsResolver
}
type userDataType struct {
Registry struct {
Endpoint string
}
Server struct {
Name string // Name given by CPI e.g. vm-384sd4-r7re9e...
}
DNS struct {
Nameserver []string
}
}
func NewConcreteMetadataService(
metadataHost string,
resolver dnsResolver,
) concreteMetadataService {
return concreteMetadataService{
metadataHost: metadataHost,
resolver: resolver,
}
}
func (ms concreteMetadataService) GetPublicKey() (string, error) {
url := fmt.Sprintf("%s/latest/meta-data/public-keys/0/openssh-key", ms.metadataHost)
resp, err := http.Get(url)
if err != nil {
return "", bosherr.WrapError(err, "Getting open ssh key")
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", bosherr.WrapError(err, "Reading ssh key response body")
}
return string(bytes), nil
}
func (ms concreteMetadataService) GetInstanceID() (string, error) {
url := fmt.Sprintf("%s/latest/meta-data/instance-id", ms.metadataHost)
resp, err := http.Get(url)
if err != nil {
return "", bosherr.WrapError(err, "Getting instance id from url")
}
defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", bosherr.WrapError(err, "Reading instance id response body")
}
return string(bytes), nil
}
func (ms concreteMetadataService) GetServerName() (string, error) {
userData, err := ms.getUserData()
if err != nil {
return "", bosherr.WrapError(err, "Getting user data")
}
serverName := userData.Server.Name
if len(serverName) == 0 {
return "", bosherr.New("Empty server name")
}
return serverName, nil
}
func (ms concreteMetadataService) GetRegistryEndpoint() (string, error) {
userData, err := ms.getUserData()
if err != nil {
return "", bosherr.WrapError(err, "Getting user data")
}
endpoint := userData.Registry.Endpoint
nameServers := userData.DNS.Nameserver
if len(nameServers) > 0 {
endpoint, err = ms.resolveRegistryEndpoint(endpoint, nameServers)
if err != nil {
return "", bosherr.WrapError(err, "Resolving registry endpoint")
}
}
return endpoint, nil
}
func (ms concreteMetadataService) getUserData() (userDataType, error) {
var userData userDataType
userDataURL := fmt.Sprintf("%s/latest/user-data", ms.metadataHost)
userDataResp, err := http.Get(userDataURL)
if err != nil {
return userData, bosherr.WrapError(err, "Getting user data from url")
}
defer userDataResp.Body.Close()
userDataBytes, err := ioutil.ReadAll(userDataResp.Body)
if err != nil {
return userData, bosherr.WrapError(err, "Reading user data response body")
}
err = json.Unmarshal(userDataBytes, &userData)
if err != nil {
return userData, bosherr.WrapError(err, "Unmarshalling user data")
}
return userData, nil
}
func (ms concreteMetadataService) resolveRegistryEndpoint(namedEndpoint string, nameServers []string) (string, error) {
registryURL, err := url.Parse(namedEndpoint)
if err != nil {
return "", bosherr.WrapError(err, "Parsing registry named endpoint")
}
registryHostAndPort := strings.Split(registryURL.Host, ":")
registryIP, err := ms.resolver.LookupHost(nameServers, registryHostAndPort[0])
if err != nil {
return "", bosherr.WrapError(err, "Looking up registry")
}
if len(registryHostAndPort) == 2 {
registryURL.Host = fmt.Sprintf("%s:%s", registryIP, registryHostAndPort[1])
} else {
registryURL.Host = registryIP
}
return registryURL.String(), nil
}