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.