I'm writing a custom state module with the purpose of creating a file in a given location with (partly) configurable content.
Basically I'm looking to shorten the following SLS (simplified for the purpose of this question, more complex in reality)...
/etc/foo/bar:
file.managed:
- contents: Hello World
...to this:
bar:
my_module.foo:
- message: World
Since this functionality is basically a more specialized version of the file.managed
state, it would be useful for me to re-use the file.managed
state in my custom state module.
Is there any way to call the file.managed
state module from my own state module?
What I've tried already (unsuccesfully):
Importing salt.states.file
and calling salt.states.file.managed
:
import salt.states.file
def foo(name, message, **kwargs):
return salt.states.file.managed(name='/etc/foo/%s' % name,
contents='Hello %s' % message,
**kwargs)
This results in an error message:
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
Using __salt__['file.managed']
:
def foo(name, message, **kwargs):
return __salt__['file.managed'](name='/etc/foo/%s' % name,
contents='Hello %s' % message,
**kwargs)
Which also results in a (different) error message (which is unsurprising, as the documentation explicitly states that __salt__
only contains execution modules, and not state modules):
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'
I found a solution using the state.single
execution module:
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]
The state.single
module returns a data structure like the following:
{
'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': '...'}
}
}
The inner object (everything under the file_|-/etc/foo/bar_|-/etc/foo/bar_|-managed
) is what the file.managed
module would return by itself, so you can re-use this value as your custom state's return value.