pyinfra-dev / pyinfra

pyinfra turns Python code into shell commands and runs them on your servers. Execute ad-hoc commands and write declarative operations. Target SSH servers, local machine and Docker containers. Fast and scales from one server to thousands.
https://pyinfra.com
MIT License
3.91k stars 383 forks source link

host.get_fact(Crontab) is not able to handle crontab-level environment variables like CRON_TZ #1191

Open JakkuSakura opened 2 months ago

JakkuSakura commented 2 months ago

Describe the bug

I need to enforce CRON_TZ=UTC in my crontab. changing machine's timezone is not possible But pyinfra can't parse the line:

Traceback (most recent call last):
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra_cli/util.py", line 65, in exec_file
    exec(PYTHON_CODES[filename], data)
  File "***.py", line 15, in <module>
    server.crontab(
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/api/operation.py", line 295, in decorated_func
    for _ in command_generator():
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/api/operation.py", line 282, in command_generator
    for command in func(*args, **kwargs):
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/operations/server.py", line 655, in crontab
    crontab = host.get_fact(Crontab, user=user)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/api/host.py", line 350, in get_fact
    return get_host_fact(self.state, self, name_or_cls, args=args, kwargs=kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/api/facts.py", line 320, in get_host_fact
    return get_fact(state, host, cls, args=args, kwargs=kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/api/facts.py", line 188, in get_fact
    return _get_fact(
           ^^^^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/api/facts.py", line 272, in _get_fact
    data = fact.process(stdout_lines)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/lib/python3.12/site-packages/pyinfra/facts/server.py", line 437, in process
    minute, hour, day_of_month, month, day_of_week, command = line.split(None, 5)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 6, got 1)

To Reproduce

Steps to reproduce the behavior, please include where possible:

Expected behavior

pyinfra handles this CRON_TZ, or at least ignore it

Meta

JakkuSakura commented 2 months ago

More severely, the operation erases all comments and the environment variables