Documentation - Controller - Specification - Rule
Author: Kevin Day
Description: Controller program rule specification.
Keywords: Kevin Day, Kevux, FLL, Featureless, Linux, Library, Controller, Open-Source, Specification

# Controller Rule Specification

The version date of this specification is `2024/07/02`.

The Rule files follow the `FSS-000D (Basic Rule)` format with `IKI-0000 (Unrestricted)`.

A Rule file name is expected to have the file extension `.rule`.

For each Rule file:

- The outer most part is a `FSS-0002 (Basic List)`.
- The outer most part is a `FSS-0002 (Basic List)`.
- The Basic List Object is considered the Rule Type.
- The Basic List Content is determined by the specific Rule Type.
- The Content for each Rule Type is called the Item.
- Each Item Object is the Item Name.
- Each Item Content is either the Action or the Setting.
- Each Action Object is the Action Name.
- Each Action Content are the Action Parameters.
- Each Setting Object is the Setting Name.
- Each Setting Content are the Setting Values.

The Rule Types:

- `command`: Follows either `FSS-0003 (Extended List)` or `FSS-0001 (Extended)`.
- `script`: Follows either `FSS-0003 (Extended List)` or `FSS-0001 (Extended)`.
- `service`: Follows either `FSS-0003 (Extended List)` or `FSS-0001 (Extended)`.
- `settings`: Is required and follows either `FSS-0001 (Extended)`.
- `utility`: Follows either `FSS-0003 (Extended List)` or `FSS-0001 (Extended)`.

For the above Rule Types, `settings` may be specified only once whereas the others may be specifed multiple times.

The `settings` Rule Type is always processed first, regardless of position.

The other Rule Types are processed top-down.

The `settings` Rule Type has the following `FSS-0001 (Extended)`:

- `affinity`: One or more Content, each must be a 0 or greater whole number.
- `capability`: One Content representing capabilities.
- `cgroup`: Two or more Content, the first Content being either `existing` or `new` and the remaining representing a valid cgroup (control group) name, must have at least 1 graph character (non white space printing character) (leading and trailing white space are trimmed off).
- `define`: Two Content, the first Content must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
- `engine`: One or more Content representing a valid program name or path (such as `bash` or `/bin/bash`) and any optional arguments.
- `environment`: Zero or more Content, each must be a case-sensitive valid environment variable name (alpha-numeric or underscore, but no leading digits).
- `group`: One or more Content representing group names or group ids.
- `limit`: Three Content, with the first representing a valid resource type and the second and third being a valid resource limit number (positive whole number or 0).
- `name`: One Content, must have at least 1 graph character (non white space printing character) (leading and trailing white space are trimmed off).
- `nice`: One Content, must be a valid number for process niceness (Any whole number inclusively between -20 to 19).
- `on`: Four Content, the first being a Rule Action, the second being `need`, `want`, or `wish`, the third being a partial path, and the fourth being a Rule file name without `.rule` extension.
- `parameter`: Two Content, the first Content must be a case-sensitive valid IKI name and the second being an IKI value.
- `path`: One Content representing a valid PATH environment string (such as `/bin:/sbin:/usr/bin`).
- `scheduler`: One or two Content representing a scheduler name and the optional numeric priority (Any whole number inclusively between 0 and 99).
- `timeout`: One or two content with the first being one of `exit`, `start`, `stop`, or `kill` and the (optional) second Content being a positive whole number or 0.
- `user`: One Content representing a user name or user id.

The `command` and `script` Rule Types allow the following the `FSS-0001 (Extended)`:

- `freeze`: One or more Content representing a program being executed and its arguments.
- `kill`: One or more Content representing a program being executed and its arguments.
- `pause`: One or more Content representing a program being executed and its arguments.
- `reload`: One or more Content representing a program being executed and its arguments.
- `rerun`: Two or more Content representing a Rule type that executes and its properties.
- `restart`: One or more Content representing a program being executed and its arguments.
- `resume`: One or more Content representing a program being executed and its arguments.
- `start`: One or more Content representing a program being executed and its arguments.
- `stop`: One or more Content representing a program being executed and its arguments.
- `thaw`: One or more Content representing a program being executed and its arguments.
- `with`: One or more Content representing special options for the Rule Type.

The `service` and `utility` Rule Types allow the following the `FSS-0001 (Extended)`:

- `pid_file`: One Content representing the path to a PID file.
- `rerun`: Two or more Content representing a Rule type that executes and its properties.
- `with`: One or more Content being one of `full_path`, `session_new`, or `session_same`.

