Call state module from within state module
<p>I'm writing a <a href="https://docs.saltstack.com/en/latest/ref/states/writing.html" rel="nofollow">custom state module</a> with the purpose of creating a file in a given location with (partly) configurable content.</p>

<p>Basically I'm looking to shorten the following SLS (simplified for the purpose of this question, more complex in reality)...</p>

<pre><code>/etc/foo/bar:
  file.managed:
    - contents: Hello World
</code></pre>

<p>...to this:</p>

<pre><code>bar:
  my_module.foo:
    - message: World
</code></pre>

<p>Since this functionality is basically a more specialized version of the <a href="https://docs.saltstack.com/en/latest/ref/states/all/salt.states.file.html#salt.states.file.managed" rel="nofollow"><code>file.managed</code></a> state, it would be useful for me to re-use the <code>file.managed</code> state in my custom state module.</p>

<p><strong>Is there any way to call the <code>file.managed</code> state module from my own state module?</strong></p>

<hr>

<p>What I've tried already (unsuccesfully):</p>

<ol>
<li><p>Importing <code>salt.states.file</code> and calling <code>salt.states.file.managed</code>:</p>

<pre><code>import salt.states.file

def foo(name, message, **kwargs):
    return salt.states.file.managed(name='/etc/foo/%s' % name,
                                    contents='Hello %s' % message, 
                                    **kwargs)
</code></pre>

<p>This results in an error message:</p>

<pre><code>  File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1626, in call
    **cdata['kwargs'])
  File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1492, in wrapper
    return f(*args, **kwargs)
  File "/var/cache/salt/minion/extmods/states/my_module.py", line 14, in static_pod
    contents=yaml.dump(data, default_flow_style=False), **kwargs)
  File "/usr/lib/python2.7/dist-packages/salt/states/file.py", line 1499, in managed
    mode = __salt__['config.manage_mode'](mode)
NameError: global name '__salt__' is not defined
</code></pre></li>
<li><p>Using <code>__salt__['file.managed']</code>:</p>

<pre><code>def foo(name, message, **kwargs):
    return __salt__['file.managed'](name='/etc/foo/%s' % name,
                                    contents='Hello %s' % message, 
                                    **kwargs)
</code></pre>

<p>Which also results in a (different) error message (which is unsurprising, as the documentation explicitly states that <code>__salt__</code> only contains <em>execution</em> modules, and not <em>state modules</em>):</p>

<pre><code>  File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1626, in call
    **cdata['kwargs'])
  File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1492, in wrapper
    return f(*args, **kwargs)
  File "/var/cache/salt/minion/extmods/states/my_module.py", line 13, in static_pod
    return __salt__['file.managed'](name='/etc/foo/%s' % name,
  File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 900, in __getitem__
    func = super(LazyLoader, self).__getitem__(item)
  File "/usr/lib/python2.7/dist-packages/salt/utils/lazy.py", line 93, in __getitem__
    raise KeyError(key)
KeyError: 'file.managed'
</code></pre></li>
</ol>

<p>I found a solution using the <a href="https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.state.html#salt.modules.state.single" rel="nofollow"><code>state.single</code></a> execution module:</p>

<pre><code>def foo(name, messsage):
    result = __salt__['state.single'](fun='file.managed',
                                      name='/etc/foo/%s' % name,
                                      contents='Hello %s' % message,
                                      test=__opts__['test'])
    return result.items()[0][1]
</code></pre>

<hr>

<p>The <code>state.single</code> module returns a data structure like the following:</p>

<pre><code>{
  'file_|-/etc/foo/bar_|-/etc/foo/bar_|-managed': {
    'comment': 'The file /etc/foo/bar is set to be changed',
    'name': '/etc/foo/bar',
    'start_time': '08:24:45.022518',
    'result': None,
    'duration': 18.019,
    '__run_num__': 0,
    'changes': {'diff': '...'}
  }
}
</code></pre>

<p>The inner object (everything under the <code>file_|-/etc/foo/bar_|-/etc/foo/bar_|-managed</code>) is what the <code>file.managed</code> module would return by itself, so you can re-use this value as your custom state's return value.</p>

python salt-stack