mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: allow search by build params in workspace search filter (#12694)
* chore: workspace search filter allow search by params * has_param will return all workspaces with the param existance * exact matching
This commit is contained in:
@@ -121,6 +121,40 @@ func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectT
|
||||
Valid: values.Has("outdated"),
|
||||
}
|
||||
|
||||
type paramMatch struct {
|
||||
name string
|
||||
value *string
|
||||
}
|
||||
// parameter matching takes the form of:
|
||||
// `param:<name>[=<value>]`
|
||||
// If the value is omitted, then we match on the presence of the parameter.
|
||||
// If the value is provided, then we match on the parameter and value.
|
||||
params := httpapi.ParseCustomList(parser, values, []paramMatch{}, "param", func(v string) (paramMatch, error) {
|
||||
// Ignore excess spaces
|
||||
v = strings.TrimSpace(v)
|
||||
parts := strings.Split(v, "=")
|
||||
if len(parts) == 1 {
|
||||
// Only match on the presence of the parameter
|
||||
return paramMatch{name: parts[0], value: nil}, nil
|
||||
}
|
||||
if len(parts) == 2 {
|
||||
if parts[1] == "" {
|
||||
return paramMatch{}, xerrors.Errorf("query element %q has an empty value. omit the '=' to match just on the parameter name", v)
|
||||
}
|
||||
// Match on the parameter and value
|
||||
return paramMatch{name: parts[0], value: &parts[1]}, nil
|
||||
}
|
||||
return paramMatch{}, xerrors.Errorf("query element %q can only contain 1 '='", v)
|
||||
})
|
||||
for _, p := range params {
|
||||
if p.value == nil {
|
||||
filter.HasParam = append(filter.HasParam, p.name)
|
||||
continue
|
||||
}
|
||||
filter.ParamNames = append(filter.ParamNames, p.name)
|
||||
filter.ParamValues = append(filter.ParamValues, *p.value)
|
||||
}
|
||||
|
||||
parser.ErrorExcessParams(values)
|
||||
return filter, parser.Errors
|
||||
}
|
||||
|
||||
@@ -137,7 +137,74 @@ func TestSearchWorkspace(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ParamName",
|
||||
Query: "param:foo",
|
||||
Expected: database.GetWorkspacesParams{
|
||||
HasParam: []string{"foo"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MultipleParamNames",
|
||||
Query: "param:foo param:bar param:baz",
|
||||
Expected: database.GetWorkspacesParams{
|
||||
HasParam: []string{"foo", "bar", "baz"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ParamValue",
|
||||
Query: "param:foo=bar",
|
||||
Expected: database.GetWorkspacesParams{
|
||||
ParamNames: []string{"foo"},
|
||||
ParamValues: []string{"bar"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "QuotedParamValue",
|
||||
Query: `param:"image=ghcr.io/coder/coder-preview:main"`,
|
||||
Expected: database.GetWorkspacesParams{
|
||||
ParamNames: []string{"image"},
|
||||
ParamValues: []string{"ghcr.io/coder/coder-preview:main"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MultipleParamValues",
|
||||
Query: "param:foo=bar param:fuzz=buzz",
|
||||
Expected: database.GetWorkspacesParams{
|
||||
ParamNames: []string{"foo", "fuzz"},
|
||||
ParamValues: []string{"bar", "buzz"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MixedParams",
|
||||
Query: "param:dot param:foo=bar param:fuzz=buzz param:tot",
|
||||
Expected: database.GetWorkspacesParams{
|
||||
HasParam: []string{"dot", "tot"},
|
||||
ParamNames: []string{"foo", "fuzz"},
|
||||
ParamValues: []string{"bar", "buzz"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ParamSpaces",
|
||||
Query: `param:" dot " param:" foo=bar "`,
|
||||
Expected: database.GetWorkspacesParams{
|
||||
HasParam: []string{"dot"},
|
||||
ParamNames: []string{"foo"},
|
||||
ParamValues: []string{"bar"},
|
||||
},
|
||||
},
|
||||
|
||||
// Failures
|
||||
{
|
||||
Name: "ParamExcessValue",
|
||||
Query: "param:foo=bar=baz",
|
||||
ExpectedErrorContains: "can only contain 1 '='",
|
||||
},
|
||||
{
|
||||
Name: "ParamNoValue",
|
||||
Query: "param:foo=",
|
||||
ExpectedErrorContains: "omit the '=' to match",
|
||||
},
|
||||
{
|
||||
Name: "NoPrefix",
|
||||
Query: `:foo`,
|
||||
@@ -163,6 +230,11 @@ func TestSearchWorkspace(t *testing.T) {
|
||||
Query: `foo:bar`,
|
||||
ExpectedErrorContains: `"foo" is not a valid query param`,
|
||||
},
|
||||
{
|
||||
Name: "ParamExtraColons",
|
||||
Query: "param:foo:value",
|
||||
ExpectedErrorContains: "can only contain 1 ':'",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
@@ -182,6 +254,10 @@ func TestSearchWorkspace(t *testing.T) {
|
||||
// nil slice vs 0 len slice is equivalent for our purposes.
|
||||
c.Expected.WorkspaceIds = values.WorkspaceIds
|
||||
}
|
||||
if len(c.Expected.HasParam) == len(values.HasParam) {
|
||||
// nil slice vs 0 len slice is equivalent for our purposes.
|
||||
c.Expected.HasParam = values.HasParam
|
||||
}
|
||||
assert.Len(t, errs, 0, "expected no error")
|
||||
assert.Equal(t, c.Expected, values, "expected values")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user