Somewhat new to salt here. I set up salt and managed to get everything working rather nicely. After the setup, I decided to try make small state files and run those from another state file. The main reason being ease of troubleshooting/changing a small file vs. troubleshooting a huge state file. Unfortunately, outside of the top file, I haven't been successful in getting a state to be called from another state.
For example, let's say I have foo.sls and bar.sls, and bar.sls is a state that installs packages properly. I have tried the following.
#foo.sls
packages:
state.apply:
- source: salt://packages/bar.sls
Also
#foo.sls
packages/bar.sls:
state.apply
And also
#foo.sls
state.apply:
- source: salt://packages/bar.sls
And few others that I'm not remembering right now.
Most times I've tried though, I get an error stating that state.apply is not available, leading me to believe this is either not possible, or I'm going about it wrong.
Can this be done? If so, how? If not, maybe I'll file a feature request for this, as it seems like it could be useful.
It sounds like your issue may stem from mixing state modules and execution modules when you are writing your states.
Brief recap, "states" are the declarative files you write (foo.sls
, bar.sls
), "state modules" are the directives you list inside those states (e.g. pkg.installed
), and "execution modules" provide the commands that salt actually knows how to run (state.apply
, test.ping
, etc.).
state.apply
is simply the execution module that knows how to interpret states. It may help to note that the fully qualified name of state.apply
from the docs (or if you browse the salt source tree) is actually salt.modules.state.apply
, whereas pkg.installed
is salt.states.pkg.installed
. A module in the modules
namespace generally cannot be accessed from states
namespace and vice versa, though there are exceptions. Knowing the full namespace is also a necessary distinction when an execution module and a state modules share a virtual name, e.g. test
exists as both salt.modules.test
and salt.states.test
.
If I understand correctly, you probably want to include your state files within each other.
For example, say you have the following folder structure:
$ tree srv
srv
└── salt
├── foo.sls
└── packages
└── bar.sls
and bar.sls
has the following contents
# bar.sls
packages_bar_install_fun:
pkg.installed:
- pkgs:
- cowsay
- fortune
- sl
To include
bar.sls
into foo.sls
you just need to reference it using dot notation, depending on your folder structure
# foo.sls
include:
- packages.bar
foo_another_example_state:
test.show_notification:
- text: |
foo.sls can have other states inside of it,
though you may need to use `require` if you want
them interspersed between multiple includes
Now you can either just include - foo
in your top.sls
, or run salt '<tgt>' state.apply foo test=True
and you should see that package.bar
would also be applied.
The salt docs also include a section titled Moving Beyond a Single SLS which discusses using include
and extend
to glue multiple states together.
Splitting up an SLS for organizational purposes is also a common use for init.sls
As a brief aside, there are some states which go the other direction and allow allow you to run execution modules from within an SLS. A few examples are salt.states.module.run
and salt.states.saltmod.state
, though the uses for these are far more specialized than what it seems you're trying to do.