pax_global_header00006660000000000000000000000064132353727300014517gustar00rootroot0000000000000052 comment=14073d9cdcedc949727228b735d3b8743326a9ee ansible-lint-3.4.20+git.20180203/000077500000000000000000000000001323537273000156435ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/.gitignore000066400000000000000000000004221323537273000176310ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__ *.py[co] *$py.class # Packages .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # Installer logs pip-log.txt # Unit test / coverage reports .tox ansible-lint-3.4.20+git.20180203/.pre-commit-hooks.yaml000066400000000000000000000003631323537273000220040ustar00rootroot00000000000000--- # For use with pre-commit. # See usage instructions at http://pre-commit.com - id: ansible-lint name: Ansible-lint description: This hook runs ansible-lint. entry: ansible-lint language: python files: \.(yaml|yml)$ ansible-lint-3.4.20+git.20180203/.travis.yml000066400000000000000000000001311323537273000177470ustar00rootroot00000000000000language: python python: - "2.7" install: - pip install -r test-deps.txt script: tox ansible-lint-3.4.20+git.20180203/CONTRIBUTING.md000066400000000000000000000021531323537273000200750ustar00rootroot00000000000000Contributing to Ansible-lint ============================ To contribute to ansible-lint, please use pull requests on a branch of your own fork. After creating your fork on github, you can do: ``` git clone git@github.com:yourname/ansible-lint cd ansible-lint git checkout -b your-branch-name DO SOME CODING HERE git add your new files git commit git push origin your-branch-name ``` You will then be able to create a pull request from your commit. All fixes to core functionality (i.e. anything except rules or examples) should be accompanied by tests that fail prior to your change and succeed afterwards. Feel free to raise issues in the repo if you don't feel able to contribute a code fix. Standards ========= ansible-lint is flake8 compliant with `max-line-length` set to 100 (see [setup.cfg](setup.cfg)). ansible-lint works with both Ansible 1.9 and Ansible 2.0 onwards. This will be the case for the foreseeable future, so please ensure all contributions work with both. Automated tests will be run against all PRs for flake8 compliance and Ansible compatibility - to check before pushing commits, just use `tox`. ansible-lint-3.4.20+git.20180203/ISSUE_TEMPLATE.md000066400000000000000000000013011323537273000203430ustar00rootroot00000000000000# Issue Type - Bug report - Feature request # Ansible and Ansible Lint details ``` ansible --version ansible-lint --version ``` - ansible installation method: one of source, pip, OS package - ansible-lint installation method: one of source, pip, OS package # Desired Behaviour Please give some details of the feature being requested or what should happen if providing a bug report # Actual Behaviour (Bug report only) Please give some details of what is actually happening. Include a [minimum complete verifiable example](http://stackoverflow.com/help/mcve) with: - playbook - output of running ansible-lint - if you're getting a stack trace, output of `ansible-playbook --syntax-check playbook` ansible-lint-3.4.20+git.20180203/LICENSE000066400000000000000000000020701323537273000166470ustar00rootroot00000000000000Copyright (c) 2013-2014 Will Thames Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ansible-lint-3.4.20+git.20180203/MANIFEST.in000066400000000000000000000000201323537273000173710ustar00rootroot00000000000000include LICENSE ansible-lint-3.4.20+git.20180203/README.md000066400000000000000000000212141323537273000171220ustar00rootroot00000000000000Ansible-lint ============ ansible-lint checks playbooks for practices and behaviour that could potentially be improved [![PyPI version](https://img.shields.io/pypi/v/ansible-lint.svg)](https://pypi.python.org/pypi/ansible-lint) [![Build Status](https://travis-ci.org/willthames/ansible-lint.svg?branch=master)](https://travis-ci.org/willthames/ansible-lint) Setup ----- Using pip: ``` pip2 install ansible-lint ``` From source: ``` git clone https://github.com/willthames/ansible-lint export PYTHONPATH=$PYTHONPATH:`pwd`/ansible-lint/lib export PATH=$PATH:`pwd`/ansible-lint/bin ``` Usage ----- ``` Usage: ansible-lint playbook.yml|roledirectory ... Options: --version show program's version number and exit -h, --help show this help message and exit -L list all the rules -q quieter, although not silent output -p parseable output in the format of pep8 -r RULESDIR specify one or more rules directories using one or more -r arguments. Any -r flags override the default rules in ['/path/to/ansible- lint/lib/ansiblelint/rules'], unless -R is also used. -R Use default rules ['/path/to/ansible- lint/lib/ansiblelint/rules'] in addition to any extra rules directories specified with -r. There is no need to specify this if no -r flags are used -t TAGS only check rules whose id/tags match these values -T list all the tags -x SKIP_LIST only check rules whose id/tags do not match these values --exclude=EXCLUDE_PATHS path to directories or files to skip. This option is repeatable. --force-color Try force colored output (relying on ansible's code) --nocolor disable colored output -c /path/to/file Specify configuration file to use. Defaults to ".ansible-lint" ``` False positives =============== Some rules are a bit of a rule of thumb. Advanced git, yum or apt usage, for example, is typically difficult to achieve through the modules. In this case, you should mark the task so that warnings aren't produced. There are two mechanisms for this - one works with all tasks, the other works with the command checking modules. Use the `warn` parameter with the command or shell module. Use `skip_ansible_lint` tag with any task that you want to skip. I recommend commenting the reasons why you're skipping the check. Unfortunately ansible-lint is unable to check for such comments at this time! (patches welcome) ``` - name: this would typically fire CommandsInsteadOfArgumentRule command: warn=no chmod 644 X - name: this would typically fire CommandsInsteadOfModuleRule command: git pull --rebase args: warn: False - name: this would typically fire GitHasVersionRule git: src=/path/to/git/repo dest=checkout tags: - skip_ansible_lint ``` Rules ===== Rules are described using a class file per rule. Default rules are named `DeprecatedVariableRule.py`, etc. Each rule definition should have the following: * ID: A unique identifier * Short description: Brief description of the rule * Description: Behaviour the rule is looking for * Tags: one or more tags that may be used to include or exclude the rule * At least one of the following methods: * `match` that takes a line and returns `None` or `False` if the line doesn't match the test and `True` or a custom message (this allows one rule to test multiple behaviours - see e.g. the CommandsInsteadOfModulesRule * `matchblock` that takes the details about the file and a block. It returns `None` or `False` if the line doesn't match the test and `True` or a custom message. * `matchtask` operates on a single task or handler. Such a task get standardized to always contain a `module` key and `module_arguments` key. Other common task modifiers such as `when`, `with_items` etc. are also available as keys if present in the task. An example rule using `match` is: ```python from ansiblelint import AnsibleLintRule class DeprecatedVariableRule(AnsibleLintRule): id = 'ANSIBLE0001' shortdesc = 'Deprecated variable declarations' description = 'Check for lines that have old style ${var} ' + \ 'declarations' tags = { 'deprecated' } def match(self, file, line): return '${' in line ``` An example rule using `matchtask` is: ```python import ansiblelint.utils from ansiblelint import AnsibleLintRule class TaskHasTag(AnsibleLintRule): id = 'ANSIBLE0008' shortdesc = 'Tasks must have tag' description = 'Tasks must have tag' tags = ['productivity'] def matchtask(self, file, task): # If the task include another task or make the playbook fail # Don't force to have a tag if not set(task.keys()).isdisjoint(['include','fail']): return False # Task should have tags if not task.has_key('tags'): return True return False ``` The `task` argument to `matchtask` contains a number of keys - the critical one is `action`. The value of `task['action']` contains the module being used, and the arguments passed, both as key-value pairs and a list of other arguments (e.g. the command used with `shell`) In ansible-lint 2.0.0, `task['action']['args']` was renamed `task['action']['module_arguments']` to avoid a clash when a module actually takes `args` as a parameter key (e.g. `ec2_tag`) In ansible-lint 3.0.0 `task['action']['module']` was renamed `task['action']['__ansible_module__']` to avoid a clash when a module take `module` as an argument. As a precaution, `task['action']['module_arguments']` was renamed `task['action']['__ansible_arguments__']` Examples -------- There are some example playbooks with undesirable features. Running ansible-lint on them works: ``` $ ansible-lint examples/example.yml [ANSIBLE0004] Git checkouts must contain explicit version examples/example.yml:15 Task/Handler: git check [ANSIBLE0004] Git checkouts must contain explicit version examples/example.yml:18 Task/Handler: git check 2 [ANSIBLE0004] Git checkouts must contain explicit version examples/example.yml:30 Task/Handler: using git module [ANSIBLE0002] Trailing whitespace examples/example.yml:13 action: do nothing [ANSIBLE0002] Trailing whitespace examples/example.yml:35 with_items: [ANSIBLE0006] git used in place of git module examples/example.yml:24 Task/Handler: executing git through command [ANSIBLE0006] git used in place of git module examples/example.yml:27 Task/Handler: executing git through command [ANSIBLE0006] git used in place of git module examples/example.yml:30 Task/Handler: executing git through command ``` If playbooks include other playbooks, or tasks, or handlers or roles, these are also handled: ``` $ bin/ansible-lint examples/include.yml [ANSIBLE0004] Checkouts must contain explicit version /Users/will/src/ansible-lint/examples/roles/bobbins/tasks/main.yml:3 action: git a=b c=d ``` As of version 2.4.0, ansible-lint now works just on roles (this is useful for CI of roles) Configuration File ================== Ansible-lint supports local configuration via a `.ansible-lint` configuration file. Ansible-lint checks the working directory for the presence of this file and applies any configuration found there. The configuration file location can also be overridden via the `-c path/to/file` CLI flag. The following values are supported and function identically to their CLI counterparts. If a value is provided on both the command line and via a config file, the values will be merged (if a list like `exclude_paths`), or the "True" value will be preferred, in the case of something like `quiet`. ```yaml exclude_paths: - ./my/excluded/directory/ - ./my/other/excluded/directory/ - ./last/excluded/directory/ parseable: true quiet: true rulesdir: - ./rule/directory/ skip_list: - skip_this_tag - and_this_one_too tags: - run_this_tag use_default_rules: true verbosity: 1 ``` Pre-commit ========== To use ansible-lint with [pre-commit](http://pre-commit.com/), just add the following to your local repo's `.pre-commit-config.yaml` file. Make sure to change `sha:` to be either a git commit sha or tag of ansible-lint containing `hooks.yaml`. ```yaml - repo: https://github.com/willthames/ansible-lint.git sha: v3.3.1 hooks: - id: ansible-lint files: \.(yaml|yml)$ ``` Contributing ============ Please read [CONTRIBUTING.md](https://github.com/willthames/ansible-lint/blob/master/CONTRIBUTING.md) if you wish to contribute. ansible-lint-3.4.20+git.20180203/bin/000077500000000000000000000000001323537273000164135ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/bin/ansible-lint000077500000000000000000000001451323537273000207220ustar00rootroot00000000000000#!/usr/bin/env python import sys import ansiblelint.__main__ sys.exit(ansiblelint.__main__.main()) ansible-lint-3.4.20+git.20180203/examples/000077500000000000000000000000001323537273000174615ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/example.yml000066400000000000000000000020251323537273000216360ustar00rootroot00000000000000--- - hosts: webservers vars: oldskool: "1.2.3" bracket: "and close bracket" tasks: - name: unset variable action: command echo {{thisvariable}} is not set in this playbook - name: trailing whitespace action: command echo do nothing - name: git check action: git a=b c=d - name: git check 2 action: git version=HEAD c=d - name: git check 3 git: version=a1b2c3d4 repo=xyz bobbins=d - name: executing git through command action: command git clone blah - name: executing git through command action: command chdir=bobbins creates=whatever /usr/bin/git clone blah - name: using git module action: git repo=blah - name: passing git as an argument to another task action: debug msg="{{item}}" with_items: - git - bobbins - name: yum latest yum: state=latest name=httpd - debug: msg="task without a name" - name: apt latest apt: state=latest name=apache2 - name: always run debug: msg="always_run is deprecated" always_run: true ansible-lint-3.4.20+git.20180203/examples/handlers/000077500000000000000000000000001323537273000212615ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/handlers/y.yml000066400000000000000000000001141323537273000222500ustar00rootroot00000000000000- name: funny handler action: service name=funny state=started force=true ansible-lint-3.4.20+git.20180203/examples/include.yml000066400000000000000000000003641323537273000216320ustar00rootroot00000000000000--- - hosts: bobbins pre_tasks: - include: tasks/x.yml roles: - hello - { role: morecomplex, t: z } tasks: - include: tasks/x.yml - include: tasks/x.yml y=z handlers: - include: handlers/y.yml - include: play.yml ansible-lint-3.4.20+git.20180203/examples/lineno.yml000066400000000000000000000000351323537273000214660ustar00rootroot00000000000000- tasks: - git: repo=hello ansible-lint-3.4.20+git.20180203/examples/lots_of_warnings.yml000066400000000000000000001110441323537273000235620ustar00rootroot00000000000000--- # This playbook causes ansible-lint to output tons of warnings # Enough to exceed typical stdout buffering size and thus to show the need for # catching IOError (EPIEP) errors. - hosts: webservers tasks: - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah - name: executing git through command action: command git clone blah ansible-lint-3.4.20+git.20180203/examples/nomatches.yml000066400000000000000000000002551323537273000221670ustar00rootroot00000000000000--- - hosts: whatever tasks: - name: hello world action: debug msg="Hello!" - name: this should be fine too action: file state=touch dest=./wherever ansible-lint-3.4.20+git.20180203/examples/play.yml000066400000000000000000000001351323537273000211500ustar00rootroot00000000000000--- - hosts: bobbins tasks: - name: a bad play action: command service blah restart ansible-lint-3.4.20+git.20180203/examples/roles/000077500000000000000000000000001323537273000206055ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/bobbins/000077500000000000000000000000001323537273000222235ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/bobbins/tasks/000077500000000000000000000000001323537273000233505ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/bobbins/tasks/main.yml000066400000000000000000000000561323537273000250200ustar00rootroot00000000000000--- - name: test tasks action: git a=b c=d ansible-lint-3.4.20+git.20180203/examples/roles/hello/000077500000000000000000000000001323537273000217105ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/hello/meta/000077500000000000000000000000001323537273000226365ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/hello/meta/main.yml000066400000000000000000000000441323537273000243030ustar00rootroot00000000000000--- dependencies: - role: bobbins ansible-lint-3.4.20+git.20180203/examples/roles/morecomplex/000077500000000000000000000000001323537273000231375ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/morecomplex/handlers/000077500000000000000000000000001323537273000247375ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/morecomplex/handlers/main.yml000066400000000000000000000001051323537273000264020ustar00rootroot00000000000000- name: restart service using command command: service bar restart ansible-lint-3.4.20+git.20180203/examples/roles/morecomplex/tasks/000077500000000000000000000000001323537273000242645ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/roles/morecomplex/tasks/main.yml000066400000000000000000000002511323537273000257310ustar00rootroot00000000000000- name: test bad command action: command mkdir blah - name: test bad command v2 command: mkdir blah - name: test bad local command local_action: shell touch foo ansible-lint-3.4.20+git.20180203/examples/rules/000077500000000000000000000000001323537273000206135ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/rules/TaskHasTag.py000066400000000000000000000016451323537273000231650ustar00rootroot00000000000000from ansiblelint import AnsibleLintRule class TaskHasTag(AnsibleLintRule): id = 'EXAMPLE001' shortdesc = 'Tasks must have tag' description = 'Tasks must have tag' tags = ['productivity', 'tags'] def matchtask(self, file, task): # The meta files don't have tags if file['type'] in ["meta", "playbooks"]: return False if isinstance(task, basestring): return False # If the task include another task or make the playbook fail # Don't force to have a tag if not set(task.keys()).isdisjoint(['include', 'fail']): return False if not set(task.keys()).isdisjoint(['include_tasks', 'fail']): return False if not set(task.keys()).isdisjoint(['import_tasks', 'fail']): return False # Task should have tags if 'tags' not in task: return True return False ansible-lint-3.4.20+git.20180203/examples/tasks/000077500000000000000000000000001323537273000206065ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/examples/tasks/x.yml000066400000000000000000000001111323537273000215710ustar00rootroot00000000000000- name: test include action: funny value=clown args: key: value ansible-lint-3.4.20+git.20180203/hooks.yaml000066400000000000000000000003631323537273000176540ustar00rootroot00000000000000--- # For use with pre-commit. # See usage instructions at http://pre-commit.com - id: ansible-lint name: Ansible-lint description: This hook runs ansible-lint. entry: ansible-lint language: python files: \.(yaml|yml)$ ansible-lint-3.4.20+git.20180203/lib/000077500000000000000000000000001323537273000164115ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/lib/ansiblelint/000077500000000000000000000000001323537273000207155ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/lib/ansiblelint/__init__.py000066400000000000000000000217711323537273000230360ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from __future__ import print_function from collections import defaultdict import os import sys import six import ansiblelint.utils import codecs default_rulesdir = os.path.join(os.path.dirname(ansiblelint.utils.__file__), 'rules') class AnsibleLintRule(object): def __repr__(self): return self.id + ": " + self.shortdesc def verbose(self): return self.id + ": " + self.shortdesc + "\n " + self.description match = None matchtask = None matchplay = None def matchlines(self, file, text): matches = [] if not self.match: return matches # arrays are 0-based, line numbers are 1-based # so use prev_line_no as the counter for (prev_line_no, line) in enumerate(text.split("\n")): result = self.match(file, line) if result: message = None if isinstance(result, str): message = result matches.append(Match(prev_line_no+1, line, file['path'], self, message)) return matches def matchtasks(self, file, text): matches = [] if not self.matchtask: return matches yaml = ansiblelint.utils.parse_yaml_linenumbers(text, file['path']) if yaml: for task in ansiblelint.utils.get_normalized_tasks(yaml, file): if 'action' in task: result = self.matchtask(file, task) if result: message = None if isinstance(result, six.string_types): message = result taskstr = "Task/Handler: " + ansiblelint.utils.task_to_str(task) matches.append(Match(task[ansiblelint.utils.LINE_NUMBER_KEY], taskstr, file['path'], self, message)) return matches def matchyaml(self, file, text): matches = [] if not self.matchplay: return matches yaml = ansiblelint.utils.parse_yaml_linenumbers(text, file['path']) if yaml and hasattr(self, 'matchplay'): if isinstance(yaml, dict): yaml = [yaml] for play in yaml: result = self.matchplay(file, play) if result: if isinstance(result, tuple): result = [result] if not isinstance(result, list): raise Exception("{} is not a list".format(result)) for section, message in result: matches.append(Match(play[ansiblelint.utils.LINE_NUMBER_KEY], section, file['path'], self, message)) return matches class RulesCollection(object): def __init__(self): self.rules = [] def register(self, obj): self.rules.append(obj) def __iter__(self): return iter(self.rules) def __len__(self): return len(self.rules) def extend(self, more): self.rules.extend(more) def run(self, playbookfile, tags=set(), skip_list=set()): text = "" matches = list() try: with codecs.open(playbookfile['path'], mode='rb', encoding='utf-8') as f: text = f.read() except IOError as e: print("WARNING: Couldn't open %s - %s" % (playbookfile['path'], e.strerror), file=sys.stderr) return matches for rule in self.rules: if not tags or not set(rule.tags).union([rule.id]).isdisjoint(tags): rule_definition = set(rule.tags) rule_definition.add(rule.id) if set(rule_definition).isdisjoint(skip_list): matches.extend(rule.matchlines(playbookfile, text)) matches.extend(rule.matchtasks(playbookfile, text)) matches.extend(rule.matchyaml(playbookfile, text)) return matches def __repr__(self): return "\n".join([rule.verbose() for rule in sorted(self.rules, key=lambda x: x.id)]) def listtags(self): tags = defaultdict(list) for rule in self.rules: for tag in rule.tags: tags[tag].append("[{0}]".format(rule.id)) results = [] for tag in sorted(tags): results.append("{0} {1}".format(tag, tags[tag])) return "\n".join(results) @classmethod def create_from_directory(cls, rulesdir): result = cls() result.rules = ansiblelint.utils.load_plugins(os.path.expanduser(rulesdir)) return result class Match(object): def __init__(self, linenumber, line, filename, rule, message=None): self.linenumber = linenumber self.line = line self.filename = filename self.rule = rule self.message = message or rule.shortdesc def __repr__(self): formatstr = u"[{0}] ({1}) matched {2}:{3} {4}" return formatstr.format(self.rule.id, self.message, self.filename, self.linenumber, self.line) class Runner(object): def __init__(self, rules, playbook, tags, skip_list, exclude_paths, verbosity=0, checked_files=None): self.rules = rules self.playbooks = set() # assume role if directory if os.path.isdir(playbook): self.playbooks.add((playbook, 'role')) self.playbook_dir = playbook else: self.playbooks.add((playbook, 'playbook')) self.playbook_dir = os.path.dirname(playbook) self.tags = tags self.skip_list = skip_list self._update_exclude_paths(exclude_paths) self.verbosity = verbosity if checked_files is None: checked_files = set() self.checked_files = checked_files def _update_exclude_paths(self, exclude_paths): if exclude_paths: # These will be (potentially) relative paths paths = [s.strip() for s in exclude_paths] # Since ansiblelint.utils.find_children returns absolute paths, # and the list of files we create in `Runner.run` can contain both # relative and absolute paths, we need to cover both bases. self.exclude_paths = paths + [os.path.abspath(p) for p in paths] else: self.exclude_paths = [] def is_excluded(self, file_path): # Any will short-circuit as soon as something returns True, but will # be poor performance for the case where the path under question is # not excluded. return any(file_path.startswith(path) for path in self.exclude_paths) def run(self): files = list() for playbook in self.playbooks: if self.is_excluded(playbook[0]): continue if playbook[1] == 'role': continue files.append({'path': playbook[0], 'type': playbook[1]}) visited = set() while (visited != self.playbooks): for arg in self.playbooks - visited: for child in ansiblelint.utils.find_children(arg, self.playbook_dir): if self.is_excluded(child['path']): continue self.playbooks.add((child['path'], child['type'])) files.append(child) visited.add(arg) matches = list() # remove files that have already been checked files = [x for x in files if x['path'] not in self.checked_files] for file in files: if self.verbosity > 0: print("Examining %s of type %s" % (file['path'], file['type'])) matches.extend(self.rules.run(file, tags=set(self.tags), skip_list=set(self.skip_list))) # update list of checked files self.checked_files.update([x['path'] for x in files]) return matches ansible-lint-3.4.20+git.20180203/lib/ansiblelint/__main__.py000077500000000000000000000162531323537273000230210ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from __future__ import print_function import errno import optparse import sys import ansiblelint import ansiblelint.formatters as formatters import six from ansiblelint import RulesCollection from ansiblelint.version import __version__ import yaml import os def load_config(config_file): config_path = config_file if config_file else ".ansible-lint" if os.path.exists(config_path): with open(config_path, "r") as stream: try: return yaml.load(stream) except yaml.YAMLError: pass return None def main(): formatter = formatters.Formatter() parser = optparse.OptionParser("%prog [options] playbook.yml [playbook2 ...]", version="%prog " + __version__) parser.add_option('-L', dest='listrules', default=False, action='store_true', help="list all the rules") parser.add_option('-q', dest='quiet', default=False, action='store_true', help="quieter, although not silent output") parser.add_option('-p', dest='parseable', default=False, action='store_true', help="parseable output in the format of pep8") parser.add_option('-r', action='append', dest='rulesdir', default=[], type='str', help="specify one or more rules directories using " "one or more -r arguments. Any -r flags override " "the default rules in %s, unless -R is also used." % ansiblelint.default_rulesdir) parser.add_option('-R', action='store_true', default=False, dest='use_default_rules', help="Use default rules in %s in addition to any extra " "rules directories specified with -r. There is " "no need to specify this if no -r flags are used" % ansiblelint.default_rulesdir) parser.add_option('-t', dest='tags', action='append', default=[], help="only check rules whose id/tags match these values") parser.add_option('-T', dest='listtags', action='store_true', help="list all the tags") parser.add_option('-v', dest='verbosity', action='count', help="Increase verbosity level", default=0) parser.add_option('-x', dest='skip_list', default=[], help="only check rules whose id/tags do not " + "match these values") parser.add_option('--nocolor', dest='colored', default=hasattr(sys.stdout, 'isatty') and sys.stdout.isatty(), action='store_false', help="disable colored output") parser.add_option('--force-color', dest='colored', action='store_true', help="Try force colored output (relying on ansible's code)") parser.add_option('--exclude', dest='exclude_paths', action='append', help='path to directories or files to skip. This option' ' is repeatable.', default=[]) parser.add_option('-c', help='Specify configuration file to use. Defaults to ".ansible-lint"') options, args = parser.parse_args(sys.argv[1:]) config = load_config(options.c) if config: if 'quiet' in config: options.quiet = options.quiet or config['quiet'] if 'parseable' in config: options.parseable = options.parseable or config['parseable'] if 'use_default_rules' in config: options.use_default_rules = options.use_default_rules or config['use_default_rules'] if 'verbosity' in config: options.verbosity = options.verbosity + config['verbosity'] if 'exclude_paths' in config: options.exclude_paths = options.exclude_paths + config['exclude_paths'] if 'rulesdir' in config: options.rulesdir = options.rulesdir + config['rulesdir'] if 'skip_list' in config: options.skip_list = options.skip_list + config['skip_list'] if 'tags' in config: options.tags = options.tags + config['tags'] if options.quiet: formatter = formatters.QuietFormatter() if options.parseable: formatter = formatters.ParseableFormatter() if len(args) == 0 and not (options.listrules or options.listtags): parser.print_help(file=sys.stderr) return 1 if options.use_default_rules: rulesdirs = options.rulesdir + [ansiblelint.default_rulesdir] else: rulesdirs = options.rulesdir or [ansiblelint.default_rulesdir] rules = RulesCollection() for rulesdir in rulesdirs: rules.extend(RulesCollection.create_from_directory(rulesdir)) if options.listrules: print(rules) return 0 if options.listtags: print(rules.listtags()) return 0 if isinstance(options.tags, six.string_types): options.tags = options.tags.split(',') if isinstance(options.skip_list, six.string_types): options.skip_list = options.skip_list.split(',') playbooks = set(args) matches = list() checked_files = set() for playbook in playbooks: runner = ansiblelint.Runner(rules, playbook, options.tags, options.skip_list, options.exclude_paths, options.verbosity, checked_files) matches.extend(runner.run()) matches.sort(key=lambda x: (x.filename, x.linenumber, x.rule.id)) for match in matches: print(formatter.format(match, options.colored)) if len(matches): return 2 else: return 0 if __name__ == "__main__": try: sys.exit(main()) except IOError as exc: if exc.errno != errno.EPIPE: raise except RuntimeError as e: raise SystemExit(str(e)) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/formatters/000077500000000000000000000000001323537273000231035ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/lib/ansiblelint/formatters/__init__.py000066400000000000000000000043311323537273000252150ustar00rootroot00000000000000try: from ansible import color except ImportError: from ansible.utils import color class Formatter(object): def format(self, match, colored=False): formatstr = u"{0} {1}\n{2}:{3}\n{4}\n" if colored: color.ANSIBLE_COLOR = True return formatstr.format(color.stringc(u"[{0}]".format(match.rule.id), 'bright red'), color.stringc(match.message, 'red'), color.stringc(match.filename, 'blue'), color.stringc(str(match.linenumber), 'cyan'), color.stringc(u"{0}".format(match.line), 'purple')) else: return formatstr.format(match.rule.id, match.message, match.filename, match.linenumber, match.line) class QuietFormatter(object): def format(self, match, colored=False): formatstr = u"{0} {1}:{2}" if colored: color.ANSIBLE_COLOR = True return formatstr.format(color.stringc(u"[{0}]".format(match.rule.id), 'bright red'), color.stringc(match.filename, 'blue'), color.stringc(str(match.linenumber), 'cyan')) else: return formatstr.format(match.rule.id, match.filename, match.linenumber) class ParseableFormatter(object): def format(self, match, colored=False): formatstr = u"{0}:{1}: [{2}] {3}" if colored: color.ANSIBLE_COLOR = True return formatstr.format(color.stringc(match.filename, 'blue'), color.stringc(str(match.linenumber), 'cyan'), color.stringc(u"E{0}".format(match.rule.id), 'bright red'), color.stringc(u"{0}".format(match.message), 'red')) else: return formatstr.format(match.filename, match.linenumber, "E" + match.rule.id, match.message) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/000077500000000000000000000000001323537273000220475ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/AlwaysRunRule.py000066400000000000000000000026141323537273000252010ustar00rootroot00000000000000# Copyright (c) 2017 Anth Courtney # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule class AlwaysRunRule(AnsibleLintRule): id = 'ANSIBLE0018' shortdesc = 'Deprecated always_run' description = 'Instead of always_run, use check_mode.' tags = ['deprecated'] def matchtask(self, file, task): return 'always_run' in task ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/BecomeUserWithoutBecomeRule.py000066400000000000000000000033601323537273000300030ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule def _become_user_without_become(data): return 'become_user' in data and 'become' not in data class BecomeUserWithoutBecomeRule(AnsibleLintRule): id = 'ANSIBLE0017' shortdesc = 'become_user requires become to work as expected' description = 'become_user without become will not actually change ' \ 'user' tags = ['oddity'] def matchplay(self, file, data): if file['type'] == 'playbook' and _become_user_without_become(data): return ({'become_user': data}, self.shortdesc) def matchtask(self, file, task): return _become_user_without_become(task) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/CommandHasChangesCheckRule.py000066400000000000000000000037671323537273000275270ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule class CommandHasChangesCheckRule(AnsibleLintRule): id = 'ANSIBLE0012' shortdesc = 'Commands should not change things if nothing needs doing' description = 'Commands should either read information (and thus set ' \ 'changed_when) or not do something if it has already been ' \ 'done (using creates/removes) or only do it if another ' \ 'check has a particular result (when)' tags = ['idempotency'] _commands = ['command', 'shell', 'raw'] def matchtask(self, file, task): if task["__ansible_action_type__"] == 'task': if task["action"]["__ansible_module__"] in self._commands: return 'changed_when' not in task and \ 'when' not in task and \ 'creates' not in task['action'] and \ 'removes' not in task['action'] ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/CommandsInsteadOfArgumentsRule.py000066400000000000000000000052751323537273000305060ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import os from ansiblelint import AnsibleLintRule try: from ansible.module_utils.parsing.convert_bool import boolean except ImportError: try: from ansible.utils.boolean import boolean except ImportError: try: from ansible.utils import boolean except ImportError: from ansible import constants boolean = constants.mk_boolean class CommandsInsteadOfArgumentsRule(AnsibleLintRule): id = 'ANSIBLE0007' shortdesc = 'Using command rather than an argument to e.g. file' description = 'Executing a command when there is are arguments to modules ' + \ 'is generally a bad idea' tags = ['resources'] _commands = ['command', 'shell', 'raw'] _arguments = {'chown': 'owner', 'chmod': 'mode', 'chgrp': 'group', 'ln': 'state=link', 'mkdir': 'state=directory', 'rmdir': 'state=absent', 'rm': 'state=absent'} def matchtask(self, file, task): if task["action"]["__ansible_module__"] in self._commands: if 'cmd' in task['action']: first_cmd_arg = task['action']['cmd'].split()[0] else: first_cmd_arg = task["action"]["__ansible_arguments__"][0] if not first_cmd_arg: return executable = os.path.basename(first_cmd_arg) if executable in self._arguments and \ boolean(task['action'].get('warn', True)): message = "{0} used in place of argument {1} to file module" return message.format(executable, self._arguments[executable]) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/CommandsInsteadOfModulesRule.py000066400000000000000000000056311323537273000301450ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import os from ansiblelint import AnsibleLintRule try: from ansible.module_utils.parsing.convert_bool import boolean except ImportError: try: from ansible.utils.boolean import boolean except ImportError: try: from ansible.utils import boolean except ImportError: from ansible import constants boolean = constants.mk_boolean class CommandsInsteadOfModulesRule(AnsibleLintRule): id = 'ANSIBLE0006' shortdesc = 'Using command rather than module' description = 'Executing a command when there is an Ansible module ' + \ 'is generally a bad idea' tags = ['resources'] _commands = ['command', 'shell'] _modules = {'git': 'git', 'hg': 'hg', 'curl': 'get_url or uri', 'wget': 'get_url or uri', 'svn': 'subversion', 'service': 'service', 'mount': 'mount', 'rpm': 'yum or rpm_key', 'yum': 'yum', 'apt-get': 'apt-get', 'unzip': 'unarchive', 'tar': 'unarchive', 'chkconfig': 'service', 'rsync': 'synchronize', 'supervisorctl': 'supervisorctl', 'systemctl': 'systemd', 'sed': 'template or lineinfile'} def matchtask(self, file, task): if task["action"]["__ansible_module__"] in self._commands: if 'cmd' in task['action']: first_cmd_arg = task['action']['cmd'].split()[0] else: first_cmd_arg = task["action"]["__ansible_arguments__"][0] if not first_cmd_arg: return executable = os.path.basename(first_cmd_arg) if executable in self._modules and \ boolean(task['action'].get('warn', True)): message = "{0} used in place of {1} module" return message.format(executable, self._modules[executable]) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/EnvVarsInCommandRule.py000066400000000000000000000041471323537273000264310ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule from ansiblelint.utils import LINE_NUMBER_KEY, FILENAME_KEY class EnvVarsInCommandRule(AnsibleLintRule): id = 'ANSIBLE0014' shortdesc = "Environment variables don't work as part of command" description = 'Environment variables should be passed to shell or ' \ 'command through environment argument' tags = ['bug'] expected_args = ['chdir', 'creates', 'executable', 'removes', 'stdin', 'warn', 'cmd', '__ansible_module__', '__ansible_arguments__', LINE_NUMBER_KEY, FILENAME_KEY] def matchtask(self, file, task): if task["action"]["__ansible_module__"] in ['shell', 'command']: if 'cmd' in task['action']: first_cmd_arg = task['action']['cmd'].split()[0] else: first_cmd_arg = task['action']['__ansible_arguments__'][0] return any([arg not in self.expected_args for arg in task['action']] + ["=" in first_cmd_arg]) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/GitHasVersionRule.py000066400000000000000000000031211323537273000257730ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule class GitHasVersionRule(AnsibleLintRule): id = 'ANSIBLE0004' shortdesc = 'Git checkouts must contain explicit version' description = 'All version control checkouts must point to ' + \ 'an explicit commit or tag, not just "latest"' tags = ['repeatability'] def matchtask(self, file, task): return (task['action']['__ansible_module__'] == 'git' and task['action'].get('version', 'HEAD') == 'HEAD') ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/MercurialHasRevisionRule.py000066400000000000000000000031461323537273000273530ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule class MercurialHasRevisionRule(AnsibleLintRule): id = 'ANSIBLE0005' shortdesc = 'Mercurial checkouts must contain explicit revision' description = 'All version control checkouts must point to ' + \ 'an explicit commit or tag, not just "latest"' tags = ['repeatability'] def matchtask(self, file, task): return (task['action']['__ansible_module__'] == 'hg' and task['action'].get('revision', 'default') == 'default') ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/OctalPermissionsRule.py000066400000000000000000000057421323537273000265570ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule import re import six class OctalPermissionsRule(AnsibleLintRule): id = 'ANSIBLE0009' shortdesc = 'Octal file permissions must contain leading zero' description = 'Numeric file permissions without leading zero can behave ' + \ 'in unexpected ways. See ' + \ 'http://docs.ansible.com/ansible/file_module.html' tags = ['formatting'] _modules = ['assemble', 'copy', 'file', 'ini_file', 'lineinfile', 'replace', 'synchronize', 'template', 'unarchive'] mode_regex = re.compile(r'^\s*[0-9]+\s*$') valid_mode_regex = re.compile(r'^\s*0[0-7]{3,4}\s*$') def matchtask(self, file, task): if task["action"]["__ansible_module__"] in self._modules: mode = task['action'].get('mode', None) if isinstance(mode, six.string_types) and self.mode_regex.match(mode): return not self.valid_mode_regex.match(mode) if isinstance(mode, int): # sensible file permission modes don't # have write bit set when read bit is # not set and don't have execute bit set # when user execute bit is not set. # also, user permissions are more generous than # group permissions and user and group permissions # are more generous than world permissions result = (mode % 8 and mode % 8 < 4 and not (mode % 8 == 1 and (mode >> 6) % 8 == 1) or (mode >> 3) % 8 and (mode >> 3) % 8 < 4 and not ((mode >> 3) % 8 == 1 and (mode >> 6) % 8 == 1) or (mode >> 6) % 8 and (mode >> 6) % 8 < 4 and not (mode >> 6) % 8 == 1 or mode & 8 < (mode << 3) & 8 or mode & 8 < (mode << 6) & 8 or (mode << 3) & 8 < (mode << 6) & 8) return result ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/PackageIsNotLatestRule.py000066400000000000000000000035251323537273000267430ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule class PackageIsNotLatestRule(AnsibleLintRule): id = 'ANSIBLE0010' shortdesc = 'Package installs should not use latest' description = 'Package installs should use state=present ' + \ 'with or without a version' tags = ['repeatability'] _package_managers = ['yum', 'apt', 'dnf', 'homebrew', 'pacman', 'openbsd_package', 'pkg5', 'portage', 'pkgutil', 'slackpkg', 'swdepot', 'zypper', 'bundler', 'pip', 'pear', 'npm', 'gem', 'easy_install', 'bower', 'package'] def matchtask(self, file, task): return (task['action']['__ansible_module__'] in self._package_managers and task['action'].get('state') == 'latest') ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/SudoRule.py000066400000000000000000000020271323537273000241640ustar00rootroot00000000000000from ansiblelint import AnsibleLintRule class SudoRule(AnsibleLintRule): id = 'ANSIBLE0008' shortdesc = 'Deprecated sudo' description = 'Instead of sudo/sudo_user, use become/become_user.' tags = ['deprecated'] def _check_value(self, play_frag): results = [] if isinstance(play_frag, dict): if 'sudo' in play_frag: results.append(({'sudo': play_frag['sudo']}, 'deprecated sudo feature')) if 'sudo_user' in play_frag: results.append(({'sudo_user': play_frag['sudo_user']}, 'deprecated sudo_user feature')) if isinstance(play_frag, list): for item in play_frag: output = self._check_value(item) if output: results += output return results def matchplay(self, file, play): return self._check_value(play) def matchtask(self, file, task): return 'sudo' in task or 'sudo_user' in task ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/TaskHasNameRule.py000066400000000000000000000031261323537273000254120ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule class TaskHasNameRule(AnsibleLintRule): id = 'ANSIBLE0011' shortdesc = 'All tasks should be named' description = 'All tasks should have a distinct name for readability ' + \ 'and for --start-at-task to work' tags = ['readability'] _nameless_tasks = ['meta', 'debug'] def matchtask(self, file, task): return task.get('name', '') == '' and \ task["action"]["__ansible_module__"] not in self._nameless_tasks ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/TrailingWhitespaceRule.py000066400000000000000000000026231323537273000270420ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule class TrailingWhitespaceRule(AnsibleLintRule): id = 'ANSIBLE0002' shortdesc = 'Trailing whitespace' description = 'There should not be any trailing whitespace' tags = ['formatting'] def match(self, file, line): return line.rstrip() != line ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/UseCommandInsteadOfShellRule.py000066400000000000000000000040471323537273000300760ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from ansiblelint import AnsibleLintRule import re def unjinja(text): return re.sub("\{\{[^\}]*\}\}", "JINJA_VAR", text) class UseCommandInsteadOfShellRule(AnsibleLintRule): id = 'ANSIBLE0013' shortdesc = 'Use shell only when shell functionality is required' description = 'Shell should only be used when piping, redirecting ' \ 'or chaining commands (and Ansible would be preferred ' \ 'for some of those!)' tags = ['safety'] def matchtask(self, file, task): # Use unjinja so that we don't match on jinja filters # rather than pipes if task["action"]["__ansible_module__"] == 'shell': if 'cmd' in task['action']: unjinjad_cmd = unjinja(task["action"].get("cmd", [])) else: unjinjad_cmd = unjinja(' '.join(task["action"].get("__ansible_arguments__", []))) return not any([ch in unjinjad_cmd for ch in '&|<>;$\n*[]{}?']) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/UseHandlerRatherThanWhenChangedRule.py000066400000000000000000000037211323537273000313630ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import six from ansiblelint import AnsibleLintRule def _changed_in_when(item): return any(changed in item for changed in ['.changed', '|changed', '["changed"]', "['changed']"]) class UseHandlerRatherThanWhenChangedRule(AnsibleLintRule): id = 'ANSIBLE0016' shortdesc = 'Tasks that run when changed should likely be handlers' description = "If a task has a `when: result.changed` setting, it's effectively " \ "acting as a handler" tags = ['behaviour'] def matchtask(self, file, task): if task["__ansible_action_type__"] == 'task': when = task.get('when') if isinstance(when, list): for item in when: if _changed_in_when(item): return True if isinstance(when, six.string_types): return _changed_in_when(when) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/UsingBareVariablesIsDeprecatedRule.py000066400000000000000000000064221323537273000312420ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import re import six from ansiblelint import AnsibleLintRule class UsingBareVariablesIsDeprecatedRule(AnsibleLintRule): id = 'ANSIBLE0015' shortdesc = 'Using bare variables is deprecated' description = 'Using bare variables is deprecated. Update your ' + \ 'playbooks so that the environment value uses the full variable ' + \ 'syntax ("{{your_variable}}").' tags = ['formatting', 'deprecated'] _jinja = re.compile("\{\{.*\}\}") _glob = re.compile('[][*?]') def matchtask(self, file, task): loop_type = next((key for key in task if key.startswith("with_")), None) if loop_type: if loop_type in ["with_nested", "with_together", "with_flattened"]: # These loops can either take a list defined directly in the task # or a variable that is a list itself. When a single variable is used # we just need to check that one variable, and not iterate over it like # it's a list. Otherwise, loop through and check all items. items = task[loop_type] if not isinstance(items, (list, tuple)): items = [items] for var in items: return self._matchvar(var, task, loop_type) elif loop_type == "with_subelements": return self._matchvar(task[loop_type][0], task, loop_type) elif loop_type in ["with_sequence", "with_ini", "with_inventory_hostnames"]: pass else: return self._matchvar(task[loop_type], task, loop_type) def _matchvar(self, varstring, task, loop_type): if (isinstance(varstring, six.string_types) and not self._jinja.match(varstring)): if loop_type != 'with_fileglob' or not (self._jinja.search(varstring) or self._glob.search(varstring)): message = "Found a bare variable '{0}' used in a '{1}' loop." + \ " You should use the full variable syntax ('{{{{{0}}}}}')" return message.format(task[loop_type], loop_type) ansible-lint-3.4.20+git.20180203/lib/ansiblelint/rules/__init__.py000066400000000000000000000000001323537273000241460ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/lib/ansiblelint/utils.py000066400000000000000000000450101323537273000224270ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import glob import imp import os import six from ansible import constants from ansible.errors import AnsibleError try: # Try to import the Ansible 2 module first, it's the future-proof one from ansible.parsing.splitter import split_args except ImportError: # Fallback on the Ansible 1.9 module from ansible.module_utils.splitter import split_args import yaml from yaml.composer import Composer from yaml.constructor import Constructor try: from ansible.utils import parse_yaml_from_file from ansible.utils import path_dwim from ansible.utils.template import template as ansible_template from ansible.utils import module_finder module_loader = module_finder ANSIBLE_VERSION = 1 except ImportError: from ansible.parsing.dataloader import DataLoader from ansible.template import Templar from ansible.parsing.mod_args import ModuleArgsParser from ansible.errors import AnsibleParserError ANSIBLE_VERSION = 2 def parse_yaml_from_file(filepath): dl = DataLoader() return dl.load_from_file(filepath) def path_dwim(basedir, given): dl = DataLoader() dl.set_basedir(basedir) return dl.path_dwim(given) def ansible_template(basedir, varname, templatevars, **kwargs): dl = DataLoader() dl.set_basedir(basedir) templar = Templar(dl, variables=templatevars) return templar.template(varname, **kwargs) try: from ansible.plugins import module_loader except ImportError: from ansible.plugins.loader import module_loader LINE_NUMBER_KEY = '__line__' FILENAME_KEY = '__file__' VALID_KEYS = [ 'name', 'action', 'when', 'async', 'poll', 'notify', 'first_available_file', 'include', 'include_tasks', 'import_tasks', 'tags', 'register', 'ignore_errors', 'delegate_to', 'local_action', 'transport', 'remote_user', 'sudo', 'sudo_user', 'sudo_pass', 'when', 'connection', 'environment', 'args', 'always_run', 'any_errors_fatal', 'changed_when', 'failed_when', 'check_mode', 'delay', 'retries', 'until', 'su', 'su_user', 'su_pass', 'no_log', 'run_once', 'become', 'become_user', 'become_method', FILENAME_KEY, ] BLOCK_NAME_TO_ACTION_TYPE_MAP = { 'tasks': 'task', 'handlers': 'handler', 'pre_tasks': 'task', 'post_tasks': 'task', 'block': 'meta', 'rescue': 'meta', 'always': 'meta', } def load_plugins(directory): result = [] fh = None for pluginfile in glob.glob(os.path.join(directory, '[A-Za-z]*.py')): pluginname = os.path.basename(pluginfile.replace('.py', '')) try: fh, filename, desc = imp.find_module(pluginname, [directory]) mod = imp.load_module(pluginname, fh, filename, desc) obj = getattr(mod, pluginname)() result.append(obj) finally: if fh: fh.close() return result def tokenize(line): tokens = line.lstrip().split(" ") if tokens[0] == '-': tokens = tokens[1:] if tokens[0] == 'action:' or tokens[0] == 'local_action:': tokens = tokens[1:] command = tokens[0].replace(":", "") args = list() kwargs = dict() nonkvfound = False for arg in tokens[1:]: if "=" in arg and not nonkvfound: kv = arg.split("=", 1) kwargs[kv[0]] = kv[1] else: nonkvfound = True args.append(arg) return (command, args, kwargs) def _playbook_items(pb_data): if isinstance(pb_data, dict): return pb_data.items() elif not pb_data: return [] else: return [item for play in pb_data for item in play.items()] def find_children(playbook, playbook_dir): if not os.path.exists(playbook[0]): return [] if playbook[1] == 'role': playbook_ds = {'roles': [{'role': playbook[0]}]} else: try: playbook_ds = parse_yaml_from_file(playbook[0]) except AnsibleError as e: raise SystemExit(str(e)) results = [] basedir = os.path.dirname(playbook[0]) items = _playbook_items(playbook_ds) for item in items: for child in play_children(basedir, item, playbook[1], playbook_dir): if "$" in child['path'] or "{{" in child['path']: continue valid_tokens = list() for token in split_args(child['path']): if '=' in token: break valid_tokens.append(token) path = ' '.join(valid_tokens) results.append({ 'path': path_dwim(basedir, path), 'type': child['type'] }) return results def template(basedir, value, vars, fail_on_undefined=False, **kwargs): try: value = ansible_template(os.path.abspath(basedir), value, vars, **dict(kwargs, fail_on_undefined=fail_on_undefined)) # Hack to skip the following exception when using to_json filter on a variable. # I guess the filter doesn't like empty vars... except (AnsibleError, ValueError): # templating failed, so just keep value as is. pass return value def play_children(basedir, item, parent_type, playbook_dir): delegate_map = { 'tasks': _taskshandlers_children, 'pre_tasks': _taskshandlers_children, 'post_tasks': _taskshandlers_children, 'block': _taskshandlers_children, 'include': _include_children, 'include_tasks': _include_children, 'import_tasks': _include_children, 'roles': _roles_children, 'dependencies': _roles_children, 'handlers': _taskshandlers_children, } (k, v) = item play_library = os.path.join(os.path.abspath(basedir), 'library') _load_library_if_exists(play_library) if k in delegate_map: if v: v = template(os.path.abspath(basedir), v, dict(playbook_dir=os.path.abspath(basedir)), fail_on_undefined=False) return delegate_map[k](basedir, k, v, parent_type) return [] def _include_children(basedir, k, v, parent_type): # handle include: filename.yml tags=blah (command, args, kwargs) = tokenize("{0}: {1}".format(k, v)) result = path_dwim(basedir, args[0]) if not os.path.exists(result) and not basedir.endswith('tasks'): result = path_dwim(os.path.join(basedir, '..', 'tasks'), v) return [{'path': result, 'type': parent_type}] def _taskshandlers_children(basedir, k, v, parent_type): results = [] for th in v: if 'include' in th: append_children(th['include'], basedir, k, parent_type, results) elif 'include_tasks' in th: append_children(th['include_tasks'], basedir, k, parent_type, results) elif 'import_tasks' in th: append_children(th['import_tasks'], basedir, k, parent_type, results) elif 'block' in th: results.extend(_taskshandlers_children(basedir, k, th['block'], parent_type)) if 'rescue' in th: results.extend(_taskshandlers_children(basedir, k, th['rescue'], parent_type)) if 'always' in th: results.extend(_taskshandlers_children(basedir, k, th['always'], parent_type)) return results def append_children(taskhandler, basedir, k, parent_type, results): # when taskshandlers_children is called for playbooks, the # actual type of the included tasks is the section containing the # include, e.g. tasks, pre_tasks, or handlers. if parent_type == 'playbook': playbook_section = k else: playbook_section = parent_type results.append({ 'path': path_dwim(basedir, taskhandler), 'type': playbook_section }) def _roles_children(basedir, k, v, parent_type): results = [] for role in v: if isinstance(role, dict): if 'role' in role or 'name' in role: if 'tags' not in role or 'skip_ansible_lint' not in role['tags']: results.extend(_look_for_role_files(basedir, role.get('role', role.get('name')))) else: raise SystemExit('role dict {0} does not contain a "role" ' 'or "name" key'.format(role)) else: results.extend(_look_for_role_files(basedir, role)) return results def _load_library_if_exists(path): if os.path.exists(path): module_loader.add_directory(path) def _rolepath(basedir, role): role_path = None possible_paths = [ # if included from a playbook path_dwim(basedir, os.path.join('roles', role)), path_dwim(basedir, role), # if included from roles/[role]/meta/main.yml path_dwim( basedir, os.path.join('..', '..', '..', 'roles', role) ), path_dwim(basedir, os.path.join('..', '..', role)) ] if constants.DEFAULT_ROLES_PATH: search_locations = constants.DEFAULT_ROLES_PATH if isinstance(search_locations, six.string_types): search_locations = search_locations.split(os.pathsep) for loc in search_locations: loc = os.path.expanduser(loc) possible_paths.append(path_dwim(loc, role)) for path_option in possible_paths: if os.path.isdir(path_option): role_path = path_option break if role_path: _load_library_if_exists(os.path.join(role_path, 'library')) return role_path def _look_for_role_files(basedir, role): role_path = _rolepath(basedir, role) if not role_path: return [] results = [] for th in ['tasks', 'handlers', 'meta']: for ext in ('.yml', '.yaml'): thpath = os.path.join(role_path, th, 'main' + ext) if os.path.exists(thpath): results.append({'path': thpath, 'type': th}) break return results def rolename(filepath): idx = filepath.find('roles/') if idx < 0: return '' role = filepath[idx+6:] role = role[:role.find('/')] return role def _kv_to_dict(v): (command, args, kwargs) = tokenize(v) return (dict(__ansible_module__=command, __ansible_arguments__=args, **kwargs)) def normalize_task_v2(task): '''Ensures tasks have an action key and strings are converted to python objects''' result = dict() mod_arg_parser = ModuleArgsParser(task) try: action, arguments, result['delegate_to'] = mod_arg_parser.parse() except AnsibleParserError as e: try: task_info = "%s:%s" % (task[FILENAME_KEY], task[LINE_NUMBER_KEY]) del task[FILENAME_KEY] del task[LINE_NUMBER_KEY] except KeyError: task_info = "Unknown" try: import pprint pp = pprint.PrettyPrinter(indent=2) task_pprint = pp.pformat(task) except ImportError: task_pprint = task raise SystemExit("Couldn't parse task at %s (%s)\n%s" % (task_info, e.message, task_pprint)) # denormalize shell -> command conversion if '_uses_shell' in arguments: action = 'shell' del(arguments['_uses_shell']) for (k, v) in list(task.items()): if k in ('action', 'local_action', 'args', 'delegate_to') or k == action: # we don't want to re-assign these values, which were # determined by the ModuleArgsParser() above continue else: result[k] = v result['action'] = dict(__ansible_module__=action) if '_raw_params' in arguments: result['action']['__ansible_arguments__'] = arguments['_raw_params'].split(' ') del(arguments['_raw_params']) else: result['action']['__ansible_arguments__'] = list() result['action'].update(arguments) return result def normalize_task_v1(task): result = dict() for (k, v) in task.items(): if k in VALID_KEYS or k.startswith('with_'): if k == 'local_action' or k == 'action': if not isinstance(v, dict): v = _kv_to_dict(v) v['__ansible_arguments__'] = v.get('__ansible_arguments__', list()) result['action'] = v else: result[k] = v else: if isinstance(v, six.string_types): v = _kv_to_dict(k + ' ' + v) elif not v: v = dict(__ansible_module__=k) else: if isinstance(v, dict): v.update(dict(__ansible_module__=k)) else: if k == '__line__': # Keep the line number stored result[k] = v continue else: # Tasks that include playbooks (rather than task files) # can get here # https://github.com/willthames/ansible-lint/issues/138 raise RuntimeError("Was not expecting value %s of type %s for key %s\n" "Task: %s. Check the syntax of your playbook using " "ansible-playbook --syntax-check" % (str(v), type(v), k, str(task))) v['__ansible_arguments__'] = v.get('__ansible_arguments__', list()) result['action'] = v if 'module' in result['action']: # this happens when a task uses # local_action: # module: ec2 # etc... result['action']['__ansible_module__'] = result['action']['module'] del(result['action']['module']) if 'args' in result: result['action'].update(result.get('args')) del(result['args']) return result def normalize_task(task, filename): ansible_action_type = task.get('__ansible_action_type__', 'task') if '__ansible_action_type__' in task: del(task['__ansible_action_type__']) if ANSIBLE_VERSION < 2: task = normalize_task_v1(task) else: task = normalize_task_v2(task) task[FILENAME_KEY] = filename task['__ansible_action_type__'] = ansible_action_type return task def task_to_str(task): name = task.get("name") if name: return name action = task.get("action") args = " ".join([u"{0}={1}".format(k, v) for (k, v) in action.items() if k not in ["__ansible_module__", "__ansible_arguments__"]] + action.get("__ansible_arguments__")) return u"{0} {1}".format(action["__ansible_module__"], args) def extract_from_list(blocks, candidates): results = list() for block in blocks: for candidate in candidates: if isinstance(block, dict) and candidate in block: if isinstance(block[candidate], list): results.extend(add_action_type(block[candidate], candidate)) elif block[candidate] is not None: raise RuntimeError( "Key '%s' defined, but bad value: '%s'" % (candidate, str(block[candidate]))) return results def add_action_type(actions, action_type): results = list() for action in actions: action['__ansible_action_type__'] = BLOCK_NAME_TO_ACTION_TYPE_MAP[action_type] results.append(action) return results def get_action_tasks(yaml, file): tasks = list() if file['type'] in ['tasks', 'handlers']: tasks = add_action_type(yaml, file['type']) else: tasks.extend(extract_from_list(yaml, ['tasks', 'handlers', 'pre_tasks', 'post_tasks'])) # Add sub-elements of block/rescue/always to tasks list tasks.extend(extract_from_list(tasks, ['block', 'rescue', 'always'])) # Remove block/rescue/always elements from tasks list block_rescue_always = ('block', 'rescue', 'always') tasks[:] = [task for task in tasks if all(k not in task for k in block_rescue_always)] return [task for task in tasks if set(['include', 'include_tasks', 'import_tasks']).isdisjoint(task.keys())] def get_normalized_tasks(yaml, file): tasks = get_action_tasks(yaml, file) res = [] for task in tasks: # An empty `tags` block causes `None` to be returned if # the `or []` is not present - `task.get('tags', [])` # does not suffice. if 'skip_ansible_lint' in (task.get('tags') or []): # No need to normalize_task is we are skipping it. continue res.append(normalize_task(task, file['path'])) return res def parse_yaml_linenumbers(data, filename): """Parses yaml as ansible.utils.parse_yaml but with linenumbers. The line numbers are stored in each node's LINE_NUMBER_KEY key. """ def compose_node(parent, index): # the line number where the previous token has ended (plus empty lines) line = loader.line node = Composer.compose_node(loader, parent, index) node.__line__ = line + 1 return node def construct_mapping(node, deep=False): mapping = Constructor.construct_mapping(loader, node, deep=deep) mapping[LINE_NUMBER_KEY] = node.__line__ mapping[FILENAME_KEY] = filename return mapping try: loader = yaml.Loader(data) loader.compose_node = compose_node loader.construct_mapping = construct_mapping data = loader.get_single_data() except (yaml.parser.ParserError, yaml.scanner.ScannerError) as e: raise SystemExit("Failed to parse YAML in %s: %s" % (filename, str(e))) return data ansible-lint-3.4.20+git.20180203/lib/ansiblelint/version.py000066400000000000000000000000271323537273000227530ustar00rootroot00000000000000__version__ = '3.4.20' ansible-lint-3.4.20+git.20180203/setup.cfg000066400000000000000000000001721323537273000174640ustar00rootroot00000000000000[metadata] description-file = README.md [flake8] max-line-length = 100 exclude = .git,.hg,.svn,test,setup.py,__pycache__ ansible-lint-3.4.20+git.20180203/setup.py000066400000000000000000000014231323537273000173550ustar00rootroot00000000000000import os from setuptools import find_packages from setuptools import setup import sys sys.path.insert(0, os.path.abspath('lib')) exec(open('lib/ansiblelint/version.py').read()) setup( name='ansible-lint', version=__version__, description=('checks playbooks for practices and behaviour that could potentially be improved'), keywords='ansible, lint', author='Will Thames', author_email='will@thames.id.au', url='https://github.com/willthames/ansible-lint', package_dir={'': 'lib'}, packages=find_packages('lib'), zip_safe=False, install_requires=['ansible', 'pyyaml', 'six'], entry_points={ 'console_scripts': [ 'ansible-lint = ansiblelint.__main__:main' ] }, license='MIT', test_suite="test" ) ansible-lint-3.4.20+git.20180203/test-deps.txt000066400000000000000000000000421323537273000203100ustar00rootroot00000000000000flake8 nose pep8-naming tox wheel ansible-lint-3.4.20+git.20180203/test/000077500000000000000000000000001323537273000166225ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/test/TestAlwaysRunRule.py000066400000000000000000000012611323537273000226110ustar00rootroot00000000000000import unittest from ansiblelint import RulesCollection, Runner from ansiblelint.rules.AlwaysRunRule import AlwaysRunRule class TestAlwaysRun(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(AlwaysRunRule()) def test_file_positive(self): success = 'test/always-run-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_file_negative(self): failure = 'test/always-run-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(1, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestBecomeUserWithoutBecome.py000066400000000000000000000014111323537273000245610ustar00rootroot00000000000000import unittest from ansiblelint import RulesCollection, Runner from ansiblelint.rules.BecomeUserWithoutBecomeRule import BecomeUserWithoutBecomeRule class TestBecomeUserWithoutBecome(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(BecomeUserWithoutBecomeRule()) def test_file_positive(self): success = 'test/become-user-without-become-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_file_negative(self): failure = 'test/become-user-without-become-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(3, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestCommandHasChangesCheck.py000066400000000000000000000014011323537273000242710ustar00rootroot00000000000000import unittest from ansiblelint import Runner, RulesCollection from ansiblelint.rules.CommandHasChangesCheckRule import CommandHasChangesCheckRule class TestCommandHasChangesCheck(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(CommandHasChangesCheckRule()) def test_command_changes_positive(self): success = 'test/command-check-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_command_changes_negative(self): failure = 'test/command-check-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(2, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestCommandLineInvocationSameAsConfig.py000066400000000000000000000052241323537273000264770ustar00rootroot00000000000000import unittest from subprocess import Popen, PIPE import os import shutil import yaml class TestCommandLineInvocationSameAsConfig(unittest.TestCase): def setUp(self): if os.path.exists(".sandbox"): shutil.rmtree(".sandbox") os.makedirs(".sandbox/subdir") def run_ansible_lint(self, args=False, config=None): command = "cd .sandbox; ../bin/ansible-lint ../test/skiptasks.yml" if args: command += " " + args if config: with open(".sandbox/.ansible-lint", "w") as outfile: yaml.dump(config, outfile, default_flow_style=False) result, err = Popen( [command], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=True ).communicate() self.assertFalse(err, "Expected no error but was " + str(err)) return result def assert_config_for(self, cli_arg, config): with_arg = self.run_ansible_lint(args=cli_arg) with_config = self.run_ansible_lint(config=config) self.assertEqual(with_arg, with_config) def test_parseable_as_config(self): self.assert_config_for("-p", dict(parseable=True)) def test_quiet_as_config(self): self.assert_config_for("-q", dict(quiet=True)) def test_rulesdir_as_config(self): self.assert_config_for("-r ../test/rules/", dict(rulesdir=["../test/rules/"])) def test_use_default_rules(self): self.assert_config_for("-R -r ../test/rules/", dict(rulesdir=["../test/rules"], use_default_rules=True)) def test_tags(self): self.assert_config_for("-t skip_ansible_lint", dict(tags=["skip_ansible_lint"])) def test_verbosity(self): self.assert_config_for("-v", dict(verbosity=1)) def test_skip_list(self): self.assert_config_for("-x bad_tag", dict(skip_list=["bad_tag"])) def test_exclude(self): self.assert_config_for("--exclude ../test/", dict(exclude_paths=["../test/"])) def test_config_can_be_overridden(self): no_override = self.run_ansible_lint(args="-t bad_tag") overridden = self.run_ansible_lint(args="-t bad_tag", config=dict(tags=["skip_ansible_lint"])) self.assertEqual(no_override, overridden) def test_different_config_file(self): with open(".sandbox/subdir/ansible-config.yml", "w") as outfile: yaml.dump(dict(verbosity=1), outfile, default_flow_style=False) diff_config = self.run_ansible_lint(args="-c ./subdir/ansible-config.yml") no_config = self.run_ansible_lint(args="-v") self.assertEqual(diff_config, no_config) ansible-lint-3.4.20+git.20180203/test/TestEnvVarsInCommand.py000066400000000000000000000021501323537273000232040ustar00rootroot00000000000000import unittest import ansible from ansiblelint import Runner, RulesCollection from ansiblelint.rules.EnvVarsInCommandRule import EnvVarsInCommandRule from pkg_resources import parse_version class TestEnvVarsInCommand(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(EnvVarsInCommandRule()) def test_file_positive(self): success = 'test/env-vars-in-command-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) @unittest.skipIf(parse_version(ansible.__version__) < parse_version('2.4'), "not supported with ansible < 2.4") def test_file_positive_2_4(self): success = 'test/env-vars-in-command-success_2_4_style.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_file_negative(self): failure = 'test/env-vars-in-command-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(2, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestFormatter.py000066400000000000000000000035671323537273000220120ustar00rootroot00000000000000# Copyright (c) 2016 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import os import unittest from ansiblelint import Match, AnsibleLintRule from ansiblelint.formatters import Formatter class TestFormatter(unittest.TestCase): def setUp(self): self.rule = AnsibleLintRule() self.rule.id = "TCF0001" self.formatter = Formatter() def test_format_coloured_string(self): match = Match(1, "hello", "filename.yml", self.rule, "message") result = self.formatter.format(match, True) def test_unicode_format_string(self): match = Match(1, "hello", "filename.yml", self.rule, u'\U0001f427') result = self.formatter.format(match, False) def test_dict_format_line(self): match = Match(1, {'hello': 'world'}, "filename.yml", self.rule, "xyz") result = self.formatter.format(match, True) ansible-lint-3.4.20+git.20180203/test/TestLintRule.py000066400000000000000000000036111323537273000215730ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import unittest from .rules import EMatcherRule from .rules import UnsetVariableMatcherRule class TestRule(unittest.TestCase): def test_rule_matching(self): text = "" filename = 'test/ematchtest.yml' with open(filename) as f: text = f.read() ematcher = EMatcherRule.EMatcherRule() matches = ematcher.matchlines(dict(path=filename, type='playbooks'), text) self.assertEqual(len(matches), 3) def test_rule_postmatching(self): text = "" filename = 'test/bracketsmatchtest.yml' with open(filename) as f: text = f.read() rule = UnsetVariableMatcherRule.UnsetVariableMatcherRule() matches = rule.matchlines(dict(path=filename, type='playbooks'), text) self.assertEqual(len(matches), 2) ansible-lint-3.4.20+git.20180203/test/TestOctalPermissions.py000066400000000000000000000013451323537273000233350ustar00rootroot00000000000000import unittest from ansiblelint import Runner, RulesCollection from ansiblelint.rules.OctalPermissionsRule import OctalPermissionsRule class TestOctalPermissionsRuleWithFile(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(OctalPermissionsRule()) def test_file_positive(self): success = 'test/octalpermissions-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_file_negative(self): failure = 'test/octalpermissions-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(5, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestPackageIsNotLatest.py000066400000000000000000000013731323537273000235250ustar00rootroot00000000000000import unittest from ansiblelint import Runner, RulesCollection from ansiblelint.rules.PackageIsNotLatestRule import PackageIsNotLatestRule class TestPackageIsNotLatestRule(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(PackageIsNotLatestRule()) def test_package_not_latest_positive(self): success = 'test/package-check-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_package_not_latest_negative(self): failure = 'test/package-check-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(3, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestRoleHandlers.py000066400000000000000000000010451323537273000224160ustar00rootroot00000000000000import unittest from ansiblelint import Runner, RulesCollection from ansiblelint.rules.UseHandlerRatherThanWhenChangedRule import UseHandlerRatherThanWhenChangedRule class TestRoleHandlers(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(UseHandlerRatherThanWhenChangedRule()) def test_role_handler_positive(self): success = 'test/role-with-handler/main.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) ansible-lint-3.4.20+git.20180203/test/TestRulesCollection.py000066400000000000000000000071721323537273000231510ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import collections import unittest from ansiblelint import RulesCollection class TestRulesCollection(unittest.TestCase): rules = None ematchtestfile = dict(path='test/ematchtest.yml', type='playbook') bracketsmatchtestfile = dict(path='test/bracketsmatchtest.yml', type='playbook') def setUp(self): self.rules = RulesCollection.create_from_directory('./test/rules') def test_load_collection_from_directory(self): self.assertEqual(len(self.rules), 2) def test_run_collection(self): matches = self.rules.run(self.ematchtestfile) self.assertEqual(len(matches), 3) def test_tags(self): matches = self.rules.run(self.ematchtestfile, tags=['test1']) self.assertEqual(len(matches), 3) matches = self.rules.run(self.ematchtestfile, tags=['test2']) self.assertEqual(len(matches), 0) matches = self.rules.run(self.bracketsmatchtestfile, tags=['test1']) self.assertEqual(len(matches), 1) matches = self.rules.run(self.bracketsmatchtestfile, tags=['test2']) self.assertEqual(len(matches), 2) def test_skip_tags(self): matches = self.rules.run(self.ematchtestfile, skip_list=['test1']) self.assertEqual(len(matches), 0) matches = self.rules.run(self.ematchtestfile, skip_list=['test2']) self.assertEqual(len(matches), 3) matches = self.rules.run(self.bracketsmatchtestfile, skip_list=['test1']) self.assertEqual(len(matches), 2) matches = self.rules.run(self.bracketsmatchtestfile, skip_list=['test2']) self.assertEqual(len(matches), 1) def test_skip_id(self): matches = self.rules.run(self.ematchtestfile, skip_list=['TEST0001']) self.assertEqual(len(matches), 0) matches = self.rules.run(self.ematchtestfile, skip_list=['TEST0002']) self.assertEqual(len(matches), 3) matches = self.rules.run(self.bracketsmatchtestfile, skip_list=['TEST0001']) self.assertEqual(len(matches), 2) matches = self.rules.run(self.bracketsmatchtestfile, skip_list=['TEST0002']) self.assertEqual(len(matches), 1) def test_skip_non_existent_id(self): matches = self.rules.run(self.ematchtestfile, skip_list=['DOESNOTEXIST']) self.assertEqual(len(matches), 3) def test_no_duplicate_rule_ids(self): real_rules = RulesCollection.create_from_directory('./lib/ansiblelint/rules') rule_ids = [ rule.id for rule in real_rules ] self.assertEqual([x for x, y in collections.Counter(rule_ids).items() if y > 1], []) ansible-lint-3.4.20+git.20180203/test/TestRunner.py000066400000000000000000000107171323537273000213130ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import os import unittest import ansiblelint from ansiblelint import Runner, RulesCollection import ansiblelint.formatters class TestRule(unittest.TestCase): def setUp(self): rulesdir = os.path.join('lib', 'ansiblelint', 'rules') self.rules = RulesCollection.create_from_directory(rulesdir) def test_runner_count(self): filename = 'test/nomatchestest.yml' runner = Runner(self.rules, filename, [], [], []) assert (len(runner.run()) == 0) def test_unicode_runner_count(self): filename = 'test/unicode.yml' runner = Runner(self.rules, filename, [], [], []) assert (len(runner.run()) == 1) def test_unicode_standard_formatting(self): filename = 'test/unicode.yml' runner = Runner(self.rules, filename, [], [], []) matches = runner.run() formatter = ansiblelint.formatters.Formatter() formatter.format(matches[0]) def test_unicode_parseable_colored_formatting(self): filename = 'test/unicode.yml' runner = Runner(self.rules, filename, [], [], []) matches = runner.run() formatter = ansiblelint.formatters.ParseableFormatter() formatter.format(matches[0], colored=True) def test_unicode_quiet_colored_formatting(self): filename = 'test/unicode.yml' runner = Runner(self.rules, filename, [], [], []) matches = runner.run() formatter = ansiblelint.formatters.QuietFormatter() formatter.format(matches[0], colored=True) def test_unicode_standard_color_formatting(self): filename = 'test/unicode.yml' runner = Runner(self.rules, filename, [], [], []) matches = runner.run() formatter = ansiblelint.formatters.Formatter() formatter.format(matches[0], colored=True) def test_runner_excludes_paths(self): filename = 'examples/lots_of_warnings.yml' excludes = ['examples/lots_of_warnings.yml'] runner = Runner(self.rules, filename, [], [], excludes) assert (len(runner.run()) == 0) def test_runner_block_count(self): filename = 'test/block.yml' runner = Runner(self.rules, filename, [], [], []) assert (len(runner.run()) == 0) def test_runner_become_count(self): filename = 'test/become.yml' runner = Runner(self.rules, filename, [], [], []) assert (len(runner.run()) == 0) def test_runner_empty_tags_count(self): filename = 'test/emptytags.yml' runner = Runner(self.rules, filename, [], [], []) assert (len(runner.run()) == 0) def test_dir_with_trailing_slash(self): filename = 'test/' runner = Runner(self.rules, filename, [], [], []) assert (list(runner.playbooks)[0][1] == 'role') def test_dir_with_fullpath(self): filename = os.path.abspath('test') runner = Runner(self.rules, filename, [], [], []) assert (list(runner.playbooks)[0][1] == 'role') def test_files_not_scanned_twice(self): checked_files = set() filename = os.path.abspath('test/common-include-1.yml') runner = Runner(self.rules, filename, [], [], [], 0, checked_files) run1 = runner.run() filename = os.path.abspath('test/common-include-2.yml') runner = Runner(self.rules, filename, [], [], [], 0, checked_files) run2 = runner.run() assert ((len(run1) + len(run2)) == 1) ansible-lint-3.4.20+git.20180203/test/TestSkippedTasks.py000066400000000000000000000032771323537273000224520ustar00rootroot00000000000000# Copyright (c) 2013-2014 Will Thames # 2014 Akira Yoshiyama # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import os import unittest import ansiblelint from ansiblelint import Runner, RulesCollection class TestRule(unittest.TestCase): def setUp(self): rulesdir = os.path.join('lib', 'ansiblelint', 'rules') self.rules = RulesCollection.create_from_directory(rulesdir) def test_runner_count(self): filename = 'test/skiptasks.yml' tags = ['ANSIBLE0004', 'ANSIBLE0005', 'ANSIBLE0006', 'ANSIBLE0007'] runner = Runner(self.rules, filename, tags, [], []) self.assertEqual(len(runner.run()), 6) ansible-lint-3.4.20+git.20180203/test/TestSudoRule.py000066400000000000000000000037621323537273000216060ustar00rootroot00000000000000import unittest from ansiblelint.rules.SudoRule import SudoRule import ansiblelint.utils class TestSudoRule(unittest.TestCase): simple_dict_yaml = { 'value1': '{foo}}', 'value2': 2, 'value3': ['foo', 'bar', '{baz}}'], 'value4': '{bar}', 'value5': '{{baz}', } def setUp(self): self.rule = SudoRule() def test_check_value_simple_matching(self): result = self.rule._check_value("sudo: yes") self.assertEquals(0, len(result)) def test_check_value_shallow_dict(self): result = self.rule._check_value({ 'sudo': 'yes', 'sudo_user': 'somebody' }) self.assertEquals(2, len(result)) def test_check_value_nested(self): yaml = [ { 'hosts': 'all', 'sudo': 'yes', 'sudo_user': 'nobody', 'tasks': [ { 'name': 'test', 'debug': 'msg=test', 'sudo': 'yes', 'sudo_user': 'somebody' } ] } ] result = self.rule._check_value(yaml) self.assertEquals(2, len(result)) class TestSudoRuleWithFile(unittest.TestCase): file1 = 'test/sudo.yml' def setUp(self): self.rule = SudoRule() def test_matchplay_sudo(self): yaml = ansiblelint.utils.parse_yaml_linenumbers(open(self.file1).read(), self.file1) self.assertTrue(yaml) for play in yaml: result = self.rule.matchplay(self.file1, play) self.assertEquals(2, len(result)) def test_matchtask_sudo(self): yaml = ansiblelint.utils.parse_yaml_linenumbers(open(self.file1).read(), self.file1) results = [] for task in ansiblelint.utils.get_normalized_tasks(yaml, dict(path=self.file1, type='playbook')): results.append(self.rule.matchtask(self.file1, task)) self.assertEquals(1, len([result for result in results if result])) ansible-lint-3.4.20+git.20180203/test/TestTaskIncludes.py000066400000000000000000000035551323537273000224350ustar00rootroot00000000000000import os import unittest import ansible from ansiblelint import Runner, RulesCollection from pkg_resources import parse_version class TestTaskIncludes(unittest.TestCase): def setUp(self): rulesdir = os.path.join('lib', 'ansiblelint', 'rules') self.rules = RulesCollection.create_from_directory(rulesdir) def test_block_included_tasks(self): filename = 'test/blockincludes.yml' runner = Runner(self.rules, filename, [], [], []) runner.run() self.assertEqual(len(runner.playbooks), 4) def test_block_included_tasks_with_rescue_and_always(self): filename = 'test/blockincludes2.yml' runner = Runner(self.rules, filename, [], [], []) runner.run() self.assertEqual(len(runner.playbooks), 4) def test_included_tasks(self): filename = 'test/taskincludes.yml' runner = Runner(self.rules, filename, [], [], []) runner.run() self.assertEqual(len(runner.playbooks), 4) @unittest.skipIf(parse_version(ansible.__version__) < parse_version('2.4'), "not supported with ansible < 2.4") def test_include_tasks_2_4_style(self): filename = 'test/taskincludes_2_4_style.yml' runner = Runner(self.rules, filename, [], [], []) runner.run() self.assertEqual(len(runner.playbooks), 4) @unittest.skipIf(parse_version(ansible.__version__) < parse_version('2.4'), "not supported with ansible < 2.4") def test_import_tasks_2_4_style(self): filename = 'test/taskimports.yml' runner = Runner(self.rules, filename, [], [], []) runner.run() self.assertEqual(len(runner.playbooks), 4) def test_include_tasks_with_block_include(self): filename = 'test/include-in-block.yml' runner = Runner(self.rules, filename, [], [], []) runner.run() self.assertEqual(len(runner.playbooks), 3) ansible-lint-3.4.20+git.20180203/test/TestUseCommandInsteadOfShell.py000066400000000000000000000014111323537273000246510ustar00rootroot00000000000000import unittest from ansiblelint import Runner, RulesCollection from ansiblelint.rules.UseCommandInsteadOfShellRule import UseCommandInsteadOfShellRule class TestUseCommandInsteadOfShell(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(UseCommandInsteadOfShellRule()) def test_file_positive(self): success = 'test/command-instead-of-shell-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_file_negative(self): failure = 'test/command-instead-of-shell-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(2, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestUseHandlerRatherThanWhenChanged.py000066400000000000000000000014751323537273000261520ustar00rootroot00000000000000import unittest from ansiblelint import RulesCollection, Runner from ansiblelint.rules.UseHandlerRatherThanWhenChangedRule import UseHandlerRatherThanWhenChangedRule class TestUseHandlerRatherThanWhenChanged(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(UseHandlerRatherThanWhenChangedRule()) def test_file_positive(self): success = 'test/use-handler-rather-than-when-changed-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_file_negative(self): failure = 'test/use-handler-rather-than-when-changed-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(5, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestUsingBareVariablesIsDeprecated.py000066400000000000000000000014321323537273000260210ustar00rootroot00000000000000import unittest from ansiblelint import Runner, RulesCollection from ansiblelint.rules.UsingBareVariablesIsDeprecatedRule import UsingBareVariablesIsDeprecatedRule class TestUsingBareVariablesIsDeprecated(unittest.TestCase): collection = RulesCollection() def setUp(self): self.collection.register(UsingBareVariablesIsDeprecatedRule()) def test_file_positive(self): success = 'test/using-bare-variables-success.yml' good_runner = Runner(self.collection, success, [], [], []) self.assertEqual([], good_runner.run()) def test_file_negative(self): failure = 'test/using-bare-variables-failure.yml' bad_runner = Runner(self.collection, failure, [], [], []) errs = bad_runner.run() self.assertEqual(13, len(errs)) ansible-lint-3.4.20+git.20180203/test/TestUtils.py000066400000000000000000000135151323537273000211410ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2013-2014 Will Thames # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import unittest import ansiblelint.utils as utils class TestUtils(unittest.TestCase): def test_tokenize_blank(self): (cmd, args, kwargs) = utils.tokenize("") self.assertEqual(cmd, '') self.assertEqual(args, []) self.assertEqual(kwargs, {}) def test_tokenize_single_word(self): (cmd, args, kwargs) = utils.tokenize("vars:") self.assertEqual(cmd, "vars") def test_tokenize_string_module_and_arg(self): (cmd, args, kwargs) = utils.tokenize("hello: a=1") self.assertEqual(cmd, "hello") self.assertEqual(kwargs, {"a": "1"}) def test_tokenize_strips_action(self): (cmd, args, kwargs) = utils.tokenize("action: hello a=1") self.assertEqual(cmd, "hello") self.assertEqual(args, []) self.assertEqual(kwargs, {"a": "1"}) def test_tokenize_more_than_one_arg(self): (cmd, args, kwargs) = utils.tokenize("action: whatever bobbins x=y z=x c=3") self.assertEqual(cmd, "whatever") self.assertEqual(args[0], "bobbins") self.assertEqual(args[1], "x=y") self.assertEqual(args[2], "z=x") self.assertEqual(args[3], "c=3") def test_tokenize_command_with_args(self): cmd, args, kwargs = utils.tokenize("action: command chdir=wxy creates=zyx tar xzf zyx.tgz") self.assertEqual(cmd, "command") self.assertEqual(args[0], "tar") self.assertEqual(args[1], "xzf") self.assertEqual(args[2], "zyx.tgz") self.assertEqual(kwargs, {'chdir': 'wxy', 'creates': 'zyx'}) def test_normalize_simple_command(self): task1 = dict(name="hello", action="command chdir=abc echo hello world") task2 = dict(name="hello", command="chdir=abc echo hello world") self.assertEqual(utils.normalize_task(task1, 'tasks.yml'), utils.normalize_task(task2, 'tasks.yml')) def test_normalize_complex_command(self): task1 = dict(name="hello", action={'module': 'ec2', 'region': 'us-east1', 'etc': 'whatever'}) task2 = dict(name="hello", ec2={'region': 'us-east1', 'etc': 'whatever'}) task3 = dict(name="hello", ec2="region=us-east1 etc=whatever") task4 = dict(name="hello", action="ec2 region=us-east1 etc=whatever") self.assertEqual(utils.normalize_task(task1, 'tasks.yml'), utils.normalize_task(task2, 'tasks.yml')) self.assertEqual(utils.normalize_task(task2, 'tasks.yml'), utils.normalize_task(task3, 'tasks.yml')) self.assertEqual(utils.normalize_task(task3, 'tasks.yml'), utils.normalize_task(task4, 'tasks.yml')) def test_normalize_args(self): task1 = dict(git={'version': 'abc'}, args={'repo': 'blah', 'dest': 'xyz'}) task2 = dict(git={'version': 'abc', 'repo': 'blah', 'dest': 'xyz'}) task3 = dict(git='version=abc repo=blah dest=xyz') task4 = dict(git=None, args={'repo': 'blah', 'dest': 'xyz', 'version': 'abc'}) self.assertEqual(utils.normalize_task(task1, 'tasks.yml'), utils.normalize_task(task2, 'tasks.yml')) self.assertEqual(utils.normalize_task(task1, 'tasks.yml'), utils.normalize_task(task3, 'tasks.yml')) self.assertEqual(utils.normalize_task(task1, 'tasks.yml'), utils.normalize_task(task4, 'tasks.yml')) def test_extract_from_list(self): block = dict( block = [dict(tasks=[dict(name="hello",command="whoami")])], test_none = None, test_string = 'foo' ) blocks = [block] test_list = utils.extract_from_list(blocks, ['block']) test_none = utils.extract_from_list(blocks, ['test_none']) self.assertEqual(list(block['block']), test_list) self.assertEqual(list(), test_none) with self.assertRaises(RuntimeError): utils.extract_from_list(blocks, ['test_string']) def test_simple_template(self): v = "{{ playbook_dir }}" result = utils.template('/a/b/c', v, dict(playbook_dir='/a/b/c')) self.assertEqual(result, "/a/b/c") def test_missing_filter(self): v = "{{ 'hello' | doesnotexist }}" result = utils.template('/a/b/c', v, dict(playbook_dir='/a/b/c')) self.assertEqual(result, "{{ 'hello' | doesnotexist }}") def test_existing_filter_on_unknown_var(self): v = "{{ hello | to_json }}" result = utils.template('/a/b/c', v, dict(playbook_dir='/a/b/c')) self.assertEqual(result, "{{ hello | to_json }}") def test_task_to_str_unicode(self): task = dict(fail=dict(msg=u"unicode é ô à")) result = utils.task_to_str(utils.normalize_task(task, 'filename.yml')) self.assertEqual(result, u"fail msg=unicode é ô à") ansible-lint-3.4.20+git.20180203/test/__init__.py000066400000000000000000000000001323537273000207210ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/test/always-run-failure.yml000066400000000000000000000001761323537273000231000ustar00rootroot00000000000000- hosts: localhost tasks: - name: always_run is deprecated debug: msg="always_run is deprecated" always_run: yes ansible-lint-3.4.20+git.20180203/test/always-run-success.yml000066400000000000000000000001761323537273000231210ustar00rootroot00000000000000- hosts: localhost tasks: - name: always_run is deprecated debug: msg="always_run is deprecated" check_mode: yes ansible-lint-3.4.20+git.20180203/test/bar.txt000066400000000000000000000000111323537273000201170ustar00rootroot00000000000000Bar file ansible-lint-3.4.20+git.20180203/test/become-user-without-become-failure.yml000066400000000000000000000005611323537273000261330ustar00rootroot00000000000000- hosts: localhost name: become_user without become play become_user: root tasks: - debug: msg: hello - hosts: localhost tasks: - name: become_user without become task command: whoami become_user: postgres - hosts: localhost become: true tasks: - name: won't work, needs to be explicit command: whoami become_user: postgres ansible-lint-3.4.20+git.20180203/test/become-user-without-become-success.yml000066400000000000000000000002711323537273000261520ustar00rootroot00000000000000- hosts: localhost become_user: root become: true tasks: - debug: msg: hello - hosts: localhost tasks: - command: whoami become_user: postgres become: true ansible-lint-3.4.20+git.20180203/test/become.yml000066400000000000000000000004241323537273000205770ustar00rootroot00000000000000- hosts: all tasks: - name: clone content repository git: repo: '{{ archive_services_repo_url }}' dest: '/home/www' accept_hostkey: yes version: master update: no become: yes become_user: nobody notify: - restart apache2 ansible-lint-3.4.20+git.20180203/test/block.yml000066400000000000000000000013131323537273000204350ustar00rootroot00000000000000--- - hosts: all pre_tasks: - { include: 'doesnotexist.yml' } tasks: - block: - name: successful debug message debug: msg='i execute normally' - name: failure command command: /bin/false changed_when: False - name: never reacehd debug message debug: msg='i never execute, cause ERROR!' rescue: - name: exception debug message debug: msg='I caught an error' - name: another failure command command: /bin/false changed_when: False - name: another missed debug message debug: msg='I also never execute :-(' always: - name: always reached debug message debug: msg="this always executes" ansible-lint-3.4.20+git.20180203/test/blockincludes.yml000066400000000000000000000005251323537273000221700ustar00rootroot00000000000000--- - hosts: webservers vars: varset: varset tasks: - block: - include: nestedincludes.yml tags=nested - block: - include: "{{ varnotset }}.yml" - block: - include: "{{ varset }}.yml" - block: - include: "directory with spaces/main.yml" ansible-lint-3.4.20+git.20180203/test/blockincludes2.yml000066400000000000000000000004571323537273000222560ustar00rootroot00000000000000--- - hosts: webservers vars: varset: varset tasks: - block: - include: nestedincludes.yml tags=nested - block: - include: "{{ varnotset }}.yml" rescue: - include: "{{ varset }}.yml" always: - include: "directory with spaces/main.yml" ansible-lint-3.4.20+git.20180203/test/brackets-do-not-match-test.yml000066400000000000000000000014521323537273000244120ustar00rootroot00000000000000--- - hosts: foo roles: - ../../../roles/base_os - ../../../roles/repos - { role: ../../../roles/openshift_master, oo_minion_ips: "{ hostvars['localhost'].oo_minion_ips | default(['']) }}", oo_bind_ip: "{{ hostvars[inventory_hostname].ansible_eth0.ipv4.address | default(['']) }}" } - ../../../roles/pods - name: "Set Origin specific facts on localhost (for later use)" hosts: localhost gather_facts: no tasks: - name: Setting oo_minion_ips fact on localhost set_fact: oo_minion_ips: "{{ hostvars | oo_select_keys(groups['tag_env-host-type-' + oo_env + '-openshift-minion']) | oo_collect(attribute='ansible_eth0.ipv4.address') }" when: groups['tag_env-host-type-' + oo_env + '-openshift-minion'] is defined ansible-lint-3.4.20+git.20180203/test/bracketsmatchtest.yml000066400000000000000000000000611323537273000230550ustar00rootroot00000000000000val1: "{{dest}}" val2: worry val3: "{{victory}}" ansible-lint-3.4.20+git.20180203/test/command-check-failure.yml000066400000000000000000000002501323537273000234600ustar00rootroot00000000000000- tasks: - name: command without checks command: echo blah args: chdir: X - name: shell without checks shell: echo blah args: chdir: X ansible-lint-3.4.20+git.20180203/test/command-check-success.yml000066400000000000000000000021001323537273000234750ustar00rootroot00000000000000- tasks: - name: command with creates check command: echo blah args: creates: Z - name: command with removes check command: echo blah args: removes: Z - name: command with changed_when command: echo blah changed_when: False - name: command with inline creates command: creates=Z echo blah - name: command with inline removes command: removes=Z echo blah - name: command with cmd command: cmd: echo blah args: creates: Z - name: shell with creates check shell: echo blah args: creates: Z - name: shell with removes check shell: echo blah args: removes: Z - name: shell with changed_when shell: echo blah changed_when: False - name: shell with inline creates shell: creates=Z echo blah - name: shell with inline removes shell: removes=Z echo blah - name: shell with cmd shell: cmd: echo blah args: creates: Z - handlers: - name: restart something command: do something - include: included-handlers.yml ansible-lint-3.4.20+git.20180203/test/command-instead-of-shell-failure.yml000066400000000000000000000002001323537273000255340ustar00rootroot00000000000000--- - tasks: - name: shell no pipe shell: echo hello - name: shell with jinja filter shell: echo {{"hello"|upper}} ansible-lint-3.4.20+git.20180203/test/command-instead-of-shell-success.yml000066400000000000000000000011701323537273000255640ustar00rootroot00000000000000- tasks: - name: shell with pipe shell: echo hello | true - name: shell with redirect shell: echo hello > /tmp/hello - name: chain two shell commands shell: echo hello && echo goodbye - name: run commands in succession shell: echo hello ; echo goodbye - name: use variables shell: echo $HOME $USER - name: use * for globbing shell: ls foo* - name: use ? for globbing shell: ls foo? - name: use [] for globbing shell: ls foo[1,2,3] - name: use shell generator shell: ls foo{.txt,.xml} - name: use shell with cmd shell: cmd: | set -x ls foo? ansible-lint-3.4.20+git.20180203/test/common-include-1.yml000066400000000000000000000001071323537273000224120ustar00rootroot00000000000000--- - hosts: webservers tasks: - include: included-with-lint.yml ansible-lint-3.4.20+git.20180203/test/common-include-2.yml000066400000000000000000000001071323537273000224130ustar00rootroot00000000000000--- - hosts: webservers tasks: - include: included-with-lint.yml ansible-lint-3.4.20+git.20180203/test/directory with spaces/000077500000000000000000000000001323537273000230215ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/test/directory with spaces/main.yml000066400000000000000000000000671323537273000244730ustar00rootroot00000000000000- debug: msg="tasks in directory with spaces included" ansible-lint-3.4.20+git.20180203/test/ematchtest.yml000066400000000000000000000000441323537273000215040ustar00rootroot00000000000000hello nothing exciting is happening ansible-lint-3.4.20+git.20180203/test/emptytags.yml000066400000000000000000000001301323537273000213540ustar00rootroot00000000000000--- - hosts: all tasks: - name: hello world debug: msg="hello world" tags: ansible-lint-3.4.20+git.20180203/test/env-vars-in-command-failure.yml000066400000000000000000000002741323537273000245560ustar00rootroot00000000000000- hosts: localhost tasks: - name: this doesn't work as it appears shell: HELLO=hello echo $HELLO - name: typo some stuff command: cerates=/tmp/blah warn=no touch /tmp/blah ansible-lint-3.4.20+git.20180203/test/env-vars-in-command-success.yml000066400000000000000000000006761323537273000246050ustar00rootroot00000000000000- hosts: localhost tasks: - name: actual use of environment shell: echo $HELLO environment: HELLO: hello - name: use some key-value pairs command: chdir=/tmp creates=/tmp/bobbins warn=no touch bobbins - name: commands can have flags command: abc --xyz=def blah - name: commands can have equals in them command: echo "===========" - name: commands with cmd command: cmd: echo "-------" ansible-lint-3.4.20+git.20180203/test/env-vars-in-command-success_2_4_style.yml000066400000000000000000000002061323537273000264560ustar00rootroot00000000000000- hosts: localhost tasks: - name: command with stdin (ansible > 2.4) command: /bin/cat args: stdin: "Hello, world!"ansible-lint-3.4.20+git.20180203/test/foo.txt000066400000000000000000000000111323537273000201360ustar00rootroot00000000000000Foo file ansible-lint-3.4.20+git.20180203/test/include-in-block-inner.yml000066400000000000000000000000741323537273000235760ustar00rootroot00000000000000--- - block: - include: simpletask.yml tags: ['foo'] ansible-lint-3.4.20+git.20180203/test/include-in-block.yml000066400000000000000000000001051323537273000224600ustar00rootroot00000000000000--- - hosts: all tasks: - include: include-in-block-inner.yml ansible-lint-3.4.20+git.20180203/test/included-handlers.yml000066400000000000000000000002071323537273000227310ustar00rootroot00000000000000--- - name: restart xyz service: name=xyz state=restarted # see Issue #165 - name: command handler issue 165 command: do something ansible-lint-3.4.20+git.20180203/test/included-with-lint.yml000066400000000000000000000000571323537273000230530ustar00rootroot00000000000000# missing a task name - yum: name: ansible ansible-lint-3.4.20+git.20180203/test/includedoesnotexist.yml000066400000000000000000000000611323537273000234360ustar00rootroot00000000000000--- - pre_tasks: - include: "doesnotexist.yml" ansible-lint-3.4.20+git.20180203/test/multiline-brackets-do-not-match-test.yml000066400000000000000000000014521323537273000264120ustar00rootroot00000000000000--- - hosts: foo roles: - ../../../roles/base_os - ../../../roles/repos - { role: ../../../roles/openshift_master, oo_minion_ips: "{ hostvars['localhost'].oo_minion_ips | default(['']) }}", oo_bind_ip: "{{ hostvars[inventory_hostname].ansible_eth0.ipv4.address | default(['']) }}" } - ../../../roles/pods - name: "Set Origin specific facts on localhost (for later use)" hosts: localhost gather_facts: no tasks: - name: Setting oo_minion_ips fact on localhost set_fact: oo_minion_ips: "{{ hostvars | oo_select_keys(groups['tag_env-host-type-' + oo_env + '-openshift-minion']) | oo_collect(attribute='ansible_eth0.ipv4.address') }" when: groups['tag_env-host-type-' + oo_env + '-openshift-minion'] is defined ansible-lint-3.4.20+git.20180203/test/multiline-bracketsmatchtest.yml000066400000000000000000000014541323537273000250640ustar00rootroot00000000000000--- - hosts: foo roles: - ../../../roles/base_os - ../../../roles/repos - { role: ../../../roles/openshift_master, oo_minion_ips: "{{ hostvars['localhost'].oo_minion_ips | default(['']) }}", oo_bind_ip: "{{ hostvars[inventory_hostname].ansible_eth0.ipv4.address | default(['']) }}" } - ../../../roles/pods - name: "Set Origin specific facts on localhost (for later use)" hosts: localhost gather_facts: no tasks: - name: Setting oo_minion_ips fact on localhost set_fact: oo_minion_ips: "{{ hostvars | oo_select_keys(groups['tag_env-host-type-' + oo_env + '-openshift-minion']) | oo_collect(attribute='ansible_eth0.ipv4.address') }}" when: groups['tag_env-host-type-' + oo_env + '-openshift-minion'] is defined ansible-lint-3.4.20+git.20180203/test/nestedincludes.yml000066400000000000000000000000511323537273000223520ustar00rootroot00000000000000--- - include: simpletask.yml tags=nginx ansible-lint-3.4.20+git.20180203/test/nomatchestest.yml000066400000000000000000000002551323537273000222300ustar00rootroot00000000000000--- - hosts: whatever tasks: - name: hello world action: debug msg="Hello!" - name: this should be fine too action: file state=touch dest=./wherever ansible-lint-3.4.20+git.20180203/test/norole.yml000066400000000000000000000000641323537273000206430ustar00rootroot00000000000000--- - hosts: - localhost roles: - name: node ansible-lint-3.4.20+git.20180203/test/norole2.yml000066400000000000000000000000651323537273000207260ustar00rootroot00000000000000--- - hosts: - localhost roles: - name: node ansible-lint-3.4.20+git.20180203/test/octalpermissions-failure.yml000066400000000000000000000010011323537273000243600ustar00rootroot00000000000000--- - hosts: hosts vars: varset: varset tasks: - name: octal permissions test fail (600) file: path: foo mode: 600 - name: octal permissions test fail (710) file: path: foo mode: 710 - name: octal permissions test fail (123) file: path: foo mode: 123 - name: octal permissions test fail (2000) file: path: bar mode: 2000 - name: octal permissions test fail (777) file: path=baz mode=777 ansible-lint-3.4.20+git.20180203/test/octalpermissions-success.yml000066400000000000000000000012501323537273000244070ustar00rootroot00000000000000--- - hosts: hosts vars: varset: varset tasks: - name: octal permissions test success (0600) file: path: foo mode: 0600 - name: octal permissions test success (0000) file: path: foo mode: 0000 - name: octal permissions test success (02000) file: path: bar mode: 02000 - name: octal permissions test success (0777) file: path=baz mode=0777 - name: octal permissions test success (0711) file: path=baz mode=0711 - name: octal permissions test success (0710) file: path=baz mode=0710 - name: permissions test success (0777) file: path=baz mode=u+rwx ansible-lint-3.4.20+git.20180203/test/package-check-failure.yml000066400000000000000000000003711323537273000234410ustar00rootroot00000000000000- tasks: - name: install ansible yum: name=ansible state=latest - name: install ansible-lint pip: name=ansible-lint args: state: latest - name: install some-package package: name: some-package state: latest ansible-lint-3.4.20+git.20180203/test/package-check-success.yml000066400000000000000000000004311323537273000234570ustar00rootroot00000000000000- tasks: - name: install ansible yum: name=ansible-2.1.0.0 state=present - name: install ansible-lint pip: name=ansible-lint args: state: present version: 3.1.2 - name: install some-package package: name: some-package state: present ansible-lint-3.4.20+git.20180203/test/role-with-handler/000077500000000000000000000000001323537273000221475ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/test/role-with-handler/a-role/000077500000000000000000000000001323537273000233265ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/test/role-with-handler/a-role/handlers/000077500000000000000000000000001323537273000251265ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/test/role-with-handler/a-role/handlers/main.yml000066400000000000000000000001221323537273000265700ustar00rootroot00000000000000--- - name: do anything shell: echo merp | cat when: - something.changed ansible-lint-3.4.20+git.20180203/test/role-with-handler/main.yml000066400000000000000000000000541323537273000236150ustar00rootroot00000000000000- name: foo roles: - { role: a-role } ansible-lint-3.4.20+git.20180203/test/rules/000077500000000000000000000000001323537273000177545ustar00rootroot00000000000000ansible-lint-3.4.20+git.20180203/test/rules/EMatcherRule.py000066400000000000000000000005441323537273000226510ustar00rootroot00000000000000from ansiblelint import AnsibleLintRule class EMatcherRule(AnsibleLintRule): id = 'TEST0001' description = 'This is a test rule that looks for lines ' + \ 'containing the letter e' shortdesc = 'The letter "e" is present' tags = {'fake', 'dummy', 'test1'} def match(self, filename, line): return "e" in line ansible-lint-3.4.20+git.20180203/test/rules/UnsetVariableMatcherRule.py000066400000000000000000000006101323537273000252230ustar00rootroot00000000000000from ansiblelint import AnsibleLintRule class UnsetVariableMatcherRule(AnsibleLintRule): id = 'TEST0002' shortdesc = 'Line contains untemplated variable' description = 'This is a test rule that looks for lines ' + \ 'post templating that still contain {{' tags = {'fake', 'dummy', 'test2'} def match(self, filename, line): return "{{" in line ansible-lint-3.4.20+git.20180203/test/rules/__init__.py000066400000000000000000000000671323537273000220700ustar00rootroot00000000000000__all__ = ['UnsetVariableMatcherRule', 'EMatcherRule'] ansible-lint-3.4.20+git.20180203/test/simpletask.yml000066400000000000000000000000561323537273000215220ustar00rootroot00000000000000--- - name: hello world debug: msg="Hello!" ansible-lint-3.4.20+git.20180203/test/skiptasks.yml000066400000000000000000000026401323537273000213630ustar00rootroot00000000000000--- - hosts: all tasks: - name: test ANSIBLE0004 action: git - name: test ANSIBLE0005 action: hg - name: test ANSIBLE0006 command: git log changed_when: False - name: test ANSIBLE0007 command: creates=B chmod 644 A - name: test invalid action (skip) foo: bar tags: - skip_ansible_lint - name: test ANSIBLE0004 (skip) action: git tags: - skip_ansible_lint - name: test ANSIBLE0005 (skip) action: hg tags: - skip_ansible_lint - name: test ANSIBLE0006 (skip) command: git log tags: - skip_ansible_lint - name: test ANSIBLE0007 (skip) command: chmod 644 A tags: - skip_ansible_lint - name: test ANSIBLE0004 (don't warn) command: git log args: warn: False changed_when: False - name: test ANSIBLE0005 (don't warn) command: chmod 644 A args: warn: False creates: B - name: test ANSIBLE0005 (warn) command: chmod 644 A args: warn: yes creates: B - name: test ANSIBLE0004 (don't warn single line) command: warn=False chdir=/tmp/blah git log changed_when: False - name: test ANSIBLE0005 (don't warn single line) command: warn=no creates=B chmod 644 A - name: test ANSIBLE0005 (warn single line) command: warn=yes creates=B chmod 644 A ansible-lint-3.4.20+git.20180203/test/sudo.yml000066400000000000000000000004611323537273000203200ustar00rootroot00000000000000- hosts: all sudo: yes sudo_user: somebody tasks: - name: clone content repository git: repo: '{{ archive_services_repo_url }}' dest: '/home/www' accept_hostkey: yes version: master update: no sudo: yes sudo_user: nobody notify: - restart apache2 ansible-lint-3.4.20+git.20180203/test/taskimports.yml000066400000000000000000000003651323537273000217310ustar00rootroot00000000000000--- - hosts: webservers vars: varset: varset tasks: - import_tasks: nestedincludes.yml tags=nested - import_tasks: "{{ varnotset }}.yml" - import_tasks: "{{ varset }}.yml" - import_tasks: "directory with spaces/main.yml" ansible-lint-3.4.20+git.20180203/test/taskincludes.yml000066400000000000000000000003411323537273000220340ustar00rootroot00000000000000--- - hosts: webservers vars: varset: varset tasks: - include: nestedincludes.yml tags=nested - include: "{{ varnotset }}.yml" - include: "{{ varset }}.yml" - include: "directory with spaces/main.yml" ansible-lint-3.4.20+git.20180203/test/taskincludes_2_4_style.yml000066400000000000000000000003711323537273000237230ustar00rootroot00000000000000--- - hosts: webservers vars: varset: varset tasks: - include_tasks: nestedincludes.yml tags=nested - include_tasks: "{{ varnotset }}.yml" - include_tasks: "{{ varset }}.yml" - include_tasks: "directory with spaces/main.yml" ansible-lint-3.4.20+git.20180203/test/unicode.yml000066400000000000000000000002371323537273000207750ustar00rootroot00000000000000--- - hosts: localhost connection: local vars: unicode_var: a_b_cö tasks: - name: bonjour, ça va? file: state=touch dest=/tmp/naïve.yml ansible-lint-3.4.20+git.20180203/test/use-handler-rather-than-when-changed-failure.yml000066400000000000000000000012601323537273000277410ustar00rootroot00000000000000- tasks: - name: execute command command: echo hello register: result - name: this should be a handler debug: msg: why isn't this a handler when: result.changed - name: this should be a handler 2 debug: msg: why isn't this a handler when: result|changed - name: this should be a handler 3 debug: msg: why isn't this a handler when: result.changed == true - name: this should be a handler 4 debug: msg: why isn't this a handler when: result['changed'] == true - name: this should be a handler 5 debug: msg: why isn't this a handler when: - result['changed'] == true - another_condition ansible-lint-3.4.20+git.20180203/test/use-handler-rather-than-when-changed-success.yml000066400000000000000000000007431323537273000277670ustar00rootroot00000000000000- tasks: - name: execute command command: echo hello register: result - name: print helpful error message debug: var: result when: result.failed - name: do something when hello is output debug: msg: why isn't this a handler when: result.stdout == "hello" - name: never actually debug debug: var: result when: False - name: check when with a list debug: var: result when: - conditionA - conditionB ansible-lint-3.4.20+git.20180203/test/using-bare-variables-failure.yml000066400000000000000000000042031323537273000247730ustar00rootroot00000000000000--- - hosts: localhost become: no vars: my_list: - foo - bar my_list2: - 1 - 2 my_list_of_dicts: - foo: 1 bar: 2 - foo: 3 bar: 4 my_list_of_lists: - "{{ my_list }}" - "{{ my_list2 }}" my_filenames: - foo.txt - bar.txt my_dict: foo: bar tasks: - name: with_items loop using bare variable debug: msg: "{{ item }}" with_items: my_list - name: with_dict loop using bare variable debug: msg: "{{ item }}" with_dict: my_dict ### Testing with_dict with a default empty dictionary - name: with_dict loop using variable and default debug: msg: "{{ item.key }} - {{ item.value }}" with_dict: uwsgi_ini | default({}) - name: with_nested loop using bare variable debug: msg: "{{ item.0 }} {{ item.1 }}" with_nested: - my_list - "{{ my_list2 }}" - name: with_file loop using bare variable debug: msg: "{{ item }}" with_file: my_list - name: with_fileglob loop using bare variable debug: msg: "{{ item }}" with_fileglob: my_list - name: with_together loop using bare variable debug: msg: "{{ item.0 }} {{ item.1 }}" with_together: - my_list - "{{ my_list2 }}" - name: with_subelements loop using bare variable debug: msg: "{{ item.0 }}" with_subelements: - my_list_of_dicts - bar - name: with_random_choice loop using bare variable debug: msg: "{{ item }}" with_random_choice: my_list - name: with_first_found loop using bare variable debug: msg: "{{ item }}" with_first_found: my_filenames - name: with_indexed_items loop debug: msg: "{{ item.0 }} {{ item.1 }}" with_indexed_items: my_list - name: with_flattened loop debug: msg: "{{ item }}" with_flattened: - my_list - my_list2 - name: with_flattened loop with a variable debug: msg: "{{ item }}" with_flattened: my_list_of_lists ansible-lint-3.4.20+git.20180203/test/using-bare-variables-success.yml000066400000000000000000000076501323537273000250250ustar00rootroot00000000000000--- - hosts: localhost become: no vars: my_list: - foo - bar my_list2: - 1 - 2 my_list_of_dicts: - foo: 1 bar: 2 - foo: 3 bar: 4 my_list_of_lists: - "{{ my_list }}" - "{{ my_list2 }}" my_filenames: - foo.txt - bar.txt my_dict: foo: bar tasks: ### Testing with_items loops - name: with_items loop using static list debug: msg: "{{ item }}" with_items: - foo - bar - name: with_items using a static hash debug: msg: "{{ item.key }} - {{ item.value }}" with_items: - { key: foo, value: 1 } - { key: bar, value: 2 } - name: with_items loop using variable debug: msg: "{{ item }}" with_items: "{{ my_list }}" ### Testing with_nested loops - name: with_nested loop using static lists debug: msg: "{{ item[0] }} - {{ item[1] }}" with_nested: - [ 'foo', 'bar' ] - [ '1', '2', '3' ] - name: with_nested loop using variable list and static debug: msg: "{{ item[0] }} - {{ item[1] }}" with_nested: - "{{ my_list }}" - [ '1', '2', '3' ] ### Testing with_dict - name: with_dict loop using variable debug: msg: "{{ item.key }} - {{ item.value }}" with_dict: "{{ my_dict }}" ### Testing with_dict with a default empty dictionary - name: with_dict loop using variable and default debug: msg: "{{ item.key }} - {{ item.value }}" with_dict: "{{ uwsgi_ini | default({}) }}" ### Testing with_file - name: with_file loop using static files list debug: msg: "{{ item }}" with_file: - foo.txt - bar.txt - name: with_file loop using list of filenames debug: msg: "{{ item }}" with_file: "{{ my_filenames }}" ### Testing with_fileglob - name: with_fileglob loop using list of *.txt debug: msg: "{{ item }}" with_fileglob: - '*.txt' ### Testing non-list form of with_fileglob - name: with_fileglob loop using single value *.txt debug: msg: "{{ item }}" with_fileglob: '*.txt' ### Testing non-list form of with_fileglob with trailing templated pattern - name: with_fileglob loop using templated pattern debug: msg: "{{ item }}" with_fileglob: 'foo{{glob}}' ### Testing with_together - name: with_together loop using variable lists debug: msg: "{{ item.0 }} - {{ item.1 }}" with_together: - "{{ my_list }}" - "{{ my_list2 }}" - name: with_subelements loop debug: msg: "{{ item }}" with_subelements: - "{{ my_list_of_dicts }}" - bar - name: with_sequence loop debug: msg: "{{ item }}" with_sequence: count=2 - name: with_random_choice loop debug: msg: "{{ item }}" with_random_choice: "{{ my_list }}" - name: with_first_found loop with static files list debug: msg: "{{ item }}" with_first_found: - foo.txt - bar.txt - name: with_first_found loop with list of filenames debug: msg: "{{ item }}" with_first_found: "{{ my_filenames }}" - name: with_indexed_items loop debug: msg: "{{ item.0 }} {{ item.1 }}" with_indexed_items: "{{ my_list }}" - name: with_ini loop debug: msg: "{{ item }}" with_ini: value[1-2] section=section1 file=foo.ini re=true - name: with_flattened loop debug: msg: "{{ item }}" with_flattened: - "{{ my_list }}" - "{{ my_list2 }}" - name: with_flattened loop with a variable debug: msg: "{{ item }}" with_flattened: "{{ my_list_of_lists }}" - name: with_inventory_hostnames loop debug: msg: "{{ item }}" with_inventory_hostnames: all ansible-lint-3.4.20+git.20180203/test/varset.yml000066400000000000000000000000621323537273000206470ustar00rootroot00000000000000- debug: msg="var was set" - git: repo=hello.git ansible-lint-3.4.20+git.20180203/test/varunset.yml000066400000000000000000000000371323537273000212140ustar00rootroot00000000000000- debug: msg="var was not set" ansible-lint-3.4.20+git.20180203/tox.ini000066400000000000000000000010301323537273000171500ustar00rootroot00000000000000[tox] minversion = 1.6 envlist = py27-ansible{19,20,21,22,23,24,devel},py36-ansible{22,23,24,devel},py27-flake8,py36-flake8 [testenv] deps = ansible19: ansible>=1.9.4,<2 ansible20: ansible>=2.0.0.2,<2.1 ansible21: ansible>=2.1,<2.2 ansible22: ansible>=2.2,<2.3 ansible23: ansible>=2.3,<2.4 ansible24: ansible>=2.4,<2.5 ansibledevel: git+https://github.com/ansible/ansible.git -rtest-deps.txt commands = nosetests [] passenv = HOME # recreate = True [testenv:flake8] commands = python setup.py flake8 usedevelop = True