salt.states.module

Execution of Salt modules from within states

Note

There are two styles of calling module.run. The legacy style will no longer be available starting in the Sodium release. To opt-in early to the new style you must add the following to your /etc/salt/minion config file:

use_superseded:
  - module.run

With module.run these states allow individual execution module calls to be made via states. Here's a contrived example, to show you how it's done:

# New Style
test.random_hash:
  module.run:
    - test.random_hash:
      - size: 42
      - hash_type: sha256

# Legacy Style
test.random_hash:
  module.run:
    - size: 42
    - hash_type: sha256

In the new style, the state ID (test.random_hash, in this case) is irrelevant when using module.run. It could have very well been written:

Generate a random hash:
  module.run:
    - test.random_hash:
      - size: 42
      - hash_type: sha256

For a simple state like that it's not a big deal, but if the module you're using has certain parameters, things can get cluttered, fast. Using the contrived custom module (stuck in /srv/salt/_modules/foo.py, or your configured file_roots):

def bar(name, names, fun, state, saltenv):
    return "Name: {name} Names: {names} Fun: {fun} State: {state} Saltenv: {saltenv}".format(**locals())

Your legacy state has to look like this:

# Legacy style
Unfortunate example:
  module.run:
  - name: foo.bar
  - m_name: Some name
  - m_names:
    - Such names
    - very wow
  - m_state: Arkansas
  - m_fun: Such fun
  - m_saltenv: Salty

With the new style it's much cleaner:

# New style
Better:
  module.run:
  - foo.bar:
    - name: Some name
    - names:
      - Such names
      - very wow
    - state: Arkansas
    - fun: Such fun
    - saltenv: Salty

The new style also allows multiple modules in one state. For instance, you can do this:

Do many things:
  module.run:
    - test.random_hash:
      - size: 10
      - hash_type: md5
    # Note the `:` at the end
    - test.true:
    - test.arg:
      - this
      - has
      - args
      - and: kwargs
      - isn't: that neat?
    # Note the `:` at the end, too
    - test.version:
    - test.fib:
      - 4

Where in the legacy style you would have had to split your states like this:

test.random_hash:
  module.run:
    - size: 10
    - hash_type: md5

test.nop:
  module.run

test.arg:
  module.run:
    - args:
      - this
      - has
      - args
    - kwargs:
        and: kwargs
        isn't: that neat?

test.version:
  module.run

Another difference is that in the legacy style, unconsumed arguments to the module state were simply passed into the module function being executed:

show off module.run with args:
  module.run:
    - name: test.random_hash
    - size: 42
    - hash_type: sha256

The new style is much more explicit, with the arguments and keyword arguments being nested under the name of the function:

show off module.run with args:
  module.run:
    # Note the lack of `name: `, and trailing `:`
    - test.random_hash:
      - size: 42
      - hash_type: sha256

If the function takes *args, they can be passed in as well:

args and kwargs:
  module.run:
    - test.arg:
      - isn't
      - this
      - fun
      - this: that
      - salt: stack

Modern Examples

Here are some other examples using the modern module.run:

fetch_out_of_band:
  module.run:
    - git.fetch:
      - cwd: /path/to/my/repo
      - user: myuser
      - opts: '--all'

A more complex example:

eventsviewer:
  module.run:
    - task.create_task:
      - name: events-viewer
      - user_name: System
      - action_type: Execute
      - cmd: 'c:\netops\scripts\events_viewer.bat'
      - trigger_type: 'Daily'
      - start_date: '2017-1-20'
      - start_time: '11:59PM'

It is sometimes desirable to trigger a function call after a state is executed, for this the module.wait state can be used:

add example to hosts:
  file.append:
    - name: /etc/hosts
    - text: 203.0.113.13     example.com

# New Style
mine.send:
  module.wait:
    # Again, note the trailing `:`
    - hosts.list_hosts:
    - watch:
      - file: add example to hosts

Legacy (Default) Examples

If you're using the legacy module.run, due to how the state system works, if a module function accepts an argument called, name, then m_name must be used to specify that argument, to avoid a collision with the name argument.

Here is a list of keywords hidden by the state system, which must be prefixed with m_:

  • fun
  • name
  • names
  • state
  • saltenv

For example:

disable_nfs:
  module.run:
    - name: service.disable
    - m_name: nfs

Note that some modules read all or some of the arguments from a list of keyword arguments. For example:

mine.send:
  module.run:
    - func: network.ip_addrs
    - kwargs:
        interface: eth0
cloud.create:
  module.run:
    - func: cloud.create
    - provider: test-provider
    - m_names:
      - test-vlad
    - kwargs: {
          ssh_username: 'ubuntu',
          image: 'ami-8d6d9daa',
          securitygroup: 'default',
          size: 'c3.large',
          location: 'ap-northeast-1',
          delvol_on_destroy: 'True'
      }

Other modules take the keyword arguments using this style:

mac_enable_ssh:
  module.run:
    - name: system.set_remote_login
    - enable: True

Another example that creates a recurring task that runs a batch file on a Windows system:

eventsviewer:
  module.run:
    - name: task.create_task
    - m_name: 'events-viewer'
    - user_name: System
    - kwargs: {
          action_type: 'Execute',
          cmd: 'c:\netops\scripts\events_viewer.bat',
          trigger_type: 'Daily',
          start_date: '2017-1-20',
          start_time: '11:59PM'
    }
salt.states.module.wait(name, **kwargs)

Run a single module function only if the watch statement calls it

name
The module function to execute
**kwargs
Pass any arguments needed to execute the function

Note

Like the cmd.run state, this state will return True but not actually execute, unless one of the following two things happens:

  1. The state has a watch requisite, and the state which it is watching changes.
  2. Another state has a watch_in requisite which references this state, and the state wth the watch_in changes.