Skip to main content

Launch

Launch is a utility command meant to facilitate locally launching and shutting down an entire Cogment project at once.

When launch is used, a set of processes will be launched to run in parallel, as described by a YAML definition file. Once any of these processes terminates, all other ones will be terminated as well.

The order of of the script execution is undefined, which is to say that they may not start in the order they are defined, and may not always start in the same order. Script dependency can be used if a certain order must be used.

Command line

cogment launch [options] filename [args...]

filename: Name (and path) of the YAML definition file describing the processes to launch.

options:

[-q], [--quiet]: Disable some of the output generated by the launcher. Process output is never disabled by this option. To increase the level, more "q" can be added, up to -qqq disabling all launcher generated output except errors.

args: These are arguments that will be used in variable substitution in the definition file. If some arguments start with a dash (-) a double dash (--) must be used to separate these from the launch options.

E.g.:

$ cogment launch --quiet ./launch.yaml 1000 8
$ cogment launch -qq ./launch.yaml 1000 8
$ cogment launch --quiet ./launch.yaml -- --file ./myfile --match_all

definition file

The launch definition file is a YAML formatted file where the details of the parallel processes to run are defined. The file consists of at least a scripts top level node, and may also contain a global top level node.

Nodes

Scripts

The scripts node contains the details of the processes to run. Each node under scripts represents a process to run. The name of the node becomes the identity of the script/process and serves to identify the process output.

Each process will run the contents of the commands list in sequence (i.e. the next command will start when the previous ends). Each command runs in an independent environment (e.g. environment variables set by one command will not be seen by the others).

E.g.:

scripts:
process_a: # The name of this process is "process_a"
commands:
- ["retrieve_db.sh"]
- ["python3", "env/main.py"]

process_b: # The name of this process is "process_b"
commands:
- ["cogment", "service", "orchestrator"]

The output will then look something like this:

2023-06-30T22:24:08Z [TRACE ] [process_a] Ready
2023-06-30T22:24:08Z [TRACE ] [process_a:(1/2)] Launch [retrieve_db.sh]
2023-06-30T22:24:08Z [TRACE ] [process_b] Ready
2023-06-30T22:24:08Z [stdout] [process_a:(1/2)] Retrieving default database...
2023-06-30T22:24:08Z [TRACE ] [process_b:(1/1)] Launch [cogment services orchestrator]
2023-06-30T22:24:08Z [stderr] [process_b:(1/1)] 2023-06-30T22:24:08Z [INFO] [cmd] starting the orchestrator service [version:2.16.0]
2023-06-30T22:24:09Z [stderr] [process_a:(1/2)] Record #2278 inconsistent
2023-06-30T22:24:12Z [stdout] [process_a:(1/2)] Database retrieved in /app/sb/
2023-06-30T22:24:12Z [TRACE ] [process_a:(1/2)] Completed
2023-06-30T22:24:12Z [TRACE ] [process_a:(2/2)] Launch [python3 env/main.py]
...

Notes:

  • "[TRACE ]" is low level information from the launcher (it could also be "[INFO ]" for more important information).
  • "[stdout]", and "[stderr]" are the output from the process.
  • "process_a" and "process_b" are the names given to the processes in the definition file.
  • "(1/2)" means that it is the first command out of two for that process.
  • The times/dates are in RFC3339 format.
Environment Variables

You can set environment variables using the environment node of the process. These will be part of the environment of all commands in the process.

E.g:

scripts:
orchestrator:
environment:
COGMENT_ORCHESTRATOR_ACTOR_PORT: 9000
COGMENT_LIFECYCLE_PORT: 9000
commands:
- ["cogment", "services", "orchestrator"]
Working folder

By default, the current working folder is set to the folder containing the launch definition file (not the folder where the Launch command is executed). You can change the working folder with the folder node for each process.

E.g.:

# Definition file is in "/home/user"
scripts:
actor_alpha:
folder: ./actors/alpha # Working folder is "/home/user/actors/alpha"
commands:
- ["python3", "main.py"]
Quiet

You can control the process output by setting this value to True or False. By default this is False, in which case standard process output (stdout and stderr) are also output by the launcher. If set to True, standard process output is discarded and not output by the launcher.

E.g.:

scripts:
setup:
quiet: True
commands:
- ["python3", "setup.py"]
Dependency (Cogment >= 2.16)

Inter-process dependency can also be defined using the depends_on and ready_output nodes of the script.

The depends_on node is a list of process names that this script depends on. Which means that all the listed processes must be "ready" before the current process is started.

The ready_output node is a regex (regular expression) string to search for in the output of the process. When the regex matches the output, the process is considered to be "ready". If no regex string is provided (or the regex string is empty), the process is considered "ready" as soon as it starts.

E.g.:

scripts:
process_a:
quiet: True
commands:
- ["retrieve_db.sh"]
- ["python3", "env/main.py"]
ready_output: "^Database retrieved in"

process_b:
depends_on:
- process_a
commands:
- ["cogment", "service", "orchestrator"]

Notes:

  • It is better to use single quotes to define the regex string to prevent YAML from interpreting control characters (e.g. backslash).
  • Be aware that colors and other terminal controls (e.g. curses) in the process output can make matching difficult.
  • The version of regex currently used mostly follows Google's RE2.
  • The matching of the process output is not affected by the quiet script option.

Global (Cogment >= 2.15)

The global node contains values that have a global scope (i.e. they affect all scripts defined in the file). Some of these values can be overridden by the individual scripts.

Environment Variables

You can set global environment variables using the environment node under the global node. These variables will be part of the environment of all scripts, unless overridden locally in the script's own environment node.

