File entrypoint.py of Package docker-salt

#!/usr/bin/env python3

"""
Entrypint script for the docker-salt container
"""

import asyncio
import json
import os
import signal
from asyncio.subprocess import Process
from typing import List

import salt.client  # pylint: disable=import-error
import salt.config  # pylint: disable=import-error


def get_mode() -> str:
    """
    TODO
    """
    if "MODE" not in os.environ:
        mode = "master-api"
    else:
        mode = os.environ["MODE"]
    if mode not in ("master", "api", "minion", "proxy", "master-api"):
        raise ValueError(
            '"MODE" must be on of "master", "api", "minion", "proxy", "master-api"!'
        )
    return mode


def create_self_signed_cert():
    """
    TODO
    """
    # https://docs.saltproject.io/en/latest/ref/clients/index.html#salt.client.Caller
    # https://gitlab.com/saltstack/open/saltdocker/-/issues/20
    minion_opts = salt.config.minion_config("/etc/salt/minion")
    minion_opts["file_client"] = "local"
    caller = salt.client.Caller(mopts=minion_opts)
    caller.cmd("tls.create_self_signed_cert")


def handle_directories():
    """
    TODO
    """
    if not os.path.exists("/etc/salt"):
        raise FileNotFoundError('Required directory "/etc/salt" didn\'t exist')
    if not os.path.exists("/etc/salt/master.d"):
        os.mkdir("/etc/salt/master.d")
    if not os.path.exists("/etc/salt/proxy.d"):
        os.mkdir("/etc/salt/proxy.d")
    if not os.path.exists("/etc/saltminion.d"):
        os.mkdir("/etc/salt/minion.d")


def handle_api_conf():
    """
    TODO
    """
    if not os.path.exists("/etc/salt/master.d/api.conf"):
        with open("/etc/salt/master.d/api.conf", "w", encoding="UTF-8") as apifile:
            if "SALT_API_CONFIG" in os.environ:
                json.dump(json.loads(os.environ["SALT_API_CONFIG"]), apifile)
            else:
                create_self_signed_cert()
                json.dump(
                    {
                        "rest_cherrypy": {
                            "port": 8000,
                            "ssl_crt": "/etc/pki/tls/certs/localhost.crt",
                            "ssl_key": "/etc/pki/tls/certs/localhost.key",
                        },
                        "external_auth": {
                            "sharedsecret": {
                                "salt": [".*", "@wheel", "@jobs", "@runner"],
                            },
                        },
                        "sharedsecret": os.environ.get(
                            "SALT_SHARED_SECRET", "supersecret"
                        ),
                    },
                    apifile,
                )


def handle_minion_conf():
    """
    TODO
    """
    if "SALT_MINION_CONFIG" in os.environ:
        if not os.path.exists("/etc/salt/minion.d/minion.conf"):
            with open(
                "/etc/salt/minion.d/minion.conf", "w", encoding="UTF-8"
            ) as minion_file:
                json.dump(json.loads(os.environ["SALT_MINION_CONFIG"]), minion_file)


def handle_master_conf():
    """
    TODO
    """
    if "SALT_MASTER_CONFIG" in os.environ:
        if not os.path.exists("/etc/salt/master.d/master.conf"):
            with open(
                "/etc/salt/master.d/master.conf", "w", encoding="UTF-8"
            ) as masterfile:
                json.dump(json.loads(os.environ["SALT_MASTER_CONFIG"]), masterfile)


def handle_user_conf():
    """
    TODO
    """
    if not os.path.exists("/etc/salt/master.d/user.conf"):
        with open("/etc/salt/master.d/user.conf", "w", encoding="UTF-8") as userfile:
            # https://github.com/kubernetes/kubernetes/issues/81089
            json.dump({"user": "root"}, userfile)


def handle_proxy_conf():
    """
    TODO
    """
    if "SALT_PROXY_CONFIG" in os.environ:
        if not os.path.exists("/etc/salt/proxy.d/proxy.conf"):
            with open(
                "/etc/salt/proxy.d/proxy.conf", "w", encoding="UTF-8"
            ) as proxy_file:
                json.dump(json.loads(os.environ["SALT_PROXY_CONFIG"]), proxy_file)


async def main():
    """
    Main entrypoint for the entrypoint script.
    """
    futures: List[Process] = []
    mode = get_mode()
    handle_directories()

    if mode == "api":
        handle_api_conf()
        futures.append(await asyncio.create_subprocess_exec("salt-api"))
    elif mode == "master":
        handle_master_conf()
        handle_user_conf()
        futures.append(await asyncio.create_subprocess_exec("salt-master"))
    elif mode == "master-api":
        handle_api_conf()
        handle_master_conf()
        handle_user_conf()
        futures.append(await asyncio.create_subprocess_exec("salt-api"))
        futures.append(await asyncio.create_subprocess_exec("salt-master"))
    elif mode == "proxy":
        if "SALT_PROXY_ID" in os.environ:
            futures.append(
                await asyncio.create_subprocess_exec(
                    "salt-proxy", f'--proxyid={os.environ["SALT_PROXY_ID"]}'
                )
            )
        else:
            futures.append(await asyncio.create_subprocess_exec("salt-proxy"))

    elif mode == "minion":
        handle_minion_conf()
        futures.append(await asyncio.create_subprocess_exec("salt-minion"))

    await asyncio.gather(*[future.communicate() for future in futures])


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    for signame in ["SIGINT", "SIGTERM"]:
        loop.add_signal_handler(getattr(signal, signame), loop.stop)

    try:
        loop.run_until_complete(main())
    finally:
        loop.close()
openSUSE Build Service is sponsored by