Saltstack : Using and manipulating grains

The last blog post was about some generalities that you should learn before using Saltstack.
This post will carry in the same context, and the goal is to let the reader master more and more the usage of grains.

You will find here more specific information about using Saltstack grains, and may be some redundant tips.. but it will be a good opportunity for you to re-examine what you’ve seen during the last post. If you haven’t read it yet, I recommend doing it.

What are grains ?

Grains are data and they are one of the main component of Salt system.

Grains constitute a system for detecting static information about a system and storing it in RAM for rapid gathering.

We already saw some examples describing the usage of Saltstack CLI and grains.

Let’s see some others just to remember.

This will match all Ubuntu hosts:

This will match all minions with 64-bit CPUs, and return number of CPU cores for each matching minion:

Grains structures

Salt is a python-based software and offers the possibility to use the power of dictionaries and lists also but since writing grains is done with YAML, some changes happens.. I explain:

Nested structure : Dicts in YAML

Here is a python dict :

Here is its YAML notation:

key:
value

To make dictionaries nested, write it like this:

Writing the same thing in python:

Note: In YAML, the format is very important.

The specific number of spaces in the indentation is unimportant as long as parallel elements have the same left justification and the hierarchically nested elements are indented further.

source: wikipedia

If you want to keep it simple, use vim and use 2 spaces. To convert tabs to 2 spaces, type

and then

As an example, the grain “user” is a dict, one of its key is “env” and the latter have “integ” as a value:

and to implement the same grain in YAML:

For more understanding, follow the next example:

The following will match hosts that have a grain called “user”, with a key called “env”, which has a value that contains the word “integ” :

 Another host having the following as a grain will be also matched:

since “*integ*” matches both : “integ” & “integration”.

An environment called “INTEGRATION” will be matched :

Grains resolve to lower case letter.

YAML & Lists

What if want to translate this to a grain :

 grains.ls , grains.items & grains.get

Available grains can be listed by using the ‘grains.ls’ module:

Grains data can be listed by using the ‘grains.items’ module:

Grains have values that could be called via ‘grains.get <grain_name>’

Where “path” is a grain.

To use ‘grains.get’ with the two above examples (dict & list), you should use “:” to access to the next level of information in a nested grain:

Example: With this grain we have 3 levels

if you call

you will have “integ” as an output.

Organizing grains

You can put your grains in the default grain folder:

There is another alternative:

note : Search for “#grains” in your default minion file

Now, Imagine that you have hundreds of variables put into thousands of files(just like I had to deal with the first time I was using Salt). In this case, I usually create a folder that I call “config” under /etc/salt/

and then I call each one of them in the minion file.

Then I add my grains to those files, here is how you should do it :

Don’t forget to type “grains:” in the beginning of the file and then you will be able to declare your gains without having errors during the execution of “state.sls” or “state.highstate”.

Note that the default_include in saltstack is:

The minion can include configuration from other files. By default the minion will automatically include all config files from minion.d/*.conf where minion.d is relative to the directory of the minion configuration file.

Syncing Grains

After adding new configuration to salt, grains are automatically synced when state.highstate is called. Another alternative is to sync them manually:

or

The latter will sync grains and also modules, outputters, renderers, returners, states and utils.

Using Python API

Using Saltstack directly from your Python scripts is very useful especially if your main scripting language is Python. Saltstack has its Python API, just import the necessary libraries and the configuration. The next example is useful to read grains data:

Salt Caller

Salt caller is also an implemented functionality that you can use with Python API and its the same thing as salt-call.

Caller is the same interface used by the salt-call command-line tool on the Salt Minion.

 

Like salt-call, Caller should be done on Minion machine with Minion user (the user running salt-minion).

Link : http://docs.saltstack.com/en/latest/ref/clients/

Auto sync on startup

On the master, create /srv/reactor/sync_grains.sls with the following contents:

And in the master config file, add the following reactor configuration:

This will ask the master to give signals to each minion and synchronize its custom grains when it starts. So grains will be available when the initial highstate is executed.

Other types can be synced by replacing

or whatever else suits the intended use case.

Afterwork

Sometimes when everything goes wrong, I do something like:

Stop everything, clear all cache, restart everything.

Here are some commands that you can use:

 

I didn’t talk about everything concerning grains, for sure ! But I think that this is a good starting point for every sysadmin or devops. If you’re discovering Saltstack, go to the post called “Saltstack tutorial for beginners” it will be more helpful for you to start with.

If you liked this tutorial or if you want to expand your knowledge about SaltStack, I wrote a book about this tool, you can buy it here. For more information, please read “SaltStack For Devops – My New Book.

Happy Hacking.

You may also like...