From 7469cadb2129ca1aa8be925dede5f7e4944100b0 Mon Sep 17 00:00:00 2001 From: Daniel Vallance Date: Thu, 11 Jun 2026 20:06:23 +0100 Subject: [PATCH] feat(pages/cli): Added "Fields" page to CLI docs This will explain the field model, and describe to the user how it can be used to sort and filter output, as well as edit instances. Closes: TOOL-1032 Signed-off-by: Daniel Vallance --- pages/cli/fields.mdx | 376 +++++++++++++++++++++++ pages/cli/filters.mdx | 163 ---------- pages/tutorials/kraftkit-to-unikraft.mdx | 6 +- zudoku.config.tsx | 2 +- 4 files changed, 380 insertions(+), 167 deletions(-) create mode 100644 pages/cli/fields.mdx delete mode 100644 pages/cli/filters.mdx diff --git a/pages/cli/fields.mdx b/pages/cli/fields.mdx new file mode 100644 index 0000000..e03ee2a --- /dev/null +++ b/pages/cli/fields.mdx @@ -0,0 +1,376 @@ +--- +title: Fields +description: Display, sort, filter, and edit resource fields in the unikraft CLI +navigation_icon: table +--- + +Every resource in the `unikraft` CLI (instances, images, services, volumes, and so on) is described by a set of **fields**. +Fields are the named pieces of data the platform stores about a resource, such as its `name`, `state`, `image`, or memory `resources`. +The same fields power table output, sorting, filtering, and editing, so once you learn a resource's field names you can use them everywhere. + +This page covers what fields are, how to control which fields are shown, how to sort and filter on them, and how to edit them with `edit`. + +## The field model + +To see the full field model for a resource, inspect it with `get`. +The output is a tree of fields, where some fields are scalars and others are nested objects or lists. + +```console +$ unikraft instance get httpserver-rust175-tokio-ngh8r +metro: fra +name: httpserver-rust175-tokio-ngh8r +uuid: 78ad8c05-ed7a-4886-abd3-07613dce7c28 +state: standby +image: /httpserver-rust175-tokio +resources: + memory: 256MiB + vcpus: 1 +service: + name: nameless-silence-donj1yl2 + uuid: cd2910d2-b709-410c-9e04-f5539a7d020a + domains: + - fqdn: nameless-silence-donj1yl2.fra.unikraft.app +networks: +- uuid: d8700d21-63c0-448a-806d-54014584b082 + private-ip: 10.0.0.25 + mac: 12:b0:0a:00:00:19 +timestamps: + created: 1 day ago +scale-to-zero: + enabled: true + policy: on + cooldown-time: 1s +stop: + reason: platform stop + exit-code: 1 +``` + +### Field paths + +Nested fields are addressed with dot-separated paths. +A path walks down the tree, one field name per segment. + +``` +name # top-level field +resources.memory # nested field +service.name # nested field +timestamps.created # nested field +networks.0.private-ip # array element by zero-based index +``` + +These same paths are used by `--field`, `--sort`, `--filter`, and the `edit` flags described below. + +## Choosing which fields to display + +Listing resources prints a default set of columns. +Use `--field` (short form `-f`) to select which fields are displayed. + +When you pass a parent field, the CLI expands it into a column for each of its child fields. + +```console +$ unikraft instance ls --field service +NAME UUID FQDN +falling-sky-k20dl7a7 32b81f2f-8767-4961-a55f-520e7462395b falling-sky-k20dl7a7.fra.unikraft.app +nameless-silence-donj1yl2 cd2910d2-b709-410c-9e04-f5539a7d020a nameless-silence-donj1yl2.fra.unikraf… +``` + +Pass a specific field path to display just that one value. + +```console +$ unikraft instance ls --field service.name +NAME +falling-sky-k20dl7a7 +nameless-silence-donj1yl2 +``` + +You can repeat `--field` to add several fields at once. + +```console +$ unikraft instance ls --field service.name --field resources.memory +NAME MEMORY +falling-sky-k20dl7a7 256MiB +nameless-silence-donj1yl2 256MiB +``` + +## Sorting + +Use `--sort` with a field path to order the output by that field. + +```console +$ unikraft instance ls --sort timestamps.created +METRO NAME STATE IMAGE ARGS MEMORY VCPUS FQDN CREATED +fra httpserver-rust175-to… standby /httpserver-rust17… 256MiB 2 nameless-silence-donj1… 1 day ago +fra nginx-fj704 running /nginx 256MiB 1 falling-sky-k20dl7a7.f… 1 hour ago +``` + +## Filtering + +Use `--filter` with a field path and an operator to show only the resources that match. + +```console +$ unikraft instance ls --filter state==standby +METRO NAME STATE IMAGE ARGS MEMORY VCPUS FQDN CREATED +fra httpserver-rust175-tok… standby /httpserver-rust17… 256MiB 2 nameless-silence-donj1… 1 day ago +``` + +`--filter` is available on `list`, `wait`, and `delete` subcommands throughout the `unikraft` CLI. +It isn't available in the legacy `kraft cloud` CLI. + +The filter expression language supports nested paths, wildcards, regular expressions, and combining multiple expressions. +See the [filter expression reference](#filter-expression-reference) for the full grammar, operators, and examples. + +## The `--until` flag + +The `--until` flag uses the same expression syntax as `--filter`. +It's available on `wait` subcommands (and aliases to `--filter` there). +The command polls until every targeted resource matches the expression. + +```bash +unikraft instance wait my-instance --until state==running +``` + +## Editing fields + +The `edit` command modifies a resource's fields in place. +It prints a diff of the change, where `+` lines are additions and `-`/`+` pairs show a value being replaced. + +### Setting a field with `--set` + +Use `--set =` to set or replace a field. +Setting a field that doesn't exist yet creates it, including any parent fields. + +```console +$ unikraft instance edit httpserver-rust175-tokio-ngh8r --set runtime.env=MYSECRET=secret + metro: fra + name: httpserver-rust175-tokio-ngh8r + uuid: 78ad8c05-ed7a-4886-abd3-07613dce7c28 + state: standby + image: /httpserver-rust175-tokio ++ runtime: ++ env: ++ MYSECRET: * + resources: + memory: 256MiB + vcpus: 1 + ... +``` + +### Adding and removing with `--add` and `--del` + +Use `--add =` to append to a list or map field, and `--del =` to remove an entry from one. + +For example, remove a previously set environment variable: + +```console +$ unikraft instance edit httpserver-rust175-tokio-ngh8r --del runtime.env=MYSECRET + metro: fra + name: httpserver-rust175-tokio-ngh8r + uuid: 78ad8c05-ed7a-4886-abd3-07613dce7c28 + state: standby + image: /httpserver-rust175-tokio +- runtime: +- env: +- MYSECRET: * + resources: + memory: 256MiB + vcpus: 2 + service: + name: nameless-silence-donj1yl2 + uuid: cd2910d2-b709-410c-9e04-f5539a7d020a + domains: + - fqdn: nameless-silence-donj1yl2.fra.unikraft.app + networks: + - uuid: d8700d21-63c0-448a-806d-54014584b082 + private-ip: 10.0.0.25 + mac: 12:b0:0a:00:00:19 + timestamps: + created: 1 day ago + scale-to-zero: + enabled: true + policy: on + cooldown-time: 1s + stop: + reason: platform stop + exit-code: 1 +``` + +The `--add` flag works the same way, appending the given value instead of removing it. +You can combine multiple `--set`, `--add`, and `--del` flags in a single `edit` invocation. + +## Visual editing + +Pass `--visual` to open the resource in your editor and modify its fields interactively. +The CLI launches the program named by the `$VISUAL` or `$EDITOR` environment variable. + +```bash +export EDITOR=vim +unikraft instance edit httpserver-rust175-tokio-ngh8r --visual +``` + +If neither variable is set, the command fails with `no editor set: please set $VISUAL or $EDITOR`. + +When you save and close the editor, the CLI applies your changes and prints the resulting diff. + +```console +$ unikraft instance edit httpserver-rust175-tokio-ngh8r --visual + metro: fra + name: httpserver-rust175-tokio-ngh8r + uuid: 78ad8c05-ed7a-4886-abd3-07613dce7c28 + state: standby + image: demo/httpserver-rust175-tokio + runtime: + env: + MYSECRET: * + resources: + memory: 256MiB +- vcpus: 1 ++ vcpus: 2 + ... +``` + +## Filter expression reference + +The `--filter` and `--until` flags accept filter expressions that match resources based on their field values. +The syntax extends the [containerd filter grammar](https://github.com/containerd/containerd/blob/main/pkg/filters/filter.go) with negated regex matching, wildcards, and alternative quoting. + +### Grammar + +``` +expression := selector ( "," selector )* +selector := fieldpath [ operator value ] + | fieldpath? "*" ( "." selector | operator value )? +fieldpath := field ( "." field )* +field := quoted-string | identifier +identifier := [A-Za-z] [A-Za-z0-9_]+ +operator := "=" | "==" | "!=" | "!==" | "~=" | "!~=" +value := quoted-string | regex-string | unquoted-string +``` + +A **quoted-string** uses Go string syntax (double quotes with standard +backslash escapes: `\n`, `\t`, `\\`, `\"`, `\xNN`, `\uNNNN`, `\UNNNNNNNN`, +octal `\NNN`). + +A **regex-string** may only appear after `~=` or `!~=`. +You can delimit it with `/` or `|` instead of `"`, which is convenient when the pattern contains double-quotes or backslashes (for example, `name~=/[abc]{0,2}/` or `path~=|foo/bar|`). + +An **unquoted-string** is any run of non-whitespace, non-comma characters. + +### Operators + +| Operator | Alias | Description | Example | +| -------- | ----- | --------------------------------- | ----------------- | +| `==` | `=` | Equals | `state==running` | +| `!=` | `!==` | Not equals | `state!=stopped` | +| `~=` | | Matches regular expression | `name~="^web-.*"` | +| `!~=` | | Doesn't match regular expression | `name!~="^test-"` | +| _(none)_ | | Field is present and non-empty | `description` | + +Regular expressions use Go `regexp` syntax. + +### Field paths in expressions + +Fields use their output name (the name shown in `kv` or `table` output). +Nested fields use dot-separated paths. + +``` +name # top-level field +settings.bar # nested field +timestamps.created-at # hyphenated field name +labels."my complex key" # quoted path segment +``` + +#### Wildcards + +A `*` in a field path iterates over all entries of a map or array field. +The wildcard can appear at any level, and you can chain wildcards. + +``` +labels.* # true if any label entry exists +labels.*==value # true if any label entry equals "value" +authors.*.email==a@b.com # true if any author's email matches +nested.*.*==true # double wildcard +``` + +**Negation semantics with wildcards:** positive operators (`==`, `~=`) match if +**any** entry meets the condition. +Negated operators (`!=`, `!~=`) match only if **all** entries meet the condition (that is, no entry matches the negated pattern). + +#### Indexed access + +You can also access array elements by zero-based numeric index. + +``` +authors.0.name==Alice # first author's name +authors.1.email==b@b.com # second author's email +``` + +### Combining expressions + +#### And (comma-separated within one flag) + +Comma-separated selectors within a single `--filter` value must **all** match for the filter to include a resource. + +```bash +--filter 'state==running,name~="^web"' +``` + +#### Or (repeated flags) + +When you specify `--filter` several times, the filter includes a resource if it matches **any** of the expressions. + +```bash +--filter 'state==running' --filter 'state==stopped' +``` + +#### Combining both operators + +The two mechanisms compose: + +```bash +--filter 'state==running,metro==fra0' --filter 'state==stopped,metro==was1' +``` + +This matches resources that are (running in fra0) **or** (stopped in was1). + +### Special fields + +The `metro` field receives special handling: when present in a filter, it restricts which metros the CLI queries rather than filtering results after the fact. +This means `--filter metro==fra0` avoids fetching data from other metros entirely. + +### Examples + +```bash +# List only running instances +unikraft instance list --filter state==running + +# List instances NOT in the "stopped" state +unikraft instance list --filter 'state!=stopped' + +# List images whose ref contains "nginx" +unikraft image list --filter 'ref~="/nginx"' + +# Exclude images matching a pattern +unikraft image list --filter 'ref!~="test"' + +# Regex with slash delimiters (avoids escaping issues) +unikraft image list --filter 'ref~=/nginx[0-9]{1,3}/' + +# Wait for an instance to reach the running state +unikraft instance wait my-instance --until state==running + +# Delete all stopped instances (with confirmation) +unikraft instance remove --filter state==stopped + +# Combine filters: running instances in fra0, OR stopped in was1 +unikraft instance list --filter 'state==running,metro==fra0' \ + --filter 'state==stopped,metro==was1' + +# Filter on nested fields +unikraft instance list --filter 'settings.autoscale==true' + +# Filter using array wildcard +unikraft instance list --filter 'volumes.*.name==data' + +# Check that no label matches a pattern (all must satisfy !=) +unikraft instance list --filter 'labels.*!=temporary' +``` diff --git a/pages/cli/filters.mdx b/pages/cli/filters.mdx deleted file mode 100644 index 720860d..0000000 --- a/pages/cli/filters.mdx +++ /dev/null @@ -1,163 +0,0 @@ ---- -title: Filters -description: Filter expression language for the --filter and --until flags -navigation_icon: filter ---- - -The `unikraft` CLI's `--filter` and `--until` flags accept filter expressions that match resources based on their field values. -These flags are available on `list`, `wait`, and `delete` subcommands throughout the `unikraft` CLI. -They aren't available in the legacy `kraft cloud` CLI. - -The syntax extends the [containerd filter grammar](https://github.com/containerd/containerd/blob/main/pkg/filters/filter.go) with negated regex matching, wildcards, and alternative quoting. - -## Grammar - -``` -expression := selector ( "," selector )* -selector := fieldpath [ operator value ] - | fieldpath? "*" ( "." selector | operator value )? -fieldpath := field ( "." field )* -field := quoted-string | identifier -identifier := [A-Za-z] [A-Za-z0-9_]+ -operator := "=" | "==" | "!=" | "!==" | "~=" | "!~=" -value := quoted-string | regex-string | unquoted-string -``` - -A **quoted-string** uses Go string syntax (double quotes with standard -backslash escapes: `\n`, `\t`, `\\`, `\"`, `\xNN`, `\uNNNN`, `\UNNNNNNNN`, -octal `\NNN`). - -A **regex-string** may only appear after `~=` or `!~=`. -You can delimit it with `/` or `|` instead of `"`, which is convenient when the pattern contains double-quotes or backslashes (for example, `name~=/[abc]{0,2}/` or `path~=|foo/bar|`). - -An **unquoted-string** is any run of non-whitespace, non-comma characters. - -## Operators - -| Operator | Alias | Description | Example | -| -------- | ----- | --------------------------------- | ----------------- | -| `==` | `=` | Equals | `state==running` | -| `!=` | `!==` | Not equals | `state!=stopped` | -| `~=` | | Matches regular expression | `name~="^web-.*"` | -| `!~=` | | Doesn't match regular expression | `name!~="^test-"` | -| _(none)_ | | Field is present and non-empty | `description` | - -Regular expressions use Go `regexp` syntax. - -## Field paths - -Fields use their output name (the name shown in `kv` or `table` output). -Nested fields use dot-separated paths. - -``` -name # top-level field -settings.bar # nested field -timestamps.created-at # hyphenated field name -labels."my complex key" # quoted path segment -``` - -### Wildcards - -A `*` in a field path iterates over all entries of a map or array field. -The wildcard can appear at any level, and you can chain wildcards. - -``` -labels.* # true if any label entry exists -labels.*==value # true if any label entry equals "value" -authors.*.email==a@b.com # true if any author's email matches -nested.*.*==true # double wildcard -``` - -**Negation semantics with wildcards:** positive operators (`==`, `~=`) match if -**any** entry meets the condition. -Negated operators (`!=`, `!~=`) match only if **all** entries meet the condition (that is, no entry matches the negated pattern). - -### Indexed access - -You can also access array elements by zero-based numeric index. - -``` -authors.0.name==Alice # first author's name -authors.1.email==b@b.com # second author's email -``` - -## Combining expressions - -### And (comma-separated within one flag) - -Comma-separated selectors within a single `--filter` value must **all** match for the filter to include a resource. - -```bash ---filter 'state==running,name~="^web"' -``` - -### Or (repeated flags) - -When you specify `--filter` several times, the filter includes a resource if it matches **any** of the expressions. - -```bash ---filter 'state==running' --filter 'state==stopped' -``` - -### Combining both operators - -The two mechanisms compose: - -```bash ---filter 'state==running,metro==fra0' --filter 'state==stopped,metro==was1' -``` - -This matches resources that are (running in fra0) **or** (stopped in was1). - -## The `--until` flag - -The `--until` flag uses the same expression syntax as `--filter`. -It's available on `wait` subcommands (and aliases to `--filter` there). -The command polls until every targeted resource matches the expression. - -```bash -unikraft instance wait my-instance --until state==running -``` - -## Special fields - -The `metro` field receives special handling: when present in a filter, it restricts which metros the CLI queries rather than filtering results after the fact. -This means `--filter metro==fra0` avoids fetching data from other metros entirely. - -## Examples - -```bash -# List only running instances -unikraft instance list --filter state==running - -# List instances NOT in the "stopped" state -unikraft instance list --filter 'state!=stopped' - -# List images whose ref contains "nginx" -unikraft image list --filter 'ref~="/nginx"' - -# Exclude images matching a pattern -unikraft image list --filter 'ref!~="test"' - -# Regex with slash delimiters (avoids escaping issues) -unikraft image list --filter 'ref~=/nginx[0-9]{1,3}/' - -# Wait for an instance to reach the running state -unikraft instance wait my-instance --until state==running - -# Delete all stopped instances (with confirmation) -unikraft instance remove --filter state==stopped - -# Combine filters: running instances in fra0, OR stopped in was1 -unikraft instance list --filter 'state==running,metro==fra0' \ - --filter 'state==stopped,metro==was1' - -# Filter on nested fields -unikraft instance list --filter 'settings.autoscale==true' - -# Filter using array wildcard -unikraft instance list --filter 'volumes.*.name==data' - -# Check that no label matches a pattern (all must satisfy !=) -unikraft instance list --filter 'labels.*!=temporary' -``` diff --git a/pages/tutorials/kraftkit-to-unikraft.mdx b/pages/tutorials/kraftkit-to-unikraft.mdx index ce2c911..58c5ee3 100644 --- a/pages/tutorials/kraftkit-to-unikraft.mdx +++ b/pages/tutorials/kraftkit-to-unikraft.mdx @@ -119,7 +119,7 @@ Write operations require an explicit metro selection with `--metro`: ```bash title="unikraft" unikraft run --metro=fra -p 443:8080/http+tls -m 512MiB --image=/my-app:latest -``` +``` For custom or private metros, define a profile in `~/.config/unikraft/config.yaml`: @@ -314,7 +314,7 @@ unikraft instance wait my-instance --until state==running These `--filter` and `--until` expressions are features of the new CLI. They aren't available in the legacy `kraft cloud` CLI. -See [Filters](/docs/cli/filters) for the full syntax. +See [Fields](/docs/cli/fields#filter-expression-reference) for the full syntax. ## A side-by-side migration example @@ -384,5 +384,5 @@ For more details, check the following references: * The [unikraft CLI overview](/docs/cli/overview). * The [legacy CLI overview](/docs/cli/legacy-overview). -* The [Filters](/docs/cli/filters) reference for the new filtering language. +* The [Fields](/docs/cli/fields#filter-expression-reference) reference for the new filtering language. * The [Environment Variables](/tutorials/environment-variables) tutorial for runtime configuration patterns. \ No newline at end of file diff --git a/zudoku.config.tsx b/zudoku.config.tsx index acb4fae..d95b557 100644 --- a/zudoku.config.tsx +++ b/zudoku.config.tsx @@ -243,7 +243,7 @@ const config: ZudokuConfig = { collapsed: false, items: [ "/cli/registries", - "/cli/filters", + "/cli/fields", ], }, {