diff --git a/pyinfra/facts/server.py b/pyinfra/facts/server.py index 08c3deab7..56795becb 100644 --- a/pyinfra/facts/server.py +++ b/pyinfra/facts/server.py @@ -899,3 +899,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 + """ + + 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" +""" + + 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..cd535fca9 --- /dev/null +++ b/tests/facts/server.RebootRequired/alpine_reboot_required.json @@ -0,0 +1,13 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\n\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\n\necho \"no_reboot_required\"\n", + "output": [ + "reboot_required" + ], + "fact": true, + "setup": [ + ["touch", "/etc/alpine-release"], + ["uname", "-r", "5.15.0-1-alpine"], + ["mkdir", "-p", "/lib/modules"], + ["touch", "/lib/modules/5.15.0-2-alpine"] + ] +} \ No newline at end of file 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..139c4436e --- /dev/null +++ b/tests/facts/server.RebootRequired/freebsd_reboot_required.json @@ -0,0 +1,12 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\n\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\n\necho \"no_reboot_required\"\n", + "output": [ + "reboot_required" + ], + "fact": true, + "setup": [ + ["uname", "-s", "FreeBSD"], + ["freebsd-version", "-r", "13.2-RELEASE"], + ["freebsd-version", "-k", "13.2-RELEASE-p1"] + ] +} \ No newline at end of file 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..124f10777 --- /dev/null +++ b/tests/facts/server.RebootRequired/linux_no_reboot.json @@ -0,0 +1,7 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\n\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\n\necho \"no_reboot_required\"\n", + "output": [ + "no_reboot_required" + ], + "fact": false +} \ No newline at end of file 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..ba421b75e --- /dev/null +++ b/tests/facts/server.RebootRequired/linux_reboot_required.json @@ -0,0 +1,10 @@ +{ + "command": "\n# Get OS type\nOS_TYPE=$(uname -s)\n\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\n\necho \"no_reboot_required\"\n", + "output": [ + "reboot_required" + ], + "fact": true, + "setup": [ + ["touch", "/var/run/reboot-required"] + ] +} \ No newline at end of file