Skip to content

Suggestion: add saltcheck tests for formula validation #87

Open
@mchugh19

Description

@mchugh19

Experpt from Neon release notes and docs: https://docs.saltstack.com/en/develop/topics/releases/neon.html
https://docs.saltstack.com/en/develop/ref/modules/all/salt.modules.saltcheck.html

Saltcheck provides unittest like functionality requiring only the knowledge of salt module execution and yaml. Saltcheck uses salt modules to return data, then runs an assertion against that return. This allows for testing with all the features included in salt modules. tst files are run through the salt rendering system, enabling tests to be written in yaml (or renderer of choice), and include jinja, as well as the usual grain and pillar information.

saltcheck can be used for formula tests as part of a CI pipeline and can also be run on machines in your environment as part of a QA validation step. Personally, I see a lot of benefit to including saltcheck-tests directories in upstream formulas, as it allows for instant testing capability without other dependencies and using a state-like yaml syntax which understands pillars. For example, validating that 100 users (defined in a pillar) are properly provisioned is trivial and clear in saltcheck, while writing the same in inspec would require duplication of the salt pillar data as well as needing inspec and its dependencies which might not be appropriate in a production environment.

Example file system layout:

/srv/salt/apache/
    init.sls
    config.sls
    saltcheck-tests/
        init.tst
        config.tst
        deployment_validation.tst

Tests can be run for each state by name, for all apache/saltcheck/*.tst files, or for all states assigned to the minion in top.sls. Tests may also be created with no associated state. These tests will be run through the use of saltcheck.run_state_tests, but will not be automatically run by saltcheck.run_highstate_tests.

salt '*' saltcheck.run_state_tests apache,apache.config
salt '*' saltcheck.run_state_tests apache check_all=True
salt '*' saltcheck.run_highstate_tests
salt '*' saltcheck.run_state_tests apache.deployment_validation

Verify package installed:

verify_vim:
  module_and_function: pkg.version
  args:
    - vim
  assertion: assertNotEmpty

Ensure latest package installed:

{% for package in ["apache2", "openssh"] %}
{# or another example #}
{# for package in salt['pillar.get']("packages") #}
jinja_test_{{ package }}_latest:
  module_and_function: pkg.upgrade_available
  args:
    - {{ package }}
  assertion: assertFalse
{% endfor %}

Ensure python can load boto and boto3 libraries:
common/saltcheck-tests/init.tst

boto-installed:
  module_and_function: cmd.run
  args:
    - python -c 'import pkgutil; print(1 if pkgutil.find_loader("boto") else 0)'
  assertion: assertNotEqual
  expected-return: 0

boto3-installed:
  module_and_function: cmd.run
  args:
    - python -c 'import pkgutil; print(1 if pkgutil.find_loader("boto3") else 0)'
  assertion: assertEqual
  expected-return: 1

Test that all users exist and have the expected ssh keys. Might be appropriate for the users formula, for example.
users/saltcheck-tests/init.tst

{% for usr,data in salt['pillar.get']('users').items() %}

validate_user_{{ usr }}:
  module_and_function: user.info
  assertion_section: shell
  args:
    - {{ usr }}
  assertion: assertEqual
  expected-return: /bin/bash

{%- if 'key' in data %}
check_ssh_key_{{ usr }}:
  module_and_function: ssh.check_key
  args:
    - {{ usr }}
    - {{ data.key }}
    - ssh-rsa
    - ''
    - ''
  assertion: assertEqual
  expected-return: exists
{%- endif %}

{% endfor %}

I'd envision having basic tests like pkg.version is notNull, service.status is True, and maybe a file.contains is True live in most formulas. Since salt already has the map.jina and pkg manager abstractions, these tests can easily be upstreamed allowing for everyone's use.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions