Skip to content

Commit 7f11858

Browse files
authored
Refactor filtering implementation (#7)
Refactor filtering implementation to resolve #6. We couldn't continue using `map`, as it does not allow filtering on multiple values of the same field (i.e., use `OR`) as per [documentation](https://backstage.io/docs/features/software-catalog/software-catalog-api/#filtering).
2 parents 10fc17b + aaa199b commit 7f11858

File tree

9 files changed

+35
-94
lines changed

9 files changed

+35
-94
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@ the low-level details of making HTTP requests and parsing responses, allowing de
1515
With Go installed, run the following to add the package to your project, along with its dependencies:
1616

1717
```bash
18-
go get github.com/tdabasinskas/go-backstage@v1
18+
go get github.com/tdabasinskas/go-backstage/v2
1919
```
2020

2121
Alternatively, you can add import the package as following and run `go get` to install it:
2222

2323
```go
24-
import "github.com/tdabasinskas/go-backstage"
24+
import "github.com/tdabasinskas/go-backstage/v2"
2525
```
2626

2727
## Usage
2828

2929
Add the package to your project as following:
3030

3131
```go
32-
import "github.com/tdabasinskas/go-backstage"
32+
import "github.com/tdabasinskas/go-backstage/v2"
3333
```
3434

3535
Once imported, create a new Backstage API client to access different parts of Backstage API:
@@ -49,7 +49,7 @@ The client than can be used to access different parts of the API, e.g. get the l
4949

5050
```go
5151
entities, response, err := c.Catalog.Entities.s.List(context.Background(), &ListEntityOptions{
52-
Filters: ListEntityFilter{},
52+
Filters: []string{},
5353
Fields: []string{},
5454
Order: []ListEntityOrder{{ Direction: OrderDescending, Field: "metadata.name" },
5555
},

backstage/entity.go

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
package backstage
22

33
import (
4-
"bytes"
54
"context"
65
"errors"
76
"fmt"
87
"net/http"
98
"net/url"
10-
"sort"
119
"strings"
1210
)
1311

@@ -110,9 +108,6 @@ type EntityRelationTarget struct {
110108
Namespace string `json:"namespace"`
111109
}
112110

113-
// ListEntityFilter defines a condition that can be used to filter entities.
114-
type ListEntityFilter map[string]string
115-
116111
// ListEntityOrder defines a condition that can be used to order entities.
117112
type ListEntityOrder struct {
118113
// Direction is the direction to order by.
@@ -125,7 +120,7 @@ type ListEntityOrder struct {
125120
// ListEntityOptions specifies the optional parameters to the catalogService.List method.
126121
type ListEntityOptions struct {
127122
// Filters is a set of conditions that can be used to filter entities.
128-
Filters ListEntityFilter
123+
Filters []string
129124

130125
// Fields is a set of fields that can be used to limit the response.
131126
Fields []string
@@ -174,8 +169,8 @@ func (s *entityService) List(ctx context.Context, options *ListEntityOptions) ([
174169

175170
values := u.Query()
176171
if options != nil {
177-
if options.Filters != nil && len(options.Filters) > 0 {
178-
values.Add("filter", options.Filters.string())
172+
for _, f := range options.Filters {
173+
values.Add("filter", f)
179174
}
180175

181176
if options.Fields != nil && len(options.Fields) > 0 {
@@ -240,26 +235,6 @@ func (s *typedEntityService[T]) get(ctx context.Context, t string, n string, ns
240235
return entity, resp, err
241236
}
242237

243-
// string returns a string representation of the ListEntityFilter.
244-
func (f *ListEntityFilter) string() string {
245-
sortedKeys := make([]string, 0, len(*f))
246-
for key := range *f {
247-
sortedKeys = append(sortedKeys, key)
248-
}
249-
sort.Strings(sortedKeys)
250-
251-
var b bytes.Buffer
252-
for _, k := range sortedKeys {
253-
if (*f)[k] != "" {
254-
b.WriteString(fmt.Sprintf("%s=%s,", k, (*f)[k]))
255-
} else {
256-
b.WriteString(fmt.Sprintf("%s,", k))
257-
}
258-
}
259-
260-
return strings.TrimSuffix(b.String(), ",")
261-
}
262-
263238
// string returns a string representation of the ListEntityOrder.
264239
func (o *ListEntityOrder) string() (string, error) {
265240
if o.Direction != OrderAscending && o.Direction != OrderDescending {

backstage/entity_test.go

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,7 @@ func TestEntityServiceList_Filter(t *testing.T) {
9696
s := newEntityService(newCatalogService(c))
9797

9898
actual, resp, err := s.List(context.Background(), &ListEntityOptions{
99-
Filters: ListEntityFilter{
100-
"kind": "User",
101-
},
99+
Filters: []string{"kind=User"},
102100
})
103101
assert.NoError(t, err, "Get should not return an error")
104102
assert.NotEmpty(t, resp, "Response should not be empty")
@@ -129,7 +127,6 @@ func TestEntityServiceList_Fields(t *testing.T) {
129127
s := newEntityService(newCatalogService(c))
130128

131129
actual, resp, err := s.List(context.Background(), &ListEntityOptions{
132-
Filters: ListEntityFilter{},
133130
Fields: []string{
134131
"metadata.name",
135132
},
@@ -163,7 +160,6 @@ func TestEntityServiceList_Order(t *testing.T) {
163160
s := newEntityService(newCatalogService(c))
164161

165162
actual, resp, err := s.List(context.Background(), &ListEntityOptions{
166-
Filters: ListEntityFilter{},
167163
Order: []ListEntityOrder{
168164
{
169165
Direction: OrderDescending,
@@ -182,7 +178,6 @@ func TestEntityServiceList_InvalidOrder(t *testing.T) {
182178
s := newEntityService(newCatalogService(c))
183179

184180
_, _, err := s.List(context.Background(), &ListEntityOptions{
185-
Filters: ListEntityFilter{},
186181
Order: []ListEntityOrder{
187182
{
188183
Direction: "InvalidOrder",
@@ -213,51 +208,6 @@ func TestEntityServiceDelete(t *testing.T) {
213208
assert.EqualValues(t, http.StatusNoContent, resp.StatusCode, "Response status code should match the one from the server")
214209
}
215210

216-
// TestListEntityFilterString tests if list entity filter string is correctly generated.
217-
func TestListEntityFilterString(t *testing.T) {
218-
tests := []struct {
219-
name string
220-
filter ListEntityFilter
221-
expected string
222-
}{
223-
{
224-
name: "empty filter",
225-
filter: ListEntityFilter{},
226-
expected: "",
227-
},
228-
{
229-
name: "filter with one key-value pair",
230-
filter: ListEntityFilter{
231-
"key1": "value1",
232-
},
233-
expected: "key1=value1",
234-
},
235-
{
236-
name: "filter with one key and no value",
237-
filter: ListEntityFilter{
238-
"key1": "",
239-
},
240-
expected: "key1",
241-
},
242-
{
243-
name: "filter with multiple key-value pairs",
244-
filter: ListEntityFilter{
245-
"key1": "value1",
246-
"key2": "value2",
247-
"key3": "",
248-
},
249-
expected: "key1=value1,key2=value2,key3",
250-
},
251-
}
252-
253-
for _, test := range tests {
254-
t.Run(test.name, func(t *testing.T) {
255-
actual := test.filter.string()
256-
assert.Equal(t, test.expected, actual, "List entity filter string should match expected value")
257-
})
258-
}
259-
}
260-
261211
// TestListEntityOrderString tests if list entity order string is correctly generated.
262212
func TestListEntityOrderString(t *testing.T) {
263213
tests := []struct {

examples/entities/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ module exampleentities
22

33
go 1.20
44

5-
replace github.com/tdabasinskas/go-backstage => ../..
5+
replace github.com/tdabasinskas/go-backstage/v2 => ../..
66

7-
require github.com/tdabasinskas/go-backstage v0.0.0-20230117064629-2a4ac9398d92
7+
require github.com/tdabasinskas/go-backstage/v2 v2.0.0-preview.2

examples/entities/go.sum

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/entities/main.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ package main
22

33
import (
44
"context"
5+
"github.com/tdabasinskas/go-backstage/v2/backstage"
56
"log"
67
"os"
7-
8-
"github.com/tdabasinskas/go-backstage/backstage"
98
)
109

1110
func main() {
@@ -26,15 +25,26 @@ func main() {
2625

2726
log.Println("Getting component entities...")
2827
if entities, _, err := c.Catalog.Entities.List(context.Background(), &backstage.ListEntityOptions{
29-
Filters: backstage.ListEntityFilter{
30-
"kind": "component",
31-
},
28+
Filters: []string{"kind=component"},
3229
}); err != nil {
3330
log.Fatal(err)
3431
} else {
3532
log.Printf("Component entities: %v", entities)
3633
}
3734

35+
log.Println("Getting location, API and component entities...")
36+
if entities, _, err := c.Catalog.Entities.List(context.Background(), &backstage.ListEntityOptions{
37+
Filters: []string{
38+
"kind=component",
39+
"kind=location",
40+
"kind=api",
41+
},
42+
}); err != nil {
43+
log.Fatal(err)
44+
} else {
45+
log.Printf("Component, location and API entities: %v", entities)
46+
}
47+
3848
log.Println("Getting specific component entity by UID...")
3949
if entity, _, err := c.Catalog.Entities.Get(context.Background(), "06f15cc8-b6b4-4e44-a9bd-1579029f8fb7"); err != nil {
4050
log.Fatal(err)

examples/locations/go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ module examplelocations
22

33
go 1.20
44

5-
replace github.com/tdabasinskas/go-backstage => ../..
5+
replace github.com/tdabasinskas/go-backstage/v2 => ../..
66

7-
require github.com/tdabasinskas/go-backstage v0.0.0-20230117064629-2a4ac9398d92
7+
require github.com/tdabasinskas/go-backstage/v2 v2.0.0-preview.2

examples/locations/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"net/http"
77
"os"
88

9-
"github.com/tdabasinskas/go-backstage/backstage"
9+
"github.com/tdabasinskas/go-backstage/v2/backstage"
1010
)
1111

1212
func main() {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module github.com/tdabasinskas/go-backstage
1+
module github.com/tdabasinskas/go-backstage/v2
22

33
go 1.20
44

0 commit comments

Comments
 (0)