Skip to content

Commit ea458bd

Browse files
committed
add farms implementation
1 parent 53cd60b commit ea458bd

File tree

1 file changed

+264
-19
lines changed

1 file changed

+264
-19
lines changed

node-registrar/client/farm.go

Lines changed: 264 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,306 @@
11
package client
22

3-
import "fmt"
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
8+
"net/url"
9+
"time"
10+
11+
"github.com/pkg/errors"
12+
)
413

514
var ErrorFarmNotFround = fmt.Errorf("failed to get requested farm from node regiatrar")
615

7-
func (c RegistrarClient) CreateFarm(farmName string, twinID uint64, dedicated bool) (farm Farm, err error) {
8-
return
16+
func (c RegistrarClient) CreateFarm(farmName string, twinID uint64, dedicated bool) (farmID uint64, err error) {
17+
return c.createFarm(farmName, twinID, dedicated)
918
}
1019

11-
func (c RegistrarClient) UpdateFarm(farmID uint64, farmName string) (err error) {
12-
return
20+
func (c RegistrarClient) UpdateFarm(farmID uint64, opts ...UpdateFarmOpts) (err error) {
21+
return c.updateFarm(farmID, opts)
1322
}
1423

1524
func (c RegistrarClient) GetFarm(id uint64) (farm Farm, err error) {
16-
return
25+
return c.getFarm(id)
1726
}
1827

19-
func (c RegistrarClient) ListFarms(opts ...FarmOpts) (farms []Farm, err error) {
20-
return
28+
func (c RegistrarClient) ListFarms(opts ...ListFarmOpts) (farms []Farm, err error) {
29+
return c.listFarms(opts...)
2130
}
2231

2332
type farmCfg struct {
24-
farmName string
25-
farmID uint64
26-
twinID uint64
27-
page uint32
28-
size uint32
33+
farmName string
34+
farmID uint64
35+
twinID uint64
36+
dedicated bool
37+
page uint32
38+
size uint32
2939
}
3040

31-
type FarmOpts func(*farmCfg)
41+
type (
42+
ListFarmOpts func(*farmCfg)
43+
UpdateFarmOpts func(*farmCfg)
44+
)
3245

33-
func FarmWithName(name string) FarmOpts {
46+
func ListFarmWithName(name string) ListFarmOpts {
3447
return func(n *farmCfg) {
3548
n.farmName = name
3649
}
3750
}
3851

39-
func FarmWithFarmID(id uint64) FarmOpts {
52+
func ListFarmWithFarmID(id uint64) ListFarmOpts {
4053
return func(n *farmCfg) {
4154
n.farmID = id
4255
}
4356
}
4457

45-
func FarmWithTwinID(id uint64) FarmOpts {
58+
func ListFarmWithTwinID(id uint64) ListFarmOpts {
4659
return func(n *farmCfg) {
4760
n.twinID = id
4861
}
4962
}
5063

51-
func FarmWithPage(page uint32) FarmOpts {
64+
func ListFarmWithDedicated() ListFarmOpts {
65+
return func(n *farmCfg) {
66+
n.dedicated = true
67+
}
68+
}
69+
70+
func ListFarmWithPage(page uint32) ListFarmOpts {
5271
return func(n *farmCfg) {
5372
n.page = page
5473
}
5574
}
5675

57-
func FarmWithSize(size uint32) FarmOpts {
76+
func ListFarmWithSize(size uint32) ListFarmOpts {
5877
return func(n *farmCfg) {
5978
n.size = size
6079
}
6180
}
81+
82+
func UpdateFarmWithName(name string) UpdateFarmOpts {
83+
return func(n *farmCfg) {
84+
n.farmName = name
85+
}
86+
}
87+
88+
func UpdateFarmWithDedicated() UpdateFarmOpts {
89+
return func(n *farmCfg) {
90+
n.dedicated = true
91+
}
92+
}
93+
94+
func (c RegistrarClient) createFarm(farmName string, twinID uint64, dedicated bool) (farmID uint64, err error) {
95+
url, err := url.JoinPath(c.baseURL, "farms")
96+
if err != nil {
97+
return farmID, errors.Wrap(err, "failed to construct registrar url")
98+
}
99+
100+
data := map[string]any{
101+
"farm_name": farmName,
102+
"twin_id": twinID,
103+
"dedicated": dedicated,
104+
}
105+
106+
var body bytes.Buffer
107+
err = json.NewEncoder(&body).Encode(data)
108+
if err != nil {
109+
return farmID, errors.Wrap(err, "failed to encode request body")
110+
}
111+
112+
req, err := http.NewRequest("POST", url, &body)
113+
if err != nil {
114+
return farmID, errors.Wrap(err, "failed to construct http request to the registrar")
115+
}
116+
117+
req.Header.Set("X-Auth", c.signRequest(time.Now().Unix()))
118+
req.Header.Set("Content-Type", "application/json")
119+
120+
resp, err := c.httpClient.Do(req)
121+
if err != nil {
122+
return farmID, errors.Wrap(err, "failed to send request to create farm")
123+
}
124+
125+
defer resp.Body.Close()
126+
127+
if resp.StatusCode != http.StatusCreated {
128+
err = parseResponseError(resp.Body)
129+
return farmID, fmt.Errorf("failed to create farm with status code %s", resp.Status)
130+
}
131+
132+
var result uint64
133+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
134+
return farmID, errors.Wrap(err, "failed to decode response body")
135+
}
136+
137+
return result, nil
138+
}
139+
140+
func (c RegistrarClient) updateFarm(farmID uint64, opts []UpdateFarmOpts) (err error) {
141+
url, err := url.JoinPath(c.baseURL, "farms", fmt.Sprint(farmID))
142+
if err != nil {
143+
return errors.Wrap(err, "failed to construct registrar url")
144+
}
145+
146+
var body bytes.Buffer
147+
data := parseUpdateFarmOpts(opts...)
148+
149+
err = json.NewEncoder(&body).Encode(data)
150+
if err != nil {
151+
return errors.Wrap(err, "failed to encode request body")
152+
}
153+
154+
req, err := http.NewRequest("PATCH", url, &body)
155+
if err != nil {
156+
return errors.Wrap(err, "failed to construct http request to the registrar")
157+
}
158+
159+
req.Header.Set("X-Auth", c.signRequest(time.Now().Unix()))
160+
req.Header.Set("Content-Type", "application/json")
161+
162+
resp, err := c.httpClient.Do(req)
163+
if err != nil {
164+
return errors.Wrap(err, "failed to send request to update farm")
165+
}
166+
167+
defer resp.Body.Close()
168+
169+
if resp.StatusCode != http.StatusOK {
170+
err = parseResponseError(resp.Body)
171+
return fmt.Errorf("failed to create farm with status code %s", resp.Status)
172+
}
173+
174+
var result uint64
175+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
176+
return errors.Wrap(err, "failed to decode response body")
177+
}
178+
179+
return
180+
}
181+
182+
func (c RegistrarClient) getFarm(id uint64) (farm Farm, err error) {
183+
url, err := url.JoinPath(c.baseURL, "farms", fmt.Sprint(id))
184+
if err != nil {
185+
return farm, errors.Wrap(err, "failed to construct registrar url")
186+
}
187+
resp, err := c.httpClient.Get(url)
188+
if err != nil {
189+
return farm, err
190+
}
191+
192+
if resp.StatusCode == http.StatusNotFound {
193+
return farm, ErrorFarmNotFround
194+
}
195+
196+
if resp.StatusCode != http.StatusOK {
197+
err = parseResponseError(resp.Body)
198+
return farm, errors.Wrapf(err, "failed to get farm with status code %s", resp.Status)
199+
}
200+
defer resp.Body.Close()
201+
202+
err = json.NewDecoder(resp.Body).Decode(&farm)
203+
if err != nil {
204+
return farm, err
205+
}
206+
207+
return
208+
}
209+
210+
func (c RegistrarClient) listFarms(opts ...ListFarmOpts) (farms []Farm, err error) {
211+
url, err := url.JoinPath(c.baseURL, "farms")
212+
if err != nil {
213+
return farms, errors.Wrap(err, "failed to construct registrar url")
214+
}
215+
216+
data := parseListFarmOpts(opts)
217+
218+
var body bytes.Buffer
219+
err = json.NewEncoder(&body).Encode(data)
220+
if err != nil {
221+
return farms, errors.Wrap(err, "failed to encode request body")
222+
}
223+
224+
req, err := http.NewRequest("GET", url, &body)
225+
if err != nil {
226+
return farms, errors.Wrap(err, "failed to construct http request to the registrar")
227+
}
228+
229+
resp, err := c.httpClient.Do(req)
230+
if err != nil {
231+
return farms, errors.Wrap(err, "failed to send request to list farm")
232+
}
233+
234+
if resp.StatusCode != http.StatusOK {
235+
err = parseResponseError(resp.Body)
236+
return farms, errors.Wrapf(err, "failed to get list farms with status code %s", resp.Status)
237+
}
238+
defer resp.Body.Close()
239+
err = json.NewDecoder(resp.Body).Decode(&farms)
240+
if err != nil {
241+
return farms, errors.Wrap(err, "failed to decode response body")
242+
}
243+
244+
return
245+
}
246+
247+
func parseListFarmOpts(opts []ListFarmOpts) map[string]any {
248+
cfg := farmCfg{
249+
farmName: "",
250+
farmID: 0,
251+
twinID: 0,
252+
dedicated: false,
253+
page: 1,
254+
size: 50,
255+
}
256+
257+
for _, opt := range opts {
258+
opt(&cfg)
259+
}
260+
261+
data := map[string]any{}
262+
263+
if len(cfg.farmName) != 0 {
264+
data["farm_name"] = cfg.farmName
265+
}
266+
267+
if cfg.farmID != 0 {
268+
data["farm_id"] = cfg.farmID
269+
}
270+
271+
if cfg.twinID != 0 {
272+
data["twin_id"] = cfg.twinID
273+
}
274+
275+
if cfg.dedicated {
276+
data["dedicated"] = true
277+
}
278+
279+
data["page"] = cfg.page
280+
data["size"] = cfg.size
281+
282+
return data
283+
}
284+
285+
func parseUpdateFarmOpts(opts ...UpdateFarmOpts) map[string]any {
286+
cfg := farmCfg{
287+
farmName: "",
288+
dedicated: false,
289+
}
290+
291+
for _, opt := range opts {
292+
opt(&cfg)
293+
}
294+
295+
data := map[string]any{}
296+
297+
if len(cfg.farmName) != 0 {
298+
data["farm_name"] = cfg.farmName
299+
}
300+
301+
if cfg.dedicated {
302+
data["dedicated"] = true
303+
}
304+
305+
return data
306+
}

0 commit comments

Comments
 (0)