Filter Language
Most Workshop API methods that begin with List (e.g., ListHosts,
ListRules, ListEvents) support filtering results using a standardized filter
language.
Overview
The filter system is:
- Generic: Works across all API types that support filtering
- Type-safe: Validates field names and types against the protobuf schema at runtime
- AIP-160 compliant: Based on Google's AIP-160 filtering standard
Filters are provided as a string in the filter field of List request messages:
message ListHostsRequest {
int32 page_size = 1;
int32 page = 2;
string filter = 3; // Filter expression goes here
string order_by = 4;
}
The fields available for filtering will match those in the type returned in
the response message. For example, the ListHostsResponse message looks like
this:
message ListHostsResponse {
repeated Host hosts = 1;
optional bool more = 2;
}
The fields available for filtering are those on the
Host
message:
message Host {
string uuid = 1;
string serial = 2;
string machine_model = 3;
// remaining fields elided for brevity
}
Basic Syntax
Simple Equality
hostname = 'example-host'
Comparison Operators
last_seen_client_mode > 1
last_seen_client_mode >= 1
last_seen_client_mode < 3
last_seen_client_mode <= 3
last_seen_client_mode != 2
String Pattern Matching (Case-Insensitive)
The : operator performs a case-insensitive pattern match (SQL ILIKE):
hostname:'r%' # Hostnames starting with 'r'
hostname:'%dev%' # Hostnames containing 'dev'
Boolean Logic
AND Operator
hostname = 'homer' AND last_seen_client_mode > 1
OR Operator
hostname = 'homer' OR hostname = 'marge'
NOT Operator
NOT (hostname = 'homer')
Operator Precedence
AND has higher precedence than OR. Use parentheses to control evaluation order:
tags_locked = true AND hostname = 'homer' OR hostname = 'marge'
# Evaluates as: (tags_locked = true AND hostname = 'homer') OR (hostname = 'marge')
Special Values
Boolean Literals
tags_locked = true
tags_locked = TRUE # Case-insensitive
tags_locked = false
tags_locked = FALSE
NULL Values
hostname = NULL # Becomes: hostname IS NULL
hostname != NULL # Becomes: hostname IS NOT NULL
Timestamp Fields
Timestamp fields can be compared using Unix timestamps (seconds since epoch):
rule_sync_time > 946688400 # After 2000-01-01 01:00:00 UTC
Current Time
Use NOW() to get the current timestamp:
rule_sync_time > NOW() # Rule sync time is in the future
Enum Fields
Enum fields can be queried by their string identifier or numeric value:
last_seen_client_mode = 'MONITOR' # Using enum identifier
last_seen_client_mode = 1 # Using numeric value
The filter system validates enum identifiers against the protobuf enum definition at runtime.
Repeated Fields
IN Operator with Repeated Fields
Check if a value exists within a repeated field:
IN('dev', tags) # Check if 'dev' is in the tags array
IN('prod', tags) # Check if 'prod' is in the tags array
IN Operator with Multiple Values
Check if a field matches any value in a list:
IN(hostname, 'homer', 'marge', 'bart')
IN(last_seen_client_mode, 1, 2)
IN(last_seen_client_mode, 'LOCKDOWN', 'STANDALONE')
Counting Array Elements
Use .count to get the number of elements in a repeated field:
tags.count > 0 # Has at least one tag
tags.count = 3 # Has exactly 3 tags
tags.count < 5 # Has fewer than 5 tags
Nested Fields
For message types that contain nested messages, use dot notation:
host.hostname = 'kvothe'
host.last_seen_client_mode = 'MONITOR'
Example with IN() on nested fields:
IN(host.hostname, 'kvothe', 'bast')
Complex Examples
Multiple Conditions
hostname:web% AND tags.count > 0 AND last_seen_client_mode = 'MONITOR'
Combining OR and AND
(hostname = 'web-1' OR hostname = 'web-2') AND tags_locked = false
Checking for Tagged Production Hosts
IN('prod', tags) AND hostname:prod-%
Type Safety
The filter system validates:
- Field existence: Referenced fields must exist in the protobuf message
- Field types: Argument types must match the field type
- Enum values: String enum identifiers must be valid for the enum type
- Repeated field operations:
.countcan only be used on repeated fields
Common Type Errors
# ERROR: Type mismatch (string vs int64)
hostname = 42
# ERROR: Type mismatch (enum vs float64)
last_seen_client_mode = 3.14
# ERROR: Type mismatch (bool vs int64)
tags_locked = 1
# ERROR: Invalid enum identifier
last_seen_client_mode = 'INVALID_MODE'
# ERROR: .count on non-repeated field
hostname.count > 1
Error Messages
When a filter fails validation, you'll receive an error describing the problem:
field "MissingField" referenced in filter does not exist or is not exported
type of argument 42 (int64) in filter isn't convertible to type of field "hostname" (StringKind)
argument FLARGLE is not valid for the enum santa.sync.v1.ClientMode
See Also
- AIP-160: Filtering - Google's API Improvement Proposal for filtering