-
Notifications
You must be signed in to change notification settings - Fork 149
/
cloud_controller_poller.go
121 lines (98 loc) · 2.69 KB
/
cloud_controller_poller.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
package main
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"plumbing"
"time"
"syslog_drain_binder/shared_types"
)
// PollOptions contains the options for the Poll function.
type PollOptions struct {
insecureSkipVerify bool
timeout time.Duration
}
// SkipCertVerify allows skipping of cert verification when polling.
func SkipCertVerify(s bool) func(*PollOptions) {
return func(o *PollOptions) {
o.insecureSkipVerify = s
}
}
// DefaultTimeout is the default http client timeout used when polling.
var DefaultTimeout = 5 * time.Second
// Timeout specifies the http client timeout when polling.
func Timeout(t time.Duration) func(*PollOptions) {
return func(o *PollOptions) {
o.timeout = t
}
}
// Poll gets all the app's syslog drain urls from the cloud controller.
func Poll(
urlBase string,
username string,
password string,
batchSize int,
options ...func(*PollOptions),
) (map[shared_types.AppID][]shared_types.DrainURL, error) {
drainURLs := make(map[shared_types.AppID][]shared_types.DrainURL)
nextID := 0
opts := PollOptions{
timeout: DefaultTimeout,
}
for _, o := range options {
o(&opts)
}
tlsConfig := plumbing.NewTLSConfig()
tlsConfig.InsecureSkipVerify = opts.insecureSkipVerify
tr := &http.Transport{
TLSClientConfig: tlsConfig,
DisableKeepAlives: true,
}
client := &http.Client{
Timeout: opts.timeout,
Transport: tr,
}
for {
url := buildUrl(urlBase, batchSize, nextID)
request, _ := http.NewRequest("GET", url, nil)
request.SetBasicAuth(username, password)
ccResponse, err := pollAndDecode(client, request)
if err != nil {
return drainURLs, err
}
for appID, urls := range ccResponse.Results {
drainURLs[appID] = urls
}
if ccResponse.NextID == nil {
break
}
nextID = *ccResponse.NextID
}
return drainURLs, nil
}
func pollAndDecode(client *http.Client, request *http.Request) (*cloudControllerResponse, error) {
response, err := client.Do(request)
if err != nil {
return nil, err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return nil, errors.New(fmt.Sprintf("Remote server error: %s", http.StatusText(response.StatusCode)))
}
decoder := json.NewDecoder(response.Body)
var ccResponse cloudControllerResponse
decoder.Decode(&ccResponse)
return &ccResponse, nil
}
type cloudControllerResponse struct {
Results map[shared_types.AppID][]shared_types.DrainURL `json:"results"`
NextID *int `json:"next_id"`
}
func buildUrl(baseURL string, batchSize int, nextID int) string {
url := fmt.Sprintf("%s/v2/syslog_drain_urls?batch_size=%d", baseURL, batchSize)
if nextID != 0 {
url = fmt.Sprintf("%s&next_id=%d", url, nextID)
}
return url
}