Documentation
Breaking changes
Behaviour changes that can affect existing scripts, with how to migrate them. New features
(failed_when, quiet, no_log, meta: exit, include export, defaults, stdio modes, pause
input) are described in Tasks and the module pages.
Changes since 2.21.0
Results and failures
- Non-zero exits are results. When
command,shellorscriptexits non-zero, the task now produces a result withrc,stdout/output,stderr,failed: trueand anerror(command exited with code 3: <stderr>). Before, the task returned an error with only the stderr text and registered nothing. A process killed by a signal reportsrc = 128 + signal. To accept some exit codes, usefailed_when(for examplefailed_when: result.rc not in [0, 1]) instead ofignore_errors. See Process failures are results. ignore_errorsregisters the failed result. The registered variable keepsfailed: true,rc,stderranderror, and an ignored failure reportschanged: truewhen the module did. Before, nothing was registered, so{{ result }}was undefined. Test it withresult is failed.ignore_errorsalso covers template and condition errors. An undefined variable in the params,when,changed_whenorfailed_whenof a task withignore_errors: trueis now ignored like any other failure instead of stopping the script.untilretries failed attempts. An attempt that fails (for example a non-zero exit) is retried instead of failing the task at once. When retries run out, the task fails withuntil condition not satisfied after N retries, whichignore_errorscan ignore; the registered result hasfailed: true.untilsees the taskvarslikewhendoes, and a task skipped bywhenis not retried.resultin conditions.changed_whenandfailed_whensee the current result asresultand under theregistername, shadowing variables with those names.- Registered result shape. Every registered result has
changed,failed,output,stdout(alias ofoutput),extraanderror, plus the non-conflicting keys ofextraat the top level. Code that dumps or iterates a whole result sees the new keys. - Loops register every item. The registered variable is the last item’s result, with
changedandfailedtrue when any item changed or failed, the first item’serror, and aresultslist with each executed item’s result (including itsitem), soresult is failedandresult.results | map(attribute='rc')work. Before, the first item’s result was kept and there was noresults.set_varsinside a loop keeps the last item’s value. --output jsonresults havefailed, next tochanged,outputandextra.- A failing
command,shellorscriptprints its result line (with the process output) before the error, like a successful one. - Async results contain stdout only (stdout and stderr were merged before), plus
rcandstderr. A job exiting non-zero gives a failed result. - Async loops with a positive
pollregister the same shape as synchronous loops (last item plusresults, see above):rash_job_idsand thejob_idof each item are no longer included, andchanged_when/failed_whenare evaluated per item withitemin scope.poll: 0still registersrash_job_ids. async_statusandasync_pollfail when the job failed, with the job error as task error. Before they reported success withfailed: trueinside the result. Useignore_errors: trueorfailed_whento inspect a failed job.rescueandalwayschanges count. A task with arescueoralwayssection reportschanged: truewhen the section changed something, so it can nownotifyhandlers. Ablockitself never reportschanged:registerandnotifyon a block see no change, use them on its child tasks.
Modules
pausealways reportschanged: false. With no seconds or minutes it outputs nothing instead of"0", and it prints itsprompteven then.scriptparsesargsandexecutablewith shell-like quoting:args: "'a b' c"passes two arguments (it was split on whitespace before) andexecutable: "python3 -u"is split into program and arguments (it was used verbatim before). A word starting with#begins a comment, inargs,executable,cmdwithtransfer_pidand shebang lines: quote it (args: "'#channel'"). The whole shebang line is honored (#!/usr/bin/env shworks) and check mode is supported: under--checkthe script is no longer run, but a missing file is still an error.no_logon anasynctask covers the task that starts the job only: theasync_statusorasync_polltask that reports its output needs its ownno_log.commandandscriptinherit stdin likeshellalready did (it was/dev/null). A process reading stdin can now consume Rash’s input or wait for terminal input; passstdin: ""to give it an empty stdin.- Async jobs get an empty stdin unless
stdinis given. Before, they inherited Rash’s stdin, so on a terminal they could be stopped waiting for input until their timeout. commandwithtransfer_pidsplitscmdwith shell-like quoting instead of whitespace, rejectsstdinand runs withstdout/stderr: captureorteeasinherit: nothing is left to capture once Rash is replaced. When the program cannot be executed (missing or not executable), Rash exits with status 1 and an error naming it, also underignore_errorsor insiderescue, with or withoutbecome. Before, it was an ordinary task failure.metarejects unknown parameters.
Parsing and validation
- Invalid
become_methodis an error. Before, it logged a warning and fell back to the global method. - Unknown top-level keys of the mapping script form (anything but
tasks,handlersanddefaults) are errors. Before, they were ignored. rescueandalwaysmust be lists, checked when the task is parsed instead of when the section runs: for top-level tasks when the script is parsed; for tasks inside ablock, an included file or arescue/alwayssection when that block, file or section runs.- Typed task attributes must have the right YAML type.
become,check_mode,ignore_errors,quietandno_logmust be booleans, andretries,delay,asyncandpollintegers. A string, including a template (retries: "{{ n }}"), is now a parse error. Before, it was silently ignored and the default used.
Privilege escalation and check mode
becomeandcheck_modeonblockandincludeapply to every child task, and each child escalates on its own. Before,check_mode: trueon a block or include was ignored and its children ran for real, andbecomeran the whole block as the become user. Control-flow modules (block,include,meta,set_vars,debug,assert,fail,pause,async_status,async_polland custom modules) always run in the Rash process. A child cannot disable an inheritedbecomeorcheck_mode.rescueandalwaysrun as part of their task. Their tasks see the taskvarsand inherit itsbecomeandcheck_mode(before, they ran for real undercheck_mode: true). Withignore_errors: truea failure is no longer rescued:alwaysruns and the task is reported as an ignored failure instead of a success that notified handlers.become_method: syscallruns the task in a new child Rash process started as Rash’s user, which switches to the become user before running the task, taking that user’s supplementary groups, on Linux and macOS alike. Before, Rash forked itself and the child kept Rash’s supplementary groups (all of root’s groups when running as root).commandwithtransfer_pidandbecome_method: syscallswitches user in Rash itself and exits Rash when the program cannot be executed (see Modules). Before, Rash had already switched to the become user and went on running the remaining tasks as that user.become_method: sudoto a non-root user other than the current one is refused unless Rash runs as root: task data is exchanged through private files that user could not read.- Async tasks with
becomerun the job as the become user, with that user’s supplementary groups (it was ignored before);become_method: sudois rejected for async tasks. - Async tasks in check mode do not start the job; they report the change they would make.
Signals
- Ctrl-C, SIGTERM and SIGHUP stop the script with exit status
128 + signal(130, 143, 129) and kill running async jobs. Before, Rash died from the default signal action, leaving its child process and async jobs running. - While a
command,shellorscriptprocess runs, signals sent withkillare forwarded to it, Rash waits for it, and then stops the script:ignore_errors,failed_when,rescueand loops do not swallow the interruption, butalwayssections run. A terminal Ctrl-C that the process handles itself (it exits normally) does not stop Rash. - Between tasks or during an in-process module (
pause,copy, async polling, …) Rash exits immediately, without runningalwayssections.