-
Notifications
You must be signed in to change notification settings - Fork 2
Device search #146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Device search #146
Changes from all commits
f783062
759038c
37c8824
174c6c4
21da9dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,7 @@ type LabelsPutReq map[string]*string | |
| // @Description Requires scope: devices:read or devices:read-update | ||
| // @Tags Devices | ||
| // @Param _ query DeviceListOpts false "Sorting options" | ||
| // @Param label query []string false "Label filters in the format key.comparison.value (e.g. env.eq.production). Comparison operators: eq, ne, contains, ncontains. Multiple filters are ANDed together." | ||
| // @Accept json | ||
| // @Produce json | ||
| // @Success 200 {array} DeviceListItem | ||
|
|
@@ -52,6 +53,12 @@ func (h *handlers) deviceList(c echo.Context) error { | |
| return EchoError(c, err, http.StatusBadRequest, "Failed to parse list options") | ||
| } | ||
|
|
||
| if filters, err := parseLabelFilters(c.QueryParams()["label"]); err != nil { | ||
| return EchoError(c, err, http.StatusBadRequest, err.Error()) | ||
| } else { | ||
| opts.LabelFilters = filters | ||
| } | ||
|
|
||
| devices, total, err := h.storage.DevicesList(opts) | ||
| if err != nil { | ||
| return EchoError(c, err, http.StatusInternalServerError, "Unexpected error listing devices") | ||
|
|
@@ -61,6 +68,32 @@ func (h *handlers) deviceList(c echo.Context) error { | |
| return c.JSON(http.StatusOK, devices) | ||
| } | ||
|
|
||
| // parseLabelFilters parses query parameters of the form "key.comparison.value" | ||
| // into LabelFilter structs. The value may contain dots. | ||
| func parseLabelFilters(params []string) ([]storage.LabelFilter, error) { | ||
| if len(params) == 0 { | ||
| return nil, nil | ||
| } | ||
| filters := make([]storage.LabelFilter, 0, len(params)) | ||
| for _, p := range params { | ||
| // Split into at most 3 parts: key, comparison, value (value may contain dots) | ||
| parts := strings.SplitN(p, ".", 3) | ||
| if len(parts) != 3 { | ||
| return nil, fmt.Errorf("invalid label filter %q: expected format key.comparison.value", p) | ||
| } | ||
| f := storage.LabelFilter{ | ||
| Label: parts[0], | ||
| Comparison: storage.LabelComparison(parts[1]), | ||
| Value: parts[2], | ||
| } | ||
| if err := f.Validate(); err != nil { | ||
| return nil, err | ||
| } | ||
|
Comment on lines
+80
to
+91
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be beneficial to use some lexer, e.g. the participle library which allows defining the LabelFilter as below. TBH. I'm not sure how much benefit any lexer would give us. A simple split (as you did) seems sufficient to me, and in case if we switch to |
||
| filters = append(filters, f) | ||
| } | ||
| return filters, nil | ||
| } | ||
|
|
||
| func setPaginationHeaders(c echo.Context, opts storage.DeviceListOpts, total int) { | ||
| if opts.Limit <= 0 { | ||
| return | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, IIUC this requires the UI to pass multiple filters as multiple
label=x.y.z&label=a.b.cquery parameters (form style) and emphasizes on label filtering.Maybe, we should consider a more broad filtering like
filter=x.y.z,a.b.cextending beyond labels, and using a comma (or semicolon) as a separator for compactness (whatever separator the UI is currently using)?