step

keys that every step has

A step is one action on a host: a module with its arguments, or a recipe.

Form

A step is a map. It has one module key, such as pkg or file, with the arguments of the module as a map. Or it has recipe with the name of a recipe. Run winch doc <module> for the arguments of a module.

Computed values

Any module argument can be a template or an expression, and so can then. when takes an expression. loop takes a list or an expression.

Evaluation

On each host, winch evaluates when. When it is false, winch skips the step. Then winch evaluates loop, and the arguments for each element. winch checks the step on the host, and apply changes what differs.

Results

A step that runs a command counts as changed: a cmd, and a service with restarted or reloaded. When a step fails, its host stops. Other hosts go on.

Key order

winch fmt puts the step keys in this order: name, the module or recipe, vars, when, loop, then, confirm_access, notify.

Keys

KeyTypeDefaultMeaning
namestring-label in the plan and the logs
recipestring-recipe to run, in place of a module
varsmap-variable values for this recipe step
whenexpression-skips the step when false
looplist or expression-elements to run the step for, as item
thenstring-command after a change
confirm_accessbooleanfalseaccess check with rollback, for a service step
notifystring or list of strings-handlers to run after a change

step.name

string

Label in the plan and the logs. Without it, the plan shows the module and its main argument.

step.recipe

string

Recipe to run, in place of a module. A recipe step has only name, recipe, vars, and when. A recipe runs at most once per host in a run.

step.vars

map

Variable values for this recipe step. A value can be an !expr or a !tpl, and an !expr can use match(). They beat the inventory, and --set beats them. Only a recipe step has vars.

step.when

expression

Skips the step when false. It is an !expr that gives true or false. winch evaluates none of the other keys of a skipped step. when runs once, before loop, and cannot use item.

step.loop

list or expression

Elements to run the step for, as item. An !expr gives the list. loop: [] runs nothing and notifies nothing. A null element fails the host.

step.then

string

Command after a change. It runs right after the step changes something, before the next step. A failure of then fails the step. With loop, then runs once after the last element and cannot use item. A then that did not run stays pending on the host, and the next run runs it.

step.confirm_access

boolean, default false

Access check with rollback, for a service step. Only a service step can use it, in steps or in handlers. A firewall step gets the same check without it.

Before the step, winch keeps the old state of each path that the changed steps of the recipe wrote or removed in this run. It starts a 60-second rollback timer in a process of its own.

After the step, winch runs the access check: it opens a new SSH connection and runs a command, through sudo -n when the login user is not root. It tries twice, 5 seconds apart.

When both tries fail, winch puts back the old files and runs daemon-reload after a unit file. It reverses a start or a stop of the step, and reloads or restarts the unit again. The host fails with the error "the access check failed: <error>; the old files are back". When the SSH connection ends first, winch rolls back as it ends. When the helper is gone, the timer rolls back.

When a run ends before a notified handler with confirm_access ran, winch puts back the files of that handler at once. The next run applies the change again.

A rollback puts back files only. It does not undo a change of a user or a group.

step.notify

string or list of strings

Handlers to run after a change. Not a template or an expression. With loop, notify fires once when any element changed. Run winch doc handlers.

Example

# winch.yaml
name: demo
hosts:
  web1.example.com: {}
vars:
  sites: [blog, shop]
steps:
  - name: Install nginx
    pkg:
      name: nginx
  - name: Write the sites
    file:
      path: !tpl /etc/nginx/sites-enabled/{{ .item }}.conf
      content: !tpl "# {{ .item }}\n"
    when: !expr len(vars.sites) > 0
    loop: !expr vars.sites
    then: nginx -t
    notify: reload
handlers:
  reload:
    - service:
        name: nginx
        reloaded: true