Skip to content

fix: coderd: decouple ttl and deadline #2282

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

Merged
merged 11 commits into from
Jun 14, 2022
Prev Previous commit
Merge remote-tracking branch 'origin/main' into cj/2229/decouple-ws-d…
…eadline-from-ttl-again
  • Loading branch information
johnstcn committed Jun 14, 2022
commit feef82388e90a05cfec10d562ea50392c50c32bd
78 changes: 78 additions & 0 deletions coderd/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,84 @@ func validWorkspaceSchedule(s *string, min time.Duration) (sql.NullString, error
}, nil
}

// workspaceSearchQuery takes a query string and returns the workspace filter.
// It also can return the list of validation errors to return to the api.
func workspaceSearchQuery(query string) (database.GetWorkspacesWithFilterParams, []httpapi.Error) {
searchParams := make(url.Values)
if query == "" {
// No filter
return database.GetWorkspacesWithFilterParams{}, nil
}
// Because we do this in 2 passes, we want to maintain quotes on the first
// pass.Further splitting occurs on the second pass and quotes will be
// dropped.
elements := splitQueryParameterByDelimiter(query, ' ', true)
for _, element := range elements {
parts := splitQueryParameterByDelimiter(element, ':', false)
switch len(parts) {
case 1:
// No key:value pair. It is a workspace name, and maybe includes an owner
parts = splitQueryParameterByDelimiter(element, '/', false)
switch len(parts) {
case 1:
searchParams.Set("name", parts[0])
case 2:
searchParams.Set("owner", parts[0])
searchParams.Set("name", parts[1])
default:
return database.GetWorkspacesWithFilterParams{}, []httpapi.Error{
{Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 '/'", element)},
}
}
case 2:
searchParams.Set(parts[0], parts[1])
default:
return database.GetWorkspacesWithFilterParams{}, []httpapi.Error{
{Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 ':'", element)},
}
}
}

// Using the query param parser here just returns consistent errors with
// other parsing.
parser := httpapi.NewQueryParamParser()
filter := database.GetWorkspacesWithFilterParams{
Deleted: false,
OwnerUsername: parser.String(searchParams, "", "owner"),
TemplateName: parser.String(searchParams, "", "template"),
Name: parser.String(searchParams, "", "name"),
}

return filter, parser.Errors
}

// splitQueryParameterByDelimiter takes a query string and splits it into the individual elements
// of the query. Each element is separated by a delimiter. All quoted strings are
// kept as a single element.
//
// Although all our names cannot have spaces, that is a validation error.
// We should still parse the quoted string as a single value so that validation
// can properly fail on the space. If we do not, a value of `template:"my name"`
// will search `template:"my name:name"`, which produces an empty list instead of
// an error.
// nolint:revive
func splitQueryParameterByDelimiter(query string, delimiter rune, maintainQuotes bool) []string {
quoted := false
parts := strings.FieldsFunc(query, func(r rune) bool {
if r == '"' {
quoted = !quoted
}
return !quoted && r == delimiter
})
if !maintainQuotes {
for i, part := range parts {
parts[i] = strings.Trim(part, "\"")
}
}

return parts
}

func min(x, y int64) int64 {
if x < y {
return x
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.