NOTE: readme is a little outdated (although mostly correct).
Best source of truth is =--help=.

#+begin_src python :results drawer :exports results 
import dron; return dron.make_parser().description
#+end_src

#+RESULTS:
:results:
dron -- simple frontend for Systemd, inspired by cron.

- *d* stands for 'Systemd'
- *ron* stands for 'cron'

dron is my attempt to overcome things that make working with Systemd tedious
:end:


#+begin_src python :results drawer :exports results 
import dron; return dron.make_parser().epilog
#+end_src

#+RESULTS:
:results:

* What does it do?
In short, you type ~dron edit~ and edit your config file, similarly to ~crontab -e~:

: from dron.api import job
:
: # at the moment you're expected to define jobs() function that yields jobs
: # in the future I might add more mechanisms
: def jobs():
:     # simple job that doesn't do much
:     yield job(
:         'daily',
:         '/home/user/scripts/run-borg /home/user',
:         unit_name='borg-backup-home',
:     )
:
:     yield job(
:         'daily',
:         'linkchecker https://beepb00p.xyz',
:         unit_name='linkchecker-beepb00p',
:     )
:
:     # drontab is simply python code!
:     # so if you're annoyed by having to rememver Systemd syntax, you can use a helper function
:     def every(*, mins: int) -> str:
:         return f'*:0/{mins}'
:
:     # make sure my website is alive, it will send local email on failure
:     yield job(
:         every(mins=10),
:         'ping https://beepb00p.xyz',
:         unit_name='ping-beepb00p',
:     )


After you save your changes and exit the editor, your drontab is checked for syntax and applied

- if checks have passed, your jobs are mapped onto Systemd units and started up
- if there are potential errors, you are prompted to fix them before retrying

* Why?
In short, because I want to benefit from the heavy lifting that Systemd does: timeouts, resource management, restart policies, powerful scheduling specs and logging,
while not having to manually manipulate numerous unit files and restart the daemon all over.

I elaborate on what led me to implement it and motivation [[https://beepb00p.xyz/scheduler.html#what_do_i_want][here]]. Also:

- why not just use [[https://beepb00p.xyz/scheduler.html#cron][cron]]?
- why not just use [[https://beepb00p.xyz/scheduler.html#systemd][systemd]]?

:end:


* Setting up

1. install system dependencies (see =.ci/run= ) -- these are necessary for =dbus-python= library
2. install dron: =pip3 install --user git+https://github.com/karlicoss/dron=
3. install =sendmail= from your package manager if you want to recieve job failure emails

* Using
  
#+begin_src python :results value :exports results 
import dron; 
p = dron.make_parser()
p.prog = ''
p.epilog = ''
return p.format_help()
#+end_src

#+RESULTS:
#+begin_example
usage: [-h] [--marker MARKER] {monitor,past,edit,apply,lint,uninstall} ...

dron -- simple frontend for Systemd, inspired by cron.

- *d* stands for 'Systemd'
- *ron* stands for 'cron'

dron is my attempt to overcome things that make working with Systemd tedious

positional arguments:
  {monitor,past,edit,apply,lint,uninstall}
    monitor             Monitor services/timers managed by dron
    past                List past job runs
    edit                Edit  drontab (like 'crontab -e')
    apply               Apply drontab (like 'crontab' with no args)
    lint                Check drontab (no 'crontab' alternative, sadly!)
    uninstall           Uninstall all managed jobs

options:
  -h, --help            show this help message and exit
  --marker MARKER       Use custom marker instead of default `(MANAGED BY DRON)`. Possibly useful for developing/testing.
#+end_example


* Job syntax
  
The idea is that it's a simple python DSL that lets you define simple jobs with minimal friction.

However, if you wish you can pass arbitrary unit properties as keyword arguments as well.

* Caveats
- older systemd versions would only accept absolute path for =ExecStart=. That should be caught during =dron edit= though
  
* Potential improvements
- custom validation; at the moment it runs pylint, mypy and systemd verify
- make it more atomic?

  E.g. roll back all the changes until daemon-reload
- more failure report mechanisms?

  Ideally, benefit from [[https://github.com/dschep/ntfy][ntfy]]
  
** TODO add issues with various questions that I had in code?
  