E.g:

global:
environment:
COGMENT_LOG_LEVEL: info
COGMENT_DIRECTORY_ENDPOINT: grpc://server:9010
Working folder

By default, the current working folder is set to the folder containing the launch definition file (not the folder where the Launch command is executed). This can be changed with the folder node under the global node. It will then become the default folder for all scripts, unless locally changed by the script's own folder node. Each level can also build on the previous one if the provided folder is a relative folder.

E.g.:

# Definition file is in "/home/user"
global:
folder: ./app # Default folder for all scripts is set to "/home/user/app"
scripts:
local:
folder: ./inside # Working folder is then "/home/user/app/inside"
somewhere:
folder: /home/away # Working folder is then "/home/away"

Variable substitution

You can substitute launch variables using {{.VAR}} in strings anywhere in the commands, environment or ready_output nodes of the yaml definition file. All environment variables when launch is started are defined as launch variables. New environment variables set in the definition file also define launch variables. And launch defines some special variables internally also.

In the concerned strings, the double open curly brackets ("{{") delimit the start of a variable to be substituted, therefore to include a literal double open brackets in a string, you have to surround them with backticks inside substitution brackets: {{`{{`}}.

Undefined values will be replaced with <no value>.

E.g.:

$ export OWNER=Elvis
$ cogment launch ./launch.yaml
scripts:
say_hi:
environment:
Type: "How"
Question: "{{.Type}} are you?"
commands:
- ["echo", "Hello, {{.OWNER}}. {{.Question}}"] # echo "Hello, Elvis. How are you?"
- ["echo", "{{`{{`}} brackets }}"] # echo "{{ brackets }}"
- ["echo", "no val: {{.MADE_UP_VARIABLE}}"] # echo "no val: <no value>"
ready_output: "Hello, {{.OWNER}}.*"

Special Variables

The launch program will also define variables that can be used in substitutions. These internally defined variables start with a double underscore (__).

Environment variables with conflicting names will be replaced by these internal launch variables. Note that this only affects variable substitution, not the environment of the command execution. And internal launch variables are not available as environment variables.

Arguments (Cogment >= 2.15)

The arguments from the command line of launch define variables and can thus be substituted. E.g. cogment launch ./launch.yaml arg1 arg2 arg3 will define __1, __2 and __3 respectively corresponding to arg1, arg2 and arg3. They can then be substituted with {{.__1}}, {{.__2}}, {{.__3}}.

__1 to __9 are always defined, but will be empty if no corresponding argument was given on the command line. Arguments 10 (__10) and above will only be defined if they were provided on the command line.

E.g.:

$ cogment launch -q ./launch.yaml 42 foo
scripts:
args_out:
commands:
- ["echo", "args:", "{{.__1}}", "{{.__2}}", "{{.__3}}"] # echo "args:" "42" "foo" ""
- ["echo", "empty: >{{.__3}}< >{{.__6}}<"] # echo "empty: >< ><"
- ["echo", "no args: {{.__10}} {{.__42}}"] # echo "no args: <no value> <no value>"
ready_output: ".* {{.__2}} $"
All Arguments (Cogment >= 2.17)

The number of arguments on the command line of launch is defined in __NB_ARGS. And all the launch arguments can be added to a script command with __ALL_ARGS.

The __ALL_ARGS variable is special in terms of substitution; if the command argument string is exactly {{.__ALL_ARGS}}, then all launch arguments will be added to this command. Otherwise if it is only part of a string, it will substitute a string containing all launch arguments.

In other words, a command argument "{{.ALL_ARGS}}" will expand to multiple arguments for the command, whereas something like "--{{.ALL_ARGS}}" will stay as one argument (a string that contains all launch arguments preceded by "--").

E.g.:

$ cogment launch ./launch.yaml 42 foo extra
scripts:
args_out:
commands:
- ["echo", "nb of args: {{.__NB_ARGS}}]"] # echo "nb of args: 3"
- ["echo", "all:", "{{.__ALL_ARGS}}", "and more"] # echo "all:" "42" "foo" "extra" "and more"
- ["echo", "all:", "args: {{.__ALL_ARGS}}"] # echo "all:" "args: 42 foo extra"
ready_output: "args:.*{{.__2}}"

File Example

global:
environment:
RUN_NAME: "COGRUN-{{.HOSTNAME}}-{{.__1}}"
COGMENT_LOG_LEVEL: info
DIR_PORT: 9010
COGMENT_DIRECTORY_ENDPOINT: "grpc://server:{{.DIR_PORT}}"
folder: /app

scripts:
prep:
commands:
- ["./importdata.sh"]
- ["./cudasetup.sh"]
- ["sleep", "infinity"] # To prevent process from ending
ready_output: "^Done"
directory:
quiet: true
folder: ./cogment
environment:
COGMENT_DIRECTORY_PORT: "{{.DIR_PORT}}"
depends_on:
- prep
commands:
- ["cogment", "services", "directory"]
ready_output: 'Listening \[port:[0-9]*\]' # To match "Listening [port:9010]"
orchestrator:
folder: ./cogment
environment:
COGMENT_ORCHESTRATOR_ACTOR_PORT: 0
COGMENT_LIFECYCLE_PORT: 0
depends_on:
- directory
commands:
- ["cogment", "services", "orchestrator"]
runner:
folder: ./pycode
depends_on:
- directory
- orchestrator
commands:
- [
"python3",
"runner.py",
"-u {{.USER}}",
"-n {{.RUN_NAME}}",
"{{.__2}}",
]
report:
commands:
- ["reporting_service"]