global directives ================= these directives can be used anywhere in your config file. they are not affected by the active section. In addition to the directives below, the parser also supports line-level conditional prefixes of the form ``ifdef SOME_DEFINE: key: value`` and ``ifndef SOME_DEFINE: key: value``. Those are documented further below in :ref:`global_conditional_lines`. Historically these directive spellings are not fully uniform: the various ``include`` directives are written without a trailing ``:``, while ``push_name_prefix:``, ``add_message_definition_dir:``, and ``add_process_default_template:`` are written with one. .. _include: include ------- syntax:: INCLUDE_DIRECTIVE := "include" + FILENAME + "\n" example: .. code-block:: lnc include my_subsystem.inc.lnc this directive can be used to read ln-config-directives from another file. it is useful to split up larger configs across multiple files. also parts of your config might be provided by some other project that provides such an include file. the included file will be read exactly the same way the main config file is read, with the only exception that names-prefixes :ref:`pushed` in an include file will automatically be pop'ed at the end of that file. optional_include ---------------- syntax:: OPT_INCLUDE_DIRECTIVE := "optional_include" + FILENAME + "\n" example: .. code-block:: lnc optional_include my_subsystem_for_%(host).inc.lnc same as the above :ref:`include` directive, but it's not considered as an error if the specified file does not exist. this is useful to conditionally include many directives only if some condition is matched - this can be achieved by using ``%()``-defines in that ``FILENAME``. include_glob & optional_include_glob ------------------------------------ syntax:: INCLUDE_GLOB_DIRECTIVE := "include_glob" + PATTERN + "\n" OPT_INCLUDE_GLOB_DIRECTIVE := "optional_include_glob" + PATTERN + "\n" example: .. code-block:: lnc include_glob cissygen/**/*.inc.lnc this directive can search for multiple include files and include them in the same way as the above :ref:`include` directive would do it. this is useful if you want to include many, possibly generated files where you don't want to explicitely spell the exact-filename. patterns are matches with python's ``fnmatch.fnmatch()``-function with the addition that ``**`` can match any sub-directory. pipe_include ---------------- syntax:: PIPE_INCLUDE_DIRECTIVE := "pipe_include" + COMMANDLINE + "\n" example: .. code-block:: lnc pipe_include python generate_ln_config.py this directive will execute the specified ``COMMANDLINE`` while the current config file is parsed. the standard-output from that command will be interpreted as if it would be contents of an include file, in exactly the same way as above with the :ref:`include`-directive. this can be used to procedurally generate processes, defines or any other config-directives. requires_version ---------------- syntax:: REQUIRES_VERSION_DIRECTIVE := "requires_version" + VERSION + "\n" example: .. code-block:: lnc requires_version 3.5.0 This directive aborts config loading unless the running ``ln_manager`` version is at least the specified version. Use this when a configuration depends on parser or manager behavior that is not available in older installations. The check is performed while reading the config file, before the rest of the file is processed further. .. _push_name_prefix: push_name_prefix ---------------- syntax: .. code-block:: lnc push_name_prefix: all objects (processes, groups, states) which are defined after this directive will get their name prefixed with ``/`` (note the additional ``/``). example: .. code-block:: lnc # ... push_name_prefix: MyPrefix process proc1 # ... process proc2 # ... push_name_prefix: SubSection process proc3 # ... pop_name_prefix process proc4 # ... will create 4 processes with these names: .. code-block:: lnc MyPrefix/proc1 MyPrefix/proc2 MyPrefix/SubSection/proc3 MyPrefix/proc4 this is mainly useful when having the instance-flag :ref:`instance-enable_auto_groups` set to ``true`` (see its description for more information). pop_name_prefix --------------- syntax: .. code-block:: lnc pop_name_prefix will remove the last :ref:`pushed` name prefix. warning ------- this directive can be used to output warnings to ln-managers log while reading the configuration. this can be useful for debugging: e.g. to print out the value of a define at a certain point within the configuration: syntax:: WARNING_DIRECTIVE := "warning: " + MESSAGE + "\n" MESSAGE := EVALUATED_STRING example: .. code-block:: lnc defines SOME_SETTING: value42 warning: value of SOME_SETTING: %(SOME_SETTING) the ``MESSAGE`` will be prefixed with the current configration file's name and the line-number within that file. example log-output could look like this:: 2021-11-16 10:54:32.97 warning SystemConfiguratio path/to/my/config.lnc:10: value of SOME_SETTING: value42 .. _global_conditional_lines: conditional config lines: ``ifdef`` and ``ifndef`` -------------------------------------------------- These are not separate sections. Instead, they are prefixes that conditionally enable or skip one normal ``key: value`` config line. You can think of them as a very small, line-based preprocessor, similar in spirit to C's ``#ifdef`` and ``#ifndef``. syntax:: IFDEF_LINE := "ifdef " + DEFINE_NAME + ": " + KEY + ": " + VALUE + "\n" IFNDEF_LINE := "ifndef " + DEFINE_NAME + ": " + KEY + ": " + VALUE + "\n" example: .. code-block:: lnc defines ENABLE_DEBUG_OUTPUT: 1 process demo ifdef ENABLE_DEBUG_OUTPUT: add environment: DEBUG_OUTPUT=1 ifndef LOG_LEVEL: add environment: LOG_LEVEL=info In the example above: * ``ifdef ENABLE_DEBUG_OUTPUT: ...`` is applied because ``ENABLE_DEBUG_OUTPUT`` exists and is non-empty. * ``ifndef LOG_LEVEL: ...`` is applied because ``LOG_LEVEL`` is not defined. The parser behaves as if the inner line had been written directly at that position: .. code-block:: lnc add environment: DEBUG_OUTPUT=1 add environment: LOG_LEVEL=info Important behavior and limitations: * ``ifdef`` checks whether the named define currently exists and has a non-empty value. * ``ifndef`` is the inverse: it applies the line only when the define is missing or currently set to the empty string. * The define name after ``ifdef`` / ``ifndef`` is taken literally. It is not string-evaluated, so write ``ifdef SOME_DEFINE: ...``, not ``ifdef %(SOME_DEFINE): ...``. * Only one normal ``key: value`` line can be guarded. The text after the condition must itself be one complete config line. * It works for normal section entries such as ``add environment: ...``, ``environment: ...`` or ``flags: ...``. * It also works for single-line directives and entries such as ``include ...``, ``optional_include ...``, ``include_glob ...``, ``pipe_include ...``, ``add_message_definition_dir: ...``, ``add_process_default_template: ...``, ``undef: ...``, ``push_name_prefix: ...``, ``pop_name_prefix``, ``warning: ...``, ``requires_version ...``, and entries in sections such as ``hosts``, ``node_map`` and ``custom_start_tools``. * It can also guard section-header lines such as ``process foo`` or ``state bar``, but this still affects only that one line. * Because these conditionals are line-scoped, they are not a block syntax. Guarding a section header does not automatically guard the following section body. If you need to conditionally include a larger block, use ``include`` / ``pipe_include`` together with ``ifdef`` / ``ifndef`` or restructure the config so each guarded item is a complete single line. * Multi-line values starting with ``[`` are still parsed as a single logical value. If the condition is false, the whole multi-line value is skipped. This is especially useful for optional process properties, environment entries, or per-project additions that should only be active when a define has been provided earlier in the configuration. ``undef`` --------- syntax:: UNDEF_LINE := "undef: " + DEFINE_NAME + "\n" example: .. code-block:: lnc defines ENABLE_LOGGING: 1 process demo ifdef ENABLE_LOGGING: add environment: ENABLE_LOGGING=1 undef: ENABLE_LOGGING ifdef ENABLE_LOGGING: add environment: THIS_LINE_WILL_NOT_BE_USED=1 ``undef`` removes a define from the current set of active defines. Behavior details: * removing a define that does not exist is silently ignored * the define name is taken literally and is not string-evaluated * this is often useful together with ``ifdef`` / ``ifndef`` when a define should only affect part of a configuration file .. _global/add_message_definition_dir: add_message_definition_dir -------------------------- syntax:: ADD_MESSAGE_DEFINITION_DIR := "add_message_definition_dir: " + DIRECTORY + "\n" example: .. code-block:: lnc add_message_definition_dir: %(CURDIR)/msg_defs This directive adds another directory to ln_manager's message-definition search path. The directory is appended to the end of the list of configured message-definition search paths, in the same order in which ``add_message_definition_dir`` directives appear in the config file. See also :doc:`reference_mdefs` for the detailed lookup rules. This is important because ln_manager must be able to find all message definitions that are used at runtime, for example: * topic message definitions used by configured processes and running clients * service message definitions The value is usually the directory that contains the top-level namespace folders of your message definitions. If a message definition is named ``my_project/some_type``, ln_manager will look for a file with that relative path below each known message-definition directory. Typical usage is to add a project-local message-definition directory near the top of the config file, before any processes or states that depend on those types are defined. add_process_default_template ---------------------------- syntax:: ADD_PROCESS_DEFAULT_TEMPLATE := "add_process_default_template: " + TEMPLATE_USE + "\n" example: .. code-block:: lnc add_process_default_template: shell with home("my_home", "echo hello") This directive registers a default ``use_template`` specification that is applied automatically to matching processes later in the configuration. Behavior details: * the directive is global and may appear anywhere in the config * it affects processes defined after it is read * the current :ref:`push_name_prefix` stack is stored with the directive, so the default template only applies to processes below that prefix * process-local ``use_template`` entries are still possible in addition to these defaults * processes can disable such automatically applied defaults with the ``no_default_templates`` flag This is useful when many processes in one part of the config should all inherit the same template without repeating ``use_template: ...`` in every process section.