config_ninja

Config Ninja 🥷

Ruff 🎨 poe (push) pylint codecov pre-commit.ci status Checked with mypy docs: pdoc readthedocs PyPI version Downloads

Similar to confd, manage your system configuration files by populating Jinja2 templates with data from a remote provider.

Installation

config-ninja is installed using the official installer or with pip / pipx. After installation, you can enable config-ninja as a systemd service.

Official Installer

The recommended way to install config-ninja is with the official installer:

curl -sSL https://config-ninja.github.io/config-ninja/install.py | python3 -

To view available installation options, run the installer with the --help flag:

curl -sSL https://config-ninja.github.io/config-ninja/install.py | python3 - --help
usage: install [-h] [--version VERSION] [--pre] [--uninstall] [--force] [--path PATH] [--backends BACKENDS]

Installs the latest (or given) version of config-ninja

options:
  -h, --help           show this help message and exit
  --version VERSION    install named version
  --pre                allow pre-release versions to be installed
  --uninstall          uninstall config-ninja
  --force              respond 'yes' to confirmation prompts; overwrite existing installations
  --path PATH          install config-ninja to this directory
  --backends BACKENDS  comma-separated list of package extras to install, or 'none' to install no backends

With pip / pipx

Alternatively, use pip / pipx to install [all available backends] (or choose a specific one):

pip install 'config-ninja[all]'

Enable the systemd Service

After installing config-ninja, enable it as a systemd service for the current user:

# omit '--user' to install the agent at the system level
config-ninja self install --user

How It Works

To demonstrate how the mechanics work locally:

  1. create a settings file for config-ninja:

    cat <<EOF >config-ninja-settings.yaml
    CONFIG_NINJA_OBJECTS:
      example-0:
        dest:
          format: json
          path: ./.local/settings.json
        source:
          backend: local
          format: toml
          init:
            kwargs:
              path: ./.local/config.toml
    EOF
    
  2. run config-ninja in monitor mode:

    config-ninja apply --poll
    
  3. in a separate shell, create the config.toml:

    cat <<EOF >./.local/config.toml
    [example-0]
    a = "first value"
    b = "second value
    EOF
    
  4. Inspect the settings.json file created by config-ninja:

    cat ./.local/settings.json
    
    {
      "example-0": {
        "a": "first value",
        "b": "second value"
      }
    }
    
  5. Make changes to the data in config.toml, and config-ninja will update settings.json accordingly:

    cat <<EOF >>./.local/config.toml
    [example-1]
    c = "third value"
    d = "fourth value
    EOF
    cat ./.local/settings.json
    
    {
      "example-0": {
        "a": "first value",
        "b": "second value"
      },
      "example-1": {
        "c": "third value",
        "d": "fourth value"
      }
    }
    

    Chances are, you'll want to update the config-ninja-settings.yaml file to use a remote backend (instead of local). See config_ninja.contrib for a list of supported config providers.

Configuration Architecture

The config-ninja agent monitors the backend source for changes. When the source data is changed, the agent updates the local configuration file with the new data:

sequenceDiagram loop polling config-ninja->>backend: query for changes end backend->>+config-ninja: [backend changed] fetch config config-ninja->>-filesystem: write updated configuration file

Navigation

config_ninja.contrib

For supported backends.

config_ninja.contrib.appconfig

Integrate with the AWS AppConfig service.

config_ninja.contrib.local

Use a local file as the backend.

config_ninja.cli

Commands and CLI documentation.

config_ninja.settings

For settings and configuration.

config_ninja.systemd

Integration with systemd.

 1""".. include:: ../../README.md
 2
 3# Navigation
 4
 5## `config_ninja.contrib`
 6
 7For supported backends.
 8
 9### `config_ninja.contrib.appconfig`
10
11Integrate with the AWS AppConfig service.
12
13### `config_ninja.contrib.local`
14
15Use a local file as the backend.
16
17## `config_ninja.cli`
18
19Commands and CLI documentation.
20
21## `config_ninja.settings`
22
23For settings and configuration.
24
25## `config_ninja.systemd`
26
27Integration with `systemd`.
28"""  # noqa: D415
29
30from __future__ import annotations
31
32import warnings
33from pathlib import Path
34
35import pyspry
36
37__version__ = '1.5.0a0'
38
39from config_ninja.settings import DEFAULT_PATHS, load
40from config_ninja.settings import resolve_path as resolve_settings_path
41
42__all__ = ['DEFAULT_SETTINGS_PATHS', 'load_settings', 'resolve_settings_path']
43
44DEFAULT_SETTINGS_PATHS = DEFAULT_PATHS
45"""Check each of these locations for `config-ninja`_'s settings file.
46
47The following locations are checked (ordered by priority):
48
491. `./config-ninja-settings.yaml`
502. `~/config-ninja-settings.yaml`
513. `/etc/config-ninja/settings.yaml`
52
53.. _config-ninja: https://config-ninja.readthedocs.io/home.html
54"""
55
56
57def load_settings(path: Path) -> pyspry.Settings:  # pragma: no cover
58    """(deprecated) Load the settings file at the given path.
59
60    This function is deprecated and will be removed in a future release. Use `config_ninja.settings.load()` instead.
61    """
62    warnings.warn(
63        '`config_ninja.load_settings()` is deprecated and will be removed in a future release. Use '
64        '`config_ninja.settings.load()` instead.',
65        DeprecationWarning,
66        stacklevel=2,
67    )
68    return load(path).settings
DEFAULT_SETTINGS_PATHS = [PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/config-ninja/checkouts/v1.5.0-alpha.0/config-ninja-settings.yaml'), PosixPath('/home/docs/config-ninja-settings.yaml'), PosixPath('/etc/config-ninja/settings.yaml')]

Check each of these locations for config-ninja's settings file.

The following locations are checked (ordered by priority):

  1. ./config-ninja-settings.yaml
  2. ~/config-ninja-settings.yaml
  3. /etc/config-ninja/settings.yaml
def load_settings(path: pathlib.Path) -> pyspry.Settings:
58def load_settings(path: Path) -> pyspry.Settings:  # pragma: no cover
59    """(deprecated) Load the settings file at the given path.
60
61    This function is deprecated and will be removed in a future release. Use `config_ninja.settings.load()` instead.
62    """
63    warnings.warn(
64        '`config_ninja.load_settings()` is deprecated and will be removed in a future release. Use '
65        '`config_ninja.settings.load()` instead.',
66        DeprecationWarning,
67        stacklevel=2,
68    )
69    return load(path).settings

(deprecated) Load the settings file at the given path.

This function is deprecated and will be removed in a future release. Use config_ninja.settings.load() instead.

def resolve_settings_path() -> pathlib.Path:
124def resolve_path() -> Path:
125    """Return the first path in `DEFAULT_PATHS` that exists."""
126    for path in DEFAULT_PATHS:
127        if path.is_file():
128            return path
129
130    raise FileNotFoundError('Could not find config-ninja settings', DEFAULT_PATHS)

Return the first path in DEFAULT_PATHS that exists.