The `command` and `service` Rule Types allow the following the `FSS-0003 (Extended List)`:

- `freeze`: A list repesenting multiple programs and their respective arguments to execute.
- `kill`: A list repesenting multiple programs and their respective arguments to execute.
- `pause`: A list repesenting multiple programs and their respective arguments to execute.
- `reload`: A list repesenting multiple programs and their respective arguments to execute.
- `restart`: A list repesenting multiple programs and their respective arguments to execute.
- `resume`: A list repesenting multiple programs and their respective arguments to execute.
- `start`: A list repesenting multiple programs and their respective arguments to execute.
- `stop`: A list repesenting multiple programs and their respective arguments to execute.
- `thaw`: A list repesenting multiple programs and their respective arguments to execute.

The `script` and `utility` Rule Types allow the following the `FSS-0003 (Extended List)`:

- `freeze`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `kill`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `pause`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `reload`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `restart`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `resume`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `start`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `stop`: A list repesenting the contents of a script, such as a GNU Bash shell.
- `thaw`: A list repesenting the contents of a script, such as a GNU Bash shell.

The `rerun` Rule Type Content has the following structure.

- The first Content represents one of: `freeze`, `kill`, `pause`, `reload`, `restart`, `resume`, `start`, `stop`, or `thaw`.
- The second Content represents one of: `success` or `failure`.
- The third and more Content represents one of: `delay`, `max`, or `reset`.
- Where `delay` and `max` must be followed by a positive number or the number 0.

## Rule Documentation

This describes the intent and purpose of a Rule file.

A Rule file, such as `ssh.rule`, is intended to designate what to execute.

The rule file is read top-down, except for the outer most list `settings`, which is intended to store setting data for this rule. Multiple outer most list Objects may be specified and they are executed as provided, in a top-down manner.

The `settings` Rule Type has the following `FSS-0001 (Extended)` Content:

- `affinity`: Define one or more processors to restrict this rule by with each number representing a specific processor by its id (starting at 0).
- `capability`: Define a set of capabilities in which to use, using the capability `text` format (such as `= cap_chown+ep`).
- `cgroup`: Define a cgroup (control group) in which everything within this rule executes under.
- `define`: A single environment variable name and its associated value that is automatically exposed to processes executed within this rule.
- `engine`: An executable name of a script, such as `bash`, to use for the `script` Rule Type (which likely defaults to `bash` if not specified).
- `environment`: A set of environment variables to expose to the processes executed within this rule (`PATH` is always exposed).
- `group`: A set of group names or IDs to execute as with the first group being the primary group and all remaining being supplementary groups.
- `limit`: Define a resource limit to use (multiple limits may be specified, but only once for each type).
- `name`: A name used to represent this rule, which is printed to the user, screen, logs, etc...
- `nice`: A single niceness value to run all processes executed within this rule as (-20 gets to be greediest in CPU usage and 19 being the nicest in CPU usage).
- `on`: Define a Rule Action in which a specified dependency is needed, wanted, or wished for.
- `parameter`: An IKI name and its associated value for use in this rule file.
- `path`: A single Content used to set a custom `PATH` environment variable value.
- `scheduler`: A valid name of a scheduler to use followed by an optional priority number.
- `timeout`: A set of timeouts to wait for in which to perform a set action or to consider failure.
- `user`: A single user name or ID to execute as.

The `capability` setting:

- If the user the controller program is run as does not have the desired capabilities already, they cannot be added.
- This essentially maintains or reduces the capabilities already available.
- Due to capabilities only being a draft in the POSIX standard, one may expect `capabilities` support may not be available and in such a case this setting will do nothing.
- If the dependent project (f_capability) does not have libcap support enabled, then capabilities will be unsupported by the compilation of this project.

The `control` setting:

- The first argument is either `existing` or `new`, where for `existing` the process is run inside the existing control used by the parent and when `new` the process is executed within a new control group namespace entirely.

The `define` setting:

- Use this to define an environment variable (this overwrites any existing environment variable with this name).
- A define is both exported as an environment variable as well as exposed as an IKI variable.
- Example IKI variable substitution: for `define PATH /bin:/sbin`, the associated IKI variable would look like: `define:"PATH"`.
- All environment variables, including those defined using this, must be in the `environment` list to be exported to the executed process.
- Environment variables added here that are not added to the environment are still exposed as an IKI variable.

The `engine` setting:

- This engine is used for both `script` and `utility` Rule Types.
- The program that engine refers to must accept a standard input pipe to be supported.
- Additional parameters may be passed to the engine.

