Skip to main content

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:

  1. Field existence: Referenced fields must exist in the protobuf message
  2. Field types: Argument types must match the field type
  3. Enum values: String enum identifiers must be valid for the enum type
  4. Repeated field operations: .count can 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