How to call salt-ssh (SSHClient) via Python API

Question:

I installed Salt in a Python 3 virtual environment and created a Salt configuration that uses a non-root folder for everything (/home/user/saltenv). When using the salt-ssh command inside the venv, e.g. salt-ssh '*' test.ping, everything works as exptected. (Please note that the config dir is resolved via a Saltfile, so the -c option is omitted, but that should not matter.)

When calling the SSHClient directly via Python however, I get no results. I already figured out that the roster file is not read, obviously resulting in an empty target list. I am stuck somehow and the documentation is not that helpful.

Here is the code:

import salt.config
from salt.client.ssh.client import SSHClient

def main():
    c_path = '/home/user/saltenv/etc/salt/master'
    master_opts = salt.config.client_config(c_path)

    c = SSHClient(c_path=c_path, mopts=master_opts)
    res = c.cmd(tgt='*', fun='test.ping')
    print(res)

if __name__ == '__main__':
    main()
Asked By: code_onkel

||

Answers:

As it seems, the processing of some options differs between the CLI and the Client. salt-ssh does not use the SSHClient. Instead, the class salt.client.ssh.SSH is used directly.

While salt-ssh adds the config_dir from the Saltfile to the opts dictionary to resolve the master config file, the SSHClient reads the config file passed to the constructor directly and config_dir is not added to the options (resulting in the roster file not being found).

My solution is to include config_dir in the master config file as well. The code from the question will then be working unchanged.

Alternative 1: If you only have one Salt configuration, it is also possible to set the environment variable SALT_CONFIG_DIR.

Alternative 2: The mopts argument of SSHClient can be used to pass a custom configuration directory, but it requires more lines of code:

config = '/home/user/saltenv/etc/salt/master'
defaults = dict(salt.config.DEFAULT_MASTER_OPTS)
defaults['config_dir'] = os.path.dirname(config)
master_opts = salt.config.client_config(config, defaults=defaults)
c = SSHClient(mopts=master_opts)
Answered By: code_onkel
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.