chore: Reworked CLI conventions and include more details (#831)

* chore: Reworked CLI conventions and include more details

* chore: Review changes

* Update conventions/cli.md

Co-authored-by: Navid Shaikh <nshaikh@redhat.com>

* Update conventions/cli.md

Co-authored-by: Navid Shaikh <nshaikh@redhat.com>

* add changes based on review comments

Co-authored-by: Navid Shaikh <nshaikh@redhat.com>
This commit is contained in:
Roland Huß 2020-05-09 17:33:45 +02:00 committed by GitHub
parent 0a65978ceb
commit 36716c3937
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 154 additions and 52 deletions

View File

@ -1,79 +1,181 @@
# Guidelines for `kn` Commands ## `kn` User Interface Principles
Commands are generally of the form `kn <resource> <verb>`; the resource kind This document describes the conventions that are used for all `kn` commands and options.
forms a command group for all the operations you might want to do with that kind It is normative in the sense that any new feature that introduces or changes user-facing commands or options needs to adhere to the given principles.
Also, the given rules apply to plugins as well.
Especially any plugin that wants to be promoted to the [knative/client-contrib](https://github.com/knative/client-contrib) plugin repository has to adhere to these rules.
### Command Structure
The general format for kn and plugin commands is
```
kn <noun> [<noun2> ...] <verb> [<id> <id2] [--opt val1 --opt2 --opt3 ...]
```
So, commands are generally of the form `kn <noun> <verb>` <sup>[1](#foot-1)</sup>, where [<noun>](#noun) is often the name of a resource (e.g. `service`) but can also refer to other concepts (e.g. `plugin` or `config`).
This first noun forms a command group for all the operations you might want to do with that kind
of resource. of resource.
Sometimes there can be deeper hierarchies with multiple nouns (`kn <noun-1> <noun-2> .... <verb>`) when it makes sense to structure complex concepts.
A good example is `kn source <source-type> <verb>` which is used like in `kn source ping create`.
Commands that directly concern more than one resource kind may be categorized `kn` commands take only positional arguments that are used as [identifiers](#identifier).
with one of the relevant resources, or may get their own top-level verb (eg. This identifier is often the name of a resource which identifies the resource uniquely for the current or given namespace.
`connect`).
Top-level commands concerning the operation of `kn` itself, like `help` and Top-level commands concerning the operation of `kn` itself, like `help` and `version` are also okay.
`version` are also okay.
## Resource ### Noun
The <group>.knative.dev Kind, singluar and lowercase. For example, `service` for For resource-related commands, the kind itself used as a command in singular and lowercase form. For example, `service` for
`serving.knative.dev/service` or `trigger` for `eventing.knative.dev/trigger`. `serving.knative.dev/service` or `trigger` for `eventing.knative.dev/trigger` are the commands for managing these resources respectively
## Verb ### Verb
If the thing the user's doing can be described by the following commands, these For CRUD (create-retrieve-update-delete) operation the following verbs have to be used:
should be the name of the verb:
- `describe` prints detailed information about a single resource. It can include - `describe` prints detailed information about a single resource that can contain data of dependent objects, too.
status information of related or child resources, too. - `list` prints summary information about all resources of a type.
- `create` creates a resource.
- `update` updates a resource.
- `delete` deletes a resource.
- `list` prints summary information about all resources of a type, possibly For a given resource, create and update should use the same arguments as much as possible and where it makes sense.
filtered by parent or label selector.
- `create` creates a resource. Accepts a `--force` flag to create-or-replace. Other domain-specific verbs are possible on a case-by-case basis for operations that go beyond basic CRUD operations.
- `update` updates a resource based on the changes the user would like to make. ### Identifier
- `delete` deletes a resource For the `CRUD` operations `describe`, `create`, `update`, `delete` the identifier is the resource's name and is required as a positional argument after the commands.
For example it is the last argument that does not start with a flag prefix `-` or `--`.
`list` operations can use a resource name to filter on the resource.
For a given resource there should be parallelism between arguments to `create` Other identifiers can be plugin names or other entities' identifiers.
and `update` as much as possible.
Other domain-specific verbs are possible on a case-by-case basis, like For bulk operations also multiple identifiers can be provided.
`set-traffic` for a Knative Serving Service. For example, a `delete` operation could use multiple resource names that should be deleted.
## Arguments
### Positionals
Where there's a single target resource, the resource name should be a positional
argument. It needs to be of the resource type we're talking about, eg.
`kn revision` subcommands the positional must be naming a revision.
```bash ```bash
kn service create foo --image gcr.io/things/stuff:tag kn service create foo --image gcr.io/things/stuff:tag
``` ```
In this case `foo` is positional, and refers to the service to create. In this case, `foo` is positional, and provides the name of the service to create.
### Flags ### Flags
- `--force` is a flag on all create commands, and will replace the resource if Flags are used for specifying the input for `kn` commands and can have different characteristics:
it already exists (otherwise this is an error). The resource will be _mutated_
to have a spec exactly like the resource that would otherwise be created. It
is not deleted and recreated.
- When a flag sets a particular field on create or update, it should be a short * They can be _mandatory_ or _optional_
name for the field, without necessarily specifying how it's nested. For * Optional flags can have _default values_
example, `--image=img.repo/asdf` in Knative Serving sets * Flag values can be _scalars_, _binary_, _lists_ or _maps_ (see below for details)
`spec.template.containers[0].image` * Flags always have a long-form (starting with a double `--`) but can also have a shortcut (beginning with a single `-`)
* Every flag has a help message attached
* Flags can be specific to a command or can be globally applicable
- Flags that control a boolean behavior (eg. generate a name or not) are When adding new flags, the following recommendations should be considered:
specified by their presence. The default happens when the flag is not present,
and adding the flag marks the user's desire for the non-default thing. When
the flag _disables_ a default behavior which is to do something, it should
start with `no` (eg. `--no-generate-name` when the default is to generate a
name).
#### Output * Never add a global flag except for very good reasons
* Group related flags together by using a common prefix, like `--label-revision` or `--label-service` so that they appear together in the help message (which is sorted alphabetically)
* Don't add a short form without former discussions
* Choose a name for the flag that is the same or close to the naming used in Knative serving itself like the corresponding CRD field or annotation name.
Commands that output information should support `--output` with a shorthand of As mentioned above, flag values can be of different types.
`-o` to choose how to frame their output, and `--template` for supplying The rules of how these values are modelled on the command line are given below.
templates to output styles that use them.
#### Scalar
A scalar option is one which just takes a single value.
This value can be a string or a number.
Such an option is allowed to be given only once.
If given multiple times, an error should be thrown.
A scalar flag's value can have an inner structure, too.
For example `--sink svc:myservice` uses a prefix `svc:` to indicate the targeted sink is a Knative Service.
A colon (`:`) should be used as separators if values have a structure.
Example:
```
# Scalar parameter "--image" for specifying an application image
kn service create myservice --image docker.io/myuser/myimage
```
#### Binary
Binary flags come in pairs and don't carry any value.
The flag representing the `true` value is just the flag name without a value (e.g. `--wait`) whereas the flag for a `false` value is this name with a `no-` prefix (e.g. `--no-wait`)
Example:
```
# Create a service an wait until deployed
kn service create myservice --wait ....
# Don't wait for the service to start
kn service create myservice --no-wait ...
```
Such a binary option can be provided only once. Otherwise, an error has to be thrown.
#### List
List flag values can be provided in two flavours:
* Within a single flag value as comma-separated list of key-value pairs (e.g. `--resource pod:v1,job:batch/v1`)
* By providing the same option multiple times (e.g. `--resource pod:v1 --resource job:batch/v1`)
The value itself can carry a structure where colons separate the parts (`:`), like in the examples above.
Example:
```
# Create an ApiServer source for listening on Pod and Job resource events
kn source apiserver create mysrc --resource pod:v1 --resource job:batch/v1 --sink svc:mysvc
# Same as above, but crammed into a single option
kn source apiserver create mysrc --resource pod:v1,job:batch/v1 --sink svc:mysvc
```
#### Maps
* Within a single flag value as comma separated list of key-value pairs (e.g. `--env USER=bla,PASSWORD=blub`)
* By providing the same option multiple times (e.g. `--env USER=bla --env PASSWORD=blub`)
For update operations, to _unset_ a value, the key has a dash suffix (`-`) and no value part. For example, to _remove_ an environment variable named `USER` from a service "hello-world".
If the same key is given multiple times on the command line, the latter definition overwrites the previous one.
Example:
```
# Create a Service "hello-world" that sets USER and PASSWORD environment variables
kn service create hello-world --env USER=bla --env PASSWORD=blub
# Same as above
kn service create hello-world --env USER=bla,PASSWORD=blub
# Remove the USER envvar and add a HOME envvar to the service "hello-world"
kn service update hello-world --env USER- --env HOME=/root
# Same as above
kn service update hello-world --env USER-,HOME=/root
# Same as above, but the last HOME "/home" flag overwrites the previous one
kn service update hello-world --env HOME=/root --env USER- --env HOME=/home
```
### Shared flags
Certain functionality is the same across command groups.
For example, specifying resource requests and limits via flags can be done when managing services but also for sources.
Those common functionalities should share the same conventions, syntax.
Area to which this applies:
* Resource limits
* Output formats, i.e. the data formats supported by the `--output` option (which is reused from k8s' _cli-runtime_)
* Sinks
* ....
_this section needs to be completed with the concrete specifications. tbd_
<a name="foot-1">1</a>: Note that this differs from the `kubectl` model where this order is vice versa (`kubectl <verb> <noun>`)