Table of contents
1.
Introduction
2.
Return Codes
2.1.
Retcode
3.
Returners
3.1.
Using Returners
3.2.
Writing our own Returner
4.
Frequently Asked Questions
4.1.
What code can I write in returners?
4.2.
If I use returners, are the return values sent to Master still?
4.3.
Can I use multiple returners on a single command?
5.
Conclusion
Last Updated: Mar 27, 2024
Medium

ReturnCodes in Salt

Author Satvik Gupta
1 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Like all software, return codes are an essential part of Salt. They are used to identify errors, which helps debug and report failure to the user. For example - the famous 404 response code is a type of return code used by the HTTP protocol. Everyone who uses the Internet will be familiar with its meaning - that the URL they tried to access was not found.

ReturnCodes in Salt

This article will go through the Return Codes used by Salt and their meaning. We will also cover the concept of Returners - what they are, how to use them, and how we can implement our own custom returners.

Return Codes

The concept of return codes is frequently used in the software industry. Return codes are special codes sent along with the main data to convey information about the response. 

For example, HTTP uses return codes (they are called response codes, in that case) to convey information about the requested resource (URL). A 200 response code means we found the resource and sent it back, and a 301 means that the resource exists, but it's been moved to a different location. A 404 means that the server couldn't find the resource. 

Salt also has similar return codes. Instead of many like HTTP - Salt defaults to only 2 return codes - 0 and 1. 0 is used for correct responses, and 1 when some error has occurred. 

1 is returned in the following cases:

  • Errors occur while running states or a state gives back a False output.
     
  • Any exception is raised while running any code.
     
  • When running remote commands (like cp.get_file), often the Minion sends back a response in the form of a Dictionary, also called a Map. 
    If the dictionary has a key result whose value is False, then we return with return code 1. 
    Similarly, if the dictionary has a key success, with a value False, we return with return code 1.

Retcode

If we are writing custom Salt codes, such as custom states or execution modules, we can customize the error codes returned. 

While writing code for State Modules, or Execution Modules, a Python dictionary named __context__ is created by default for us. This is created by the Salt libraries that we import. While states run, this dictionary persists, and all states use the common __context__ dictionary. It is destroyed only after all state runs have finished.

This helps make things efficient. For example, many states may need to fetch files from the Master using the file client module. It would have to be initialized every time. But, using the __context__ dictionary, we can initialize it once and store it in the dictionary. Then each state module can access it from there.

To set custom return codes, we can set the retcode key in __context__. 

For example:

if successful==False:
__context__["retcode"] = 10

We can set different error codes for different errors, depending on what we need. 

Returners

Each command in Salt has a return value. The return values are always sent to the Master. However, we can specify what we want to do with the return data using Returners. We can send it to a custom database - such as MySQL, MongoDB, etc. We can also tell Salt to store the return values locally on the minion machine in a log file. 

Before we start using and writing returners, let us see what return values for commands look like. 

On your minion machine, execute the following command:

sudo salt-call --local --metadata test.version --out=pprint
Return Value format

The inner dictionary (the one with the keys fun,fun_args,etc.) is our return value.

Now, let's see how to use returners.

Using Returners

Salt provides many built-in Returners. They allow us to store return values in popular databases such as MongoDB, Redis, MySQL, etc. For simplicity, we won't be using an external database. We will use the rawfile_json returner that is built-in with Salt. It stores the return values in a local file on the minion machine. 

The location for this file is /var/log/salt/events

To use, we need to add the following line whenever we execute a salt command.

--return rawfile_json


Let's try with a ping command. The final command will be this.

sudo salt '*' test.ping --return rawfile_json
Test ping command running

Let's go to the Minion machine and check if our log file has been created. 

To go to the correct directory, type the command:

cd /var/log/salt

Once there, check if the file exists. 

File exists and has correct data

We see that the file exists and has the return data about our function.

Writing our own Returner

Sometimes, we may like to take customized actions with our return data. For this, we will need to write our own returner. 

Writing returners is very simple. We need to create a python file containing the returner function, taking a single argument. Salt will pass the argument to that function itself. The argument will contain the return value we saw above. 

That is it! In that function, we can implement whatever we want. It is up to us to do what we want with the return value. Let's take a basic example - once again, we will simply write the data to a file.

In your Master machine, go to the file_roots directory of the base environment. For us, this is /srv/salt/base. 

Create a new folder _returners. This name is fixed and can't be changed. Navigate to inside this folder. Create a file test_returner.py. Write this code in it:

import os
import shut ill
def returner (ret):
logFilePath ="/home/ubuntu/log.txt "
file = open(logFilePath, 'a')
file.write (str(ret))
file.close()


This code will open the file at /home/ubuntu/log.txt in append mode. In append mode, data is written to the end of the file. If this file doesn't exist, Python will create it for us. After that, the return value will be written to the file directly as a String.

Let's save the file. Now, we need to ensure this returner file is synced to the minion. To do that, run the following command.

sudo salt '*' saltutil.sync_returners
Sync returners

We receive a successful response. Let's run a command and see if a log file is generated. Run the following command.

sudo salt '*' test.ping --return test_returner
Test ping command running with test_returner

Let's go to the minion machine and check. 

Log file exists with correct data

We see that a log file is generated with the correct data.

Frequently Asked Questions

What code can I write in returners?

Anything that you can imagine can be written in returners. It is up to us. Salt will pass us the return value, and we can use it however we wish.

If I use returners, are the return values sent to Master still?

Master always receives return values. Using returners makes returners also get those values. It does not stop the master from receiving them.

Can I use multiple returners on a single command?

Yes, you can. You can write multiple returner names separated by commas. For e.g. - salt '*' test.ping --return returner1,returner2 

Conclusion

In this blog, we have seen how Salt uses the concept of Return Codes. We have seen the meaning of return codes in Salt. Returners help us to consolidate information about the various tasks we do use Salt on a single database. We can then use this for data analysis and changing policies.

We hope you leave this article with a broader knowledge of Salt,return codes, and configuration management. You should read our other articles about these topics as well, such as

You can practice questions on various problems on Coding Ninjas Studio, and attempt mock tests. You can also go through interview experiences, interview bundle, go along guided paths for preparations, and a lot more!

 

Keep coding, and keep reading Ninjas. 

Live masterclass