blog Wrapping a Salt Module

Tags:
docker python saltstack deployment

I use saltstack to manage deployment of docker containers in my homelab. For two of my cloud servers, I am running them in memory constrained environments for cost reasons, and typically only run the minimum required there.

Since I wanted to wrap the docker_container module, I started by creating my own state in _states/docker_customized. I can do a simple naive version, just by using setdefault

# _states/docker_customized.py
def running(name, **kwargs):
    kwargs.setdefault("mem_limit", "1024M")
    kwargs.setdefault("oom_score_adj", 100)

    return __states__["docker_container.running"](name, **kwargs)

If I then do a find replace on s/docker_container.running/docker_customized.running/g, then when I use state.apply on a target, it will call my method, update the values I want, before calling the original with the updated parameters (I may also need to update any watch or requires entires as needed).

I can then take this further, and do more specific logic, like basing the limit on the server grains.

def running(name, **kwargs):
    if "mem_limit" not in kwargs:
        # if for whatever reason the grain is missing, we'll default to 1G
        total_mem = __grains__.get("mem_total", 1024)
        # Then we want to ensure our container limits to only 10% of total memory or a max of 1G
        default_limit = min(int(total_mem * 0.10), 1024)
        kwargs["mem_limit"] = f"{default_limit}M"

    # I just set a default value here without extra logic
    kwargs.setdefault("oom_score_adj", 100)

    # Call the parent state with our updated values
    return __states__["docker_container.running"](name, **kwargs)

I could also use this to validate the data before calling it, if I did some kind of check and returned a state dictionary on failure.

if not some_condition:
    return {
                "name": name,
                "changes": {},
                "result": False,
                "comment": "Failed some condition check"
            }

With this new change, hopefully I can keep the host system more responsive, even if a container misbehaves. Now that I know how easy it is to wrap some of these states, there may be some more I handle in the same way in the future.