# validate-modules

Topics

- validate-modules
  - Usage
  - Help
  - Extending validate-modules
  - Codes
    - Errors
    - Warnings

Python program to help test or validate Ansible modules.

`validate-modules` is one of the `ansible-test` Sanity Tests, see Sanity Tests for more information.

Originally developed by Matt Martz (@sivel)

## Usage

    cd /path/to/ansible/source
    source hacking/env-setup
    ansible-test sanity --test validate-modules

## Help

    usage: validate-modules [-h] [-w] [--exclude EXCLUDE] [--arg-spec]
                            [--base-branch BASE_BRANCH] [--format {json,plain}]
                            [--output OUTPUT]
                            modules [modules ...]

    positional arguments:
      modules               Path to module or module directory

    optional arguments:
      -h, --help            show this help message and exit
      -w, --warnings        Show warnings
      --exclude EXCLUDE     RegEx exclusion pattern
      --arg-spec            Analyze module argument spec
      --base-branch BASE_BRANCH
                            Used in determining if new options were added
      --format {json,plain}
                            Output format. Default: "plain"
      --output OUTPUT       Output location, use "-" for stdout. Default "-"

## Extending validate-modules

The `validate-modules` tool has a schema.py that is used to validate the YAML blocks, such as `DOCUMENTATION` and `RETURNS`.

## Codes

### Errors

code | sample message
1xx | Locations
101 | Interpreter line is not `#!/usr/bin/python`
102 | Interpreter line is not `#!powershell`
103 | Did not find a call to `main()` (or `removed_module()` in the case of deprecated & docs only modules)
104 | Call to `main()` not the last line (or `removed_module()` in the case of deprecated & docs only modules)
105 | GPLv3 license header not found
106 | Import found before documentation variables. All imports must appear below `DOCUMENTATION`/`EXAMPLES`/`RETURN`/`ANSIBLE_METADATA`
107 | Imports should be directly below `DOCUMENTATION`/`EXAMPLES`/`RETURN`/`ANSIBLE_METADATA`
108 | GPLv3 license header should be the short form for new modules
109 | Next to last line is not `if __name__ == "__main__":`
2xx | Imports
201 | Did not find a `module_utils` import
203 | `requests` import found, should use `ansible.module_utils.urls` instead
204 | `boto` import found, new modules should use `boto3`
205 | `sys.exit()` call found. Should be `exit_json`/`fail_json`
206 | `WANT_JSON` not found in module
207 | `REPLACER_WINDOWS` not found in module
208 | `module_utils` imports should import specific components, not `*`
209 | Only the following `from __future__` imports are allowed: `absolute_import`, `division`, and `print_function`.
3xx | Documentation
301 | No `DOCUMENTATION` provided
302 | `DOCUMENTATION` is not valid YAML
303 | `DOCUMENTATION` fragment missing
304 | Unknown `DOCUMENTATION` error
305 | Invalid `DOCUMENTATION` schema
306 | Module level `version_added` is not a valid version number
307 | Module level `version_added` is incorrect
308 | `version_added` for new option is not a valid version number
309 | `version_added` for new option is incorrect
310 | No `EXAMPLES` provided
311 | `EXAMPLES` is not valid YAML
312 | No `RETURN` documentation provided
313 | `RETURN` is not valid YAML
314 | No `ANSIBLE_METADATA` provided
315 | `ANSIBLE_METADATA` was not provided as a dict, YAML not supported
316 | Invalid `ANSIBLE_METADATA` schema
317 | option is marked as required but specifies a default. Arguments with a default should not be marked as required
318 | Module deprecated, but DOCUMENTATION.deprecated is missing
319 | `RETURN` fragments missing or invalid
320 | `DOCUMENTATION.options` must be a dictionary/hash when used
321 | `Exception` attempting to import module for `argument_spec` introspection
322 | argument is listed in the argument_spec, but not documented in the module
323 | argument is listed in DOCUMENTATION.options, but not accepted by the module
324 | Value for “default” from the argument_spec does not match the documentation
325 | argument_spec defines type=”bool” but documentation does not
326 | Value for “choices” from the argument_spec does not match the documentation
327 | Default value from the documentation is not compatible with type defined in the argument_spec
328 | Choices value from the documentation is not compatible with type defined in the argument_spec
329 | Default value from the argument_spec is not compatible with type defined in the argument_spec
330 | Choices value from the argument_spec is not compatible with type defined in the argument_spec
332 | `AnsibleModule` schema validation error
4xx | Syntax
401 | Python `SyntaxError` while parsing module
403 | Type comparison using `type()` found. Use `isinstance()` instead
5xx | Naming
501 | Official Ansible modules must have a `.py` extension for python modules or a `.ps1` for powershell modules
502 | Ansible module subdirectories must contain an `__init__.py`
503 | Missing python documentation file

### Warnings

code | sample message
1xx | Locations
107 | Imports should be directly below `DOCUMENTATION`/`EXAMPLES`/`RETURN`/`ANSIBLE_METADATA` for legacy modules
2xx | Imports
208 | `module_utils` imports should import specific components for legacy module, not `*`
291 | Try/Except `HAS_` expression missing
292 | Did not find `ansible.module_utils.basic` import
3xx | Documentation
312 | No `RETURN` documentation provided for legacy module
391 | Unknown pre-existing `DOCUMENTATION` error
392 | Pre-existing `DOCUMENTATION` fragment missing