The `group` and `user` settings:

- Only users and groups that the user the controller program is being run as is allowed to use may be used.

The `limit` setting:

- The first parameter must be one of: `as`, `core`, `cpu`, `data`, `fsize`, `locks`, `memlock`, `msgqueue`, `nice`, `nofile`, `nproc`, `rss`, `rtprio`, `rttime`, `sigpending`, or `stack`.
- The second parameter represents the soft limit.
- The third parameter represents the hard limit.
- This may be specified multiply times, but only once for each type.

The `on` setting:

- The first parameter represents the Action the dependency exists under and must be one of: `freeze`, `kill`, `pause`, `reload`, `restart`, `resume`, `start`, `stop`, or `thaw`.
- The second parameter represents how the dependency is required and must be one of: `need`, `want`, or `wish`.
- The third parameter is a partial path to the rule file.
- The fourth parameter represents the name of the rule file.

In the case of the second parameter:

- A `need` designates that the dependent rule is required to be executed (must exist and must succeed).
- A `want` designates that the dependent rule is to be executed (may exist and if it does, then it must succeed).
- A `wish` designates that the dependent rule is to be executed (may exist and if it does, but it does not need to succeed).

In the case of `want` and `wish`, if the desired rule is either not found or is otherwise disabled, then this will not fail or otherwise block the wanting or wishing rule.

The `path` setting:

- When specified, the `PATH` environment variable is automatically added to the `environment` setting.

The `parameter` setting:

- Use this to define an IKI variable name and value.
- These do not conflict with environment variables and are not exposed as environment variables.
- Example IKI variable substitution: for `parameter hello world`, the associated IKI variable would look like: `parameter:"hello"`.

The `scheduler` setting:

- The valid range of the priority number is dependent on the scheduler.
- For example, non-real-time schedulers (such as `idle`) only support a value of 0 whereas real-time schedulers (such as `fifo`) only support an inclusive range of 1 to 99.
- Supported non-real-time schedulers are: `batch`, `idle`, and `other` (aka: `normal/default`).
- Supported real-time schedulers are: `deadline`, `fifo`, `round_robin`.

The `timeout` setting:

- (This is not currently implemented.)
- Provides settings for each of the three special situations: `kill`, `start`, and `stop`.
- Each of these may only have a single one exist at a time (one `kill`, one `start`, and one `stop`).
- Each successive `timeout` Item Action, specific to each Action Name (such as `start`), specified replaces the previously defined `timeout` Action (in a top-down manner).
- The second Content for each of these, when specified, may be a 0 or greater whole number representing the number of MegaTime (MT) (equivalent to milliseconds).
- For `kill`, this represents the number of MegaTime to wait after stopping some Rule and that Rule has not yet stopped to forcefully stop the Rule (aka kill the Rule).
- For `start`, this represents the number of MegaTime to wait after starting some Rule before assuming something went wrong and the Rule is returned as failed.
- For `stop`, this represents the number of MegaTime to wait after stopping some Rule before assuming something went wrong and the Rule is returned as failed.
- If the second Content is not specified, then this disables the type (prevents the specified timeout action).

There are four available Rule Types to choose from: `command`, `service`, `script`, and `utility`.

The `command` Rule Type provides a simple command to run under the different circumstances: `start`, `stop`, `restart`, and `reload`.
A `command` always operates in the foreground.

The `service` Rule Type provides a `command` accompanied with a PID file (Process Identifier file).

The `script` Rule Type provides a series of lines to be executed by some engine, such as GNU Bash.
This `script` operates in the foreground, but individual things done within the script may operate in foreground or background.
The last return state is treated as an error, so be sure to finish the script with a return code of 0 to designate no error and any other whole number, such a 1, to designate an error.
Therefore passing `exit 1` would return as an error and passing `exit 0` would return as a success.
A `script` is assumed to be in GNU Bash, which is the default expected behavior, but the specification does not explicitly require this.
Another scripting language can be used but changing this incurs the responsibility to ensure all rules are updated to the appropriate scripting language.

The `utility` Rule Type provides a `script` accompanied with a PID file (Process Identifier file).

There are nine Rule Actions used to execute (`freeze`, `kill`, `pause`, `reload`, `restart`, `resume`, `start`, `stop`, and `thaw`):

When `restart` Object's Content is not provided, then `start` and `stop` is called when the rule is executed using the restart Action, if both `start` and `stop` are provided.

When `reload`, `start`, or `stop` Object's Content are not provided, then no respective Action is performed.

