Dry-running sls or just checking it's yaml syntax

Developing SaltStack sls states to Qubes has been painful, specially because I often run my sudo qubesctl --show-output --target=<vm-name> state.highstate just to be siting and waiting for the target mgm to boot up, attempt the execution and shut down telling me my sls has a malformed yaml (a space missing, a colon missing, etc…) (usually giving me ‘rendering sls failed mapping values are not allowed’, ‘wrong references to environments and states’, etc…).

It would be lovely to have a --dry-run option or a separate command to validate yamls - ideally this should be up-streamed to SaltStack people. Or in case it exists, documentation could advise the use of it.

I found the argument test for states in top.sls, but I don’t really use top.sls, I might just need to read the proper documentation on it, if anyone has it, please. It would be good to describe a workflow testing in it and migrating to top files, if that’s a good way of proceding.

I also could only find one repo tackling this with a simple python script that makes sense to me. But I was unable to run it on dom0 (How to copy from dom0 | Qubes OS) and I guess I will be running it on a VM and syncing my sls via git (brunoschroeder/qubes-git-syncer: Sync git repositories through Qubes doms. - qubes-git-syncer - Codeberg.org).

#!/usr/bin/python
# MIT by ipernet
# https://github.com/ipernet/yaml-linter-python-wrapper/tree/master

import yaml, sys, getopt, os.path

def main(argv):
    try:
        opts, args = getopt.getopt(argv, "hi:")
    except getopt.GetoptError:
        print 'linter.py -i <inputfile.yml>'
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print 'linter.py -i <inputfile.yml>'
            sys.exit()
        elif opt == '-i':
            if os.path.isfile(arg):
                stream = open(arg, 'r')
                try:
                    yaml.safe_load(stream)
                    sys.exit()
                except yaml.scanner.ScannerError:
                    sys.exit(1)
            else:
                print "Input file is missing or not readable"
                sys.exit(1)

if __name__ == "__main__":
    main(sys.argv[1:])

The Salt user guide and official documentation both have a section about the file top.sls.

Regarding the test argument, as I understand it it sets a Boolean variable that can be accessed from within state configuration files, so I don’t think it could be used to do a dry run:

https://docs.saltproject.io/en/latest/ref/states/testing.html

As the documentation you linked explains, I confirm that adding test=True to the command line will make salt simulating changes and report potential changes (files, missing packages etc…), but it can’t figure ALL changes as it won’t know side effects of commands.

2 Likes