aboutsummaryrefslogtreecommitdiff
path: root/echo/netbox/client.go
diff options
context:
space:
mode:
Diffstat (limited to 'echo/netbox/client.go')
-rw-r--r--echo/netbox/client.go169
1 files changed, 169 insertions, 0 deletions
diff --git a/echo/netbox/client.go b/echo/netbox/client.go
new file mode 100644
index 0000000..aabadc8
--- /dev/null
+++ b/echo/netbox/client.go
@@ -0,0 +1,169 @@
1package netbox
2
3import (
4 "encoding/json"
5 "fmt"
6 "io"
7 "net"
8 "net/http"
9 "net/url"
10 "strconv"
11
12 "code.crute.us/mcrute/golib/vault"
13)
14
15type NetboxClient interface {
16 GetSitePrefixesWithTag(site string, tag string) ([]*net.IPNet, error)
17 GetPrefixesWithTag(tag string) ([]*net.IPNet, error)
18}
19
20func NewNetboxClientDefault() NetboxClient {
21 return &netboxClient{
22 endpoint: "https://netbox.crute.me",
23 vaultMaterial: "infra/netbox-readonly",
24 }
25}
26
27func NewNetboxClient(endpoint string, vaultMaterial string) NetboxClient {
28 return &netboxClient{
29 endpoint: endpoint,
30 vaultMaterial: vaultMaterial,
31 }
32}
33
34type netboxClient struct {
35 endpoint string
36 vaultMaterial string
37}
38
39func (c *netboxClient) makeRequestRaw(method, u string, ib io.Reader, o interface{}) error {
40 apiKey, err := vault.GetVaultApiKey(c.vaultMaterial)
41 if err != nil {
42 return err
43 }
44
45 req, err := http.NewRequest(method, u, ib)
46 if err != nil {
47 return err
48 }
49 req.Header.Add("Authorization", fmt.Sprintf("Token %s", apiKey))
50
51 res, err := http.DefaultClient.Do(req)
52 if err != nil {
53 return err
54 }
55 defer res.Body.Close()
56
57 if err = json.NewDecoder(res.Body).Decode(o); err != nil {
58 return err
59 }
60
61 return nil
62}
63
64func (c *netboxClient) makeRequest(method, path string, q url.Values, ib io.Reader, o interface{}) error {
65 u, err := url.Parse(c.endpoint)
66 if err != nil {
67 return err
68 }
69 u.Path = path
70 u.RawQuery = q.Encode()
71
72 return c.makeRequestRaw(method, u.String(), ib, o)
73}
74
75func (c *netboxClient) GetSitePrefixesWithTag(site string, tag string) ([]*net.IPNet, error) {
76 s, err := c.resolveSiteNameToId(site)
77 if err != nil {
78 return nil, err
79 }
80
81 out := []*net.IPNet{}
82
83 q := url.Values{}
84 q.Add("site_id", strconv.Itoa(s))
85 q.Add("tag", tag)
86
87 page := &PrefixList{}
88 if err := c.makeRequest(http.MethodGet, "/api/ipam/prefixes/", q, nil, page); err != nil {
89 return nil, err
90 }
91
92 for _, r := range page.Results {
93 _, ipnet, err := net.ParseCIDR(r.Prefix)
94 if err != nil {
95 return nil, err
96 }
97 out = append(out, ipnet)
98 }
99
100 for page.Next != "" {
101 page = &PrefixList{}
102 if err := c.makeRequestRaw(http.MethodGet, page.Next, nil, page); err != nil {
103 return nil, err
104 }
105
106 for _, r := range page.Results {
107 _, ipnet, err := net.ParseCIDR(r.Prefix)
108 if err != nil {
109 return nil, err
110 }
111 out = append(out, ipnet)
112 }
113 }
114
115 return out, nil
116}
117
118func (c *netboxClient) GetPrefixesWithTag(tag string) ([]*net.IPNet, error) {
119 out := []*net.IPNet{}
120
121 q := url.Values{}
122 q.Add("tag", tag)
123
124 page := &PrefixList{}
125 if err := c.makeRequest(http.MethodGet, "/api/ipam/prefixes/", q, nil, page); err != nil {
126 return nil, err
127 }
128
129 for _, r := range page.Results {
130 _, ipnet, err := net.ParseCIDR(r.Prefix)
131 if err != nil {
132 return nil, err
133 }
134 out = append(out, ipnet)
135 }
136
137 for page.Next != "" {
138 page = &PrefixList{}
139 if err := c.makeRequestRaw(http.MethodGet, page.Next, nil, page); err != nil {
140 return nil, err
141 }
142
143 for _, r := range page.Results {
144 _, ipnet, err := net.ParseCIDR(r.Prefix)
145 if err != nil {
146 return nil, err
147 }
148 out = append(out, ipnet)
149 }
150 }
151
152 return out, nil
153}
154
155func (c *netboxClient) resolveSiteNameToId(s string) (int, error) {
156 q := url.Values{}
157 q.Add("name", s)
158
159 out := &SiteList{}
160 if err := c.makeRequest(http.MethodGet, "/api/dcim/sites/", q, nil, out); err != nil {
161 return 0, err
162 }
163
164 if len(out.Results) == 0 {
165 return 0, fmt.Errorf("resolveSiteNameToId: no results returned from netbox")
166 }
167
168 return out.Results[0].ID, nil
169}