SaltStack – Handy scripting Tips


 Scripting Salt Commands – Updated 2015-02-17

Some handy tips for creating useful Salt scripts. These are excerpts from working files with the identifiers changed as needed. To use, create a text file in the /srv/salt root directory (or use a sub directory under that) and add the blue text from the appropriate tip into the file.

Things to keep in mind:

  • The first ID is usually an identifier and you cant duplicate them in Salt if you are using “include” to include a number of scripts.
  • Each line is indented by 2 spaces for YAML to process, the first line (the identifier) has no indentation, the next has 2 and then anything under that has 4 spaces. DO NOT USE TABS!

 Task: Add some packages – basic method

At the start of your script you might need to ensure that the required packages are installed. You can do this with:

#========================================
#
# install packages
#
autoconf:
 pkg.installed
automake:
 pkg.installed
libtool:
 pkg.installed
/opt/installdir:
 file.directory:
 - mode: 775

 

Task: Add a CRON file entry on the Salt-Minion

This script will create an entry on the Salt Minions CRONTAB with the parameter line in “name” and run it every minute. In salt you can set an Identifier (must be unique) so you can delete the crontab line based on ID values (very handy).

cron-entry-for-example-program:
 cron.present:
   - user: root
   - name: '/opt/my-new-directory/my-shell-script.sh > /dev/null 2>&1'
   - minute: '*'
   - hour: '*'
   - daymonth: '*'
   - month: '*'
   - dayweek: '*'
   - identifier: 'id-every-minute-script'
   - comment: 'Installed via Salt'

 

Task: Need to create a directory on the salt minion?

Using “file.directory”, the command below sets the owner to root and the permissions to 755, if the directory is already present the command ensures the permissions and owner/group are set accordingly:

/opt/my-new-directory:
 file.directory:
   - user: root
   - group: root
   - mode: 755

Task: Need to create an “install all” file?

This 3 line example references two other .SLS files and runs them in order. Make sure all identifiers are unique or Salt will return an error.

include:
 - .installscripts
 - .cronscript

lets extend this script a little, lets say you have a script in /srv/salt/common/setupcron.sls and you have a script to setup a RabbitMQ server with specialized parameters in an SLS file called /srv/salt/servers/rabbitmqsetup.sls

If you want to call the setup cron script in your install sls file, you can reference it with:

include:
 - common.setupcron
 - .installscripts
 - .cronscript

 

Task: Need to create Symbolic Links under Linux?

Using file.symlink, the identifier is the symlink to create and target is the real file. In this example a Rabbit MQ shared Object file in /opt/rabbitmq is referenced via symlinks in /lib64.

/lib64/librabbitmq.so:
 file.symlink:
 - target: /opt/rabbitmq/librabbitmq.so.1.1.1
/lib64/librabbitmq.so.1:
 file.symlink:
 - target: /opt/rabbitmq/librabbitmq.so.1.1.1
/lib64/librabbitmq.so.1.1:
 file.symlink:
 - target: /opt/rabbitmq/librabbitmq.so.1.1.1

 

Task: Copy a .zip file to a minion and unzip it into a different directory.

This script is in two parts, first copy file to minion and set permissions etc, then the archive “master.zip” is unzipped into a new directory called /opt/rabbit-c-0.5

/opt/xxx/master.zip:
 file:
 - managed
 - source: salt://common/mq/master.zip
 - mode: 664
 - user: root
 - group: root
master.zip:
 module.run:
 - name: archive.unzip
 - zipfile: /opt/xxx/master.zip
 - dest: /opt/rabbitmq-c-0.5

 

Task: Untar a .tar archive

Like our zip file example above, but this time a .tar archive, note the “options” line.

/opt/master.tar:
 module.run:
 - name: archive.tar
 - options: xvf
 - tarfile: /opt/master.tar
 - dest: /opt

 

Task: Add a user to the Minion

In this example we create an account for a daemon that needs a user account but does not allow log in’s. The user account to create is “collectd”. More information on the user add command is available at http://docs.saltstack.com/en/latest/ref/states/all/salt.states.user.html

collectd:
 user.present:
 - fullname: 'Collectd Daemon'
 - createhome: false
 - shell: /bin/nologin

To enable the user to login, change the “shell” line to “/bin/bash” and change “createhome” to “true”.

Task: Create a group with the same name as the user:

www-app:
 user.present:
 - fullname: 'Web Data App'
 - createhome: false
 - shell: /bin/nologin
group.present:
 - addusers:
 - www-app

Task: Apply a script to a group of CloudLinux Servers

This command uses Grains to find all the CloudLinux servers and runs an SNMP install.sls script, the install.sls script is located in /srv/salt/common/snmp. The -G option tells SaltStack to use Grains to target a group of servers.

salt -G 'os:CloudLinux' state.sls common.snmp.install

 

Task: Running multiple Commands remotely on the Minion

service speciald stop:
  cmd.run

or use:

stop-my-service:
  cmd.run:
    - name 'service speciald stop'

Note: there are different ways to start a service, this example is to show the cmd.run formats not “services”.

 

Create a MySQL Database, User and Set Permissions

This block of code creates a database if NOT present and defines the user with permissions. The script also sets the password via a variable which is hand if the variable is reused in other parts of the script later.

#
# create and setup the DB
#
keystone:
 mysql_database:
 - present
 mysql_grants.present:
 - grant: all privileges
 - database: keystone.*
 - user: keystone
 - host: localhost
 mysql_user.present:
 - host: localhost
 - password: {{ KEYSTONE_DBPASS }}
 - connection_charset: utf8
 - saltenv:
 - LC_ALL: "en_US.utf8"

 

Creating Multiple DB’s in a loop

To create multiple databases on the same server and with basically the same user permissions you can use a Jinja for loop calling the SaltStack commands in a classic “for” loop as show below (here we are creating some Openstack databases), our database password is set in a variable as is the database name and user name (set in the DB variable by the for loop):

{% set DATABASE_PASS = 'our-db-password' %}
{% for DB in ['keystone','nova','cinder','glance','heat','neutron'] %}
{{ DB }}:
mysql_database:
 - present
 mysql_grants.present:
 - grant: all privileges
 - database: {{ DB }}.*
 - user: {{ DB }}
 - host: localhost
 mysql_user.present:
 - host: localhost
 - password: {{ DATABASE_PASS }}
 - connection_charset: utf8
{% endfor %}

Task: Add a custom grain to a host

It is often useful to just use a grain to target a number of hosts. Lets say we want to run a command (in this example a special report program) on a group of hosts that have a certain grain set. The grain might be called ‘dfreport’ and it is set to ‘True’.

First we set the grain against the host(s) when we initially set up the host the first time.

salt 'hostname-goes-here.com' grains.setvals "{'dfreport':'True'}"

Now when we want to target all hosts with the dfreport grain, we can use:

salt -G 'dfreport:True' cmd.run '/usr/local/bin/dfreport'

We can see which hosts have the grain by doing a ping prior to running the program just to be safe:

salt -G 'dfreport:True' test.ping

Always More to come!

-oOo-

 

 

4 thoughts on “SaltStack – Handy scripting Tips”

  1. very helpful!

  2. Thanks for the pointers!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s