diff --git a/pyinfra/facts/server.py b/pyinfra/facts/server.py index 8f67d1da3..99221d554 100644 --- a/pyinfra/facts/server.py +++ b/pyinfra/facts/server.py @@ -661,7 +661,9 @@ def process(self, output) -> LinuxDistributionDict: for filename, content in parts.items(): with open( - os.path.join(temp_etc_dir, os.path.basename(filename)), "w", encoding="utf-8" + os.path.join(temp_etc_dir, os.path.basename(filename)), + "w", + encoding="utf-8", ) as fp: fp.write(content) @@ -901,3 +903,52 @@ def process(self, output): ) return limits + + +class RebootRequired(FactBase[bool]): + """ + Returns a boolean indicating whether the system requires a reboot. + + On Linux systems: + - Checks /var/run/reboot-required and /var/run/reboot-required.pkgs + - On Alpine Linux, compares installed kernel with running kernel + + On FreeBSD systems: + - Compares running kernel version with installed kernel version + """ + + @override + def command(self) -> str: + return """ +# Get OS type +OS_TYPE=$(uname -s) +if [ "$OS_TYPE" = "Linux" ]; then + # Check if it's Alpine Linux + if [ -f /etc/alpine-release ]; then + RUNNING_KERNEL=$(uname -r) + INSTALLED_KERNEL=$(ls -1 /lib/modules | sort -V | tail -n1) + if [ "$RUNNING_KERNEL" != "$INSTALLED_KERNEL" ]; then + echo "reboot_required" + exit 0 + fi + else + # Check standard Linux reboot required files + if [ -f /var/run/reboot-required ] || [ -f /var/run/reboot-required.pkgs ]; then + echo "reboot_required" + exit 0 + fi + fi +elif [ "$OS_TYPE" = "FreeBSD" ]; then + RUNNING_VERSION=$(freebsd-version -r) + INSTALLED_VERSION=$(freebsd-version -k) + if [ "$RUNNING_VERSION" != "$INSTALLED_VERSION" ]; then + echo "reboot_required" + exit 0 + fi +fi +echo "no_reboot_required" +""" + + @override + def process(self, output) -> bool: + return list(output)[0].strip() == "reboot_required" diff --git a/tests/facts/server.RebootRequired/alpine_reboot_required.json b/tests/facts/server.RebootRequired/alpine_reboot_required.json new file mode 100644 index 000000000..34dce95a3 --- /dev/null +++ b/tests/facts/server.RebootRequired/alpine_reboot_required.json @@ -0,0 +1,5 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\nif [ \"$OS_TYPE\" = \"Linux\" ]; then\n # Check if it's Alpine Linux\n if [ -f /etc/alpine-release ]; then\n RUNNING_KERNEL=$(uname -r)\n INSTALLED_KERNEL=$(ls -1 /lib/modules | sort -V | tail -n1)\n if [ \"$RUNNING_KERNEL\" != \"$INSTALLED_KERNEL\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\n else\n # Check standard Linux reboot required files\n if [ -f /var/run/reboot-required ] || [ -f /var/run/reboot-required.pkgs ]; then\n echo \"reboot_required\"\n exit 0\n fi\n fi\nelif [ \"$OS_TYPE\" = \"FreeBSD\" ]; then\n RUNNING_VERSION=$(freebsd-version -r)\n INSTALLED_VERSION=$(freebsd-version -k)\n if [ \"$RUNNING_VERSION\" != \"$INSTALLED_VERSION\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\nfi\necho \"no_reboot_required\"\n", + "output": ["reboot_required"], + "fact": true +} diff --git a/tests/facts/server.RebootRequired/freebsd_reboot_required.json b/tests/facts/server.RebootRequired/freebsd_reboot_required.json new file mode 100644 index 000000000..efb3732a5 --- /dev/null +++ b/tests/facts/server.RebootRequired/freebsd_reboot_required.json @@ -0,0 +1,4 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\nif [ \"$OS_TYPE\" = \"Linux\" ]; then\n # Check if it's Alpine Linux\n if [ -f /etc/alpine-release ]; then\n RUNNING_KERNEL=$(uname -r)\n INSTALLED_KERNEL=$(ls -1 /lib/modules | sort -V | tail -n1)\n if [ \"$RUNNING_KERNEL\" != \"$INSTALLED_KERNEL\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\n else\n # Check standard Linux reboot required files\n if [ -f /var/run/reboot-required ] || [ -f /var/run/reboot-required.pkgs ]; then\n echo \"reboot_required\"\n exit 0\n fi\n fi\nelif [ \"$OS_TYPE\" = \"FreeBSD\" ]; then\n RUNNING_VERSION=$(freebsd-version -r)\n INSTALLED_VERSION=$(freebsd-version -k)\n if [ \"$RUNNING_VERSION\" != \"$INSTALLED_VERSION\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\nfi\necho \"no_reboot_required\"\n", "output": ["reboot_required"], + "fact": true +} diff --git a/tests/facts/server.RebootRequired/linux_no_reboot.json b/tests/facts/server.RebootRequired/linux_no_reboot.json new file mode 100644 index 000000000..5ccba912c --- /dev/null +++ b/tests/facts/server.RebootRequired/linux_no_reboot.json @@ -0,0 +1,5 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\nif [ \"$OS_TYPE\" = \"Linux\" ]; then\n # Check if it's Alpine Linux\n if [ -f /etc/alpine-release ]; then\n RUNNING_KERNEL=$(uname -r)\n INSTALLED_KERNEL=$(ls -1 /lib/modules | sort -V | tail -n1)\n if [ \"$RUNNING_KERNEL\" != \"$INSTALLED_KERNEL\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\n else\n # Check standard Linux reboot required files\n if [ -f /var/run/reboot-required ] || [ -f /var/run/reboot-required.pkgs ]; then\n echo \"reboot_required\"\n exit 0\n fi\n fi\nelif [ \"$OS_TYPE\" = \"FreeBSD\" ]; then\n RUNNING_VERSION=$(freebsd-version -r)\n INSTALLED_VERSION=$(freebsd-version -k)\n if [ \"$RUNNING_VERSION\" != \"$INSTALLED_VERSION\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\nfi\necho \"no_reboot_required\"\n", + "fact": false, + "output": ["no_reboot_required"] +} diff --git a/tests/facts/server.RebootRequired/linux_reboot_required.json b/tests/facts/server.RebootRequired/linux_reboot_required.json new file mode 100644 index 000000000..34dce95a3 --- /dev/null +++ b/tests/facts/server.RebootRequired/linux_reboot_required.json @@ -0,0 +1,5 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\nif [ \"$OS_TYPE\" = \"Linux\" ]; then\n # Check if it's Alpine Linux\n if [ -f /etc/alpine-release ]; then\n RUNNING_KERNEL=$(uname -r)\n INSTALLED_KERNEL=$(ls -1 /lib/modules | sort -V | tail -n1)\n if [ \"$RUNNING_KERNEL\" != \"$INSTALLED_KERNEL\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\n else\n # Check standard Linux reboot required files\n if [ -f /var/run/reboot-required ] || [ -f /var/run/reboot-required.pkgs ]; then\n echo \"reboot_required\"\n exit 0\n fi\n fi\nelif [ \"$OS_TYPE\" = \"FreeBSD\" ]; then\n RUNNING_VERSION=$(freebsd-version -r)\n INSTALLED_VERSION=$(freebsd-version -k)\n if [ \"$RUNNING_VERSION\" != \"$INSTALLED_VERSION\" ]; then\n echo \"reboot_required\"\n exit 0\n fi\nfi\necho \"no_reboot_required\"\n", + "output": ["reboot_required"], + "fact": true +}