Commands are conditionally available depending on the presence of these, such as if `stop` is not provided then `stop` (and `restart`) will not be available for the `control` program(s) to use.

Thee are additional Rule Actions not used to execute (`pid_file`, `rerun`, and `with`):

- The `pid_file` Object's Content designates the path to the PID file created by the called program.
- The `rerun` Object's Content designates how to re-run a given execution Rule type.
  - The first Content represents the execution type, which may be one of: `freeze`, `kill`, `pause`, `reload`, `restart`, `resume`, `start`, `stop`, and `thaw`.
  - The second Content represents when to run this re-run is triggered, which is either `success` (return code of 0) or `failure` (return code is not 0).
  - The third Content and more represent additional options for fine tuning how the re-run is Performed:
    - When `delay`, followed by a number of MegaTime (MT) (equivalent to milliseconds) in which to wait before attempting the re-run.
    - When `max`, followed by a positive number or the number 0 designating the maximum number of re-runs to perform.
    - When `reset`, the `max` re-run counter is reset for the opposite re-run when this re-run is triggered, such as:
      - A `rerun start success reset` and a `rerun failure max 10`, the failure counter would reset to 0 when the `success` re-run is performed and not when the `failure` re-run is performed.
  - A `max` of 0 designates that the re-run will happen infinitely.
- The `with` Object's Content designates special flags designating very specific behavior to be applied to any single Rule Type.
  - The following flags are supported:
    - `full_path`: Used only by Rule Types that execute something, wherein the entire full path is used for execution and is assigned as `argument[0]` (such as `/bin/bash`).
    - When not specified, the path provided is used and the `argument[0]` will be the base name (such as `bash`).
    - `session_new`: Execute in a new session setting the process group to the executed process' id (making the executed process a `controlling terminal`).
    - `session_same`: Execute in the same session where the process group is set to the parent process id.

IKI Variables:

- All Rule Actions support IKI variable substitution.
- The Rule Settings do not support IKI variable substitution.
- The following IKI variable names are supported:
  - define
  - parameter
  - program

  The `define` IKI variables, such as `define:"PATH"`, expand environment variables.

  The `parameter` IKI variables, such as `parameter:"hello"`, expand IKI variables defined using the `parameter` Setting Rule Type.

  The `program` IKI variables, such as `program:"verbose:option"`, expand program arguments (where `verbose:option` might expand into `-v` ).

  Only the following `program` IKI variables are supported:

  - `dark`:
    - This variable holds the `dark` program parameters, such as `+d`.
    - This supports `:option`.
  - `light`:
    - This variable holds the `light` program parameters, such as `+l`.
    - This supports `:option`.
  - `no_color`:
    - This variable holds the `no_color` program parameters, such as `+n`.
    - This supports `:option`.
  - `quiet`:
    - This variable holds the `quiet` program parameters, such as `+Q`.
    - This supports `:option`.
  - `error`:
    - This variable holds the `error` program parameters, such as `+E`.
    - This supports `:option`.
  - `normal`:
    - This variable holds the `normal` program parameters, such as `+N`.
    - This supports `:option`.
  - `verbose`:
    - This variable holds the `verbose` program parameters, such as `+V`.
    - This supports `:option`.
  - `debug`:
    - This variable holds the `debug` program parameters, such as `+D`.
    - This supports `:option`.
  - `cgroup`:
    - This variable holds the `cgroup` program parameters, such as `-c /sys/fs/cgroup/`.
    - This supports both `:option` and `:value`.
  - `daemon`:
    - This variable holds the `daemon` program parameters, such as `-d`.
    - This supports `:option`.
  - `init`:
    - This variable holds the `init` program parameters, such as `-I`.
    - This supports `:option`.
  - `interruptible`:
    - This variable holds the `interruptible` program parameters, such as `-i`.
    - This supports `:option`.
  - `pid`:
    - This variable holds the `pid` program parameters, such as `-p controller/run/default.pid`.
    - This supports both `:option` and `:value`.
  - `settings`:
    - This variable holds the `settings` program parameters, such as `-s controller/`.
    - This supports both `:option` and `:value`.
  - `simulate`:
    - This variable holds the `simulate` program parameters, such as `-S`.
    - This supports `:option`.
    - `socket`:
      - This variable holds the `socket` program parameters, such as `-k controller/run/default.socket`.
      - This supports both `:option` and `:value`.
    - `uninterruptible`:
      - This variable holds the `uninterruptible` program parameters, such as `-U`.
      - This supports `:option`.
    - `validate`:
      - This variable holds the `validate` program parameters, such as `-v`.
      - This supports `:option`.