Skip to content

Commit 17c2efa

Browse files
authored
feat(router): label support (#199)
1 parent 69bdf03 commit 17c2efa

21 files changed

Lines changed: 704 additions & 228 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ See updating [Changelog example here](https://keepachangelog.com/en/1.0.0/)
77

88
### Added
99
- storage: possibility to control what to do with backups related to the storage that is about to be deleted
10+
- router: label support
11+
12+
## Deprecated
13+
- request: `ServerFilter` and `ServerGroupFilter` types will be replaced with `QueryFilter` type in the future
1014

1115
## [5.2.1]
1216

upcloud/network.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ type Router struct {
290290
Name string `json:"name"`
291291
Type string `json:"type"`
292292
UUID string `json:"uuid"`
293+
Labels []Label `json:"labels"`
293294
}
294295

295296
// UnmarshalJSON is a custom unmarshaller that deals with

upcloud/network_test.go

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -450,30 +450,35 @@ func TestUnmarshalRouters(t *testing.T) {
450450
// behaves correctly.
451451
func TestUnmarshalRouter(t *testing.T) {
452452
originalJSON := `
453-
{
453+
{
454454
"router": {
455-
"attached_networks": {
456-
"network": [
457-
{
458-
"uuid" : "03206c92-50f2-40b0-ad05-5f02cab2e932"
459-
},
460-
{
461-
"uuid" : "03d781c3-65e3-4a7a-b6cd-a7ce7e23b8c5"
462-
},
463-
{
464-
"uuid" : "03854a28-fafe-428f-964f-760cd1b83f1f"
465-
},
466-
{
467-
"uuid" : "03bae36d-a30a-4640-9a35-f2ccb0e2cddc"
468-
}
469-
]
455+
"attached_networks": {
456+
"network": [
457+
{
458+
"uuid" : "03206c92-50f2-40b0-ad05-5f02cab2e932"
459+
},
460+
{
461+
"uuid" : "03d781c3-65e3-4a7a-b6cd-a7ce7e23b8c5"
462+
},
463+
{
464+
"uuid" : "03854a28-fafe-428f-964f-760cd1b83f1f"
465+
},
466+
{
467+
"uuid" : "03bae36d-a30a-4640-9a35-f2ccb0e2cddc"
468+
}
469+
]
470470
},
471471
"name": "Example router",
472472
"type": "normal",
473-
"uuid": "04c0df35-2658-4b0c-8ac7-962090f4e92a"
473+
"uuid": "04c0df35-2658-4b0c-8ac7-962090f4e92a",
474+
"labels": [
475+
{
476+
"key": "managedBy",
477+
"value": "upcloud-go-sdk-unit-test"
478+
}
479+
]
474480
}
475-
}
476-
`
481+
}`
477482

478483
var router Router
479484
err := json.Unmarshal([]byte(originalJSON), &router)
@@ -497,6 +502,12 @@ func TestUnmarshalRouter(t *testing.T) {
497502
Name: "Example router",
498503
Type: "normal",
499504
UUID: "04c0df35-2658-4b0c-8ac7-962090f4e92a",
505+
Labels: LabelSlice{
506+
{
507+
Key: "managedBy",
508+
Value: "upcloud-go-sdk-unit-test",
509+
},
510+
},
500511
}
501512

502513
assert.Equal(t, testRouter, router)

upcloud/request/kubernetes.go

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,22 @@ func (r *GetKubernetesClustersRequest) RequestURL() string {
1919
return kubernetesClusterBasePath
2020
}
2121

22-
type KubernetesFilter interface {
23-
ToQueryParam() string
24-
}
22+
// Deprecated: KubernetesFilter filter is deprecated. Use QueryFilter instead.
23+
type KubernetesFilter = QueryFilter
2524

2625
// GetKubernetesClustersWithFiltersRequest represents a request to get all clusters
2726
// using labels or label keys as filters.
2827
// Using multiple filters returns only clusters that match all.
2928
type GetKubernetesClustersWithFiltersRequest struct {
30-
Filters []KubernetesFilter
29+
Filters []QueryFilter
3130
}
3231

3332
// RequestURL implements the Request interface.
3433
func (r *GetKubernetesClustersWithFiltersRequest) RequestURL() string {
3534
if len(r.Filters) == 0 {
3635
return kubernetesClusterBasePath
3736
}
38-
39-
params := ""
40-
for _, v := range r.Filters {
41-
if len(params) > 0 {
42-
params += "&"
43-
}
44-
params += v.ToQueryParam()
45-
}
46-
47-
return fmt.Sprintf("%s?%s", kubernetesClusterBasePath, params)
37+
return fmt.Sprintf("%s?%s", kubernetesClusterBasePath, encodeQueryFilters(r.Filters))
4838
}
4939

5040
// GetKubernetesClusterRequest represents a request to get a Kubernetes cluster details

upcloud/request/kubernetes_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ func TestKubernetes(t *testing.T) {
8989
expected := fmt.Sprintf(
9090
"%s?%s&%s",
9191
kubernetesClusterBasePath,
92-
"labels=managedBy",
93-
"labels=managedBy=upcloud-go-sdk-unit-test",
92+
"label=managedBy",
93+
"label=managedBy%3Dupcloud-go-sdk-unit-test",
9494
)
9595

9696
r := exampleGetKubernetesClustersWithFiltersRequest()

upcloud/request/label.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ type FilterLabel struct {
1111
}
1212

1313
func (l FilterLabel) ToQueryParam() string {
14-
return fmt.Sprintf("labels=%s=%s", l.Key, l.Value)
14+
return fmt.Sprintf("label=%s=%s", l.Key, l.Value)
1515
}
1616

1717
type FilterLabelKey struct {
1818
Key string
1919
}
2020

2121
func (k FilterLabelKey) ToQueryParam() string {
22-
return fmt.Sprintf("labels=%s", k.Key)
22+
return fmt.Sprintf("label=%s", k.Key)
2323
}

upcloud/request/network.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,21 @@ func (r ModifyNetworkInterfaceRequest) MarshalJSON() ([]byte, error) {
232232
return json.Marshal(&v)
233233
}
234234

235+
// GetRouterssequest represents a request to list routers.
236+
type GetRoutersRequest struct {
237+
Filters []QueryFilter
238+
}
239+
240+
func (r *GetRoutersRequest) RequestURL() string {
241+
basePath := "/router"
242+
243+
if len(r.Filters) == 0 {
244+
return basePath
245+
}
246+
247+
return fmt.Sprintf("%s?%s", basePath, encodeQueryFilters(r.Filters))
248+
}
249+
235250
// GetRouterDetailsRequest represents a request to get details about a single router.
236251
type GetRouterDetailsRequest struct {
237252
UUID string
@@ -244,7 +259,8 @@ func (r *GetRouterDetailsRequest) RequestURL() string {
244259

245260
// CreateRouterRequest represents a request to create a new router.
246261
type CreateRouterRequest struct {
247-
Name string `json:"name"`
262+
Name string `json:"name"`
263+
Labels []upcloud.Label `json:"labels,omitempty"`
248264
}
249265

250266
// RequestURL implements the Request interface.
@@ -266,9 +282,9 @@ func (r CreateRouterRequest) MarshalJSON() ([]byte, error) {
266282

267283
// ModifyRouterRequest represents a request to modify an existing router.
268284
type ModifyRouterRequest struct {
269-
UUID string `json:"-"`
270-
271-
Name string `json:"name"`
285+
UUID string `json:"-"`
286+
Name string `json:"name"`
287+
Labels *[]upcloud.Label `json:"labels,omitempty"`
272288
}
273289

274290
// RequestURL implements the Request interface.

upcloud/request/network_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,4 +320,24 @@ func TestMarshalModifyRouterRequest(t *testing.T) {
320320
assert.JSONEq(t, expectedJSON, string(actualJSON))
321321

322322
assert.Equal(t, "/router/foo", request.RequestURL())
323+
324+
request = ModifyRouterRequest{
325+
UUID: "",
326+
Name: "Modified router",
327+
Labels: &[]upcloud.Label{},
328+
}
329+
330+
expectedJSON = `
331+
{
332+
"router": {
333+
"name": "Modified router",
334+
"labels": []
335+
}
336+
}
337+
`
338+
339+
actualJSON, err = json.Marshal(&request)
340+
assert.NoError(t, err)
341+
342+
assert.JSONEq(t, expectedJSON, string(actualJSON))
323343
}

upcloud/request/request.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,26 @@
11
package request
22

3+
import "net/url"
4+
35
// Request is the interface for request objects
46
type Request interface {
57
// RequestURL returns the relative API URL for the request, excluding the API version.
68
RequestURL() string
79
}
10+
11+
type QueryFilter interface {
12+
ToQueryParam() string
13+
}
14+
15+
func encodeQueryFilters(f []QueryFilter) string {
16+
u := url.Values{}
17+
for _, v := range f {
18+
p, err := url.ParseQuery(v.ToQueryParam())
19+
if err == nil {
20+
for key := range p {
21+
u.Add(key, p.Get(key))
22+
}
23+
}
24+
}
25+
return u.Encode()
26+
}

upcloud/request/request_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package request
2+
3+
import (
4+
"testing"
5+
6+
"github.com/UpCloudLtd/upcloud-go-api/v5/upcloud"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestEncodeQueryFilters(t *testing.T) {
11+
want := "label=env%3Dprod&label=v2"
12+
got := encodeQueryFilters([]QueryFilter{
13+
FilterLabel{
14+
Label: upcloud.Label{
15+
Key: "env",
16+
Value: "prod",
17+
},
18+
},
19+
FilterLabelKey{Key: "v2"},
20+
})
21+
assert.Equal(t, want, got)
22+
}

0 commit comments

Comments
 (0)