The CLI
toa is the one command-line tool for running, inspecting, building and deploying an
application. Its commands are grouped by what you are doing; the first few are met in Run It and Make a Change.
§Installing
The toa binary comes with the runtime. What a command needs beyond it depends on the command:
$ npm i -D @toa.io/runtime @toa.io/operations An application toa create wrote lists both, and @toa.io/userland, in its devDependencies: npm install is all it takes. toa is installed with the project, so in a
shell it is run as npx toa, and by its name in a script of package.json.
| Needs | Commands |
|---|---|
@toa.io/userland | create |
@toa.io/runtime | compose, mono, serve, call |
@toa.io/operations | env, build, push, deploy, conceal, reveal, export deployment, export images, export secrets, export tags, compose --dock, key --public, key --format paseto |
| neither | map, types, npm, export manifest, export convergence, shell, key |
A command whose package is missing says so:
`toa deploy` needs @toa.io/operations, which is not installed A machine that only deploys needs no runtime:
$ npm i @toa.io/cli @toa.io/operations
$ npx toa deploy production -p application build, push and deploy use docker; deploy, conceal, reveal and shell use kubectl and, for deploy, helm. They act on the current docker and kubectl contexts.
§Creating an application
§toa create
$ npx -p @toa.io/cli -p @toa.io/userland toa create <name> Writes an application into the working directory; name is the application’s name, which is
what its Context is called. Create an Application starts from it.
$ mkdir store && cd store
$ npx -p @toa.io/cli -p @toa.io/userland toa create store package.json
tsconfig.json
docker-compose.yaml
ecosystem.config.js
context.toa.yaml
cucumber.js
components/
hello/
manifest.toa.yaml
operations/greet.ts
notes/
manifest.toa.yaml
features/
hello.feature
notes.feature
steps/
application.ts
http.ts | File | Is |
|---|---|
context.toa.yaml | The Context: the application’s name and where its infrastructure is. |
docker-compose.yaml | RabbitMQ, MongoDB as a replica set of one member, and Redis, on their usual ports, with the credentials toa env --dev writes. |
ecosystem.config.js | The two processes PM2 keeps: sys, what Toa serves beside an application, and app, the components. |
components/hello | A component with code and no state. |
components/notes | A component with state and no code. |
features | A scenario for each component, and the steps they are written with; see Write a Test. |
package.json | The packages of Toa at the version that created the application, and the scripts. |
tsconfig.json | What tsc checks the components and the steps with. |
- The directory has to be empty;
.gitmay be there. Otherwise nothing is written:The directory is not empty: it holds README.md. - A name a Context cannot have is refused the same way:
'my store' is not a name an application can have. - The files come from
@toa.io/userland, which is why the command is run with both packages. - Nothing is installed or started. The command prints what to run next; running the application takes Docker and PM2 on the machine.
§The scripts
The generated package.json wraps the commands of every day:
| Script | Runs | Does |
|---|---|---|
npm install | toa npm, as postinstall | Installs the packages, then what the declarations require beyond them. |
npm run dock | docker compose up -d --wait | Starts RabbitMQ, MongoDB and Redis from docker-compose.yaml and waits until they are ready. |
npm run env | toa types --quiet && toa env --dev && toa map | Writes the types, .env and .map.json. |
npm run sys | pm2 start ecosystem.config.js --only sys | Starts sys alone: toa serve configuration exposition introspection. It is what the scenarios need, since they start the components themselves. |
npm start | pm2 start ecosystem.config.js | Starts sys and app; app is toa compose with every directory under components. The gateway is on http://localhost:8000. |
npm run restart | npm run env && pm2 restart ecosystem.config.js | Generates again and restarts both processes. Run it after any change. |
npm stop | pm2 delete ecosystem.config.js | Stops both processes, and PM2 forgets them. |
npm run features | cucumber-js | Runs the scenarios; see Write a Test. |
npm run typecheck | tsc | Checks the types of the components and the steps; see Use TypeScript. |
pm2 logs shows what the two processes write, and pm2 ls whether they run.
§Options every command takes
| Option | Meaning |
|---|---|
--env <path> | read variables from this .env file |
--map <path> | read the component map from this file |
--log <level> | log level; info by default |
-h, --help | help for the program or for one command |
-v, --version | the version |
Without --env, a .env file is looked for from the working directory upwards. Without --map, .map.json is looked for the same way by the commands that need one: compose, mono, serve and call.
Most commands that read a Context take -p, --path: where the Context is, . by default. The
directory given, or one of its parents, must contain context.toa.yaml. With the application in
a subdirectory, commands are run from the repository root as toa env -p application.
Unknown options are refused.
§Preparing to run
§toa env
$ npx toa env [environment] Writes the variables of an environment to a .env file beside the Context.
| Option | Default | Meaning |
|---|---|---|
environment | local | the environment, or a chain such as staging:production |
-p, --path | . | path to the Context |
--as | .env | output file, relative to the Context |
-d, --dev | off | fill secrets with local development defaults |
-i, --interactive | off | ask for each secret that has no value |
-c, --component | all | only what this component needs; repeat for several |
-s, --service | all | only what this service needs, by shortcut or package; repeat |
Secret values already in the output file are kept. With --dev alone, a secret that has no
default and is not set in the shell’s environment is written empty. -d -i together fills what
can be filled and asks for the rest. npm run env runs toa env --dev.
-c writes the variables of a component even when it is evicted. An unknown name is refused: Component 'store.order' is not in the context.
§toa map
$ npx toa map [environment] Writes the component map to .map.json beside the Context. Run it again
whenever component sources change; npm run env and npm run restart do.
| Option | Default | Meaning |
|---|---|---|
environment | local | as for toa env |
-p, --path | . | path to the Context |
--as | .map.json | output file, relative to the Context |
§toa npm
$ npx toa npm [environment] Installs the packages the application’s declarations require and Toa does not bundle: for
example, the SDK of a storage provider a component’s storage uses. A deployment installs the same
set into its images; this command installs it into your workspace, as devDependencies of the
nearest package.json above the Context.
| Option | Default | Meaning |
|---|---|---|
environment | local | as for toa env |
-p, --path | . | path to the Context |
-n, --dry-run | off | print what is missing instead of installing it |
Prints Nothing to install when the workspace already declares everything. Run it after
upgrading Toa and after declaring a new storage provider. In a generated application it is the postinstall script, so npm install runs it.
§Running
Tests start components themselves; see Write a Test.
§toa compose
$ npx toa compose [paths...] Runs components as one composition.
| Option | Default | Meaning |
|---|---|---|
paths | . | component directories, or glob patterns matching them |
--service | none | an extension service to run in the same process; repeat |
--kill | off | shut down as soon as it has started |
--dock | off | build the composition’s image and run it in Docker |
--context | . | path to the Context, for --dock |
$ npx toa compose # the component in the current directory
$ npx toa compose ./components/store.orders
$ npx toa compose ./components/*
$ npx toa compose ./components/* --service exposition --service configuration It prints Composition complete when every component is connected and serving, and stops on SIGINT or SIGTERM after finishing what is in progress. See Decide What Runs Together for running services in the same process.
--service names are exact; nothing is added to them. Without the option, the list comes from TOA_SERVICES, separated by spaces. An extension that runs no service is refused: Service is not implemented by '@toa.io/extensions.telemetry'.
--dock builds the image a deployment would build for these components and services, runs it
with the current .env, and removes it. The exit code is the composition’s. Inside the
container, your machine is host.docker.internal, so use an environment whose addresses say so;
see Several local environments. The components
must belong to the Context.
§toa mono
$ npx toa mono [paths...] Runs components and every extension service they use in one process. Unlike compose, the
services are discovered from what the components declare.
| Option | Default | Meaning |
|---|---|---|
paths | . | component directories, or glob patterns |
--kill | off | shut down as soon as it has started |
§toa serve
$ npx toa serve [paths...] Runs extension services, without components, in one process.
$ npx toa serve exposition
$ npx toa serve exposition configuration introspection Each is named by shortcut, package name, or path. The list is exact. A named service that is off in this environment, because its variables are absent, is refused and nothing starts:
'introspection' has no service to run in this environment: its variables are absent.
Regenerate the environment file with `toa env`. A usual local arrangement is two processes: toa serve for the services and toa compose for
the components, both reading the same .env and .map.json. It is the one a generated
application runs under PM2: sys is toa serve configuration exposition introspection, and app is toa compose with every component.
§toa call
$ npx toa call <endpoint> [request] Calls an operation of a running component and prints the reply.
$ npx toa call hello.greet "{ input: { name: 'Toa' } }"
$ npx toa call notes.observe "{ query: { id: '7a1c...' } }" hello and notes are the two components of a generated application.
endpoint is <namespace>.<component>.<operation>; with two segments the namespace is default. request is a request (Call Operations and Select State)
written as YAML, which includes JSON; without it the request is empty.
The reply is printed to stdout. A streamed reply is printed chunk by chunk. An exception is
printed to stderr and the command exits with 1.
The component must be running somewhere the broker reaches, and the call is validated against
the map, so call needs .env and .map.json as compose does.
§Inspecting
§toa types
$ npx toa types Generates TypeScript types for the Context and every component in it; see Use TypeScript.
| Option | Default | Meaning |
|---|---|---|
-p, --path | . | path to the Context |
-e, --environment | local | the environment the Context is read for |
-c, --components | paths to components that belong to no Context, instead of reading one | |
-q, --quiet | off | print nothing |
It writes types/ beside context.toa.yaml and a types directory in each component, and
prints the files written. In each, toa.d.ts is rewritten on every run, and index.d.ts, which
is where types of your own go, is kept. npm run env runs it with --quiet.
§toa export manifest
$ npx toa export manifest Prints a component’s manifest as the runtime reads it: with the prototype merged in, shorthand
expanded and defaults filled. toa export man is the same.
| Option | Default | Meaning |
|---|---|---|
-p, --path | . | path to the component |
-o, --output | yaml | yaml or json |
-e, --error | off | print nothing unless the manifest is invalid |
With --error it is a manifest validator: silent and 0 for a valid manifest, an error
otherwise.
§toa export secrets
$ npx toa export secrets <environment> Lists every secret a deployment of the environment needs, with its keys. See Supply Secrets. Takes -p, --path.
§toa export tags
$ npx toa export tags <environment> Prints the image reference of every workload the environment deploys. Takes -p, --path, and --mono for the single-image form.
§toa export deployment
$ npx toa export deployment <environment> <target> Writes the Helm chart of a deployment into the target directory without applying it, and
prints the path. Takes -p, --path and --mono. toa export dep is the same.
§toa export images
$ npx toa export images <target> Writes the build contexts of the images — Dockerfiles and sources — into target without
building them. Takes -p, --path and --mono. toa export img is the same.
§toa export convergence
$ npx toa export convergence <environment> Prints what a region’s convergence broker must hold before the region is deployed; see Adding a region.
| Option | Default | Meaning |
|---|---|---|
-p, --path | . | path to the Context |
--format | definitions | definitions for the broker’s import, or commands for rabbitmqadmin invocations |
§Building and deploying
See Deploy and Build Images.
§toa build
$ npx toa build Builds every image on the local Docker daemon. Takes -p, --path, and --mono to build the
single image.
§toa push
$ npx toa push [environment] Builds every image and pushes it to the registry. An image the registry already has is skipped. environment defaults to default. Takes -p, --path.
§toa deploy
$ npx toa deploy [environment] Checks secrets, builds and pushes images, and applies the deployment to the current Kubernetes context.
| Option | Default | Meaning |
|---|---|---|
environment | default | the environment, or a chain |
-p, --path | . | path to the Context |
-n, --namespace | current | Kubernetes namespace to deploy into |
-w, --wait | off | wait until the rollout is complete |
-t, --timeout | 5m | how long --wait may take, as a duration such as 15m0s |
-d, --dry | off | print what would be applied; no cluster is read and nothing is applied |
--mono | off | deploy the single-image form |
§Secrets
§toa conceal
$ npx toa conceal <secret> <key=value...> Creates or updates a secret in the cluster. The name is prefixed with toa-.
$ npx toa conceal mongodb.default username=store password=secret
$ npx toa conceal -i -e production | Option | Default | Meaning |
|---|---|---|
-n, --namespace | current | Kubernetes namespace |
-i, --interactive | off | ask for every secret the Context needs, instead of naming one |
-e, --environment | the environment, for --interactive | |
-p, --path | . | path to the Context, for --interactive |
Keys given to an existing secret are added to it; other keys stay.
§toa reveal
$ npx toa reveal <secret> Prints the keys and values of a secret created by toa conceal, one key: value per line. The
name is given without the toa- prefix. Prints nothing when there is no such secret.
§toa key
$ npx toa key Generates a key for identity tokens, to store as a secret.
| Option | Default | Meaning |
|---|---|---|
--format | jwe | jwe for a 256-bit encryption key, paseto for a legacy PASETO key |
--public | off | print a secret/public key pair instead, one per line |
Where the keys go is shown in Tokens.
§In the cluster
§toa shell
$ npx toa shell [image] Starts a disposable pod in the current Kubernetes context and opens an interactive shell in it. The pod is removed when the shell exits.
$ npx toa shell # alpine
$ npx toa shell mongo # an image with the client you need
$ npx toa shell -- ping 10.0.0.7 # run a command instead of a shell Use it to check, from inside the cluster, that the application’s infrastructure is reachable; see A pod does not become ready.
§Variables the CLI reads
| Variable | Effect |
|---|---|
TOA_ENV | the environment types and npm read the Context for, when none is given |
TOA_SERVICES | services compose runs when --service is absent |
TOA_DEBUG=1 | sets the default log level to debug |
TOA_BOOT_TRACE=1 | compose, mono and serve trace their own startup |
TOA_OUTBOX_DEFER, TOA_OUTBOX_INTERVAL, TOA_OUTBOX_BATCH | development settings of event publication; see Settings |
TOA_SUFFIX | runs an isolated copy; see a second copy |
§Exit codes
A command exits with 0 on success and 1 on any failure, printing the error to stderr. A
running process that fails — an uncaught exception, an unhandled rejection, a boot that cannot
complete — prints the error, writes a Process failed log record with the reason, and exits
with 1.
§Every command
| Command | Purpose |
|---|---|
toa create <name> | create an application in the working directory |
toa env [environment] | write the environment’s variables to .env |
toa map [environment] | write the component map to .map.json |
toa npm [environment] | install packages the declarations require |
toa compose [paths...] | run components as one composition |
toa mono [paths...] | run components and their services in one process |
toa serve [paths...] | run extension services |
toa call <endpoint> [request] | call an operation |
toa types | generate TypeScript types |
toa export manifest | print a normalized manifest |
toa export secrets <environment> | list the secrets a deployment needs |
toa export tags <environment> | print image references |
toa export deployment <environment> <target> | write the chart |
toa export images <target> | write the image build contexts |
toa export convergence <environment> | print a region’s broker definitions |
toa build | build images locally |
toa push [environment] | build and push images |
toa deploy [environment] | deploy |
toa conceal <secret> <key=value...> | write a cluster secret |
toa reveal <secret> | read a cluster secret |
toa key | generate a token key |
toa shell [image] | open a shell in the cluster |