query-spec · diff

git:20260610.5ee9b17 to git:20260612.b890dfa

18 added, 9 removed. Audit A to A.

---
name: query-spec
description: "Filters, selects, and sorts Control Plane resources with the query spec language. Use when the user asks about targetQuery, memberQuery, cpln query commands, tag-based selection, property filtering, or dynamic location selection."
---
# Query Spec — Filtering & Sorting Resources
+ > **Tool availability:** some MCP tools named here live in the `full` toolset profile — if one is not advertised on this connection, tell the user to reconnect the MCP server with `?toolsets=full` (or use the `cpln` CLI fallback). Reads and deletes work on every profile via the generic `list_resources` / `get_resource` / `delete_resource` tools.
+
Control Plane has a universal query system for filtering and sorting resources. The same spec is used everywhere:
- **Policy** `targetQuery` — dynamically target resources by tags/properties (authored via `mcp__cpln__create_policy` / `mcp__cpln__update_policy`)
- **Group** `memberQuery` — dynamically assign users to groups (authored via `mcp__cpln__create_group` / `mcp__cpln__edit_group`)
- **GVC** `staticPlacement.locationQuery` — select locations by query instead of explicit `locationLinks` (authored via `mcp__cpln__create_gvc` / `mcp__cpln__update_gvc`)
- - **MCP list/query tools** — `mcp__cpln__list_resources` accepts the same `*_query` spec param to filter results for any kind (e.g. kind="workload", kind="secret", kind="identity", kind="policy"), plus `mcp__cpln__query_audit_events` and `mcp__cpln__query_metrics`. **Prefer these for ad-hoc filtering.**
- - **CLI** `cpln RESOURCE query` — fallback for the command line when the MCP server is unavailable
+ - **MCP tools do NOT take a query spec** — `mcp__cpln__list_resources` has no filter param; `mcp__cpln__query_audit_events` filters by kind/name/subject/context/time; `mcp__cpln__query_metrics` takes PromQL. In MCP manifests, query specs appear only inside the resource fields above.
+ - **CLI** `cpln RESOURCE query` — ad-hoc query-spec filtering from the command line
- **API** `POST /org/ORG/RESOURCE/-query` — filter via REST
## Query Structure
```yaml
kind: workload # resource kind to query
fetch: items # "items" (default) or "links"
spec:
match: all # "all", "any", or "none"
terms:
- op: "="
tag: environment
value: production
- op: "exists"
tag: monitored
sort:
by: name
order: asc
```
### Match Modes
| Mode | Behavior |
|:---|:---|
| `all` | Every term must match (default) |
| `any` | At least one term matches |
| `none` | No terms may match |
## Terms
Each term filters on exactly **one** of three fields (mutually exclusive):
| Field | What It Targets | Example |
|:---|:---|:---|
| `tag` | Resource tags (key-value labels) | `tag: environment`, `value: production` |
| `property` | Resource properties (name, description, etc.) | `property: name`, `value: my-app` |
| `rel` | Resource relationships | `rel: gvc`, `value: my-gvc` |
### Operators
| Operator | Category | Requires `value` | Description |
|:---|:---|:---:|:---|
| `=` | Equality | Yes | Exact match (default if `op` omitted) |
| `!=` | Equality | Yes | Not equal |
| `>` | Comparison | Yes | Greater than |
| `>=` | Comparison | Yes | Greater than or equal |
| `<` | Comparison | Yes | Less than |
| `<=` | Comparison | Yes | Less than or equal |
| `~` | Pattern | Yes | Regex match |
| `=~` | Pattern | Yes | Regex match (case-sensitive) |
| `contains` | String | Yes | Substring match |
| `exists` | Existence | No | Tag/property exists (any value) |
| `!exists` | Existence | No | Tag/property does not exist |
## Sorting
Optional. Only available via API/manifest (not exposed as CLI flags).
```yaml
sort:
by: name # required — field to sort by
order: asc # "asc" (default) or "desc"
```
### Common Sort Fields
Available for most resources: `id`, `name`, `version`, `description`, `created`, `lastModified`.
Resource-specific fields:
| Resource | Extra Sort Fields |
|:---|:---|
| **location** | `origin`, `provider`, `region` |
| **cloudaccount** | `provider` |
| **user** | `idp`, `email` |
| **policy** | `origin` |
| **group** | `origin` |
- ## MCP-First Filtering
+ ## Where Query Specs Apply (and Where They Don't)
- For ad-hoc filtering, pass the query spec to the list/query MCP tools rather than reaching for the CLI:
+ Query specs are a **resource-field language**, not a parameter the MCP list/query tools accept:
- - `mcp__cpln__list_resources` (for any kind — e.g. kind="workload", kind="secret", kind="identity", kind="policy") accepts a `*_query` spec param that takes the same `match` / `terms` / `sort` shape shown above.
- - `mcp__cpln__query_audit_events` filters the audit trail; `mcp__cpln__query_metrics` filters metric series.
+ - `mcp__cpln__list_resources` has NO query/filter param — it lists a kind (org/GVC scope, `limit`); filter the returned table yourself.
+ - `mcp__cpln__query_audit_events` filters by `kind`, `name`/`names`, `subject`, `context`, and a time window (`since` or `from`/`to`) — not by query spec.
+ - `mcp__cpln__query_metrics` takes PromQL (label matchers like `{workload="api"}`) — a different language entirely.
- The CLI shapes below are the fallback when the MCP server is unavailable or unauthenticated.
+ Query specs DO apply inside these resource fields, authored via the typed MCP tools:
- ## CLI Usage (Fallback)
+ - Policy `targetQuery` — `mcp__cpln__create_policy` / `mcp__cpln__update_policy`
+ - Group `memberQuery` — `mcp__cpln__create_group` / `mcp__cpln__edit_group`
+ - GVC `staticPlacement.locationQuery` — `mcp__cpln__create_gvc` / `mcp__cpln__update_gvc`
+ For ad-hoc query-spec filtering of resources, use the CLI (`cpln RESOURCE query`) or the `/-query` API endpoint below.
+
+ ## CLI Usage
+
Every resource kind supports `cpln RESOURCE query`:
```bash
# Filter workloads by tag
cpln workload query --tag environment=production
# Filter with multiple tags (match all)
cpln workload query --match all --tag environment=production --tag region=europe
# Filter by relation (e.g., workloads in a specific GVC)
cpln workload query --rel gvc=my-gvc
# Filter by property
cpln policy query --prop name=my-policy
# Existence check (tag exists, no value)
cpln workload query --tag monitored
# Combine tag + rel
cpln workload query --match all --rel gvc=emea --tag payment-service=true
# Match any of multiple GVCs
cpln workload query --match any --rel gvc=gvc-one --rel gvc=gvc-two
```
### CLI Query Flags
| Flag | Alias | Description |
|:---|:---|:---|
| `--match` | | Match mode: `all`, `any`, `none` (default: `all`) |
| `--tag` | | Filter by tag: `key=value` or just `key` for existence |
| `--property` | `--prop` | Filter by property: `key=value` |
| `--rel` | | Filter by relation: `key=value` |
`--tag`, `--property`, and `--rel` can be repeated to add multiple terms. `--match` accepts a single value.
**Resources supporting query:** agent, auditctx, cloudaccount, domain, group, gvc, identity, image, ipset, location, mk8s, org, policy, quota, secret, serviceaccount, task, user, volumeset, workload.
## API Usage (Fallback)
- When neither an MCP tool nor the CLI fits, every resource kind exposes a `/-query` POST endpoint:
+ When the CLI is unavailable, every resource kind exposes a `/-query` POST endpoint:
```
POST https://api.cpln.io/org/ORG_NAME/workload/-query
```
```json
{
"spec": {
"match": "all",
"terms": [
{ "op": "=", "tag": "region", "value": "emea" },
{ "rel": "gvc", "op": "=", "value": "mygvc" }
],
"sort": { "by": "name", "order": "asc" }
}
}
```
## Policy targetQuery
Policies can dynamically target resources instead of listing them explicitly in `targetLinks`:
```yaml
kind: policy
name: image-repo-policy
targetKind: image
targetQuery:
kind: image
fetch: items
spec:
match: all
terms:
- op: "="
property: repository
value: my-app
bindings:
- permissions:
- pull
- view
principalLinks:
- //group/developers
```
This policy automatically applies to any image whose `repository` property equals `my-app` — including images created after the policy.
## Group memberQuery
Groups can dynamically assign users based on user tags:
```yaml
kind: group
name: microsoft-users
memberQuery:
kind: user
fetch: items
spec:
match: all
terms:
- op: "="
tag: firebase/sign_in_provider
value: microsoft.com
```
**Dynamic membership works for users only.** Service accounts must be added directly via `memberLinks`.
## Validation Constraints
From the platform schema:
- Each term uses exactly one of `tag`, `property`, or `rel` (mutually exclusive)
- `value` is required for all operators except `exists` and `!exists`
- `value` accepts: string, number, boolean, or date (ISO format)
- Boolean values in tag terms are auto-converted to strings (`true` → `"true"`)
- Default `op` is `=` if omitted
- Default `match` is `all` if omitted
- Default `fetch` is `items`
- Default sort `order` is `asc`
## Documentation
For the latest reference, see:
- [Query Reference](https://docs.controlplane.com/core/query.md)
- [Logs Reference](https://docs.controlplane.com/core/logs.md)