forked from Kong/go-kong
/
listeners.go
115 lines (99 loc) · 4.35 KB
/
listeners.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
package kong
import (
"context"
"encoding/json"
"fmt"
"github.com/mitchellh/mapstructure"
)
// -----------------------------------------------------------------------------
// Kong Listeners - Public Types
// -----------------------------------------------------------------------------
// ProxyListener is a configured listener on the Kong Gateway for L7 routing.
type ProxyListener struct {
SSL bool `json:"ssl" mapstructure:"ssl"`
Listener string `json:"listener" mapstructure:"listener"`
Port int `json:"port" mapstructure:"port"`
Bind bool `json:"bind" mapstructure:"bind"`
IP string `json:"ip" mapstructure:"ip"`
HTTP2 bool `json:"http2" mapstructure:"http2"`
ProxyProtocol bool `json:"proxy_protocol" mapstructure:"proxy_protocol"`
Deferred bool `json:"deferred" mapstructure:"deferred"`
ReusePort bool `json:"reuseport" mapstructure:"reuseport"`
Backlog bool `json:"backlog=%d+" mapstructure:"backlog=%d+"`
}
// StreamListener is a configured listener on the Kong Gateway for L4 routing.
type StreamListener struct {
UDP bool `json:"udp" mapstructure:"udp"`
SSL bool `json:"ssl" mapstructure:"ssl"`
ProxyProtocol bool `json:"proxy_protocol" mapstructure:"proxy_protocol"`
IP string `json:"ip" mapstructure:"ip"`
Listener string `json:"listener" mapstructure:"listener"`
Port int `json:"port" mapstructure:"port"`
Bind bool `json:"bind" mapstructure:"bind"`
ReusePort bool `json:"reuseport" mapstructure:"reuseport"`
Backlog bool `json:"backlog=%d+" mapstructure:"backlog=%d+"`
}
// -----------------------------------------------------------------------------
// Kong Listeners - Client Methods
// -----------------------------------------------------------------------------
// Listeners returns the proxy_listeners and stream_listeners that are currently configured in the
// Kong root as convenient native types rather than JSON or unstructured.
func (c *Client) Listeners(ctx context.Context) ([]ProxyListener, []StreamListener, error) {
rootJSON, err := c.RootJSON(ctx)
if err != nil {
return nil, nil, fmt.Errorf("couldn't get root JSON when trying to determine listeners: %w", err)
}
root := dataPlaneConfigWrapper{}
if err := json.Unmarshal(rootJSON, &root); err != nil {
return nil, nil, fmt.Errorf("couldn't decode root JSON when trying to determine listeners: %w", err)
}
return root.Config.ProxyListeners, root.Config.StreamListeners, nil
}
// -----------------------------------------------------------------------------
// Kong Listeners - Private Wrapper Types
// -----------------------------------------------------------------------------
type dataPlaneConfigWrapper struct {
Config dataPlaneConfig `json:"configuration"`
}
type dataPlaneConfig struct {
ProxyListeners []ProxyListener `json:"proxy_listeners"`
StreamListeners []StreamListener `json:"stream_listeners"`
}
// UnmarshalJSON implements custom JSON unmarshaling for this type which must
// be done because the Kong Admin API will return empty objects when a list
// is empty which will confuse the default unmarshaler.
func (d *dataPlaneConfig) UnmarshalJSON(data []byte) error {
wrapper := make(map[string]interface{})
if err := json.Unmarshal(data, &wrapper); err != nil {
return err
}
proxyListenersRaw, ok := wrapper["proxy_listeners"]
if ok {
listeners, ok := proxyListenersRaw.([]interface{})
if ok {
d.ProxyListeners = make([]ProxyListener, 0, len(listeners))
for _, listener := range listeners {
proxyListener := ProxyListener{}
if err := mapstructure.Decode(listener, &proxyListener); err != nil {
return err
}
d.ProxyListeners = append(d.ProxyListeners, proxyListener)
}
}
}
streamListenersRaw, ok := wrapper["stream_listeners"]
if ok {
listeners, ok := streamListenersRaw.([]interface{})
if ok {
d.StreamListeners = make([]StreamListener, 0, len(listeners))
for _, listener := range listeners {
streamListener := StreamListener{}
if err := mapstructure.Decode(listener, &streamListener); err != nil {
return err
}
d.StreamListeners = append(d.StreamListeners, streamListener)
}
}
}
return nil
}